An edge to a vanished port needs a handle, so the port stays as a ghost (#60)
game-maker / suite (push) Successful in 10m7s
game-maker / suite (push) Successful in 10m7s
Four ways erase a derived port and take no edge with them: deleting a state, deleting the `State machine` literal, deleting `Behavior start`/`end`, deleting the asset. The common cause is `RemoveNodeCommand` clearing only its own graph, so the fix sits in `drawnDef` (graph/nested.ts) and touches no delete site. A right-click on an edge goes through `view.portAt` only — there is no curve hit-test. Without a port row such an edge is not merely invisible, it is unreachable, so the ghost row is the handle Disconnect hangs on. `resolveDef` stays untouched: it is the truth for interpreter, compiler, ConnectCommand and dropTarget, so nothing runs or connects through a ghost without a second guard.
This commit is contained in:
1 parent
d5e67cd80c
commit
a041322a0e
8 files changed
+372
-16
No files matched your search
@@ -22,6 +22,7 @@ export async function stateMachine(t) {
|
||||
has,
|
||||
doubleClick,
|
||||
drag,
|
||||
mouse,
|
||||
} = t;
|
||||
const { typeText, undo, redo, world, play, stop } = t;
|
||||
const machines = () =>
|
||||
@@ -273,6 +274,65 @@ export async function stateMachine(t) {
|
||||
);
|
||||
await shot('03-machine-picked');
|
||||
|
||||
// 26i. A deleted state leaves its edge hanging; the port comes back as a ghost so it can be seen.
|
||||
const named = await states();
|
||||
const nameOf = (id) => named.find((s) => s.id === id)?.name;
|
||||
check(
|
||||
'before the deletion the edge to the second state is drawn',
|
||||
(await json("__gm.graph.edgeDrawn('sm-e4')")) === true,
|
||||
);
|
||||
await mutate(`
|
||||
const m = __gm.state.project.assets.find((x) => x.id === ${JSON.stringify(made.id)});
|
||||
m.graph.nodes = m.graph.nodes.filter((n) => n.id !== ${JSON.stringify(second)});
|
||||
`);
|
||||
await sleep(400);
|
||||
const ghosted = await outputsOf('sm-branch');
|
||||
check(
|
||||
'the deleted state leaves a row named after its key, and takes its name away',
|
||||
names(ghosted).includes(second) && !names(ghosted).includes(nameOf(second)),
|
||||
JSON.stringify({ ghosted, was: nameOf(second) }),
|
||||
);
|
||||
check(
|
||||
'the edge on it is drawn again instead of vanishing',
|
||||
(await json("__gm.graph.edgeDrawn('sm-e4')")) === true,
|
||||
);
|
||||
check(
|
||||
'the node warns about it',
|
||||
(await json("__gm.graph.nodeProblem('sm-branch')")) === '1 edge on a port that is gone',
|
||||
JSON.stringify(await json("__gm.graph.nodeProblem('sm-branch')")),
|
||||
);
|
||||
check(
|
||||
'the ghost pin can be reached, so the edge has a right-click handle',
|
||||
(await json(`__gm.graph.portAt('sm-branch', ${JSON.stringify(second)}, true)`)) !== null,
|
||||
);
|
||||
const pin = await json(`__gm.graph.portAt('sm-branch', ${JSON.stringify(second)}, true)`);
|
||||
const before = await json("__gm.graph.nodeRect('sm-branch')");
|
||||
const links = () => json('__gm.state.project.assets.find((a) => a.id === "sm-logic").graph.edges.length');
|
||||
const linksBefore = await links();
|
||||
// Measured mid-drag: after the release nothing would show either way, because a ghost has no type
|
||||
// and `openPaletteForDrop` gives up on that. The rubber band is the only visible difference.
|
||||
const empty = await json('__gm.graph.emptySpot()');
|
||||
await mouse('mouseMoved', pin.x, pin.y);
|
||||
await mouse('mousePressed', pin.x, pin.y, 'left', {});
|
||||
await mouse('mouseMoved', empty.x, empty.y, 'left', { buttons: 1 });
|
||||
await sleep(150);
|
||||
const dangling = await json('__gm.graph.danglingEdge()');
|
||||
await mouse('mouseReleased', empty.x, empty.y, 'left', {});
|
||||
await sleep(250);
|
||||
const after = await json("__gm.graph.nodeRect('sm-branch')");
|
||||
check(
|
||||
'pressing a ghost pin starts no rubber band, adds no link, and leaves the node where it was',
|
||||
dangling === false && (await links()) === linksBefore && after.x === before.x && after.y === before.y,
|
||||
JSON.stringify({ dangling, linksBefore, links: await links(), moved: after.x - before.x }),
|
||||
);
|
||||
check(
|
||||
'the state that is left keeps its edge and its name',
|
||||
(await json("__gm.graph.edgeDrawn('sm-e3')")) === true &&
|
||||
names(await outputsOf('sm-branch')).includes(nameOf(first)),
|
||||
JSON.stringify({ lines: await outputsOf('sm-branch'), kept: nameOf(first) }),
|
||||
);
|
||||
await shot('04-ghost-port');
|
||||
|
||||
// 26h. Everything the step made goes away again.
|
||||
const left = await rig.remove();
|
||||
await mutate(`
|
||||
|
||||
Reference in new issue
Block a user