diff --git a/public/CHANGELOG.md b/public/CHANGELOG.md
index d5859ea..9e34de2 100644
--- a/public/CHANGELOG.md
+++ b/public/CHANGELOG.md
@@ -1,5 +1,8 @@
All notable changes to this project will be documented in this file.
+## [2.4.0] - 2026-01-03
+- Add pixel editor
+
## [2.3.0] - 2026-01-01
- Add authentication
- You can now save projects and open them
diff --git a/src/components/DrawTab.vue b/src/components/DrawTab.vue
new file mode 100644
index 0000000..72b46ef
--- /dev/null
+++ b/src/components/DrawTab.vue
@@ -0,0 +1,504 @@
+
+
+
+
+
+
+ {{ layer.name }}
+ ({{ layer.sprites.length }} frames)
+
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ editor.zoom.value }}x
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Grid
+
+
+
+ Coords
+
+
+
+
+ {{ editor.pointerX.value }}, {{ editor.pointerY.value }}
+
+
+
+
+ {{ editor.canvasWidth.value }} × {{ editor.canvasHeight.value }}
+
+
+
+
+
+
+
+
+
+
+
+ Cancel
+
+
+
+
+ Save
+
+
+
+
+
+
+
+
+
+
+
+
Anchor Position
+
+
+
+
+
+
+
+
+
+ Cancel
+
+
+ Apply
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/SpriteCanvas.vue b/src/components/SpriteCanvas.vue
index ac2d924..8b8d3ed 100644
--- a/src/components/SpriteCanvas.vue
+++ b/src/components/SpriteCanvas.vue
@@ -25,6 +25,10 @@
Copy to frame...
+
+
+ Edit in Pixel Editor
+
@@ -223,6 +227,7 @@
(e: 'rotateSprite', id: string, angle: number): void;
(e: 'flipSprite', id: string, direction: 'horizontal' | 'vertical'): void;
(e: 'copySpriteToFrame', spriteId: string, targetLayerId: string, targetFrameIndex: number): void;
+ (e: 'openPixelEditor', layerId: string, frameIndex: number): void;
}>();
const settingsStore = useSettingsStore();
@@ -535,6 +540,21 @@
}
};
+ const openPixelEditor = () => {
+ if (contextMenuSpriteId.value) {
+ // Find the frame index by finding the sprite in the active layer
+ const layer = props.layers.find(l => l.id === props.activeLayerId);
+ if (layer) {
+ const frameIndex = layer.sprites.findIndex(s => s.id === contextMenuSpriteId.value);
+ if (frameIndex !== -1) {
+ emit('openPixelEditor', props.activeLayerId, frameIndex);
+ }
+ }
+ showContextMenu.value = false;
+ contextMenuSpriteId.value = null;
+ }
+ };
+
const onDragLeave = (event: DragEvent) => {
handleDragLeave(event, gridContainerRef.value);
};
diff --git a/src/components/SpritePreview.vue b/src/components/SpritePreview.vue
index 16f10f1..cf53eb3 100644
--- a/src/components/SpritePreview.vue
+++ b/src/components/SpritePreview.vue
@@ -21,6 +21,10 @@
Copy to Frame...
+
+
+ Edit in Pixel Editor
+
@@ -299,6 +303,7 @@
(e: 'flipSprite', id: string, direction: 'horizontal' | 'vertical'): void;
(e: 'copySpriteToFrame', spriteId: string, targetLayerId: string, targetFrameIndex: number): void;
(e: 'replaceSprite', id: string, file: File): void;
+ (e: 'openPixelEditor', layerId: string, frameIndex: number): void;
}>();
const previewContainerRef = ref(null);
@@ -691,6 +696,13 @@
replacingSpriteId.value = null;
input.value = '';
};
+
+ const openPixelEditor = () => {
+ if (contextMenuSpriteId.value && contextMenuLayerId.value) {
+ emit('openPixelEditor', contextMenuLayerId.value, currentFrameIndex.value);
+ hideContextMenu();
+ }
+ };