diff --git a/package-lock.json b/package-lock.json index 3e1a46f..4781c68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "react-dropzone": "^14.3.5", "sharp": "^0.33.5", "tailwind-merge": "^2.6.0", + "upng-js": "^2.1.0", "zod": "^3.24.1", "zustand": "^5.0.2" }, @@ -8957,6 +8958,15 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/upng-js": { + "version": "2.1.0", + "resolved": "https://mirrors.tencent.com/npm/upng-js/-/upng-js-2.1.0.tgz", + "integrity": "sha512-d3xzZzpMP64YkjP5pr8gNyvBt7dLk/uGI67EctzDuVp4lCZyVMo0aJO6l/VDlgbInJYDY6cnClLoBp29eKWI6g==", + "license": "MIT", + "dependencies": { + "pako": "^1.0.5" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", diff --git a/package.json b/package.json index 8abdeff..c4b4256 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "react-dropzone": "^14.3.5", "sharp": "^0.33.5", "tailwind-merge": "^2.6.0", + "upng-js": "^2.1.0", "zod": "^3.24.1", "zustand": "^5.0.2" }, diff --git a/src/app/page.tsx b/src/app/page.tsx index a31aa7f..3f4b07e 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -6,6 +6,7 @@ import { ArrowRight, ChevronDown, Image as ImageIcon, + Layers, Music, ShieldCheck, Sparkles, @@ -136,7 +137,7 @@ function Hero({ t, reduceMotion }: { t: TFn; reduceMotion: boolean }) { {t("home.hero.previewTitle")} -
+ {t("atlas.multiAtlasHint")} +
++ {t("atlas.compressionHint")} +
++ {t("atlas.unpackedCount", { count: result.unpackedSpriteIds.length })} +
++ {t("atlas.unpackedSuggestion")} +
+{result.width} × {result.height}
-{result.placements.length}
-{atlasCount}
+{result.packedCount}
+{currentAtlas.width} × {currentAtlas.height}
+{currentAtlas.placements.length}
+{currentAtlas.width} × {currentAtlas.height}
+{currentAtlas.placements.length}
+{sprite.name}
++ {sprite.name} +
{sprite.width} × {sprite.height}
diff --git a/src/hooks/useAtlasWorker.ts b/src/hooks/useAtlasWorker.ts index 790c45d..850a9b4 100644 --- a/src/hooks/useAtlasWorker.ts +++ b/src/hooks/useAtlasWorker.ts @@ -1,24 +1,26 @@ /** * Hook for managing Atlas Worker communication + * Supports multi-atlas mode and PNG compression */ import { useRef, useCallback, useEffect } from "react"; -import { useAtlasStore, type BrowserSprite, type AtlasResult } from "@/store/atlasStore"; +import { useAtlasStore, type BrowserSprite, type AtlasResult, type SingleAtlasResult } from "@/store/atlasStore"; import type { TextureAtlasConfig, AtlasFrame } from "@/types"; -import type { PackerPlacement } from "@/lib/atlas-packer"; +import type { PackerPlacement, SinglePackerResult } from "@/lib/atlas-packer"; interface WorkerInputMessage { type: "pack"; sprites: { id: string; name: string; width: number; height: number }[]; config: TextureAtlasConfig; + enableMultiAtlas: boolean; } interface WorkerOutputMessage { type: "result" | "progress" | "error"; result?: { - width: number; - height: number; - placements: PackerPlacement[]; + atlases: SinglePackerResult[]; + packedCount: number; + unpackedSprites: { id: string; name: string; width: number; height: number }[]; }; progress?: number; error?: string; @@ -26,6 +28,7 @@ interface WorkerOutputMessage { /** * Render sprites to canvas and get data URL + * Always returns uncompressed data URL for preview */ async function renderAtlasToCanvas( sprites: BrowserSprite[], @@ -91,7 +94,7 @@ function buildFrames(placements: PackerPlacement[]): AtlasFrame[] { export function useAtlasWorker() { const workerRef = useRef