diff --git a/public/CHANGELOG.md b/public/CHANGELOG.md index e95cdd5..b1d5217 100644 --- a/public/CHANGELOG.md +++ b/public/CHANGELOG.md @@ -1,6 +1,11 @@ All notable changes to this project will be documented in this file. -## [1.0.1] - 2025-04-06 +## [1.2.0] - 2025-04-06 + +### Added +- Import and split existing spritesheet functionality + +## [1.1.0] - 2025-04-06 ### Added - 📝 Help modal with instructions and tips diff --git a/src/App.vue b/src/App.vue index 3f0ae7b..c182139 100644 --- a/src/App.vue +++ b/src/App.vue @@ -64,7 +64,7 @@ - + @@ -74,6 +74,7 @@ + @@ -84,6 +85,7 @@ import Modal from './components/utilities/Modal.vue'; import SpritePreview from './components/SpritePreview.vue'; import HelpModal from './components/HelpModal.vue'; + import SpritesheetSplitter from './components/SpritesheetSplitter.vue'; interface Sprite { id: string; @@ -100,7 +102,10 @@ const columns = ref(4); const isPreviewModalOpen = ref(false); const isHelpModalOpen = ref(false); + const isSpritesheetSplitterOpen = ref(false); const jsonFileInput = ref(null); + const spritesheetImageUrl = ref(''); + const spritesheetImageFile = ref(null); const handleSpritesUpload = (files: File[]) => { // Check if any of the files is a JSON file @@ -112,7 +117,40 @@ return; } - // Otherwise, process as normal image files + // Check if it's a single image file that might be a spritesheet + if (files.length === 1 && files[0].type.startsWith('image/')) { + const file = files[0]; + const url = URL.createObjectURL(file); + + // Load the image to check its dimensions + const img = new Image(); + img.onload = () => { + // If the image is large enough, it might be a spritesheet + // This is a simple heuristic - we can improve it later + if (img.width > 200 && img.height > 200) { + // Ask the user if they want to split the spritesheet + if (confirm('This looks like it might be a spritesheet. Would you like to split it into individual sprites?')) { + // Open the spritesheet splitter + spritesheetImageUrl.value = url; + spritesheetImageFile.value = file; + isSpritesheetSplitterOpen.value = true; + return; + } + } + + // If the user doesn't want to split or it's not large enough, process as a single sprite + processImageFiles([file]); + }; + img.src = url; + return; + } + + // Process multiple image files normally + processImageFiles(files); + }; + + // Extract the image processing logic to a separate function for reuse + const processImageFiles = (files: File[]) => { Promise.all( files.map(file => { return new Promise(resolve => { @@ -211,6 +249,23 @@ isHelpModalOpen.value = false; }; + // Spritesheet splitter modal control + const closeSpritesheetSplitter = () => { + isSpritesheetSplitterOpen.value = false; + // Clean up the URL object to prevent memory leaks + if (spritesheetImageUrl.value) { + URL.revokeObjectURL(spritesheetImageUrl.value); + spritesheetImageUrl.value = ''; + } + spritesheetImageFile.value = null; + }; + + // Handle the split spritesheet result + const handleSplitSpritesheet = (files: File[]) => { + // Process the split sprite files + processImageFiles(files); + }; + // Export spritesheet as JSON with base64 images const exportSpritesheetJSON = async () => { if (sprites.value.length === 0) return; @@ -380,4 +435,22 @@ return { ...sprite, x, y }; }); }; + + const updateSpriteCell = (id: string, newIndex: number) => { + // Find the current index of the sprite + const currentIndex = sprites.value.findIndex(sprite => sprite.id === id); + if (currentIndex === -1) return; + + // Create a new sprites array + const newSprites = [...sprites.value]; + + // Remove the sprite from its current position + const [movedSprite] = newSprites.splice(currentIndex, 1); + + // Insert the sprite at the new position + newSprites.splice(newIndex, 0, movedSprite); + + // Update the sprites array + sprites.value = newSprites; + }; diff --git a/src/components/HelpModal.vue b/src/components/HelpModal.vue index 2b6acf1..ae03563 100644 --- a/src/components/HelpModal.vue +++ b/src/components/HelpModal.vue @@ -32,6 +32,7 @@

How to use:

  1. Upload your sprite images by dragging and dropping them or clicking the upload area
  2. +
  3. If you upload a single large image, you'll be asked if you want to split it into individual sprites
  4. Arrange your sprites by dragging them to the desired position
  5. Adjust the number of columns to change the layout
  6. Preview your animation using the "Preview Animation" button
  7. @@ -41,6 +42,8 @@

    Tips:

    • For best results, use sprites with consistent dimensions
    • +
    • When uploading a spritesheet, you can split it automatically into individual sprites
    • +
    • The spritesheet splitter allows you to specify rows and columns or try auto-detection
    • The preview animation plays frames in the order they appear in the spritesheet (left to right, top to bottom)
    • You can adjust the animation speed in the preview window
    • The tool works entirely in your browser - no files are uploaded to any server
    • diff --git a/src/components/SpriteCanvas.vue b/src/components/SpriteCanvas.vue index d94cf8a..85657f4 100644 --- a/src/components/SpriteCanvas.vue +++ b/src/components/SpriteCanvas.vue @@ -1,9 +1,15 @@