@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,455 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UIWindowSystem - wires window chrome, keeps the `WindowManager` in sync
|
|
3
|
+
* with entities, applies focus ordering and minimize state.
|
|
4
|
+
*
|
|
5
|
+
* Reuse over recreation: the panel itself is loaded/rendered by the IWSDK's
|
|
6
|
+
* `PanelUISystem`; this system only discovers the chrome elements by their
|
|
7
|
+
* well-known ids and drives them.
|
|
8
|
+
*/
|
|
9
|
+
import { type Entity } from '@iwsdk/core';
|
|
10
|
+
declare const UIWindowSystem_base: import("elics").SystemConstructor<import("elics").SystemSchema, {
|
|
11
|
+
pendingWindows: {
|
|
12
|
+
required: (import("elics").Component<{
|
|
13
|
+
windowId: {
|
|
14
|
+
type: import("@iwsdk/core").Types.String;
|
|
15
|
+
default: string;
|
|
16
|
+
};
|
|
17
|
+
title: {
|
|
18
|
+
type: import("@iwsdk/core").Types.String;
|
|
19
|
+
default: string;
|
|
20
|
+
};
|
|
21
|
+
dockMode: {
|
|
22
|
+
type: import("@iwsdk/core").Types.Enum;
|
|
23
|
+
enum: {
|
|
24
|
+
readonly WorldLocked: "world-locked";
|
|
25
|
+
readonly BodyFollow: "body-follow";
|
|
26
|
+
readonly HeadLocked: "head-locked";
|
|
27
|
+
};
|
|
28
|
+
default: "world-locked";
|
|
29
|
+
};
|
|
30
|
+
movable: {
|
|
31
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
32
|
+
default: true;
|
|
33
|
+
};
|
|
34
|
+
closable: {
|
|
35
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
36
|
+
default: true;
|
|
37
|
+
};
|
|
38
|
+
minimizable: {
|
|
39
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
40
|
+
default: true;
|
|
41
|
+
};
|
|
42
|
+
pinnable: {
|
|
43
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
44
|
+
default: true;
|
|
45
|
+
};
|
|
46
|
+
billboardWhileDragging: {
|
|
47
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
48
|
+
default: true;
|
|
49
|
+
};
|
|
50
|
+
dragDelay: {
|
|
51
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
52
|
+
default: number;
|
|
53
|
+
};
|
|
54
|
+
followOffset: {
|
|
55
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
56
|
+
default: [number, number, number];
|
|
57
|
+
};
|
|
58
|
+
followSpeed: {
|
|
59
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
60
|
+
default: number;
|
|
61
|
+
};
|
|
62
|
+
followTolerance: {
|
|
63
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
64
|
+
default: number;
|
|
65
|
+
};
|
|
66
|
+
focusBias: {
|
|
67
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
68
|
+
default: number;
|
|
69
|
+
};
|
|
70
|
+
targetWidth: {
|
|
71
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
72
|
+
default: number;
|
|
73
|
+
};
|
|
74
|
+
targetHeight: {
|
|
75
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
76
|
+
default: number;
|
|
77
|
+
};
|
|
78
|
+
}> | import("elics").Component<{
|
|
79
|
+
config: {
|
|
80
|
+
type: import("@iwsdk/core").Types.String;
|
|
81
|
+
default: string;
|
|
82
|
+
};
|
|
83
|
+
maxWidth: {
|
|
84
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
85
|
+
default: number;
|
|
86
|
+
};
|
|
87
|
+
maxHeight: {
|
|
88
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
89
|
+
default: number;
|
|
90
|
+
};
|
|
91
|
+
}> | import("elics").Component<{
|
|
92
|
+
document: {
|
|
93
|
+
type: import("@iwsdk/core").Types.Object;
|
|
94
|
+
default: undefined;
|
|
95
|
+
};
|
|
96
|
+
}>)[];
|
|
97
|
+
excluded: import("elics").Component<{
|
|
98
|
+
appliedDockMode: {
|
|
99
|
+
type: import("@iwsdk/core").Types.String;
|
|
100
|
+
default: string;
|
|
101
|
+
};
|
|
102
|
+
chromeWired: {
|
|
103
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
104
|
+
default: false;
|
|
105
|
+
};
|
|
106
|
+
homeDockMode: {
|
|
107
|
+
type: import("@iwsdk/core").Types.String;
|
|
108
|
+
default: string;
|
|
109
|
+
};
|
|
110
|
+
homeRegion: {
|
|
111
|
+
type: import("@iwsdk/core").Types.String;
|
|
112
|
+
default: string;
|
|
113
|
+
};
|
|
114
|
+
homePosition: {
|
|
115
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
116
|
+
default: [number, number, number];
|
|
117
|
+
};
|
|
118
|
+
homeYaw: {
|
|
119
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
120
|
+
default: number;
|
|
121
|
+
};
|
|
122
|
+
}>[];
|
|
123
|
+
};
|
|
124
|
+
windows: {
|
|
125
|
+
required: (import("elics").Component<{
|
|
126
|
+
windowId: {
|
|
127
|
+
type: import("@iwsdk/core").Types.String;
|
|
128
|
+
default: string;
|
|
129
|
+
};
|
|
130
|
+
title: {
|
|
131
|
+
type: import("@iwsdk/core").Types.String;
|
|
132
|
+
default: string;
|
|
133
|
+
};
|
|
134
|
+
dockMode: {
|
|
135
|
+
type: import("@iwsdk/core").Types.Enum;
|
|
136
|
+
enum: {
|
|
137
|
+
readonly WorldLocked: "world-locked";
|
|
138
|
+
readonly BodyFollow: "body-follow";
|
|
139
|
+
readonly HeadLocked: "head-locked";
|
|
140
|
+
};
|
|
141
|
+
default: "world-locked";
|
|
142
|
+
};
|
|
143
|
+
movable: {
|
|
144
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
145
|
+
default: true;
|
|
146
|
+
};
|
|
147
|
+
closable: {
|
|
148
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
149
|
+
default: true;
|
|
150
|
+
};
|
|
151
|
+
minimizable: {
|
|
152
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
153
|
+
default: true;
|
|
154
|
+
};
|
|
155
|
+
pinnable: {
|
|
156
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
157
|
+
default: true;
|
|
158
|
+
};
|
|
159
|
+
billboardWhileDragging: {
|
|
160
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
161
|
+
default: true;
|
|
162
|
+
};
|
|
163
|
+
dragDelay: {
|
|
164
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
165
|
+
default: number;
|
|
166
|
+
};
|
|
167
|
+
followOffset: {
|
|
168
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
169
|
+
default: [number, number, number];
|
|
170
|
+
};
|
|
171
|
+
followSpeed: {
|
|
172
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
173
|
+
default: number;
|
|
174
|
+
};
|
|
175
|
+
followTolerance: {
|
|
176
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
177
|
+
default: number;
|
|
178
|
+
};
|
|
179
|
+
focusBias: {
|
|
180
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
181
|
+
default: number;
|
|
182
|
+
};
|
|
183
|
+
targetWidth: {
|
|
184
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
185
|
+
default: number;
|
|
186
|
+
};
|
|
187
|
+
targetHeight: {
|
|
188
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
189
|
+
default: number;
|
|
190
|
+
};
|
|
191
|
+
}> | import("elics").Component<{
|
|
192
|
+
appliedDockMode: {
|
|
193
|
+
type: import("@iwsdk/core").Types.String;
|
|
194
|
+
default: string;
|
|
195
|
+
};
|
|
196
|
+
chromeWired: {
|
|
197
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
198
|
+
default: false;
|
|
199
|
+
};
|
|
200
|
+
homeDockMode: {
|
|
201
|
+
type: import("@iwsdk/core").Types.String;
|
|
202
|
+
default: string;
|
|
203
|
+
};
|
|
204
|
+
homeRegion: {
|
|
205
|
+
type: import("@iwsdk/core").Types.String;
|
|
206
|
+
default: string;
|
|
207
|
+
};
|
|
208
|
+
homePosition: {
|
|
209
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
210
|
+
default: [number, number, number];
|
|
211
|
+
};
|
|
212
|
+
homeYaw: {
|
|
213
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
214
|
+
default: number;
|
|
215
|
+
};
|
|
216
|
+
}> | import("elics").Component<{
|
|
217
|
+
document: {
|
|
218
|
+
type: import("@iwsdk/core").Types.Object;
|
|
219
|
+
default: undefined;
|
|
220
|
+
};
|
|
221
|
+
}>)[];
|
|
222
|
+
};
|
|
223
|
+
}, World, import("@iwsdk/core").System<import("elics").SystemSchema, {
|
|
224
|
+
pendingWindows: {
|
|
225
|
+
required: (import("elics").Component<{
|
|
226
|
+
windowId: {
|
|
227
|
+
type: import("@iwsdk/core").Types.String;
|
|
228
|
+
default: string;
|
|
229
|
+
};
|
|
230
|
+
title: {
|
|
231
|
+
type: import("@iwsdk/core").Types.String;
|
|
232
|
+
default: string;
|
|
233
|
+
};
|
|
234
|
+
dockMode: {
|
|
235
|
+
type: import("@iwsdk/core").Types.Enum;
|
|
236
|
+
enum: {
|
|
237
|
+
readonly WorldLocked: "world-locked";
|
|
238
|
+
readonly BodyFollow: "body-follow";
|
|
239
|
+
readonly HeadLocked: "head-locked";
|
|
240
|
+
};
|
|
241
|
+
default: "world-locked";
|
|
242
|
+
};
|
|
243
|
+
movable: {
|
|
244
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
245
|
+
default: true;
|
|
246
|
+
};
|
|
247
|
+
closable: {
|
|
248
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
249
|
+
default: true;
|
|
250
|
+
};
|
|
251
|
+
minimizable: {
|
|
252
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
253
|
+
default: true;
|
|
254
|
+
};
|
|
255
|
+
pinnable: {
|
|
256
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
257
|
+
default: true;
|
|
258
|
+
};
|
|
259
|
+
billboardWhileDragging: {
|
|
260
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
261
|
+
default: true;
|
|
262
|
+
};
|
|
263
|
+
dragDelay: {
|
|
264
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
265
|
+
default: number;
|
|
266
|
+
};
|
|
267
|
+
followOffset: {
|
|
268
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
269
|
+
default: [number, number, number];
|
|
270
|
+
};
|
|
271
|
+
followSpeed: {
|
|
272
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
273
|
+
default: number;
|
|
274
|
+
};
|
|
275
|
+
followTolerance: {
|
|
276
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
277
|
+
default: number;
|
|
278
|
+
};
|
|
279
|
+
focusBias: {
|
|
280
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
281
|
+
default: number;
|
|
282
|
+
};
|
|
283
|
+
targetWidth: {
|
|
284
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
285
|
+
default: number;
|
|
286
|
+
};
|
|
287
|
+
targetHeight: {
|
|
288
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
289
|
+
default: number;
|
|
290
|
+
};
|
|
291
|
+
}> | import("elics").Component<{
|
|
292
|
+
config: {
|
|
293
|
+
type: import("@iwsdk/core").Types.String;
|
|
294
|
+
default: string;
|
|
295
|
+
};
|
|
296
|
+
maxWidth: {
|
|
297
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
298
|
+
default: number;
|
|
299
|
+
};
|
|
300
|
+
maxHeight: {
|
|
301
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
302
|
+
default: number;
|
|
303
|
+
};
|
|
304
|
+
}> | import("elics").Component<{
|
|
305
|
+
document: {
|
|
306
|
+
type: import("@iwsdk/core").Types.Object;
|
|
307
|
+
default: undefined;
|
|
308
|
+
};
|
|
309
|
+
}>)[];
|
|
310
|
+
excluded: import("elics").Component<{
|
|
311
|
+
appliedDockMode: {
|
|
312
|
+
type: import("@iwsdk/core").Types.String;
|
|
313
|
+
default: string;
|
|
314
|
+
};
|
|
315
|
+
chromeWired: {
|
|
316
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
317
|
+
default: false;
|
|
318
|
+
};
|
|
319
|
+
homeDockMode: {
|
|
320
|
+
type: import("@iwsdk/core").Types.String;
|
|
321
|
+
default: string;
|
|
322
|
+
};
|
|
323
|
+
homeRegion: {
|
|
324
|
+
type: import("@iwsdk/core").Types.String;
|
|
325
|
+
default: string;
|
|
326
|
+
};
|
|
327
|
+
homePosition: {
|
|
328
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
329
|
+
default: [number, number, number];
|
|
330
|
+
};
|
|
331
|
+
homeYaw: {
|
|
332
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
333
|
+
default: number;
|
|
334
|
+
};
|
|
335
|
+
}>[];
|
|
336
|
+
};
|
|
337
|
+
windows: {
|
|
338
|
+
required: (import("elics").Component<{
|
|
339
|
+
windowId: {
|
|
340
|
+
type: import("@iwsdk/core").Types.String;
|
|
341
|
+
default: string;
|
|
342
|
+
};
|
|
343
|
+
title: {
|
|
344
|
+
type: import("@iwsdk/core").Types.String;
|
|
345
|
+
default: string;
|
|
346
|
+
};
|
|
347
|
+
dockMode: {
|
|
348
|
+
type: import("@iwsdk/core").Types.Enum;
|
|
349
|
+
enum: {
|
|
350
|
+
readonly WorldLocked: "world-locked";
|
|
351
|
+
readonly BodyFollow: "body-follow";
|
|
352
|
+
readonly HeadLocked: "head-locked";
|
|
353
|
+
};
|
|
354
|
+
default: "world-locked";
|
|
355
|
+
};
|
|
356
|
+
movable: {
|
|
357
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
358
|
+
default: true;
|
|
359
|
+
};
|
|
360
|
+
closable: {
|
|
361
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
362
|
+
default: true;
|
|
363
|
+
};
|
|
364
|
+
minimizable: {
|
|
365
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
366
|
+
default: true;
|
|
367
|
+
};
|
|
368
|
+
pinnable: {
|
|
369
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
370
|
+
default: true;
|
|
371
|
+
};
|
|
372
|
+
billboardWhileDragging: {
|
|
373
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
374
|
+
default: true;
|
|
375
|
+
};
|
|
376
|
+
dragDelay: {
|
|
377
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
378
|
+
default: number;
|
|
379
|
+
};
|
|
380
|
+
followOffset: {
|
|
381
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
382
|
+
default: [number, number, number];
|
|
383
|
+
};
|
|
384
|
+
followSpeed: {
|
|
385
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
386
|
+
default: number;
|
|
387
|
+
};
|
|
388
|
+
followTolerance: {
|
|
389
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
390
|
+
default: number;
|
|
391
|
+
};
|
|
392
|
+
focusBias: {
|
|
393
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
394
|
+
default: number;
|
|
395
|
+
};
|
|
396
|
+
targetWidth: {
|
|
397
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
398
|
+
default: number;
|
|
399
|
+
};
|
|
400
|
+
targetHeight: {
|
|
401
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
402
|
+
default: number;
|
|
403
|
+
};
|
|
404
|
+
}> | import("elics").Component<{
|
|
405
|
+
appliedDockMode: {
|
|
406
|
+
type: import("@iwsdk/core").Types.String;
|
|
407
|
+
default: string;
|
|
408
|
+
};
|
|
409
|
+
chromeWired: {
|
|
410
|
+
type: import("@iwsdk/core").Types.Boolean;
|
|
411
|
+
default: false;
|
|
412
|
+
};
|
|
413
|
+
homeDockMode: {
|
|
414
|
+
type: import("@iwsdk/core").Types.String;
|
|
415
|
+
default: string;
|
|
416
|
+
};
|
|
417
|
+
homeRegion: {
|
|
418
|
+
type: import("@iwsdk/core").Types.String;
|
|
419
|
+
default: string;
|
|
420
|
+
};
|
|
421
|
+
homePosition: {
|
|
422
|
+
type: import("@iwsdk/core").Types.Vec3;
|
|
423
|
+
default: [number, number, number];
|
|
424
|
+
};
|
|
425
|
+
homeYaw: {
|
|
426
|
+
type: import("@iwsdk/core").Types.Float32;
|
|
427
|
+
default: number;
|
|
428
|
+
};
|
|
429
|
+
}> | import("elics").Component<{
|
|
430
|
+
document: {
|
|
431
|
+
type: import("@iwsdk/core").Types.Object;
|
|
432
|
+
default: undefined;
|
|
433
|
+
};
|
|
434
|
+
}>)[];
|
|
435
|
+
};
|
|
436
|
+
}>>;
|
|
437
|
+
export declare class UIWindowSystem extends UIWindowSystem_base {
|
|
438
|
+
private manager;
|
|
439
|
+
private entitiesById;
|
|
440
|
+
private localCamera;
|
|
441
|
+
init(): void;
|
|
442
|
+
update(): void;
|
|
443
|
+
entityFor(windowId: string): Entity | undefined;
|
|
444
|
+
private adoptWindow;
|
|
445
|
+
/** Return a window to its home: spawn region, or original placement/mode. */
|
|
446
|
+
returnHome(entity: Entity): void;
|
|
447
|
+
/** MIN when open, MAX when minimized - the label names the next action. */
|
|
448
|
+
private syncMinimizeLabel;
|
|
449
|
+
private syncPinLabel;
|
|
450
|
+
private releaseWindow;
|
|
451
|
+
private wireChrome;
|
|
452
|
+
private applyMinimized;
|
|
453
|
+
private documentOf;
|
|
454
|
+
}
|
|
455
|
+
export {};
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UIWindowSystem - wires window chrome, keeps the `WindowManager` in sync
|
|
3
|
+
* with entities, applies focus ordering and minimize state.
|
|
4
|
+
*
|
|
5
|
+
* Reuse over recreation: the panel itself is loaded/rendered by the IWSDK's
|
|
6
|
+
* `PanelUISystem`; this system only discovers the chrome elements by their
|
|
7
|
+
* well-known ids and drives them.
|
|
8
|
+
*/
|
|
9
|
+
import { PanelDocument, PanelUI, Vector3, createSystem, } from '@iwsdk/core';
|
|
10
|
+
import { UIDockedTo, UIWindow, UIWindowState } from '../components.js';
|
|
11
|
+
import { WINDOW_CHROME_IDS } from '@realitycollective/webxr-uiextensions';
|
|
12
|
+
import { windowManagerFor } from '../manager-registry.js';
|
|
13
|
+
import { minimizeLabelFor, pinLabelFor, } from '@realitycollective/webxr-uiextensions';
|
|
14
|
+
import { DockMode, isDockMode } from '@realitycollective/webxr-uiextensions';
|
|
15
|
+
let autoId = 0;
|
|
16
|
+
export class UIWindowSystem extends createSystem({
|
|
17
|
+
pendingWindows: {
|
|
18
|
+
required: [UIWindow, PanelUI, PanelDocument],
|
|
19
|
+
excluded: [UIWindowState],
|
|
20
|
+
},
|
|
21
|
+
windows: { required: [UIWindow, UIWindowState, PanelDocument] },
|
|
22
|
+
}) {
|
|
23
|
+
manager;
|
|
24
|
+
entitiesById = new Map();
|
|
25
|
+
localCamera = new Vector3();
|
|
26
|
+
init() {
|
|
27
|
+
this.manager = windowManagerFor(this.world);
|
|
28
|
+
this.cleanupFuncs.push(this.queries.pendingWindows.subscribe('qualify', (entity) => {
|
|
29
|
+
this.adoptWindow(entity);
|
|
30
|
+
}), this.queries.windows.subscribe('disqualify', (entity) => {
|
|
31
|
+
this.releaseWindow(entity);
|
|
32
|
+
}), this.manager.events.on('minimized', ({ id }) => this.applyMinimized(id, true)), this.manager.events.on('restored', ({ id }) => this.applyMinimized(id, false)), this.manager.events.on('minimized', (record) => this.syncMinimizeLabel(record)), this.manager.events.on('restored', (record) => this.syncMinimizeLabel(record)), this.manager.events.on('dockChanged', ({ window }) => {
|
|
33
|
+
const entity = this.entitiesById.get(window.id);
|
|
34
|
+
if (entity && entity.getValue(UIWindow, 'dockMode') !== window.dockMode) {
|
|
35
|
+
entity.setValue(UIWindow, 'dockMode', window.dockMode);
|
|
36
|
+
}
|
|
37
|
+
this.syncPinLabel(window);
|
|
38
|
+
}), this.manager.events.on('dragStarted', (window) => this.syncPinLabel(window)), this.manager.events.on('dragEnded', (window) => this.syncPinLabel(window)));
|
|
39
|
+
}
|
|
40
|
+
update() {
|
|
41
|
+
// Focus bias: nudge each window's document toward the viewer by a small
|
|
42
|
+
// amount inversely related to focus depth, so overlapping windows resolve
|
|
43
|
+
// in focus order. Computed in entity-local space so it holds for any
|
|
44
|
+
// window orientation.
|
|
45
|
+
for (const entity of this.queries.windows.entities) {
|
|
46
|
+
const id = entity.getValue(UIWindow, 'windowId');
|
|
47
|
+
if (!this.manager.has(id)) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const document = this.documentOf(entity);
|
|
51
|
+
const object = entity.object3D;
|
|
52
|
+
if (!document || !object) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const bias = entity.getValue(UIWindow, 'focusBias');
|
|
56
|
+
const depth = this.manager.orderOf(id);
|
|
57
|
+
const amount = bias * Math.max(0, this.manager.count - 1 - depth);
|
|
58
|
+
if (amount === 0) {
|
|
59
|
+
document.position.set(0, 0, 0);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
this.camera.getWorldPosition(this.localCamera);
|
|
63
|
+
object.worldToLocal(this.localCamera);
|
|
64
|
+
if (this.localCamera.lengthSq() === 0) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
document.position.copy(this.localCamera.normalize().multiplyScalar(amount));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
entityFor(windowId) {
|
|
71
|
+
return this.entitiesById.get(windowId);
|
|
72
|
+
}
|
|
73
|
+
adoptWindow(entity) {
|
|
74
|
+
let id = entity.getValue(UIWindow, 'windowId');
|
|
75
|
+
if (!id) {
|
|
76
|
+
id = `uix-window-${autoId++}`;
|
|
77
|
+
entity.setValue(UIWindow, 'windowId', id);
|
|
78
|
+
}
|
|
79
|
+
const title = entity.getValue(UIWindow, 'title');
|
|
80
|
+
const dockMode = entity.getValue(UIWindow, 'dockMode');
|
|
81
|
+
this.entitiesById.set(id, entity);
|
|
82
|
+
if (!this.manager.has(id)) {
|
|
83
|
+
this.manager.open(id, { title, dockMode });
|
|
84
|
+
}
|
|
85
|
+
this.wireChrome(entity, id, title);
|
|
86
|
+
// Snapshot "home" so the DOCK button can return the window: the spawn
|
|
87
|
+
// region if it was born docked, otherwise its placement + dock mode.
|
|
88
|
+
const object = entity.object3D;
|
|
89
|
+
entity.addComponent(UIWindowState, {
|
|
90
|
+
chromeWired: true,
|
|
91
|
+
appliedDockMode: '',
|
|
92
|
+
homeDockMode: dockMode,
|
|
93
|
+
homeRegion: entity.hasComponent(UIDockedTo)
|
|
94
|
+
? entity.getValue(UIDockedTo, 'regionId')
|
|
95
|
+
: '',
|
|
96
|
+
homePosition: object ? [object.position.x, object.position.y, object.position.z] : [0, 0, 0],
|
|
97
|
+
homeYaw: object ? object.rotation.y : 0,
|
|
98
|
+
});
|
|
99
|
+
this.syncPinLabel({ id, dockMode, dragging: false });
|
|
100
|
+
}
|
|
101
|
+
/** Return a window to its home: spawn region, or original placement/mode. */
|
|
102
|
+
returnHome(entity) {
|
|
103
|
+
const homeRegion = entity.getValue(UIWindowState, 'homeRegion');
|
|
104
|
+
if (homeRegion) {
|
|
105
|
+
if (entity.hasComponent(UIDockedTo) &&
|
|
106
|
+
entity.getValue(UIDockedTo, 'regionId') === homeRegion) {
|
|
107
|
+
return; // already home
|
|
108
|
+
}
|
|
109
|
+
if (entity.hasComponent(UIDockedTo)) {
|
|
110
|
+
entity.removeComponent(UIDockedTo);
|
|
111
|
+
}
|
|
112
|
+
entity.addComponent(UIDockedTo, { regionId: homeRegion });
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (entity.hasComponent(UIDockedTo)) {
|
|
116
|
+
entity.removeComponent(UIDockedTo);
|
|
117
|
+
}
|
|
118
|
+
const homeDockMode = entity.getValue(UIWindowState, 'homeDockMode');
|
|
119
|
+
if (isDockMode(homeDockMode)) {
|
|
120
|
+
entity.setValue(UIWindow, 'dockMode', homeDockMode);
|
|
121
|
+
}
|
|
122
|
+
if (homeDockMode === DockMode.WorldLocked) {
|
|
123
|
+
const object = entity.object3D;
|
|
124
|
+
const home = entity.getVectorView(UIWindowState, 'homePosition');
|
|
125
|
+
if (object) {
|
|
126
|
+
object.position.set(home[0] ?? 0, home[1] ?? 0, home[2] ?? 0);
|
|
127
|
+
object.rotation.set(0, entity.getValue(UIWindowState, 'homeYaw'), 0);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Follow modes re-snap on their own (the dock system syncs the Follower).
|
|
131
|
+
}
|
|
132
|
+
/** MIN when open, MAX when minimized - the label names the next action. */
|
|
133
|
+
syncMinimizeLabel(record) {
|
|
134
|
+
const entity = this.entitiesById.get(record.id);
|
|
135
|
+
const minimize = entity
|
|
136
|
+
? this.documentOf(entity)?.getElementById(WINDOW_CHROME_IDS.minimize)
|
|
137
|
+
: undefined;
|
|
138
|
+
minimize?.setProperties({ text: minimizeLabelFor(record) });
|
|
139
|
+
}
|
|
140
|
+
syncPinLabel(record) {
|
|
141
|
+
const entity = this.entitiesById.get(record.id);
|
|
142
|
+
const pin = entity
|
|
143
|
+
? this.documentOf(entity)?.getElementById(WINDOW_CHROME_IDS.pin)
|
|
144
|
+
: undefined;
|
|
145
|
+
pin?.setProperties({ text: pinLabelFor(record) });
|
|
146
|
+
}
|
|
147
|
+
releaseWindow(entity) {
|
|
148
|
+
const id = entity.getValue(UIWindow, 'windowId');
|
|
149
|
+
if (id && this.entitiesById.get(id) === entity) {
|
|
150
|
+
this.entitiesById.delete(id);
|
|
151
|
+
if (this.manager.has(id)) {
|
|
152
|
+
this.manager.close(id);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
wireChrome(entity, id, title) {
|
|
157
|
+
const document = this.documentOf(entity);
|
|
158
|
+
if (!document) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// IWSDK 0.5 removed PanelUI.maxWidth/maxHeight; world size is now the
|
|
162
|
+
// document's own concern. Fit into the requested box, preserving aspect
|
|
163
|
+
// ratio. Zero means "leave intrinsic" so the entity transform owns scale.
|
|
164
|
+
const targetWidth = entity.getValue(UIWindow, 'targetWidth') ?? 0;
|
|
165
|
+
const targetHeight = entity.getValue(UIWindow, 'targetHeight') ?? 0;
|
|
166
|
+
if (targetWidth > 0 && targetHeight > 0) {
|
|
167
|
+
document.setTargetDimensions(targetWidth, targetHeight);
|
|
168
|
+
}
|
|
169
|
+
const element = (elementId) => document.getElementById(elementId);
|
|
170
|
+
const titleEl = element(WINDOW_CHROME_IDS.title);
|
|
171
|
+
if (titleEl && title) {
|
|
172
|
+
titleEl.setProperties({ text: title });
|
|
173
|
+
}
|
|
174
|
+
// Chrome buttons live on the drag surface - keep their presses out of
|
|
175
|
+
// the title-bar drag handle so clicks never turn into (or arm) drags.
|
|
176
|
+
const swallowPress = (button) => {
|
|
177
|
+
button?.addEventListener('pointerdown', (event) => {
|
|
178
|
+
event?.stopPropagation?.();
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
swallowPress(element(WINDOW_CHROME_IDS.pin));
|
|
182
|
+
swallowPress(element(WINDOW_CHROME_IDS.dock));
|
|
183
|
+
swallowPress(element(WINDOW_CHROME_IDS.minimize));
|
|
184
|
+
swallowPress(element(WINDOW_CHROME_IDS.close));
|
|
185
|
+
// Any press anywhere on the window brings it to the front.
|
|
186
|
+
const root = element(WINDOW_CHROME_IDS.window);
|
|
187
|
+
root?.addEventListener('pointerdown', () => {
|
|
188
|
+
if (this.manager.has(id)) {
|
|
189
|
+
this.manager.focus(id);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
const close = element(WINDOW_CHROME_IDS.close);
|
|
193
|
+
if (close) {
|
|
194
|
+
if (entity.getValue(UIWindow, 'closable')) {
|
|
195
|
+
close.addEventListener('click', () => {
|
|
196
|
+
// Destroying the entity disqualifies it everywhere; releaseWindow
|
|
197
|
+
// then closes the manager record.
|
|
198
|
+
entity.destroy();
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
close.setProperties({ display: 'none' });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const minimize = element(WINDOW_CHROME_IDS.minimize);
|
|
206
|
+
if (minimize) {
|
|
207
|
+
if (entity.getValue(UIWindow, 'minimizable')) {
|
|
208
|
+
minimize.addEventListener('click', () => {
|
|
209
|
+
if (this.manager.has(id)) {
|
|
210
|
+
this.manager.toggleMinimized(id);
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
minimize.setProperties({ display: 'none' });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
const pin = element(WINDOW_CHROME_IDS.pin);
|
|
219
|
+
if (pin) {
|
|
220
|
+
if (entity.getValue(UIWindow, 'pinnable')) {
|
|
221
|
+
pin.addEventListener('click', () => {
|
|
222
|
+
if (this.manager.has(id)) {
|
|
223
|
+
this.manager.togglePin(id);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
pin.setProperties({ display: 'none' });
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const dock = element(WINDOW_CHROME_IDS.dock);
|
|
232
|
+
dock?.addEventListener('click', () => this.returnHome(entity));
|
|
233
|
+
}
|
|
234
|
+
applyMinimized(id, minimized) {
|
|
235
|
+
const entity = this.entitiesById.get(id);
|
|
236
|
+
const document = entity ? this.documentOf(entity) : undefined;
|
|
237
|
+
const content = document?.getElementById(WINDOW_CHROME_IDS.content);
|
|
238
|
+
content?.setProperties({ display: minimized ? 'none' : 'flex' });
|
|
239
|
+
}
|
|
240
|
+
documentOf(entity) {
|
|
241
|
+
return PanelDocument.data.document[entity.index];
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=window-system.js.map
|