[FEAT] Bug fixes
This commit is contained in:
@@ -9,6 +9,14 @@ html {
|
|||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Disable selection on images and canvases */
|
||||||
|
img,
|
||||||
|
canvas {
|
||||||
|
user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@apply bg-gray-50 text-gray-900 dark:bg-gray-950 dark:text-gray-100 antialiased font-sans;
|
@apply bg-gray-50 text-gray-900 dark:bg-gray-950 dark:text-gray-100 antialiased font-sans;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
|
|||||||
@@ -85,13 +85,12 @@
|
|||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- Current frame sprites -->
|
<!-- Current frame sprites - maintaining layer order -->
|
||||||
<template v-for="layer in getVisibleLayers()" :key="layer.id">
|
<template v-for="layer in getVisibleLayers()" :key="layer.id">
|
||||||
<img
|
<img
|
||||||
v-if="layer.sprites[currentFrameIndex]"
|
v-if="layer.sprites[currentFrameIndex]"
|
||||||
:src="layer.sprites[currentFrameIndex].url"
|
:src="layer.sprites[currentFrameIndex].url"
|
||||||
class="absolute"
|
class="absolute"
|
||||||
:class="{ 'cursor-move': isDraggable }"
|
|
||||||
:style="{
|
:style="{
|
||||||
left: `${Math.round(getCellPosition(0).x + gridMetrics.negativeSpacing + layer.sprites[currentFrameIndex].x)}px`,
|
left: `${Math.round(getCellPosition(0).x + gridMetrics.negativeSpacing + layer.sprites[currentFrameIndex].x)}px`,
|
||||||
top: `${Math.round(getCellPosition(0).y + gridMetrics.negativeSpacing + layer.sprites[currentFrameIndex].y)}px`,
|
top: `${Math.round(getCellPosition(0).y + gridMetrics.negativeSpacing + layer.sprites[currentFrameIndex].y)}px`,
|
||||||
@@ -100,12 +99,29 @@
|
|||||||
imageRendering: settingsStore.pixelPerfect ? 'pixelated' : 'auto',
|
imageRendering: settingsStore.pixelPerfect ? 'pixelated' : 'auto',
|
||||||
transform: `rotate(${layer.sprites[currentFrameIndex].rotation || 0}deg) scale(${layer.sprites[currentFrameIndex].flipX ? -1 : 1}, ${layer.sprites[currentFrameIndex].flipY ? -1 : 1})`,
|
transform: `rotate(${layer.sprites[currentFrameIndex].rotation || 0}deg) scale(${layer.sprites[currentFrameIndex].flipX ? -1 : 1}, ${layer.sprites[currentFrameIndex].flipY ? -1 : 1})`,
|
||||||
}"
|
}"
|
||||||
@mousedown="startDrag($event, layer.sprites[currentFrameIndex], layer.id)"
|
|
||||||
@touchstart="handleTouchStart($event, layer.sprites[currentFrameIndex], layer.id)"
|
|
||||||
@contextmenu.prevent="openContextMenu($event, layer.sprites[currentFrameIndex], layer.id)"
|
@contextmenu.prevent="openContextMenu($event, layer.sprites[currentFrameIndex], layer.id)"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- Invisible drag overlay for active layer sprite - sits on top to capture mouse events -->
|
||||||
|
<template v-if="isDraggable">
|
||||||
|
<template v-for="layer in getVisibleLayers()" :key="'drag-' + layer.id">
|
||||||
|
<div
|
||||||
|
v-if="layer.sprites[currentFrameIndex] && (layer.id === props.activeLayerId || repositionAllLayers)"
|
||||||
|
class="absolute cursor-move"
|
||||||
|
:style="{
|
||||||
|
left: `${Math.round(getCellPosition(0).x + gridMetrics.negativeSpacing + layer.sprites[currentFrameIndex].x)}px`,
|
||||||
|
top: `${Math.round(getCellPosition(0).y + gridMetrics.negativeSpacing + layer.sprites[currentFrameIndex].y)}px`,
|
||||||
|
width: `${Math.round(layer.sprites[currentFrameIndex].width)}px`,
|
||||||
|
height: `${Math.round(layer.sprites[currentFrameIndex].height)}px`,
|
||||||
|
zIndex: 100,
|
||||||
|
}"
|
||||||
|
@mousedown="startDrag($event, layer.sprites[currentFrameIndex], layer.id)"
|
||||||
|
@touchstart="handleTouchStart($event, layer.sprites[currentFrameIndex], layer.id)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Mobile zoom controls -->
|
<!-- Mobile zoom controls -->
|
||||||
@@ -320,6 +336,17 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
const getVisibleLayers = () => props.layers.filter(l => l.visible);
|
const getVisibleLayers = () => props.layers.filter(l => l.visible);
|
||||||
|
// Reversed order so active layer renders on top for drag operations
|
||||||
|
const getVisibleLayersReversed = () => {
|
||||||
|
const visible = props.layers.filter(l => l.visible);
|
||||||
|
// Put active layer last so it renders on top
|
||||||
|
const activeIdx = visible.findIndex(l => l.id === props.activeLayerId);
|
||||||
|
if (activeIdx > -1) {
|
||||||
|
const active = visible.splice(activeIdx, 1)[0];
|
||||||
|
visible.push(active);
|
||||||
|
}
|
||||||
|
return visible;
|
||||||
|
};
|
||||||
const maxFrames = () => Math.max(0, ...getVisibleLayers().map(l => l.sprites.length));
|
const maxFrames = () => Math.max(0, ...getVisibleLayers().map(l => l.sprites.length));
|
||||||
|
|
||||||
const { currentFrameIndex, isPlaying, fps, hiddenFrames, visibleFrames, visibleFramesCount, visibleFrameIndex, visibleFrameNumber, togglePlayback, nextFrame, previousFrame, handleSliderInput, toggleHiddenFrame, showAllFrames, hideAllFrames, stopAnimation } = useAnimationFrames({
|
const { currentFrameIndex, isPlaying, fps, hiddenFrames, visibleFrames, visibleFramesCount, visibleFrameIndex, visibleFrameNumber, togglePlayback, nextFrame, previousFrame, handleSliderInput, toggleHiddenFrame, showAllFrames, hideAllFrames, stopAnimation } = useAnimationFrames({
|
||||||
|
|||||||
@@ -615,27 +615,27 @@
|
|||||||
flipX: false,
|
flipX: false,
|
||||||
flipY: false,
|
flipY: false,
|
||||||
};
|
};
|
||||||
const insertIndex = frameIndex + fileIdx;
|
const targetIndex = frameIndex + fileIdx;
|
||||||
if (insertIndex < layer.sprites.length) {
|
|
||||||
layer.sprites = [...layer.sprites.slice(0, insertIndex), sprite, ...layer.sprites.slice(insertIndex + 1)];
|
// Extend the array with empty slots if needed
|
||||||
} else {
|
while (layer.sprites.length <= targetIndex) {
|
||||||
while (layer.sprites.length < insertIndex) {
|
layer.sprites.push({
|
||||||
layer.sprites.push({
|
id: crypto.randomUUID(),
|
||||||
id: crypto.randomUUID(),
|
file: new File([], 'empty'),
|
||||||
file: new File([], 'empty'),
|
img: new Image(),
|
||||||
img: new Image(),
|
url: '',
|
||||||
url: '',
|
width: 0,
|
||||||
width: 0,
|
height: 0,
|
||||||
height: 0,
|
x: 0,
|
||||||
x: 0,
|
y: 0,
|
||||||
y: 0,
|
rotation: 0,
|
||||||
rotation: 0,
|
flipX: false,
|
||||||
flipX: false,
|
flipY: false,
|
||||||
flipY: false,
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
layer.sprites = [...layer.sprites, sprite];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now replace at target index (either existing sprite or empty placeholder)
|
||||||
|
layer.sprites = [...layer.sprites.slice(0, targetIndex), sprite, ...layer.sprites.slice(targetIndex + 1)];
|
||||||
};
|
};
|
||||||
img.src = url;
|
img.src = url;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user