@realitycollective/iwsdk-uiextensions 0.1.0-preview.0
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.
Potentially problematic release.
This version of @realitycollective/iwsdk-uiextensions might be problematic. Click here for more details.
- package/CHANGELOG.md +17 -0
- package/Examples/README.md +13 -0
- package/Examples/basic-window/main.ts +31 -0
- package/Examples/basic-window/window.uikitml +59 -0
- package/Examples/controls/controls.uikitml +50 -0
- package/Examples/controls/main.ts +44 -0
- package/Examples/dock-regions/main.ts +55 -0
- package/LICENSE +21 -0
- package/README.md +117 -0
- package/dist/components.d.ts +189 -0
- package/dist/components.js +97 -0
- package/dist/components.js.map +1 -0
- package/dist/factory.d.ts +55 -0
- package/dist/factory.js +63 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/manager-registry.d.ts +8 -0
- package/dist/manager-registry.js +11 -0
- package/dist/manager-registry.js.map +1 -0
- package/dist/region-registry-store.d.ts +7 -0
- package/dist/region-registry-store.js +11 -0
- package/dist/region-registry-store.js.map +1 -0
- package/dist/register.d.ts +19 -0
- package/dist/register.js +20 -0
- package/dist/register.js.map +1 -0
- package/dist/scene-host.d.ts +23 -0
- package/dist/scene-host.js +145 -0
- package/dist/scene-host.js.map +1 -0
- package/dist/systems/controls-system.d.ts +24 -0
- package/dist/systems/controls-system.js +24 -0
- package/dist/systems/controls-system.js.map +1 -0
- package/dist/systems/dock-region-system.d.ts +230 -0
- package/dist/systems/dock-region-system.js +102 -0
- package/dist/systems/dock-region-system.js.map +1 -0
- package/dist/systems/dock-system.d.ts +205 -0
- package/dist/systems/dock-system.js +135 -0
- package/dist/systems/dock-system.js.map +1 -0
- package/dist/systems/drag-system.d.ts +280 -0
- package/dist/systems/drag-system.js +167 -0
- package/dist/systems/drag-system.js.map +1 -0
- package/dist/systems/window-system.d.ts +455 -0
- package/dist/systems/window-system.js +244 -0
- package/dist/systems/window-system.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UIControlsSystem - upgrades `data-uix` controls in every loaded panel.
|
|
3
|
+
*
|
|
4
|
+
* Runs against ALL `PanelDocument` panels, not just windows: any IWSDK panel
|
|
5
|
+
* gains steppers, toggles, expandable labels and log views by markup alone.
|
|
6
|
+
*/
|
|
7
|
+
import { PanelDocument, createSystem } from '@iwsdk/core';
|
|
8
|
+
import { upgradePanel } from '@realitycollective/webxr-uiextensions';
|
|
9
|
+
export class UIControlsSystem extends createSystem({
|
|
10
|
+
panels: { required: [PanelDocument] },
|
|
11
|
+
}) {
|
|
12
|
+
init() {
|
|
13
|
+
this.cleanupFuncs.push(this.queries.panels.subscribe('qualify', (entity) => this.upgrade(entity)));
|
|
14
|
+
this.queries.panels.entities.forEach((entity) => this.upgrade(entity));
|
|
15
|
+
}
|
|
16
|
+
upgrade(entity) {
|
|
17
|
+
const document = PanelDocument.data.document[entity.index];
|
|
18
|
+
if (!document?.rootElement) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
upgradePanel(document, document.rootElement);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=controls-system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controls-system.js","sourceRoot":"","sources":["../../src/systems/controls-system.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,aAAa,EAAiB,YAAY,EAAe,MAAM,aAAa,CAAC;AAEtF,OAAO,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAErE,MAAM,OAAO,gBAAiB,SAAQ,YAAY,CAAC;IACjD,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,aAAa,CAAC,EAAE;CACtC,CAAC;IACS,IAAI;QACX,IAAI,CAAC,YAAY,CAAC,IAAI,CACpB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAC3E,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACzE,CAAC;IAEO,OAAO,CAAC,MAAc;QAC5B,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAE5C,CAAC;QACd,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAC;YAC3B,OAAO;QACT,CAAC;QACD,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,WAAoC,CAAC,CAAC;IACxE,CAAC;CACF","sourcesContent":["/**\n * UIControlsSystem - upgrades `data-uix` controls in every loaded panel.\n *\n * Runs against ALL `PanelDocument` panels, not just windows: any IWSDK panel\n * gains steppers, toggles, expandable labels and log views by markup alone.\n */\nimport { PanelDocument, UIKitDocument, createSystem, type Entity } from '@iwsdk/core';\nimport type { UixElement } from '@realitycollective/webxr-uiextensions';\nimport { upgradePanel } from '@realitycollective/webxr-uiextensions';\n\nexport class UIControlsSystem extends createSystem({\n panels: { required: [PanelDocument] },\n}) {\n override init(): void {\n this.cleanupFuncs.push(\n this.queries.panels.subscribe('qualify', (entity) => this.upgrade(entity)),\n );\n this.queries.panels.entities.forEach((entity) => this.upgrade(entity));\n }\n\n private upgrade(entity: Entity): void {\n const document = PanelDocument.data.document[entity.index] as\n | UIKitDocument\n | undefined;\n if (!document?.rootElement) {\n return;\n }\n upgradePanel(document, document.rootElement as unknown as UixElement);\n }\n}\n"]}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
declare const UIDockRegionSystem_base: import("elics").SystemConstructor<import("elics").SystemSchema, {
|
|
2
|
+
regions: {
|
|
3
|
+
required: import("elics").Component<{
|
|
4
|
+
regionId: {
|
|
5
|
+
type: import("@iwsdk/core").Types.String;
|
|
6
|
+
default: string;
|
|
7
|
+
};
|
|
8
|
+
flow: {
|
|
9
|
+
type: import("@iwsdk/core").Types.Enum;
|
|
10
|
+
enum: {
|
|
11
|
+
readonly Row: "row";
|
|
12
|
+
readonly Column: "column";
|
|
13
|
+
readonly Grid: "grid";
|
|
14
|
+
};
|
|
15
|
+
default: "column";
|
|
16
|
+
};
|
|
17
|
+
pitch: {
|
|
18
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
19
|
+
default: number;
|
|
20
|
+
};
|
|
21
|
+
columns: {
|
|
22
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
23
|
+
default: number;
|
|
24
|
+
};
|
|
25
|
+
capacity: {
|
|
26
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
27
|
+
default: number;
|
|
28
|
+
};
|
|
29
|
+
snapRadius: {
|
|
30
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
31
|
+
default: number;
|
|
32
|
+
};
|
|
33
|
+
}>[];
|
|
34
|
+
};
|
|
35
|
+
docked: {
|
|
36
|
+
required: (import("elics").Component<{
|
|
37
|
+
windowId: {
|
|
38
|
+
type: import("@iwsdk/core").Types.String;
|
|
39
|
+
default: string;
|
|
40
|
+
};
|
|
41
|
+
title: {
|
|
42
|
+
type: import("@iwsdk/core").Types.String;
|
|
43
|
+
default: string;
|
|
44
|
+
};
|
|
45
|
+
dockMode: {
|
|
46
|
+
type: import("@iwsdk/core").Types.Enum;
|
|
47
|
+
enum: {
|
|
48
|
+
readonly WorldLocked: "world-locked";
|
|
49
|
+
readonly BodyFollow: "body-follow";
|
|
50
|
+
readonly HeadLocked: "head-locked";
|
|
51
|
+
};
|
|
52
|
+
default: "world-locked";
|
|
53
|
+
};
|
|
54
|
+
movable: {
|
|
55
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
56
|
+
default: true;
|
|
57
|
+
};
|
|
58
|
+
closable: {
|
|
59
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
60
|
+
default: true;
|
|
61
|
+
};
|
|
62
|
+
minimizable: {
|
|
63
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
64
|
+
default: true;
|
|
65
|
+
};
|
|
66
|
+
pinnable: {
|
|
67
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
68
|
+
default: true;
|
|
69
|
+
};
|
|
70
|
+
billboardWhileDragging: {
|
|
71
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
72
|
+
default: true;
|
|
73
|
+
};
|
|
74
|
+
dragDelay: {
|
|
75
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
76
|
+
default: number;
|
|
77
|
+
};
|
|
78
|
+
followOffset: {
|
|
79
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
80
|
+
default: [number, number, number];
|
|
81
|
+
};
|
|
82
|
+
followSpeed: {
|
|
83
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
84
|
+
default: number;
|
|
85
|
+
};
|
|
86
|
+
followTolerance: {
|
|
87
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
88
|
+
default: number;
|
|
89
|
+
};
|
|
90
|
+
focusBias: {
|
|
91
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
92
|
+
default: number;
|
|
93
|
+
};
|
|
94
|
+
targetWidth: {
|
|
95
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
96
|
+
default: number;
|
|
97
|
+
};
|
|
98
|
+
targetHeight: {
|
|
99
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
100
|
+
default: number;
|
|
101
|
+
};
|
|
102
|
+
}> | import("elics").Component<{
|
|
103
|
+
regionId: {
|
|
104
|
+
type: import("@iwsdk/core").Types.String;
|
|
105
|
+
default: string;
|
|
106
|
+
};
|
|
107
|
+
}>)[];
|
|
108
|
+
};
|
|
109
|
+
}, World, import("@iwsdk/core").System<import("elics").SystemSchema, {
|
|
110
|
+
regions: {
|
|
111
|
+
required: import("elics").Component<{
|
|
112
|
+
regionId: {
|
|
113
|
+
type: import("@iwsdk/core").Types.String;
|
|
114
|
+
default: string;
|
|
115
|
+
};
|
|
116
|
+
flow: {
|
|
117
|
+
type: import("@iwsdk/core").Types.Enum;
|
|
118
|
+
enum: {
|
|
119
|
+
readonly Row: "row";
|
|
120
|
+
readonly Column: "column";
|
|
121
|
+
readonly Grid: "grid";
|
|
122
|
+
};
|
|
123
|
+
default: "column";
|
|
124
|
+
};
|
|
125
|
+
pitch: {
|
|
126
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
127
|
+
default: number;
|
|
128
|
+
};
|
|
129
|
+
columns: {
|
|
130
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
131
|
+
default: number;
|
|
132
|
+
};
|
|
133
|
+
capacity: {
|
|
134
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
135
|
+
default: number;
|
|
136
|
+
};
|
|
137
|
+
snapRadius: {
|
|
138
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
139
|
+
default: number;
|
|
140
|
+
};
|
|
141
|
+
}>[];
|
|
142
|
+
};
|
|
143
|
+
docked: {
|
|
144
|
+
required: (import("elics").Component<{
|
|
145
|
+
windowId: {
|
|
146
|
+
type: import("@iwsdk/core").Types.String;
|
|
147
|
+
default: string;
|
|
148
|
+
};
|
|
149
|
+
title: {
|
|
150
|
+
type: import("@iwsdk/core").Types.String;
|
|
151
|
+
default: string;
|
|
152
|
+
};
|
|
153
|
+
dockMode: {
|
|
154
|
+
type: import("@iwsdk/core").Types.Enum;
|
|
155
|
+
enum: {
|
|
156
|
+
readonly WorldLocked: "world-locked";
|
|
157
|
+
readonly BodyFollow: "body-follow";
|
|
158
|
+
readonly HeadLocked: "head-locked";
|
|
159
|
+
};
|
|
160
|
+
default: "world-locked";
|
|
161
|
+
};
|
|
162
|
+
movable: {
|
|
163
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
164
|
+
default: true;
|
|
165
|
+
};
|
|
166
|
+
closable: {
|
|
167
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
168
|
+
default: true;
|
|
169
|
+
};
|
|
170
|
+
minimizable: {
|
|
171
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
172
|
+
default: true;
|
|
173
|
+
};
|
|
174
|
+
pinnable: {
|
|
175
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
176
|
+
default: true;
|
|
177
|
+
};
|
|
178
|
+
billboardWhileDragging: {
|
|
179
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
180
|
+
default: true;
|
|
181
|
+
};
|
|
182
|
+
dragDelay: {
|
|
183
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
184
|
+
default: number;
|
|
185
|
+
};
|
|
186
|
+
followOffset: {
|
|
187
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
188
|
+
default: [number, number, number];
|
|
189
|
+
};
|
|
190
|
+
followSpeed: {
|
|
191
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
192
|
+
default: number;
|
|
193
|
+
};
|
|
194
|
+
followTolerance: {
|
|
195
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
196
|
+
default: number;
|
|
197
|
+
};
|
|
198
|
+
focusBias: {
|
|
199
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
200
|
+
default: number;
|
|
201
|
+
};
|
|
202
|
+
targetWidth: {
|
|
203
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
204
|
+
default: number;
|
|
205
|
+
};
|
|
206
|
+
targetHeight: {
|
|
207
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
208
|
+
default: number;
|
|
209
|
+
};
|
|
210
|
+
}> | import("elics").Component<{
|
|
211
|
+
regionId: {
|
|
212
|
+
type: import("@iwsdk/core").Types.String;
|
|
213
|
+
default: string;
|
|
214
|
+
};
|
|
215
|
+
}>)[];
|
|
216
|
+
};
|
|
217
|
+
}>>;
|
|
218
|
+
export declare class UIDockRegionSystem extends UIDockRegionSystem_base {
|
|
219
|
+
private registry;
|
|
220
|
+
private regionEntities;
|
|
221
|
+
private slotPosition;
|
|
222
|
+
private regionQuaternion;
|
|
223
|
+
init(): void;
|
|
224
|
+
update(): void;
|
|
225
|
+
private addRegion;
|
|
226
|
+
private removeRegion;
|
|
227
|
+
private dockWindow;
|
|
228
|
+
private undockWindow;
|
|
229
|
+
}
|
|
230
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UIDockRegionSystem - keeps the region registry in sync with `UIDockRegion`
|
|
3
|
+
* entities and lays docked windows out in their region's slots each frame.
|
|
4
|
+
*
|
|
5
|
+
* Regions are ordinary entities: give one a `Follower` and its docked
|
|
6
|
+
* windows become a body-locked toolbar; leave it static for a world-locked
|
|
7
|
+
* console wall.
|
|
8
|
+
*/
|
|
9
|
+
import { Quaternion, Vector3, createSystem } from '@iwsdk/core';
|
|
10
|
+
import { UIDockRegion, UIDockedTo, UIWindow } from '../components.js';
|
|
11
|
+
import { DockMode } from '@realitycollective/webxr-uiextensions';
|
|
12
|
+
import { regionRegistryFor } from '../region-registry-store.js';
|
|
13
|
+
let autoRegionId = 0;
|
|
14
|
+
export class UIDockRegionSystem extends createSystem({
|
|
15
|
+
regions: { required: [UIDockRegion] },
|
|
16
|
+
docked: { required: [UIWindow, UIDockedTo] },
|
|
17
|
+
}) {
|
|
18
|
+
registry;
|
|
19
|
+
regionEntities = new Map();
|
|
20
|
+
slotPosition = new Vector3();
|
|
21
|
+
regionQuaternion = new Quaternion();
|
|
22
|
+
init() {
|
|
23
|
+
this.registry = regionRegistryFor(this.world);
|
|
24
|
+
this.cleanupFuncs.push(this.queries.regions.subscribe('qualify', (entity) => this.addRegion(entity)), this.queries.regions.subscribe('disqualify', (entity) => this.removeRegion(entity)), this.queries.docked.subscribe('qualify', (entity) => this.dockWindow(entity)), this.queries.docked.subscribe('disqualify', (entity) => this.undockWindow(entity)));
|
|
25
|
+
this.queries.regions.entities.forEach((entity) => this.addRegion(entity));
|
|
26
|
+
this.queries.docked.entities.forEach((entity) => this.dockWindow(entity));
|
|
27
|
+
}
|
|
28
|
+
update() {
|
|
29
|
+
for (const entity of this.queries.docked.entities) {
|
|
30
|
+
const windowId = entity.getValue(UIWindow, 'windowId');
|
|
31
|
+
const offset = this.registry.offsetOf(windowId);
|
|
32
|
+
const regionId = this.registry.regionOf(windowId);
|
|
33
|
+
const regionEntity = regionId === undefined ? undefined : this.regionEntities.get(regionId);
|
|
34
|
+
const regionObject = regionEntity?.object3D;
|
|
35
|
+
const object = entity.object3D;
|
|
36
|
+
if (!offset || !regionObject || !object || !object.parent) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
// Slot offset is region-local; express it in the window's parent space.
|
|
40
|
+
this.slotPosition.set(offset[0], offset[1], offset[2]);
|
|
41
|
+
regionObject.localToWorld(this.slotPosition);
|
|
42
|
+
object.parent.worldToLocal(this.slotPosition);
|
|
43
|
+
object.position.copy(this.slotPosition);
|
|
44
|
+
regionObject.getWorldQuaternion(this.regionQuaternion);
|
|
45
|
+
object.quaternion.copy(this.regionQuaternion);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
addRegion(entity) {
|
|
49
|
+
let id = entity.getValue(UIDockRegion, 'regionId');
|
|
50
|
+
if (!id) {
|
|
51
|
+
id = `uix-region-${autoRegionId++}`;
|
|
52
|
+
entity.setValue(UIDockRegion, 'regionId', id);
|
|
53
|
+
}
|
|
54
|
+
if (this.registry.get(id)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const definition = {
|
|
58
|
+
flow: entity.getValue(UIDockRegion, 'flow'),
|
|
59
|
+
pitch: entity.getValue(UIDockRegion, 'pitch'),
|
|
60
|
+
columns: Math.max(1, Math.round(entity.getValue(UIDockRegion, 'columns'))),
|
|
61
|
+
capacity: Math.max(0, Math.round(entity.getValue(UIDockRegion, 'capacity'))),
|
|
62
|
+
snapRadius: entity.getValue(UIDockRegion, 'snapRadius'),
|
|
63
|
+
};
|
|
64
|
+
this.registry.register(id, definition);
|
|
65
|
+
this.regionEntities.set(id, entity);
|
|
66
|
+
}
|
|
67
|
+
removeRegion(entity) {
|
|
68
|
+
const id = entity.getValue(UIDockRegion, 'regionId');
|
|
69
|
+
if (id && this.regionEntities.get(id) === entity) {
|
|
70
|
+
this.registry.unregister(id);
|
|
71
|
+
this.regionEntities.delete(id);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
dockWindow(entity) {
|
|
75
|
+
const windowId = entity.getValue(UIWindow, 'windowId');
|
|
76
|
+
const regionId = entity.getValue(UIDockedTo, 'regionId');
|
|
77
|
+
if (!windowId || !regionId || !this.registry.get(regionId)) {
|
|
78
|
+
// Unknown region (or the window has no id yet) - docking is meaningless.
|
|
79
|
+
entity.removeComponent(UIDockedTo);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
this.registry.dock(windowId, regionId);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Region is full: reject the dock.
|
|
87
|
+
entity.removeComponent(UIDockedTo);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// Docked windows are world-locked by definition (the region may follow).
|
|
91
|
+
if (entity.getValue(UIWindow, 'dockMode') !== DockMode.WorldLocked) {
|
|
92
|
+
entity.setValue(UIWindow, 'dockMode', DockMode.WorldLocked);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
undockWindow(entity) {
|
|
96
|
+
const windowId = entity.getValue(UIWindow, 'windowId');
|
|
97
|
+
if (windowId) {
|
|
98
|
+
this.registry.undock(windowId);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=dock-region-system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dock-region-system.js","sourceRoot":"","sources":["../../src/systems/dock-region-system.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * UIDockRegionSystem - keeps the region registry in sync with `UIDockRegion`\n * entities and lays docked windows out in their region's slots each frame.\n *\n * Regions are ordinary entities: give one a `Follower` and its docked\n * windows become a body-locked toolbar; leave it static for a world-locked\n * console wall.\n */\nimport { Quaternion, Vector3, createSystem, type Entity } from '@iwsdk/core';\nimport { UIDockRegion, UIDockedTo, UIWindow } from '../components.js';\nimport { DockMode } from '@realitycollective/webxr-uiextensions';\nimport type { RegionDefinition, RegionFlow } from '@realitycollective/webxr-uiextensions';\nimport { regionRegistryFor } from '../region-registry-store.js';\nimport type { RegionRegistry } from '@realitycollective/webxr-uiextensions';\n\nlet autoRegionId = 0;\n\nexport class UIDockRegionSystem extends createSystem({\n regions: { required: [UIDockRegion] },\n docked: { required: [UIWindow, UIDockedTo] },\n}) {\n private registry!: RegionRegistry;\n private regionEntities = new Map<string, Entity>();\n private slotPosition = new Vector3();\n private regionQuaternion = new Quaternion();\n\n override init(): void {\n this.registry = regionRegistryFor(this.world);\n\n this.cleanupFuncs.push(\n this.queries.regions.subscribe('qualify', (entity) => this.addRegion(entity)),\n this.queries.regions.subscribe('disqualify', (entity) => this.removeRegion(entity)),\n this.queries.docked.subscribe('qualify', (entity) => this.dockWindow(entity)),\n this.queries.docked.subscribe('disqualify', (entity) => this.undockWindow(entity)),\n );\n this.queries.regions.entities.forEach((entity) => this.addRegion(entity));\n this.queries.docked.entities.forEach((entity) => this.dockWindow(entity));\n }\n\n override update(): void {\n for (const entity of this.queries.docked.entities) {\n const windowId = entity.getValue(UIWindow, 'windowId') as string;\n const offset = this.registry.offsetOf(windowId);\n const regionId = this.registry.regionOf(windowId);\n const regionEntity = regionId === undefined ? undefined : this.regionEntities.get(regionId);\n const regionObject = regionEntity?.object3D;\n const object = entity.object3D;\n if (!offset || !regionObject || !object || !object.parent) {\n continue;\n }\n // Slot offset is region-local; express it in the window's parent space.\n this.slotPosition.set(offset[0], offset[1], offset[2]);\n regionObject.localToWorld(this.slotPosition);\n object.parent.worldToLocal(this.slotPosition);\n object.position.copy(this.slotPosition);\n regionObject.getWorldQuaternion(this.regionQuaternion);\n object.quaternion.copy(this.regionQuaternion);\n }\n }\n\n private addRegion(entity: Entity): void {\n let id = entity.getValue(UIDockRegion, 'regionId') as string;\n if (!id) {\n id = `uix-region-${autoRegionId++}`;\n entity.setValue(UIDockRegion, 'regionId', id);\n }\n if (this.registry.get(id)) {\n return;\n }\n const definition: Partial<RegionDefinition> = {\n flow: entity.getValue(UIDockRegion, 'flow') as RegionFlow,\n pitch: entity.getValue(UIDockRegion, 'pitch') as number,\n columns: Math.max(1, Math.round(entity.getValue(UIDockRegion, 'columns') as number)),\n capacity: Math.max(0, Math.round(entity.getValue(UIDockRegion, 'capacity') as number)),\n snapRadius: entity.getValue(UIDockRegion, 'snapRadius') as number,\n };\n this.registry.register(id, definition);\n this.regionEntities.set(id, entity);\n }\n\n private removeRegion(entity: Entity): void {\n const id = entity.getValue(UIDockRegion, 'regionId') as string;\n if (id && this.regionEntities.get(id) === entity) {\n this.registry.unregister(id);\n this.regionEntities.delete(id);\n }\n }\n\n private dockWindow(entity: Entity): void {\n const windowId = entity.getValue(UIWindow, 'windowId') as string;\n const regionId = entity.getValue(UIDockedTo, 'regionId') as string;\n if (!windowId || !regionId || !this.registry.get(regionId)) {\n // Unknown region (or the window has no id yet) - docking is meaningless.\n entity.removeComponent(UIDockedTo);\n return;\n }\n try {\n this.registry.dock(windowId, regionId);\n } catch {\n // Region is full: reject the dock.\n entity.removeComponent(UIDockedTo);\n return;\n }\n // Docked windows are world-locked by definition (the region may follow).\n if (entity.getValue(UIWindow, 'dockMode') !== DockMode.WorldLocked) {\n entity.setValue(UIWindow, 'dockMode', DockMode.WorldLocked);\n }\n }\n\n private undockWindow(entity: Entity): void {\n const windowId = entity.getValue(UIWindow, 'windowId') as string;\n if (windowId) {\n this.registry.undock(windowId);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
declare const UIDockSystem_base: import("elics").SystemConstructor<import("elics").SystemSchema, {
|
|
2
|
+
windows: {
|
|
3
|
+
required: (import("elics").Component<{
|
|
4
|
+
windowId: {
|
|
5
|
+
type: import("@iwsdk/core").Types.String;
|
|
6
|
+
default: string;
|
|
7
|
+
};
|
|
8
|
+
title: {
|
|
9
|
+
type: import("@iwsdk/core").Types.String;
|
|
10
|
+
default: string;
|
|
11
|
+
};
|
|
12
|
+
dockMode: {
|
|
13
|
+
type: import("@iwsdk/core").Types.Enum;
|
|
14
|
+
enum: {
|
|
15
|
+
readonly WorldLocked: "world-locked";
|
|
16
|
+
readonly BodyFollow: "body-follow";
|
|
17
|
+
readonly HeadLocked: "head-locked";
|
|
18
|
+
};
|
|
19
|
+
default: "world-locked";
|
|
20
|
+
};
|
|
21
|
+
movable: {
|
|
22
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
23
|
+
default: true;
|
|
24
|
+
};
|
|
25
|
+
closable: {
|
|
26
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
27
|
+
default: true;
|
|
28
|
+
};
|
|
29
|
+
minimizable: {
|
|
30
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
31
|
+
default: true;
|
|
32
|
+
};
|
|
33
|
+
pinnable: {
|
|
34
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
35
|
+
default: true;
|
|
36
|
+
};
|
|
37
|
+
billboardWhileDragging: {
|
|
38
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
39
|
+
default: true;
|
|
40
|
+
};
|
|
41
|
+
dragDelay: {
|
|
42
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
43
|
+
default: number;
|
|
44
|
+
};
|
|
45
|
+
followOffset: {
|
|
46
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
47
|
+
default: [number, number, number];
|
|
48
|
+
};
|
|
49
|
+
followSpeed: {
|
|
50
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
51
|
+
default: number;
|
|
52
|
+
};
|
|
53
|
+
followTolerance: {
|
|
54
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
55
|
+
default: number;
|
|
56
|
+
};
|
|
57
|
+
focusBias: {
|
|
58
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
59
|
+
default: number;
|
|
60
|
+
};
|
|
61
|
+
targetWidth: {
|
|
62
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
63
|
+
default: number;
|
|
64
|
+
};
|
|
65
|
+
targetHeight: {
|
|
66
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
67
|
+
default: number;
|
|
68
|
+
};
|
|
69
|
+
}> | import("elics").Component<{
|
|
70
|
+
appliedDockMode: {
|
|
71
|
+
type: import("@iwsdk/core").Types.String;
|
|
72
|
+
default: string;
|
|
73
|
+
};
|
|
74
|
+
chromeWired: {
|
|
75
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
76
|
+
default: false;
|
|
77
|
+
};
|
|
78
|
+
homeDockMode: {
|
|
79
|
+
type: import("@iwsdk/core").Types.String;
|
|
80
|
+
default: string;
|
|
81
|
+
};
|
|
82
|
+
homeRegion: {
|
|
83
|
+
type: import("@iwsdk/core").Types.String;
|
|
84
|
+
default: string;
|
|
85
|
+
};
|
|
86
|
+
homePosition: {
|
|
87
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
88
|
+
default: [number, number, number];
|
|
89
|
+
};
|
|
90
|
+
homeYaw: {
|
|
91
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
92
|
+
default: number;
|
|
93
|
+
};
|
|
94
|
+
}>)[];
|
|
95
|
+
};
|
|
96
|
+
}, World, import("@iwsdk/core").System<import("elics").SystemSchema, {
|
|
97
|
+
windows: {
|
|
98
|
+
required: (import("elics").Component<{
|
|
99
|
+
windowId: {
|
|
100
|
+
type: import("@iwsdk/core").Types.String;
|
|
101
|
+
default: string;
|
|
102
|
+
};
|
|
103
|
+
title: {
|
|
104
|
+
type: import("@iwsdk/core").Types.String;
|
|
105
|
+
default: string;
|
|
106
|
+
};
|
|
107
|
+
dockMode: {
|
|
108
|
+
type: import("@iwsdk/core").Types.Enum;
|
|
109
|
+
enum: {
|
|
110
|
+
readonly WorldLocked: "world-locked";
|
|
111
|
+
readonly BodyFollow: "body-follow";
|
|
112
|
+
readonly HeadLocked: "head-locked";
|
|
113
|
+
};
|
|
114
|
+
default: "world-locked";
|
|
115
|
+
};
|
|
116
|
+
movable: {
|
|
117
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
118
|
+
default: true;
|
|
119
|
+
};
|
|
120
|
+
closable: {
|
|
121
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
122
|
+
default: true;
|
|
123
|
+
};
|
|
124
|
+
minimizable: {
|
|
125
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
126
|
+
default: true;
|
|
127
|
+
};
|
|
128
|
+
pinnable: {
|
|
129
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
130
|
+
default: true;
|
|
131
|
+
};
|
|
132
|
+
billboardWhileDragging: {
|
|
133
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
134
|
+
default: true;
|
|
135
|
+
};
|
|
136
|
+
dragDelay: {
|
|
137
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
138
|
+
default: number;
|
|
139
|
+
};
|
|
140
|
+
followOffset: {
|
|
141
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
142
|
+
default: [number, number, number];
|
|
143
|
+
};
|
|
144
|
+
followSpeed: {
|
|
145
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
146
|
+
default: number;
|
|
147
|
+
};
|
|
148
|
+
followTolerance: {
|
|
149
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
150
|
+
default: number;
|
|
151
|
+
};
|
|
152
|
+
focusBias: {
|
|
153
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
154
|
+
default: number;
|
|
155
|
+
};
|
|
156
|
+
targetWidth: {
|
|
157
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
158
|
+
default: number;
|
|
159
|
+
};
|
|
160
|
+
targetHeight: {
|
|
161
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
162
|
+
default: number;
|
|
163
|
+
};
|
|
164
|
+
}> | import("elics").Component<{
|
|
165
|
+
appliedDockMode: {
|
|
166
|
+
type: import("@iwsdk/core").Types.String;
|
|
167
|
+
default: string;
|
|
168
|
+
};
|
|
169
|
+
chromeWired: {
|
|
170
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
171
|
+
default: false;
|
|
172
|
+
};
|
|
173
|
+
homeDockMode: {
|
|
174
|
+
type: import("@iwsdk/core").Types.String;
|
|
175
|
+
default: string;
|
|
176
|
+
};
|
|
177
|
+
homeRegion: {
|
|
178
|
+
type: import("@iwsdk/core").Types.String;
|
|
179
|
+
default: string;
|
|
180
|
+
};
|
|
181
|
+
homePosition: {
|
|
182
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
183
|
+
default: [number, number, number];
|
|
184
|
+
};
|
|
185
|
+
homeYaw: {
|
|
186
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
187
|
+
default: number;
|
|
188
|
+
};
|
|
189
|
+
}>)[];
|
|
190
|
+
};
|
|
191
|
+
}>>;
|
|
192
|
+
export declare class UIDockSystem extends UIDockSystem_base {
|
|
193
|
+
private manager;
|
|
194
|
+
private windowPosition;
|
|
195
|
+
private viewerPosition;
|
|
196
|
+
init(): void;
|
|
197
|
+
update(): void;
|
|
198
|
+
private apply;
|
|
199
|
+
private faceViewer;
|
|
200
|
+
private offsetHelper;
|
|
201
|
+
private yawQuaternion;
|
|
202
|
+
private yawEuler;
|
|
203
|
+
private addFollower;
|
|
204
|
+
}
|
|
205
|
+
export {};
|