Fixes
This commit is contained in:
parent
1a16457efc
commit
293bed9135
@ -57,15 +57,7 @@
|
||||
<button @click="zoomIn" :disabled="previewZoom >= 5" class="flex items-center justify-center w-8 h-8 bg-gray-700 text-gray-200 border border-gray-600 rounded transition-colors disabled:opacity-60 disabled:cursor-not-allowed hover:border-blue-500">
|
||||
<i class="fas fa-search-plus"></i>
|
||||
</button>
|
||||
<button
|
||||
@click="applyOffsetsToMainView"
|
||||
:disabled="!hasSpriteOffset"
|
||||
class="flex items-center gap-1 px-2 h-8 bg-gray-700 text-gray-200 border border-gray-600 rounded text-xs transition-colors disabled:opacity-60 disabled:cursor-not-allowed hover:border-blue-500"
|
||||
title="Permanently apply offset to sprite position"
|
||||
>
|
||||
<i class="fas fa-save"></i>
|
||||
Apply Offset
|
||||
</button>
|
||||
<!-- Apply Offset button removed -->
|
||||
<button @click="resetZoom" :disabled="previewZoom === 1" class="flex items-center justify-center px-2 h-8 bg-gray-700 text-gray-200 border border-gray-600 rounded text-xs transition-colors disabled:opacity-60 disabled:cursor-not-allowed hover:border-blue-500">Reset Zoom</button>
|
||||
</div>
|
||||
|
||||
@ -78,23 +70,17 @@
|
||||
</label>
|
||||
|
||||
<!-- Reset sprite position button -->
|
||||
<button
|
||||
@click="resetSpritePosition"
|
||||
:disabled="!hasSpriteOffset"
|
||||
class="flex items-center gap-1 px-2 h-8 bg-gray-700 text-gray-200 border border-gray-600 rounded text-xs transition-colors disabled:opacity-60 disabled:cursor-not-allowed hover:border-blue-500"
|
||||
title="Reset sprite to original position"
|
||||
>
|
||||
<button @click="resetSpritePosition" :disabled="!hasSpriteOffset" class="flex items-center gap-1 px-2 h-8 bg-gray-700 text-gray-200 border border-gray-600 rounded text-xs transition-colors disabled:opacity-60 disabled:cursor-not-allowed hover:border-blue-500" title="Center sprite in cell">
|
||||
<i class="fas fa-crosshairs"></i>
|
||||
Reset Position
|
||||
Center Sprite
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col justify-center items-center bg-gray-700 p-6 rounded mb-6 relative overflow-auto flex-grow">
|
||||
<!-- Tooltip for dragging instructions -->
|
||||
<div class="text-xs text-gray-400 mb-2" v-if="hasSpriteOffset || sprites.length > 0">
|
||||
<span v-if="hasSpriteOffset">Sprite offset: {{ Math.round(spriteOffset.x) }}px, {{ Math.round(spriteOffset.y) }}px</span>
|
||||
<span v-else>Click and drag the sprite to move it within the cell</span>
|
||||
<div class="text-xs text-gray-400 mb-2" v-if="sprites.length > 0">
|
||||
<span>Position: {{ Math.round(spriteOffset.x) }}px, {{ Math.round(spriteOffset.y) }}px (drag to move within cell)</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@ -201,10 +187,7 @@
|
||||
return spriteOffset.x !== 0 || spriteOffset.y !== 0;
|
||||
});
|
||||
|
||||
const applyOffsetsToMainView = () => {
|
||||
store.applyOffsetsToMainView();
|
||||
store.showNotification('Offset permanently applied to sprite position');
|
||||
};
|
||||
// applyOffsetsToMainView function removed
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (!isModalOpen.value) return;
|
||||
@ -245,33 +228,17 @@
|
||||
resetSpritePosition();
|
||||
} else {
|
||||
// R: Reset both sprite position and viewport
|
||||
// Reset the sprite offset for the current frame
|
||||
const frameOffset = store.getSpriteOffset(currentFrame.value);
|
||||
frameOffset.x = 0;
|
||||
frameOffset.y = 0;
|
||||
store.currentSpriteOffset.x = 0;
|
||||
store.currentSpriteOffset.y = 0;
|
||||
viewportOffset.value = { x: 0, y: 0 };
|
||||
resetSpritePosition();
|
||||
updateFrame();
|
||||
store.showNotification('View and position reset');
|
||||
}
|
||||
e.preventDefault();
|
||||
} else if (previewZoom.value > 1) {
|
||||
// Arrow key navigation for panning when zoomed in
|
||||
const panAmount = 10;
|
||||
if (e.key === 'ArrowUp') {
|
||||
viewportOffset.value.y += panAmount / previewZoom.value;
|
||||
e.preventDefault();
|
||||
} else if (e.key === 'ArrowDown') {
|
||||
viewportOffset.value.y -= panAmount / previewZoom.value;
|
||||
e.preventDefault();
|
||||
} else if (e.key === 'ArrowLeft' && animation.value.isPlaying) {
|
||||
viewportOffset.value.x += panAmount / previewZoom.value;
|
||||
e.preventDefault();
|
||||
} else if (e.key === 'ArrowRight' && animation.value.isPlaying) {
|
||||
viewportOffset.value.x -= panAmount / previewZoom.value;
|
||||
e.preventDefault();
|
||||
}
|
||||
} else if (e.key === 'ArrowLeft' && animation.value.isPlaying) {
|
||||
viewportOffset.value.x += panAmount / previewZoom.value;
|
||||
e.preventDefault();
|
||||
} else if (e.key === 'ArrowRight' && animation.value.isPlaying) {
|
||||
viewportOffset.value.x -= panAmount / previewZoom.value;
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
@ -315,9 +282,22 @@
|
||||
|
||||
// Force render the first frame
|
||||
if (sprites.value.length > 0) {
|
||||
// Get the current sprite
|
||||
const currentSprite = sprites.value[0];
|
||||
|
||||
// Calculate center position
|
||||
const centerX = Math.max(0, Math.floor((store.cellSize.width - currentSprite.width) / 2));
|
||||
const centerY = Math.max(0, Math.floor((store.cellSize.height - currentSprite.height) / 2));
|
||||
|
||||
// Get the frame-specific offset for the first frame
|
||||
const frameOffset = store.getSpriteOffset(0);
|
||||
|
||||
// If the offset is (0,0), center the sprite
|
||||
if (frameOffset.x === 0 && frameOffset.y === 0) {
|
||||
frameOffset.x = centerX;
|
||||
frameOffset.y = centerY;
|
||||
}
|
||||
|
||||
// Update the current offset for UI display
|
||||
store.currentSpriteOffset.x = frameOffset.x;
|
||||
store.currentSpriteOffset.y = frameOffset.y;
|
||||
@ -448,22 +428,30 @@
|
||||
});
|
||||
};
|
||||
|
||||
// Reset sprite position to original
|
||||
// Reset sprite position to center
|
||||
const resetSpritePosition = () => {
|
||||
// Reset the sprite offset for the current frame to zero
|
||||
// Get current sprite
|
||||
const currentSprite = sprites.value[currentFrame.value];
|
||||
if (!currentSprite) return;
|
||||
|
||||
// Calculate center position
|
||||
const centerX = Math.max(0, Math.floor((store.cellSize.width - currentSprite.width) / 2));
|
||||
const centerY = Math.max(0, Math.floor((store.cellSize.height - currentSprite.height) / 2));
|
||||
|
||||
// Reset the sprite offset for the current frame to the center position
|
||||
const frameOffset = store.getSpriteOffset(currentFrame.value);
|
||||
frameOffset.x = 0;
|
||||
frameOffset.y = 0;
|
||||
frameOffset.x = centerX;
|
||||
frameOffset.y = centerY;
|
||||
|
||||
// Also update the current offset
|
||||
store.currentSpriteOffset.x = 0;
|
||||
store.currentSpriteOffset.y = 0;
|
||||
store.currentSpriteOffset.x = centerX;
|
||||
store.currentSpriteOffset.y = centerY;
|
||||
|
||||
// Update the frame to reflect the change
|
||||
updateFrame();
|
||||
|
||||
// Show a notification
|
||||
store.showNotification('Sprite position reset to original');
|
||||
store.showNotification('Sprite position reset to center');
|
||||
};
|
||||
|
||||
// Update canvas container size based on zoom level
|
||||
@ -477,74 +465,85 @@
|
||||
// Canvas drag functions for moving the sprite within its cell
|
||||
const startCanvasDrag = (e: MouseEvent) => {
|
||||
if (sprites.value.length === 0) return;
|
||||
|
||||
// Don't start sprite dragging if we're already dragging the viewport
|
||||
if (isViewportDragging.value) return;
|
||||
|
||||
isCanvasDragging.value = true;
|
||||
|
||||
// Store initial position
|
||||
canvasDragStart.value = {
|
||||
x: e.clientX,
|
||||
y: e.clientY,
|
||||
};
|
||||
|
||||
// Add temporary event listeners
|
||||
window.addEventListener('mousemove', handleCanvasDrag);
|
||||
window.addEventListener('mouseup', stopCanvasDrag);
|
||||
window.addEventListener('mousemove', handleCanvasDrag, { capture: true });
|
||||
window.addEventListener('mouseup', stopCanvasDrag, { capture: true });
|
||||
|
||||
// Prevent default to avoid text selection
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const handleCanvasDrag = (e: MouseEvent) => {
|
||||
if (!isCanvasDragging.value) return;
|
||||
|
||||
const deltaX = e.clientX - canvasDragStart.value.x;
|
||||
const deltaY = e.clientY - canvasDragStart.value.y;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
// Get the frame-specific offset
|
||||
const frameOffset = store.getSpriteOffset(currentFrame.value);
|
||||
|
||||
// Calculate new position and round to nearest pixel
|
||||
const newX = Math.round(frameOffset.x + deltaX / previewZoom.value);
|
||||
const newY = Math.round(frameOffset.y + deltaY / previewZoom.value);
|
||||
|
||||
// Get current sprite
|
||||
const currentSprite = sprites.value[currentFrame.value];
|
||||
if (!currentSprite) return;
|
||||
|
||||
// Calculate maximum allowed offset based on sprite and cell size
|
||||
const maxOffsetX = Math.floor((store.cellSize.width - currentSprite.width) / 2);
|
||||
const maxOffsetY = Math.floor((store.cellSize.height - currentSprite.height) / 2);
|
||||
// Calculate delta from last position
|
||||
const deltaX = e.clientX - canvasDragStart.value.x;
|
||||
const deltaY = e.clientY - canvasDragStart.value.y;
|
||||
|
||||
// Constrain movement to stay within cell boundaries, preventing negative offsets
|
||||
const constrainedX = Math.max(0, Math.min(maxOffsetX, newX));
|
||||
const constrainedY = Math.max(0, Math.min(maxOffsetY, newY));
|
||||
// Only move when delta exceeds the threshold for one pixel movement at current zoom
|
||||
const pixelThreshold = previewZoom.value; // One pixel at current zoom level
|
||||
|
||||
// Update both the current offset and the frame-specific offset
|
||||
frameOffset.x = constrainedX;
|
||||
frameOffset.y = constrainedY;
|
||||
store.currentSpriteOffset.x = constrainedX;
|
||||
store.currentSpriteOffset.y = constrainedY;
|
||||
// Get the frame-specific offset
|
||||
const frameOffset = store.getSpriteOffset(currentFrame.value);
|
||||
|
||||
// Reset drag start position
|
||||
canvasDragStart.value = {
|
||||
x: e.clientX,
|
||||
y: e.clientY,
|
||||
};
|
||||
// Calculate the maximum allowed offset
|
||||
const maxOffsetX = Math.max(0, store.cellSize.width - currentSprite.width);
|
||||
const maxOffsetY = Math.max(0, store.cellSize.height - currentSprite.height);
|
||||
|
||||
// Update the frame with the new offset
|
||||
// Move one pixel at a time when threshold is reached
|
||||
if (Math.abs(deltaX) >= pixelThreshold) {
|
||||
const pixelsToMove = Math.sign(deltaX);
|
||||
const newX = frameOffset.x + pixelsToMove;
|
||||
frameOffset.x = Math.max(0, Math.min(maxOffsetX, newX));
|
||||
|
||||
// Reset the start X position for next pixel move
|
||||
canvasDragStart.value.x = e.clientX;
|
||||
}
|
||||
|
||||
if (Math.abs(deltaY) >= pixelThreshold) {
|
||||
const pixelsToMove = Math.sign(deltaY);
|
||||
const newY = frameOffset.y + pixelsToMove;
|
||||
frameOffset.y = Math.max(0, Math.min(maxOffsetY, newY));
|
||||
|
||||
// Reset the start Y position for next pixel move
|
||||
canvasDragStart.value.y = e.clientY;
|
||||
}
|
||||
|
||||
// Update the current offset to match
|
||||
store.currentSpriteOffset.x = frameOffset.x;
|
||||
store.currentSpriteOffset.y = frameOffset.y;
|
||||
|
||||
// Update the frame
|
||||
updateFrame();
|
||||
|
||||
// Re-render the main view to reflect the changes
|
||||
// Re-render the main view
|
||||
store.renderSpritesheetPreview();
|
||||
});
|
||||
};
|
||||
|
||||
const stopCanvasDrag = () => {
|
||||
const stopCanvasDrag = (e: MouseEvent) => {
|
||||
if (!isCanvasDragging.value) return;
|
||||
|
||||
isCanvasDragging.value = false;
|
||||
window.removeEventListener('mousemove', handleCanvasDrag);
|
||||
window.removeEventListener('mouseup', stopCanvasDrag);
|
||||
window.removeEventListener('mousemove', handleCanvasDrag, { capture: true });
|
||||
window.removeEventListener('mouseup', stopCanvasDrag, { capture: true });
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
// Canvas viewport navigation functions
|
||||
|
@ -527,8 +527,9 @@ export function useSpritesheetStore() {
|
||||
const originalOffsetY = Math.round(currentSprite.y - cellY * cellSize.height);
|
||||
|
||||
// Calculate precise offset for pixel-perfect rendering, including the user's drag offset
|
||||
const offsetX = originalOffsetX + spriteOffset.x;
|
||||
const offsetY = originalOffsetY + spriteOffset.y;
|
||||
// Use the spriteOffset directly as the position within the cell
|
||||
const offsetX = spriteOffset.x;
|
||||
const offsetY = spriteOffset.y;
|
||||
|
||||
// Draw the current sprite at full opacity at the new position
|
||||
animation.ctx.drawImage(currentSprite.img, offsetX, offsetY);
|
||||
|
Loading…
x
Reference in New Issue
Block a user