angular-three 1.9.16 → 1.10.1

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.
Files changed (72) hide show
  1. package/esm2022/lib/canvas.mjs +243 -0
  2. package/esm2022/lib/directives/args.mjs +36 -0
  3. package/esm2022/lib/directives/common.mjs +32 -0
  4. package/esm2022/lib/directives/parent.mjs +36 -0
  5. package/esm2022/lib/directives/repeat.mjs +18 -0
  6. package/esm2022/lib/loader.mjs +55 -0
  7. package/esm2022/lib/pipes/push.mjs +50 -0
  8. package/esm2022/lib/portal.mjs +240 -0
  9. package/esm2022/lib/renderer/renderer.mjs +361 -0
  10. package/esm2022/lib/routed-scene.mjs +29 -0
  11. package/esm2022/lib/stores/rx-store.mjs +108 -0
  12. package/esm2022/lib/stores/store.mjs +404 -0
  13. package/esm2022/lib/types.mjs +2 -0
  14. package/esm2022/lib/utils/apply-props.mjs +107 -0
  15. package/esm2022/lib/utils/is.mjs +51 -0
  16. package/{fesm2020 → fesm2022}/angular-three.mjs +78 -61
  17. package/fesm2022/angular-three.mjs.map +1 -0
  18. package/lib/canvas.d.ts +1 -1
  19. package/lib/directives/args.d.ts +1 -1
  20. package/lib/directives/parent.d.ts +1 -1
  21. package/lib/directives/repeat.d.ts +1 -1
  22. package/lib/loader.d.ts +3 -11
  23. package/lib/portal.d.ts +2 -2
  24. package/lib/types.d.ts +91 -120
  25. package/lib/utils/is.d.ts +6 -1
  26. package/metadata.json +1 -0
  27. package/package.json +13 -17
  28. package/plugin/package.json +1 -4
  29. package/plugin/src/generators/init/compat.js +1 -1
  30. package/plugin/src/generators/init/compat.js.map +1 -1
  31. package/plugin/src/generators/init/init.d.ts +3 -3
  32. package/plugin/src/generators/init/init.js +23 -3
  33. package/plugin/src/generators/init/init.js.map +1 -1
  34. package/web-types.json +1 -0
  35. package/esm2020/lib/canvas.mjs +0 -242
  36. package/esm2020/lib/directives/args.mjs +0 -35
  37. package/esm2020/lib/directives/common.mjs +0 -31
  38. package/esm2020/lib/directives/parent.mjs +0 -35
  39. package/esm2020/lib/directives/repeat.mjs +0 -17
  40. package/esm2020/lib/loader.mjs +0 -56
  41. package/esm2020/lib/pipes/push.mjs +0 -49
  42. package/esm2020/lib/portal.mjs +0 -237
  43. package/esm2020/lib/renderer/renderer.mjs +0 -360
  44. package/esm2020/lib/routed-scene.mjs +0 -28
  45. package/esm2020/lib/stores/rx-store.mjs +0 -107
  46. package/esm2020/lib/stores/store.mjs +0 -402
  47. package/esm2020/lib/types.mjs +0 -2
  48. package/esm2020/lib/utils/apply-props.mjs +0 -91
  49. package/esm2020/lib/utils/is.mjs +0 -50
  50. package/fesm2015/angular-three.mjs +0 -3051
  51. package/fesm2015/angular-three.mjs.map +0 -1
  52. package/fesm2020/angular-three.mjs.map +0 -1
  53. /package/{esm2020 → esm2022}/angular-three.mjs +0 -0
  54. /package/{esm2020 → esm2022}/index.mjs +0 -0
  55. /package/{esm2020 → esm2022}/lib/di/before-render.mjs +0 -0
  56. /package/{esm2020 → esm2022}/lib/di/catalogue.mjs +0 -0
  57. /package/{esm2020 → esm2022}/lib/di/destroy.mjs +0 -0
  58. /package/{esm2020 → esm2022}/lib/di/ref.mjs +0 -0
  59. /package/{esm2020 → esm2022}/lib/di/run-in-context.mjs +0 -0
  60. /package/{esm2020 → esm2022}/lib/events.mjs +0 -0
  61. /package/{esm2020 → esm2022}/lib/loop.mjs +0 -0
  62. /package/{esm2020 → esm2022}/lib/renderer/di.mjs +0 -0
  63. /package/{esm2020 → esm2022}/lib/renderer/enums.mjs +0 -0
  64. /package/{esm2020 → esm2022}/lib/renderer/provider.mjs +0 -0
  65. /package/{esm2020 → esm2022}/lib/renderer/store.mjs +0 -0
  66. /package/{esm2020 → esm2022}/lib/renderer/utils.mjs +0 -0
  67. /package/{esm2020 → esm2022}/lib/utils/attach.mjs +0 -0
  68. /package/{esm2020 → esm2022}/lib/utils/instance.mjs +0 -0
  69. /package/{esm2020 → esm2022}/lib/utils/make.mjs +0 -0
  70. /package/{esm2020 → esm2022}/lib/utils/safe-detect-changes.mjs +0 -0
  71. /package/{esm2020 → esm2022}/lib/utils/update.mjs +0 -0
  72. /package/{esm2020 → esm2022}/lib/web/events.mjs +0 -0
