Clear references to a template object in every scene on delete (#269)
Deleting an object in a container tab only cleared references inside the template. Placements in scenes and other containers kept their instance edit and showed "(missing)" in the inspector. - shownObjectIds records which objects every holder shows before the delete. dropReferencesToGone compares that with the state after it and clears each reference that no longer resolves. - A reference is resolved from its own place with referenceCandidates, the same way the runtime does. One rule covers instance edits, nested placements and full ids like p~crate. - A cleared instance edit is dropped when it now says the same as the template's own value. Without such a value a marked None stays, as if picked by hand, and Reset hands the row back to the template. - All cleared references come back with a single undo. - References that were already dead in saved projects stay untouched. Findings, not fixed here: - A reference from container D into a nested placement q is stored as q~<id>, but the copy is named r~q/<id> in every placement of D. The runtime finds nothing, so that reference is dead from the start. - Delete asset removes placed objects by cascade but does not clear references to them. Tests: - Unit object-references: 17 passed (13 + 4) - Gate: 198 files, 2873 tests, exit 0 - e2e 1-17,57: 564 checks passed, 57 has 13 (+1 for 57h) - Five unit counter-probes and one browser counter-probe fail as expected - e2e total 1607 is computed, not measured in a full run Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0f6e628616
commit
214218d1b2
6 files changed
+249
-18
No files matched your search
@@ -9,6 +9,8 @@
|
||||
* a right-click and a second press of the eyedropper leave it as it was. From a list item in a
|
||||
* Variables tab it goes to the scene view and comes back with Take.
|
||||
*
|
||||
* Removing an object in the Container tab empties a reference a placement of it holds (#269).
|
||||
*
|
||||
* Everything it adds carries an `or57` id and goes again at the end.
|
||||
*/
|
||||
import { LANES, MAKE_OBJECT } from './lib/scaffold.mjs';
|
||||
@@ -268,6 +270,76 @@ export async function objectReferences(t) {
|
||||
JSON.stringify({ tabShown, inTab, fromList, listCandidate, backIn, crowd }),
|
||||
);
|
||||
|
||||
// 57h. A container placed in the scene, its Aim pointed at its own Crate there (#269). Removing
|
||||
// the Crate in the Container tab empties that reference too: the row says None, not
|
||||
// (missing). One undo brings both back.
|
||||
await t.showTab('scene');
|
||||
await mutate(`
|
||||
const p = __gm.state.project;
|
||||
const scene = __gm.state.activeScene;
|
||||
${MAKE_OBJECT}
|
||||
const sprite = p.assets.find((a) => a.type === 'sprite');
|
||||
p.assets.push({
|
||||
id: 'or57-box',
|
||||
type: 'container',
|
||||
name: 'Box 57',
|
||||
props: {},
|
||||
objects: [make('or57-t-aim', 'or57-aim', '', 0, 'Aim 57'), make('or57-t-crate', sprite.id, '', 50, 'Crate 57')],
|
||||
});
|
||||
const placed = make('or57-placed', 'or57-box', '', ${LANES.containerReference}, 'Box 57');
|
||||
placed.instanceEdits = {
|
||||
'or57-t-aim': { position: {}, overrides: { target: { $object: 'or57-t-crate' } } },
|
||||
};
|
||||
scene.objects.push(placed);
|
||||
`);
|
||||
const placedTarget = () =>
|
||||
json(
|
||||
"__gm.state.activeScene.objects.find((o) => o.id === 'or57-placed')?.instanceEdits['or57-t-aim']?.overrides.target ?? null",
|
||||
);
|
||||
const targetRow = async () => {
|
||||
const field = await json("__gm.inspectorField('target')");
|
||||
const hits = (await json("__gm.locateAll('None')")) ?? [];
|
||||
return {
|
||||
none: hits.some((p) => field && p.x >= field.left && Math.abs(p.y - field.y) < 12),
|
||||
missing: await inInspector('(missing)'),
|
||||
crate: await inInspector('Crate 57'),
|
||||
};
|
||||
};
|
||||
const placedAim = { kind: 'object', holderId: sceneId, objectId: 'or57-placed~or57-t-aim' };
|
||||
await select(placedAim);
|
||||
await sleep(200);
|
||||
const rowBefore = await targetRow();
|
||||
|
||||
await select({ kind: 'object', holderId: 'or57-box', objectId: 'or57-t-crate' });
|
||||
await sleep(200);
|
||||
const tabThen = await json('__gm.tab()');
|
||||
await press('Delete');
|
||||
await sleep(150);
|
||||
const templateLeft = await json(
|
||||
"__gm.state.project.assets.find((a) => a.id === 'or57-box').objects.map((o) => o.id)",
|
||||
);
|
||||
const emptied = await placedTarget();
|
||||
await t.showTab('scene');
|
||||
await select(placedAim);
|
||||
await sleep(200);
|
||||
const rowAfter = await targetRow();
|
||||
await shot('04-container-reference');
|
||||
await undo();
|
||||
await sleep(150);
|
||||
const restored = await placedTarget();
|
||||
check(
|
||||
'removing an object in the Container tab empties the placement pointing at it, undo brings it back',
|
||||
rowBefore.crate &&
|
||||
!rowBefore.missing &&
|
||||
tabThen === 'container' &&
|
||||
JSON.stringify(templateLeft) === JSON.stringify(['or57-t-aim']) &&
|
||||
JSON.stringify(emptied) === JSON.stringify({ $object: '' }) &&
|
||||
rowAfter.none &&
|
||||
!rowAfter.missing &&
|
||||
JSON.stringify(restored) === JSON.stringify({ $object: 'or57-t-crate' }),
|
||||
JSON.stringify({ rowBefore, tabThen, templateLeft, emptied, rowAfter, restored }),
|
||||
);
|
||||
|
||||
// Clean up. Back to the scene view first: removing Aim 57 closes 57g's Variables tab, and the
|
||||
// editor then shows whatever document earlier steps left open, not the scene view.
|
||||
await t.showTab('scene');
|
||||
@@ -276,6 +348,6 @@ export async function objectReferences(t) {
|
||||
const p = __gm.state.project;
|
||||
const scene = __gm.state.activeScene;
|
||||
scene.objects = scene.objects.filter((o) => !o.id.startsWith('or57-'));
|
||||
p.assets = p.assets.filter((a) => a.id !== 'or57-aim');
|
||||
p.assets = p.assets.filter((a) => a.id !== 'or57-aim' && a.id !== 'or57-box');
|
||||
`);
|
||||
}
|
||||
@@ -28,6 +28,7 @@ export const LANES = {
|
||||
vectorArt: -5100,
|
||||
pixelArt: -5400,
|
||||
eyedropper: -5800,
|
||||
containerReference: -6200,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user