Recenter brings a lost keyboard back under the primary display

Recenter moved every root rigidly, so a keyboard dropped far away stayed far
away, and one left on a hand did not move at all. A keyboard that no longer
hangs from a display is now hinged back onto the primary display's bottom
slot; if a display already hangs there, the keyboard stays free.

Agent: Claude Code 2.1.303; model claude-opus-5-5; thread b05c29b5-7ac1-4548-9065-aa346fab238f
This commit is contained in:
mommysgoodpuppy committed 2026-10-19 18:20:02 +03:00
1 parent 40af768ac4
commit 53bb6745f8
2 files changed
+27

No files matched your search

+21
View File
@@ -577,6 +577,27 @@ Deno.test("recenter puts the primary display in front of the head and keeps the
);
});
Deno.test("recenter brings a lost keyboard back under the primary display", () => {
let graph = detachFromParent(createInitialSpatialGraph(), "keyboard");
graph = commitNodeTransform(graph, "keyboard", {
position: [40, -3, 12],
rotation: [0, 2, 0],
scale: [0.38, 0.38, 0.38],
});
const recentered = recenterSpatialRoots(graph, [0, 1.6, 0], 0, [0, -0.08, -1.35]);
const keyboard = recentered.nodes.keyboard;
assert(keyboard?.parentId === "display-1", "keyboard reparented to the primary display");
assert(
keyboard.constraint?.attachmentSlotId === "display-1-bottom-slot",
"keyboard hinged to the bottom slot",
);
// A display already hanging below the primary keeps the slot; the keyboard just moves along.
let occupied = detachFromParent(spawnHingedDisplay(graph, "display-1", "bottom"), "keyboard");
occupied = recenterSpatialRoots(occupied, [0, 1.6, 0], 0, [0, -0.08, -1.35]);
assert(occupied.nodes.keyboard?.constraint == null, "taken bottom slot leaves the keyboard free");
});
Deno.test("locking a node is a no-op when unchanged and survives a clone", () => {
const graph = createInitialSpatialGraph();
assert(setSpatialNodeLocked(graph, "display-1", false) === graph, "unlocking an unlocked node");
+6
View File
@@ -699,6 +699,12 @@ export function recenterSpatialRoots(
},
};
}
// A keyboard that no longer hangs from a display comes back under the primary one, so one
// dropped out of reach, or left on a hand, is a Recenter away. A taken bottom slot keeps it put.
const keyboard = Object.values(graph.nodes).find((node) => node.kind === "keyboard");
if (keyboard != null && keyboard.constraint == null) {
return attachSpatialNodeToSlot(graph, keyboard.id, `${primary.id}-bottom-slot`);
}
return graph;
}