@@ -1,3051 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { inject, ChangeDetectorRef, ElementRef, Injectable, InjectionToken, ViewContainerRef, TemplateRef, Directive, Input, EventEmitter, getDebugNode, RendererFactory2, makeEnvironmentProviders, EnvironmentInjector, createEnvironmentInjector, Component, HostBinding, Output, ViewChild, Injector, Pipe, SkipSelf, ContentChild } from '@angular/core';
3
- import { provideNgxResizeOptions, NgxResize } from 'ngx-resize';
4
- import { isObservable, of, map, from, tap, retry, catchError, share, ReplaySubject, switchMap, forkJoin, take, BehaviorSubject, startWith, combineLatest, filter, distinctUntilChanged, takeUntil, merge } from 'rxjs';
5
- import * as THREE from 'three';
6
- import { __rest } from 'tslib';
7
- import { DOCUMENT, NgForOf, NgIf } from '@angular/common';
8
- import { RxState } from '@rx-angular/state';
9
- import * as i1 from '@angular/router';
10
- import { ActivationEnd, RouterOutlet } from '@angular/router';
11
-
12
- const idCache = {};
13
- function makeId(event) {
14
- if (event) {
15
- return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
16
- }
17
- const newId = THREE.MathUtils.generateUUID();
18
- // ensure not already used
19
- if (!idCache[newId]) {
20
- idCache[newId] = true;
21
- return newId;
22
- }
23
- return makeId();
24
- }
25
- function makeDpr(dpr, window) {
26
- const target = (window === null || window === void 0 ? void 0 : window.devicePixelRatio) || 1;
27
- return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
28
- }
29
- function makeDefaultCamera(isOrthographic, size) {
30
- if (isOrthographic)
31
- return new THREE.OrthographicCamera(0, 0, 0, 0, 0.1, 1000);
32
- return new THREE.PerspectiveCamera(75, size.width / size.height, 0.1, 1000);
33
- }
34
- function makeDefaultRenderer(glOptions, canvasElement) {
35
- const customRenderer = (typeof glOptions === 'function' ? glOptions(canvasElement) : glOptions);
36
- if ((customRenderer === null || customRenderer === void 0 ? void 0 : customRenderer.render) != null)
37
- return customRenderer;
38
- return new THREE.WebGLRenderer(Object.assign({ powerPreference: 'high-performance', canvas: canvasElement, antialias: true, alpha: true }, (glOptions || {})));
39
- }
40
- function makeObjectGraph(object) {
41
- const data = { nodes: {}, materials: {} };
42
- if (object) {
43
- object.traverse((child) => {
44
- if (child.name)
45
- data.nodes[child.name] = child;
46
- if ('material' in child && !data.materials[child.material.name]) {
47
- data.materials[child.material.name] = child
48
- .material;
49
- }
50
- });
51
- }
52
- return data;
53
- }
54
-
55
- function safeDetectChanges(cdr) {
56
- if (!cdr)
57
- return;
58
- try {
59
- // dynamic created component with ViewContainerRef#createComponent does not have Context
60
- // but it has _attachedToViewContainer
61
- if (cdr['context'] || cdr['_attachedToViewContainer']) {
62
- cdr.detectChanges();
63
- }
64
- }
65
- catch (e) {
66
- cdr.markForCheck();
67
- }
68
- }
69
-
70
- const cached = new Map();
71
- function load(loaderConstructorFactory, input, extensions, onProgress) {
72
- const urls$ = isObservable(input) ? input : of(input);
73
- return urls$.pipe(map((inputs) => {
74
- const loaderConstructor = loaderConstructorFactory(inputs);
75
- const loader = new loaderConstructor();
76
- if (extensions)
77
- extensions(loader);
78
- const urls = Array.isArray(inputs) ? inputs : typeof inputs === 'string' ? [inputs] : Object.values(inputs);
79
- return [
80
- urls.map((url) => {
81
- if (!cached.has(url)) {
82
- cached.set(url, from(loader.loadAsync(url, onProgress)).pipe(tap((data) => {
83
- if (data.scene)
84
- Object.assign(data, makeObjectGraph(data.scene));
85
- }), retry(2), catchError((err) => {
86
- console.error(`[NGT] Error loading ${url}: ${err.message}`);
87
- return of([]);
88
- }), share({ connector: () => new ReplaySubject(1) })));
89
- }
90
- return cached.get(url);
91
- }),
92
- inputs,
93
- ];
94
- }));
95
- }
96
- function injectLoader(loaderConstructorFactory, input, extensions, onProgress) {
97
- const cdr = inject(ChangeDetectorRef);
98
- return load(loaderConstructorFactory, input, extensions, onProgress).pipe(switchMap(([observables$, inputs]) => {
99
- return forkJoin(observables$).pipe(map((results) => {
100
- if (Array.isArray(inputs))
101
- return results;
102
- if (typeof inputs === 'string')
103
- return results[0];
104
- const keys = Object.keys(inputs);
105
- return keys.reduce((result, key) => {
106
- result[key] = results[keys.indexOf(key)];
107
- return result;
108
- }, {});
109
- }), tap(() => {
110
- requestAnimationFrame(() => void safeDetectChanges(cdr));
111
- }));
112
- }));
113
- }
114
- injectLoader.destroy = () => {
115
- cached.clear();
116
- };
117
- injectLoader.preLoad = (loaderConstructorFactory, inputs, extensions) => {
118
- load(loaderConstructorFactory, inputs, extensions).pipe(take(1)).subscribe();
119
- };
120
- const injectNgtLoader = injectLoader;
121
-
122
- function createSubs(callback, subs) {
123
- const sub = { callback };
124
- subs.add(sub);
125
- return () => void subs.delete(sub);
126
- }
127
- const globalEffects = new Set();
128
- const globalAfterEffects = new Set();
129
- const globalTailEffects = new Set();
130
- /**
131
- * Adds a global render callback which is called each frame.
132
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addEffect
133
- */
134
- const addEffect = (callback) => createSubs(callback, globalEffects);
135
- /**
136
- * Adds a global after-render callback which is called each frame.
137
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addAfterEffect
138
- */
139
- const addAfterEffect = (callback) => createSubs(callback, globalAfterEffects);
140
- /**
141
- * Adds a global callback which is called when rendering stops.
142
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#addTail
143
- */
144
- const addTail = (callback) => createSubs(callback, globalTailEffects);
145
- function run(effects, timestamp) {
146
- if (!effects.size)
147
- return;
148
- for (const { callback } of effects.values()) {
149
- callback(timestamp);
150
- }
151
- }
152
- function flushGlobalEffects(type, timestamp) {
153
- switch (type) {
154
- case 'before':
155
- return run(globalEffects, timestamp);
156
- case 'after':
157
- return run(globalAfterEffects, timestamp);
158
- case 'tail':
159
- return run(globalTailEffects, timestamp);
160
- }
161
- }
162
- function render(timestamp, store, frame) {
163
- const state = store.get();
164
- // Run local effects
165
- let delta = state.clock.getDelta();
166
- // In frameloop='never' mode, clock times are updated using the provided timestamp
167
- if (state.frameloop === 'never' && typeof timestamp === 'number') {
168
- delta = timestamp - state.clock.elapsedTime;
169
- state.clock.oldTime = state.clock.elapsedTime;
170
- state.clock.elapsedTime = timestamp;
171
- }
172
- // Call subscribers (useFrame)
173
- // subscribers = state.internal.subscribers;
174
- for (let i = 0; i < state.internal.subscribers.length; i++) {
175
- const subscriber = state.internal.subscribers[i];
176
- subscriber.callback(Object.assign(Object.assign({}, state), { delta, frame }));
177
- }
178
- // Render content
179
- if (!state.internal.priority && state.gl.render) {
180
- state.gl.render(state.scene, state.camera);
181
- }
182
- // Decrease frame count
183
- state.internal.frames = Math.max(0, state.internal.frames - 1);
184
- return state.frameloop === 'always' ? 1 : state.internal.frames;
185
- }
186
- function createLoop(roots) {
187
- let running = false;
188
- let repeat;
189
- let frame;
190
- function loop(timestamp) {
191
- var _a;
192
- frame = requestAnimationFrame(loop);
193
- running = true;
194
- repeat = 0;
195
- // Run effects
196
- flushGlobalEffects('before', timestamp);
197
- // Render all roots
198
- for (const root of roots.values()) {
199
- const state = root.get();
200
- // If the frameloop is invalidated, do not run another frame
201
- if (state.internal.active &&
202
- (state.frameloop === 'always' || state.internal.frames > 0) &&
203
- !((_a = state.gl.xr) === null || _a === void 0 ? void 0 : _a.isPresenting)) {
204
- repeat += render(timestamp, root);
205
- }
206
- }
207
- // Run after-effects
208
- flushGlobalEffects('after', timestamp);
209
- // Stop the loop if nothing invalidates it
210
- if (repeat === 0) {
211
- // Tail call effects, they are called when rendering stops
212
- flushGlobalEffects('tail', timestamp);
213
- // Flag end of operation
214
- running = false;
215
- return cancelAnimationFrame(frame);
216
- }
217
- }
218
- function invalidate(store, frames = 1) {
219
- var _a;
220
- const state = store === null || store === void 0 ? void 0 : store.get();
221
- if (!state)
222
- return roots.forEach((root) => invalidate(root, frames));
223
- if (((_a = state.gl.xr) === null || _a === void 0 ? void 0 : _a.isPresenting) || !state.internal.active || state.frameloop === 'never')
224
- return;
225
- // Increase frames, do not go higher than 60
226
- state.internal.frames = Math.min(60, state.internal.frames + frames);
227
- // If the render-loop isn't active, start it
228
- if (!running) {
229
- running = true;
230
- requestAnimationFrame(loop);
231
- }
232
- }
233
- function advance(timestamp, runGlobalEffects = true, store, frame) {
234
- const state = store === null || store === void 0 ? void 0 : store.get();
235
- if (runGlobalEffects)
236
- flushGlobalEffects('before', timestamp);
237
- if (!state)
238
- for (const root of roots.values())
239
- render(timestamp, root);
240
- // safe to assume store is available here
241
- else
242
- render(timestamp, store, frame);
243
- if (runGlobalEffects)
244
- flushGlobalEffects('after', timestamp);
245
- }
246
- return {
247
- loop,
248
- /**
249
- * Invalidates the view, requesting a frame to be rendered. Will globally invalidate unless passed a root's state.
250
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#invalidate
251
- */
252
- invalidate,
253
- /**
254
- * Advances the frameloop and runs render effects, useful for when manually rendering via `frameloop="never"`.
255
- * @see https://docs.pmnd.rs/react-three-fiber/api/additional-exports#advance
256
- */
257
- advance,
258
- };
259
- }
260
-
261
- const is = {
262
- obj: (a) => a === Object(a) && !Array.isArray(a) && typeof a !== 'function',
263
- material: (a) => !!a && a.isMaterial,
264
- geometry: (a) => !!a && a.isBufferGeometry,
265
- orthographicCamera: (a) => !!a && a.isOrthographicCamera,
266
- perspectiveCamera: (a) => !!a && a.isPerspectiveCamera,
267
- camera: (a) => !!a && a.isCamera,
268
- renderer: (a) => !!a && a instanceof THREE.WebGLRenderer,
269
- scene: (a) => !!a && a.isScene,
270
- object3D: (a) => !!a && a.isObject3D,
271
- instance: (a) => !!a && !!a['__ngt__'],
272
- ref: (a) => a instanceof ElementRef,
273
- equ(a, b, { arrays = 'shallow', objects = 'reference', strict = true } = {}) {
274
- // Wrong type or one of the two undefined, doesn't match
275
- if (typeof a !== typeof b || !!a !== !!b)
276
- return false;
277
- // Atomic, just compare a against b
278
- if (typeof a === 'string' || typeof a === 'number')
279
- return a === b;
280
- const isObj = is.obj(a);
281
- if (isObj && objects === 'reference')
282
- return a === b;
283
- const isArr = Array.isArray(a);
284
- if (isArr && arrays === 'reference')
285
- return a === b;
286
- // Array or Object, shallow compare first to see if it's a match
287
- if ((isArr || isObj) && a === b)
288
- return true;
289
- // Last resort, go through keys
290
- let i;
291
- for (i in a)
292
- if (!(i in b))
293
- return false;
294
- for (i in strict ? b : a)
295
- if (a[i] !== b[i])
296
- return false;
297
- if (i === void 0) {
298
- if (isArr && a.length === 0 && b.length === 0)
299
- return true;
300
- if (isObj && Object.keys(a).length === 0 && Object.keys(b).length === 0)
301
- return true;
302
- if (a !== b)
303
- return false;
304
- }
305
- return true;
306
- },
307
- };
308
-
309
- function checkNeedsUpdate(value) {
310
- if (value !== null && is.obj(value) && 'needsUpdate' in value) {
311
- value['needsUpdate'] = true;
312
- if ('uniformsNeedUpdate' in value)
313
- value['uniformsNeedUpdate'] = true;
314
- }
315
- }
316
- function checkUpdate(value) {
317
- if (is.object3D(value))
318
- value.updateMatrix();
319
- if (is.camera(value)) {
320
- if (is.perspectiveCamera(value) || is.orthographicCamera(value))
321
- value.updateProjectionMatrix();
322
- value.updateMatrixWorld();
323
- }
324
- checkNeedsUpdate(value);
325
- }
326
- function updateCamera(camera, size) {
327
- if (!camera.manual) {
328
- if (is.orthographicCamera(camera)) {
329
- camera.left = size.width / -2;
330
- camera.right = size.width / 2;
331
- camera.top = size.height / 2;
332
- camera.bottom = size.height / -2;
333
- }
334
- else
335
- camera.aspect = size.width / size.height;
336
- camera.updateProjectionMatrix();
337
- camera.updateMatrixWorld();
338
- }
339
- }
340
-
341
- function getLocalState(obj) {
342
- if (!obj)
343
- return {};
344
- return obj['__ngt__'] || {};
345
- }
346
- function invalidateInstance(instance) {
347
- var _a;
348
- const state = (_a = getLocalState(instance).store) === null || _a === void 0 ? void 0 : _a.get();
349
- if (state && state.internal.frames === 0)
350
- state.invalidate();
351
- checkUpdate(instance);
352
- }
353
- function prepare(object, localState) {
354
- const instance = (typeof object === 'function' ? object() : object);
355
- if ((localState === null || localState === void 0 ? void 0 : localState.primitive) || !instance.__ngt__) {
356
- const _a = localState || {}, { objects = new BehaviorSubject([]), nonObjects = new BehaviorSubject([]) } = _a, rest = __rest(_a, ["objects", "nonObjects"]);
357
- instance.__ngt__ = Object.assign({ previousAttach: null, store: null, parent: null, memoized: {}, eventCount: 0, handlers: {}, objects,
358
- nonObjects, add: (object, type) => {
359
- const current = instance.__ngt__[type].value;
360
- const foundIndex = current.indexOf((obj) => obj === object);
361
- if (foundIndex > -1) {
362
- // if we add an object with the same reference, then we switch it out
363
- // and update the BehaviorSubject
364
- current.splice(foundIndex, 1, object);
365
- instance.__ngt__[type].next(current);
366
- }
367
- else {
368
- instance.__ngt__[type].next([...instance.__ngt__[type].value, object]);
369
- }
370
- notifyAncestors(instance.__ngt__.parent);
371
- }, remove: (object, type) => {
372
- instance.__ngt__[type].next(instance.__ngt__[type].value.filter((o) => o !== object));
373
- notifyAncestors(instance.__ngt__.parent);
374
- } }, rest);
375
- }
376
- return instance;
377
- }
378
- function notifyAncestors(instance) {
379
- if (!instance)
380
- return;
381
- const localState = getLocalState(instance);
382
- if (localState.objects)
383
- localState.objects.next(localState.objects.value);
384
- if (localState.nonObjects)
385
- localState.nonObjects.next(localState.nonObjects.value);
386
- notifyAncestors(localState.parent);
387
- }
388
-
389
- function diffProps(instance, props) {
390
- const propsEntries = Object.entries(props);
391
- const changes = [];
392
- for (const [propKey, propValue] of propsEntries) {
393
- if (is.equ(propValue, instance[propKey]))
394
- continue;
395
- changes.push([propKey, propValue]);
396
- }
397
- return changes;
398
- }
399
- function applyProps(instance, props) {
400
- var _a;
401
- // if props is empty
402
- if (!Object.keys(props).length)
403
- return instance;
404
- // filter equals, events , and reserved props
405
- const localState = getLocalState(instance);
406
- const rootState = (_a = localState.store) === null || _a === void 0 ? void 0 : _a.get();
407
- const changes = diffProps(instance, props);
408
- for (let i = 0; i < changes.length; i++) {
409
- const key = changes[i][0];
410
- const currentInstance = instance;
411
- const targetProp = currentInstance[key];
412
- const value = changes[i][1];
413
- // special treatmen for objects with support for set/copy, and layers
414
- if (targetProp && targetProp['set'] && (targetProp['copy'] || targetProp instanceof THREE.Layers)) {
415
- const isColor = targetProp instanceof THREE.Color;
416
- // if value is an array
417
- if (Array.isArray(value)) {
418
- if (targetProp['fromArray'])
419
- targetProp['fromArray'](value);
420
- else
421
- targetProp['set'](...value);
422
- }
423
- // test again target.copy
424
- else if (targetProp['copy'] &&
425
- value &&
426
- value.constructor &&
427
- targetProp.constructor.name === value.constructor.name) {
428
- targetProp['copy'](value);
429
- if (!THREE.ColorManagement && !rootState.linear && isColor)
430
- targetProp['convertSRGBToLinear']();
431
- }
432
- // if nothing else fits, just set the single value, ignore undefined
433
- else if (value !== undefined) {
434
- const isColor = targetProp instanceof THREE.Color;
435
- // allow setting array scalars
436
- if (!isColor && targetProp['setScalar'])
437
- targetProp['setScalar'](value);
438
- // layers have no copy function, copy the mask
439
- else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers)
440
- targetProp.mask = value.mask;
441
- // otherwise just set ...
442
- else
443
- targetProp['set'](value);
444
- // auto-convert srgb
445
- if (!THREE.ColorManagement && !(rootState === null || rootState === void 0 ? void 0 : rootState.linear) && isColor)
446
- targetProp.convertSRGBToLinear();
447
- }
448
- }
449
- // else just overwrite the value
450
- else {
451
- currentInstance[key] = value;
452
- // auto-convert srgb textures
453
- if (!(rootState === null || rootState === void 0 ? void 0 : rootState.linear) &&
454
- currentInstance[key] instanceof THREE.Texture &&
455
- currentInstance[key].format === THREE.RGBAFormat &&
456
- currentInstance[key].type === THREE.UnsignedByteType) {
457
- currentInstance[key]['encoding'] = THREE.sRGBEncoding;
458
- }
459
- }
460
- checkUpdate(targetProp);
461
- invalidateInstance(instance);
462
- }
463
- const instanceHandlers = localState.eventCount;
464
- if (localState.parent && rootState.internal && instance['raycast'] && instanceHandlers !== localState.eventCount) {
465
- // pre-emptively remove the interaction from manager
466
- rootState.removeInteraction(instance['uuid']);
467
- // add the instance to the interaction manager only when it has handlers
468
- if (localState.eventCount)
469
- rootState.addInteraction(instance);
470
- }
471
- if (localState.parent && localState.afterUpdate && localState.afterUpdate.observed && changes.length) {
472
- localState.afterUpdate.emit(instance);
473
- }
474
- return instance;
475
- }
476
-
477
- const startWithUndefined = () => startWith(undefined);
478
- /**
479
- * An extended `tap` operator that accepts an `effectFn` which:
480
- * - runs on every `next` notification from `source$`
481
- * - can optionally return a `cleanUp` function that
482
- * invokes from the 2nd `next` notification onward and on `unsubscribe` (destroyed)
483
- *
484
- * @example
485
- * ```typescript
486
- * source$.pipe(
487
- * tapEffect((sourceValue) = {
488
- * const cb = () => {
489
- * doStuff(sourceValue);
490
- * };
491
- * addListener('event', cb);
492
- *
493
- * return () => {
494
- * removeListener('event', cb);
495
- * }
496
- * })
497
- * )
498
- * ```
499
- */
500
- function tapEffect(effectFn) {
501
- let cleanupFn = () => { };
502
- let firstRun = false;
503
- let prev = undefined;
504
- const teardown = (error) => () => {
505
- if (cleanupFn)
506
- cleanupFn({ prev, complete: true, error });
507
- };
508
- return tap({
509
- next: (value) => {
510
- if (cleanupFn && firstRun)
511
- cleanupFn({ prev, complete: false, error: false });
512
- const cleanUpOrVoid = effectFn(value);
513
- if (cleanUpOrVoid)
514
- cleanupFn = cleanUpOrVoid;
515
- prev = value;
516
- if (!firstRun)
517
- firstRun = true;
518
- },
519
- complete: teardown(false),
520
- unsubscribe: teardown(false),
521
- error: teardown(true),
522
- });
523
- }
524
- class NgtRxStore extends RxState {
525
- constructor() {
526
- super();
527
- // set a dummy property so that initial this.get() won't return undefined
528
- this.set({ __ngt_dummy__: '__ngt_dummy__' });
529
- // override set so our consumers don't have to handle undefined for state that already have default values
530
- const originalSet = this.set.bind(this);
531
- Object.defineProperty(this, 'set', {
532
- get: () => {
533
- return (...args) => {
534
- const firstArg = args[0];
535
- if (is.obj(firstArg)) {
536
- const modArgs = Object.entries(firstArg).reduce((modded, [key, value]) => {
537
- modded[key] = value === undefined ? this.get(key) : value;
538
- return modded;
539
- }, {});
540
- return originalSet(modArgs);
541
- }
542
- return originalSet(...args);
543
- };
544
- },
545
- });
546
- // override get to return {} if get() returns undefined
547
- const originalGet = this.get.bind(this);
548
- Object.defineProperty(this, 'get', {
549
- get: () => (...args) => {
550
- var _a;
551
- if (args.length === 0)
552
- return (_a = originalGet()) !== null && _a !== void 0 ? _a : {};
553
- return originalGet(...args);
554
- },
555
- });
556
- // call initialize that might be setup by derived Stores
557
- this.initialize();
558
- }
559
- initialize() {
560
- return;
561
- }
562
- effect(obs, sideEffectFn) {
563
- return this.hold(obs.pipe(tapEffect(sideEffectFn)));
564
- }
565
- triggerChangeDetection(cdr, keys = []) {
566
- let $ = this.$;
567
- if (keys.length) {
568
- $ = combineLatest(keys.map((key) => { var _a; return this.select(key).pipe(startWith((_a = this.get(key)) !== null && _a !== void 0 ? _a : undefined)); }));
569
- }
570
- this.hold($, () => void requestAnimationFrame(() => void safeDetectChanges(cdr)));
571
- }
572
- }
573
- NgtRxStore.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtRxStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
574
- NgtRxStore.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtRxStore });
575
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtRxStore, decorators: [{
576
- type: Injectable
577
- }], ctorParameters: function () { return []; } });
578
-
579
- const rootStateMap = new Map();
580
- const { invalidate, advance } = createLoop(rootStateMap);
581
- const shallowLoose = { objects: 'shallow', strict: false };
582
- class NgtStore extends NgtRxStore {
583
- constructor() {
584
- super(...arguments);
585
- this.parentStore = inject(NgtStore, { optional: true, skipSelf: true });
586
- this.window = inject(DOCUMENT).defaultView;
587
- this.isInit = false;
588
- }
589
- init() {
590
- if (!this.isInit) {
591
- const position = new THREE.Vector3();
592
- const defaultTarget = new THREE.Vector3();
593
- const tempTarget = new THREE.Vector3();
594
- const getCurrentViewport = (camera = this.get('camera'), target = defaultTarget, size = this.get('size')) => {
595
- const { width, height, top, left } = size;
596
- const aspect = width / height;
597
- if (target instanceof THREE.Vector3)
598
- tempTarget.copy(target);
599
- else
600
- tempTarget.set(...target);
601
- const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
602
- if (is.orthographicCamera(camera)) {
603
- return {
604
- width: width / camera.zoom,
605
- height: height / camera.zoom,
606
- top,
607
- left,
608
- factor: 1,
609
- distance,
610
- aspect,
611
- };
612
- }
613
- const fov = (camera.fov * Math.PI) / 180; // convert vertical fov to radians
614
- const h = 2 * Math.tan(fov / 2) * distance; // visible height
615
- const w = h * aspect;
616
- return { width: w, height: h, top, left, factor: width / w, distance, aspect };
617
- };
618
- let performanceTimeout;
619
- const setPerformanceCurrent = (current) => {
620
- this.set((state) => ({ performance: Object.assign(Object.assign({}, state.performance), { current }) }));
621
- };
622
- this.set({
623
- get: this.get.bind(this),
624
- set: this.set.bind(this),
625
- select: this.select.bind(this),
626
- ready: false,
627
- scene: prepare(new THREE.Scene(), { store: this }),
628
- events: { priority: 1, enabled: true, connected: false },
629
- invalidate: (frames = 1) => invalidate(this, frames),
630
- advance: (timestamp, runGlobalEffects) => advance(timestamp, runGlobalEffects, this),
631
- legacy: false,
632
- linear: false,
633
- flat: false,
634
- controls: null,
635
- clock: new THREE.Clock(),
636
- pointer: new THREE.Vector2(),
637
- frameloop: 'always',
638
- performance: {
639
- current: 1,
640
- min: 0.5,
641
- max: 1,
642
- debounce: 200,
643
- regress: () => {
644
- const state = this.get();
645
- // clear timeout
646
- if (performanceTimeout)
647
- clearTimeout(performanceTimeout);
648
- // set lower bound
649
- if (state.performance.current !== state.performance.min) {
650
- setPerformanceCurrent(state.performance.min);
651
- }
652
- // go back to upper bound
653
- performanceTimeout = setTimeout(() => setPerformanceCurrent(this.get('performance', 'max') || 1), state.performance.debounce);
654
- },
655
- },
656
- size: { width: 0, height: 0, top: 0, left: 0 },
657
- viewport: {
658
- initialDpr: 0,
659
- dpr: 0,
660
- width: 0,
661
- height: 0,
662
- top: 0,
663
- left: 0,
664
- aspect: 0,
665
- distance: 0,
666
- factor: 0,
667
- getCurrentViewport,
668
- },
669
- previousStore: this.parentStore,
670
- internal: {
671
- active: false,
672
- priority: 0,
673
- frames: 0,
674
- lastEvent: null,
675
- interaction: [],
676
- hovered: new Map(),
677
- subscribers: [],
678
- initialClick: [0, 0],
679
- initialHits: [],
680
- capturedMap: new Map(),
681
- subscribe: (callback, priority = 0, store = this) => {
682
- const internal = this.get('internal');
683
- // If this subscription was given a priority, it takes rendering into its own hands
684
- // For that reason we switch off automatic rendering and increase the manual flag
685
- // As long as this flag is positive there can be no internal rendering at all
686
- // because there could be multiple render subscriptions
687
- internal.priority = internal.priority + (priority > 0 ? 1 : 0);
688
- internal.subscribers.push({ priority, store, callback });
689
- // Register subscriber and sort layers from lowest to highest, meaning,
690
- // highest priority renders last (on top of the other frames)
691
- internal.subscribers.sort((a, b) => (a.priority || 0) - (b.priority || 0));
692
- return () => {
693
- const internal = this.get('internal');
694
- if (internal === null || internal === void 0 ? void 0 : internal.subscribers) {
695
- // Decrease manual flag if this subscription had a priority
696
- internal.priority = internal.priority - (priority > 0 ? 1 : 0);
697
- // Remove subscriber from list
698
- internal.subscribers = internal.subscribers.filter((s) => s.callback !== callback);
699
- }
700
- };
701
- },
702
- },
703
- setEvents: (events) => {
704
- this.set((state) => ({ events: Object.assign(Object.assign({}, state.events), events) }));
705
- },
706
- setSize: (width, height, top, left) => {
707
- const camera = this.get('camera');
708
- const size = { width, height, top: top || 0, left: left || 0 };
709
- this.set((state) => ({
710
- size,
711
- viewport: Object.assign(Object.assign({}, state.viewport), getCurrentViewport(camera, defaultTarget, size)),
712
- }));
713
- },
714
- setDpr: (dpr) => {
715
- const resolved = makeDpr(dpr, this.window);
716
- this.set((state) => ({
717
- viewport: Object.assign(Object.assign({}, state.viewport), { dpr: resolved, initialDpr: state.viewport.initialDpr || resolved }),
718
- }));
719
- },
720
- setFrameloop: (frameloop = 'always') => {
721
- const clock = this.get('clock');
722
- clock.stop();
723
- clock.elapsedTime = 0;
724
- if (frameloop !== 'never') {
725
- clock.start();
726
- clock.elapsedTime = 0;
727
- }
728
- this.set({ frameloop });
729
- },
730
- addInteraction: (interaction) => {
731
- this.set((state) => ({
732
- internal: Object.assign(Object.assign({}, state.internal), { interaction: [...state.internal.interaction, interaction] }),
733
- }));
734
- },
735
- removeInteraction: (uuid) => {
736
- this.set((state) => ({
737
- internal: Object.assign(Object.assign({}, state.internal), { interaction: state.internal.interaction.filter((interaction) => interaction.uuid !== uuid) }),
738
- }));
739
- },
740
- });
741
- this.isInit = true;
742
- this.resize();
743
- }
744
- }
745
- configure(inputs, canvasElement) {
746
- var _a, _b;
747
- const { gl: glOptions, size: sizeOptions, camera: cameraOptions, raycaster: raycasterOptions, events, orthographic, lookAt, shadows, linear, legacy, flat, dpr, frameloop, performance, } = inputs;
748
- const state = this.get();
749
- const stateToUpdate = {};
750
- // setup renderer
751
- let gl = state.gl;
752
- if (!state.gl)
753
- stateToUpdate.gl = gl = makeDefaultRenderer(glOptions, canvasElement);
754
- // setup raycaster
755
- let raycaster = state.raycaster;
756
- if (!raycaster)
757
- stateToUpdate.raycaster = raycaster = new THREE.Raycaster();
758
- // set raycaster options
759
- const _c = raycasterOptions || {}, { params } = _c, options = __rest(_c, ["params"]);
760
- if (!is.equ(options, raycaster, shallowLoose))
761
- applyProps(raycaster, Object.assign({}, options));
762
- if (!is.equ(params, raycaster.params, shallowLoose)) {
763
- applyProps(raycaster, { params: Object.assign(Object.assign({}, raycaster.params), (params || {})) });
764
- }
765
- // create default camera
766
- if (!state.camera) {
767
- const isCamera = is.camera(cameraOptions);
768
- let camera = isCamera ? cameraOptions : makeDefaultCamera(orthographic || false, state.size);
769
- if (!isCamera) {
770
- if (cameraOptions)
771
- applyProps(camera, cameraOptions);
772
- // set position.z
773
- if (!(cameraOptions === null || cameraOptions === void 0 ? void 0 : cameraOptions.position))
774
- camera.position.z = 5;
775
- // always look at center or passed-in lookAt by default
776
- if (!(cameraOptions === null || cameraOptions === void 0 ? void 0 : cameraOptions.rotation)) {
777
- if (Array.isArray(lookAt))
778
- camera.lookAt(lookAt[0], lookAt[1], lookAt[2]);
779
- else if (lookAt instanceof THREE.Vector3)
780
- camera.lookAt(lookAt);
781
- else
782
- camera.lookAt(0, 0, 0);
783
- }
784
- // update projection matrix after applyprops
785
- (_a = camera.updateProjectionMatrix) === null || _a === void 0 ? void 0 : _a.call(camera);
786
- }
787
- if (!is.instance(camera))
788
- camera = prepare(camera, { store: this });
789
- stateToUpdate.camera = camera;
790
- }
791
- // Set up XR (one time only!)
792
- if (!state.xr) {
793
- // Handle frame behavior in WebXR
794
- const handleXRFrame = (timestamp, frame) => {
795
- const state = this.get();
796
- if (state.frameloop === 'never')
797
- return;
798
- advance(timestamp, true, this, frame);
799
- };
800
- // Toggle render switching on session
801
- const handleSessionChange = () => {
802
- const state = this.get();
803
- state.gl.xr.enabled = state.gl.xr.isPresenting;
804
- state.gl.xr.setAnimationLoop(state.gl.xr.isPresenting ? handleXRFrame : null);
805
- if (!state.gl.xr.isPresenting)
806
- invalidate(this);
807
- };
808
- // WebXR session manager
809
- const xr = {
810
- connect: () => {
811
- gl.xr.addEventListener('sessionstart', handleSessionChange);
812
- gl.xr.addEventListener('sessionend', handleSessionChange);
813
- },
814
- disconnect: () => {
815
- gl.xr.removeEventListener('sessionstart', handleSessionChange);
816
- gl.xr.removeEventListener('sessionend', handleSessionChange);
817
- },
818
- };
819
- // Subscribe to WebXR session events
820
- if (gl.xr)
821
- xr.connect();
822
- stateToUpdate.xr = xr;
823
- }
824
- // Set shadowmap
825
- if (gl.shadowMap) {
826
- const isBoolean = typeof shadows === 'boolean';
827
- if ((isBoolean && gl.shadowMap.enabled !== shadows) || !is.equ(shadows, gl.shadowMap, shallowLoose)) {
828
- const old = gl.shadowMap.enabled;
829
- gl.shadowMap.enabled = !!shadows;
830
- if (!isBoolean)
831
- Object.assign(gl.shadowMap, shadows);
832
- else
833
- gl.shadowMap.type = THREE.PCFSoftShadowMap;
834
- if (old !== gl.shadowMap.enabled)
835
- checkNeedsUpdate(gl.shadowMap);
836
- }
837
- }
838
- // Safely set color management if available.
839
- // Avoid accessing THREE.ColorManagement to play nice with older versions
840
- if (THREE.ColorManagement) {
841
- const ColorManagement = THREE.ColorManagement;
842
- if ('enabled' in ColorManagement)
843
- ColorManagement['enabled'] = (_b = !legacy) !== null && _b !== void 0 ? _b : false;
844
- else if ('legacyMode' in ColorManagement)
845
- ColorManagement['legacyMode'] = legacy !== null && legacy !== void 0 ? legacy : true;
846
- }
847
- const outputEncoding = linear ? THREE.LinearEncoding : THREE.sRGBEncoding;
848
- const toneMapping = flat ? THREE.NoToneMapping : THREE.ACESFilmicToneMapping;
849
- if (gl.outputEncoding !== outputEncoding)
850
- gl.outputEncoding = outputEncoding;
851
- if (gl.toneMapping !== toneMapping)
852
- gl.toneMapping = toneMapping;
853
- // Update color management state
854
- if (state.legacy !== legacy)
855
- stateToUpdate.legacy = legacy;
856
- if (state.linear !== linear)
857
- stateToUpdate.linear = linear;
858
- if (state.flat !== flat)
859
- stateToUpdate.flat = flat;
860
- // Set gl props
861
- gl.setClearAlpha(0);
862
- gl.setPixelRatio(makeDpr(state.viewport.dpr));
863
- gl.setSize(state.size.width, state.size.height);
864
- if (is.obj(glOptions) &&
865
- !(typeof glOptions === 'function') &&
866
- !is.renderer(glOptions) &&
867
- !is.equ(glOptions, gl, shallowLoose)) {
868
- applyProps(gl, glOptions);
869
- }
870
- // Store events internally
871
- if (events && !state.events.handlers)
872
- stateToUpdate.events = events(this);
873
- // Check performance
874
- if (performance && !is.equ(performance, state.performance, shallowLoose)) {
875
- stateToUpdate.performance = Object.assign(Object.assign({}, state.performance), performance);
876
- }
877
- this.set(stateToUpdate);
878
- // Check pixelratio
879
- if (dpr && state.viewport.dpr !== makeDpr(dpr))
880
- state.setDpr(dpr);
881
- // Check size, allow it to take on container bounds initially
882
- const size = computeInitialSize(canvasElement, sizeOptions);
883
- if (!is.equ(size, state.size, shallowLoose))
884
- state.setSize(size.width, size.height, size.top, size.left);
885
- // Check frameloop
886
- if (state.frameloop !== frameloop)
887
- state.setFrameloop(frameloop);
888
- if (!this.get('ready'))
889
- this.set({ ready: true });
890
- this.invalidate();
891
- }
892
- destroy(canvas) {
893
- this.set((state) => ({ internal: Object.assign(Object.assign({}, state.internal), { active: false }) }));
894
- setTimeout(() => {
895
- const { gl, xr, events } = this.get();
896
- if (gl) {
897
- if (events.disconnect) {
898
- events.disconnect();
899
- }
900
- gl.renderLists.dispose();
901
- gl.forceContextLoss();
902
- if (gl.xr && gl.xr.enabled) {
903
- gl.xr.setAnimationLoop(null);
904
- xr.disconnect();
905
- }
906
- dispose(this.get());
907
- rootStateMap.delete(canvas);
908
- }
909
- }, 500);
910
- }
911
- resize() {
912
- const state = this.get();
913
- let oldSize = state.size;
914
- let oldDpr = state.viewport.dpr;
915
- let oldCamera = state.camera;
916
- this.hold(combineLatest([this.select('camera'), this.select('size'), this.select('viewport'), this.select('gl')]), ([camera, size, viewport, gl]) => {
917
- // resize camera and renderer on changes to size and dpr
918
- if (size !== oldSize || viewport.dpr !== oldDpr) {
919
- oldSize = size;
920
- oldDpr = viewport.dpr;
921
- // update camera
922
- updateCamera(camera, size);
923
- gl.setPixelRatio(viewport.dpr);
924
- gl.setSize(size.width, size.height);
925
- }
926
- // update viewport when camera changes
927
- if (camera !== oldCamera) {
928
- updateCamera(camera, size);
929
- oldCamera = camera;
930
- this.set((state) => ({
931
- viewport: Object.assign(Object.assign({}, state.viewport), state.viewport.getCurrentViewport(camera)),
932
- }));
933
- }
934
- });
935
- }
936
- invalidate() {
937
- this.hold(this.select(), () => invalidate(this));
938
- }
939
- }
940
- NgtStore.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtStore, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
941
- NgtStore.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtStore });
942
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtStore, decorators: [{
943
- type: Injectable
944
- }] });
945
- function computeInitialSize(canvas, defaultSize) {
946
- if (defaultSize)
947
- return defaultSize;
948
- if (canvas instanceof HTMLCanvasElement && canvas.parentElement) {
949
- return canvas.parentElement.getBoundingClientRect();
950
- }
951
- return { width: 0, height: 0, top: 0, left: 0 };
952
- }
953
- // Disposes an object and all its properties
954
- function dispose(obj) {
955
- var _a;
956
- if (obj.dispose && !is.scene(obj))
957
- obj.dispose();
958
- for (const p in obj) {
959
- (_a = p.dispose) === null || _a === void 0 ? void 0 : _a.call(p);
960
- delete obj[p];
961
- }
962
- }
963
-
964
- const NGT_COMPOUND_PREFIXES = new InjectionToken('NgtCompoundPrefixes');
965
-
966
- const catalogue = {};
967
- function extend(objects) {
968
- Object.assign(catalogue, objects);
969
- }
970
- const NGT_CATALOGUE = new InjectionToken('THREE Constructors Catalogue', { factory: () => catalogue });
971
-
972
- class NgtCommonDirective {
973
- constructor() {
974
- this.vcr = inject(ViewContainerRef);
975
- this.template = inject(TemplateRef);
976
- this.injected = false;
977
- this.shouldCreateView = true;
978
- const commentNode = this.vcr.element.nativeElement;
979
- if (commentNode['__ngt_renderer_add_comment__']) {
980
- commentNode['__ngt_renderer_add_comment__']();
981
- delete commentNode['__ngt_renderer_add_comment__'];
982
- }
983
- }
984
- createView() {
985
- if (this.shouldCreateView) {
986
- if (this.view && !this.view.destroyed) {
987
- this.view.destroy();
988
- }
989
- this.view = this.vcr.createEmbeddedView(this.template);
990
- safeDetectChanges(this.view);
991
- }
992
- }
993
- }
994
- NgtCommonDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtCommonDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
995
- NgtCommonDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.6", type: NgtCommonDirective, ngImport: i0 });
996
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtCommonDirective, decorators: [{
997
- type: Directive
998
- }], ctorParameters: function () { return []; } });
999
-
1000
- class NgtArgs extends NgtCommonDirective {
1001
- constructor() {
1002
- super(...arguments);
1003
- this.injectedArgs = [];
1004
- }
1005
- set args(args) {
1006
- if (args == null || !Array.isArray(args) || (args.length === 1 && args[0] === null))
1007
- return;
1008
- this.injected = false;
1009
- this.injectedArgs = args;
1010
- this.createView();
1011
- }
1012
- get args() {
1013
- if (this.validate()) {
1014
- this.injected = true;
1015
- return this.injectedArgs;
1016
- }
1017
- return null;
1018
- }
1019
- validate() {
1020
- return !this.injected && !!this.injectedArgs.length;
1021
- }
1022
- }
1023
- NgtArgs.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtArgs, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1024
- NgtArgs.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.6", type: NgtArgs, isStandalone: true, selector: "[args]", inputs: { args: "args" }, usesInheritance: true, ngImport: i0 });
1025
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtArgs, decorators: [{
1026
- type: Directive,
1027
- args: [{ selector: '[args]', standalone: true }]
1028
- }], propDecorators: { args: [{
1029
- type: Input
1030
- }] } });
1031
-
1032
- class NgtParent extends NgtCommonDirective {
1033
- constructor() {
1034
- super(...arguments);
1035
- this.injectedParent = null;
1036
- }
1037
- set parent(parent) {
1038
- if (!parent)
1039
- return;
1040
- this.injected = false;
1041
- this.injectedParent = parent;
1042
- this.createView();
1043
- }
1044
- get parent() {
1045
- if (this.validate()) {
1046
- this.injected = true;
1047
- return this.injectedParent;
1048
- }
1049
- return null;
1050
- }
1051
- validate() {
1052
- return !this.injected && !!this.injectedParent;
1053
- }
1054
- }
1055
- NgtParent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtParent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1056
- NgtParent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.6", type: NgtParent, isStandalone: true, selector: "[parent]", inputs: { parent: "parent" }, usesInheritance: true, ngImport: i0 });
1057
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtParent, decorators: [{
1058
- type: Directive,
1059
- args: [{ selector: '[parent]', standalone: true }]
1060
- }], propDecorators: { parent: [{
1061
- type: Input
1062
- }] } });
1063
-
1064
- function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
1065
- const captureData = captures.get(obj);
1066
- if (captureData) {
1067
- captures.delete(obj);
1068
- // if this was the last captured object for this pointer
1069
- if (captures.size === 0) {
1070
- capturedMap.delete(pointerId);
1071
- captureData.target.releasePointerCapture(pointerId);
1072
- }
1073
- }
1074
- }
1075
- function removeInteractivity(store, object) {
1076
- const internal = store.get('internal');
1077
- // removes every trace of an object from data store
1078
- internal.interaction = internal.interaction.filter((o) => o !== object);
1079
- internal.initialHits = internal.initialHits.filter((o) => o !== object);
1080
- internal.hovered.forEach((value, key) => {
1081
- if (value.eventObject === object || value.object === object) {
1082
- // clear out intersects, they are outdated by now
1083
- internal.hovered.delete(key);
1084
- }
1085
- });
1086
- internal.capturedMap.forEach((captures, pointerId) => {
1087
- releaseInternalPointerCapture(internal.capturedMap, object, captures, pointerId);
1088
- });
1089
- if (store.get('previousStore')) {
1090
- removeInteractivity(store.get('previousStore'), object);
1091
- }
1092
- }
1093
- function createEvents(store) {
1094
- /** calculates delta **/
1095
- function calculateDistance(event) {
1096
- const internal = store.get('internal');
1097
- const dx = event.offsetX - internal.initialClick[0];
1098
- const dy = event.offsetY - internal.initialClick[1];
1099
- return Math.round(Math.sqrt(dx * dx + dy * dy));
1100
- }
1101
- /** returns true if an instance has a valid pointer-event registered, this excludes scroll, clicks etc... **/
1102
- function filterPointerEvents(objects) {
1103
- return objects.filter((obj) => ['move', 'over', 'enter', 'out', 'leave'].some((name) => {
1104
- var _a;
1105
- const eventName = `pointer${name}`;
1106
- return (_a = getLocalState(obj).handlers) === null || _a === void 0 ? void 0 : _a[eventName];
1107
- }));
1108
- }
1109
- function intersect(event, filter) {
1110
- var _a, _b, _c;
1111
- const state = store.get();
1112
- const duplicates = new Set();
1113
- const intersections = [];
1114
- // allow callers to eliminate event objects
1115
- const eventObjects = filter ? filter(state.internal.interaction) : state.internal.interaction;
1116
- // reset all raycaster cameras to undefined
1117
- for (let i = 0; i < eventObjects.length; i++) {
1118
- const instanceState = (_a = getLocalState(eventObjects[i]).store) === null || _a === void 0 ? void 0 : _a.get();
1119
- if (instanceState) {
1120
- instanceState.raycaster.camera = undefined;
1121
- }
1122
- }
1123
- if (!state.previousStore) {
1124
- // make sure root-level pointer and ray are setup
1125
- (_c = (_b = state.events).compute) === null || _c === void 0 ? void 0 : _c.call(_b, event, store);
1126
- }
1127
- function handleRaycast(obj) {
1128
- var _a, _b;
1129
- const objLocalState = getLocalState(obj);
1130
- const objStore = objLocalState.store;
1131
- const objState = objStore === null || objStore === void 0 ? void 0 : objStore.get();
1132
- // skip event handling when noEvents is set, or when raycaster camera is null
1133
- if (!objState || !objState.events.enabled || objState.raycaster.camera === null)
1134
- return [];
1135
- // when the camera is undefined, we have to call the events layers to update function
1136
- if (objState.raycaster.camera === undefined) {
1137
- (_b = (_a = objState.events).compute) === null || _b === void 0 ? void 0 : _b.call(_a, event, objStore, objState.previousStore);
1138
- // if the camera is still undefined, we have to skip this layer entirely
1139
- if (objState.raycaster.camera === undefined)
1140
- objState.raycaster.camera = null;
1141
- }
1142
- // intersect object by object
1143
- return objState.raycaster.camera ? objState.raycaster.intersectObject(obj, true) : [];
1144
- }
1145
- // collect events
1146
- let hits = eventObjects
1147
- // intersect objects
1148
- .flatMap(handleRaycast)
1149
- // sort by event priority
1150
- .sort((a, b) => {
1151
- const aState = getLocalState(a.object).store.get();
1152
- const bState = getLocalState(b.object).store.get();
1153
- if (!aState || !bState)
1154
- return a.distance - b.distance;
1155
- return bState.events.priority - aState.events.priority || a.distance - b.distance;
1156
- })
1157
- // filter out duplicates
1158
- .filter((item) => {
1159
- const id = makeId(item);
1160
- if (duplicates.has(id))
1161
- return false;
1162
- duplicates.add(id);
1163
- return true;
1164
- });
1165
- // allow custom userland intersect sort order, this likely only makes sense on the root
1166
- if (state.events.filter)
1167
- hits = state.events.filter(hits, store);
1168
- // bubble up the events, find the event source
1169
- for (const hit of hits) {
1170
- let eventObject = hit.object;
1171
- // bubble event up
1172
- while (eventObject) {
1173
- if (getLocalState(eventObject).eventCount) {
1174
- intersections.push(Object.assign(Object.assign({}, hit), { eventObject }));
1175
- }
1176
- eventObject = eventObject.parent;
1177
- }
1178
- }
1179
- // if the interaction is captured, make all capturing targets part of the intersects
1180
- if ('pointerId' in event && state.internal.capturedMap.has(event.pointerId)) {
1181
- for (const capturedData of state.internal.capturedMap.get(event.pointerId).values()) {
1182
- if (!duplicates.has(makeId(capturedData.intersection))) {
1183
- intersections.push(capturedData.intersection);
1184
- }
1185
- }
1186
- }
1187
- return intersections;
1188
- }
1189
- /** handle intersections by forwarding them to handlers */
1190
- function handleIntersects(intersections, event, delta, callback) {
1191
- var _a;
1192
- const rootState = store.get();
1193
- // if anything has been found, forward it to the event listeners
1194
- if (intersections.length) {
1195
- const localState = { stopped: false };
1196
- for (const hit of intersections) {
1197
- const state = ((_a = getLocalState(hit.object).store) === null || _a === void 0 ? void 0 : _a.get()) || rootState;
1198
- const { raycaster, pointer, camera, internal } = state;
1199
- const unprojectedPoint = new THREE.Vector3(pointer.x, pointer.y, 0).unproject(camera);
1200
- const hasPointerCapture = (id) => { var _a, _b; return (_b = (_a = internal.capturedMap.get(id)) === null || _a === void 0 ? void 0 : _a.has(hit.eventObject)) !== null && _b !== void 0 ? _b : false; };
1201
- const setPointerCapture = (id) => {
1202
- const captureData = { intersection: hit, target: event.target };
1203
- if (internal.capturedMap.has(id)) {
1204
- // if the pointerId was previously captured, we add the hit to the event capturedMap
1205
- internal.capturedMap.get(id).set(hit.eventObject, captureData);
1206
- }
1207
- else {
1208
- // if the pointerId was not previously captured, we create a Map containing the hitObject, and the hit. hitObject is used for faster access
1209
- internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
1210
- }
1211
- // call the original event now
1212
- event.target.setPointerCapture(id);
1213
- };
1214
- const releasePointerCapture = (id) => {
1215
- const captures = internal.capturedMap.get(id);
1216
- if (captures) {
1217
- releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
1218
- }
1219
- };
1220
- // add native event props
1221
- const extractEventProps = {};
1222
- // This iterates over the event's properties including the inherited ones. Native PointerEvents have most of their props as getters which are inherited, but polyfilled PointerEvents have them all as their own properties (i.e. not inherited). We can't use Object.keys() or Object.entries() as they only return "own" properties; nor Object.getPrototypeOf(event) as that *doesn't* return "own" properties, only inherited ones.
1223
- for (const prop in event) {
1224
- const property = event[prop];
1225
- // only copy over atomics, leave functions alone as these should be called as event.nativeEvent.fn()
1226
- if (typeof property !== 'function') {
1227
- extractEventProps[prop] = property;
1228
- }
1229
- }
1230
- const raycastEvent = Object.assign(Object.assign(Object.assign({}, hit), extractEventProps), { pointer,
1231
- intersections, stopped: localState.stopped, delta,
1232
- unprojectedPoint, ray: raycaster.ray, camera: camera,
1233
- // Hijack stopPropagation, which just sets a flag
1234
- stopPropagation() {
1235
- // https://github.com/pmndrs/react-three-fiber/issues/596
1236
- // Events are not allowed to stop propagation if the pointer has been captured
1237
- const capturesForPointer = 'pointerId' in event && internal.capturedMap.get(event.pointerId);
1238
- // We only authorize stopPropagation...
1239
- if (
1240
- // ...if this pointer hasn't been captured
1241
- !capturesForPointer ||
1242
- // ... or if the hit object is capturing the pointer
1243
- capturesForPointer.has(hit.eventObject)) {
1244
- raycastEvent.stopped = localState.stopped = true;
1245
- // Propagation is stopped, remove all other hover records
1246
- // An event handler is only allowed to flush other handlers if it is hovered itself
1247
- if (internal.hovered.size &&
1248
- Array.from(internal.hovered.values()).find((i) => i.eventObject === hit.eventObject)) {
1249
- // Objects cannot flush out higher up objects that have already caught the event
1250
- const higher = intersections.slice(0, intersections.indexOf(hit));
1251
- cancelPointer([...higher, hit]);
1252
- }
1253
- }
1254
- },
1255
- // there should be a distinction between target and currentTarget
1256
- target: { hasPointerCapture, setPointerCapture, releasePointerCapture }, currentTarget: { hasPointerCapture, setPointerCapture, releasePointerCapture }, nativeEvent: event });
1257
- // call subscribers
1258
- callback(raycastEvent);
1259
- // event bubbling may be interupted by stopPropagation
1260
- if (localState.stopped === true)
1261
- break;
1262
- }
1263
- }
1264
- return intersections;
1265
- }
1266
- function cancelPointer(intersections) {
1267
- var _a, _b;
1268
- const { internal } = store.get();
1269
- for (const hoveredObj of internal.hovered.values()) {
1270
- // When no objects were hit or the hovered object wasn't found underneath the cursor
1271
- // we call onPointerOut and delete the object from the hovered-elements map
1272
- if (!intersections.length ||
1273
- !intersections.find((hit) => hit.object === hoveredObj.object &&
1274
- hit.index === hoveredObj.index &&
1275
- hit.instanceId === hoveredObj.instanceId)) {
1276
- const eventObject = hoveredObj.eventObject;
1277
- const instance = getLocalState(eventObject);
1278
- const handlers = instance === null || instance === void 0 ? void 0 : instance.handlers;
1279
- internal.hovered.delete(makeId(hoveredObj));
1280
- if (instance === null || instance === void 0 ? void 0 : instance.eventCount) {
1281
- // Clear out intersects, they are outdated by now
1282
- const data = Object.assign(Object.assign({}, hoveredObj), { intersections });
1283
- (_a = handlers === null || handlers === void 0 ? void 0 : handlers.pointerout) === null || _a === void 0 ? void 0 : _a.call(handlers, data);
1284
- (_b = handlers === null || handlers === void 0 ? void 0 : handlers.pointerleave) === null || _b === void 0 ? void 0 : _b.call(handlers, data);
1285
- }
1286
- }
1287
- }
1288
- }
1289
- function pointerMissed(event, objects) {
1290
- var _a, _b;
1291
- for (let i = 0; i < objects.length; i++) {
1292
- const instance = getLocalState(objects[i]);
1293
- (_b = instance === null || instance === void 0 ? void 0 : (_a = instance.handlers).pointermissed) === null || _b === void 0 ? void 0 : _b.call(_a, event);
1294
- }
1295
- }
1296
- function handlePointer(name) {
1297
- // Deal with cancelation
1298
- switch (name) {
1299
- case 'pointerleave':
1300
- case 'pointercancel':
1301
- return () => cancelPointer([]);
1302
- case 'lostpointercapture':
1303
- return (event) => {
1304
- const { internal } = store.get();
1305
- if ('pointerId' in event && internal.capturedMap.has(event.pointerId)) {
1306
- // If the object event interface had onLostPointerCapture, we'd call it here on every
1307
- // object that's getting removed.
1308
- internal.capturedMap.delete(event.pointerId);
1309
- cancelPointer([]);
1310
- }
1311
- };
1312
- }
1313
- // Any other pointer goes here ...
1314
- return function handleEvent(event) {
1315
- const { onPointerMissed, internal } = store.get();
1316
- // prepareRay(event)
1317
- internal.lastEvent = event;
1318
- // Get fresh intersects
1319
- const isPointerMove = name === 'pointermove';
1320
- const isClickEvent = name === 'click' || name === 'contextmenu' || name === 'dblclick';
1321
- const filter = isPointerMove ? filterPointerEvents : undefined;
1322
- // const hits = patchIntersects(intersect(filter), event)
1323
- const hits = intersect(event, filter);
1324
- const delta = isClickEvent ? calculateDistance(event) : 0;
1325
- // Save initial coordinates on pointer-down
1326
- if (name === 'pointerdown') {
1327
- internal.initialClick = [event.offsetX, event.offsetY];
1328
- internal.initialHits = hits.map((hit) => hit.eventObject);
1329
- }
1330
- // If a click yields no results, pass it back to the user as a miss
1331
- // Missed events have to come first in order to establish user-land side-effect clean up
1332
- if (isClickEvent && !hits.length) {
1333
- if (delta <= 2) {
1334
- pointerMissed(event, internal.interaction);
1335
- if (onPointerMissed)
1336
- onPointerMissed(event);
1337
- }
1338
- }
1339
- // Take care of unhover
1340
- if (isPointerMove)
1341
- cancelPointer(hits);
1342
- function onIntersect(data) {
1343
- var _a, _b, _c;
1344
- const eventObject = data.eventObject;
1345
- const instance = getLocalState(eventObject);
1346
- const handlers = instance === null || instance === void 0 ? void 0 : instance.handlers;
1347
- // Check presence of handlers
1348
- if (!(instance === null || instance === void 0 ? void 0 : instance.eventCount))
1349
- return;
1350
- if (isPointerMove) {
1351
- // Move event ...
1352
- if ((handlers === null || handlers === void 0 ? void 0 : handlers.pointerover) ||
1353
- (handlers === null || handlers === void 0 ? void 0 : handlers.pointerenter) ||
1354
- (handlers === null || handlers === void 0 ? void 0 : handlers.pointerout) ||
1355
- (handlers === null || handlers === void 0 ? void 0 : handlers.pointerleave)) {
1356
- // When enter or out is present take care of hover-state
1357
- const id = makeId(data);
1358
- const hoveredItem = internal.hovered.get(id);
1359
- if (!hoveredItem) {
1360
- // If the object wasn't previously hovered, book it and call its handler
1361
- internal.hovered.set(id, data);
1362
- (_a = handlers.pointerover) === null || _a === void 0 ? void 0 : _a.call(handlers, data);
1363
- (_b = handlers.pointerenter) === null || _b === void 0 ? void 0 : _b.call(handlers, data);
1364
- }
1365
- else if (hoveredItem.stopped) {
1366
- // If the object was previously hovered and stopped, we shouldn't allow other items to proceed
1367
- data.stopPropagation();
1368
- }
1369
- }
1370
- // Call mouse move
1371
- (_c = handlers === null || handlers === void 0 ? void 0 : handlers.pointermove) === null || _c === void 0 ? void 0 : _c.call(handlers, data);
1372
- }
1373
- else {
1374
- // All other events ...
1375
- const handler = handlers === null || handlers === void 0 ? void 0 : handlers[name];
1376
- if (handler) {
1377
- // Forward all events back to their respective handlers with the exception of click events,
1378
- // which must use the initial target
1379
- if (!isClickEvent || internal.initialHits.includes(eventObject)) {
1380
- // Missed events have to come first
1381
- pointerMissed(event, internal.interaction.filter((object) => !internal.initialHits.includes(object)));
1382
- // Now call the handler
1383
- handler(data);
1384
- }
1385
- }
1386
- else {
1387
- // Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit
1388
- if (isClickEvent && internal.initialHits.includes(eventObject)) {
1389
- pointerMissed(event, internal.interaction.filter((object) => !internal.initialHits.includes(object)));
1390
- }
1391
- }
1392
- }
1393
- }
1394
- handleIntersects(hits, event, delta, onIntersect);
1395
- };
1396
- }
1397
- return { handlePointer };
1398
- }
1399
-
1400
- function attach(object, value, paths = []) {
1401
- const [base, ...remaining] = paths;
1402
- if (!base)
1403
- return;
1404
- if (remaining.length === 0) {
1405
- applyProps(object, { [base]: value });
1406
- }
1407
- else {
1408
- assignEmpty(object, base);
1409
- attach(object[base], value, remaining);
1410
- }
1411
- }
1412
- function detach(parent, child, attachProp) {
1413
- const childLocalState = getLocalState(child);
1414
- if (Array.isArray(attachProp)) {
1415
- attach(parent, childLocalState.previousAttach, attachProp);
1416
- }
1417
- else {
1418
- childLocalState.previousAttach();
1419
- }
1420
- }
1421
- function assignEmpty(obj, base) {
1422
- if ((!Object.hasOwn(obj, base) && Reflect && !!Reflect.has && !Reflect.has(obj, base)) || obj[base] === undefined) {
1423
- obj[base] = {};
1424
- }
1425
- }
1426
- function createAttachFunction(cb) {
1427
- return (parent, child, store) => cb({ parent, child, store });
1428
- }
1429
-
1430
- const SPECIAL_DOM_TAG = {
1431
- NGT_PORTAL: 'ngt-portal',
1432
- NGT_PRIMITIVE: 'ngt-primitive',
1433
- NGT_VALUE: 'ngt-value',
1434
- };
1435
- const SPECIAL_PROPERTIES = {
1436
- COMPOUND: 'ngtCompound',
1437
- RENDER_PRIORITY: 'priority',
1438
- ATTACH: 'attach',
1439
- VALUE: 'rawValue',
1440
- REF: 'ref',
1441
- };
1442
- const SPECIAL_EVENTS = {
1443
- BEFORE_RENDER: 'beforeRender',
1444
- AFTER_UPDATE: 'afterUpdate',
1445
- AFTER_ATTACH: 'afterAttach',
1446
- };
1447
- function attachThreeChild(parent, child) {
1448
- const pLS = getLocalState(parent);
1449
- const cLS = getLocalState(child);
1450
- if (!pLS || !cLS) {
1451
- throw new Error(`[NGT] THREE instances need to be prepared with local state.`);
1452
- }
1453
- // whether the child is added to the parent with parent.add()
1454
- let added = false;
1455
- // assign store on child if not already exist
1456
- // or child store is the parent of parent store
1457
- if (!cLS.store || cLS.store === pLS.store.get('previousStore')) {
1458
- cLS.store = pLS.store;
1459
- }
1460
- if (cLS.attach) {
1461
- const attachProp = cLS.attach;
1462
- if (typeof attachProp === 'function') {
1463
- const attachCleanUp = attachProp(parent, child, cLS.store);
1464
- if (attachCleanUp)
1465
- cLS.previousAttach = attachCleanUp;
1466
- }
1467
- else {
1468
- // we skip attach none if set explicitly
1469
- if (attachProp[0] === 'none') {
1470
- invalidateInstance(child);
1471
- return;
1472
- }
1473
- // handle material array
1474
- if (attachProp[0] === 'material' &&
1475
- attachProp[1] &&
1476
- typeof Number(attachProp[1]) === 'number' &&
1477
- is.material(child) &&
1478
- !Array.isArray(parent['material'])) {
1479
- parent['material'] = [];
1480
- }
1481
- // attach
1482
- if (cLS.isRaw) {
1483
- cLS.parent = parent;
1484
- // at this point we don't have rawValue yet, so we bail and wait until the Renderer recalls attach
1485
- if (child.__ngt_renderer__[11 /* NgtRendererClassId.rawValue */] === undefined)
1486
- return;
1487
- attach(parent, child.__ngt_renderer__[11 /* NgtRendererClassId.rawValue */], attachProp);
1488
- }
1489
- else {
1490
- attach(parent, child, attachProp);
1491
- }
1492
- // save value
1493
- cLS.previousAttach = attachProp.reduce((value, property) => value[property], parent);
1494
- }
1495
- }
1496
- else if (is.object3D(parent) && is.object3D(child)) {
1497
- parent.add(child);
1498
- added = true;
1499
- }
1500
- pLS.add(child, added ? 'objects' : 'nonObjects');
1501
- cLS.parent = parent;
1502
- if (cLS.afterAttach)
1503
- cLS.afterAttach.emit({ parent, node: child });
1504
- invalidateInstance(child);
1505
- invalidateInstance(parent);
1506
- }
1507
- function removeThreeChild(parent, child, dispose) {
1508
- var _a;
1509
- const pLS = getLocalState(parent);
1510
- const cLS = getLocalState(child);
1511
- // clear parent ref
1512
- cLS.parent = null;
1513
- // remove child from parent
1514
- if (pLS.objects)
1515
- pLS.remove(child, 'objects');
1516
- if (pLS.nonObjects)
1517
- pLS.remove(child, 'nonObjects');
1518
- if (cLS.attach) {
1519
- detach(parent, child, cLS.attach);
1520
- }
1521
- else if (is.object3D(parent) && is.object3D(child)) {
1522
- parent.remove(child);
1523
- removeInteractivity(cLS.store || pLS.store, child);
1524
- }
1525
- const isPrimitive = cLS.primitive;
1526
- if (!isPrimitive) {
1527
- removeThreeRecursive(((_a = cLS.objects) === null || _a === void 0 ? void 0 : _a.value) || [], child, !!dispose);
1528
- removeThreeRecursive(child.childre, child, !!dispose);
1529
- }
1530
- // dispose
1531
- if (!isPrimitive && child['dispose'] && !is.scene(child)) {
1532
- queueMicrotask(() => child['dispose']());
1533
- }
1534
- invalidateInstance(parent);
1535
- }
1536
- function removeThreeRecursive(array, parent, dispose) {
1537
- if (array)
1538
- [...array].forEach((child) => removeThreeChild(parent, child, dispose));
1539
- }
1540
- function processThreeEvent(instance, priority, eventName, callback, cdr, targetCdr) {
1541
- const lS = getLocalState(instance);
1542
- if (eventName === SPECIAL_EVENTS.BEFORE_RENDER) {
1543
- return lS.store
1544
- .get('internal')
1545
- .subscribe((state) => callback({ state, object: instance }), priority || lS.priority || 0);
1546
- }
1547
- if (eventName === SPECIAL_EVENTS.AFTER_UPDATE || eventName === SPECIAL_EVENTS.AFTER_ATTACH) {
1548
- let emitter = lS[eventName];
1549
- if (!emitter)
1550
- emitter = lS[eventName] = new EventEmitter();
1551
- const sub = emitter.subscribe(callback);
1552
- return sub.unsubscribe.bind(sub);
1553
- }
1554
- if (!lS.handlers)
1555
- lS.handlers = {};
1556
- // try to get the previous handler. compound might have one, the THREE object might also have one with the same name
1557
- const previousHandler = lS.handlers[eventName];
1558
- // readjust the callback
1559
- const updatedCallback = (event) => {
1560
- if (previousHandler)
1561
- previousHandler(event);
1562
- callback(event);
1563
- };
1564
- Object.assign(lS.handlers, { [eventName]: eventToHandler(updatedCallback, cdr, targetCdr) });
1565
- // increment the count everytime
1566
- lS.eventCount += 1;
1567
- // but only add the instance (target) to the interaction array (so that it is handled by the EventManager with Raycast)
1568
- // the first time eventCount is incremented
1569
- if (lS.eventCount === 1 && instance['raycast'])
1570
- lS.store.get('addInteraction')(instance);
1571
- // clean up the event listener by removing the target from the interaction array
1572
- return () => {
1573
- const localState = getLocalState(instance);
1574
- if (localState && localState.eventCount)
1575
- localState.store.get('removeInteraction')(instance['uuid']);
1576
- };
1577
- }
1578
- function eventToHandler(callback, cdr, targetCdr) {
1579
- return (event) => {
1580
- callback(event);
1581
- safeDetectChanges(targetCdr);
1582
- safeDetectChanges(cdr);
1583
- };
1584
- }
1585
- function kebabToPascal(str) {
1586
- // split the string at each hyphen
1587
- const parts = str.split('-');
1588
- // map over the parts, capitalizing the first letter of each part
1589
- const pascalParts = parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1));
1590
- // join the parts together to create the final PascalCase string
1591
- return pascalParts.join('');
1592
- }
1593
-
1594
- class NgtRendererStore {
1595
- constructor(root) {
1596
- this.root = root;
1597
- this.comments = [];
1598
- }
1599
- createNode(type, node) {
1600
- const state = [
1601
- type,
1602
- null,
1603
- null,
1604
- [],
1605
- false,
1606
- undefined,
1607
- undefined,
1608
- undefined,
1609
- undefined,
1610
- undefined,
1611
- undefined,
1612
- undefined,
1613
- undefined,
1614
- undefined,
1615
- undefined,
1616
- ];
1617
- const rendererNode = Object.assign(node, { __ngt_renderer__: state });
1618
- // assign ownerDocument to node so we can use HostListener in Component
1619
- if (!rendererNode['ownerDocument'])
1620
- rendererNode['ownerDocument'] = this.root.document;
1621
- // assign injectorFactory on non-three type since
1622
- // rendererNode is an instance of DOM Node
1623
- if (state[0 /* NgtRendererClassId.type */] !== 'three') {
1624
- state[14 /* NgtRendererClassId.injectorFactory */] = () => getDebugNode(rendererNode).injector;
1625
- }
1626
- if (state[0 /* NgtRendererClassId.type */] === 'comment') {
1627
- // we attach an arrow function to the Comment node
1628
- // In our directives, we can call this function to then start tracking the RendererNode
1629
- // this is done to limit the amount of Nodes we need to process for getCreationState
1630
- rendererNode['__ngt_renderer_add_comment__'] = (node) => {
1631
- if (node && node.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'portal') {
1632
- this.portals.push(node);
1633
- }
1634
- else {
1635
- this.comments.push(rendererNode);
1636
- }
1637
- };
1638
- return rendererNode;
1639
- }
1640
- if (state[0 /* NgtRendererClassId.type */] === 'compound') {
1641
- state[8 /* NgtRendererClassId.queueOps */] = new Set();
1642
- state[9 /* NgtRendererClassId.attributes */] = {};
1643
- state[10 /* NgtRendererClassId.properties */] = {};
1644
- return rendererNode;
1645
- }
1646
- return rendererNode;
1647
- }
1648
- setParent(node, parent) {
1649
- if (!node.__ngt_renderer__[1 /* NgtRendererClassId.parent */]) {
1650
- node.__ngt_renderer__[1 /* NgtRendererClassId.parent */] = parent;
1651
- }
1652
- }
1653
- addChild(node, child) {
1654
- if (!node.__ngt_renderer__[3 /* NgtRendererClassId.children */].includes(child)) {
1655
- node.__ngt_renderer__[3 /* NgtRendererClassId.children */].push(child);
1656
- }
1657
- }
1658
- removeChild(node, child) {
1659
- const index = node.__ngt_renderer__[3 /* NgtRendererClassId.children */].findIndex((c) => child === c);
1660
- if (index >= 0) {
1661
- node.__ngt_renderer__[3 /* NgtRendererClassId.children */].splice(index, 1);
1662
- }
1663
- }
1664
- setCompound(compound, instance) {
1665
- const rS = compound.__ngt_renderer__;
1666
- rS[7 /* NgtRendererClassId.compounded */] = instance;
1667
- const attributes = Object.keys(rS[9 /* NgtRendererClassId.attributes */]);
1668
- const properties = Object.keys(rS[10 /* NgtRendererClassId.properties */]);
1669
- for (const key of attributes) {
1670
- this.applyAttribute(instance, key, rS[9 /* NgtRendererClassId.attributes */][key]);
1671
- }
1672
- for (const key of properties) {
1673
- this.applyProperty(instance, key, rS[10 /* NgtRendererClassId.properties */][key]);
1674
- }
1675
- this.executeOperation(compound);
1676
- }
1677
- queueOperation(node, op) {
1678
- node.__ngt_renderer__[8 /* NgtRendererClassId.queueOps */].add(op);
1679
- }
1680
- executeOperation(node, type = 'op') {
1681
- var _a;
1682
- const rS = node.__ngt_renderer__;
1683
- if ((_a = rS[8 /* NgtRendererClassId.queueOps */]) === null || _a === void 0 ? void 0 : _a.size) {
1684
- rS[8 /* NgtRendererClassId.queueOps */].forEach((op) => {
1685
- if (op[0 /* NgtQueueOpClassId.type */] === type) {
1686
- op[1 /* NgtQueueOpClassId.op */]();
1687
- rS[8 /* NgtRendererClassId.queueOps */].delete(op);
1688
- }
1689
- });
1690
- }
1691
- }
1692
- processPortalContainer(portal) {
1693
- const injectorFactory = portal.__ngt_renderer__[14 /* NgtRendererClassId.injectorFactory */];
1694
- const injector = injectorFactory === null || injectorFactory === void 0 ? void 0 : injectorFactory();
1695
- if (!injector)
1696
- return;
1697
- const portalStore = injector.get(NgtStore, null);
1698
- if (!portalStore)
1699
- return;
1700
- const portalContainer = portalStore.get('scene');
1701
- if (!portalContainer)
1702
- return;
1703
- portal.__ngt_renderer__[13 /* NgtRendererClassId.portalContainer */] = this.createNode('three', portalContainer);
1704
- }
1705
- applyAttribute(node, name, value) {
1706
- const rS = node.__ngt_renderer__;
1707
- if (rS[4 /* NgtRendererClassId.destroyed */])
1708
- return;
1709
- if (name === SPECIAL_PROPERTIES.RENDER_PRIORITY) {
1710
- // priority needs to be set as an attribute string so that they can be set as early as possible
1711
- // we convert that string to a number. if it's invalid, 0
1712
- let priority = Number(value);
1713
- if (isNaN(priority)) {
1714
- priority = 0;
1715
- console.warn(`[NGT] "priority" is an invalid number, default to 0`);
1716
- }
1717
- getLocalState(node).priority = priority;
1718
- }
1719
- if (name === SPECIAL_PROPERTIES.COMPOUND) {
1720
- // we set the compound property on instance node now so we know that this instance is being compounded
1721
- rS[5 /* NgtRendererClassId.compound */] = [value === '' || value === 'first', {}];
1722
- return;
1723
- }
1724
- if (name === SPECIAL_PROPERTIES.ATTACH) {
1725
- // handle attach as tring
1726
- const paths = value.split('.');
1727
- if (paths.length)
1728
- getLocalState(node).attach = paths;
1729
- return;
1730
- }
1731
- if (name === SPECIAL_PROPERTIES.VALUE) {
1732
- // coercion
1733
- let maybeCoerced = value;
1734
- if (maybeCoerced === '' || maybeCoerced === 'true' || maybeCoerced === 'false') {
1735
- maybeCoerced = maybeCoerced === 'true' || maybeCoerced === '';
1736
- }
1737
- else if (!isNaN(Number(maybeCoerced))) {
1738
- maybeCoerced = Number(maybeCoerced);
1739
- }
1740
- rS[11 /* NgtRendererClassId.rawValue */] = maybeCoerced;
1741
- return;
1742
- }
1743
- applyProps(node, { [name]: value });
1744
- }
1745
- applyProperty(node, name, value) {
1746
- const rS = node.__ngt_renderer__;
1747
- if (rS[4 /* NgtRendererClassId.destroyed */])
1748
- return;
1749
- // [ref]
1750
- if (name === SPECIAL_PROPERTIES.REF && is.ref(value)) {
1751
- rS[12 /* NgtRendererClassId.ref */] = value;
1752
- value.nativeElement = node;
1753
- return;
1754
- }
1755
- const parent = getLocalState(node).parent || rS[1 /* NgtRendererClassId.parent */];
1756
- // [rawValue]
1757
- if (getLocalState(node).isRaw && name === SPECIAL_PROPERTIES.VALUE) {
1758
- rS[11 /* NgtRendererClassId.rawValue */] = value;
1759
- if (parent)
1760
- attachThreeChild(parent, node);
1761
- return;
1762
- }
1763
- // [attach]
1764
- if (name === SPECIAL_PROPERTIES.ATTACH) {
1765
- getLocalState(node).attach = Array.isArray(value) ? value.map((v) => v.toString()) : value;
1766
- if (parent)
1767
- attachThreeChild(parent, node);
1768
- return;
1769
- }
1770
- const compound = rS[5 /* NgtRendererClassId.compound */];
1771
- if ((compound === null || compound === void 0 ? void 0 : compound[1 /* NgtCompoundClassId.props */]) &&
1772
- name in compound[1 /* NgtCompoundClassId.props */] &&
1773
- !compound[0 /* NgtCompoundClassId.applyFirst */]) {
1774
- value = compound[1 /* NgtCompoundClassId.props */][name];
1775
- }
1776
- applyProps(node, { [name]: value });
1777
- }
1778
- isCompound(name) {
1779
- return this.root.compoundPrefixes.some((prefix) => name.startsWith(prefix));
1780
- }
1781
- isDOM(node) {
1782
- const rS = node['__ngt_renderer__'];
1783
- return (!rS ||
1784
- (rS[0 /* NgtRendererClassId.type */] !== 'compound' &&
1785
- (node instanceof Element || node instanceof Document || node instanceof Window)));
1786
- }
1787
- get rootScene() {
1788
- return this.root.store.get('scene');
1789
- }
1790
- get rootCdr() {
1791
- return this.root.cdr;
1792
- }
1793
- get portals() {
1794
- return this.root.portals;
1795
- }
1796
- getClosestParentWithInstance(node) {
1797
- let parent = node.__ngt_renderer__[1 /* NgtRendererClassId.parent */];
1798
- while (parent && parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] !== 'three') {
1799
- parent = parent.__ngt_renderer__[13 /* NgtRendererClassId.portalContainer */]
1800
- ? parent.__ngt_renderer__[13 /* NgtRendererClassId.portalContainer */]
1801
- : parent.__ngt_renderer__[1 /* NgtRendererClassId.parent */];
1802
- }
1803
- return parent;
1804
- }
1805
- getClosestParentWithCompound(node) {
1806
- if (node.__ngt_renderer__[6 /* NgtRendererClassId.compoundParent */]) {
1807
- return node.__ngt_renderer__[6 /* NgtRendererClassId.compoundParent */];
1808
- }
1809
- let parent = node.__ngt_renderer__[1 /* NgtRendererClassId.parent */];
1810
- if (parent &&
1811
- parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'compound' &&
1812
- !parent.__ngt_renderer__[7 /* NgtRendererClassId.compounded */]) {
1813
- return parent;
1814
- }
1815
- while (parent &&
1816
- (parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three' ||
1817
- !parent.__ngt_renderer__[6 /* NgtRendererClassId.compoundParent */] ||
1818
- parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] !== 'compound')) {
1819
- parent = parent.__ngt_renderer__[1 /* NgtRendererClassId.parent */];
1820
- }
1821
- if (!parent)
1822
- return;
1823
- if (parent.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three' &&
1824
- parent.__ngt_renderer__[6 /* NgtRendererClassId.compoundParent */]) {
1825
- return parent.__ngt_renderer__[6 /* NgtRendererClassId.compoundParent */];
1826
- }
1827
- if (!parent.__ngt_renderer__[7 /* NgtRendererClassId.compounded */]) {
1828
- return parent;
1829
- }
1830
- return null;
1831
- }
1832
- getCreationState() {
1833
- var _a, _b;
1834
- const injectedArgs = ((_a = this.firstNonInjectedDirective(NgtArgs)) === null || _a === void 0 ? void 0 : _a.args) || [];
1835
- const injectedParent = ((_b = this.firstNonInjectedDirective(NgtParent)) === null || _b === void 0 ? void 0 : _b.parent) || null;
1836
- const store = this.tryGetPortalStore();
1837
- return { injectedArgs, injectedParent, store };
1838
- }
1839
- destroy(node, parent) {
1840
- const rS = node.__ngt_renderer__;
1841
- if (rS[4 /* NgtRendererClassId.destroyed */])
1842
- return;
1843
- if (rS[0 /* NgtRendererClassId.type */] === 'three') {
1844
- rS[5 /* NgtRendererClassId.compound */] = undefined;
1845
- rS[6 /* NgtRendererClassId.compoundParent */] = undefined;
1846
- const localState = getLocalState(node);
1847
- if (localState.objects) {
1848
- localState.objects.value.forEach((obj) => this.destroy(obj, parent));
1849
- localState.objects.complete();
1850
- }
1851
- if (localState.nonObjects) {
1852
- localState.nonObjects.value.forEach((obj) => this.destroy(obj, parent));
1853
- localState.nonObjects.complete();
1854
- }
1855
- if (localState.afterUpdate)
1856
- localState.afterUpdate.complete();
1857
- if (localState.afterAttach)
1858
- localState.afterAttach.complete();
1859
- delete localState['objects'];
1860
- delete localState['nonObjects'];
1861
- delete localState['add'];
1862
- delete localState['remove'];
1863
- delete localState['afterUpdate'];
1864
- delete localState['afterAttach'];
1865
- delete localState['store'];
1866
- delete localState['handlers'];
1867
- if (!localState.primitive) {
1868
- delete node['__ngt__'];
1869
- }
1870
- }
1871
- if (rS[0 /* NgtRendererClassId.type */] === 'comment') {
1872
- rS[14 /* NgtRendererClassId.injectorFactory */] = null;
1873
- delete node['__ngt_renderer_add_comment__'];
1874
- const index = this.comments.findIndex((comment) => comment === node);
1875
- if (index > -1) {
1876
- this.comments.splice(index, 1);
1877
- }
1878
- }
1879
- if (rS[0 /* NgtRendererClassId.type */] === 'portal') {
1880
- rS[14 /* NgtRendererClassId.injectorFactory */] = null;
1881
- const index = this.portals.findIndex((portal) => portal === node);
1882
- if (index > -1) {
1883
- this.portals.splice(index, 1);
1884
- }
1885
- }
1886
- if (rS[0 /* NgtRendererClassId.type */] === 'compound') {
1887
- rS[7 /* NgtRendererClassId.compounded */] = undefined;
1888
- rS[9 /* NgtRendererClassId.attributes */] = null;
1889
- rS[10 /* NgtRendererClassId.properties */] = null;
1890
- this.executeOperation(node, 'cleanUp');
1891
- rS[8 /* NgtRendererClassId.queueOps */].clear();
1892
- rS[8 /* NgtRendererClassId.queueOps */] = null;
1893
- }
1894
- if (rS[12 /* NgtRendererClassId.ref */]) {
1895
- // nullify ref
1896
- rS[12 /* NgtRendererClassId.ref */].nativeElement = null;
1897
- rS[12 /* NgtRendererClassId.ref */] = undefined;
1898
- }
1899
- // nullify parent
1900
- rS[1 /* NgtRendererClassId.parent */] = null;
1901
- for (const renderChild of rS[3 /* NgtRendererClassId.children */] || []) {
1902
- if (renderChild.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'three' && parent) {
1903
- removeThreeChild(parent, renderChild, true);
1904
- }
1905
- this.destroy(renderChild, parent);
1906
- }
1907
- rS[3 /* NgtRendererClassId.children */] = [];
1908
- rS[4 /* NgtRendererClassId.destroyed */] = true;
1909
- if (parent) {
1910
- this.removeChild(parent, node);
1911
- }
1912
- }
1913
- firstNonInjectedDirective(dir) {
1914
- let directive;
1915
- let i = this.comments.length - 1;
1916
- while (i >= 0) {
1917
- const comment = this.comments[i];
1918
- if (comment.__ngt_renderer__[4 /* NgtRendererClassId.destroyed */]) {
1919
- i--;
1920
- continue;
1921
- }
1922
- const injector = comment.__ngt_renderer__[14 /* NgtRendererClassId.injectorFactory */]();
1923
- if (!injector) {
1924
- i--;
1925
- continue;
1926
- }
1927
- const instance = injector.get(dir, null);
1928
- if (instance && instance.validate()) {
1929
- directive = instance;
1930
- break;
1931
- }
1932
- i--;
1933
- }
1934
- return directive;
1935
- }
1936
- tryGetPortalStore() {
1937
- let store;
1938
- // we only care about the portal states because NgtStore only differs per Portal
1939
- let i = this.portals.length - 1;
1940
- while (i >= 0) {
1941
- // loop through the portal state backwards to find the closest NgtStore
1942
- const portal = this.portals[i];
1943
- if (portal.__ngt_renderer__[4 /* NgtRendererClassId.destroyed */]) {
1944
- i--;
1945
- continue;
1946
- }
1947
- const injector = portal.__ngt_renderer__[14 /* NgtRendererClassId.injectorFactory */]();
1948
- if (!injector) {
1949
- i--;
1950
- continue;
1951
- }
1952
- const instance = injector.get(NgtStore, null);
1953
- // only the instance with previousStore should pass
1954
- if (instance && instance.get('previousStore')) {
1955
- store = instance;
1956
- break;
1957
- }
1958
- i--;
1959
- }
1960
- return store || this.root.store;
1961
- }
1962
- }
1963
-
1964
- class NgtRendererFactory {
1965
- constructor() {
1966
- this.delegateRendererFactory = inject(RendererFactory2, { skipSelf: true });
1967
- this.catalogue = inject(NGT_CATALOGUE);
1968
- this.rendererMap = new Map();
1969
- this.routedSet = new Set();
1970
- // all Renderer instances share the same Store
1971
- this.rendererStore = new NgtRendererStore({
1972
- store: inject(NgtStore),
1973
- cdr: inject(ChangeDetectorRef),
1974
- portals: [],
1975
- compoundPrefixes: inject(NGT_COMPOUND_PREFIXES),
1976
- document: inject(DOCUMENT),
1977
- });
1978
- }
1979
- createRenderer(hostElement, type) {
1980
- const delegateRenderer = this.delegateRendererFactory.createRenderer(hostElement, type);
1981
- if (!type)
1982
- return delegateRenderer;
1983
- if (type['type']['isRoutedScene']) {
1984
- this.routedSet.add(type.id);
1985
- }
1986
- let renderer = this.rendererMap.get(type.id);
1987
- if (!renderer) {
1988
- renderer = new NgtRenderer(delegateRenderer, this.rendererStore, this.catalogue,
1989
- // setting root scene if there's no routed scene OR this component is the routed Scene
1990
- !hostElement && (this.routedSet.size === 0 || this.routedSet.has(type.id)));
1991
- this.rendererMap.set(type.id, renderer);
1992
- }
1993
- return renderer;
1994
- }
1995
- }
1996
- NgtRendererFactory.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtRendererFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1997
- NgtRendererFactory.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtRendererFactory });
1998
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtRendererFactory, decorators: [{
1999
- type: Injectable
2000
- }] });
2001
- /**
2002
- * Anything abbreviated with rS/RS stands for RendererState
2003
- */
2004
- class NgtRenderer {
2005
- constructor(delegate, store, catalogue, root = true) {
2006
- this.delegate = delegate;
2007
- this.store = store;
2008
- this.catalogue = catalogue;
2009
- this.root = root;
2010
- this.createText = this.delegate.createText.bind(this.delegate);
2011
- this.destroy = this.delegate.destroy.bind(this.delegate);
2012
- this.destroyNode = null;
2013
- this.selectRootElement = this.delegate.selectRootElement.bind(this.delegate);
2014
- this.nextSibling = this.delegate.nextSibling.bind(this.delegate);
2015
- this.removeAttribute = this.delegate.removeAttribute.bind(this.delegate);
2016
- this.addClass = this.delegate.addClass.bind(this.delegate);
2017
- this.removeClass = this.delegate.removeClass.bind(this.delegate);
2018
- this.setStyle = this.delegate.setStyle.bind(this.delegate);
2019
- this.removeStyle = this.delegate.removeStyle.bind(this.delegate);
2020
- this.setValue = this.delegate.setValue.bind(this.delegate);
2021
- }
2022
- createElement(name, namespace) {
2023
- const element = this.delegate.createElement(name, namespace);
2024
- // on first pass, we return the Root Scene as the root node
2025
- if (this.root) {
2026
- this.root = false;
2027
- const node = this.store.createNode('three', this.store.rootScene);
2028
- node.__ngt_renderer__[14 /* NgtRendererClassId.injectorFactory */] = () => getDebugNode(element).injector;
2029
- return node;
2030
- }
2031
- // handle compound
2032
- if (this.store.isCompound(name)) {
2033
- return this.store.createNode('compound', element);
2034
- }
2035
- // handle portal
2036
- if (name === SPECIAL_DOM_TAG.NGT_PORTAL) {
2037
- return this.store.createNode('portal', element);
2038
- }
2039
- // handle raw value
2040
- if (name === SPECIAL_DOM_TAG.NGT_VALUE) {
2041
- return this.store.createNode('three', Object.assign({ __ngt_renderer__: { rawValue: undefined } }, { __ngt__: { isRaw: true } }));
2042
- }
2043
- const { injectedArgs, injectedParent, store } = this.store.getCreationState();
2044
- let parent = injectedParent;
2045
- if (typeof injectedParent === 'string') {
2046
- parent = store
2047
- .get('scene')
2048
- .getObjectByName(injectedParent);
2049
- }
2050
- // handle primitive
2051
- if (name === SPECIAL_DOM_TAG.NGT_PRIMITIVE) {
2052
- if (!injectedArgs[0])
2053
- throw new Error(`[NGT] ngt-primitive without args is invalid`);
2054
- const object = injectedArgs[0];
2055
- let localState = getLocalState(object);
2056
- if (!Object.keys(localState).length) {
2057
- prepare(object, { store, args: injectedArgs, primitive: true });
2058
- localState = getLocalState(object);
2059
- }
2060
- if (!localState.store)
2061
- localState.store = store;
2062
- const node = this.store.createNode('three', object);
2063
- if (parent) {
2064
- node.__ngt_renderer__[2 /* NgtRendererClassId.injectedParent */] = parent;
2065
- }
2066
- return node;
2067
- }
2068
- const threeTag = name.startsWith('ngt') ? name.slice(4) : name;
2069
- const threeName = kebabToPascal(threeTag);
2070
- const threeTarget = this.catalogue[threeName];
2071
- // we have the THREE constructor here, handle it
2072
- if (threeTarget) {
2073
- const instance = prepare(new threeTarget(...injectedArgs), { store, args: injectedArgs });
2074
- const node = this.store.createNode('three', instance);
2075
- const localState = getLocalState(instance);
2076
- // auto-attach for geometry and material
2077
- if (is.geometry(instance)) {
2078
- localState.attach = ['geometry'];
2079
- }
2080
- else if (is.material(instance)) {
2081
- localState.attach = ['material'];
2082
- }
2083
- if (parent) {
2084
- node.__ngt_renderer__[2 /* NgtRendererClassId.injectedParent */] = parent;
2085
- }
2086
- return node;
2087
- }
2088
- return this.store.createNode('dom', element);
2089
- }
2090
- createComment(value) {
2091
- return this.store.createNode('comment', this.delegate.createComment(value));
2092
- }
2093
- appendChild(parent, newChild) {
2094
- // TODO: just ignore text node for now
2095
- if (newChild instanceof Text)
2096
- return;
2097
- const cRS = newChild.__ngt_renderer__;
2098
- const pRS = parent.__ngt_renderer__;
2099
- if (cRS[0 /* NgtRendererClassId.type */] === 'comment') {
2100
- this.store.setParent(newChild, parent);
2101
- return;
2102
- }
2103
- if (cRS[2 /* NgtRendererClassId.injectedParent */]) {
2104
- if (is.ref(cRS[2 /* NgtRendererClassId.injectedParent */])) {
2105
- cRS[2 /* NgtRendererClassId.injectedParent */].$.pipe(take(1)).subscribe((val) => {
2106
- if (val !== parent) {
2107
- this.appendChild(val, newChild);
2108
- }
2109
- });
2110
- return;
2111
- }
2112
- else if (parent !== cRS[2 /* NgtRendererClassId.injectedParent */]) {
2113
- this.appendChild(cRS[2 /* NgtRendererClassId.injectedParent */], newChild);
2114
- return;
2115
- }
2116
- }
2117
- this.store.setParent(newChild, parent);
2118
- this.store.addChild(parent, newChild);
2119
- // if new child is a portal
2120
- if (cRS[0 /* NgtRendererClassId.type */] === 'portal') {
2121
- this.store.processPortalContainer(newChild);
2122
- if (cRS[13 /* NgtRendererClassId.portalContainer */]) {
2123
- this.appendChild(parent, cRS[13 /* NgtRendererClassId.portalContainer */]);
2124
- }
2125
- return;
2126
- }
2127
- // if parent is a portal
2128
- if (pRS[0 /* NgtRendererClassId.type */] === 'portal') {
2129
- this.store.processPortalContainer(parent);
2130
- if (pRS[13 /* NgtRendererClassId.portalContainer */]) {
2131
- this.appendChild(pRS[13 /* NgtRendererClassId.portalContainer */], newChild);
2132
- }
2133
- return;
2134
- }
2135
- // if both are three instances, straightforward case
2136
- if (pRS[0 /* NgtRendererClassId.type */] === 'three' && cRS[0 /* NgtRendererClassId.type */] === 'three') {
2137
- // if child already attached to a parent, skip
2138
- if (getLocalState(newChild).parent)
2139
- return;
2140
- // attach THREE child
2141
- attachThreeChild(parent, newChild);
2142
- // here, we handle the special case of if the parent has a compoundParent, which means this child is part of a compound parent template
2143
- if (!cRS[5 /* NgtRendererClassId.compound */])
2144
- return;
2145
- const closestGrandparentWithCompound = this.store.getClosestParentWithCompound(parent);
2146
- if (!closestGrandparentWithCompound)
2147
- return;
2148
- this.appendChild(closestGrandparentWithCompound, newChild);
2149
- return;
2150
- }
2151
- // if only the parent is the THREE instance
2152
- if (pRS[0 /* NgtRendererClassId.type */] === 'three') {
2153
- for (const renderChild of cRS[3 /* NgtRendererClassId.children */]) {
2154
- this.appendChild(parent, renderChild);
2155
- }
2156
- }
2157
- // if parent is a compound
2158
- if (pRS[0 /* NgtRendererClassId.type */] === 'compound') {
2159
- // if compound doesn't have a THREE instance set yet
2160
- if (!pRS[7 /* NgtRendererClassId.compounded */] && cRS[0 /* NgtRendererClassId.type */] === 'three') {
2161
- // if child is indeed an ngtCompound
2162
- if (cRS[5 /* NgtRendererClassId.compound */])
2163
- this.store.setCompound(parent, newChild);
2164
- // if not, we track the parent (that is supposedly the compound component) on this three instance
2165
- else if (!cRS[6 /* NgtRendererClassId.compoundParent */])
2166
- cRS[6 /* NgtRendererClassId.compoundParent */] = parent;
2167
- }
2168
- // reset the compound if it's changed
2169
- if (pRS[7 /* NgtRendererClassId.compounded */] &&
2170
- cRS[0 /* NgtRendererClassId.type */] === 'three' &&
2171
- cRS[5 /* NgtRendererClassId.compound */] &&
2172
- pRS[7 /* NgtRendererClassId.compounded */] !== newChild) {
2173
- this.store.setCompound(parent, newChild);
2174
- }
2175
- }
2176
- const shouldFindGrandparentInstance =
2177
- // if child is three but haven't been attached to a parent yet
2178
- (cRS[0 /* NgtRendererClassId.type */] === 'three' && !getLocalState(newChild).parent) ||
2179
- // or both parent and child are DOM elements
2180
- // or they are compound AND haven't had a THREE instance yet
2181
- ((pRS[0 /* NgtRendererClassId.type */] === 'dom' ||
2182
- (pRS[0 /* NgtRendererClassId.type */] === 'compound' && !pRS[7 /* NgtRendererClassId.compounded */])) &&
2183
- (cRS[0 /* NgtRendererClassId.type */] === 'dom' ||
2184
- (cRS[0 /* NgtRendererClassId.type */] === 'compound' && !cRS[7 /* NgtRendererClassId.compounded */])));
2185
- if (shouldFindGrandparentInstance) {
2186
- // we'll try to get the grandparent instance here so that we can run appendChild with both instances
2187
- const closestGrandparentInstance = this.store.getClosestParentWithInstance(parent);
2188
- if (closestGrandparentInstance)
2189
- this.appendChild(closestGrandparentInstance, newChild);
2190
- }
2191
- }
2192
- insertBefore(parent, newChild
2193
- // TODO we might need these?
2194
- // refChild: NgtRendererNode
2195
- // isMove?: boolean | undefined
2196
- ) {
2197
- if (parent == null || !parent.__ngt_renderer__ || parent === newChild)
2198
- return;
2199
- this.appendChild(parent, newChild);
2200
- }
2201
- removeChild(parent, oldChild, isHostElement) {
2202
- const pRS = parent.__ngt_renderer__;
2203
- const cRS = oldChild.__ngt_renderer__;
2204
- if (pRS[0 /* NgtRendererClassId.type */] === 'three' && cRS[0 /* NgtRendererClassId.type */] === 'three') {
2205
- removeThreeChild(parent, oldChild, true);
2206
- this.store.destroy(oldChild, parent);
2207
- return;
2208
- }
2209
- if (pRS[0 /* NgtRendererClassId.type */] === 'compound' && pRS[1 /* NgtRendererClassId.parent */]) {
2210
- this.removeChild(pRS[1 /* NgtRendererClassId.parent */], oldChild, isHostElement);
2211
- return;
2212
- }
2213
- if (pRS[0 /* NgtRendererClassId.type */] === 'three') {
2214
- this.store.destroy(oldChild, parent);
2215
- return;
2216
- }
2217
- const closestGrandparentInstance = this.store.getClosestParentWithInstance(parent);
2218
- if (closestGrandparentInstance)
2219
- this.removeChild(closestGrandparentInstance, oldChild, isHostElement);
2220
- this.store.destroy(oldChild, closestGrandparentInstance);
2221
- }
2222
- parentNode(node) {
2223
- const rS = node.__ngt_renderer__;
2224
- if (rS === null || rS === void 0 ? void 0 : rS[1 /* NgtRendererClassId.parent */])
2225
- return rS[1 /* NgtRendererClassId.parent */];
2226
- return this.delegate.parentNode(node);
2227
- }
2228
- setAttribute(el, name, value, namespace) {
2229
- const rS = el.__ngt_renderer__;
2230
- if (rS[0 /* NgtRendererClassId.type */] === 'compound') {
2231
- // we don't have the compound instance yet
2232
- rS[9 /* NgtRendererClassId.attributes */][name] = value;
2233
- if (!rS[7 /* NgtRendererClassId.compounded */]) {
2234
- this.store.queueOperation(el, ['op', () => this.setAttribute(el, name, value, namespace)]);
2235
- return;
2236
- }
2237
- this.setAttribute(rS[7 /* NgtRendererClassId.compounded */], name, value, namespace);
2238
- return;
2239
- }
2240
- if (rS[0 /* NgtRendererClassId.type */] === 'three')
2241
- this.store.applyAttribute(el, name, value);
2242
- }
2243
- setProperty(el, name, value) {
2244
- const rS = el.__ngt_renderer__;
2245
- if (rS[0 /* NgtRendererClassId.type */] === 'compound') {
2246
- // we don't have the compound instance yet
2247
- rS[10 /* NgtRendererClassId.properties */][name] = value;
2248
- if (!rS[7 /* NgtRendererClassId.compounded */]) {
2249
- this.store.queueOperation(el, ['op', () => this.setProperty(el, name, value)]);
2250
- return;
2251
- }
2252
- if (rS[7 /* NgtRendererClassId.compounded */].__ngt_renderer__[5 /* NgtRendererClassId.compound */]) {
2253
- Object.assign(rS[7 /* NgtRendererClassId.compounded */].__ngt_renderer__[5 /* NgtRendererClassId.compound */], {
2254
- props: Object.assign(rS[7 /* NgtRendererClassId.compounded */].__ngt_renderer__[5 /* NgtRendererClassId.compound */], { [name]: value }),
2255
- });
2256
- }
2257
- this.setProperty(rS[7 /* NgtRendererClassId.compounded */], name, value);
2258
- return;
2259
- }
2260
- if (rS[0 /* NgtRendererClassId.type */] === 'three')
2261
- this.store.applyProperty(el, name, value);
2262
- }
2263
- listen(target, eventName, callback) {
2264
- var _a;
2265
- const rS = target.__ngt_renderer__;
2266
- const targetCdr = (_a = rS === null || rS === void 0 ? void 0 : rS[14 /* NgtRendererClassId.injectorFactory */]) === null || _a === void 0 ? void 0 : _a.call(rS).get(ChangeDetectorRef, null);
2267
- if (rS[0 /* NgtRendererClassId.type */] === 'three' ||
2268
- (rS[0 /* NgtRendererClassId.type */] === 'compound' && rS[7 /* NgtRendererClassId.compounded */])) {
2269
- const instance = rS[7 /* NgtRendererClassId.compounded */] || target;
2270
- const priority = getLocalState(target).priority;
2271
- return processThreeEvent(instance, priority || 0, eventName, callback, this.store.rootCdr, targetCdr);
2272
- }
2273
- if (rS[0 /* NgtRendererClassId.type */] === 'compound' && !rS[7 /* NgtRendererClassId.compounded */]) {
2274
- this.store.queueOperation(target, [
2275
- 'op',
2276
- () => this.store.queueOperation(target, ['cleanUp', this.listen(target, eventName, callback)]),
2277
- ]);
2278
- }
2279
- // setup a new callback with CDR so that it will trigger change detection properly
2280
- const callbackWithCdr = (event) => {
2281
- const value = callback(event);
2282
- safeDetectChanges(targetCdr);
2283
- safeDetectChanges(this.store.rootCdr);
2284
- return value;
2285
- };
2286
- // if the target doesn't have __ngt_renderer__, we delegate
2287
- if (!rS) {
2288
- return this.delegate.listen(target, eventName, callbackWithCdr);
2289
- }
2290
- // if target is DOM node, then we pass that to delegate Renderer
2291
- if (this.store.isDOM(target)) {
2292
- return this.delegate.listen(target, eventName, callbackWithCdr);
2293
- }
2294
- // @ts-expect-error - we know that target is not DOM node
2295
- if (target === this.store.rootScene) {
2296
- let [domTarget, event] = eventName.split(':');
2297
- if (event == null) {
2298
- event = domTarget;
2299
- domTarget = '';
2300
- }
2301
- const eventTarget = domTarget === 'window'
2302
- ? target['ownerDocument']['defaultView']
2303
- : target['ownerDocument'];
2304
- return this.delegate.listen(eventTarget, event, callbackWithCdr);
2305
- }
2306
- return () => { };
2307
- }
2308
- get data() {
2309
- return this.delegate.data;
2310
- }
2311
- }
2312
-
2313
- function provideNgtRenderer({ store, changeDetectorRef, compoundPrefixes = [] }) {
2314
- if (!compoundPrefixes.includes('ngts'))
2315
- compoundPrefixes.push('ngts');
2316
- if (!compoundPrefixes.includes('ngtp'))
2317
- compoundPrefixes.push('ngtp');
2318
- return makeEnvironmentProviders([
2319
- { provide: RendererFactory2, useClass: NgtRendererFactory },
2320
- { provide: NgtStore, useValue: store },
2321
- { provide: ChangeDetectorRef, useValue: changeDetectorRef },
2322
- { provide: NGT_COMPOUND_PREFIXES, useValue: compoundPrefixes },
2323
- ]);
2324
- }
2325
-
2326
- const DOM_EVENTS = {
2327
- click: false,
2328
- contextmenu: false,
2329
- dblclick: false,
2330
- wheel: false,
2331
- pointerdown: true,
2332
- pointerup: true,
2333
- pointerleave: true,
2334
- pointermove: true,
2335
- pointercancel: true,
2336
- lostpointercapture: true,
2337
- };
2338
- const supportedEvents = [
2339
- 'click',
2340
- 'contextmenu',
2341
- 'dblclick',
2342
- 'pointerup',
2343
- 'pointerdown',
2344
- 'pointerover',
2345
- 'pointerout',
2346
- 'pointerenter',
2347
- 'pointerleave',
2348
- 'pointermove',
2349
- 'pointermissed',
2350
- 'pointercancel',
2351
- 'wheel',
2352
- ];
2353
- function createPointerEvents(store) {
2354
- const { handlePointer } = createEvents(store);
2355
- return {
2356
- priority: 1,
2357
- enabled: true,
2358
- compute: (event, root) => {
2359
- const state = root.get();
2360
- // https://github.com/pmndrs/react-three-fiber/pull/782
2361
- // Events trigger outside of canvas when moved, use offsetX/Y by default and allow overrides
2362
- state.pointer.set((event.offsetX / state.size.width) * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1);
2363
- state.raycaster.setFromCamera(state.pointer, state.camera);
2364
- },
2365
- connected: undefined,
2366
- handlers: Object.keys(DOM_EVENTS).reduce((handlers, supportedEventName) => {
2367
- handlers[supportedEventName] = handlePointer(supportedEventName);
2368
- return handlers;
2369
- }, {}),
2370
- connect: (target) => {
2371
- var _a, _b, _c;
2372
- const state = store.get();
2373
- (_b = (_a = state.events).disconnect) === null || _b === void 0 ? void 0 : _b.call(_a);
2374
- state.setEvents({ connected: target });
2375
- Object.entries((_c = state.events.handlers) !== null && _c !== void 0 ? _c : {}).forEach(([eventName, eventHandler]) => {
2376
- const passive = DOM_EVENTS[eventName];
2377
- target.addEventListener(eventName, eventHandler, { passive });
2378
- });
2379
- },
2380
- disconnect: () => {
2381
- var _a;
2382
- const { events, setEvents } = store.get();
2383
- if (events.connected) {
2384
- Object.entries((_a = events.handlers) !== null && _a !== void 0 ? _a : {}).forEach(([eventName, eventHandler]) => {
2385
- if (events.connected instanceof HTMLElement) {
2386
- events.connected.removeEventListener(eventName, eventHandler);
2387
- }
2388
- });
2389
- setEvents({ connected: undefined });
2390
- }
2391
- },
2392
- };
2393
- }
2394
-
2395
- class NgtCanvas extends NgtRxStore {
2396
- constructor() {
2397
- super(...arguments);
2398
- this.cdr = inject(ChangeDetectorRef);
2399
- this.envInjector = inject(EnvironmentInjector);
2400
- this.host = inject(ElementRef);
2401
- this.store = inject(NgtStore);
2402
- this.hbClass = true;
2403
- this.sceneGraphInputs = {};
2404
- this.compoundPrefixes = [];
2405
- this.created = new EventEmitter();
2406
- this.pointerMissed = new EventEmitter();
2407
- }
2408
- initialize() {
2409
- super.initialize();
2410
- this.set({
2411
- shadows: false,
2412
- linear: false,
2413
- flat: false,
2414
- legacy: false,
2415
- orthographic: false,
2416
- frameloop: 'always',
2417
- dpr: [1, 2],
2418
- events: createPointerEvents,
2419
- });
2420
- }
2421
- get hbPointerEvents() {
2422
- return this.get('eventSource') !== this.host.nativeElement ? 'none' : 'auto';
2423
- }
2424
- set linear(linear) {
2425
- this.set({ linear });
2426
- }
2427
- set legacy(legacy) {
2428
- this.set({ legacy });
2429
- }
2430
- set flat(flat) {
2431
- this.set({ flat });
2432
- }
2433
- set orthographic(orthographic) {
2434
- this.set({ orthographic });
2435
- }
2436
- set frameloop(frameloop) {
2437
- this.set({ frameloop });
2438
- }
2439
- set dpr(dpr) {
2440
- this.set({ dpr });
2441
- }
2442
- set raycaster(raycaster) {
2443
- this.set({ raycaster });
2444
- }
2445
- set shadows(shadows) {
2446
- this.set({
2447
- shadows: typeof shadows === 'object' ? shadows : shadows,
2448
- });
2449
- }
2450
- set camera(camera) {
2451
- this.set({ camera });
2452
- }
2453
- set gl(gl) {
2454
- this.set({ gl });
2455
- }
2456
- set eventSource(eventSource) {
2457
- this.set({ eventSource });
2458
- }
2459
- set eventPrefix(eventPrefix) {
2460
- this.set({ eventPrefix });
2461
- }
2462
- set lookAt(lookAt) {
2463
- this.set({ lookAt });
2464
- }
2465
- set performance(performance) {
2466
- this.set({ performance });
2467
- }
2468
- ngOnChanges(changes) {
2469
- if (changes['sceneGraphInputs'] && this.glRef) {
2470
- this.setSceneGraphInputs();
2471
- }
2472
- }
2473
- ngOnInit() {
2474
- if (!this.get('eventSource')) {
2475
- // set default event source to the host element
2476
- this.eventSource = this.host.nativeElement;
2477
- }
2478
- if (this.pointerMissed.observed) {
2479
- this.store.set({
2480
- onPointerMissed: (event) => {
2481
- this.pointerMissed.emit(event);
2482
- safeDetectChanges(this.cdr);
2483
- },
2484
- });
2485
- }
2486
- // setup NgtStore
2487
- this.store.init();
2488
- // set rootStateMap
2489
- rootStateMap.set(this.glCanvas.nativeElement, this.store);
2490
- // subscribe to store to listen for ready state
2491
- this.hold(this.store.select('ready').pipe(filter((ready) => ready)), () => this.storeReady());
2492
- }
2493
- onResize({ width, height }) {
2494
- if (width > 0 && height > 0) {
2495
- if (!this.store.isInit)
2496
- this.store.init();
2497
- this.store.configure(this.get(), this.glCanvas.nativeElement);
2498
- }
2499
- }
2500
- storeReady() {
2501
- var _a, _b;
2502
- // canvas is ready, let's activate the loop
2503
- this.store.set((state) => ({ internal: Object.assign(Object.assign({}, state.internal), { active: true }) }));
2504
- const inputs = this.get();
2505
- const state = this.store.get();
2506
- // connect to event source
2507
- (_b = (_a = state.events).connect) === null || _b === void 0 ? void 0 : _b.call(_a, is.ref(inputs.eventSource) ? inputs.eventSource.nativeElement : inputs.eventSource);
2508
- // setup compute function for events
2509
- if (inputs.eventPrefix) {
2510
- state.setEvents({
2511
- compute: (event, store) => {
2512
- const innerState = store.get();
2513
- const x = event[(inputs.eventPrefix + 'X')];
2514
- const y = event[(inputs.eventPrefix + 'Y')];
2515
- innerState.pointer.set((x / innerState.size.width) * 2 - 1, -(y / innerState.size.height) * 2 + 1);
2516
- innerState.raycaster.setFromCamera(innerState.pointer, innerState.camera);
2517
- },
2518
- });
2519
- }
2520
- // emit created event if observed
2521
- if (this.created.observed)
2522
- this.created.emit(this.store.get());
2523
- // render
2524
- if (this.glRef)
2525
- this.glRef.destroy();
2526
- requestAnimationFrame(() => {
2527
- const { store, cdr: changeDetectorRef, compoundPrefixes } = this;
2528
- this.glEnvInjector = createEnvironmentInjector([provideNgtRenderer({ store, changeDetectorRef, compoundPrefixes })], this.envInjector);
2529
- this.glRef = this.glAnchor.createComponent(this.sceneGraph, { environmentInjector: this.glEnvInjector });
2530
- // detach the Scene graph from Change Detection mechanism
2531
- // everything from this point forward will trigger CD manually with detectChanges
2532
- this.glRef.changeDetectorRef.detach();
2533
- this.setSceneGraphInputs();
2534
- // here, we override the detectChanges to also call detectChanges on the ComponentRef
2535
- this.overrideDetectChanges();
2536
- this.cdr.detectChanges();
2537
- });
2538
- }
2539
- ngOnDestroy() {
2540
- if (this.glRef)
2541
- this.glRef.destroy();
2542
- if (this.glEnvInjector)
2543
- this.glEnvInjector.destroy();
2544
- injectNgtLoader.destroy();
2545
- this.store.destroy(this.glCanvas.nativeElement);
2546
- super.ngOnDestroy();
2547
- }
2548
- overrideDetectChanges() {
2549
- const originalDetectChanges = this.cdr.detectChanges.bind(this.cdr);
2550
- this.cdr.detectChanges = () => {
2551
- var _a;
2552
- originalDetectChanges();
2553
- safeDetectChanges((_a = this.glRef) === null || _a === void 0 ? void 0 : _a.changeDetectorRef);
2554
- };
2555
- }
2556
- setSceneGraphInputs() {
2557
- for (const key of Object.keys(this.sceneGraphInputs)) {
2558
- this.glRef.setInput(key, this.sceneGraphInputs[key]);
2559
- }
2560
- safeDetectChanges(this.cdr);
2561
- }
2562
- }
2563
- NgtCanvas.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtCanvas, deps: null, target: i0.ɵɵFactoryTarget.Component });
2564
- NgtCanvas.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.6", type: NgtCanvas, isStandalone: true, selector: "ngt-canvas", inputs: { sceneGraph: "sceneGraph", sceneGraphInputs: "sceneGraphInputs", compoundPrefixes: "compoundPrefixes", linear: "linear", legacy: "legacy", flat: "flat", orthographic: "orthographic", frameloop: "frameloop", dpr: "dpr", raycaster: "raycaster", shadows: "shadows", camera: "camera", gl: "gl", eventSource: "eventSource", eventPrefix: "eventPrefix", lookAt: "lookAt", performance: "performance" }, outputs: { created: "created", pointerMissed: "pointerMissed" }, host: { properties: { "class.ngt-canvas": "this.hbClass", "style.pointerEvents": "this.hbPointerEvents" } }, providers: [NgtStore, provideNgxResizeOptions({ emitInZone: false })], viewQueries: [{ propertyName: "glCanvas", first: true, predicate: ["glCanvas"], descendants: true, static: true }, { propertyName: "glAnchor", first: true, predicate: ["glCanvas"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `
2565
- <div (ngxResize)="onResize($event)" style="height: 100%; width: 100%;">
2566
- <canvas #glCanvas style="display: block;"></canvas>
2567
- </div>
2568
- `, isInline: true, styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}\n"], dependencies: [{ kind: "directive", type: NgxResize, selector: "[ngxResize]", inputs: ["ngxResizeOptions"], outputs: ["ngxResize"] }] });
2569
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtCanvas, decorators: [{
2570
- type: Component,
2571
- args: [{ selector: 'ngt-canvas', standalone: true, template: `
2572
- <div (ngxResize)="onResize($event)" style="height: 100%; width: 100%;">
2573
- <canvas #glCanvas style="display: block;"></canvas>
2574
- </div>
2575
- `, imports: [NgxResize], providers: [NgtStore, provideNgxResizeOptions({ emitInZone: false })], styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}\n"] }]
2576
- }], propDecorators: { hbClass: [{
2577
- type: HostBinding,
2578
- args: ['class.ngt-canvas']
2579
- }], hbPointerEvents: [{
2580
- type: HostBinding,
2581
- args: ['style.pointerEvents']
2582
- }], sceneGraph: [{
2583
- type: Input
2584
- }], sceneGraphInputs: [{
2585
- type: Input
2586
- }], compoundPrefixes: [{
2587
- type: Input
2588
- }], linear: [{
2589
- type: Input
2590
- }], legacy: [{
2591
- type: Input
2592
- }], flat: [{
2593
- type: Input
2594
- }], orthographic: [{
2595
- type: Input
2596
- }], frameloop: [{
2597
- type: Input
2598
- }], dpr: [{
2599
- type: Input
2600
- }], raycaster: [{
2601
- type: Input
2602
- }], shadows: [{
2603
- type: Input
2604
- }], camera: [{
2605
- type: Input
2606
- }], gl: [{
2607
- type: Input
2608
- }], eventSource: [{
2609
- type: Input
2610
- }], eventPrefix: [{
2611
- type: Input
2612
- }], lookAt: [{
2613
- type: Input
2614
- }], performance: [{
2615
- type: Input
2616
- }], created: [{
2617
- type: Output
2618
- }], pointerMissed: [{
2619
- type: Output
2620
- }], glCanvas: [{
2621
- type: ViewChild,
2622
- args: ['glCanvas', { static: true }]
2623
- }], glAnchor: [{
2624
- type: ViewChild,
2625
- args: ['glCanvas', { static: true, read: ViewContainerRef }]
2626
- }] } });
2627
-
2628
- /**
2629
- * A utility injection fn that can be used in other injection fn to provide the destroy capability.
2630
- */
2631
- function injectNgtDestroy(cb) {
2632
- try {
2633
- const cdr = inject(ChangeDetectorRef);
2634
- const destroy$ = new ReplaySubject();
2635
- queueMicrotask(() => {
2636
- cdr.onDestroy(() => {
2637
- destroy$.next();
2638
- destroy$.complete();
2639
- cb === null || cb === void 0 ? void 0 : cb();
2640
- });
2641
- });
2642
- return { destroy$, cdr };
2643
- }
2644
- catch (e) {
2645
- throw new Error(`[NGT] injectNgtDestroy is being called outside of Constructor Context`);
2646
- }
2647
- }
2648
-
2649
- function injectBeforeRender(cb, priority = 0) {
2650
- try {
2651
- const store = inject(NgtStore);
2652
- const sub = store.get('internal').subscribe(cb, priority, store);
2653
- injectNgtDestroy(() => void sub());
2654
- return sub;
2655
- }
2656
- catch (e) {
2657
- throw new Error(`[NGT] "injectBeforeRender" is invoked outside of Constructor Context`);
2658
- }
2659
- }
2660
-
2661
- function injectNgtRef(initialValue = null) {
2662
- const ref = is.ref(initialValue) ? initialValue : new ElementRef(initialValue);
2663
- let lastValue = ref.nativeElement;
2664
- const cdRefs = [];
2665
- const ref$ = new BehaviorSubject(lastValue);
2666
- const { destroy$, cdr } = injectNgtDestroy(() => void ref$.complete());
2667
- cdRefs.push(cdr);
2668
- const obs$ = ref$.asObservable().pipe(distinctUntilChanged(), takeUntil(destroy$));
2669
- const subscribe = (callback) => obs$.subscribe((current) => {
2670
- callback(current, lastValue);
2671
- lastValue = current;
2672
- });
2673
- const useCDR = (cdr) => void cdRefs.push(cdr);
2674
- const $ = obs$.pipe(filter((value, index) => index > 0 || value != null), takeUntil(destroy$));
2675
- const children$ = (type = 'objects') => $.pipe(switchMap((instance) => {
2676
- const localState = getLocalState(instance);
2677
- if (localState.objects && localState.nonObjects) {
2678
- return merge(localState.objects, localState.nonObjects).pipe(map(() => {
2679
- try {
2680
- return type === 'both'
2681
- ? [...localState.objects.value, ...localState.nonObjects.value]
2682
- : localState[type].value;
2683
- }
2684
- catch (e) {
2685
- console.error(`[NGT] Exception in accessing children of ${instance}`);
2686
- return [];
2687
- }
2688
- }));
2689
- }
2690
- return of([]);
2691
- }), filter((children, index) => index > 0 || children.length > 0), takeUntil(destroy$));
2692
- // here, we override nativeElement to add more functionalities to nativeElement
2693
- Object.defineProperty(ref, 'nativeElement', {
2694
- set: (newVal) => {
2695
- if (ref.nativeElement !== newVal) {
2696
- ref$.next(newVal);
2697
- lastValue = ref.nativeElement;
2698
- ref.nativeElement = newVal;
2699
- // clone the cdRefs so we can mutate cdRefs in the loop
2700
- const cds = [...cdRefs];
2701
- for (let i = 0; i < cds.length; i++) {
2702
- const cd = cds[i];
2703
- // if a ChangeDetectorRef is destroyed, we stop tracking it and go to the next one
2704
- if (cd.destroyed) {
2705
- cdRefs.splice(i, 1);
2706
- continue;
2707
- }
2708
- // during creation phase, 'context' on ViewRef will be null
2709
- // we check the "context" to avoid running detectChanges during this phase.
2710
- // because there's nothing to check
2711
- safeDetectChanges(cd);
2712
- }
2713
- }
2714
- },
2715
- get: () => ref$.value,
2716
- });
2717
- return Object.assign(ref, { subscribe, $, children$, useCDR });
2718
- }
2719
-
2720
- /**
2721
- * Please use this sparringly and know what you're doing.
2722
- *
2723
- * Create a runInContext function that has access to the NodeInjector as well
2724
- */
2725
- function createRunInContext() {
2726
- const nodeInjector = inject(Injector);
2727
- const envInjector = inject(EnvironmentInjector);
2728
- const originalGet = envInjector.get.bind(envInjector);
2729
- return (cb) => {
2730
- let tryFromNodeInjector = false;
2731
- envInjector.get = (...args) => {
2732
- try {
2733
- const originalFlags = args[2];
2734
- if (!(originalFlags & 8)) {
2735
- args[2] |= 8;
2736
- }
2737
- const fromEnvInjector = originalGet(...args);
2738
- if (fromEnvInjector)
2739
- return fromEnvInjector;
2740
- if (fromEnvInjector === null && ((args[1] !== undefined && args[1] === null) || originalFlags & 8))
2741
- return fromEnvInjector;
2742
- args[2] = originalFlags;
2743
- if (!tryFromNodeInjector) {
2744
- tryFromNodeInjector = true;
2745
- const fromNodeInjector = nodeInjector.get(...args);
2746
- tryFromNodeInjector = false;
2747
- return fromNodeInjector;
2748
- }
2749
- return null;
2750
- }
2751
- catch (e) {
2752
- return originalGet(...args);
2753
- }
2754
- };
2755
- return envInjector.runInContext(cb);
2756
- };
2757
- }
2758
-
2759
- class NgtRepeat extends NgForOf {
2760
- set ngForRepeat(count) {
2761
- this.ngForOf = Number.isInteger(count) ? Array.from({ length: count }, (_, i) => i) : [];
2762
- }
2763
- }
2764
- NgtRepeat.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtRepeat, deps: null, target: i0.ɵɵFactoryTarget.Directive });
2765
- NgtRepeat.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.6", type: NgtRepeat, isStandalone: true, selector: "[ngFor][ngForRepeat]", inputs: { ngForRepeat: "ngForRepeat" }, usesInheritance: true, ngImport: i0 });
2766
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtRepeat, decorators: [{
2767
- type: Directive,
2768
- args: [{ selector: '[ngFor][ngForRepeat]', standalone: true }]
2769
- }], propDecorators: { ngForRepeat: [{
2770
- type: Input
2771
- }] } });
2772
-
2773
- function isPromise(value) {
2774
- return ((value instanceof Promise || Object.prototype.toString.call(value) === '[object Promise]') &&
2775
- typeof value['then'] === 'function');
2776
- }
2777
- class NgtPush {
2778
- constructor() {
2779
- this.cdr = inject(ChangeDetectorRef);
2780
- this.parentCdr = inject(ChangeDetectorRef, { skipSelf: true, optional: true });
2781
- this.envCdr = inject(EnvironmentInjector).get(ChangeDetectorRef, null);
2782
- }
2783
- transform(value, defaultValue = null) {
2784
- if (this.obj === value)
2785
- return this.latestValue;
2786
- this.obj = value;
2787
- this.latestValue = defaultValue;
2788
- if (this.sub)
2789
- this.sub.unsubscribe();
2790
- if (isObservable(this.obj))
2791
- this.sub = this.obj.subscribe(this.updateValue.bind(this));
2792
- else if (isPromise(this.obj))
2793
- this.obj.then(this.updateValue.bind(this));
2794
- else
2795
- throw new Error(`[NGT] Invalid value passed to ngtPush pipe`);
2796
- return this.latestValue;
2797
- }
2798
- updateValue(val) {
2799
- this.latestValue = val;
2800
- safeDetectChanges(this.cdr);
2801
- safeDetectChanges(this.parentCdr);
2802
- safeDetectChanges(this.envCdr);
2803
- }
2804
- ngOnDestroy() {
2805
- if (this.sub)
2806
- this.sub.unsubscribe();
2807
- this.latestValue = undefined;
2808
- this.obj = undefined;
2809
- }
2810
- }
2811
- NgtPush.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtPush, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2812
- NgtPush.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.2.6", ngImport: i0, type: NgtPush, isStandalone: true, name: "ngtPush", pure: false });
2813
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtPush, decorators: [{
2814
- type: Pipe,
2815
- args: [{ name: 'ngtPush', pure: false, standalone: true }]
2816
- }] });
2817
-
2818
- const privateKeys = [
2819
- 'get',
2820
- 'set',
2821
- 'select',
2822
- 'setSize',
2823
- 'setDpr',
2824
- 'setFrameloop',
2825
- 'events',
2826
- 'invalidate',
2827
- 'advance',
2828
- 'size',
2829
- 'viewport',
2830
- 'addInteraction',
2831
- 'removeInteraction',
2832
- ];
2833
- class NgtPortalBeforeRender {
2834
- constructor() {
2835
- this.portalStore = inject(NgtStore);
2836
- this.renderPriority = 1;
2837
- this.beforeRender = new EventEmitter();
2838
- }
2839
- ngOnInit() {
2840
- let oldClear;
2841
- this.subscription = this.portalStore.get('internal').subscribe(({ delta, frame }) => {
2842
- this.beforeRender.emit(Object.assign(Object.assign({}, this.portalStore.get()), { delta, frame }));
2843
- const { gl, scene, camera } = this.portalStore.get();
2844
- oldClear = gl.autoClear;
2845
- if (this.renderPriority === 1) {
2846
- // clear scene and render with default
2847
- gl.autoClear = true;
2848
- gl.render(this.parentScene, this.parentCamera);
2849
- }
2850
- // disable cleaning
2851
- gl.autoClear = false;
2852
- gl.clearDepth();
2853
- gl.render(scene, camera);
2854
- // restore
2855
- gl.autoClear = oldClear;
2856
- }, this.renderPriority, this.portalStore);
2857
- }
2858
- ngOnDestroy() {
2859
- var _a;
2860
- (_a = this.subscription) === null || _a === void 0 ? void 0 : _a.call(this);
2861
- }
2862
- }
2863
- NgtPortalBeforeRender.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtPortalBeforeRender, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2864
- NgtPortalBeforeRender.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.6", type: NgtPortalBeforeRender, isStandalone: true, selector: "[ngtPortalBeforeRender]", inputs: { renderPriority: "renderPriority", parentScene: "parentScene", parentCamera: "parentCamera" }, outputs: { beforeRender: "beforeRender" }, ngImport: i0 });
2865
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtPortalBeforeRender, decorators: [{
2866
- type: Directive,
2867
- args: [{ selector: '[ngtPortalBeforeRender]', standalone: true }]
2868
- }], propDecorators: { renderPriority: [{
2869
- type: Input
2870
- }], parentScene: [{
2871
- type: Input
2872
- }], parentCamera: [{
2873
- type: Input
2874
- }], beforeRender: [{
2875
- type: Output
2876
- }] } });
2877
- class NgtPortalContent {
2878
- constructor(vcr, parentVcr) {
2879
- const commentNode = vcr.element.nativeElement;
2880
- if (commentNode['__ngt_renderer_add_comment__']) {
2881
- commentNode['__ngt_renderer_add_comment__'](parentVcr.element.nativeElement);
2882
- delete commentNode['__ngt_renderer_add_comment__'];
2883
- }
2884
- }
2885
- }
2886
- NgtPortalContent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtPortalContent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ViewContainerRef, skipSelf: true }], target: i0.ɵɵFactoryTarget.Directive });
2887
- NgtPortalContent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.6", type: NgtPortalContent, isStandalone: true, selector: "ng-template[ngtPortalContent]", ngImport: i0 });
2888
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtPortalContent, decorators: [{
2889
- type: Directive,
2890
- args: [{ selector: 'ng-template[ngtPortalContent]', standalone: true }]
2891
- }], ctorParameters: function () {
2892
- return [{ type: i0.ViewContainerRef }, { type: i0.ViewContainerRef, decorators: [{
2893
- type: SkipSelf
2894
- }] }];
2895
- } });
2896
- class NgtPortal extends NgtRxStore {
2897
- constructor() {
2898
- super(...arguments);
2899
- this.autoRender = true;
2900
- this.autoRenderPriority = 1;
2901
- this.beforeRender = new EventEmitter();
2902
- this.parentStore = inject(NgtStore, { skipSelf: true });
2903
- this.parentScene = this.parentStore.get('scene');
2904
- this.parentCamera = this.parentStore.get('camera');
2905
- this.portalStore = inject(NgtStore, { self: true });
2906
- this.raycaster = new THREE.Raycaster();
2907
- this.pointer = new THREE.Vector2();
2908
- this.portalContentRendered = false;
2909
- }
2910
- set container(container) {
2911
- this.set({ container });
2912
- }
2913
- set state(state) {
2914
- this.set({ state });
2915
- }
2916
- initialize() {
2917
- super.initialize();
2918
- this.set({ container: injectNgtRef(prepare(new THREE.Scene())) });
2919
- }
2920
- ngOnInit() {
2921
- const previousState = this.parentStore.get();
2922
- const inputsState = this.get();
2923
- if (!inputsState.state && this.autoRender) {
2924
- inputsState.state = { events: { priority: this.autoRenderPriority + 1 } };
2925
- }
2926
- const _a = inputsState.state || {}, { events, size } = _a, restInputsState = __rest(_a, ["events", "size"]);
2927
- const containerState = inputsState.container;
2928
- const container = is.ref(containerState) ? containerState.nativeElement : containerState;
2929
- const localState = getLocalState(container);
2930
- if (!localState.store) {
2931
- localState.store = this.portalStore;
2932
- }
2933
- this.portalStore.set(Object.assign(Object.assign(Object.assign(Object.assign({}, previousState), { scene: container, raycaster: this.raycaster, pointer: this.pointer, previousStore: this.parentStore, events: Object.assign(Object.assign({}, previousState.events), (events || {})), size: Object.assign(Object.assign({}, previousState.size), (size || {})) }), restInputsState), { get: this.portalStore.get.bind(this.portalStore), set: this.portalStore.set.bind(this.portalStore), select: this.portalStore.select.bind(this.portalStore), setEvents: (events) => this.portalStore.set((state) => (Object.assign(Object.assign({}, state), { events: Object.assign(Object.assign({}, state.events), events) }))) }));
2934
- this.hold(this.parentStore.select(), (previous) => this.portalStore.set((state) => this.inject(previous, state)));
2935
- requestAnimationFrame(() => {
2936
- this.portalStore.set((injectState) => this.inject(this.parentStore.get(), injectState));
2937
- });
2938
- this.portalContentView = this.portalContentAnchor.createEmbeddedView(this.portalContentTemplate);
2939
- this.portalContentView.detectChanges();
2940
- this.portalContentRendered = true;
2941
- }
2942
- onBeforeRender(portal) {
2943
- this.beforeRender.emit({
2944
- root: Object.assign(Object.assign({}, this.parentStore.get()), { delta: portal.delta, frame: portal.frame }),
2945
- portal,
2946
- });
2947
- }
2948
- ngOnDestroy() {
2949
- if (this.portalContentView && !this.portalContentView.destroyed) {
2950
- this.portalContentView.destroy();
2951
- }
2952
- super.ngOnDestroy();
2953
- }
2954
- inject(rootState, injectState) {
2955
- const intersect = Object.assign({}, rootState);
2956
- Object.keys(intersect).forEach((key) => {
2957
- if (privateKeys.includes(key) ||
2958
- rootState[key] !== injectState[key]) {
2959
- delete intersect[key];
2960
- }
2961
- });
2962
- const inputs = this.get();
2963
- const _a = inputs.state || {}, { size, events } = _a, restInputsState = __rest(_a, ["size", "events"]);
2964
- let viewport = undefined;
2965
- if (injectState && size) {
2966
- const camera = injectState.camera;
2967
- viewport = rootState.viewport.getCurrentViewport(camera, new THREE.Vector3(), size);
2968
- if (camera !== rootState.camera)
2969
- updateCamera(camera, size);
2970
- }
2971
- return Object.assign(Object.assign(Object.assign({}, intersect), { scene: is.ref(inputs.container) ? inputs.container.nativeElement : inputs.container, raycaster: this.raycaster, pointer: this.pointer, previousStore: this.parentStore, events: Object.assign(Object.assign(Object.assign({}, rootState.events), ((injectState === null || injectState === void 0 ? void 0 : injectState.events) || {})), events), size: Object.assign(Object.assign({}, rootState.size), size), viewport: Object.assign(Object.assign({}, rootState.viewport), (viewport || {})) }), restInputsState);
2972
- }
2973
- }
2974
- NgtPortal.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtPortal, deps: null, target: i0.ɵɵFactoryTarget.Component });
2975
- NgtPortal.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.6", type: NgtPortal, isStandalone: true, selector: "ngt-portal", inputs: { container: "container", state: "state", autoRender: "autoRender", autoRenderPriority: "autoRenderPriority" }, outputs: { beforeRender: "beforeRender" }, providers: [NgtStore], queries: [{ propertyName: "portalContentTemplate", first: true, predicate: NgtPortalContent, descendants: true, read: TemplateRef, static: true }], viewQueries: [{ propertyName: "portalContentAnchor", first: true, predicate: ["portalContentAnchor"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, ngImport: i0, template: `
2976
- <ng-container #portalContentAnchor>
2977
- <ng-container
2978
- *ngIf="autoRender && portalContentRendered"
2979
- ngtPortalBeforeRender
2980
- [renderPriority]="autoRenderPriority"
2981
- [parentScene]="parentScene"
2982
- [parentCamera]="parentCamera"
2983
- (beforeRender)="onBeforeRender($event)"
2984
- />
2985
- </ng-container>
2986
- `, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgtPortalBeforeRender, selector: "[ngtPortalBeforeRender]", inputs: ["renderPriority", "parentScene", "parentCamera"], outputs: ["beforeRender"] }] });
2987
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtPortal, decorators: [{
2988
- type: Component,
2989
- args: [{
2990
- selector: 'ngt-portal',
2991
- standalone: true,
2992
- template: `
2993
- <ng-container #portalContentAnchor>
2994
- <ng-container
2995
- *ngIf="autoRender && portalContentRendered"
2996
- ngtPortalBeforeRender
2997
- [renderPriority]="autoRenderPriority"
2998
- [parentScene]="parentScene"
2999
- [parentCamera]="parentCamera"
3000
- (beforeRender)="onBeforeRender($event)"
3001
- />
3002
- </ng-container>
3003
- `,
3004
- imports: [NgIf, NgtPortalBeforeRender],
3005
- providers: [NgtStore],
3006
- }]
3007
- }], propDecorators: { container: [{
3008
- type: Input
3009
- }], state: [{
3010
- type: Input
3011
- }], autoRender: [{
3012
- type: Input
3013
- }], autoRenderPriority: [{
3014
- type: Input
3015
- }], beforeRender: [{
3016
- type: Output
3017
- }], portalContentTemplate: [{
3018
- type: ContentChild,
3019
- args: [NgtPortalContent, { read: TemplateRef, static: true }]
3020
- }], portalContentAnchor: [{
3021
- type: ViewChild,
3022
- args: ['portalContentAnchor', { read: ViewContainerRef, static: true }]
3023
- }] } });
3024
-
3025
- class NgtRoutedScene {
3026
- constructor(router) {
3027
- const { destroy$, cdr } = injectNgtDestroy();
3028
- router.events
3029
- .pipe(filter((event) => event instanceof ActivationEnd), takeUntil(destroy$))
3030
- .subscribe(() => safeDetectChanges(cdr));
3031
- }
3032
- }
3033
- NgtRoutedScene.isRoutedScene = true;
3034
- NgtRoutedScene.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtRoutedScene, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
3035
- NgtRoutedScene.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.6", type: NgtRoutedScene, isStandalone: true, selector: "ngt-routed-scene", ngImport: i0, template: `<router-outlet />`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }] });
3036
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.6", ngImport: i0, type: NgtRoutedScene, decorators: [{
3037
- type: Component,
3038
- args: [{
3039
- standalone: true,
3040
- selector: 'ngt-routed-scene',
3041
- template: `<router-outlet />`,
3042
- imports: [RouterOutlet],
3043
- }]
3044
- }], ctorParameters: function () { return [{ type: i1.Router }]; } });
3045
-
3046
- /**
3047
- * Generated bundle index. Do not edit.
3048
- */
3049
-
3050
- export { NGT_CATALOGUE, NgtArgs, NgtCanvas, NgtParent, NgtPortal, NgtPortalBeforeRender, NgtPortalContent, NgtPush, NgtRepeat, NgtRoutedScene, NgtRxStore, NgtStore, addAfterEffect, addEffect, addTail, applyProps, checkNeedsUpdate, checkUpdate, createAttachFunction, createLoop, createRunInContext, extend, flushGlobalEffects, getLocalState, injectBeforeRender, injectNgtDestroy, injectNgtLoader, injectNgtRef, invalidateInstance, is, makeDefaultCamera, makeDefaultRenderer, makeDpr, makeId, makeObjectGraph, prepare, rootStateMap, safeDetectChanges, startWithUndefined, tapEffect, updateCamera };
3051
- //# sourceMappingURL=angular-three.mjs.map