## [1.7.0] - 2025-11-22
- Add layer support - Add background color picker - Improved UI
This commit is contained in:
@@ -6,14 +6,17 @@ import type { Layer, Sprite } from '@/types/sprites';
|
||||
import { getMaxDimensionsAcrossLayers } from './useLayers';
|
||||
import { calculateNegativeSpacing } from './useNegativeSpacing';
|
||||
|
||||
export const useExportLayers = (layersRef: Ref<Layer[]>, columns: Ref<number>, negativeSpacingEnabled: Ref<boolean>) => {
|
||||
export const useExportLayers = (layersRef: Ref<Layer[]>, columns: Ref<number>, negativeSpacingEnabled: Ref<boolean>, activeLayerId?: Ref<string>, backgroundColor?: Ref<string>) => {
|
||||
const getVisibleLayers = () => layersRef.value.filter(l => l.visible);
|
||||
const getAllVisibleSprites = () => getVisibleLayers().flatMap(l => l.sprites);
|
||||
|
||||
const drawCompositeCell = (ctx: CanvasRenderingContext2D, cellIndex: number, cellWidth: number, cellHeight: number, negativeSpacing: number) => {
|
||||
ctx.clearRect(0, 0, cellWidth, cellHeight);
|
||||
ctx.fillStyle = '#f9fafb';
|
||||
ctx.fillRect(0, 0, cellWidth, cellHeight);
|
||||
// Apply background color if not transparent
|
||||
if (backgroundColor?.value && backgroundColor.value !== 'transparent') {
|
||||
ctx.fillStyle = backgroundColor.value;
|
||||
ctx.fillRect(0, 0, cellWidth, cellHeight);
|
||||
}
|
||||
const vLayers = getVisibleLayers();
|
||||
vLayers.forEach(layer => {
|
||||
const sprite = layer.sprites[cellIndex];
|
||||
@@ -130,16 +133,32 @@ export const useExportLayers = (layersRef: Ref<Layer[]>, columns: Ref<number>, n
|
||||
const sprites: Sprite[] = await Promise.all(layerData.sprites.map((s: any) => loadSprite(s)));
|
||||
newLayers.push({ id: layerData.id || crypto.randomUUID(), name: layerData.name || 'Layer', visible: layerData.visible !== false, locked: !!layerData.locked, sprites });
|
||||
}
|
||||
// Ensure at least one layer with sprites is visible
|
||||
if (newLayers.length > 0 && !newLayers.some(l => l.visible && l.sprites.length > 0)) {
|
||||
const firstLayerWithSprites = newLayers.find(l => l.sprites.length > 0);
|
||||
if (firstLayerWithSprites) {
|
||||
firstLayerWithSprites.visible = true;
|
||||
}
|
||||
}
|
||||
layersRef.value = newLayers;
|
||||
// Set active layer to the first layer with sprites
|
||||
if (activeLayerId && newLayers.length > 0) {
|
||||
const firstWithSprites = newLayers.find(l => l.sprites.length > 0);
|
||||
activeLayerId.value = firstWithSprites ? firstWithSprites.id : newLayers[0].id;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(data.sprites)) {
|
||||
const sprites: Sprite[] = await Promise.all(data.sprites.map((s: any) => loadSprite(s)));
|
||||
const baseLayerId = crypto.randomUUID();
|
||||
layersRef.value = [
|
||||
{ id: crypto.randomUUID(), name: 'Base', visible: true, locked: false, sprites },
|
||||
{ id: crypto.randomUUID(), name: 'Clothes', visible: true, locked: false, sprites: [] },
|
||||
{ id: baseLayerId, name: 'Base', visible: true, locked: false, sprites },
|
||||
{ id: crypto.randomUUID(), name: 'Other', visible: true, locked: false, sprites: [] },
|
||||
];
|
||||
if (activeLayerId) {
|
||||
activeLayerId.value = baseLayerId;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -222,9 +241,7 @@ export const useExportLayers = (layersRef: Ref<Layer[]>, columns: Ref<number>, n
|
||||
name: layer.name,
|
||||
visible: layer.visible,
|
||||
locked: layer.locked,
|
||||
sprites: await Promise.all(
|
||||
layer.sprites.map(async s => ({ id: s.id, width: s.width, height: s.height, x: s.x, y: s.y, name: s.file.name }))
|
||||
),
|
||||
sprites: await Promise.all(layer.sprites.map(async s => ({ id: s.id, width: s.width, height: s.height, x: s.x, y: s.y, name: s.file.name }))),
|
||||
}))
|
||||
);
|
||||
const meta = { version: 2, columns: columns.value, negativeSpacingEnabled: negativeSpacingEnabled.value, layers: layersPayload };
|
||||
|
||||
Reference in New Issue
Block a user