idek
This commit is contained in:
parent
a773b51ece
commit
22390acfa6
@ -28,12 +28,23 @@ export function addSprites(newSprites: Sprite[]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Log the number of valid sprites being added
|
||||
logger.info(`Adding ${validSprites.length} valid sprites`);
|
||||
|
||||
sprites.value.push(...validSprites);
|
||||
sprites.value.sort((a, b) => a.uploadOrder - b.uploadOrder);
|
||||
|
||||
// Update cell size before arranging sprites
|
||||
logger.info('Updating cell size after adding sprites');
|
||||
updateCellSize();
|
||||
autoArrangeSprites();
|
||||
|
||||
// Only auto-arrange if cell size is valid
|
||||
if (cellSize && typeof cellSize.width === 'number' && typeof cellSize.height === 'number' && cellSize.width > 0 && cellSize.height > 0) {
|
||||
logger.info('Auto-arranging sprites');
|
||||
autoArrangeSprites();
|
||||
} else {
|
||||
logger.warn('Skipping auto-arrange due to invalid cell size');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error adding sprites:', error);
|
||||
}
|
||||
@ -44,12 +55,14 @@ export function addSprites(newSprites: Sprite[]) {
|
||||
*/
|
||||
export function updateCellSize() {
|
||||
if (sprites.value.length === 0) {
|
||||
logger.warn('Cannot update cell size: no sprites available');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let maxWidth = 0;
|
||||
let maxHeight = 0;
|
||||
let validSpriteCount = 0;
|
||||
|
||||
// Find the maximum dimensions across all sprites
|
||||
sprites.value.forEach(sprite => {
|
||||
@ -59,17 +72,29 @@ export function updateCellSize() {
|
||||
}
|
||||
maxWidth = Math.max(maxWidth, sprite.width);
|
||||
maxHeight = Math.max(maxHeight, sprite.height);
|
||||
validSpriteCount++;
|
||||
});
|
||||
|
||||
if (maxWidth === 0 || maxHeight === 0) {
|
||||
logger.error('Failed to calculate valid cell size');
|
||||
if (maxWidth === 0 || maxHeight === 0 || validSpriteCount === 0) {
|
||||
logger.error('Failed to calculate valid cell size - no valid sprites found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Add a small buffer to ensure sprites fit completely (optional)
|
||||
const buffer = 0; // Increase if you want padding between sprites
|
||||
cellSize.width = maxWidth + buffer;
|
||||
cellSize.height = maxHeight + buffer;
|
||||
|
||||
// Set cell size with validation
|
||||
const newWidth = maxWidth + buffer;
|
||||
const newHeight = maxHeight + buffer;
|
||||
|
||||
if (newWidth <= 0 || newHeight <= 0) {
|
||||
logger.error(`Invalid calculated cell dimensions: ${newWidth}x${newHeight}`);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(`Updating cell size to ${newWidth}x${newHeight}`);
|
||||
cellSize.width = newWidth;
|
||||
cellSize.height = newHeight;
|
||||
|
||||
// Ensure all sprites are within their cell bounds after resize
|
||||
sprites.value.forEach((sprite, index) => {
|
||||
@ -100,13 +125,25 @@ export function updateCellSize() {
|
||||
*/
|
||||
export function autoArrangeSprites() {
|
||||
if (sprites.value.length === 0) {
|
||||
logger.warn('No sprites to arrange');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (cellSize.width <= 0 || cellSize.height <= 0) {
|
||||
// Ensure cell size is valid before proceeding
|
||||
if (!cellSize || typeof cellSize.width !== 'number' || typeof cellSize.height !== 'number' || cellSize.width <= 0 || cellSize.height <= 0) {
|
||||
logger.error('Invalid cell size for auto-arranging', cellSize);
|
||||
return;
|
||||
|
||||
// Try to update cell size first
|
||||
updateCellSize();
|
||||
|
||||
// Check again after update attempt
|
||||
if (!cellSize || typeof cellSize.width !== 'number' || typeof cellSize.height !== 'number' || cellSize.width <= 0 || cellSize.height <= 0) {
|
||||
logger.error('Still invalid cell size after update attempt', cellSize);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.warn('Cell size was updated and is now valid');
|
||||
}
|
||||
|
||||
// First update the canvas size to ensure it's large enough
|
||||
|
@ -5,6 +5,9 @@ import { type Sprite } from '@/application/types';
|
||||
* Logger utility with consistent error format
|
||||
*/
|
||||
export const logger = {
|
||||
info: (message: string, details?: any) => {
|
||||
console.log(`Spritesheet: ${message}`, details || '');
|
||||
},
|
||||
warn: (message: string, details?: any) => {
|
||||
console.warn(`Spritesheet: ${message}`, details || '');
|
||||
},
|
||||
|
@ -1,5 +1,12 @@
|
||||
<template>
|
||||
<div @click="openFileDialog" @dragover.prevent="onDragOver" @dragleave="onDragLeave" @drop.prevent="onDrop" class="border-2 border-dashed border-gray-600 rounded-lg p-8 text-center cursor-pointer transition-all" :class="{ 'border-blue-500 bg-blue-500 bg-opacity-5': isDragOver }">
|
||||
<div
|
||||
@click="openFileDialog"
|
||||
@dragover.prevent.stop="onDragOver"
|
||||
@dragleave.prevent.stop="onDragLeave"
|
||||
@drop.prevent.stop="onDrop"
|
||||
class="border-2 border-dashed border-gray-600 rounded-lg p-8 text-center cursor-pointer transition-all"
|
||||
:class="{ 'border-blue-500 bg-blue-500 bg-opacity-5': isDragOver }"
|
||||
>
|
||||
<i class="fas fa-cloud-upload-alt text-blue-500 text-3xl mb-4"></i>
|
||||
<p class="text-gray-400">Drag & drop sprite images here<br />or click to select files</p>
|
||||
<input type="file" ref="fileInput" multiple accept="image/*" class="hidden" @change="onFileChange" />
|
||||
@ -37,6 +44,8 @@
|
||||
if (e.dataTransfer?.files.length) {
|
||||
handleFiles(e.dataTransfer.files);
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const onFileChange = (e: Event) => {
|
||||
|
@ -158,6 +158,9 @@
|
||||
|
||||
if (!canvasEl.value) return;
|
||||
|
||||
// Prevent default to avoid any browser handling that might interfere
|
||||
e.preventDefault();
|
||||
|
||||
const rect = canvasEl.value.getBoundingClientRect();
|
||||
// Adjust coordinates for zoom level
|
||||
const x = (e.clientX - rect.left) / store.zoomLevel.value;
|
||||
@ -265,8 +268,14 @@
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseUp = () => {
|
||||
const handleMouseUp = (e: MouseEvent) => {
|
||||
store.draggedSprite.value = null;
|
||||
|
||||
// Ensure the event is captured
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseOut = () => {
|
||||
@ -322,14 +331,19 @@
|
||||
// Regular sprite dragging
|
||||
handleMouseDown(e);
|
||||
}
|
||||
|
||||
// Ensure the event is captured
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle mouse movement on the canvas for panning and sprite interactions
|
||||
*/
|
||||
const handleCanvasMouseMove = (e: MouseEvent) => {
|
||||
// Always prevent default to ensure consistent behavior
|
||||
e.preventDefault();
|
||||
|
||||
if (isPanning.value && containerEl.value) {
|
||||
e.preventDefault();
|
||||
// Calculate the distance moved since last position
|
||||
const dx = e.clientX - lastPosition.value.x;
|
||||
const dy = e.clientY - lastPosition.value.y;
|
||||
@ -345,11 +359,18 @@
|
||||
// Handle regular mouse move for sprites and tooltip
|
||||
handleMouseMove(e);
|
||||
}
|
||||
|
||||
// Ensure the event is captured
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const handleCanvasMouseUp = () => {
|
||||
const handleCanvasMouseUp = (e: MouseEvent) => {
|
||||
isPanning.value = false;
|
||||
handleMouseUp();
|
||||
handleMouseUp(e);
|
||||
|
||||
// Ensure the event is captured
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
const handleCanvasMouseLeave = () => {
|
||||
@ -371,11 +392,15 @@
|
||||
}
|
||||
|
||||
// Set up mouse events for the canvas
|
||||
canvasEl.value.addEventListener('mousedown', handleCanvasMouseDown);
|
||||
canvasEl.value.addEventListener('mousemove', handleCanvasMouseMove);
|
||||
canvasEl.value.addEventListener('mouseup', handleCanvasMouseUp);
|
||||
canvasEl.value.addEventListener('mouseleave', handleCanvasMouseLeave);
|
||||
canvasEl.value.addEventListener('contextmenu', preventContextMenu);
|
||||
canvasEl.value.addEventListener('mousedown', handleCanvasMouseDown, { passive: false });
|
||||
canvasEl.value.addEventListener('mousemove', handleCanvasMouseMove, { passive: false });
|
||||
canvasEl.value.addEventListener('mouseup', handleCanvasMouseUp, { passive: false });
|
||||
canvasEl.value.addEventListener('mouseleave', handleCanvasMouseLeave, { passive: false });
|
||||
canvasEl.value.addEventListener('contextmenu', preventContextMenu, { passive: false });
|
||||
|
||||
// Add global event listeners to ensure drag operations complete even if cursor leaves canvas
|
||||
window.addEventListener('mousemove', handleCanvasMouseMove, { passive: false });
|
||||
window.addEventListener('mouseup', handleCanvasMouseUp, { passive: false });
|
||||
};
|
||||
|
||||
// Handle window resize to update canvas dimensions
|
||||
@ -467,6 +492,10 @@
|
||||
canvasEl.value.removeEventListener('mouseleave', handleCanvasMouseLeave);
|
||||
canvasEl.value.removeEventListener('contextmenu', preventContextMenu);
|
||||
}
|
||||
|
||||
// Remove global event listeners
|
||||
window.removeEventListener('mousemove', handleCanvasMouseMove);
|
||||
window.removeEventListener('mouseup', handleCanvasMouseUp);
|
||||
} catch (error) {
|
||||
logger.error('Error during component unmount:', error);
|
||||
}
|
||||
|
@ -27,8 +27,8 @@
|
||||
minHeight: `${store.cellSize.height * previewZoom}px`,
|
||||
cursor: previewZoom > 1 ? (isViewportDragging ? 'grabbing' : 'grab') : 'default',
|
||||
}"
|
||||
@mousedown="e => startViewportDrag(e, isCanvasDragging)"
|
||||
@wheel="handleCanvasWheel"
|
||||
@mousedown.prevent="e => startViewportDrag(e, isCanvasDragging)"
|
||||
@wheel.prevent="handleCanvasWheel"
|
||||
>
|
||||
<div
|
||||
class="sprite-wrapper"
|
||||
@ -47,7 +47,7 @@
|
||||
backgroundPosition: '0 0, 0 5px, 5px -5px, -5px 0px',
|
||||
backgroundColor: '#2d3748',
|
||||
}"
|
||||
@mousedown.stop="e => startCanvasDrag(e, isViewportDragging, previewZoom)"
|
||||
@mousedown.prevent.stop="e => startCanvasDrag(e, isViewportDragging, previewZoom)"
|
||||
title="Drag to move sprite within cell"
|
||||
>
|
||||
<canvas ref="animCanvas" class="block pixel-art absolute top-0 left-0"></canvas>
|
||||
@ -143,7 +143,9 @@
|
||||
await nextTick();
|
||||
|
||||
// Ensure cell size is valid before proceeding
|
||||
if (!store.cellSize || typeof store.cellSize.width !== 'number' || typeof store.cellSize.height !== 'number' || store.cellSize.width <= 0 || store.cellSize.height <= 0) {
|
||||
if (!store.cellSize.value || typeof store.cellSize.value.width !== 'number' || typeof store.cellSize.value.height !== 'number' || store.cellSize.value.width <= 0 || store.cellSize.value.height <= 0) {
|
||||
console.log('Attempting to update cell size...', store.cellSize.value);
|
||||
|
||||
// Try to update cell size if there are sprites
|
||||
if (sprites.value.length > 0) {
|
||||
store.updateCellSize();
|
||||
@ -151,8 +153,12 @@
|
||||
}
|
||||
|
||||
// Check again after update attempt
|
||||
if (!store.cellSize || typeof store.cellSize.width !== 'number' || typeof store.cellSize.height !== 'number' || store.cellSize.width <= 0 || store.cellSize.height <= 0) {
|
||||
if (!store.cellSize.value || typeof store.cellSize.value.width !== 'number' || typeof store.cellSize.value.height !== 'number' || store.cellSize.value.width <= 0 || store.cellSize.value.height <= 0) {
|
||||
console.warn('Failed to set valid cell dimensions', store.cellSize.value);
|
||||
store.showNotification('Invalid cell dimensions. Please check sprite sizes.', 'error');
|
||||
return; // Don't proceed if we can't set valid cell dimensions
|
||||
} else {
|
||||
console.log('Successfully updated cell size to', store.cellSize.value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,6 +248,24 @@
|
||||
}
|
||||
);
|
||||
|
||||
// Watch for changes in cellSize to update the canvas
|
||||
watch(
|
||||
() => store.cellSize.value,
|
||||
newCellSize => {
|
||||
if (isModalOpen.value && sprites.value.length > 0) {
|
||||
if (newCellSize && typeof newCellSize.width === 'number' && typeof newCellSize.height === 'number' && newCellSize.width > 0 && newCellSize.height > 0) {
|
||||
console.log('Cell size changed, updating canvas...', newCellSize);
|
||||
updateCanvasSize();
|
||||
updateCanvasContainerSize();
|
||||
updateFrame();
|
||||
} else {
|
||||
console.warn('Invalid cell size detected in watcher', newCellSize);
|
||||
}
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
// Expose openModal for external use
|
||||
defineExpose({ openModal });
|
||||
</script>
|
||||
|
@ -58,6 +58,13 @@ export function useSpritePosition(sprites: Ref<Sprite[]>, currentFrame: Ref<numb
|
||||
if (sprites.value.length === 0) return;
|
||||
if (isViewportDragging.value) return;
|
||||
|
||||
// Validate cell size before starting drag
|
||||
if (!cellSize.value || typeof cellSize.value.width !== 'number' || typeof cellSize.value.height !== 'number' || cellSize.value.width <= 0 || cellSize.value.height <= 0) {
|
||||
console.warn('Cannot start drag - invalid cell dimensions', cellSize.value ? `width: ${cellSize.value.width}, height: ${cellSize.value.height}` : 'cellSize is undefined');
|
||||
showNotification('Cannot drag sprite - invalid cell dimensions', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
isCanvasDragging.value = true;
|
||||
|
||||
// Store initial position
|
||||
@ -66,9 +73,13 @@ export function useSpritePosition(sprites: Ref<Sprite[]>, currentFrame: Ref<numb
|
||||
y: e.clientY,
|
||||
};
|
||||
|
||||
// Add event listeners
|
||||
window.addEventListener('mousemove', e => handleCanvasDrag(e, previewZoom), { capture: true });
|
||||
window.addEventListener('mouseup', stopCanvasDrag, { capture: true });
|
||||
// Add event listeners with passive: false to ensure preventDefault works
|
||||
const boundHandleCanvasDrag = (e: MouseEvent) => handleCanvasDrag(e, previewZoom);
|
||||
window.addEventListener('mousemove', boundHandleCanvasDrag, { capture: true, passive: false });
|
||||
window.addEventListener('mouseup', stopCanvasDrag, { capture: true, passive: false });
|
||||
|
||||
// Store the bound function for later removal
|
||||
(window as any).__boundHandleCanvasDrag = boundHandleCanvasDrag;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@ -82,9 +93,11 @@ export function useSpritePosition(sprites: Ref<Sprite[]>, currentFrame: Ref<numb
|
||||
const sprite = sprites.value[currentFrame.value];
|
||||
if (!sprite) return;
|
||||
|
||||
// Check if cellSize is properly defined
|
||||
if (!cellSize.value || typeof cellSize.value.width !== 'number' || typeof cellSize.value.height !== 'number') {
|
||||
console.warn('Invalid cell dimensions during drag operation');
|
||||
// More robust check for cellSize validity
|
||||
if (!cellSize.value || typeof cellSize.value.width !== 'number' || typeof cellSize.value.height !== 'number' || cellSize.value.width <= 0 || cellSize.value.height <= 0) {
|
||||
console.warn('Invalid cell dimensions during drag operation', cellSize.value ? `width: ${cellSize.value.width}, height: ${cellSize.value.height}` : 'cellSize is undefined');
|
||||
showNotification('Cannot drag sprite - invalid cell dimensions', 'error');
|
||||
isCanvasDragging.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -127,9 +140,13 @@ export function useSpritePosition(sprites: Ref<Sprite[]>, currentFrame: Ref<numb
|
||||
if (!isCanvasDragging.value) return;
|
||||
|
||||
isCanvasDragging.value = false;
|
||||
window.removeEventListener('mousemove', handleCanvasDrag as any, { capture: true });
|
||||
// Use the stored bound function for removal
|
||||
window.removeEventListener('mousemove', (window as any).__boundHandleCanvasDrag, { capture: true });
|
||||
window.removeEventListener('mouseup', stopCanvasDrag, { capture: true });
|
||||
|
||||
// Clean up the reference
|
||||
delete (window as any).__boundHandleCanvasDrag;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
@ -56,9 +56,9 @@ export function useViewport(animation: Ref<AnimationState>, onUpdateFrame: () =>
|
||||
y: e.clientY,
|
||||
};
|
||||
|
||||
// Add temporary event listeners
|
||||
window.addEventListener('mousemove', handleViewportDrag);
|
||||
window.addEventListener('mouseup', stopViewportDrag);
|
||||
// Add temporary event listeners with passive: false to ensure preventDefault works
|
||||
window.addEventListener('mousemove', handleViewportDrag, { passive: false });
|
||||
window.addEventListener('mouseup', stopViewportDrag, { passive: false });
|
||||
|
||||
// Prevent default to avoid text selection
|
||||
e.preventDefault();
|
||||
@ -67,6 +67,10 @@ export function useViewport(animation: Ref<AnimationState>, onUpdateFrame: () =>
|
||||
const handleViewportDrag = (e: MouseEvent) => {
|
||||
if (!isViewportDragging.value) return;
|
||||
|
||||
// Prevent default browser behavior
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const deltaX = e.clientX - viewportDragStart.value.x;
|
||||
const deltaY = e.clientY - viewportDragStart.value.y;
|
||||
|
||||
@ -83,10 +87,18 @@ export function useViewport(animation: Ref<AnimationState>, onUpdateFrame: () =>
|
||||
};
|
||||
};
|
||||
|
||||
const stopViewportDrag = () => {
|
||||
const stopViewportDrag = (e: MouseEvent) => {
|
||||
if (!isViewportDragging.value) return;
|
||||
|
||||
isViewportDragging.value = false;
|
||||
window.removeEventListener('mousemove', handleViewportDrag);
|
||||
window.removeEventListener('mouseup', stopViewportDrag);
|
||||
|
||||
// Prevent default browser behavior
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
const handleCanvasWheel = (e: WheelEvent) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user