distark-render 1.1.14 → 1.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/distark-check.js +16 -16
- package/dist/modules/adapters/p5Renderer.d.ts.map +1 -1
- package/dist/modules/adapters/p5Renderer.js +54 -12
- package/dist/modules/adapters/p5Renderer.js.map +1 -1
- package/dist/modules/adapters/skiaRenderer.d.ts.map +1 -1
- package/dist/modules/adapters/skiaRenderer.js +2 -1
- package/dist/modules/adapters/skiaRenderer.js.map +1 -1
- package/dist/modules/eyeSystem.d.ts.map +1 -1
- package/dist/modules/eyeSystem.js +104 -69
- package/dist/modules/eyeSystem.js.map +1 -1
- package/dist/modules/imageLoad.d.ts +50 -0
- package/dist/modules/imageLoad.d.ts.map +1 -1
- package/dist/modules/imageLoad.js +262 -18
- package/dist/modules/imageLoad.js.map +1 -1
- package/dist/tests/test-auto-eye-movement-e2e.d.ts +24 -0
- package/dist/tests/test-auto-eye-movement-e2e.d.ts.map +1 -0
- package/dist/tests/test-auto-eye-movement-e2e.js +514 -0
- package/dist/tests/test-auto-eye-movement-e2e.js.map +1 -0
- package/dist/tests/test-eye-system-reset.d.ts +15 -0
- package/dist/tests/test-eye-system-reset.d.ts.map +1 -0
- package/dist/tests/test-eye-system-reset.js +148 -0
- package/dist/tests/test-eye-system-reset.js.map +1 -0
- package/dist/tests/test-svg-rerasterization.js +194 -4
- package/dist/tests/test-svg-rerasterization.js.map +1 -1
- package/dist/tests/test-teen-tank-rig.d.ts +12 -0
- package/dist/tests/test-teen-tank-rig.d.ts.map +1 -0
- package/dist/tests/test-teen-tank-rig.js +122 -0
- package/dist/tests/test-teen-tank-rig.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EyeSystem resetTiming guard tests
|
|
3
|
+
*
|
|
4
|
+
* Guards against the regression where update() called resetTiming() on every
|
|
5
|
+
* frame while currentTime < 0.1, causing randomEyeMovement() to fire at ~50%
|
|
6
|
+
* of frames (every ~16 ms) instead of the intended ~750 ms interval.
|
|
7
|
+
*
|
|
8
|
+
* Specifically covers:
|
|
9
|
+
* - First call initialises timing correctly (resetTiming fires once)
|
|
10
|
+
* - Subsequent early frames do NOT re-call resetTiming (no burst movement)
|
|
11
|
+
* - A genuine timeline loop (time jumping from > 0.1 back to ~0) DOES reset
|
|
12
|
+
* - detectReset (time going backward during playback) still resets correctly
|
|
13
|
+
*/
|
|
14
|
+
import { createEyeSystem } from '../modules/eyeSystem.js';
|
|
15
|
+
import { assert, printSummary } from './helpers.js';
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Helpers
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
function makeEyeData() {
|
|
20
|
+
return {
|
|
21
|
+
leftIrisXCoor: 10,
|
|
22
|
+
leftIrisYCoor: -50,
|
|
23
|
+
rightIrisXCoor: -10,
|
|
24
|
+
rightIrisYCoor: -50,
|
|
25
|
+
leftIrisWidth: 20,
|
|
26
|
+
leftIrisHeight: 20,
|
|
27
|
+
rightIrisWidth: 20,
|
|
28
|
+
rightIrisHeight: 20,
|
|
29
|
+
leftIrisWidthRatio: 1,
|
|
30
|
+
leftIrisHeightRatio: 1,
|
|
31
|
+
rightIrisWidthRatio: 1,
|
|
32
|
+
rightIrisHeightRatio: 1,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// Control Math.random so that eye movement ALWAYS fires (< 0.5) and
|
|
36
|
+
// look-at-speaker always fires (< 0.7) — makes test deterministic.
|
|
37
|
+
const originalRandom = Math.random;
|
|
38
|
+
function alwaysMove() { Math.random = () => 0.1; } // always fires movement
|
|
39
|
+
function neverMove() { Math.random = () => 0.9; } // never fires movement
|
|
40
|
+
function restoreRandom() { Math.random = originalRandom; }
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// 1. Startup: resetTiming fires exactly once at t=0 (not on t=0.033, 0.066)
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
console.log('\n--- Test: resetTiming fires once on startup ---');
|
|
45
|
+
{
|
|
46
|
+
alwaysMove();
|
|
47
|
+
const sys = createEyeSystem('char', makeEyeData());
|
|
48
|
+
// Frame 1 (t=0): first-ever call → resetTiming fires, then movement fires
|
|
49
|
+
sys.update(0.0, true);
|
|
50
|
+
const pos1 = sys.getIrisPositions();
|
|
51
|
+
// Frame 2 (t=0.033): still in startup window but eyeLastUpdatedTime was set to 0.0
|
|
52
|
+
// → no reset, no movement (0.033 < 0.75 elapsed)
|
|
53
|
+
sys.update(0.033, true);
|
|
54
|
+
const pos2 = sys.getIrisPositions();
|
|
55
|
+
// Frame 3 (t=0.066): same — no reset, no movement
|
|
56
|
+
sys.update(0.066, true);
|
|
57
|
+
const pos3 = sys.getIrisPositions();
|
|
58
|
+
assert(pos1.left.x === pos2.left.x && pos1.left.y === pos2.left.y, 'Frame 2 iris position unchanged from frame 1 (no spurious reset on t=0.033)');
|
|
59
|
+
assert(pos2.left.x === pos3.left.x && pos2.left.y === pos3.left.y, 'Frame 3 iris position unchanged from frame 2 (no spurious reset on t=0.066)');
|
|
60
|
+
restoreRandom();
|
|
61
|
+
}
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// 2. After the startup window, movement fires on the normal 0.75 s cadence
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
console.log('\n--- Test: movement fires at correct 0.75 s interval after startup ---');
|
|
66
|
+
{
|
|
67
|
+
// Queue of Math.random() return values, consumed in call order:
|
|
68
|
+
// [0] constructor: eyeLidUpdateInterval = 3 + 0.5*2 = 4.0
|
|
69
|
+
// [1] constructor: nextBlinkOffset = 0.5*0.5 = 0.25
|
|
70
|
+
// [2] resetTiming: nextBlinkOffset = 0.5*0.5 = 0.25
|
|
71
|
+
// [3] update(t=0) movement check: 0.3 < 0.5 → fires
|
|
72
|
+
// [4] update(t=0) direction: floor(0.2*9)=1 → 'right' (iris offset: +5, 0)
|
|
73
|
+
// t=0.5 guard returns early; no Math.random calls
|
|
74
|
+
// [5] update(t=0.76) movement check: 0.3 < 0.5 → fires
|
|
75
|
+
// [6] update(t=0.76) direction: floor(0.7*9)=6 → 'up-right' (iris offset: +3.2, -1.6)
|
|
76
|
+
const _q = [0.5, 0.5, 0.5, 0.3, 0.2, 0.3, 0.7, 0.5, 0.5];
|
|
77
|
+
let _qi = 0;
|
|
78
|
+
Math.random = () => _q[Math.min(_qi++, _q.length - 1)];
|
|
79
|
+
const sys = createEyeSystem('char', makeEyeData());
|
|
80
|
+
sys.update(0.0, true); // reset fires, then movement picks 'right'
|
|
81
|
+
const posA = sys.getIrisPositions(); // left.x = base(10) + 5 = 15
|
|
82
|
+
sys.update(0.5, true); // 0.5 s since last movement — guard fires, no move
|
|
83
|
+
const posB = sys.getIrisPositions();
|
|
84
|
+
assert(posA.left.x === posB.left.x && posA.left.y === posB.left.y, 'No movement at t=0.5 (only 0.5 s since last movement, < 0.75 s interval)');
|
|
85
|
+
sys.update(0.76, true); // 0.76 s elapsed — fires, picks 'up-right' (different offset)
|
|
86
|
+
const posC = sys.getIrisPositions(); // left.x = base(10) + 3.2 = 13.2
|
|
87
|
+
assert(posC.left.x !== posA.left.x || posC.left.y !== posA.left.y, 'Movement fires at t=0.76 s (>= 0.75 s interval, direction changed → iris moved)');
|
|
88
|
+
restoreRandom();
|
|
89
|
+
}
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// 3. Timeline loop: time jumps from a late value back to ~0 → reset fires
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
console.log('\n--- Test: timeline loop triggers resetTiming ---');
|
|
94
|
+
{
|
|
95
|
+
alwaysMove();
|
|
96
|
+
const sys = createEyeSystem('char', makeEyeData());
|
|
97
|
+
// Simulate 2 seconds of playback so eyeLastUpdatedTime is well past 0.1
|
|
98
|
+
sys.update(0.0, true);
|
|
99
|
+
sys.update(0.76, true);
|
|
100
|
+
sys.update(1.52, true);
|
|
101
|
+
sys.update(2.28, true);
|
|
102
|
+
sys.getIrisPositions(); // consume late position (used to advance internal state)
|
|
103
|
+
// Loop back to t=0 — should trigger resetTiming via isEarlyJumpBack
|
|
104
|
+
sys.update(0.0, true);
|
|
105
|
+
const posLoop = sys.getIrisPositions();
|
|
106
|
+
// After reset, movement should have fired (eyeLastUpdatedTime set to -0.75 → timeSinceUpdate = 0.75)
|
|
107
|
+
// The new iris position may or may not match posLate — just check it exists
|
|
108
|
+
assert(typeof posLoop.left.x === 'number' && typeof posLoop.right.x === 'number', 'After timeline loop reset, getIrisPositions() returns valid positions');
|
|
109
|
+
restoreRandom();
|
|
110
|
+
}
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// 4. Backward scrub during playback (detectReset path) triggers resetTiming
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
console.log('\n--- Test: backward scrub (detectReset) triggers resetTiming ---');
|
|
115
|
+
{
|
|
116
|
+
alwaysMove();
|
|
117
|
+
const sys = createEyeSystem('char', makeEyeData());
|
|
118
|
+
sys.update(0.0, true);
|
|
119
|
+
sys.update(2.0, true); // normal playback at 2 s (eyeLastUpdatedTime ≈ 2.0)
|
|
120
|
+
// Scrub backward: t=1.5 — detectReset should fire, resetTiming called
|
|
121
|
+
sys.update(1.5, true);
|
|
122
|
+
const posAfter = sys.getIrisPositions();
|
|
123
|
+
// Just verify the system is still responsive (positions are valid numbers)
|
|
124
|
+
assert(Number.isFinite(posAfter.left.x) && Number.isFinite(posAfter.right.x), 'After backward scrub, getIrisPositions() returns finite positions');
|
|
125
|
+
restoreRandom();
|
|
126
|
+
}
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
// 5. isPlaying=false: iris position unchanged even across the startup window
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
console.log('\n--- Test: isPlaying=false keeps iris frozen across startup frames ---');
|
|
131
|
+
{
|
|
132
|
+
neverMove(); // extra safety — but shouldn't matter since !isPlaying returns early
|
|
133
|
+
const sys = createEyeSystem('char', makeEyeData());
|
|
134
|
+
const initial = sys.getIrisPositions();
|
|
135
|
+
sys.update(0.0, false);
|
|
136
|
+
sys.update(0.033, false);
|
|
137
|
+
sys.update(0.066, false);
|
|
138
|
+
sys.update(0.750, false); // even past the movement interval — still frozen
|
|
139
|
+
const after = sys.getIrisPositions();
|
|
140
|
+
assert(after.left.x === initial.left.x &&
|
|
141
|
+
after.left.y === initial.left.y &&
|
|
142
|
+
after.right.x === initial.right.x &&
|
|
143
|
+
after.right.y === initial.right.y, 'Iris stays frozen across early frames and past 0.75 s when isPlaying=false');
|
|
144
|
+
restoreRandom();
|
|
145
|
+
}
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
printSummary();
|
|
148
|
+
//# sourceMappingURL=test-eye-system-reset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-eye-system-reset.js","sourceRoot":"","sources":["../../tests/test-eye-system-reset.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,10 +30,12 @@ class MockImage {
|
|
|
30
30
|
}, 0);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
function
|
|
34
|
-
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10" fill="black" /></svg>`;
|
|
33
|
+
function svgDataUrl(svg) {
|
|
35
34
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
|
36
35
|
}
|
|
36
|
+
function makeSvgDataUrl() {
|
|
37
|
+
return svgDataUrl(`<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><rect x="0" y="0" width="24" height="24" fill="black" /></svg>`);
|
|
38
|
+
}
|
|
37
39
|
function makeRig(svgPath, torsoWidth, torsoHeight) {
|
|
38
40
|
return {
|
|
39
41
|
imagePaths: {
|
|
@@ -71,7 +73,8 @@ async function main() {
|
|
|
71
73
|
const initialAsset = loadedImages[svgPath];
|
|
72
74
|
assert(!!initialAsset?.__distarkSvgSource, 'Initial SVG asset keeps original SVG source');
|
|
73
75
|
assert(initialAsset?.width === 24 && initialAsset?.height === 24, 'Initial SVG raster matches initial rendered size');
|
|
74
|
-
|
|
76
|
+
// Use 50×50 — a 2× jump from the 24px initial raster, well above the 5% hysteresis band.
|
|
77
|
+
const largeRig = makeRig(svgPath, 50, 50);
|
|
75
78
|
const firstLargeRender = renderer.computeCharacterRigData(largeRig, {
|
|
76
79
|
canvasWidth: 400,
|
|
77
80
|
canvasHeight: 400,
|
|
@@ -81,13 +84,200 @@ async function main() {
|
|
|
81
84
|
await loader.waitForPendingImageUpgrades();
|
|
82
85
|
const upgradedAsset = loadedImages[svgPath];
|
|
83
86
|
assert(upgradedAsset !== initialAsset, 'Upscaling swaps in a regenerated SVG raster asset');
|
|
84
|
-
assert(upgradedAsset?.width >=
|
|
87
|
+
assert(upgradedAsset?.width >= 50 && upgradedAsset?.height >= 50, 'Any upscale immediately regenerates a larger SVG raster');
|
|
85
88
|
const secondLargeRender = renderer.computeCharacterRigData(largeRig, {
|
|
86
89
|
canvasWidth: 400,
|
|
87
90
|
canvasHeight: 400,
|
|
88
91
|
loadedImages,
|
|
89
92
|
});
|
|
90
93
|
assert(secondLargeRender.objects[0]?.imageData === upgradedAsset, 'Subsequent renders use the upgraded SVG raster');
|
|
94
|
+
const mmSvgPath = svgDataUrl(`<svg xmlns="http://www.w3.org/2000/svg" width="25.4mm" height="1in" viewBox="0 0 25.4 25.4"><rect x="0" y="0" width="25.4" height="25.4" fill="black" /></svg>`);
|
|
95
|
+
const mmLoadedImages = await loader.loadAllRigImages(makeRig(mmSvgPath, 24, 24), false);
|
|
96
|
+
const mmAsset = mmLoadedImages[mmSvgPath];
|
|
97
|
+
assert(mmAsset?.width === 96 && mmAsset?.height === 96, 'SVG physical units rasterize to CSS pixels');
|
|
98
|
+
const loosePartSvgPath = svgDataUrl(`<svg xmlns="http://www.w3.org/2000/svg" width="50.8mm" height="46.566666mm" viewBox="0 0 50.8 46.566665"><g transform="translate(-98.248611,-138.2007)"><ellipse cx="104.81959" cy="148.46378" rx="5.8557706" ry="9.6129332" fill="black"/><image width="13.052777" height="20.461111" x="98.248611" y="138.2007" style="display:none"/><ellipse cx="106.75509" cy="144.67407" rx="1.6606208" ry="2.1973581" fill="white"/></g></svg>`);
|
|
99
|
+
const partLoadedImages = await loader.loadAllRigImages(makeRig(loosePartSvgPath, 24, 24), false);
|
|
100
|
+
const partInitial = partLoadedImages[loosePartSvgPath];
|
|
101
|
+
assert(!!partInitial?.__distarkSvgSource, 'SVG part retains original raw source after initial load');
|
|
102
|
+
assert(!(partInitial?.__distarkSvgSource || '').includes('<g transform="matrix('), 'Raw source stored in cache has no injected fit-matrix transform');
|
|
103
|
+
renderer.computeCharacterRigData(makeRig(loosePartSvgPath, 24, 24), {
|
|
104
|
+
canvasWidth: 400,
|
|
105
|
+
canvasHeight: 400,
|
|
106
|
+
loadedImages: partLoadedImages,
|
|
107
|
+
});
|
|
108
|
+
await loader.waitForPendingImageUpgrades();
|
|
109
|
+
const partAsset = partLoadedImages[loosePartSvgPath];
|
|
110
|
+
// Guard 1 (<=): requesting 24×24 on a canvas that is already >= 24 on both sides
|
|
111
|
+
// serves the existing raster without a downgrade. The renderer draws it scaled
|
|
112
|
+
// into the 24×24 display region at the correct visual size — no re-rasterization needed.
|
|
113
|
+
assert((partAsset?.width ?? 0) >= 24 && (partAsset?.height ?? 0) >= 24, 'SVG part raster is at least as large as the requested rig dimensions (no downgrade)');
|
|
114
|
+
// ── Monotonic upgrade / anti-oscillation tests ─────────────────────────────
|
|
115
|
+
// Regression for commit 20182eb which changed both size guards from `<=` to
|
|
116
|
+
// `===` and removed the `Math.max` for __distarkRequestedRasterWidth. That
|
|
117
|
+
// change allowed DOWNGRADE requests: when desiredSize dipped below the cached
|
|
118
|
+
// raster size a new smaller canvas was triggered; the following frame needing
|
|
119
|
+
// the original larger size triggered another upgrade; creating perpetual
|
|
120
|
+
// oscillation ("shaky dimensions"). These tests pin the correct behaviour.
|
|
121
|
+
const oscLoader = new ImageLoader('http://example.test');
|
|
122
|
+
const oscSvgPath = makeSvgDataUrl();
|
|
123
|
+
let oscUpgradeCount = 0;
|
|
124
|
+
const OrigCreateSvgCanvas = oscLoader.createSvgCanvas.bind(oscLoader);
|
|
125
|
+
oscLoader.createSvgCanvas = async (...args) => {
|
|
126
|
+
oscUpgradeCount++;
|
|
127
|
+
return OrigCreateSvgCanvas(...args);
|
|
128
|
+
};
|
|
129
|
+
// Seed loadedImages with the SVG at its intrinsic size (24×24).
|
|
130
|
+
const oscImages = await oscLoader.loadAllRigImages(makeRig(oscSvgPath, 24, 24), false);
|
|
131
|
+
oscUpgradeCount = 0; // reset counter — we only care about requestImageForSize calls
|
|
132
|
+
// Frame 1: request at 100×100 → should trigger exactly ONE upgrade.
|
|
133
|
+
oscLoader.requestImageForSize(oscSvgPath, 100, 100, oscImages);
|
|
134
|
+
await oscLoader.waitForPendingImageUpgrades();
|
|
135
|
+
assert(oscUpgradeCount === 1, 'Upscale from intrinsic triggers exactly one rasterization');
|
|
136
|
+
assert(oscImages[oscSvgPath]?.width >= 100, 'Canvas after first upgrade is at least 100 wide');
|
|
137
|
+
oscUpgradeCount = 0;
|
|
138
|
+
// Frame 2: same size request → must NOT trigger a new rasterization.
|
|
139
|
+
oscLoader.requestImageForSize(oscSvgPath, 100, 100, oscImages);
|
|
140
|
+
await oscLoader.waitForPendingImageUpgrades();
|
|
141
|
+
assert(oscUpgradeCount === 0, 'Identical size request does not re-rasterize (Guard 1 <=)');
|
|
142
|
+
// Frame 3: slightly SMALLER request (95×95, 5% below current 100×100).
|
|
143
|
+
// Guard 1 (<=): 95 <= 100 → should return the 100×100 canvas without re-rasterizing.
|
|
144
|
+
oscLoader.requestImageForSize(oscSvgPath, 95, 95, oscImages);
|
|
145
|
+
await oscLoader.waitForPendingImageUpgrades();
|
|
146
|
+
assert(oscUpgradeCount === 0, 'Smaller request served by existing larger raster (no downgrade)');
|
|
147
|
+
assert(oscImages[oscSvgPath]?.width >= 100, 'Canvas stays at 100 after smaller request');
|
|
148
|
+
// Oscillation simulation: alternate 95 ↔ 110 for 10 frames.
|
|
149
|
+
// With the old buggy code each alternation triggered a new rasterization.
|
|
150
|
+
// With the fix, the raster grows to 110 on the first 110 request and stays
|
|
151
|
+
// there for all subsequent requests (both 95 and 110 pass Guard 1 afterwards).
|
|
152
|
+
const oscImages2 = await oscLoader.loadAllRigImages(makeRig(oscSvgPath, 24, 24), false);
|
|
153
|
+
oscUpgradeCount = 0;
|
|
154
|
+
for (let i = 0; i < 10; i++) {
|
|
155
|
+
const size = i % 2 === 0 ? 95 : 110;
|
|
156
|
+
oscLoader.requestImageForSize(oscSvgPath, size, size, oscImages2);
|
|
157
|
+
await oscLoader.waitForPendingImageUpgrades();
|
|
158
|
+
}
|
|
159
|
+
assert(oscUpgradeCount <= 2, `Oscillating size requests trigger at most 2 rasterizations (got ${oscUpgradeCount}), not one per frame`);
|
|
160
|
+
assert(oscImages2[oscSvgPath]?.width >= 95, 'Canvas after oscillation is still valid');
|
|
161
|
+
// __distarkIntrinsicWidth must survive through the upgrade so it can still be
|
|
162
|
+
// used as a fallback when desiredWidth is 0.
|
|
163
|
+
const intrLoader = new ImageLoader('http://example.test');
|
|
164
|
+
const intrImages = await intrLoader.loadAllRigImages(makeRig(makeSvgDataUrl(), 24, 24), false);
|
|
165
|
+
const intrKey = Object.keys(intrImages)[0];
|
|
166
|
+
const intrinsicBefore = intrImages[intrKey].__distarkIntrinsicWidth;
|
|
167
|
+
intrLoader.requestImageForSize(intrKey, 80, 80, intrImages);
|
|
168
|
+
await intrLoader.waitForPendingImageUpgrades();
|
|
169
|
+
const intrinsicAfter = intrImages[intrKey].__distarkIntrinsicWidth;
|
|
170
|
+
assert(intrinsicAfter === intrinsicBefore, `__distarkIntrinsicWidth preserved through upgrade (${intrinsicBefore} → ${intrinsicAfter})`);
|
|
171
|
+
// ── preserveAspectRatio="none" → non-uniform fill (no letterboxing) ────────
|
|
172
|
+
// When Body.js stores an Inkscape SVG it adds preserveAspectRatio="none" so
|
|
173
|
+
// that future upgrade rasters stretch the content to fill the target box.
|
|
174
|
+
// Without the fix, normalizeSvgToVisibleBounds uses uniform min-scale fit and
|
|
175
|
+
// centres the content with padding — causing a visible dimension jump the
|
|
176
|
+
// first time the raster is upgraded after the attribute is added.
|
|
177
|
+
//
|
|
178
|
+
// Geometry of this test:
|
|
179
|
+
// SVG viewBox 10×20 (tall, aspect 0.5), target 200×100 (wide, aspect 2.0)
|
|
180
|
+
// Uniform fit → fitScale = min(200/10, 100/20) = 5 → matrix(5 0 0 5 75 0)
|
|
181
|
+
// content is only 50 px wide inside a 200 px canvas (75 px padding each side)
|
|
182
|
+
// Non-uniform fill → scaleX = 200/10 = 20, scaleY = 100/20 = 5 → matrix(20 0 0 5 0 0)
|
|
183
|
+
// content fills the entire 200×100 canvas with no padding
|
|
184
|
+
class NormalizeTester extends ImageLoader {
|
|
185
|
+
static expose(svg, w, h) {
|
|
186
|
+
return ImageLoader.normalizeSvgToVisibleBounds(svg, w, h);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const tallSvgWithFill = '<svg xmlns="http://www.w3.org/2000/svg" width="10" height="20" viewBox="0 0 10 20" preserveAspectRatio="none"><rect width="10" height="20"/></svg>';
|
|
190
|
+
const tallSvgNoHint = '<svg xmlns="http://www.w3.org/2000/svg" width="10" height="20" viewBox="0 0 10 20"><rect width="10" height="20"/></svg>';
|
|
191
|
+
const wideTarget = { w: 200, h: 100 };
|
|
192
|
+
const normalizedFill = NormalizeTester.expose(tallSvgWithFill, wideTarget.w, wideTarget.h);
|
|
193
|
+
const normalizedFit = NormalizeTester.expose(tallSvgNoHint, wideTarget.w, wideTarget.h);
|
|
194
|
+
// With preserveAspectRatio="none": fill → scaleX 20, scaleY 5, no centering offset
|
|
195
|
+
assert(normalizedFill.includes('matrix(20'), `preserveAspectRatio="none" SVG should use fill scaleX=20 (got: ${normalizedFill.match(/matrix\([^)]+\)/)?.[0] ?? 'no matrix'})`);
|
|
196
|
+
assert(!normalizedFill.includes('matrix(5 0 0 5 75'), 'preserveAspectRatio="none" SVG must NOT produce a uniform-fit pillarboxed matrix');
|
|
197
|
+
// Without preserveAspectRatio: uniform fit → existing behaviour preserved
|
|
198
|
+
assert(normalizedFit.includes('matrix(5 0 0 5'), `SVG without preserveAspectRatio hint should still use uniform fit scaleX=scaleY=5 (got: ${normalizedFit.match(/matrix\([^)]+\)/)?.[0] ?? 'no matrix'})`);
|
|
199
|
+
// Verify mm SVG: after Body.js patches __distarkSvgSource with preserveAspectRatio="none",
|
|
200
|
+
// a subsequent requestImageForSize upgrade must produce a canvas whose content fills the
|
|
201
|
+
// target box without pillarboxing.
|
|
202
|
+
//
|
|
203
|
+
// Olivia head: mm SVG intrinsic ~390×525 px, dimensionValues 208×232.
|
|
204
|
+
// The aspect ratio mismatch (0.897 vs 0.743) would produce heavy pillarboxing under
|
|
205
|
+
// the old uniform-fit code. With fill mode the matrix scaleX/scaleY differ, confirming
|
|
206
|
+
// non-uniform (stretch) rendering.
|
|
207
|
+
const oliviaHeadSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="103.1875mm" height="138.90625mm" viewBox="0 0 103.1875 138.90625" preserveAspectRatio="none"><rect width="103.1875" height="138.90625"/></svg>';
|
|
208
|
+
const oliviaNormalized = NormalizeTester.expose(oliviaHeadSvg, 208, 232);
|
|
209
|
+
// scaleUU_X = 208 / 103.1875 ≈ 2.016, scaleUU_Y = 232 / 138.90625 ≈ 1.670 — must differ
|
|
210
|
+
const oliviaMatrixMatch = oliviaNormalized.match(/matrix\(([\d.]+)\s+0\s+0\s+([\d.]+)/);
|
|
211
|
+
const oliviaScaleX = parseFloat(oliviaMatrixMatch?.[1] ?? '0');
|
|
212
|
+
const oliviaScaleY = parseFloat(oliviaMatrixMatch?.[2] ?? '0');
|
|
213
|
+
assert(Math.abs(oliviaScaleX - oliviaScaleY) > 0.1, `Olivia mm SVG with preserveAspectRatio="none" must use non-uniform scaling (scaleX=${oliviaScaleX.toFixed(3)}, scaleY=${oliviaScaleY.toFixed(3)})`);
|
|
214
|
+
// ── prepareSvgCanvases: pre-rasterize all SVG parts at dimensionValues sizes ──
|
|
215
|
+
// Before playback starts, every SVG part in loadedImages must have a canvas
|
|
216
|
+
// that is already the exact size dictated by dimensionValues. Without this,
|
|
217
|
+
// the first rendered frame uses the intrinsic-size canvas (often much larger
|
|
218
|
+
// than the display slot), then an async requestImageForSize upgrade fires —
|
|
219
|
+
// causing the visible "flash then correct size" artefact.
|
|
220
|
+
//
|
|
221
|
+
// prepareSvgCanvases(rigData, loadedImages) must:
|
|
222
|
+
// 1. Read dimensionValues[partName] for each SVG imagePath
|
|
223
|
+
// 2. Create a canvas at exactly that size using the (already-normalized) source
|
|
224
|
+
// 3. Mark the canvas __distarkSvgNormalized = true so Body.js doesn't re-normalize
|
|
225
|
+
// 4. Update both imageCache and loadedImages in-place
|
|
226
|
+
const prepLoader = new ImageLoader('http://example.test');
|
|
227
|
+
// Simple SVG — full viewBox is filled, no offset transform.
|
|
228
|
+
// preserveAspectRatio="none" is already set so normalizeSvgToVisibleBounds fills.
|
|
229
|
+
const simpleSvgForPrep = `<svg xmlns="http://www.w3.org/2000/svg" width="100" height="120" viewBox="0 0 100 120" preserveAspectRatio="none"><rect x="0" y="0" width="100" height="120" fill="black"/></svg>`;
|
|
230
|
+
const prepPath = svgDataUrl(simpleSvgForPrep);
|
|
231
|
+
const prepRig = makeRig(prepPath, 60, 80);
|
|
232
|
+
// Load at intrinsic size (100×120)
|
|
233
|
+
const prepImages = await prepLoader.loadAllRigImages(prepRig, false);
|
|
234
|
+
assert(prepImages[prepPath]?.width === 100 && prepImages[prepPath]?.height === 120, `Before prepareSvgCanvases: canvas at intrinsic 100×120 (got ${prepImages[prepPath]?.width}×${prepImages[prepPath]?.height})`);
|
|
235
|
+
// prepareSvgCanvases must exist and be callable
|
|
236
|
+
assert(typeof prepLoader.prepareSvgCanvases === 'function', 'prepareSvgCanvases is a public method on ImageLoader');
|
|
237
|
+
await prepLoader.prepareSvgCanvases(prepRig, prepImages);
|
|
238
|
+
// After: canvas must be at the dimensionValues size (60×80) with default pixelDensity=1
|
|
239
|
+
assert(prepImages[prepPath]?.width === 60 && prepImages[prepPath]?.height === 80, `prepareSvgCanvases resizes canvas to dimensionValues 60×80 (got ${prepImages[prepPath]?.width}×${prepImages[prepPath]?.height})`);
|
|
240
|
+
// With pixelDensity=2 the canvas must be at 120×160 (dimensionValues × 2)
|
|
241
|
+
const prepLoader2 = new ImageLoader('http://example.test');
|
|
242
|
+
const prepImages2 = await prepLoader2.loadAllRigImages(prepRig, false);
|
|
243
|
+
await prepLoader2.prepareSvgCanvases(prepRig, prepImages2, { pixelDensity: 2 });
|
|
244
|
+
assert(prepImages2[prepPath]?.width === 120 && prepImages2[prepPath]?.height === 160, `prepareSvgCanvases with pixelDensity=2 resizes to 120×160 (got ${prepImages2[prepPath]?.width}×${prepImages2[prepPath]?.height})`);
|
|
245
|
+
// Fractional camera scales must be preserved. Rounding 1.25 to 1 would
|
|
246
|
+
// leave playback undersized and trigger requestImageForSize on frame 1.
|
|
247
|
+
const prepLoader125 = new ImageLoader('http://example.test');
|
|
248
|
+
const prepImages125 = await prepLoader125.loadAllRigImages(prepRig, false);
|
|
249
|
+
await prepLoader125.prepareSvgCanvases(prepRig, prepImages125, { pixelDensity: 1.25 });
|
|
250
|
+
assert(prepImages125[prepPath]?.width === 75 && prepImages125[prepPath]?.height === 100, `prepareSvgCanvases preserves fractional scale 1.25 → 75×100 (got ${prepImages125[prepPath]?.width}×${prepImages125[prepPath]?.height})`);
|
|
251
|
+
// A later lower-resolution loadImages call must not downgrade a canvas that
|
|
252
|
+
// playback precompute already warmed at a higher camera/capture scale.
|
|
253
|
+
await prepLoader125.prepareSvgCanvases(prepRig, prepImages125, { pixelDensity: 1 });
|
|
254
|
+
assert(prepImages125[prepPath]?.width === 75 && prepImages125[prepPath]?.height === 100, `prepareSvgCanvases must not downgrade 75×100 cache back to 60×80 (got ${prepImages125[prepPath]?.width}×${prepImages125[prepPath]?.height})`);
|
|
255
|
+
// Canvas must be marked so Body.js rememberOriginalSvgImage skips re-normalization
|
|
256
|
+
assert(prepImages[prepPath]?.__distarkSvgNormalized === true, 'Canvas produced by prepareSvgCanvases is marked __distarkSvgNormalized');
|
|
257
|
+
// imageCache must also point to the new canvas
|
|
258
|
+
assert(prepLoader.getCachedImage(prepPath)?.width === 60, 'imageCache updated to the target-sized canvas after prepareSvgCanvases');
|
|
259
|
+
// Runtime playback lock: once the app has precomputed the fixed-size SVG
|
|
260
|
+
// manifest, requestImageForSize must not create/swap a larger canvas.
|
|
261
|
+
globalThis.__distarkSvgRuntimeUpgradeLocked = true;
|
|
262
|
+
const lockedBefore = prepImages[prepPath];
|
|
263
|
+
const lockedReturned = prepLoader.requestImageForSize(prepPath, 500, 500, prepImages);
|
|
264
|
+
await new Promise(resolve => setTimeout(resolve, 20));
|
|
265
|
+
assert(lockedReturned === lockedBefore, 'locked requestImageForSize returns existing canvas');
|
|
266
|
+
assert(prepImages[prepPath] === lockedBefore, 'locked requestImageForSize does not replace loadedImages entry');
|
|
267
|
+
assert(prepImages[prepPath]?.width === 60 && prepImages[prepPath]?.height === 80, 'locked requestImageForSize does not resize canvas');
|
|
268
|
+
globalThis.__distarkSvgRuntimeUpgradeLocked = false;
|
|
269
|
+
// ── loadImageWithCache: public alias for loadImage ──────────────────────────
|
|
270
|
+
// cacheVariationImages in RigCharacterControl calls loadImageWithCache().
|
|
271
|
+
// That method does not exist on ImageLoader/P5ImageLoader, so the pre-caching
|
|
272
|
+
// silently fails (TypeError). Adding it as a public alias makes pre-caching work.
|
|
273
|
+
const aliasLoader = new ImageLoader('http://example.test');
|
|
274
|
+
assert(typeof aliasLoader.loadImageWithCache === 'function', 'loadImageWithCache is a public method on ImageLoader (alias for loadImage)');
|
|
275
|
+
let aliasCalled = false;
|
|
276
|
+
aliasLoader.loadImageWithCache(prepPath, prepPath, (_key, _img) => { aliasCalled = true; }, (_key, _err) => { });
|
|
277
|
+
// Allow async loadImage to complete
|
|
278
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
279
|
+
assert(aliasCalled, 'loadImageWithCache triggers loadImage and fires onLoad callback');
|
|
280
|
+
assert(aliasLoader.getCachedImage(prepPath) !== undefined, 'loadImageWithCache populates imageCache');
|
|
91
281
|
printSummary();
|
|
92
282
|
}
|
|
93
283
|
main().catch((error) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-svg-rerasterization.js","sourceRoot":"","sources":["../../tests/test-svg-rerasterization.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"test-svg-rerasterization.js","sourceRoot":"","sources":["../../tests/test-svg-rerasterization.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration test: Teen Tank SVG rig
|
|
3
|
+
*
|
|
4
|
+
* Verifies:
|
|
5
|
+
* 1. All expected body parts load with images
|
|
6
|
+
* 2. Every part's rendered bounding box stays within the canvas (no clipping)
|
|
7
|
+
* 3. Every part's rendered dimensions match dimensionValues (no squash/stretch)
|
|
8
|
+
* 4. Every joint-connected part pair has overlapping or adjacent bounding boxes
|
|
9
|
+
* (ensures joints connect visually, not floating apart)
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=test-teen-tank-rig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-teen-tank-rig.d.ts","sourceRoot":"","sources":["../../tests/test-teen-tank-rig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration test: Teen Tank SVG rig
|
|
3
|
+
*
|
|
4
|
+
* Verifies:
|
|
5
|
+
* 1. All expected body parts load with images
|
|
6
|
+
* 2. Every part's rendered bounding box stays within the canvas (no clipping)
|
|
7
|
+
* 3. Every part's rendered dimensions match dimensionValues (no squash/stretch)
|
|
8
|
+
* 4. Every joint-connected part pair has overlapping or adjacent bounding boxes
|
|
9
|
+
* (ensures joints connect visually, not floating apart)
|
|
10
|
+
*/
|
|
11
|
+
import { readFile } from 'fs/promises';
|
|
12
|
+
import { SkiaRenderer } from '../modules/adapters/skiaRenderer.js';
|
|
13
|
+
import { assert, printSummary } from './helpers.js';
|
|
14
|
+
// The parts we expect to be present and have loaded images
|
|
15
|
+
const EXPECTED_BODY_PARTS = [
|
|
16
|
+
'head',
|
|
17
|
+
'torso',
|
|
18
|
+
'leftUpperArm', 'leftForearm', 'leftHand',
|
|
19
|
+
'rightUpperArm', 'rightForearm', 'rightHand',
|
|
20
|
+
'leftThigh', 'leftLeg',
|
|
21
|
+
'rightThigh', 'rightLeg',
|
|
22
|
+
];
|
|
23
|
+
// Joint connections: [parent, child] — their bounding boxes must touch or overlap
|
|
24
|
+
const JOINT_CONNECTIONS = [
|
|
25
|
+
['torso', 'head'],
|
|
26
|
+
['torso', 'leftUpperArm'],
|
|
27
|
+
['leftUpperArm', 'leftForearm'],
|
|
28
|
+
['leftForearm', 'leftHand'],
|
|
29
|
+
['torso', 'rightUpperArm'],
|
|
30
|
+
['rightUpperArm', 'rightForearm'],
|
|
31
|
+
['rightForearm', 'rightHand'],
|
|
32
|
+
['torso', 'leftThigh'],
|
|
33
|
+
['leftThigh', 'leftLeg'],
|
|
34
|
+
['torso', 'rightThigh'],
|
|
35
|
+
['rightThigh', 'rightLeg'],
|
|
36
|
+
];
|
|
37
|
+
// Tolerance in pixels for joint proximity check (parts can be slightly apart due to anchor math)
|
|
38
|
+
const JOINT_PROXIMITY_PX = 80;
|
|
39
|
+
// Tolerance ratio: rendered dimension must be within this fraction of the declared dimension
|
|
40
|
+
const DIMENSION_TOLERANCE = 0.02; // 2%
|
|
41
|
+
function getBounds(obj) {
|
|
42
|
+
const left = obj.x - obj.width * obj.anchorX;
|
|
43
|
+
const top = obj.y - obj.height * obj.anchorY;
|
|
44
|
+
return { left, top, right: left + obj.width, bottom: top + obj.height };
|
|
45
|
+
}
|
|
46
|
+
function boxesTouching(a, b, tolerance) {
|
|
47
|
+
return (a.right + tolerance >= b.left &&
|
|
48
|
+
b.right + tolerance >= a.left &&
|
|
49
|
+
a.bottom + tolerance >= b.top &&
|
|
50
|
+
b.bottom + tolerance >= a.top);
|
|
51
|
+
}
|
|
52
|
+
async function main() {
|
|
53
|
+
console.log('\n=== Teen Tank SVG Rig Integration Tests ===\n');
|
|
54
|
+
const rigPath = 'C:\\Users\\kirag\\Downloads\\teen_tank_Svg.json';
|
|
55
|
+
const rigData = JSON.parse(await readFile(rigPath, 'utf-8'));
|
|
56
|
+
const dimensions = rigData.dimensionValues || {};
|
|
57
|
+
const origLog = console.log;
|
|
58
|
+
console.log = (...a) => process.stderr.write(a.join(' ') + '\n');
|
|
59
|
+
const renderer = new SkiaRenderer();
|
|
60
|
+
await renderer.loadImages(rigData);
|
|
61
|
+
const canvasWidth = 1200;
|
|
62
|
+
const canvasHeight = 2000;
|
|
63
|
+
const renderData = renderer.compute(rigData, {
|
|
64
|
+
canvasWidth,
|
|
65
|
+
canvasHeight,
|
|
66
|
+
});
|
|
67
|
+
console.log = origLog;
|
|
68
|
+
const objects = renderData.objects;
|
|
69
|
+
const byName = new Map(objects.map(o => [o.name, o]));
|
|
70
|
+
// ── 1. All expected parts loaded with images ───────────────────────────────
|
|
71
|
+
console.log('--- Part presence & image loading ---');
|
|
72
|
+
for (const part of EXPECTED_BODY_PARTS) {
|
|
73
|
+
const obj = byName.get(part);
|
|
74
|
+
assert(!!obj, `Part '${part}' is present in render data`);
|
|
75
|
+
assert(!!obj?.imageData, `Part '${part}' has a loaded image`);
|
|
76
|
+
}
|
|
77
|
+
// ── 2. No part clips outside canvas bounds ─────────────────────────────────
|
|
78
|
+
console.log('\n--- Canvas bounds (no clipping) ---');
|
|
79
|
+
for (const part of EXPECTED_BODY_PARTS) {
|
|
80
|
+
const obj = byName.get(part);
|
|
81
|
+
if (!obj)
|
|
82
|
+
continue;
|
|
83
|
+
const b = getBounds(obj);
|
|
84
|
+
const withinCanvas = b.left >= -1 &&
|
|
85
|
+
b.top >= -1 &&
|
|
86
|
+
b.right <= canvasWidth + 1 &&
|
|
87
|
+
b.bottom <= canvasHeight + 1;
|
|
88
|
+
assert(withinCanvas, `Part '${part}' stays within canvas (left=${Math.round(b.left)} top=${Math.round(b.top)} right=${Math.round(b.right)} bottom=${Math.round(b.bottom)})`);
|
|
89
|
+
}
|
|
90
|
+
// ── 3. Rendered dimensions match dimensionValues ───────────────────────────
|
|
91
|
+
console.log('\n--- Rendered dimensions match dimensionValues ---');
|
|
92
|
+
for (const part of EXPECTED_BODY_PARTS) {
|
|
93
|
+
const obj = byName.get(part);
|
|
94
|
+
const decl = dimensions[part];
|
|
95
|
+
if (!obj || !decl)
|
|
96
|
+
continue;
|
|
97
|
+
const wDiff = Math.abs(obj.width - decl.width) / decl.width;
|
|
98
|
+
const hDiff = Math.abs(obj.height - decl.height) / decl.height;
|
|
99
|
+
assert(wDiff <= DIMENSION_TOLERANCE, `Part '${part}' width ${Math.round(obj.width)} ≈ declared ${decl.width} (diff ${(wDiff * 100).toFixed(1)}%)`);
|
|
100
|
+
assert(hDiff <= DIMENSION_TOLERANCE, `Part '${part}' height ${Math.round(obj.height)} ≈ declared ${decl.height} (diff ${(hDiff * 100).toFixed(1)}%)`);
|
|
101
|
+
}
|
|
102
|
+
// ── 4. Joint connections — parts must touch or nearly overlap ──────────────
|
|
103
|
+
console.log('\n--- Joint connectivity ---');
|
|
104
|
+
for (const [parentName, childName] of JOINT_CONNECTIONS) {
|
|
105
|
+
const parent = byName.get(parentName);
|
|
106
|
+
const child = byName.get(childName);
|
|
107
|
+
if (!parent || !child) {
|
|
108
|
+
assert(false, `Cannot check joint ${parentName}→${childName}: part missing`);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const pb = getBounds(parent);
|
|
112
|
+
const cb = getBounds(child);
|
|
113
|
+
const touching = boxesTouching(pb, cb, JOINT_PROXIMITY_PX);
|
|
114
|
+
assert(touching, `Joint ${parentName}→${childName} bounding boxes are adjacent/overlapping (within ${JOINT_PROXIMITY_PX}px)`);
|
|
115
|
+
}
|
|
116
|
+
printSummary();
|
|
117
|
+
}
|
|
118
|
+
main().catch(err => {
|
|
119
|
+
console.error(err);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
});
|
|
122
|
+
//# sourceMappingURL=test-teen-tank-rig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-teen-tank-rig.js","sourceRoot":"","sources":["../../tests/test-teen-tank-rig.ts"],"names":[],"mappings":"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"}
|