diff --git a/src/index.ts b/src/index.ts index 3282d6d..537adbc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,7 +2,6 @@ const config: IConfig = { name: "BulkAnimationEditor", title: "Bulk Animation Editor", - version: "1.4.0", debug: false }; @@ -16,6 +15,18 @@ const last_used = { stride_vertical: 0 }; +enum AnimationDirection { + Right, + Down, + Both +} + +const directions = [ + AnimationDirection.Right, + AnimationDirection.Down, + AnimationDirection.Both, +]; + const action_animation_create = tiled.registerAction(`${config.name}_CreateFromSelection`, animation_create); action_animation_create.text = "Create Animations From Selection"; action_animation_create.icon = "images/icon-create.png"; @@ -112,12 +123,12 @@ function animation_create() { result.confirmation_button.clicked.connect(() => { const duration = result.animation_frame_duration.value; const frame_count = result.animation_frames_input.value; - const direction = ["Right", "Down", "Both"][result.animation_direction.currentIndex]; + const direction = result.animation_direction.currentIndex as AnimationDirection; const stride: IStride = { horizontal: result.animation_stride_horizontal.value, vertical: result.animation_stride_vertical.value }; - if (!direction) { + if (direction === undefined) { tiled.alert("No direction selected. (This should not occur)"); return; } @@ -143,11 +154,11 @@ function animation_create() { }); } -export function get_tile_frames(tile: Tile, frame_count: number, duration: number, direction: string, tileset_selected_tiles: rect, tile_dimensions: ITilesetDimensions, stride: IStride = { horizontal: 0, vertical: 0 }) { +export function get_tile_frames(tile: Tile, frame_count: number, duration: number, direction: AnimationDirection, tileset_selected_tiles: rect, tile_dimensions: ITilesetDimensions, stride: IStride = { horizontal: 0, vertical: 0 }) { const columns = tile_dimensions.tileset.columns; const max_tiles = columns * tile_dimensions.tileset.rows; - if (direction === "Both") { + if (direction === AnimationDirection.Both) { const h_advance = tileset_selected_tiles.width + stride.horizontal; const v_advance = tileset_selected_tiles.height + stride.vertical; const cells_per_row = 1 + Math.floor((columns - tileset_selected_tiles.x - tileset_selected_tiles.width) / h_advance); @@ -175,12 +186,12 @@ export function get_tile_frames(tile: Tile, frame_count: number, duration: numbe return frames; } - const stride_value = direction === "Down" + const stride_value = direction === AnimationDirection.Down ? columns * (tileset_selected_tiles.height + stride.vertical) : tileset_selected_tiles.width + stride.horizontal; if (frame_count > 0) { - if (direction === "Right") { + if (direction === AnimationDirection.Right) { if (tile.id % columns + (frame_count - 1) * stride_value >= columns) return null; } else { if (tile.id + (frame_count - 1) * stride_value >= max_tiles) return null; @@ -246,7 +257,7 @@ function dialog_create(title: string, min_width?: number, min_height?: number): function animation_dialog_create(dialog: Dialog, tileset_selected_tiles: rect, tile_dimensions: ITilesetDimensions): IAnimationConfirmation { dialog.addHeading("The direction that animation frames advance in the sprite sheet", true); dialog.addNewRow(); - const animation_direction = dialog.addComboBox('Direction: ', ['Right', 'Down', 'Both']); + const animation_direction = dialog.addComboBox('Direction: ', directions.map(d => AnimationDirection[d])); dialog.addSeparator(); diff --git a/src/tests/_helpers.ts b/src/tests/_helpers.ts index ac8f7e8..5febed1 100644 --- a/src/tests/_helpers.ts +++ b/src/tests/_helpers.ts @@ -1,3 +1,9 @@ +export enum AnimationDirection { + Right, + Down, + Both +} + (globalThis as any).tiled = { activeAssetChanged: { connect: () => {} }, registerAction: () => ({} as any), diff --git a/src/tests/frames_both.test.ts b/src/tests/frames_both.test.ts index 4220980..bf7537f 100644 --- a/src/tests/frames_both.test.ts +++ b/src/tests/frames_both.test.ts @@ -1,10 +1,10 @@ import { test, expect } from "bun:test"; -import { makeTile, makeRect, makeTilesetDimensions, getIndexModule } from "./_helpers"; +import { makeTile, makeRect, makeTilesetDimensions, getIndexModule, AnimationDirection } from "./_helpers"; test("Both fills a row left-to-right then wraps to the next", async () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(12); - const frames = get_tile_frames(tile, 3, 100, "Both", makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 8)); + const frames = get_tile_frames(tile, 3, 100, AnimationDirection.Both, makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 8)); expect(frames).toHaveLength(3); expect(frames[0]).toEqual({ tileId: 12, duration: 100 }); expect(frames[1]).toEqual({ tileId: 15, duration: 100 }); diff --git a/src/tests/frames_both_wide.test.ts b/src/tests/frames_both_wide.test.ts index 7a12cf7..1629787 100644 --- a/src/tests/frames_both_wide.test.ts +++ b/src/tests/frames_both_wide.test.ts @@ -1,10 +1,10 @@ import { test, expect } from "bun:test"; -import { makeTile, makeRect, makeTilesetDimensions, getIndexModule } from "./_helpers"; +import { makeTile, makeRect, makeTilesetDimensions, getIndexModule, AnimationDirection } from "./_helpers"; test("Both wraps to next row per cells_per_row", async () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(1); - const frames = get_tile_frames(tile, 2, 100, "Both", makeRect(1, 0, 5, 2), makeTilesetDimensions(10, 8)); + const frames = get_tile_frames(tile, 2, 100, AnimationDirection.Both, makeRect(1, 0, 5, 2), makeTilesetDimensions(10, 8)); expect(frames[0].tileId).toBe(1); expect(frames[1].tileId).toBe(21); }); diff --git a/src/tests/frames_down.test.ts b/src/tests/frames_down.test.ts index 49be0e1..bba8e84 100644 --- a/src/tests/frames_down.test.ts +++ b/src/tests/frames_down.test.ts @@ -1,10 +1,10 @@ import { test, expect } from "bun:test"; -import { makeTile, makeRect, makeTilesetDimensions, getIndexModule } from "./_helpers"; +import { makeTile, makeRect, makeTilesetDimensions, getIndexModule, AnimationDirection } from "./_helpers"; test("Down frames advance by columns * selection height", async () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(12); - const frames = get_tile_frames(tile, 3, 100, "Down", makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 8)); + const frames = get_tile_frames(tile, 3, 100, AnimationDirection.Down, makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 8)); expect(frames).toHaveLength(3); expect(frames[0]).toEqual({ tileId: 12, duration: 100 }); expect(frames[1]).toEqual({ tileId: 32, duration: 100 }); diff --git a/src/tests/frames_stride.test.ts b/src/tests/frames_stride.test.ts index 7ae78a6..4214e81 100644 --- a/src/tests/frames_stride.test.ts +++ b/src/tests/frames_stride.test.ts @@ -1,10 +1,10 @@ import { test, expect } from "bun:test"; -import { makeTile, makeRect, makeTilesetDimensions, makeStride, getIndexModule } from "./_helpers"; +import { makeTile, makeRect, makeTilesetDimensions, makeStride, getIndexModule, AnimationDirection } from "./_helpers"; test("Right stride adds horizontal stride", async () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(2); - const frames = get_tile_frames(tile, 3, 100, "Right", makeRect(0, 0, 3, 2), makeTilesetDimensions(15, 8), makeStride(1)); + const frames = get_tile_frames(tile, 3, 100, AnimationDirection.Right, makeRect(0, 0, 3, 2), makeTilesetDimensions(15, 8), makeStride(1)); expect(frames).toHaveLength(3); expect(frames[0]).toEqual({ tileId: 2, duration: 100 }); expect(frames[1]).toEqual({ tileId: 6, duration: 100 }); @@ -14,7 +14,7 @@ test("Right stride adds horizontal stride", async () => { test("Down stride adds vertical stride", async () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(12); - const frames = get_tile_frames(tile, 3, 100, "Down", makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 15), makeStride(0, 1)); + const frames = get_tile_frames(tile, 3, 100, AnimationDirection.Down, makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 15), makeStride(0, 1)); expect(frames).toHaveLength(3); expect(frames[0]).toEqual({ tileId: 12, duration: 100 }); expect(frames[1]).toEqual({ tileId: 42, duration: 100 }); @@ -24,7 +24,7 @@ test("Down stride adds vertical stride", async () => { test("Both stride adds horizontal + vertical stride", async () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(12); - const frames = get_tile_frames(tile, 3, 100, "Both", makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 15), makeStride(1, 10)); + const frames = get_tile_frames(tile, 3, 100, AnimationDirection.Both, makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 15), makeStride(1, 10)); expect(frames).toHaveLength(3); expect(frames[0]).toEqual({ tileId: 12, duration: 100 }); expect(frames[1]).toEqual({ tileId: 16, duration: 100 }); @@ -34,22 +34,22 @@ test("Both stride adds horizontal + vertical stride", async () => { test("Zero stride produces same results as no stride", async () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(12); - const frames_no_stride = get_tile_frames(tile, 3, 100, "Right", makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 8)); - const frames_zero_stride = get_tile_frames(tile, 3, 100, "Right", makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 8), makeStride(0, 0)); + const frames_no_stride = get_tile_frames(tile, 3, 100, AnimationDirection.Right, makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 8)); + const frames_zero_stride = get_tile_frames(tile, 3, 100, AnimationDirection.Right, makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 8), makeStride(0, 0)); expect(frames_no_stride).toEqual(frames_zero_stride); }); test("returns null when frames reference non-existent tiles", async () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(75); - const frames = get_tile_frames(tile, 3, 100, "Right", makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 8)); + const frames = get_tile_frames(tile, 3, 100, AnimationDirection.Right, makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 8)); expect(frames).toBeNull(); }); test("negative horizontal stride reduces advance below selection width", async () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(0); - const frames = get_tile_frames(tile, 3, 100, "Right", makeRect(0, 0, 3, 2), makeTilesetDimensions(10, 8), makeStride(-1)); + const frames = get_tile_frames(tile, 3, 100, AnimationDirection.Right, makeRect(0, 0, 3, 2), makeTilesetDimensions(10, 8), makeStride(-1)); expect(frames).toHaveLength(3); expect(frames[0]).toEqual({ tileId: 0, duration: 100 }); expect(frames[1]).toEqual({ tileId: 2, duration: 100 }); @@ -59,7 +59,7 @@ test("negative horizontal stride reduces advance below selection width", async ( test("negative vertical stride reduces advance below selection height", async () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(12); - const frames = get_tile_frames(tile, 3, 100, "Down", makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 15), makeStride(0, -1)); + const frames = get_tile_frames(tile, 3, 100, AnimationDirection.Down, makeRect(2, 1, 3, 2), makeTilesetDimensions(10, 15), makeStride(0, -1)); expect(frames).toHaveLength(3); expect(frames[0]).toEqual({ tileId: 12, duration: 100 }); expect(frames[1]).toEqual({ tileId: 22, duration: 100 }); diff --git a/src/tests/integration.test.ts b/src/tests/integration.test.ts index f790cd6..636f756 100644 --- a/src/tests/integration.test.ts +++ b/src/tests/integration.test.ts @@ -1,5 +1,5 @@ import { test, expect, describe } from "bun:test"; -import { makeTile, makeRect, makeTilesetDimensions, makeStride, makeTilesetAsset, getIndexModule } from "./_helpers"; +import { makeTile, makeRect, makeTilesetDimensions, makeStride, makeTilesetAsset, getIndexModule, AnimationDirection } from "./_helpers"; // These constants are derived from test_map.json tileset configurations const TILESETS = { @@ -98,7 +98,7 @@ describe("integration: get_tile_frames with real tileset layouts", () => { const cfg = TILESETS.group1.rect2; const tile = makeTile(0); const frames = get_tile_frames( - tile, 4, 500, "Right", + tile, 4, 500, AnimationDirection.Right, makeRect(0, 0, 3, 2), makeTilesetDimensions(cfg.cols, cfg.rows, cfg.tw, cfg.th) ); @@ -114,7 +114,7 @@ describe("integration: get_tile_frames with real tileset layouts", () => { const cfg = TILESETS.group1.rect1; const tile = makeTile(0); const frames = get_tile_frames( - tile, 4, 500, "Down", + tile, 4, 500, AnimationDirection.Down, makeRect(0, 0, 3, 2), makeTilesetDimensions(cfg.cols, cfg.rows, cfg.tw, cfg.th) ); @@ -130,7 +130,7 @@ describe("integration: get_tile_frames with real tileset layouts", () => { const cfg = TILESETS.group1.rect1; const tile = makeTile(0); const frames = get_tile_frames( - tile, 4, 500, "Both", + tile, 4, 500, AnimationDirection.Both, makeRect(0, 0, 3, 2), makeTilesetDimensions(cfg.cols, cfg.rows, cfg.tw, cfg.th) ); @@ -146,7 +146,7 @@ describe("integration: get_tile_frames with real tileset layouts", () => { const cfg = TILESETS.group1.rect2; const tile = makeTile(0); const frames = get_tile_frames( - tile, 4, 500, "Both", + tile, 4, 500, AnimationDirection.Both, makeRect(0, 0, 3, 2), makeTilesetDimensions(cfg.cols, cfg.rows, cfg.tw, cfg.th) ); @@ -162,7 +162,7 @@ describe("integration: get_tile_frames with real tileset layouts", () => { const cfg = TILESETS.group1.square; const tile = makeTile(0); const frames = get_tile_frames( - tile, 4, 500, "Both", + tile, 4, 500, AnimationDirection.Both, makeRect(0, 0, 3, 2), makeTilesetDimensions(cfg.cols, cfg.rows, cfg.tw, cfg.th) ); @@ -178,7 +178,7 @@ describe("integration: get_tile_frames with real tileset layouts", () => { const cfg = TILESETS.group3.rect2; const tile = makeTile(0); const frames = get_tile_frames( - tile, 4, 500, "Right", + tile, 4, 500, AnimationDirection.Right, makeRect(0, 0, 2, 2), makeTilesetDimensions(cfg.cols, cfg.rows, cfg.tw, cfg.th) ); @@ -193,7 +193,7 @@ describe("integration: get_tile_frames with real tileset layouts", () => { const cfg = TILESETS.group3.rect2; const tile = makeTile(0); const frames = get_tile_frames( - tile, 4, 500, "Both", + tile, 4, 500, AnimationDirection.Both, makeRect(0, 0, 2, 2), makeTilesetDimensions(cfg.cols, cfg.rows, cfg.tw, cfg.th) ); @@ -211,7 +211,7 @@ describe("integration: stride with real tileset layouts", () => { const cfg = TILESETS.group1.rect2; const tile = makeTile(0); const frames = get_tile_frames( - tile, 3, 500, "Right", + tile, 3, 500, AnimationDirection.Right, makeRect(0, 0, 3, 2), makeTilesetDimensions(cfg.cols, cfg.rows, cfg.tw, cfg.th), makeStride(1) @@ -226,7 +226,7 @@ describe("integration: stride with real tileset layouts", () => { const cfg = TILESETS.group1.rect1; const tile = makeTile(0); const frames = get_tile_frames( - tile, 3, 500, "Down", + tile, 3, 500, AnimationDirection.Down, makeRect(0, 0, 3, 2), makeTilesetDimensions(cfg.cols, cfg.rows, cfg.tw, cfg.th), makeStride(0, 1) @@ -241,7 +241,7 @@ describe("integration: stride with real tileset layouts", () => { const cfg = TILESETS.group1.square; const tile = makeTile(0); const frames = get_tile_frames( - tile, 3, 500, "Both", + tile, 3, 500, AnimationDirection.Both, makeRect(0, 0, 3, 2), makeTilesetDimensions(cfg.cols, cfg.rows, cfg.tw, cfg.th), makeStride(3, 0) @@ -257,7 +257,7 @@ describe("integration: stride with real tileset layouts", () => { const cfg = TILESETS.group1.rect2; const tile = makeTile(0); const frames = get_tile_frames( - tile, 4, 500, "Right", + tile, 4, 500, AnimationDirection.Right, makeRect(0, 0, 2, 2), makeTilesetDimensions(cfg.cols, cfg.rows, cfg.tw, cfg.th), makeStride(1) @@ -274,7 +274,7 @@ describe("integration: frame_count edge cases with real tilesets", () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(0); const frames = get_tile_frames( - tile, 0, 100, "Right", + tile, 0, 100, AnimationDirection.Right, makeRect(0, 0, 3, 2), makeTilesetDimensions(6, 15, 32, 32) ); @@ -285,7 +285,7 @@ describe("integration: frame_count edge cases with real tilesets", () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(42); const frames = get_tile_frames( - tile, 1, 100, "Down", + tile, 1, 100, AnimationDirection.Down, makeRect(0, 0, 3, 2), makeTilesetDimensions(12, 9, 32, 32) ); @@ -297,7 +297,7 @@ describe("integration: frame_count edge cases with real tilesets", () => { const { get_tile_frames } = await getIndexModule(); const tile = makeTile(0); const frames = get_tile_frames( - tile, 20, 500, "Right", + tile, 20, 500, AnimationDirection.Right, makeRect(0, 0, 3, 2), makeTilesetDimensions(100, 10, 32, 32) ); @@ -318,7 +318,7 @@ describe("integration: consistency across tileset variants", () => { for (const cols of tilesetColumnWidths) { const rows = 10; const frames = get_tile_frames( - tile, 2, 100, "Right", + tile, 2, 100, AnimationDirection.Right, sel, makeTilesetDimensions(cols, rows, 32, 32) ); @@ -333,8 +333,8 @@ describe("integration: consistency across tileset variants", () => { const tile = makeTile(0); const sel = makeRect(0, 0, 3, 2); - const frames6 = get_tile_frames(tile, 3, 100, "Down", sel, makeTilesetDimensions(6, 15, 32, 32)); - const frames12 = get_tile_frames(tile, 3, 100, "Down", sel, makeTilesetDimensions(12, 9, 32, 32)); + const frames6 = get_tile_frames(tile, 3, 100, AnimationDirection.Down, sel, makeTilesetDimensions(6, 15, 32, 32)); + const frames12 = get_tile_frames(tile, 3, 100, AnimationDirection.Down, sel, makeTilesetDimensions(12, 9, 32, 32)); // 6 cols: stride = 6*2 = 12 → 0, 12, 24 // 12 cols: stride = 12*2 = 24 → 0, 24, 48 @@ -349,8 +349,8 @@ describe("integration: consistency across tileset variants", () => { const sel = makeRect(0, 0, 2, 2); const st = makeStride(1); - const frames16 = get_tile_frames(tile, 3, 100, "Right", sel, makeTilesetDimensions(8, 10, 16, 16), st); - const frames32 = get_tile_frames(tile, 3, 100, "Right", sel, makeTilesetDimensions(8, 10, 32, 32), st); + const frames16 = get_tile_frames(tile, 3, 100, AnimationDirection.Right, sel, makeTilesetDimensions(8, 10, 16, 16), st); + const frames32 = get_tile_frames(tile, 3, 100, AnimationDirection.Right, sel, makeTilesetDimensions(8, 10, 32, 32), st); // stride = 2 + 1 = 3, independent of tile width/height expect(frames16[1].tileId).toBe(3); diff --git a/types.d.ts b/types.d.ts index e079ec9..22976c1 100644 --- a/types.d.ts +++ b/types.d.ts @@ -15,7 +15,6 @@ declare interface IResult { declare interface IConfig { name: string title: string - version: string debug?: boolean }