card harness dynamic changes
This commit is contained in:
@@ -5,6 +5,7 @@ import { installDOM, TestCanvas, geometryHash, wrapperCases } from './test-suppo
|
||||
|
||||
const { createFoilWrapper } = await import('../src/foilWrapper.ts')
|
||||
const { PackOpening } = await import('../src/packOpening.ts')
|
||||
const { packStyles, defaultPackStyle, createPackTexture } = await import('../src/packDesigns.ts')
|
||||
|
||||
// Captured from the pre-optimization implementation, including normals, UVs and bounds.
|
||||
const originalHashes = [
|
||||
@@ -56,6 +57,49 @@ test('only changed surfaces recompute normals, bounds and upload buffers', (t) =
|
||||
assert.deepEqual(boundsSpies.map((spy) => spy.mock.callCount()), [2, 1, 1])
|
||||
})
|
||||
|
||||
test('three cached pack designs change all printed surfaces without changing geometry or materials', () => {
|
||||
installDOM()
|
||||
const wrapper = createFoilWrapper()
|
||||
assert.equal(packStyles.length, 3)
|
||||
assert.equal(wrapper.style, defaultPackStyle)
|
||||
assert.equal(wrapper.textures.length, 6)
|
||||
const materials = wrapper.root.children.map(mesh => mesh.material)
|
||||
const maps = new Set()
|
||||
for (const style of packStyles) {
|
||||
wrapper.setStyle(style)
|
||||
assert.equal(wrapper.style, style)
|
||||
const [front, back, strip] = wrapper.root.children.map(mesh => mesh.material.map)
|
||||
assert.equal(front, strip, 'ribbon must use the same printed sheet as the front')
|
||||
assert.notEqual(front, back)
|
||||
maps.add(front)
|
||||
maps.add(back)
|
||||
for (const texture of [front, back]) {
|
||||
assert.equal(texture.image.width, 1024)
|
||||
assert.equal(texture.image.height, 1400)
|
||||
assert.equal(texture.colorSpace, THREE.SRGBColorSpace)
|
||||
}
|
||||
assert.deepEqual(wrapper.root.children.map(mesh => mesh.material), materials)
|
||||
wrapperCases.forEach(([tear, detach, mouth, touch, exit], index) => {
|
||||
wrapper.deform(tear, detach, mouth, new THREE.Vector3(...touch), exit)
|
||||
assert.equal(geometryHash(wrapper), originalHashes[index], `${style}, pose ${index}`)
|
||||
})
|
||||
wrapper.setStyle(style)
|
||||
assert.equal(wrapper.root.children[0].material.map, front, 'selecting the same style reuses its texture')
|
||||
}
|
||||
assert.equal(maps.size, 6)
|
||||
const before = wrapper.root.children.map(mesh => mesh.material.map)
|
||||
assert.throws(() => wrapper.setStyle('unknown'), /Unknown pack style/)
|
||||
assert.deepEqual(wrapper.root.children.map(mesh => mesh.material.map), before)
|
||||
wrapper.dispose()
|
||||
})
|
||||
|
||||
test('pack textures reject invalid styles and unavailable drawing contexts', (t) => {
|
||||
installDOM()
|
||||
assert.throws(() => createPackTexture('unknown'))
|
||||
t.mock.method(TestCanvas.prototype, 'getContext', () => null)
|
||||
assert.throws(() => createPackTexture(defaultPackStyle))
|
||||
})
|
||||
|
||||
function setupPack(t, reducedMotion = false) {
|
||||
installDOM(reducedMotion)
|
||||
let now = 1000
|
||||
@@ -158,6 +202,39 @@ test('interruption and mode changes preserve progress without deforming in point
|
||||
assert.equal(pack.state, 'stackReady')
|
||||
})
|
||||
|
||||
test('style switching preserves partial tears, card order, restart selection and retained mode state', (t) => {
|
||||
const { pack, canvas, step } = setupPack(t)
|
||||
let reveals = 0
|
||||
canvas.addEventListener('packreveal', () => { reveals++ })
|
||||
pack.primary()
|
||||
step(600)
|
||||
pack.pointerDown(pointer(1, 0, 0))
|
||||
pack.pointerUp(pointer(1, 0, 0))
|
||||
const progress = pack.tearProgress
|
||||
const geometry = geometryHash(pack.wrapper)
|
||||
const cardSpecs = pack.cards.map(card => card.material.uuid)
|
||||
for (const style of packStyles) {
|
||||
pack.setStyle(style)
|
||||
assert.equal(pack.style, style)
|
||||
assert.equal(pack.tearProgress, progress)
|
||||
assert.equal(pack.paused, true)
|
||||
assert.equal(pack.state, 'opening')
|
||||
assert.equal(geometryHash(pack.wrapper), geometry)
|
||||
assert.deepEqual(pack.cards.map(card => card.material.uuid), cardSpecs)
|
||||
assert.equal(reveals, 0)
|
||||
}
|
||||
pack.setStyle(packStyles[0])
|
||||
pack.setActive(false)
|
||||
pack.setActive(true)
|
||||
assert.equal(pack.style, packStyles[0])
|
||||
assert.equal(pack.tearProgress, progress)
|
||||
pack.restart()
|
||||
assert.equal(pack.style, packStyles[0])
|
||||
assert.equal(pack.state, 'sealed')
|
||||
assert.equal(pack.tearProgress, 0)
|
||||
pack.dispose()
|
||||
})
|
||||
|
||||
test('a second finger cancels seam dragging for pinch without losing the partial tear', (t) => {
|
||||
const { pack, canvas, step } = setupPack(t)
|
||||
const seam = pack.seamScreenBounds()
|
||||
@@ -267,7 +344,7 @@ test('GPU preparation uploads unique textures and compiles hidden fronts and bot
|
||||
finishCompile()
|
||||
await preparation
|
||||
assert.equal(uploaded.length, new Set(uploaded).size)
|
||||
assert.equal(uploaded.length, 9, '4 artwork/mask textures, normal, environment, back and 2 wrapper maps')
|
||||
assert.equal(uploaded.length, 13, '4 artwork/mask textures, normal, environment, back and 6 wrapper maps')
|
||||
for (const { artwork, mask } of Object.values(pack.options.textures)) {
|
||||
assert.ok(uploaded.includes(artwork))
|
||||
assert.ok(uploaded.includes(mask))
|
||||
@@ -275,6 +352,7 @@ test('GPU preparation uploads unique textures and compiles hidden fronts and bot
|
||||
assert.ok(uploaded.includes(backTexture))
|
||||
assert.ok(uploaded.includes(pack.options.normalMap))
|
||||
assert.ok(uploaded.includes(scene.environment))
|
||||
for (const texture of pack.wrapper.textures) assert.ok(uploaded.includes(texture), 'inactive pack styles must also be GPU-ready')
|
||||
assert.deepEqual(compiledEdges, [[0.02, 0.02, 0.02], [0, 0.02, 0.18]])
|
||||
assert.deepEqual(pack.cards.map((card) => card.edge.clearcoat), [0.02, 0.02, 0.02])
|
||||
assert.equal(geometryHash(pack.wrapper), before)
|
||||
@@ -333,8 +411,7 @@ test('pack cleanup disposes owned resources without disposing shared or caller-o
|
||||
materials.add(object.material)
|
||||
})
|
||||
materials.delete(pack.options.backMaterial)
|
||||
const resources = [...geometries, ...materials,
|
||||
...new Set(pack.wrapper.root.children.map((mesh) => mesh.material.map))]
|
||||
const resources = [...geometries, ...materials, ...pack.wrapper.textures]
|
||||
const ownedSpies = resources.map((resource) => t.mock.method(resource, 'dispose'))
|
||||
pack.dispose()
|
||||
assert.equal(pack.root.parent, null)
|
||||
|
||||
Reference in New Issue
Block a user