diff --git a/tools/e2e/41-physics.mjs b/tools/e2e/41-physics.mjs index a83b0442..b7c2e829 100644 --- a/tools/e2e/41-physics.mjs +++ b/tools/e2e/41-physics.mjs @@ -302,6 +302,8 @@ export async function physics(t) { () => false, ); // Every frame recorded in the page, so the count follows the frames and not the round trips. + // The page also stamps the release itself: a stamp taken after the round trip came frames late, + // and the first sample after it was already 7 units into the fall on the WSL runner. await evaluate(`(() => { const out = (window.__dragSamples = []); const sample = () => { @@ -309,29 +311,36 @@ export async function physics(t) { if (!window.__dragSamplesDone) requestAnimationFrame(sample); }; window.__dragSamplesDone = false; + window.__dragLetGo = undefined; + window.addEventListener('pointerup', () => (window.__dragLetGo = performance.now()), { + capture: true, + once: true, + }); requestAnimationFrame(sample); })()`); await sleep(1000); await shot('41-drag-while-playing'); const dragInfo = { grab, selected: (await state()).selection?.objectId }; - const holdEnd = await evaluate('performance.now()'); await mouse('mouseReleased', to.x, to.y, 'left'); - const letGo = await evaluate('performance.now()'); await sleep(300); await evaluate('window.__dragSamplesDone = true'); const dragSamples = await json('window.__dragSamples'); + const letGo = await evaluate('window.__dragLetGo'); const log = (await json('__gm.world()'))?.log ?? []; await stop(); - const held = dragSamples.filter((s) => s.t < holdEnd).map((s) => s.y); + const held = dragSamples.filter((s) => s.t < letGo).map((s) => s.y); const released = dragSamples.filter((s) => s.t >= letGo); - // 200 ms of free fall from rest is under 20 below the hold, a body let go at speed is not. - const fell = released.filter((s) => s.t - letGo <= 200).at(-1)?.y; + // 200 ms of free fall from rest is about 25 below the hold, a body let go at speed is not. + const falling = released.filter((s) => s.t - letGo <= 200).map((s) => s.y); + const fell = falling.at(-1); check( 'a body dragged while playing hangs where the pointer holds it and is let go at rest', arrived && held.length >= 30 && held.every((y) => Math.abs(y - target) < 1.5) && - Math.abs(released[0]?.y - target) < 3 && + // Let go it only falls: no jump above the hold, no kick up. How far the first frame after + // the release has already fallen follows the frame time, so that is not a bound here. + falling.every((y, i) => y > target - 1.5 && (i === 0 || y >= falling[i - 1] - 0.01)) && fell > target + 1 && fell < target + 40 && !log.some((line) => line.includes('moved directly')), @@ -339,7 +348,8 @@ export async function physics(t) { target, arrived, held: { frames: held.length, first: held[0], last: held.at(-1) }, - released: released.slice(0, 3).map((s) => s.y), + stamped: typeof letGo === 'number', + released: released.slice(0, 3).map((s) => [Math.round(s.t - letGo), s.y]), fell, log, dragInfo,