perf: 优化合图功能
This commit is contained in:
@@ -15,14 +15,41 @@ export interface BrowserSprite {
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete atlas result
|
||||
* Single atlas result
|
||||
*/
|
||||
export interface AtlasResult {
|
||||
export interface SingleAtlasResult {
|
||||
index: number;
|
||||
width: number;
|
||||
height: number;
|
||||
placements: PackerPlacement[];
|
||||
frames: AtlasFrame[];
|
||||
imageDataUrl: string | null;
|
||||
/** Sprite IDs in this atlas */
|
||||
spriteIds: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete atlas result (supports multiple atlases)
|
||||
*/
|
||||
export interface AtlasResult {
|
||||
/** All atlases */
|
||||
atlases: SingleAtlasResult[];
|
||||
/** Total number of packed sprites */
|
||||
packedCount: number;
|
||||
/** Sprites that couldn't fit in any atlas (only when multi-atlas is disabled) */
|
||||
unpackedSpriteIds: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy single result format for backward compatibility
|
||||
*/
|
||||
export interface LegacyAtlasResult {
|
||||
width: number;
|
||||
height: number;
|
||||
placements: PackerPlacement[];
|
||||
frames: AtlasFrame[];
|
||||
imageDataUrl: string | null;
|
||||
unpackedSpriteIds: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,14 +68,23 @@ interface AtlasState {
|
||||
// Configuration
|
||||
config: TextureAtlasConfig;
|
||||
|
||||
// Multi-atlas mode
|
||||
enableMultiAtlas: boolean;
|
||||
|
||||
// Compression mode (PNG quantization)
|
||||
enableCompression: boolean;
|
||||
|
||||
// Processing state
|
||||
status: AtlasProcessStatus;
|
||||
progress: number;
|
||||
errorMessage: string | null;
|
||||
|
||||
// Result
|
||||
// Result (supports multiple atlases)
|
||||
result: AtlasResult | null;
|
||||
|
||||
// Current preview atlas index
|
||||
currentAtlasIndex: number;
|
||||
|
||||
// Preview state
|
||||
previewScale: number;
|
||||
previewOffset: { x: number; y: number };
|
||||
@@ -67,11 +103,15 @@ interface AtlasState {
|
||||
updateConfig: (config: Partial<TextureAtlasConfig>) => void;
|
||||
resetConfig: () => void;
|
||||
|
||||
setEnableMultiAtlas: (enable: boolean) => void;
|
||||
setEnableCompression: (enable: boolean) => void;
|
||||
|
||||
setStatus: (status: AtlasProcessStatus) => void;
|
||||
setProgress: (progress: number) => void;
|
||||
setError: (message: string | null) => void;
|
||||
|
||||
setResult: (result: AtlasResult | null) => void;
|
||||
setCurrentAtlasIndex: (index: number) => void;
|
||||
|
||||
setPreviewScale: (scale: number) => void;
|
||||
setPreviewOffset: (offset: { x: number; y: number }) => void;
|
||||
@@ -81,6 +121,9 @@ interface AtlasState {
|
||||
openAnimationDialog: () => void;
|
||||
closeAnimationDialog: () => void;
|
||||
setAnimationFps: (fps: number) => void;
|
||||
|
||||
// Computed helpers
|
||||
getCurrentAtlas: () => SingleAtlasResult | null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,7 +134,7 @@ const defaultConfig: TextureAtlasConfig = {
|
||||
maxHeight: 1024,
|
||||
padding: 2,
|
||||
allowRotation: false,
|
||||
pot: true,
|
||||
pot: false,
|
||||
format: "png",
|
||||
quality: 90,
|
||||
outputFormat: "cocos2d",
|
||||
@@ -106,10 +149,13 @@ export const useAtlasStore = create<AtlasState>((set, get) => ({
|
||||
sprites: [],
|
||||
folderName: "",
|
||||
config: { ...defaultConfig },
|
||||
enableMultiAtlas: false,
|
||||
enableCompression: false,
|
||||
status: "idle",
|
||||
progress: 0,
|
||||
errorMessage: null,
|
||||
result: null,
|
||||
currentAtlasIndex: 0,
|
||||
previewScale: 1,
|
||||
previewOffset: { x: 0, y: 0 },
|
||||
selectedSpriteIds: [],
|
||||
@@ -128,7 +174,7 @@ export const useAtlasStore = create<AtlasState>((set, get) => ({
|
||||
a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: "base" })
|
||||
);
|
||||
|
||||
return { sprites: allSprites, result: null };
|
||||
return { sprites: allSprites, result: null, currentAtlasIndex: 0 };
|
||||
});
|
||||
},
|
||||
|
||||
@@ -137,6 +183,7 @@ export const useAtlasStore = create<AtlasState>((set, get) => ({
|
||||
sprites: state.sprites.filter((s) => s.id !== id),
|
||||
selectedSpriteIds: state.selectedSpriteIds.filter((sid) => sid !== id),
|
||||
result: null,
|
||||
currentAtlasIndex: 0,
|
||||
}));
|
||||
},
|
||||
|
||||
@@ -149,6 +196,7 @@ export const useAtlasStore = create<AtlasState>((set, get) => ({
|
||||
sprites: [],
|
||||
folderName: "",
|
||||
result: null,
|
||||
currentAtlasIndex: 0,
|
||||
selectedSpriteIds: [],
|
||||
status: "idle",
|
||||
progress: 0,
|
||||
@@ -163,10 +211,17 @@ export const useAtlasStore = create<AtlasState>((set, get) => ({
|
||||
set((state) => ({
|
||||
config: { ...state.config, ...partialConfig },
|
||||
result: null, // Clear result when config changes
|
||||
currentAtlasIndex: 0,
|
||||
}));
|
||||
},
|
||||
|
||||
resetConfig: () => set({ config: { ...defaultConfig }, result: null }),
|
||||
resetConfig: () => set({ config: { ...defaultConfig }, result: null, currentAtlasIndex: 0 }),
|
||||
|
||||
// Multi-atlas mode
|
||||
setEnableMultiAtlas: (enable) => set({ enableMultiAtlas: enable, result: null, currentAtlasIndex: 0 }),
|
||||
|
||||
// Compression mode (only affects download, not preview)
|
||||
setEnableCompression: (enable) => set({ enableCompression: enable }),
|
||||
|
||||
// Status actions
|
||||
setStatus: (status) => set({ status }),
|
||||
@@ -174,7 +229,14 @@ export const useAtlasStore = create<AtlasState>((set, get) => ({
|
||||
setError: (message) => set({ errorMessage: message, status: message ? "error" : "idle" }),
|
||||
|
||||
// Result actions
|
||||
setResult: (result) => set({ result, status: result ? "completed" : "idle" }),
|
||||
setResult: (result) => set({ result, status: result ? "completed" : "idle", currentAtlasIndex: 0 }),
|
||||
|
||||
setCurrentAtlasIndex: (index) => {
|
||||
const { result } = get();
|
||||
if (result && index >= 0 && index < result.atlases.length) {
|
||||
set({ currentAtlasIndex: index, previewOffset: { x: 0, y: 0 } });
|
||||
}
|
||||
},
|
||||
|
||||
// Preview actions
|
||||
setPreviewScale: (scale) => set({ previewScale: Math.max(0.1, Math.min(4, scale)) }),
|
||||
@@ -191,7 +253,7 @@ export const useAtlasStore = create<AtlasState>((set, get) => ({
|
||||
: [...state.selectedSpriteIds, id],
|
||||
};
|
||||
}
|
||||
return { selectedSpriteIds: [id] };
|
||||
return { selectedSpriteIds: id ? [id] : [] };
|
||||
});
|
||||
},
|
||||
|
||||
@@ -201,6 +263,13 @@ export const useAtlasStore = create<AtlasState>((set, get) => ({
|
||||
openAnimationDialog: () => set({ isAnimationDialogOpen: true }),
|
||||
closeAnimationDialog: () => set({ isAnimationDialogOpen: false }),
|
||||
setAnimationFps: (fps) => set({ animationFps: Math.max(1, Math.min(60, fps)) }),
|
||||
|
||||
// Computed helpers
|
||||
getCurrentAtlas: () => {
|
||||
const { result, currentAtlasIndex } = get();
|
||||
if (!result || result.atlases.length === 0) return null;
|
||||
return result.atlases[currentAtlasIndex] || null;
|
||||
},
|
||||
}));
|
||||
|
||||
/**
|
||||
@@ -218,3 +287,7 @@ export const useAtlasPreview = () => useAtlasStore((state) => ({
|
||||
scale: state.previewScale,
|
||||
offset: state.previewOffset,
|
||||
}));
|
||||
export const useCurrentAtlas = () => useAtlasStore((state) => {
|
||||
if (!state.result || state.result.atlases.length === 0) return null;
|
||||
return state.result.atlases[state.currentAtlasIndex] || null;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user