diff --git a/devx/camera-api.md b/devx/camera-api.md index 29cfccf..87d91c3 100644 --- a/devx/camera-api.md +++ b/devx/camera-api.md @@ -1,10 +1,10 @@ --- number: 31 -title: "No camera on the api" -status: open -gap: "no **camera** on the api (the crosshair ray under a lock)" +title: "No camera on the api — **SHIPPED**" +status: shipped +gap: "~~no **camera** on the api (the crosshair ray under a lock)~~" blocks: "`untangle`" -workaround: "yes — `pointerRay().camera`, else the scene camera nearest `playerPosition()`" +workaround: "**SHIPPED** (core 1.26, 37-slipped: `api.camera()` — the camera the user looks through, the XR camera in a headset). untangle 2.4.2 asks it first and keeps its inference for older cores" --- **Found in:** `modules/untangle` (P0). Under a pointer lock the carry must follow the diff --git a/devx/play-mode-signal.md b/devx/play-mode-signal.md index 757c795..4b920a1 100644 --- a/devx/play-mode-signal.md +++ b/devx/play-mode-signal.md @@ -1,10 +1,10 @@ --- number: 11 -title: "No play-mode signal" -status: open -gap: "play-mode signal (`api.isPlaying()` / `onPlayMode`)" +title: "No play-mode signal — **SHIPPED**" +status: shipped +gap: "~~play-mode signal (`api.isPlaying()` / `onPlayMode`)~~" blocks: "`dungeon-realms`" -workaround: "yes — observes `#dungeon-minimap` visibility (brittle DOM)" +workaround: "**SHIPPED** (`api.isPlaying()` since 17-A; core 1.26, 37-slipped: `api.onPlayMode(fn)` + `api.inGame()` — Play OR a headset game in Interact). dungeon-realms keeps its own rule (desktop Interact is a game view too) and no longer reaches the minimap sniff on any core with `api.isPlaying`" --- **Found in:** `modules/dungeon-realms` — the GUI must appear "only after the diff --git a/devx/pointer-seam-dispose-hook-own-listeners.md b/devx/pointer-seam-dispose-hook-own-listeners.md index d2700c1..b1addc6 100644 --- a/devx/pointer-seam-dispose-hook-own-listeners.md +++ b/devx/pointer-seam-dispose-hook-own-listeners.md @@ -1,10 +1,10 @@ --- number: 29 -title: "No pointer seam and no dispose hook for a module's own listeners" -status: open -gap: "no **pointer seam** (pointerdown/up, click-miss) and no module **dispose hook**" +title: "No pointer seam and no dispose hook for a module's own listeners — **SHIPPED**" +status: shipped +gap: "~~no **pointer seam** (pointerdown/up, click-miss) and no module **dispose hook**~~" blocks: "`untangle`" -workaround: "yes — window CAPTURE listeners, self-detaching when a newer copy owns the module's hook" +workaround: "**SHIPPED** (dispose: `api.onUnload` 34 R6; core 1.26, 37-slipped: `api.registerPointerHandler({down, move, up}, {modes})` — `down` returning true OWNS the gesture, orbit/select/carry stand down — and `api.onClickMiss(fn)`). untangle still runs its own capture-phase gesture (tap-to-pick, two-finger rotate, menu suppression); porting it onto the seam is a follow-up" --- **Found in:** `modules/untangle` (roadmap 30, P0). A real drag needs the PRESS: core diff --git a/index.json b/index.json index 0897e7a..34525b8 100644 --- a/index.json +++ b/index.json @@ -264,7 +264,7 @@ { "id": "untangle", "name": "Untangle", - "version": "2.4.1", + "version": "2.4.2", "description": "Untangle the graph: drag the dots until no edges cross, on a flat 2D board or around a 3D globe (great-circle arcs). 30 levels with ONE progress across both modes (switching keeps your level), best times kept on your device, reset any time. In VR: you start in front of the board, grab dots with the trigger (laser or tip), hold, turn and scale the globe, the stick pushes the board or the held globe farther and pulls it closer like an object in the editor, the grips move and scale the world, a level picker with Globe / 2D in the headset and a waist-height level bar, haptics. Procedural and replicated, with game sounds and quiet puzzle music - board pose, level and readouts as flow nodes.", "author": "theprototype-app", "source": "modules/untangle", diff --git a/modules/untangle/manifest.json b/modules/untangle/manifest.json index 9087c7c..643efa8 100644 --- a/modules/untangle/manifest.json +++ b/modules/untangle/manifest.json @@ -1,7 +1,7 @@ { "id": "untangle", "name": "Untangle", - "version": "2.4.1", + "version": "2.4.2", "format": 1, "description": "Untangle the graph: drag the dots until no edges cross, on a flat 2D board or around a 3D globe (great-circle arcs). 30 levels with ONE progress across both modes (switching keeps your level), best times kept on your device, reset any time. In VR: you start in front of the board, grab dots with the trigger (laser or tip), hold, turn and scale the globe, the stick pushes the board or the held globe farther and pulls it closer like an object in the editor, the grips move and scale the world, a level picker with Globe / 2D in the headset and a waist-height level bar, haptics. Procedural and replicated, with game sounds and quiet puzzle music - board pose, level and readouts as flow nodes.", "entry": "module.js", diff --git a/modules/untangle/module.js b/modules/untangle/module.js index dfaf917..96068d7 100644 --- a/modules/untangle/module.js +++ b/modules/untangle/module.js @@ -305,6 +305,8 @@ function makeAim(api, THREE) { return best; } function camera() { + const direct = typeof api.camera === "function" ? api.camera() : null; + if (direct) return direct; const r = api.pointerRay?.(); return r?.camera ?? sceneCamera(); } @@ -1890,7 +1892,7 @@ var EXPIRE_FRAMES = 40; var index_default = { id: "untangle", name: "Untangle", - version: "2.4.1", + version: "2.4.2", description: "Drag the dots until no edges cross \u2014 on a flat board or around a globe, 30 levels that unlock as you solve them, one progress for both (it stays on your device). In VR: you start in front of the board, grab dots with the trigger, hold/turn/scale the globe, the stick pushes the board or the held globe farther / pulls it closer (as Edit does to a held object), the grips scale the world, a level picker with Globe / 2D and a level bar. Replicated; board pose, level and readouts as flow nodes.", /** @param {any} api */ register(api) { diff --git a/modules/untangle/src/aim.js b/modules/untangle/src/aim.js index 476dcee..a77a53b 100644 --- a/modules/untangle/src/aim.js +++ b/modules/untangle/src/aim.js @@ -13,7 +13,8 @@ // camera's forward: equal -> trust the api ('api'), otherwise build the NDC (0,0) ray // from the same camera ('crosshair'). // -// The camera: a Raycaster remembers the camera it was set from (`ray.camera`), so the +// The camera: `api.camera()` on a core that has it (DEVX #31, 1.26). Before that, a +// Raycaster remembers the camera it was set from (`ray.camera`), so the // api's own ray names the active camera; before the first pointer event (api ray null) we // fall back to the scene camera nearest `api.playerPosition()`, which core reads off that // same active camera. @@ -48,6 +49,10 @@ export function makeAim(api, THREE) { } function camera() { + // core 1.26+ (DEVX #31): the camera the user looks through, asked directly; the two + // inferences below stay for older cores + const direct = typeof api.camera === 'function' ? api.camera() : null; + if (direct) return direct; const r = api.pointerRay?.(); return r?.camera ?? sceneCamera(); } diff --git a/modules/untangle/src/def.js b/modules/untangle/src/def.js index 0888190..8cdc6a4 100644 --- a/modules/untangle/src/def.js +++ b/modules/untangle/src/def.js @@ -218,7 +218,7 @@ export function untangleDef() { license: 'CC0-1.0', author: 'theprototype', tags: ['puzzle', 'co-op', 'procedural', '3d'], - modules: [{ id: 'untangle', version: '2.4.1' }], + modules: [{ id: 'untangle', version: '2.4.2' }], installModules: ['untangle'], env: ENV, // play.cursor 'free' (30-core-flow): no pointer lock — the real cursor drags; a core diff --git a/modules/untangle/src/index.js b/modules/untangle/src/index.js index 3afdb11..595684c 100644 --- a/modules/untangle/src/index.js +++ b/modules/untangle/src/index.js @@ -42,7 +42,7 @@ const EXPIRE_FRAMES = 40; // a node gone from the graph -> the module's own defa export default { id: 'untangle', name: 'Untangle', - version: '2.4.1', + version: '2.4.2', description: 'Drag the dots until no edges cross — on a flat board or around a globe, 30 levels that unlock as you solve them, one progress for both (it stays on your device). In VR: you start in front of the board, grab dots with the trigger, hold/turn/scale the globe, the stick pushes the board or the held globe farther / pulls it closer (as Edit does to a held object), the grips scale the world, a level picker with Globe / 2D and a level bar. Replicated; board pose, level and readouts as flow nodes.', /** @param {any} api */ register(api) { diff --git a/modules/untangle/untangle.def.json b/modules/untangle/untangle.def.json index 4ea2d8b..dacc186 100644 --- a/modules/untangle/untangle.def.json +++ b/modules/untangle/untangle.def.json @@ -14,7 +14,7 @@ "modules": [ { "id": "untangle", - "version": "2.4.1" + "version": "2.4.2" } ], "installModules": [