@realitycollective/iwsdk-uiextensions 0.1.1-preview.1 → 0.1.1-preview.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,9 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
|
8
8
|
|
|
9
9
|
### Added
|
|
10
10
|
|
|
11
|
+
- `@realitycollective/webxr-uiextensions` - hover per element as one core decision (`core/hover.ts`, `HoverTracker`): each pointer raises `pointerenter` on the element it moves onto and `pointerleave` on the one it left, once per change, and an element's hover style holds while any pointer is over it, as IWSDK's pointer events drive uikit's `:hover`. The three.js binding raises hover from it, and the native binding decides hover from its pointer samples and tells the host through the new `NativeUiHost.setHover`; a `pointerenter` or `pointerleave` a native host raises itself is ignored.
|
|
12
|
+
- `@realitycollective/webxr-uiextensions` - scrolling as a core rule (`core/scroll.ts`, `ScrollState`, `SCROLL_DEFAULTS`): uikit's drag, coast (0.9 damping per frame, stopping below 10 px/s), rubber band (100 px, 30 % return per frame) and wheel, restated so a native host only draws the offset it is handed (`NativeUiHost.setScroll`; a node declares `scroll` and a ray sample carries `localPoint`). Text entry as a core rule (`core/text-entry.ts`, `TextEntry`) over a platform keyboard facility (`TextInputFacility`): a click on a text field asks for the keyboard with the field's value, `multiline` and `type`; every reported value replaces the field's and raises `valueChanged`. The web default is uikit's `Input` over a hidden HTML input and the browser's keyboard; the native default is the system keyboard (`NativeUiHost.showKeyboard`/`hideKeyboard`, host events `input` and `keyboardclosed`). Kit cases: `ui/hover is decided by the binding...`, `ui/the host scrolls an element's content exactly as told`, `ui/the host shows its keyboard for a text field when told...`.
|
|
13
|
+
- `@realitycollective/webxr-uiextensions` - `WindowManager.setFollow(id, options)` and `OpenWindowOptions.follow`: a following window's offset (in the viewer's yaw frame, metres), speed, dead zone and angle live on the `WindowRecord` (`follow`, `DEFAULT_WINDOW_FOLLOW` unless set) and can change after spawn; the `followChanged` event carries the previous values. Every binding steps the core follow rule from the record: the IWSDK dock system writes the live `Follower`, the three.js and native hosts re-aim at the new offset.
|
|
11
14
|
- `@realitycollective/threejs-uiextensions` - a plain three.js / WebXR binding. `UixWindowHost`, `UixPanelDocument`, `configureRendererForUikit` and `fitScale` moved here from `@realitycollective/xrblocks-uiextensions` unchanged (the XR Blocks scene graph is plain three.js already, so its host had no XR-Blocks-specific code in it), plus a new `pointerBridgeFactory` option on `UixWindowHost` so a platform's own interaction source can drive the same host - `@realitycollective/xrblocks-uiextensions`'s `UixWindowHost` is now a thin subclass that supplies `XrBlocksPointerBridge` in place of this package's own bridge, and every other export keeps its old import path through a re-export. New in this package: `ScenePointerBridge` (`pointer-bridge.ts`), which resolves a hit-tested ray, a proximity-tested grab or touch, into the same `pointerdown`/`pointerup`/`click`/`pointerenter`/`pointerleave` events and `TouchPress` samples `XrBlocksPointerBridge` produces from XR Blocks' own callbacks; `connectWebXrPointerInput` (`webxr-input.ts`), which wires that bridge straight to a live WebXR session through `renderer.xr` - `selectstart`/`selectend`/`squeezestart`/`squeezeend` on three's own controller objects for ray and near/grab, and a per-frame `index-finger-tip` joint poll for touch - with no engine SDK beyond three.js itself; and `connectUIExtensions` (`setup.ts`), the package's one setup entry point, mirroring `xrblocks-uiextensions`'s own `connectUIExtensions` for a scene with no XR Blocks Script. `webxrRayInputAccess` (`ray-input.ts`) reads a title-bar ray drag's live ray from three's own `getController(i)` objects, so a drag rides the ray at a fixed grab distance (`beginDrag`/`dragPosition`), the same laser-distance math every other platform uses. Runs the shared `windowHostContractCases`, `sceneTargetContractCases` and `uixElementContractCases`, a core-parity suite (follow equals `stepFollow`, region and hand-menu defaults, title default, control upgrades), and a rule-by-rule suite mirroring `xrblocks-uiextensions/test/pointer-bridge.test.ts` for touch press, controller poke, ray click on release, hover, hold-to-drag with a per-window `dragDelay`, near drag, laser-distance ray drag, billboard while dragging, drop capture and focus bias including a docked window. `CursorVisual` (`cursor-visual.ts`) closes `ui/pointer-cursor` for this binding: a disc drawn at each ray's current hit on a panel, oriented to the hit surface (or the ray's own orientation with no surface normal to read), shown and hidden only by whether the ray currently hits something - never by hover or focus state. XR Blocks is excused from this rule (its SDK draws its own reticle with no seam to observe) but plain three.js owns rendering, so nothing drew one here until now. `ScenePointerBridge.rayCast` reports the world-space hit point and surface normal a cursor needs, alongside the existing `rayHit` (now a thin projection of it); `connectWebXrPointerInput` draws one `CursorVisual` per controller slot from the same per-frame ray cast hover already runs, given a `scene` (`connectUIExtensions` passes its own automatically).
|
|
12
15
|
- `@realitycollective/webxr-uiextensions` - `core/cursor.ts`'s `cursorPlacement` and `DEFAULT_CURSOR_OFFSET` (0.004 m): the one placement rule `ui/pointer-cursor` states as pure logic - a cursor disc's hit point nudged a fixed distance off the surface along its own facing, so it never z-fights that surface, restated from IWSDK's `@iwsdk/xr-input` `CursorVisual.updateFromIntersection`'s `zOffset`. The orientation itself reuses the core's existing `faceViewer`/`rotate` primitives rather than adding a new one. `@realitycollective/threejs-uiextensions`'s `CursorVisual` is the first binding to run it.
|
|
13
16
|
- `stepFollow()`, the follow rule every following window and region uses, as pure logic in the core: IWSDK's `FollowSystem` in its `PivotY` behaviour restated step for step, with `enterFollow()`, `followOffsetFromPose()`, `resolveFollow()`, the yaw helpers (`yawOf`, `yawQuaternion`, `rotateByYaw`, `yawToward`, `strictFollowTarget`) and the defaults `DEFAULT_WINDOW_FOLLOW` (offset `[0, -0.15, -1.2]`, speed 3, tolerance 0.35 m, 30 degrees) and `DEFAULT_REGION_FOLLOW` (IWSDK's `Follower` defaults: offset `[0, -0.2, -1.4]`, speed 1, tolerance 0.4 m). A new IWSDK test drives IWSDK's own `FollowSystem` headlessly beside `stepFollow` over the same head motion and requires the same position and facing every frame, so the core rule cannot drift from the reference.
|
|
@@ -306,5 +306,7 @@ export declare class UIDockSystem extends UIDockSystem_base {
|
|
|
306
306
|
private yawQuaternion;
|
|
307
307
|
private yawEuler;
|
|
308
308
|
private addFollower;
|
|
309
|
+
/** `manager.setFollow` after spawn: the live Follower takes the new offset and tuning at once. */
|
|
310
|
+
private applyFollowChange;
|
|
309
311
|
}
|
|
310
312
|
export {};
|
|
@@ -30,6 +30,7 @@ export class UIDockSystem extends createSystem({
|
|
|
30
30
|
parentQuaternion = new Quaternion();
|
|
31
31
|
init() {
|
|
32
32
|
this.manager = windowManagerFor(this.world);
|
|
33
|
+
this.cleanupFuncs.push(this.manager.events.on('followChanged', ({ window }) => this.applyFollowChange(window.id)));
|
|
33
34
|
}
|
|
34
35
|
update() {
|
|
35
36
|
let hands;
|
|
@@ -174,12 +175,13 @@ export class UIDockSystem extends createSystem({
|
|
|
174
175
|
yawQuaternion = new Quaternion();
|
|
175
176
|
yawEuler = new Euler();
|
|
176
177
|
addFollower(entity, options = {}) {
|
|
178
|
+
// The record's follow settings (`manager.setFollow` may have changed them
|
|
179
|
+
// since spawn); the component's own values only before a record exists.
|
|
180
|
+
const record = this.manager.get(entity.getValue(UIWindow, 'windowId'));
|
|
177
181
|
const configured = entity.getVectorView(UIWindow, 'followOffset');
|
|
178
|
-
let offset =
|
|
179
|
-
|
|
180
|
-
configured[1] ?? 0,
|
|
181
|
-
configured[2] ?? 0,
|
|
182
|
-
];
|
|
182
|
+
let offset = record
|
|
183
|
+
? [record.follow.offset[0], record.follow.offset[1], record.follow.offset[2]]
|
|
184
|
+
: [configured[0] ?? 0, configured[1] ?? 0, configured[2] ?? 0];
|
|
183
185
|
const object = entity.object3D;
|
|
184
186
|
if (options.fromCurrentPose && object) {
|
|
185
187
|
// Current window position in the viewer's yaw-local frame (matching
|
|
@@ -205,9 +207,25 @@ export class UIDockSystem extends createSystem({
|
|
|
205
207
|
target: this.camera,
|
|
206
208
|
offsetPosition: offset,
|
|
207
209
|
behavior: FollowBehavior.PivotY,
|
|
208
|
-
speed: entity.getValue(UIWindow, 'followSpeed'),
|
|
209
|
-
tolerance: entity.getValue(UIWindow, 'followTolerance'),
|
|
210
|
+
speed: record ? record.follow.speed : entity.getValue(UIWindow, 'followSpeed'),
|
|
211
|
+
tolerance: record ? record.follow.tolerance : entity.getValue(UIWindow, 'followTolerance'),
|
|
210
212
|
});
|
|
211
213
|
}
|
|
214
|
+
/** `manager.setFollow` after spawn: the live Follower takes the new offset and tuning at once. */
|
|
215
|
+
applyFollowChange(windowId) {
|
|
216
|
+
const record = this.manager.get(windowId);
|
|
217
|
+
if (!record)
|
|
218
|
+
return;
|
|
219
|
+
for (const entity of this.queries.windows.entities) {
|
|
220
|
+
if (entity.getValue(UIWindow, 'windowId') !== windowId || !entity.hasComponent(Follower))
|
|
221
|
+
continue;
|
|
222
|
+
const offset = entity.getVectorView(Follower, 'offsetPosition');
|
|
223
|
+
offset[0] = record.follow.offset[0];
|
|
224
|
+
offset[1] = record.follow.offset[1];
|
|
225
|
+
offset[2] = record.follow.offset[2];
|
|
226
|
+
entity.setValue(Follower, 'speed', record.follow.speed);
|
|
227
|
+
entity.setValue(Follower, 'tolerance', record.follow.tolerance);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
212
230
|
}
|
|
213
231
|
//# sourceMappingURL=dock-system.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dock-system.js","sourceRoot":"","sources":["../../src/systems/dock-system.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * UIDockSystem - realises dock modes by composing IWSDK components.\n *\n * `body-follow` and `head-locked` are implemented with the IWSDK's own\n * `Follower` / `ScreenSpace` components (reuse, not recreation); this system\n * only plans and applies transitions with the pure dock state machine.\n *\n * `hand-locked` (a hand menu) has no IWSDK component to lean on, so it is\n * placed here each frame: the hand poses come from the player rig's grip\n * spaces (a controller's grip, or the tracked hand), the decision of which\n * hand, whether the palm gate is open and where the panel goes is the core's\n * `evaluateHandMenu`, and the result is written to the entity transform and\n * to `UIWindowState.gateOpen`, which `UIWindowSystem` turns into visibility.\n */\nimport {\n Follower,\n FollowBehavior,\n ScreenSpace,\n type Entity,\n} from '@iwsdk/core';\nimport { createSystem } from '../create-system.js';\nimport { Euler, Quaternion, Vector3, type Object3D } from 'three';\nimport { UIWindow, UIWindowState } from '../components.js';\nimport {\n DockMode,\n evaluateHandMenu,\n isDockMode,\n planTransition,\n recipeFor,\n type DockModeValue,\n type Hand,\n type HandPoses,\n type PoseTuple,\n} from '@realitycollective/webxr-uiextensions';\nimport { faceViewerYaw } from '@realitycollective/webxr-uiextensions';\nimport { windowManagerFor } from '../manager-registry.js';\nimport type { WindowManager } from '@realitycollective/webxr-uiextensions';\n\nexport class UIDockSystem extends createSystem({\n windows: { required: [UIWindow, UIWindowState] },\n}) {\n private manager!: WindowManager;\n private windowPosition = new Vector3();\n private viewerPosition = new Vector3();\n private handPosition = new Vector3();\n private handQuaternion = new Quaternion();\n private parentQuaternion = new Quaternion();\n\n override init(): void {\n this.manager = windowManagerFor(this.world);\n }\n\n override update(): void {\n let hands: HandPoses | undefined;\n for (const entity of this.queries.windows.entities) {\n const requested = entity.getValue(UIWindow, 'dockMode') as DockModeValue;\n const applied = entity.getValue(UIWindowState, 'appliedDockMode') as string;\n if (isDockMode(requested) && applied !== requested) {\n this.apply(entity, applied, requested);\n }\n if (requested === DockMode.HandLocked) {\n hands ??= this.readHands();\n this.placeOnHand(entity, hands);\n }\n }\n }\n\n /** This frame's tracked hands, in the core's hand frame (WebXR grip convention). */\n private readHands(): HandPoses {\n const poses: HandPoses = {};\n const xr = (this.input as typeof this.input | undefined)?.xr;\n const rig = this.player as { gripSpaces?: Record<Hand, Object3D> } | undefined;\n if (!xr || !rig?.gripSpaces) {\n return poses;\n }\n for (const hand of ['left', 'right'] as const) {\n if (!xr.getPrimaryInputSource(hand)) {\n continue; // nothing tracked on that side this frame\n }\n const space = rig.gripSpaces[hand];\n space.getWorldPosition(this.handPosition);\n space.getWorldQuaternion(this.handQuaternion);\n poses[hand] = {\n position: [this.handPosition.x, this.handPosition.y, this.handPosition.z],\n quaternion: [\n this.handQuaternion.x,\n this.handQuaternion.y,\n this.handQuaternion.z,\n this.handQuaternion.w,\n ],\n };\n }\n return poses;\n }\n\n private placeOnHand(entity: Entity, hands: HandPoses): void {\n const id = entity.getValue(UIWindow, 'windowId') as string;\n const record = this.manager.get(id);\n const object = entity.object3D;\n if (!record || !object) {\n return;\n }\n this.camera.getWorldPosition(this.viewerPosition);\n const placement = evaluateHandMenu(\n hands,\n [this.viewerPosition.x, this.viewerPosition.y, this.viewerPosition.z],\n record.handMenu,\n );\n if (Boolean(entity.getValue(UIWindowState, 'gateOpen')) !== placement.visible) {\n entity.setValue(UIWindowState, 'gateOpen', placement.visible);\n }\n if (placement.pose) {\n this.applyWorldPose(object, placement.pose);\n }\n }\n\n /** Write a world pose onto an object whatever it is parented to. */\n private applyWorldPose(object: Object3D, pose: PoseTuple): void {\n this.windowPosition.set(pose.position[0], pose.position[1], pose.position[2]);\n this.handQuaternion.set(\n pose.quaternion[0],\n pose.quaternion[1],\n pose.quaternion[2],\n pose.quaternion[3],\n );\n const parent = object.parent;\n if (parent) {\n parent.worldToLocal(this.windowPosition);\n parent.getWorldQuaternion(this.parentQuaternion).invert();\n this.handQuaternion.premultiply(this.parentQuaternion);\n }\n object.position.copy(this.windowPosition);\n object.quaternion.copy(this.handQuaternion);\n }\n\n private apply(entity: Entity, applied: string, requested: DockModeValue): void {\n if (isDockMode(applied)) {\n const plan = planTransition(applied, requested);\n if (!plan) {\n return;\n }\n if (plan.removeFollower && entity.hasComponent(Follower)) {\n entity.removeComponent(Follower);\n }\n if (plan.removeFollower && requested === DockMode.WorldLocked) {\n // Pinning in place: leave the window facing the user at the spot it\n // was pinned, instead of freezing whatever lagging follow rotation\n // it happened to have this frame.\n this.faceViewer(entity);\n }\n if (plan.removeScreenSpace && entity.hasComponent(ScreenSpace)) {\n entity.removeComponent(ScreenSpace);\n }\n if (plan.removeHandAnchor) {\n // Off the hand: the gate no longer applies, and the window stays\n // where the hand left it, facing the viewer.\n entity.setValue(UIWindowState, 'gateOpen', true);\n this.faceViewer(entity);\n }\n if (plan.addFollower) {\n // Unpinning: keep the window where the user left it, expressed\n // relative to their head, instead of snapping to the default offset.\n this.addFollower(entity, { fromCurrentPose: true });\n }\n if (plan.addScreenSpace) {\n entity.addComponent(ScreenSpace);\n }\n if (plan.snap && entity.hasComponent(Follower)) {\n entity.setValue(Follower, 'needsPositionSync', true);\n }\n } else {\n // First application after adoption: build the requested recipe from\n // scratch (the entity carries no dock components we own yet).\n const recipe = recipeFor(requested);\n if (recipe.follower && !entity.hasComponent(Follower)) {\n this.addFollower(entity);\n }\n if (!recipe.follower && entity.hasComponent(Follower)) {\n entity.removeComponent(Follower);\n }\n if (recipe.screenSpace && !entity.hasComponent(ScreenSpace)) {\n entity.addComponent(ScreenSpace);\n }\n if (!recipe.screenSpace && entity.hasComponent(ScreenSpace)) {\n entity.removeComponent(ScreenSpace);\n }\n }\n\n entity.setValue(UIWindowState, 'appliedDockMode', requested);\n\n const id = entity.getValue(UIWindow, 'windowId') as string;\n if (id && this.manager.has(id)) {\n this.manager.setDockMode(id, requested);\n }\n }\n\n private faceViewer(entity: Entity): void {\n const object = entity.object3D;\n if (!object) {\n return;\n }\n object.getWorldPosition(this.windowPosition);\n this.camera.getWorldPosition(this.viewerPosition);\n const yaw = faceViewerYaw(\n [this.windowPosition.x, this.windowPosition.y, this.windowPosition.z],\n [this.viewerPosition.x, this.viewerPosition.y, this.viewerPosition.z],\n object.rotation.y,\n );\n object.rotation.set(0, yaw, 0);\n }\n\n private offsetHelper = new Vector3();\n private yawQuaternion = new Quaternion();\n private yawEuler = new Euler();\n\n private addFollower(entity: Entity, options: { fromCurrentPose?: boolean } = {}): void {\n const configured = entity.getVectorView(UIWindow, 'followOffset');\n let offset: [number, number, number] = [\n configured[0] ?? 0,\n configured[1] ?? 0,\n configured[2] ?? 0,\n ];\n\n const object = entity.object3D;\n if (options.fromCurrentPose && object) {\n // Current window position in the viewer's yaw-local frame (matching\n // how Follower's PivotY applies offsets), so following resumes from\n // the same bearing and distance the window was unpinned at.\n object.getWorldPosition(this.offsetHelper);\n this.camera.getWorldPosition(this.windowPosition);\n this.camera.getWorldQuaternion(this.yawQuaternion);\n this.yawEuler.setFromQuaternion(this.yawQuaternion, 'YXZ');\n this.yawEuler.x = 0;\n this.yawEuler.z = 0;\n this.yawQuaternion.setFromEuler(this.yawEuler).conjugate();\n this.offsetHelper.sub(this.windowPosition).applyQuaternion(this.yawQuaternion);\n // Degenerate (window at the viewer): keep the configured offset.\n if (this.offsetHelper.lengthSq() > 0.01) {\n offset = [this.offsetHelper.x, this.offsetHelper.y, this.offsetHelper.z];\n }\n }\n\n entity.addComponent(Follower, {\n // The camera, not player.head: three.js syncs the camera to the\n // headset pose in-session, while the head rig sits at the origin\n // outside XR (desktop) - following it would park windows at the floor.\n target: this.camera,\n offsetPosition: offset,\n behavior: FollowBehavior.PivotY,\n speed: entity.getValue(UIWindow, 'followSpeed') as number,\n tolerance: entity.getValue(UIWindow, 'followTolerance') as number,\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dock-system.js","sourceRoot":"","sources":["../../src/systems/dock-system.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EACL,QAAQ,EACR,cAAc,EACd,WAAW,GAEZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAiB,MAAM,OAAO,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,QAAQ,EACR,gBAAgB,EAChB,UAAU,EACV,cAAc,EACd,SAAS,GAKV,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,MAAM,OAAO,YAAa,SAAQ,YAAY,CAAC;IAC7C,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,EAAE;CACjD,CAAC;IACQ,OAAO,CAAiB;IACxB,cAAc,GAAG,IAAI,OAAO,EAAE,CAAC;IAC/B,cAAc,GAAG,IAAI,OAAO,EAAE,CAAC;IAC/B,YAAY,GAAG,IAAI,OAAO,EAAE,CAAC;IAC7B,cAAc,GAAG,IAAI,UAAU,EAAE,CAAC;IAClC,gBAAgB,GAAG,IAAI,UAAU,EAAE,CAAC;IAEnC,IAAI;QACX,IAAI,CAAC,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACrH,CAAC;IAEQ,MAAM;QACb,IAAI,KAA4B,CAAC;QACjC,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACnD,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAkB,CAAC;YACzE,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,iBAAiB,CAAW,CAAC;YAC5E,IAAI,UAAU,CAAC,SAAS,CAAC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBACnD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;YACzC,CAAC;YACD,IAAI,SAAS,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC;gBACtC,KAAK,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;gBAC3B,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IAED,oFAAoF;IAC5E,SAAS;QACf,MAAM,KAAK,GAAc,EAAE,CAAC;QAC5B,MAAM,EAAE,GAAI,IAAI,CAAC,KAAuC,EAAE,EAAE,CAAC;QAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,MAA6D,CAAC;QAC/E,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,CAAC;YAC5B,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO,CAAU,EAAE,CAAC;YAC9C,IAAI,CAAC,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpC,SAAS,CAAC,0CAA0C;YACtD,CAAC;YACD,MAAM,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACnC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC1C,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC9C,KAAK,CAAC,IAAI,CAAC,GAAG;gBACZ,QAAQ,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;gBACzE,UAAU,EAAE;oBACV,IAAI,CAAC,cAAc,CAAC,CAAC;oBACrB,IAAI,CAAC,cAAc,CAAC,CAAC;oBACrB,IAAI,CAAC,cAAc,CAAC,CAAC;oBACrB,IAAI,CAAC,cAAc,CAAC,CAAC;iBACtB;aACF,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,WAAW,CAAC,MAAc,EAAE,KAAgB;QAClD,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAW,CAAC;QAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC/B,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,gBAAgB,CAChC,KAAK,EACL,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EACrE,MAAM,CAAC,QAAQ,CAChB,CAAC;QACF,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC;YAC9E,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC;YACnB,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,oEAAoE;IAC5D,cAAc,CAAC,MAAgB,EAAE,IAAe;QACtD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9E,IAAI,CAAC,cAAc,CAAC,GAAG,CACrB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAClB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAClB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAClB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CACnB,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC7B,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACzC,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,MAAM,EAAE,CAAC;YAC1D,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC1C,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC9C,CAAC;IAEO,KAAK,CAAC,MAAc,EAAE,OAAe,EAAE,SAAwB;QACrE,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAChD,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YACD,IAAI,IAAI,CAAC,cAAc,IAAI,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACzD,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;YACnC,CAAC;YACD,IAAI,IAAI,CAAC,cAAc,IAAI,SAAS,KAAK,QAAQ,CAAC,WAAW,EAAE,CAAC;gBAC9D,oEAAoE;gBACpE,mEAAmE;gBACnE,kCAAkC;gBAClC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC1B,CAAC;YACD,IAAI,IAAI,CAAC,iBAAiB,IAAI,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC/D,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;YACtC,CAAC;YACD,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC1B,iEAAiE;gBACjE,6CAA6C;gBAC7C,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;gBACjD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC1B,CAAC;YACD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,+DAA+D;gBAC/D,qEAAqE;gBACrE,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;YACtD,CAAC;YACD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;gBACxB,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;YACnC,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC/C,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,EAAE,IAAI,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,oEAAoE;YACpE,8DAA8D;YAC9D,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;YACpC,IAAI,MAAM,CAAC,QAAQ,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtD,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YAC3B,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtD,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;YACnC,CAAC;YACD,IAAI,MAAM,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC5D,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;YACnC,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC5D,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;QAED,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE,iBAAiB,EAAE,SAAS,CAAC,CAAC;QAE7D,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAW,CAAC;QAC3D,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAEO,UAAU,CAAC,MAAc;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO;QACT,CAAC;QACD,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,aAAa,CACvB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EACrE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EACrE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAClB,CAAC;QACF,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IACjC,CAAC;IAEO,YAAY,GAAG,IAAI,OAAO,EAAE,CAAC;IAC7B,aAAa,GAAG,IAAI,UAAU,EAAE,CAAC;IACjC,QAAQ,GAAG,IAAI,KAAK,EAAE,CAAC;IAEvB,WAAW,CAAC,MAAc,EAAE,UAAyC,EAAE;QAC7E,0EAA0E;QAC1E,wEAAwE;QACxE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAW,CAAC,CAAC;QACjF,MAAM,UAAU,GAAG,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAClE,IAAI,MAAM,GAA6B,MAAM;YAC3C,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC7E,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAEjE,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC;QAC/B,IAAI,OAAO,CAAC,eAAe,IAAI,MAAM,EAAE,CAAC;YACtC,oEAAoE;YACpE,oEAAoE;YACpE,4DAA4D;YAC5D,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC3C,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACnD,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;YAC3D,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;YACpB,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;YACpB,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,SAAS,EAAE,CAAC;YAC3D,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC/E,iEAAiE;YACjE,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,GAAG,IAAI,EAAE,CAAC;gBACxC,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC;QAED,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE;YAC5B,gEAAgE;YAChE,iEAAiE;YACjE,uEAAuE;YACvE,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,cAAc,EAAE,MAAM;YACtB,QAAQ,EAAE,cAAc,CAAC,MAAM;YAC/B,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAY;YAC1F,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAY;SACvG,CAAC,CAAC;IACL,CAAC;IAED,kGAAkG;IAC1F,iBAAiB,CAAC,QAAgB;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACnD,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC;gBAAE,SAAS;YACnG,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;YAChE,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACpC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACpC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACpC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACxD,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * UIDockSystem - realises dock modes by composing IWSDK components.\n *\n * `body-follow` and `head-locked` are implemented with the IWSDK's own\n * `Follower` / `ScreenSpace` components (reuse, not recreation); this system\n * only plans and applies transitions with the pure dock state machine.\n *\n * `hand-locked` (a hand menu) has no IWSDK component to lean on, so it is\n * placed here each frame: the hand poses come from the player rig's grip\n * spaces (a controller's grip, or the tracked hand), the decision of which\n * hand, whether the palm gate is open and where the panel goes is the core's\n * `evaluateHandMenu`, and the result is written to the entity transform and\n * to `UIWindowState.gateOpen`, which `UIWindowSystem` turns into visibility.\n */\nimport {\n Follower,\n FollowBehavior,\n ScreenSpace,\n type Entity,\n} from '@iwsdk/core';\nimport { createSystem } from '../create-system.js';\nimport { Euler, Quaternion, Vector3, type Object3D } from 'three';\nimport { UIWindow, UIWindowState } from '../components.js';\nimport {\n DockMode,\n evaluateHandMenu,\n isDockMode,\n planTransition,\n recipeFor,\n type DockModeValue,\n type Hand,\n type HandPoses,\n type PoseTuple,\n} from '@realitycollective/webxr-uiextensions';\nimport { faceViewerYaw } from '@realitycollective/webxr-uiextensions';\nimport { windowManagerFor } from '../manager-registry.js';\nimport type { WindowManager } from '@realitycollective/webxr-uiextensions';\n\nexport class UIDockSystem extends createSystem({\n windows: { required: [UIWindow, UIWindowState] },\n}) {\n private manager!: WindowManager;\n private windowPosition = new Vector3();\n private viewerPosition = new Vector3();\n private handPosition = new Vector3();\n private handQuaternion = new Quaternion();\n private parentQuaternion = new Quaternion();\n\n override init(): void {\n this.manager = windowManagerFor(this.world);\n this.cleanupFuncs.push(this.manager.events.on('followChanged', ({ window }) => this.applyFollowChange(window.id)));\n }\n\n override update(): void {\n let hands: HandPoses | undefined;\n for (const entity of this.queries.windows.entities) {\n const requested = entity.getValue(UIWindow, 'dockMode') as DockModeValue;\n const applied = entity.getValue(UIWindowState, 'appliedDockMode') as string;\n if (isDockMode(requested) && applied !== requested) {\n this.apply(entity, applied, requested);\n }\n if (requested === DockMode.HandLocked) {\n hands ??= this.readHands();\n this.placeOnHand(entity, hands);\n }\n }\n }\n\n /** This frame's tracked hands, in the core's hand frame (WebXR grip convention). */\n private readHands(): HandPoses {\n const poses: HandPoses = {};\n const xr = (this.input as typeof this.input | undefined)?.xr;\n const rig = this.player as { gripSpaces?: Record<Hand, Object3D> } | undefined;\n if (!xr || !rig?.gripSpaces) {\n return poses;\n }\n for (const hand of ['left', 'right'] as const) {\n if (!xr.getPrimaryInputSource(hand)) {\n continue; // nothing tracked on that side this frame\n }\n const space = rig.gripSpaces[hand];\n space.getWorldPosition(this.handPosition);\n space.getWorldQuaternion(this.handQuaternion);\n poses[hand] = {\n position: [this.handPosition.x, this.handPosition.y, this.handPosition.z],\n quaternion: [\n this.handQuaternion.x,\n this.handQuaternion.y,\n this.handQuaternion.z,\n this.handQuaternion.w,\n ],\n };\n }\n return poses;\n }\n\n private placeOnHand(entity: Entity, hands: HandPoses): void {\n const id = entity.getValue(UIWindow, 'windowId') as string;\n const record = this.manager.get(id);\n const object = entity.object3D;\n if (!record || !object) {\n return;\n }\n this.camera.getWorldPosition(this.viewerPosition);\n const placement = evaluateHandMenu(\n hands,\n [this.viewerPosition.x, this.viewerPosition.y, this.viewerPosition.z],\n record.handMenu,\n );\n if (Boolean(entity.getValue(UIWindowState, 'gateOpen')) !== placement.visible) {\n entity.setValue(UIWindowState, 'gateOpen', placement.visible);\n }\n if (placement.pose) {\n this.applyWorldPose(object, placement.pose);\n }\n }\n\n /** Write a world pose onto an object whatever it is parented to. */\n private applyWorldPose(object: Object3D, pose: PoseTuple): void {\n this.windowPosition.set(pose.position[0], pose.position[1], pose.position[2]);\n this.handQuaternion.set(\n pose.quaternion[0],\n pose.quaternion[1],\n pose.quaternion[2],\n pose.quaternion[3],\n );\n const parent = object.parent;\n if (parent) {\n parent.worldToLocal(this.windowPosition);\n parent.getWorldQuaternion(this.parentQuaternion).invert();\n this.handQuaternion.premultiply(this.parentQuaternion);\n }\n object.position.copy(this.windowPosition);\n object.quaternion.copy(this.handQuaternion);\n }\n\n private apply(entity: Entity, applied: string, requested: DockModeValue): void {\n if (isDockMode(applied)) {\n const plan = planTransition(applied, requested);\n if (!plan) {\n return;\n }\n if (plan.removeFollower && entity.hasComponent(Follower)) {\n entity.removeComponent(Follower);\n }\n if (plan.removeFollower && requested === DockMode.WorldLocked) {\n // Pinning in place: leave the window facing the user at the spot it\n // was pinned, instead of freezing whatever lagging follow rotation\n // it happened to have this frame.\n this.faceViewer(entity);\n }\n if (plan.removeScreenSpace && entity.hasComponent(ScreenSpace)) {\n entity.removeComponent(ScreenSpace);\n }\n if (plan.removeHandAnchor) {\n // Off the hand: the gate no longer applies, and the window stays\n // where the hand left it, facing the viewer.\n entity.setValue(UIWindowState, 'gateOpen', true);\n this.faceViewer(entity);\n }\n if (plan.addFollower) {\n // Unpinning: keep the window where the user left it, expressed\n // relative to their head, instead of snapping to the default offset.\n this.addFollower(entity, { fromCurrentPose: true });\n }\n if (plan.addScreenSpace) {\n entity.addComponent(ScreenSpace);\n }\n if (plan.snap && entity.hasComponent(Follower)) {\n entity.setValue(Follower, 'needsPositionSync', true);\n }\n } else {\n // First application after adoption: build the requested recipe from\n // scratch (the entity carries no dock components we own yet).\n const recipe = recipeFor(requested);\n if (recipe.follower && !entity.hasComponent(Follower)) {\n this.addFollower(entity);\n }\n if (!recipe.follower && entity.hasComponent(Follower)) {\n entity.removeComponent(Follower);\n }\n if (recipe.screenSpace && !entity.hasComponent(ScreenSpace)) {\n entity.addComponent(ScreenSpace);\n }\n if (!recipe.screenSpace && entity.hasComponent(ScreenSpace)) {\n entity.removeComponent(ScreenSpace);\n }\n }\n\n entity.setValue(UIWindowState, 'appliedDockMode', requested);\n\n const id = entity.getValue(UIWindow, 'windowId') as string;\n if (id && this.manager.has(id)) {\n this.manager.setDockMode(id, requested);\n }\n }\n\n private faceViewer(entity: Entity): void {\n const object = entity.object3D;\n if (!object) {\n return;\n }\n object.getWorldPosition(this.windowPosition);\n this.camera.getWorldPosition(this.viewerPosition);\n const yaw = faceViewerYaw(\n [this.windowPosition.x, this.windowPosition.y, this.windowPosition.z],\n [this.viewerPosition.x, this.viewerPosition.y, this.viewerPosition.z],\n object.rotation.y,\n );\n object.rotation.set(0, yaw, 0);\n }\n\n private offsetHelper = new Vector3();\n private yawQuaternion = new Quaternion();\n private yawEuler = new Euler();\n\n private addFollower(entity: Entity, options: { fromCurrentPose?: boolean } = {}): void {\n // The record's follow settings (`manager.setFollow` may have changed them\n // since spawn); the component's own values only before a record exists.\n const record = this.manager.get(entity.getValue(UIWindow, 'windowId') as string);\n const configured = entity.getVectorView(UIWindow, 'followOffset');\n let offset: [number, number, number] = record\n ? [record.follow.offset[0], record.follow.offset[1], record.follow.offset[2]]\n : [configured[0] ?? 0, configured[1] ?? 0, configured[2] ?? 0];\n\n const object = entity.object3D;\n if (options.fromCurrentPose && object) {\n // Current window position in the viewer's yaw-local frame (matching\n // how Follower's PivotY applies offsets), so following resumes from\n // the same bearing and distance the window was unpinned at.\n object.getWorldPosition(this.offsetHelper);\n this.camera.getWorldPosition(this.windowPosition);\n this.camera.getWorldQuaternion(this.yawQuaternion);\n this.yawEuler.setFromQuaternion(this.yawQuaternion, 'YXZ');\n this.yawEuler.x = 0;\n this.yawEuler.z = 0;\n this.yawQuaternion.setFromEuler(this.yawEuler).conjugate();\n this.offsetHelper.sub(this.windowPosition).applyQuaternion(this.yawQuaternion);\n // Degenerate (window at the viewer): keep the configured offset.\n if (this.offsetHelper.lengthSq() > 0.01) {\n offset = [this.offsetHelper.x, this.offsetHelper.y, this.offsetHelper.z];\n }\n }\n\n entity.addComponent(Follower, {\n // The camera, not player.head: three.js syncs the camera to the\n // headset pose in-session, while the head rig sits at the origin\n // outside XR (desktop) - following it would park windows at the floor.\n target: this.camera,\n offsetPosition: offset,\n behavior: FollowBehavior.PivotY,\n speed: record ? record.follow.speed : (entity.getValue(UIWindow, 'followSpeed') as number),\n tolerance: record ? record.follow.tolerance : (entity.getValue(UIWindow, 'followTolerance') as number),\n });\n }\n\n /** `manager.setFollow` after spawn: the live Follower takes the new offset and tuning at once. */\n private applyFollowChange(windowId: string): void {\n const record = this.manager.get(windowId);\n if (!record) return;\n for (const entity of this.queries.windows.entities) {\n if (entity.getValue(UIWindow, 'windowId') !== windowId || !entity.hasComponent(Follower)) continue;\n const offset = entity.getVectorView(Follower, 'offsetPosition');\n offset[0] = record.follow.offset[0];\n offset[1] = record.follow.offset[1];\n offset[2] = record.follow.offset[2];\n entity.setValue(Follower, 'speed', record.follow.speed);\n entity.setValue(Follower, 'tolerance', record.follow.tolerance);\n }\n }\n}\n"]}
|
|
@@ -105,12 +105,18 @@ export class UIWindowSystem extends createSystem({
|
|
|
105
105
|
: '';
|
|
106
106
|
this.entitiesById.set(id, entity);
|
|
107
107
|
if (!this.manager.has(id)) {
|
|
108
|
+
const followOffset = entity.getVectorView(UIWindow, 'followOffset');
|
|
108
109
|
this.manager.open(id, {
|
|
109
110
|
title,
|
|
110
111
|
dockMode,
|
|
111
112
|
...(region ? { region } : {}),
|
|
112
113
|
chrome: this.chromeFlagsOf(entity),
|
|
113
114
|
handMenu: this.handMenuOf(entity),
|
|
115
|
+
follow: {
|
|
116
|
+
offset: [followOffset[0] ?? 0, followOffset[1] ?? 0, followOffset[2] ?? 0],
|
|
117
|
+
speed: entity.getValue(UIWindow, 'followSpeed'),
|
|
118
|
+
tolerance: entity.getValue(UIWindow, 'followTolerance'),
|
|
119
|
+
},
|
|
114
120
|
});
|
|
115
121
|
}
|
|
116
122
|
this.wireChrome(entity, id, title);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"window-system.js","sourceRoot":"","sources":["../../src/systems/window-system.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * UIWindowSystem - wires window chrome, keeps the `WindowManager` in sync\n * with entities, and applies every manager event to the ECS: focus\n * ordering, minimize, hide/show, region docking, return-home, chrome\n * enablement and close.\n *\n * The manager is the API app code drives (a hand menu calls\n * `manager.hide(id)` or `manager.dockTo(id, region)`); this system is where\n * those calls become entity changes. The reverse direction is kept in step\n * too: a title-bar drag that docks a window, or a dock-mode change applied\n * by `UIDockSystem`, is written back into the record, so the record is\n * always what the scene shows.\n *\n * Reuse over recreation: the panel itself is loaded/rendered by the IWSDK's\n * `PanelUISystem`; this system only discovers the chrome elements by their\n * well-known ids and drives them.\n */\nimport {\n PanelDocument,\n PanelUI,\n PokeInteractable,\n RayInteractable,\n UIKitDocument,\n type Entity,\n} from '@iwsdk/core';\nimport { createSystem } from '../create-system.js';\nimport { Vector3 } from 'three';\nimport { UIDockedTo, UIWindow, UIWindowState } from '../components.js';\nimport { WINDOW_CHROME_IDS } from '@realitycollective/webxr-uiextensions';\nimport { windowManagerFor } from '../manager-registry.js';\nimport {\n minimizeLabelFor,\n pinLabelFor,\n type HandMenuOptions,\n type WindowChrome,\n type WindowManager,\n type WindowRecord,\n} from '@realitycollective/webxr-uiextensions';\nimport { DockMode, isDockMode, type DockModeValue } from '@realitycollective/webxr-uiextensions';\n\ntype UikitElement = {\n addEventListener: (type: string, listener: (event?: unknown) => void) => void;\n setProperties: (props: Record<string, unknown>) => void;\n};\n\n/** Which IWSDK interaction tags were stripped while not presented, so only those come back. */\ninterface HiddenTags {\n ray: boolean;\n poke: boolean;\n}\n\nlet autoId = 0;\n\nexport class UIWindowSystem extends createSystem({\n pendingWindows: {\n required: [UIWindow, PanelUI, PanelDocument],\n excluded: [UIWindowState],\n },\n windows: { required: [UIWindow, UIWindowState, PanelDocument] },\n}) {\n private manager!: WindowManager;\n private entitiesById = new Map<string, Entity>();\n private hiddenTags = new Map<string, HiddenTags>();\n private localCamera = new Vector3();\n\n override init(): void {\n this.manager = windowManagerFor(this.world);\n\n this.cleanupFuncs.push(\n this.queries.pendingWindows.subscribe('qualify', (entity) => {\n this.adoptWindow(entity);\n }),\n this.queries.windows.subscribe('disqualify', (entity) => {\n this.releaseWindow(entity);\n }),\n this.manager.events.on('closed', ({ id }) => this.destroyWindow(id)),\n this.manager.events.on('minimized', ({ id }) => this.applyMinimized(id, true)),\n this.manager.events.on('restored', ({ id }) => this.applyMinimized(id, false)),\n this.manager.events.on('minimized', (record) => this.syncMinimizeLabel(record)),\n this.manager.events.on('restored', (record) => this.syncMinimizeLabel(record)),\n this.manager.events.on('hidden', ({ id }) => this.reconcilePresentation(id)),\n this.manager.events.on('shown', ({ id }) => this.reconcilePresentation(id)),\n this.manager.events.on('dockChanged', ({ window }) => {\n const entity = this.entitiesById.get(window.id);\n if (entity && entity.getValue(UIWindow, 'dockMode') !== window.dockMode) {\n entity.setValue(UIWindow, 'dockMode', window.dockMode);\n }\n this.syncPinLabel(window);\n }),\n this.manager.events.on('regionChanged', ({ window }) => this.applyRegion(window)),\n this.manager.events.on('returnHome', ({ id }) => {\n const entity = this.entitiesById.get(id);\n if (entity) {\n this.returnHome(entity);\n }\n }),\n this.manager.events.on('chromeChanged', ({ window }) => this.applyChrome(window)),\n this.manager.events.on('handMenuChanged', ({ window }) => this.applyHandMenu(window)),\n this.manager.events.on('dragStarted', (window) => this.syncPinLabel(window)),\n this.manager.events.on('dragEnded', (window) => this.syncPinLabel(window)),\n );\n }\n\n override update(): void {\n // Focus bias: nudge each window's document toward the viewer by a small\n // amount inversely related to focus depth, so overlapping windows resolve\n // in focus order. Computed in entity-local space so it holds for any\n // window orientation.\n for (const entity of this.queries.windows.entities) {\n const id = entity.getValue(UIWindow, 'windowId') as string;\n const record = this.manager.get(id);\n if (!record) {\n continue;\n }\n // The palm gate (UIDockSystem) and hide() both feed one decision.\n if (!this.reconcilePresentation(id)) {\n continue;\n }\n const document = this.documentOf(entity);\n const object = entity.object3D;\n if (!document || !object) {\n continue;\n }\n const bias = entity.getValue(UIWindow, 'focusBias') as number;\n const depth = this.manager.orderOf(id);\n const amount = bias * Math.max(0, this.manager.count - 1 - depth);\n if (amount === 0) {\n document.position.set(0, 0, 0);\n continue;\n }\n this.camera.getWorldPosition(this.localCamera);\n object.worldToLocal(this.localCamera);\n if (this.localCamera.lengthSq() === 0) {\n continue;\n }\n document.position.copy(this.localCamera.normalize().multiplyScalar(amount));\n }\n }\n\n entityFor(windowId: string): Entity | undefined {\n return this.entitiesById.get(windowId);\n }\n\n private adoptWindow(entity: Entity): void {\n let id = entity.getValue(UIWindow, 'windowId') as string;\n if (!id) {\n id = `uix-window-${autoId++}`;\n entity.setValue(UIWindow, 'windowId', id);\n }\n const title = entity.getValue(UIWindow, 'title') as string;\n const dockMode = entity.getValue(UIWindow, 'dockMode') as DockModeValue;\n const region = entity.hasComponent(UIDockedTo)\n ? (entity.getValue(UIDockedTo, 'regionId') as string)\n : '';\n this.entitiesById.set(id, entity);\n if (!this.manager.has(id)) {\n this.manager.open(id, {\n title,\n dockMode,\n ...(region ? { region } : {}),\n chrome: this.chromeFlagsOf(entity),\n handMenu: this.handMenuOf(entity),\n });\n }\n this.wireChrome(entity, id, title);\n\n // Snapshot \"home\" so the DOCK button can return the window: the spawn\n // region if it was born docked, otherwise its placement + dock mode.\n const object = entity.object3D;\n entity.addComponent(UIWindowState, {\n chromeWired: true,\n appliedDockMode: '',\n homeDockMode: dockMode,\n homeRegion: region,\n homePosition: object ? [object.position.x, object.position.y, object.position.z] : [0, 0, 0],\n homeYaw: object ? object.rotation.y : 0,\n });\n const record = this.manager.get(id);\n if (record) {\n this.applyChrome(record);\n this.applyHandMenu(record);\n this.syncPinLabel(record);\n this.syncMinimizeLabel(record);\n if (record.minimized) {\n this.applyMinimized(id, true);\n }\n this.reconcilePresentation(id);\n }\n }\n\n /** The hand-menu fields on the component, in the manager's vocabulary. */\n private handMenuOf(entity: Entity): HandMenuOptions {\n const offset = entity.getVectorView(UIWindow, 'handOffset');\n return {\n hand: entity.getValue(UIWindow, 'hand') as HandMenuOptions['hand'],\n anchor: entity.getValue(UIWindow, 'handAnchor') as HandMenuOptions['anchor'],\n anchorDistance: entity.getValue(UIWindow, 'handAnchorDistance') as number,\n offset: [offset[0] ?? 0, offset[1] ?? 0, offset[2] ?? 0],\n palmGate: Boolean(entity.getValue(UIWindow, 'palmGate')),\n palmAngle: entity.getValue(UIWindow, 'palmAngle') as number,\n };\n }\n\n /** Keep the component's hand-menu fields equal to the record. */\n private applyHandMenu(record: Pick<WindowRecord, 'id' | 'handMenu'>): void {\n const entity = this.entitiesById.get(record.id);\n if (!entity) {\n return;\n }\n const { handMenu } = record;\n entity.setValue(UIWindow, 'hand', handMenu.hand);\n entity.setValue(UIWindow, 'handAnchor', handMenu.anchor);\n entity.setValue(UIWindow, 'handAnchorDistance', handMenu.anchorDistance);\n entity.getVectorView(UIWindow, 'handOffset').set(handMenu.offset);\n entity.setValue(UIWindow, 'palmGate', handMenu.palmGate);\n entity.setValue(UIWindow, 'palmAngle', handMenu.palmAngle);\n }\n\n /** Return a window to its home: spawn region, or original placement/mode. */\n returnHome(entity: Entity): void {\n const homeRegion = entity.getValue(UIWindowState, 'homeRegion') as string;\n if (homeRegion) {\n if (\n entity.hasComponent(UIDockedTo) &&\n entity.getValue(UIDockedTo, 'regionId') === homeRegion\n ) {\n return; // already home\n }\n if (entity.hasComponent(UIDockedTo)) {\n entity.removeComponent(UIDockedTo);\n }\n entity.addComponent(UIDockedTo, { regionId: homeRegion });\n return;\n }\n if (entity.hasComponent(UIDockedTo)) {\n entity.removeComponent(UIDockedTo);\n }\n const homeDockMode = entity.getValue(UIWindowState, 'homeDockMode') as string;\n if (isDockMode(homeDockMode)) {\n entity.setValue(UIWindow, 'dockMode', homeDockMode);\n }\n if (homeDockMode === DockMode.WorldLocked) {\n const object = entity.object3D;\n const home = entity.getVectorView(UIWindowState, 'homePosition');\n if (object) {\n object.position.set(home[0] ?? 0, home[1] ?? 0, home[2] ?? 0);\n object.rotation.set(0, entity.getValue(UIWindowState, 'homeYaw') as number, 0);\n }\n }\n // Follow modes re-snap on their own (the dock system syncs the Follower).\n }\n\n /** The chrome flags on the component, in the manager's vocabulary. */\n private chromeFlagsOf(entity: Entity): WindowChrome {\n return {\n close: Boolean(entity.getValue(UIWindow, 'closable')),\n minimize: Boolean(entity.getValue(UIWindow, 'minimizable')),\n pin: Boolean(entity.getValue(UIWindow, 'pinnable')),\n dock: Boolean(entity.getValue(UIWindow, 'dockable')),\n };\n }\n\n /**\n * Show exactly the enabled buttons, and keep the component flags equal to\n * the record so code reading either sees one answer.\n */\n private applyChrome(record: Pick<WindowRecord, 'id' | 'chrome'>): void {\n const entity = this.entitiesById.get(record.id);\n if (!entity) {\n return;\n }\n const { chrome } = record;\n entity.setValue(UIWindow, 'closable', chrome.close);\n entity.setValue(UIWindow, 'minimizable', chrome.minimize);\n entity.setValue(UIWindow, 'pinnable', chrome.pin);\n entity.setValue(UIWindow, 'dockable', chrome.dock);\n const document = this.documentOf(entity);\n if (!document) {\n return;\n }\n const buttons: Array<[string, boolean]> = [\n [WINDOW_CHROME_IDS.close, chrome.close],\n [WINDOW_CHROME_IDS.minimize, chrome.minimize],\n [WINDOW_CHROME_IDS.pin, chrome.pin],\n [WINDOW_CHROME_IDS.dock, chrome.dock],\n ];\n for (const [elementId, enabled] of buttons) {\n (document.getElementById(elementId) as UikitElement | undefined)?.setProperties({\n display: enabled ? 'flex' : 'none',\n });\n }\n }\n\n /** MIN when open, MAX when minimized - the label names the next action. */\n private syncMinimizeLabel(record: Pick<WindowRecord, 'id' | 'minimized'>): void {\n const entity = this.entitiesById.get(record.id);\n const minimize = entity\n ? (this.documentOf(entity)?.getElementById(WINDOW_CHROME_IDS.minimize) as\n | UikitElement\n | undefined)\n : undefined;\n minimize?.setProperties({ text: minimizeLabelFor(record) });\n }\n\n private syncPinLabel(record: Pick<WindowRecord, 'id' | 'dockMode' | 'dragging'>): void {\n const entity = this.entitiesById.get(record.id);\n const pin = entity\n ? (this.documentOf(entity)?.getElementById(WINDOW_CHROME_IDS.pin) as\n | UikitElement\n | undefined)\n : undefined;\n pin?.setProperties({ text: pinLabelFor(record) });\n }\n\n /** The entity went away (destroyed, or lost its panel): close the record. */\n private releaseWindow(entity: Entity): void {\n const id = entity.getValue(UIWindow, 'windowId') as string;\n if (id && this.entitiesById.get(id) === entity) {\n this.entitiesById.delete(id);\n this.hiddenTags.delete(id);\n if (this.manager.has(id)) {\n this.manager.close(id);\n }\n }\n }\n\n /** The record was closed through the manager: tear the entity down. */\n private destroyWindow(id: string): void {\n const entity = this.entitiesById.get(id);\n if (!entity) {\n return; // closed from the entity side; releaseWindow already ran\n }\n this.entitiesById.delete(id);\n this.hiddenTags.delete(id);\n entity.destroy();\n }\n\n /**\n * Draw and expose the window exactly when the record is not hidden AND the\n * palm gate (for a hand menu) is open. Idempotent: `UIWindowState.presented`\n * records what was last applied, so this is cheap to call every frame.\n * Returns whether the window is presented.\n */\n private reconcilePresentation(id: string): boolean {\n const entity = this.entitiesById.get(id);\n const record = this.manager.get(id);\n if (!entity || !record) {\n return false;\n }\n const desired = !record.hidden && Boolean(entity.getValue(UIWindowState, 'gateOpen'));\n if (Boolean(entity.getValue(UIWindowState, 'presented')) === desired) {\n return desired;\n }\n entity.setValue(UIWindowState, 'presented', desired);\n const object = entity.object3D;\n if (object) {\n object.visible = desired;\n }\n if (!desired) {\n // Strip the interaction tags so no pointer can reach the window, and\n // remember which ones were there so only those come back.\n const tags: HiddenTags = {\n ray: entity.hasComponent(RayInteractable),\n poke: entity.hasComponent(PokeInteractable),\n };\n if (tags.ray) {\n entity.removeComponent(RayInteractable);\n }\n if (tags.poke) {\n entity.removeComponent(PokeInteractable);\n }\n this.hiddenTags.set(id, tags);\n return false;\n }\n const tags = this.hiddenTags.get(id);\n this.hiddenTags.delete(id);\n if (tags?.ray && !entity.hasComponent(RayInteractable)) {\n entity.addComponent(RayInteractable);\n }\n if (tags?.poke && !entity.hasComponent(PokeInteractable)) {\n entity.addComponent(PokeInteractable);\n }\n return true;\n }\n\n /** Make the entity's `UIDockedTo` agree with the record's region. */\n private applyRegion(record: Pick<WindowRecord, 'id' | 'region'>): void {\n const entity = this.entitiesById.get(record.id);\n if (!entity) {\n return;\n }\n const current = entity.hasComponent(UIDockedTo)\n ? (entity.getValue(UIDockedTo, 'regionId') as string)\n : undefined;\n if (current === record.region) {\n return; // the ECS already shows it (drag-drop docked, or a write-back)\n }\n if (entity.hasComponent(UIDockedTo)) {\n entity.removeComponent(UIDockedTo);\n }\n if (record.region !== undefined) {\n entity.addComponent(UIDockedTo, { regionId: record.region });\n }\n }\n\n private wireChrome(entity: Entity, id: string, title: string): void {\n const document = this.documentOf(entity);\n if (!document) {\n return;\n }\n\n // IWSDK 0.5 removed PanelUI.maxWidth/maxHeight; world size is now the\n // document's own concern. Fit into the requested box, preserving aspect\n // ratio. Zero means \"leave intrinsic\" so the entity transform owns scale.\n const targetWidth = entity.getValue(UIWindow, 'targetWidth') ?? 0;\n const targetHeight = entity.getValue(UIWindow, 'targetHeight') ?? 0;\n if (targetWidth > 0 && targetHeight > 0) {\n document.setTargetDimensions(targetWidth, targetHeight);\n }\n\n const element = (elementId: string): UikitElement | undefined =>\n document.getElementById(elementId) as UikitElement | undefined;\n\n const titleEl = element(WINDOW_CHROME_IDS.title);\n if (titleEl && title) {\n titleEl.setProperties({ text: title });\n }\n\n // Chrome buttons live on the drag surface - keep their presses out of\n // the title-bar drag handle so clicks never turn into (or arm) drags.\n const swallowPress = (button: UikitElement | undefined): void => {\n button?.addEventListener('pointerdown', (event) => {\n (event as { stopPropagation?: () => void } | undefined)?.stopPropagation?.();\n });\n };\n swallowPress(element(WINDOW_CHROME_IDS.pin));\n swallowPress(element(WINDOW_CHROME_IDS.dock));\n swallowPress(element(WINDOW_CHROME_IDS.minimize));\n swallowPress(element(WINDOW_CHROME_IDS.close));\n\n // Any press anywhere on the window brings it to the front.\n const root = element(WINDOW_CHROME_IDS.window);\n root?.addEventListener('pointerdown', () => {\n if (this.manager.has(id)) {\n this.manager.focus(id);\n }\n });\n\n // Every button is wired once and gated on the record at click time, so\n // enabling a button later (manager.setChrome) needs no rewiring.\n const enabled = (key: keyof WindowChrome): boolean =>\n this.manager.get(id)?.chrome[key] === true;\n\n element(WINDOW_CHROME_IDS.close)?.addEventListener('click', () => {\n if (enabled('close')) {\n // One teardown path: the manager closes, destroyWindow removes the\n // entity, releaseWindow sees the record is already gone.\n this.manager.close(id);\n }\n });\n element(WINDOW_CHROME_IDS.minimize)?.addEventListener('click', () => {\n if (enabled('minimize')) {\n this.manager.toggleMinimized(id);\n }\n });\n element(WINDOW_CHROME_IDS.pin)?.addEventListener('click', () => {\n if (enabled('pin')) {\n this.manager.togglePin(id);\n }\n });\n element(WINDOW_CHROME_IDS.dock)?.addEventListener('click', () => {\n if (enabled('dock')) {\n this.manager.returnHome(id);\n }\n });\n }\n\n private applyMinimized(id: string, minimized: boolean): void {\n const entity = this.entitiesById.get(id);\n const document = entity ? this.documentOf(entity) : undefined;\n const content = document?.getElementById(WINDOW_CHROME_IDS.content) as\n | UikitElement\n | undefined;\n content?.setProperties({ display: minimized ? 'none' : 'flex' });\n }\n\n private documentOf(entity: Entity): UIKitDocument | undefined {\n return PanelDocument.data.document[entity.index] as UIKitDocument | undefined;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"window-system.js","sourceRoot":"","sources":["../../src/systems/window-system.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * UIWindowSystem - wires window chrome, keeps the `WindowManager` in sync\n * with entities, and applies every manager event to the ECS: focus\n * ordering, minimize, hide/show, region docking, return-home, chrome\n * enablement and close.\n *\n * The manager is the API app code drives (a hand menu calls\n * `manager.hide(id)` or `manager.dockTo(id, region)`); this system is where\n * those calls become entity changes. The reverse direction is kept in step\n * too: a title-bar drag that docks a window, or a dock-mode change applied\n * by `UIDockSystem`, is written back into the record, so the record is\n * always what the scene shows.\n *\n * Reuse over recreation: the panel itself is loaded/rendered by the IWSDK's\n * `PanelUISystem`; this system only discovers the chrome elements by their\n * well-known ids and drives them.\n */\nimport {\n PanelDocument,\n PanelUI,\n PokeInteractable,\n RayInteractable,\n UIKitDocument,\n type Entity,\n} from '@iwsdk/core';\nimport { createSystem } from '../create-system.js';\nimport { Vector3 } from 'three';\nimport { UIDockedTo, UIWindow, UIWindowState } from '../components.js';\nimport { WINDOW_CHROME_IDS } from '@realitycollective/webxr-uiextensions';\nimport { windowManagerFor } from '../manager-registry.js';\nimport {\n minimizeLabelFor,\n pinLabelFor,\n type HandMenuOptions,\n type WindowChrome,\n type WindowManager,\n type WindowRecord,\n} from '@realitycollective/webxr-uiextensions';\nimport { DockMode, isDockMode, type DockModeValue } from '@realitycollective/webxr-uiextensions';\n\ntype UikitElement = {\n addEventListener: (type: string, listener: (event?: unknown) => void) => void;\n setProperties: (props: Record<string, unknown>) => void;\n};\n\n/** Which IWSDK interaction tags were stripped while not presented, so only those come back. */\ninterface HiddenTags {\n ray: boolean;\n poke: boolean;\n}\n\nlet autoId = 0;\n\nexport class UIWindowSystem extends createSystem({\n pendingWindows: {\n required: [UIWindow, PanelUI, PanelDocument],\n excluded: [UIWindowState],\n },\n windows: { required: [UIWindow, UIWindowState, PanelDocument] },\n}) {\n private manager!: WindowManager;\n private entitiesById = new Map<string, Entity>();\n private hiddenTags = new Map<string, HiddenTags>();\n private localCamera = new Vector3();\n\n override init(): void {\n this.manager = windowManagerFor(this.world);\n\n this.cleanupFuncs.push(\n this.queries.pendingWindows.subscribe('qualify', (entity) => {\n this.adoptWindow(entity);\n }),\n this.queries.windows.subscribe('disqualify', (entity) => {\n this.releaseWindow(entity);\n }),\n this.manager.events.on('closed', ({ id }) => this.destroyWindow(id)),\n this.manager.events.on('minimized', ({ id }) => this.applyMinimized(id, true)),\n this.manager.events.on('restored', ({ id }) => this.applyMinimized(id, false)),\n this.manager.events.on('minimized', (record) => this.syncMinimizeLabel(record)),\n this.manager.events.on('restored', (record) => this.syncMinimizeLabel(record)),\n this.manager.events.on('hidden', ({ id }) => this.reconcilePresentation(id)),\n this.manager.events.on('shown', ({ id }) => this.reconcilePresentation(id)),\n this.manager.events.on('dockChanged', ({ window }) => {\n const entity = this.entitiesById.get(window.id);\n if (entity && entity.getValue(UIWindow, 'dockMode') !== window.dockMode) {\n entity.setValue(UIWindow, 'dockMode', window.dockMode);\n }\n this.syncPinLabel(window);\n }),\n this.manager.events.on('regionChanged', ({ window }) => this.applyRegion(window)),\n this.manager.events.on('returnHome', ({ id }) => {\n const entity = this.entitiesById.get(id);\n if (entity) {\n this.returnHome(entity);\n }\n }),\n this.manager.events.on('chromeChanged', ({ window }) => this.applyChrome(window)),\n this.manager.events.on('handMenuChanged', ({ window }) => this.applyHandMenu(window)),\n this.manager.events.on('dragStarted', (window) => this.syncPinLabel(window)),\n this.manager.events.on('dragEnded', (window) => this.syncPinLabel(window)),\n );\n }\n\n override update(): void {\n // Focus bias: nudge each window's document toward the viewer by a small\n // amount inversely related to focus depth, so overlapping windows resolve\n // in focus order. Computed in entity-local space so it holds for any\n // window orientation.\n for (const entity of this.queries.windows.entities) {\n const id = entity.getValue(UIWindow, 'windowId') as string;\n const record = this.manager.get(id);\n if (!record) {\n continue;\n }\n // The palm gate (UIDockSystem) and hide() both feed one decision.\n if (!this.reconcilePresentation(id)) {\n continue;\n }\n const document = this.documentOf(entity);\n const object = entity.object3D;\n if (!document || !object) {\n continue;\n }\n const bias = entity.getValue(UIWindow, 'focusBias') as number;\n const depth = this.manager.orderOf(id);\n const amount = bias * Math.max(0, this.manager.count - 1 - depth);\n if (amount === 0) {\n document.position.set(0, 0, 0);\n continue;\n }\n this.camera.getWorldPosition(this.localCamera);\n object.worldToLocal(this.localCamera);\n if (this.localCamera.lengthSq() === 0) {\n continue;\n }\n document.position.copy(this.localCamera.normalize().multiplyScalar(amount));\n }\n }\n\n entityFor(windowId: string): Entity | undefined {\n return this.entitiesById.get(windowId);\n }\n\n private adoptWindow(entity: Entity): void {\n let id = entity.getValue(UIWindow, 'windowId') as string;\n if (!id) {\n id = `uix-window-${autoId++}`;\n entity.setValue(UIWindow, 'windowId', id);\n }\n const title = entity.getValue(UIWindow, 'title') as string;\n const dockMode = entity.getValue(UIWindow, 'dockMode') as DockModeValue;\n const region = entity.hasComponent(UIDockedTo)\n ? (entity.getValue(UIDockedTo, 'regionId') as string)\n : '';\n this.entitiesById.set(id, entity);\n if (!this.manager.has(id)) {\n const followOffset = entity.getVectorView(UIWindow, 'followOffset');\n this.manager.open(id, {\n title,\n dockMode,\n ...(region ? { region } : {}),\n chrome: this.chromeFlagsOf(entity),\n handMenu: this.handMenuOf(entity),\n follow: {\n offset: [followOffset[0] ?? 0, followOffset[1] ?? 0, followOffset[2] ?? 0],\n speed: entity.getValue(UIWindow, 'followSpeed') as number,\n tolerance: entity.getValue(UIWindow, 'followTolerance') as number,\n },\n });\n }\n this.wireChrome(entity, id, title);\n\n // Snapshot \"home\" so the DOCK button can return the window: the spawn\n // region if it was born docked, otherwise its placement + dock mode.\n const object = entity.object3D;\n entity.addComponent(UIWindowState, {\n chromeWired: true,\n appliedDockMode: '',\n homeDockMode: dockMode,\n homeRegion: region,\n homePosition: object ? [object.position.x, object.position.y, object.position.z] : [0, 0, 0],\n homeYaw: object ? object.rotation.y : 0,\n });\n const record = this.manager.get(id);\n if (record) {\n this.applyChrome(record);\n this.applyHandMenu(record);\n this.syncPinLabel(record);\n this.syncMinimizeLabel(record);\n if (record.minimized) {\n this.applyMinimized(id, true);\n }\n this.reconcilePresentation(id);\n }\n }\n\n /** The hand-menu fields on the component, in the manager's vocabulary. */\n private handMenuOf(entity: Entity): HandMenuOptions {\n const offset = entity.getVectorView(UIWindow, 'handOffset');\n return {\n hand: entity.getValue(UIWindow, 'hand') as HandMenuOptions['hand'],\n anchor: entity.getValue(UIWindow, 'handAnchor') as HandMenuOptions['anchor'],\n anchorDistance: entity.getValue(UIWindow, 'handAnchorDistance') as number,\n offset: [offset[0] ?? 0, offset[1] ?? 0, offset[2] ?? 0],\n palmGate: Boolean(entity.getValue(UIWindow, 'palmGate')),\n palmAngle: entity.getValue(UIWindow, 'palmAngle') as number,\n };\n }\n\n /** Keep the component's hand-menu fields equal to the record. */\n private applyHandMenu(record: Pick<WindowRecord, 'id' | 'handMenu'>): void {\n const entity = this.entitiesById.get(record.id);\n if (!entity) {\n return;\n }\n const { handMenu } = record;\n entity.setValue(UIWindow, 'hand', handMenu.hand);\n entity.setValue(UIWindow, 'handAnchor', handMenu.anchor);\n entity.setValue(UIWindow, 'handAnchorDistance', handMenu.anchorDistance);\n entity.getVectorView(UIWindow, 'handOffset').set(handMenu.offset);\n entity.setValue(UIWindow, 'palmGate', handMenu.palmGate);\n entity.setValue(UIWindow, 'palmAngle', handMenu.palmAngle);\n }\n\n /** Return a window to its home: spawn region, or original placement/mode. */\n returnHome(entity: Entity): void {\n const homeRegion = entity.getValue(UIWindowState, 'homeRegion') as string;\n if (homeRegion) {\n if (\n entity.hasComponent(UIDockedTo) &&\n entity.getValue(UIDockedTo, 'regionId') === homeRegion\n ) {\n return; // already home\n }\n if (entity.hasComponent(UIDockedTo)) {\n entity.removeComponent(UIDockedTo);\n }\n entity.addComponent(UIDockedTo, { regionId: homeRegion });\n return;\n }\n if (entity.hasComponent(UIDockedTo)) {\n entity.removeComponent(UIDockedTo);\n }\n const homeDockMode = entity.getValue(UIWindowState, 'homeDockMode') as string;\n if (isDockMode(homeDockMode)) {\n entity.setValue(UIWindow, 'dockMode', homeDockMode);\n }\n if (homeDockMode === DockMode.WorldLocked) {\n const object = entity.object3D;\n const home = entity.getVectorView(UIWindowState, 'homePosition');\n if (object) {\n object.position.set(home[0] ?? 0, home[1] ?? 0, home[2] ?? 0);\n object.rotation.set(0, entity.getValue(UIWindowState, 'homeYaw') as number, 0);\n }\n }\n // Follow modes re-snap on their own (the dock system syncs the Follower).\n }\n\n /** The chrome flags on the component, in the manager's vocabulary. */\n private chromeFlagsOf(entity: Entity): WindowChrome {\n return {\n close: Boolean(entity.getValue(UIWindow, 'closable')),\n minimize: Boolean(entity.getValue(UIWindow, 'minimizable')),\n pin: Boolean(entity.getValue(UIWindow, 'pinnable')),\n dock: Boolean(entity.getValue(UIWindow, 'dockable')),\n };\n }\n\n /**\n * Show exactly the enabled buttons, and keep the component flags equal to\n * the record so code reading either sees one answer.\n */\n private applyChrome(record: Pick<WindowRecord, 'id' | 'chrome'>): void {\n const entity = this.entitiesById.get(record.id);\n if (!entity) {\n return;\n }\n const { chrome } = record;\n entity.setValue(UIWindow, 'closable', chrome.close);\n entity.setValue(UIWindow, 'minimizable', chrome.minimize);\n entity.setValue(UIWindow, 'pinnable', chrome.pin);\n entity.setValue(UIWindow, 'dockable', chrome.dock);\n const document = this.documentOf(entity);\n if (!document) {\n return;\n }\n const buttons: Array<[string, boolean]> = [\n [WINDOW_CHROME_IDS.close, chrome.close],\n [WINDOW_CHROME_IDS.minimize, chrome.minimize],\n [WINDOW_CHROME_IDS.pin, chrome.pin],\n [WINDOW_CHROME_IDS.dock, chrome.dock],\n ];\n for (const [elementId, enabled] of buttons) {\n (document.getElementById(elementId) as UikitElement | undefined)?.setProperties({\n display: enabled ? 'flex' : 'none',\n });\n }\n }\n\n /** MIN when open, MAX when minimized - the label names the next action. */\n private syncMinimizeLabel(record: Pick<WindowRecord, 'id' | 'minimized'>): void {\n const entity = this.entitiesById.get(record.id);\n const minimize = entity\n ? (this.documentOf(entity)?.getElementById(WINDOW_CHROME_IDS.minimize) as\n | UikitElement\n | undefined)\n : undefined;\n minimize?.setProperties({ text: minimizeLabelFor(record) });\n }\n\n private syncPinLabel(record: Pick<WindowRecord, 'id' | 'dockMode' | 'dragging'>): void {\n const entity = this.entitiesById.get(record.id);\n const pin = entity\n ? (this.documentOf(entity)?.getElementById(WINDOW_CHROME_IDS.pin) as\n | UikitElement\n | undefined)\n : undefined;\n pin?.setProperties({ text: pinLabelFor(record) });\n }\n\n /** The entity went away (destroyed, or lost its panel): close the record. */\n private releaseWindow(entity: Entity): void {\n const id = entity.getValue(UIWindow, 'windowId') as string;\n if (id && this.entitiesById.get(id) === entity) {\n this.entitiesById.delete(id);\n this.hiddenTags.delete(id);\n if (this.manager.has(id)) {\n this.manager.close(id);\n }\n }\n }\n\n /** The record was closed through the manager: tear the entity down. */\n private destroyWindow(id: string): void {\n const entity = this.entitiesById.get(id);\n if (!entity) {\n return; // closed from the entity side; releaseWindow already ran\n }\n this.entitiesById.delete(id);\n this.hiddenTags.delete(id);\n entity.destroy();\n }\n\n /**\n * Draw and expose the window exactly when the record is not hidden AND the\n * palm gate (for a hand menu) is open. Idempotent: `UIWindowState.presented`\n * records what was last applied, so this is cheap to call every frame.\n * Returns whether the window is presented.\n */\n private reconcilePresentation(id: string): boolean {\n const entity = this.entitiesById.get(id);\n const record = this.manager.get(id);\n if (!entity || !record) {\n return false;\n }\n const desired = !record.hidden && Boolean(entity.getValue(UIWindowState, 'gateOpen'));\n if (Boolean(entity.getValue(UIWindowState, 'presented')) === desired) {\n return desired;\n }\n entity.setValue(UIWindowState, 'presented', desired);\n const object = entity.object3D;\n if (object) {\n object.visible = desired;\n }\n if (!desired) {\n // Strip the interaction tags so no pointer can reach the window, and\n // remember which ones were there so only those come back.\n const tags: HiddenTags = {\n ray: entity.hasComponent(RayInteractable),\n poke: entity.hasComponent(PokeInteractable),\n };\n if (tags.ray) {\n entity.removeComponent(RayInteractable);\n }\n if (tags.poke) {\n entity.removeComponent(PokeInteractable);\n }\n this.hiddenTags.set(id, tags);\n return false;\n }\n const tags = this.hiddenTags.get(id);\n this.hiddenTags.delete(id);\n if (tags?.ray && !entity.hasComponent(RayInteractable)) {\n entity.addComponent(RayInteractable);\n }\n if (tags?.poke && !entity.hasComponent(PokeInteractable)) {\n entity.addComponent(PokeInteractable);\n }\n return true;\n }\n\n /** Make the entity's `UIDockedTo` agree with the record's region. */\n private applyRegion(record: Pick<WindowRecord, 'id' | 'region'>): void {\n const entity = this.entitiesById.get(record.id);\n if (!entity) {\n return;\n }\n const current = entity.hasComponent(UIDockedTo)\n ? (entity.getValue(UIDockedTo, 'regionId') as string)\n : undefined;\n if (current === record.region) {\n return; // the ECS already shows it (drag-drop docked, or a write-back)\n }\n if (entity.hasComponent(UIDockedTo)) {\n entity.removeComponent(UIDockedTo);\n }\n if (record.region !== undefined) {\n entity.addComponent(UIDockedTo, { regionId: record.region });\n }\n }\n\n private wireChrome(entity: Entity, id: string, title: string): void {\n const document = this.documentOf(entity);\n if (!document) {\n return;\n }\n\n // IWSDK 0.5 removed PanelUI.maxWidth/maxHeight; world size is now the\n // document's own concern. Fit into the requested box, preserving aspect\n // ratio. Zero means \"leave intrinsic\" so the entity transform owns scale.\n const targetWidth = entity.getValue(UIWindow, 'targetWidth') ?? 0;\n const targetHeight = entity.getValue(UIWindow, 'targetHeight') ?? 0;\n if (targetWidth > 0 && targetHeight > 0) {\n document.setTargetDimensions(targetWidth, targetHeight);\n }\n\n const element = (elementId: string): UikitElement | undefined =>\n document.getElementById(elementId) as UikitElement | undefined;\n\n const titleEl = element(WINDOW_CHROME_IDS.title);\n if (titleEl && title) {\n titleEl.setProperties({ text: title });\n }\n\n // Chrome buttons live on the drag surface - keep their presses out of\n // the title-bar drag handle so clicks never turn into (or arm) drags.\n const swallowPress = (button: UikitElement | undefined): void => {\n button?.addEventListener('pointerdown', (event) => {\n (event as { stopPropagation?: () => void } | undefined)?.stopPropagation?.();\n });\n };\n swallowPress(element(WINDOW_CHROME_IDS.pin));\n swallowPress(element(WINDOW_CHROME_IDS.dock));\n swallowPress(element(WINDOW_CHROME_IDS.minimize));\n swallowPress(element(WINDOW_CHROME_IDS.close));\n\n // Any press anywhere on the window brings it to the front.\n const root = element(WINDOW_CHROME_IDS.window);\n root?.addEventListener('pointerdown', () => {\n if (this.manager.has(id)) {\n this.manager.focus(id);\n }\n });\n\n // Every button is wired once and gated on the record at click time, so\n // enabling a button later (manager.setChrome) needs no rewiring.\n const enabled = (key: keyof WindowChrome): boolean =>\n this.manager.get(id)?.chrome[key] === true;\n\n element(WINDOW_CHROME_IDS.close)?.addEventListener('click', () => {\n if (enabled('close')) {\n // One teardown path: the manager closes, destroyWindow removes the\n // entity, releaseWindow sees the record is already gone.\n this.manager.close(id);\n }\n });\n element(WINDOW_CHROME_IDS.minimize)?.addEventListener('click', () => {\n if (enabled('minimize')) {\n this.manager.toggleMinimized(id);\n }\n });\n element(WINDOW_CHROME_IDS.pin)?.addEventListener('click', () => {\n if (enabled('pin')) {\n this.manager.togglePin(id);\n }\n });\n element(WINDOW_CHROME_IDS.dock)?.addEventListener('click', () => {\n if (enabled('dock')) {\n this.manager.returnHome(id);\n }\n });\n }\n\n private applyMinimized(id: string, minimized: boolean): void {\n const entity = this.entitiesById.get(id);\n const document = entity ? this.documentOf(entity) : undefined;\n const content = document?.getElementById(WINDOW_CHROME_IDS.content) as\n | UikitElement\n | undefined;\n content?.setProperties({ display: minimized ? 'none' : 'flex' });\n }\n\n private documentOf(entity: Entity): UIKitDocument | undefined {\n return PanelDocument.data.document[entity.index] as UIKitDocument | undefined;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@realitycollective/iwsdk-uiextensions",
|
|
3
|
-
"version": "0.1.1-preview.
|
|
3
|
+
"version": "0.1.1-preview.2",
|
|
4
4
|
"description": "Meta IWSDK adapter for the Reality Collective UI Extensions - windowing, docking, layout regions and extra controls, binding the engine-free @realitycollective/webxr-uiextensions core onto IWSDK's ECS, UIKitML and interaction systems.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"realitycollective",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@drawcall/uikitml": "0.1.8",
|
|
40
40
|
"zod": "^4.4.3",
|
|
41
41
|
"@pmndrs/handle": "^6.6.16",
|
|
42
|
-
"@realitycollective/webxr-uiextensions": "^0.1.1-preview.
|
|
42
|
+
"@realitycollective/webxr-uiextensions": "^0.1.1-preview.2"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"@iwsdk/core": ">=1.0.0 <2.0.0",
|