format
This commit is contained in:
parent
3e849c0286
commit
5a7f7032ef
@ -113,7 +113,7 @@ export function createSpriteFromFile(file: File, index: number): Promise<Sprite>
|
|||||||
/**
|
/**
|
||||||
* Process multiple files and create sprites
|
* Process multiple files and create sprites
|
||||||
*/
|
*/
|
||||||
export async function processImageFiles(files: FileList): Promise<{ newSprites: Sprite[], errorCount: number }> {
|
export async function processImageFiles(files: FileList): Promise<{ newSprites: Sprite[]; errorCount: number }> {
|
||||||
const imageFiles = Array.from(files).filter(file => file.type.startsWith('image/'));
|
const imageFiles = Array.from(files).filter(file => file.type.startsWith('image/'));
|
||||||
|
|
||||||
if (imageFiles.length === 0) {
|
if (imageFiles.length === 0) {
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted, onBeforeUnmount, watch, nextTick } from 'vue';
|
import { ref, computed, onMounted, onBeforeUnmount, watch, nextTick } from 'vue';
|
||||||
import { useSpritesheetStore } from '../composables/useSpritesheetStore';
|
import { useSpritesheetStore } from '../composables/useSpritesheetStore';
|
||||||
|
import { logger, getPixelPerfectCoordinate } from '../application/utilities';
|
||||||
|
|
||||||
const store = useSpritesheetStore();
|
const store = useSpritesheetStore();
|
||||||
const canvasEl = ref<HTMLCanvasElement | null>(null);
|
const canvasEl = ref<HTMLCanvasElement | null>(null);
|
||||||
@ -102,10 +103,9 @@
|
|||||||
{ deep: true }
|
{ deep: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
const setupCheckerboardPattern = () => {
|
/**
|
||||||
// Remove this function or leave it empty since we don't need it anymore
|
* Update canvas size based on container dimensions
|
||||||
};
|
*/
|
||||||
|
|
||||||
const updateCanvasSize = () => {
|
const updateCanvasSize = () => {
|
||||||
if (!canvasEl.value || !containerEl.value) return;
|
if (!canvasEl.value || !containerEl.value) return;
|
||||||
|
|
||||||
@ -114,11 +114,10 @@
|
|||||||
containerHeight.value = containerEl.value.clientHeight;
|
containerHeight.value = containerEl.value.clientHeight;
|
||||||
|
|
||||||
// Set the base canvas size to fill the container
|
// Set the base canvas size to fill the container
|
||||||
// These are the "unzoomed" dimensions
|
|
||||||
baseCanvasWidth.value = Math.max(containerWidth.value, store.cellSize.width * Math.ceil(containerWidth.value / store.cellSize.width));
|
baseCanvasWidth.value = Math.max(containerWidth.value, store.cellSize.width * Math.ceil(containerWidth.value / store.cellSize.width));
|
||||||
baseCanvasHeight.value = Math.max(containerHeight.value, store.cellSize.height * Math.ceil(containerHeight.value / store.cellSize.height));
|
baseCanvasHeight.value = Math.max(containerHeight.value, store.cellSize.height * Math.ceil(containerHeight.value / store.cellSize.height));
|
||||||
|
|
||||||
// Set the actual canvas dimensions - remove any zoom scaling here
|
// Set the actual canvas dimensions
|
||||||
canvasEl.value.width = baseCanvasWidth.value;
|
canvasEl.value.width = baseCanvasWidth.value;
|
||||||
canvasEl.value.height = baseCanvasHeight.value;
|
canvasEl.value.height = baseCanvasHeight.value;
|
||||||
|
|
||||||
@ -146,6 +145,9 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle mouse movement for tooltips and sprite dragging
|
||||||
|
*/
|
||||||
const handleMouseMove = (e: MouseEvent) => {
|
const handleMouseMove = (e: MouseEvent) => {
|
||||||
// Don't process sprite movement or tooltips while panning
|
// Don't process sprite movement or tooltips while panning
|
||||||
if (isPanning.value) return;
|
if (isPanning.value) return;
|
||||||
@ -153,14 +155,15 @@
|
|||||||
if (!canvasEl.value) return;
|
if (!canvasEl.value) return;
|
||||||
|
|
||||||
const rect = canvasEl.value.getBoundingClientRect();
|
const rect = canvasEl.value.getBoundingClientRect();
|
||||||
// Adjust coordinates for zoom
|
// Adjust coordinates for zoom level
|
||||||
const x = (e.clientX - rect.left) / store.zoomLevel.value;
|
const x = (e.clientX - rect.left) / store.zoomLevel.value;
|
||||||
const y = (e.clientY - rect.top) / store.zoomLevel.value;
|
const y = (e.clientY - rect.top) / store.zoomLevel.value;
|
||||||
|
|
||||||
// Update tooltip
|
// Update tooltip with cell coordinates
|
||||||
const cellX = Math.floor(x / store.cellSize.width);
|
const cellX = Math.floor(x / store.cellSize.width);
|
||||||
const cellY = Math.floor(y / store.cellSize.height);
|
const cellY = Math.floor(y / store.cellSize.height);
|
||||||
|
|
||||||
|
// Show tooltip if mouse is within canvas bounds
|
||||||
if (canvasEl.value && cellX >= 0 && cellX < canvasEl.value.width / store.cellSize.width && cellY >= 0 && cellY < canvasEl.value.height / store.cellSize.height) {
|
if (canvasEl.value && cellX >= 0 && cellX < canvasEl.value.width / store.cellSize.width && cellY >= 0 && cellY < canvasEl.value.height / store.cellSize.height) {
|
||||||
isTooltipVisible.value = true;
|
isTooltipVisible.value = true;
|
||||||
tooltipText.value = `Cell: (${cellX}, ${cellY})`;
|
tooltipText.value = `Cell: (${cellX}, ${cellY})`;
|
||||||
@ -170,7 +173,7 @@
|
|||||||
isTooltipVisible.value = false;
|
isTooltipVisible.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the sprite if we're dragging one
|
// Handle sprite dragging
|
||||||
if (store.draggedSprite.value) {
|
if (store.draggedSprite.value) {
|
||||||
if (store.isShiftPressed.value) {
|
if (store.isShiftPressed.value) {
|
||||||
// Free positioning within the cell bounds when shift is pressed
|
// Free positioning within the cell bounds when shift is pressed
|
||||||
@ -223,12 +226,11 @@
|
|||||||
const boundedCellX = Math.max(0, Math.min(newCellX, maxCellX));
|
const boundedCellX = Math.max(0, Math.min(newCellX, maxCellX));
|
||||||
const boundedCellY = Math.max(0, Math.min(newCellY, maxCellY));
|
const boundedCellY = Math.max(0, Math.min(newCellY, maxCellY));
|
||||||
|
|
||||||
const oldX = store.draggedSprite.value.x;
|
// Update the sprite position with pixel-perfect coordinates
|
||||||
const oldY = store.draggedSprite.value.y;
|
const newX = boundedCellX * store.cellSize.width;
|
||||||
|
const newY = boundedCellY * store.cellSize.height;
|
||||||
// Update the sprite position
|
store.draggedSprite.value.x = newX;
|
||||||
store.draggedSprite.value.x = boundedCellX * store.cellSize.width;
|
store.draggedSprite.value.y = newY;
|
||||||
store.draggedSprite.value.y = boundedCellY * store.cellSize.height;
|
|
||||||
|
|
||||||
// When snapping to grid, reset any offsets for this sprite
|
// When snapping to grid, reset any offsets for this sprite
|
||||||
const spriteIndex = store.sprites.value.findIndex(s => s.id === store.draggedSprite.value.id);
|
const spriteIndex = store.sprites.value.findIndex(s => s.id === store.draggedSprite.value.id);
|
||||||
@ -258,6 +260,9 @@
|
|||||||
store.draggedSprite.value = null;
|
store.draggedSprite.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle keyboard down events
|
||||||
|
*/
|
||||||
const handleKeyDown = (e: KeyboardEvent) => {
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
if (e.key === 'Shift') {
|
if (e.key === 'Shift') {
|
||||||
store.isShiftPressed.value = true;
|
store.isShiftPressed.value = true;
|
||||||
@ -268,7 +273,7 @@
|
|||||||
isAltPressed.value = true;
|
isAltPressed.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add keyboard shortcuts for zooming
|
// Handle keyboard shortcuts for zooming
|
||||||
if (e.ctrlKey || e.metaKey) {
|
if (e.ctrlKey || e.metaKey) {
|
||||||
if (e.key === '=' || e.key === '+') {
|
if (e.key === '=' || e.key === '+') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -305,13 +310,18 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle mouse movement on the canvas for panning and sprite interactions
|
||||||
|
*/
|
||||||
const handleCanvasMouseMove = (e: MouseEvent) => {
|
const handleCanvasMouseMove = (e: MouseEvent) => {
|
||||||
if (isPanning.value && containerEl.value) {
|
if (isPanning.value && containerEl.value) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
// Calculate the distance moved since last position
|
||||||
const dx = e.clientX - lastPosition.value.x;
|
const dx = e.clientX - lastPosition.value.x;
|
||||||
const dy = e.clientY - lastPosition.value.y;
|
const dy = e.clientY - lastPosition.value.y;
|
||||||
|
|
||||||
// Scroll the container in the opposite direction of the mouse movement
|
// Scroll the container in the opposite direction of the mouse movement
|
||||||
|
// for natural panning behavior
|
||||||
containerEl.value.scrollLeft -= dx;
|
containerEl.value.scrollLeft -= dx;
|
||||||
containerEl.value.scrollTop -= dy;
|
containerEl.value.scrollTop -= dy;
|
||||||
|
|
||||||
@ -337,8 +347,14 @@
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up all canvas event listeners
|
||||||
|
*/
|
||||||
const setupCanvasEvents = () => {
|
const setupCanvasEvents = () => {
|
||||||
if (!canvasEl.value) return;
|
if (!canvasEl.value) {
|
||||||
|
logger.warn('Cannot set up canvas events: canvas element not available');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Set up mouse events for the canvas
|
// Set up mouse events for the canvas
|
||||||
canvasEl.value.addEventListener('mousedown', handleCanvasMouseDown);
|
canvasEl.value.addEventListener('mousedown', handleCanvasMouseDown);
|
||||||
@ -353,35 +369,48 @@
|
|||||||
updateCanvasSize();
|
updateCanvasSize();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component lifecycle hook - setup
|
||||||
|
*/
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
// Set up global event listeners
|
try {
|
||||||
window.addEventListener('keydown', handleKeyDown);
|
// Set up global event listeners
|
||||||
window.addEventListener('keyup', handleKeyUp);
|
window.addEventListener('keydown', handleKeyDown);
|
||||||
window.addEventListener('resize', handleResize);
|
window.addEventListener('keyup', handleKeyUp);
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
|
||||||
// Initialize the canvas
|
// Initialize the canvas after DOM is updated
|
||||||
await nextTick();
|
await nextTick();
|
||||||
initializeCanvas();
|
initializeCanvas();
|
||||||
|
|
||||||
// Observe container size changes
|
// Set up ResizeObserver to handle container size changes
|
||||||
if ('ResizeObserver' in window) {
|
if ('ResizeObserver' in window) {
|
||||||
const resizeObserver = new ResizeObserver(() => {
|
const resizeObserver = new ResizeObserver(() => {
|
||||||
updateCanvasSize();
|
updateCanvasSize();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (containerEl.value) {
|
if (containerEl.value) {
|
||||||
resizeObserver.observe(containerEl.value);
|
resizeObserver.observe(containerEl.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error during component mount:', error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the canvas and set up required event handlers
|
||||||
|
*/
|
||||||
const initializeCanvas = () => {
|
const initializeCanvas = () => {
|
||||||
if (!canvasEl.value || !containerEl.value) return;
|
if (!canvasEl.value || !containerEl.value) {
|
||||||
|
logger.error('Canvas or container element not available');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const context = canvasEl.value.getContext('2d');
|
const context = canvasEl.value.getContext('2d');
|
||||||
if (!context) {
|
if (!context) {
|
||||||
console.error('Failed to get 2D context from canvas');
|
logger.error('Failed to get 2D context from canvas');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,9 +418,6 @@
|
|||||||
store.canvas.value = canvasEl.value;
|
store.canvas.value = canvasEl.value;
|
||||||
store.ctx.value = context;
|
store.ctx.value = context;
|
||||||
|
|
||||||
// Set up the checkerboard pattern
|
|
||||||
setupCheckerboardPattern();
|
|
||||||
|
|
||||||
// Set up canvas mouse events
|
// Set up canvas mouse events
|
||||||
setupCanvasEvents();
|
setupCanvasEvents();
|
||||||
|
|
||||||
@ -405,23 +431,30 @@
|
|||||||
store.renderSpritesheetPreview();
|
store.renderSpritesheetPreview();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error initializing canvas:', error);
|
logger.error('Error initializing canvas:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component lifecycle hook - cleanup
|
||||||
|
*/
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
// Remove global event listeners
|
try {
|
||||||
window.removeEventListener('keydown', handleKeyDown);
|
// Remove global event listeners
|
||||||
window.removeEventListener('keyup', handleKeyUp);
|
window.removeEventListener('keydown', handleKeyDown);
|
||||||
window.removeEventListener('resize', handleResize);
|
window.removeEventListener('keyup', handleKeyUp);
|
||||||
|
window.removeEventListener('resize', handleResize);
|
||||||
|
|
||||||
// Remove canvas event listeners
|
// Remove canvas event listeners
|
||||||
if (canvasEl.value) {
|
if (canvasEl.value) {
|
||||||
canvasEl.value.removeEventListener('mousedown', handleCanvasMouseDown);
|
canvasEl.value.removeEventListener('mousedown', handleCanvasMouseDown);
|
||||||
canvasEl.value.removeEventListener('mousemove', handleCanvasMouseMove);
|
canvasEl.value.removeEventListener('mousemove', handleCanvasMouseMove);
|
||||||
canvasEl.value.removeEventListener('mouseup', handleCanvasMouseUp);
|
canvasEl.value.removeEventListener('mouseup', handleCanvasMouseUp);
|
||||||
canvasEl.value.removeEventListener('mouseleave', handleCanvasMouseLeave);
|
canvasEl.value.removeEventListener('mouseleave', handleCanvasMouseLeave);
|
||||||
canvasEl.value.removeEventListener('contextmenu', preventContextMenu);
|
canvasEl.value.removeEventListener('contextmenu', preventContextMenu);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error during component unmount:', error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user