145 lines
5.1 KiB
TypeScript
145 lines
5.1 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import {
|
|
ADDITIVE_OBJECT_TOKENS,
|
|
type ObjectDrawable,
|
|
} from '../src/scene/act-scene.ts'
|
|
import {
|
|
buildObjectDrawables,
|
|
executeDepthDrawDispatch,
|
|
MockRenderer,
|
|
type PackObjectInput,
|
|
type SimulatedWall,
|
|
} from '../scripts/verify-scene-object-dispatch.ts'
|
|
|
|
describe('Scene Object Rendering Dispatch (Milestone 1 / R1)', () => {
|
|
it('correctly maps all 1.13c additive tokens to blendMode: "additive"', () => {
|
|
const tokens = ['11', '12', 'R1', 'R2', 'R3', 'R4', 'R5', '1R', '2R', '3R', '4R', 'HA']
|
|
for (const token of tokens) {
|
|
expect(ADDITIVE_OBJECT_TOKENS.has(token)).toBe(true)
|
|
|
|
const drawables = buildObjectDrawables([
|
|
{
|
|
x: 100,
|
|
y: 200,
|
|
token,
|
|
frame: { x: 0, y: 0, width: 32, height: 32, offsetX: 0, offsetY: 0, page: 0 },
|
|
},
|
|
])
|
|
expect(drawables).toHaveLength(1)
|
|
expect(drawables[0]!.blendMode).toBe('additive')
|
|
}
|
|
})
|
|
|
|
it('correctly identifies trans=7 and trans=1 objects as additive', () => {
|
|
const drawables = buildObjectDrawables([
|
|
{
|
|
x: 10,
|
|
y: 20,
|
|
token: 'UNKNOWN',
|
|
trans: 7,
|
|
frame: { x: 0, y: 0, width: 32, height: 32, offsetX: 0, offsetY: 0, page: 0 },
|
|
},
|
|
{
|
|
x: 30,
|
|
y: 40,
|
|
token: 'OTHER',
|
|
trans: 1,
|
|
frame: { x: 0, y: 0, width: 32, height: 32, offsetX: 0, offsetY: 0, page: 0 },
|
|
},
|
|
])
|
|
expect(drawables).toHaveLength(2)
|
|
expect(drawables[0]!.blendMode).toBe('additive')
|
|
expect(drawables[1]!.blendMode).toBe('additive')
|
|
})
|
|
|
|
it('preserves blendMode: "normal" for regular objects and torches', () => {
|
|
const drawables = buildObjectDrawables([
|
|
{
|
|
x: 10,
|
|
y: 20,
|
|
token: 'CHEST',
|
|
trans: 0,
|
|
frame: { x: 0, y: 0, width: 32, height: 32, offsetX: 0, offsetY: 0, page: 0 },
|
|
},
|
|
{
|
|
x: 30,
|
|
y: 40,
|
|
token: 'TO',
|
|
trans: 0,
|
|
frame: { x: 0, y: 0, width: 32, height: 32, offsetX: 0, offsetY: 0, page: 0 },
|
|
},
|
|
])
|
|
expect(drawables).toHaveLength(2)
|
|
expect(drawables[0]!.blendMode).toBe('normal')
|
|
expect(drawables[1]!.blendMode).toBe('normal')
|
|
})
|
|
|
|
it('dispatches additive objects with blendMode: "additive" and regular objects with "normal"', () => {
|
|
const rawObjects: PackObjectInput[] = [
|
|
{ id: 1, token: '11', depth: 2, frame: { x: 0, y: 0, width: 10, height: 10, offsetX: 0, offsetY: 0, page: 0 }, x: 10, y: 0 },
|
|
{ id: 2, token: 'BOX', depth: 6, frame: { x: 0, y: 0, width: 10, height: 10, offsetX: 0, offsetY: 0, page: 0 }, x: 30, y: 0 },
|
|
]
|
|
const objs = buildObjectDrawables(rawObjects)
|
|
|
|
const walls: SimulatedWall[] = [
|
|
{ frame: { x: 0, y: 0, width: 32, height: 32, _depth: 4 } as any, x: 0, y: 0, cellX: 2, cellY: 2, page: 0 },
|
|
]
|
|
|
|
const renderer = new MockRenderer()
|
|
executeDepthDrawDispatch(renderer, {
|
|
walls,
|
|
objs,
|
|
maxDepthSteps: [Infinity],
|
|
})
|
|
|
|
expect(renderer.draws).toHaveLength(3)
|
|
|
|
// Draw 0: Object 1 (Token 11, depth 2) -> additive
|
|
expect(renderer.draws[0]!.target).toBe('object')
|
|
expect(renderer.draws[0]!.depth).toBe(2)
|
|
expect(renderer.draws[0]!.blendMode).toBe('additive')
|
|
|
|
// Draw 1: Wall (depth 4) -> blendMode undefined (options has { atlas })
|
|
expect(renderer.draws[1]!.target).toBe('wall')
|
|
expect(renderer.draws[1]!.depth).toBe(4)
|
|
expect(renderer.draws[1]!.blendMode).toBeUndefined()
|
|
|
|
// Draw 2: Object 2 (BOX, depth 6) -> normal
|
|
expect(renderer.draws[2]!.target).toBe('object')
|
|
expect(renderer.draws[2]!.depth).toBe(6)
|
|
expect(renderer.draws[2]!.blendMode).toBe('normal')
|
|
})
|
|
|
|
it('strictly preserves depth ordering across mixed walls, objects, and incremental depth steps', () => {
|
|
const rawObjects: PackObjectInput[] = [
|
|
{ id: 1, depth: 3, token: '11', frame: { x: 0, y: 0, width: 10, height: 10, offsetX: 0, offsetY: 0, page: 0 }, x: 15, y: 0 },
|
|
{ id: 2, depth: 8, token: '12', frame: { x: 0, y: 0, width: 10, height: 10, offsetX: 0, offsetY: 0, page: 0 }, x: 40, y: 0 },
|
|
{ id: 3, depth: 15, token: 'CHEST', frame: { x: 0, y: 0, width: 10, height: 10, offsetX: 0, offsetY: 0, page: 0 }, x: 75, y: 0 },
|
|
]
|
|
const objs = buildObjectDrawables(rawObjects)
|
|
|
|
const walls: SimulatedWall[] = [
|
|
{ frame: { x: 0, y: 0, width: 32, height: 32, _depth: 1 } as any, x: 0, y: 0, cellX: 0, cellY: 1, page: 0 },
|
|
{ frame: { x: 0, y: 0, width: 32, height: 32, _depth: 5 } as any, x: 0, y: 0, cellX: 2, cellY: 3, page: 0 },
|
|
{ frame: { x: 0, y: 0, width: 32, height: 32, _depth: 10 } as any, x: 0, y: 0, cellX: 5, cellY: 5, page: 0 },
|
|
]
|
|
|
|
const renderer = new MockRenderer()
|
|
executeDepthDrawDispatch(renderer, {
|
|
walls,
|
|
objs,
|
|
maxDepthSteps: [4, 9, Infinity],
|
|
})
|
|
|
|
expect(renderer.draws).toHaveLength(6)
|
|
|
|
// Verify non-decreasing order
|
|
for (let i = 1; i < renderer.draws.length; i++) {
|
|
expect(renderer.draws[i]!.depth).toBeGreaterThanOrEqual(renderer.draws[i - 1]!.depth)
|
|
}
|
|
|
|
const depths = renderer.draws.map(d => d.depth)
|
|
expect(depths).toEqual([1, 3, 5, 8, 10, 15])
|
|
})
|
|
})
|