angular-three 1.0.0-beta.8 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,114 @@
1
1
  import * as i0 from '@angular/core';
2
- import { ElementRef, Injectable, inject, InjectionToken, ViewContainerRef, TemplateRef, Directive, Input, EventEmitter, getDebugNode, ChangeDetectorRef, RendererFactory2, Component, Output, EnvironmentInjector, createEnvironmentInjector, HostBinding, ViewChild, Pipe } from '@angular/core';
3
- import { injectNgxResize, provideNgxResizeOptions } from 'ngx-resize';
4
- import { BehaviorSubject, startWith, tap, isObservable, of, map, from, retry, catchError, share, ReplaySubject, switchMap, forkJoin, take, filter, distinctUntilChanged, takeUntil, merge } from 'rxjs';
5
- import { DOCUMENT, NgForOf } from '@angular/common';
6
- import { RxState, selectSlice } from '@rx-angular/state';
2
+ import { ElementRef, Injectable, inject, InjectionToken, ViewContainerRef, TemplateRef, Directive, Input, EventEmitter, getDebugNode, ChangeDetectorRef, RendererFactory2, EnvironmentInjector, createEnvironmentInjector, Component, HostBinding, Output, ViewChild, 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, filter, distinctUntilChanged, takeUntil, merge } from 'rxjs';
7
5
  import * as THREE from 'three';
6
+ import { DOCUMENT, NgForOf, NgIf } from '@angular/common';
7
+ import { RxState, selectSlice } from '@rx-angular/state';
8
8
  import { ɵDomRendererFactory2 } from '@angular/platform-browser';
9
+ import { __classPrivateFieldGet } from 'tslib';
10
+
11
+ const idCache = {};
12
+ function makeId(event) {
13
+ if (event) {
14
+ return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
15
+ }
16
+ const newId = THREE.MathUtils.generateUUID();
17
+ // ensure not already used
18
+ if (!idCache[newId]) {
19
+ idCache[newId] = true;
20
+ return newId;
21
+ }
22
+ return makeId();
23
+ }
24
+ function makeDpr(dpr, window) {
25
+ const target = window?.devicePixelRatio || 1;
26
+ return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
27
+ }
28
+ function makeDefaultCamera(isOrthographic, size) {
29
+ if (isOrthographic)
30
+ return new THREE.OrthographicCamera(0, 0, 0, 0, 0.1, 1000);
31
+ return new THREE.PerspectiveCamera(75, size.width / size.height, 0.1, 1000);
32
+ }
33
+ function makeDefaultRenderer(glOptions, canvasElement) {
34
+ const customRenderer = (typeof glOptions === 'function' ? glOptions(canvasElement) : glOptions);
35
+ if (customRenderer?.render != null)
36
+ return customRenderer;
37
+ return new THREE.WebGLRenderer({
38
+ powerPreference: 'high-performance',
39
+ canvas: canvasElement,
40
+ antialias: true,
41
+ alpha: true,
42
+ ...(glOptions || {}),
43
+ });
44
+ }
45
+ function makeObjectGraph(object) {
46
+ const data = { nodes: {}, materials: {} };
47
+ if (object) {
48
+ object.traverse((child) => {
49
+ if (child.name)
50
+ data.nodes[child.name] = child;
51
+ if ('material' in child && !data.materials[child.material.name]) {
52
+ data.materials[child.material.name] = child
53
+ .material;
54
+ }
55
+ });
56
+ }
57
+ return data;
58
+ }
59
+
60
+ const cached = new Map();
61
+ function injectLoader(loaderConstructorFactory, input, extensions, onProgress) {
62
+ const urls$ = isObservable(input) ? input : of(input);
63
+ return urls$.pipe(map((inputs) => {
64
+ const loaderConstructor = loaderConstructorFactory(inputs);
65
+ const loader = new loaderConstructor();
66
+ if (extensions) {
67
+ extensions(loader);
68
+ }
69
+ const urls = Array.isArray(inputs) ? inputs : typeof inputs === 'string' ? [inputs] : Object.values(inputs);
70
+ return [
71
+ urls.map((url) => {
72
+ if (!cached.has(url)) {
73
+ cached.set(url, from(loader.loadAsync(url, onProgress)).pipe(tap((data) => {
74
+ if (data.scene) {
75
+ Object.assign(data, makeObjectGraph(data.scene));
76
+ }
77
+ }), retry(2), catchError((err) => {
78
+ console.error(`[NGT] Error loading ${url}: ${err.message}`);
79
+ return of([]);
80
+ }), share({
81
+ connector: () => new ReplaySubject(1),
82
+ resetOnComplete: true,
83
+ resetOnError: true,
84
+ resetOnRefCountZero: true,
85
+ })));
86
+ }
87
+ return cached.get(url);
88
+ }),
89
+ inputs,
90
+ ];
91
+ }), switchMap(([observables$, inputs]) => {
92
+ return forkJoin(observables$).pipe(map((results) => {
93
+ if (Array.isArray(inputs))
94
+ return results;
95
+ if (typeof inputs === 'string')
96
+ return results[0];
97
+ const keys = Object.keys(inputs);
98
+ return keys.reduce((result, key) => {
99
+ result[key] = results[keys.indexOf(key)];
100
+ return result;
101
+ }, {});
102
+ }));
103
+ }));
104
+ }
105
+ injectLoader.destroy = () => {
106
+ cached.clear();
107
+ };
108
+ injectLoader.preLoad = (loaderConstructorFactory, inputs, extensions) => {
109
+ injectLoader(loaderConstructorFactory, inputs, extensions).pipe(take(1)).subscribe();
110
+ };
111
+ const injectNgtLoader = injectLoader;
9
112
 
10
113
  function createSubs(callback, subs) {
11
114
  const sub = { callback };
@@ -240,7 +343,7 @@ function invalidateInstance(instance) {
240
343
  checkUpdate(instance);
241
344
  }
242
345
  function prepare(object, localState) {
243
- const instance = object;
346
+ const instance = (typeof object === 'function' ? object() : object);
244
347
  if (localState?.primitive || !instance.__ngt__) {
245
348
  const { objects = new BehaviorSubject([]), nonObjects = new BehaviorSubject([]), ...rest } = localState || {};
246
349
  instance.__ngt__ = {
@@ -253,7 +356,15 @@ function prepare(object, localState) {
253
356
  objects,
254
357
  nonObjects,
255
358
  add: (object, type) => {
256
- instance.__ngt__[type].next([...instance.__ngt__[type].value, object]);
359
+ const current = instance.__ngt__[type].value;
360
+ const foundIndex = current.indexOf((obj) => obj === object);
361
+ if (foundIndex > -1) {
362
+ current.splice(foundIndex, 1, object);
363
+ instance.__ngt__[type].next(current);
364
+ }
365
+ else {
366
+ instance.__ngt__[type].next([...instance.__ngt__[type].value, object]);
367
+ }
257
368
  notifyAncestors(instance.__ngt__.parent);
258
369
  },
259
370
  remove: (object, type) => {
@@ -364,55 +475,6 @@ function applyProps(instance, props) {
364
475
  return instance;
365
476
  }
366
477
 
367
- const idCache = {};
368
- function makeId(event) {
369
- if (event) {
370
- return (event.eventObject || event.object).uuid + '/' + event.index + event.instanceId;
371
- }
372
- const newId = THREE.MathUtils.generateUUID();
373
- // ensure not already used
374
- if (!idCache[newId]) {
375
- idCache[newId] = true;
376
- return newId;
377
- }
378
- return makeId();
379
- }
380
- function makeDpr(dpr, window) {
381
- const target = window?.devicePixelRatio || 1;
382
- return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], target), dpr[1]) : dpr;
383
- }
384
- function makeDefaultCamera(isOrthographic, size) {
385
- if (isOrthographic)
386
- return new THREE.OrthographicCamera(0, 0, 0, 0, 0.1, 1000);
387
- return new THREE.PerspectiveCamera(75, size.width / size.height, 0.1, 1000);
388
- }
389
- function makeDefaultRenderer(glOptions, canvasElement) {
390
- const customRenderer = (typeof glOptions === 'function' ? glOptions(canvasElement) : glOptions);
391
- if (customRenderer?.render != null)
392
- return customRenderer;
393
- return new THREE.WebGLRenderer({
394
- powerPreference: 'high-performance',
395
- canvas: canvasElement,
396
- antialias: true,
397
- alpha: true,
398
- ...(glOptions || {}),
399
- });
400
- }
401
- function makeObjectGraph(object) {
402
- const data = { nodes: {}, materials: {} };
403
- if (object) {
404
- object.traverse((child) => {
405
- if (child.name)
406
- data.nodes[child.name] = child;
407
- if ('material' in child && !data.materials[child.material.name]) {
408
- data.materials[child.material.name] = child
409
- .material;
410
- }
411
- });
412
- }
413
- return data;
414
- }
415
-
416
478
  const startWithUndefined = () => startWith(undefined);
417
479
  /**
418
480
  * An extended `tap` operator that accepts an `effectFn` which:
@@ -787,7 +849,7 @@ class NgtStore extends NgtRxStore {
787
849
  // Safely set color management if available.
788
850
  // Avoid accessing THREE.ColorManagement to play nice with older versions
789
851
  if (THREE.ColorManagement)
790
- THREE.ColorManagement.legacyMode = state.legacy;
852
+ THREE.ColorManagement.legacyMode = legacy ?? true;
791
853
  const outputEncoding = linear ? THREE.LinearEncoding : THREE.sRGBEncoding;
792
854
  const toneMapping = flat ? THREE.NoToneMapping : THREE.ACESFilmicToneMapping;
793
855
  if (gl.outputEncoding !== outputEncoding)
@@ -1300,6 +1362,9 @@ function assignEmpty(obj, base) {
1300
1362
  obj[base] = {};
1301
1363
  }
1302
1364
  }
1365
+ function createAttachFunction(cb) {
1366
+ return (parent, child, store) => cb({ parent, child, store });
1367
+ }
1303
1368
 
1304
1369
  const SPECIAL_DOM_TAG = {
1305
1370
  NGT_PORTAL: 'ngt-portal',
@@ -1403,7 +1468,7 @@ function removeThreeChild(parent, child, dispose) {
1403
1468
  removeThreeRecursive(child.childre, child, !!dispose);
1404
1469
  }
1405
1470
  // dispose
1406
- if (child['dispose'] && !is.scene(child)) {
1471
+ if (!isPrimitive && child['dispose'] && !is.scene(child)) {
1407
1472
  queueMicrotask(() => child['dispose']());
1408
1473
  }
1409
1474
  invalidateInstance(parent);
@@ -1501,14 +1566,18 @@ class NgtRendererStore {
1501
1566
  state[13 /* NgtRendererClassId.injectorFactory */] = () => getDebugNode(rendererNode).injector;
1502
1567
  // we attach an arrow function to the Comment node
1503
1568
  // In our directives, we can call this function to then start tracking the RendererNode
1504
- rendererNode['__ngt_renderer_add_comment__'] = () => {
1505
- this.comments.push(rendererNode);
1569
+ rendererNode['__ngt_renderer_add_comment__'] = (portalNode) => {
1570
+ if (portalNode && portalNode.__ngt_renderer__[0 /* NgtRendererClassId.type */] === 'portal') {
1571
+ this.portals.push(portalNode);
1572
+ }
1573
+ else {
1574
+ this.comments.push(rendererNode);
1575
+ }
1506
1576
  };
1507
1577
  return rendererNode;
1508
1578
  }
1509
1579
  if (state[0 /* NgtRendererClassId.type */] === 'portal') {
1510
1580
  state[13 /* NgtRendererClassId.injectorFactory */] = () => getDebugNode(rendererNode).injector;
1511
- this.portals.push(rendererNode);
1512
1581
  return rendererNode;
1513
1582
  }
1514
1583
  if (state[0 /* NgtRendererClassId.type */] === 'compound') {
@@ -1621,6 +1690,7 @@ class NgtRendererStore {
1621
1690
  if (node.__ngt_renderer__[3 /* NgtRendererClassId.destroyed */])
1622
1691
  return;
1623
1692
  // setup [ref] here
1693
+ // ref should never change
1624
1694
  if (name === SPECIAL_PROPERTIES.REF && is.ref(value)) {
1625
1695
  node.__ngt_renderer__[11 /* NgtRendererClassId.ref */] = value;
1626
1696
  value.nativeElement = node;
@@ -1806,7 +1876,8 @@ class NgtRendererStore {
1806
1876
  continue;
1807
1877
  }
1808
1878
  const instance = injector.get(NgtStore, null);
1809
- if (instance) {
1879
+ // only the instance with previousStore should pass
1880
+ if (instance && instance.get('previousStore')) {
1810
1881
  store = instance;
1811
1882
  break;
1812
1883
  }
@@ -2181,72 +2252,6 @@ function createPointerEvents(store) {
2181
2252
  };
2182
2253
  }
2183
2254
 
2184
- const cached = new Map();
2185
- function injectLoader(loaderConstructorFactory, input, extensions, onProgress) {
2186
- const urls$ = isObservable(input) ? input : of(input);
2187
- return urls$.pipe(map((inputs) => {
2188
- const loaderConstructor = loaderConstructorFactory(inputs);
2189
- const loader = new loaderConstructor();
2190
- if (extensions) {
2191
- extensions(loader);
2192
- }
2193
- const urls = Array.isArray(inputs) ? inputs : typeof inputs === 'string' ? [inputs] : Object.values(inputs);
2194
- return [
2195
- urls.map((url) => {
2196
- if (!cached.has(url)) {
2197
- cached.set(url, from(loader.loadAsync(url, onProgress)).pipe(tap((data) => {
2198
- if (data.scene) {
2199
- Object.assign(data, makeObjectGraph(data.scene));
2200
- }
2201
- }), retry(2), catchError((err) => {
2202
- console.error(`[NGT] Error loading ${url}: ${err.message}`);
2203
- return of([]);
2204
- }), share({
2205
- connector: () => new ReplaySubject(1),
2206
- resetOnComplete: true,
2207
- resetOnError: true,
2208
- resetOnRefCountZero: true,
2209
- })));
2210
- }
2211
- return cached.get(url);
2212
- }),
2213
- inputs,
2214
- ];
2215
- }), switchMap(([observables$, inputs]) => {
2216
- return forkJoin(observables$).pipe(map((results) => {
2217
- if (Array.isArray(inputs))
2218
- return results;
2219
- if (typeof inputs === 'string')
2220
- return results[0];
2221
- const keys = Object.keys(inputs);
2222
- return keys.reduce((result, key) => {
2223
- result[key] = results[keys.indexOf(key)];
2224
- return result;
2225
- }, {});
2226
- }));
2227
- }));
2228
- }
2229
- injectLoader.destroy = () => {
2230
- cached.clear();
2231
- };
2232
- injectLoader.preLoad = (loaderConstructorFactory, inputs, extensions) => {
2233
- injectLoader(loaderConstructorFactory, inputs, extensions).pipe(take(1)).subscribe();
2234
- };
2235
- const injectNgtLoader = injectLoader;
2236
-
2237
- class NgtCanvasContainer {
2238
- constructor() {
2239
- this.canvasResize = injectNgxResize();
2240
- }
2241
- }
2242
- NgtCanvasContainer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtCanvasContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
2243
- NgtCanvasContainer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.1.1", type: NgtCanvasContainer, isStandalone: true, selector: "ngt-canvas-container", outputs: { canvasResize: "canvasResize" }, providers: [provideNgxResizeOptions({ emitInZone: false })], ngImport: i0, template: '<ng-content />', isInline: true, styles: [":host{display:block;width:100%;height:100%}\n"] });
2244
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtCanvasContainer, decorators: [{
2245
- type: Component,
2246
- args: [{ selector: 'ngt-canvas-container', standalone: true, template: '<ng-content />', providers: [provideNgxResizeOptions({ emitInZone: false })], styles: [":host{display:block;width:100%;height:100%}\n"] }]
2247
- }], propDecorators: { canvasResize: [{
2248
- type: Output
2249
- }] } });
2250
2255
  class NgtCanvas extends NgtRxStore {
2251
2256
  constructor() {
2252
2257
  super(...arguments);
@@ -2384,7 +2389,9 @@ class NgtCanvas extends NgtRxStore {
2384
2389
  compoundPrefixes: this.compoundPrefixes,
2385
2390
  }),
2386
2391
  ], this.envInjector);
2387
- this.glRef = this.glAnchor.createComponent(this.sceneGraph, { environmentInjector: this.glEnvInjector });
2392
+ this.glRef = this.glAnchor.createComponent(this.sceneGraph, {
2393
+ environmentInjector: this.glEnvInjector,
2394
+ });
2388
2395
  this.glRef.changeDetectorRef.detach();
2389
2396
  // here, we override the detectChanges to also call detectChanges on the ComponentRef
2390
2397
  this.overrideDetectChanges();
@@ -2410,20 +2417,18 @@ class NgtCanvas extends NgtRxStore {
2410
2417
  }
2411
2418
  }
2412
2419
  NgtCanvas.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtCanvas, deps: null, target: i0.ɵɵFactoryTarget.Component });
2413
- NgtCanvas.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.1.1", type: NgtCanvas, isStandalone: true, selector: "ngt-canvas", inputs: { sceneGraph: "sceneGraph", 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.hostClass", "style.pointerEvents": "this.pointerEvents" } }, providers: [NgtStore], viewQueries: [{ propertyName: "glCanvas", first: true, predicate: ["glCanvas"], descendants: true, static: true }, { propertyName: "glAnchor", first: true, predicate: ["glAnchor"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, ngImport: i0, template: `
2414
- <ngt-canvas-container (canvasResize)="onResize($event)">
2420
+ NgtCanvas.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.1.1", type: NgtCanvas, isStandalone: true, selector: "ngt-canvas", inputs: { sceneGraph: "sceneGraph", 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.hostClass", "style.pointerEvents": "this.pointerEvents" } }, 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, ngImport: i0, template: `
2421
+ <div (ngxResize)="onResize($event)" style="height: 100%; width: 100%;">
2415
2422
  <canvas #glCanvas style="display: block;"></canvas>
2416
- <ng-container #glAnchor />
2417
- </ngt-canvas-container>
2418
- `, isInline: true, styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}\n"], dependencies: [{ kind: "component", type: NgtCanvasContainer, selector: "ngt-canvas-container", outputs: ["canvasResize"] }] });
2423
+ </div>
2424
+ `, 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"] }] });
2419
2425
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtCanvas, decorators: [{
2420
2426
  type: Component,
2421
2427
  args: [{ selector: 'ngt-canvas', standalone: true, template: `
2422
- <ngt-canvas-container (canvasResize)="onResize($event)">
2428
+ <div (ngxResize)="onResize($event)" style="height: 100%; width: 100%;">
2423
2429
  <canvas #glCanvas style="display: block;"></canvas>
2424
- <ng-container #glAnchor />
2425
- </ngt-canvas-container>
2426
- `, imports: [NgtCanvasContainer], providers: [NgtStore], styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}\n"] }]
2430
+ </div>
2431
+ `, imports: [NgxResize], providers: [NgtStore, provideNgxResizeOptions({ emitInZone: false })], styles: [":host{display:block;position:relative;width:100%;height:100%;overflow:hidden}\n"] }]
2427
2432
  }], propDecorators: { hostClass: [{
2428
2433
  type: HostBinding,
2429
2434
  args: ['class.ngt-canvas']
@@ -2471,21 +2476,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImpor
2471
2476
  args: ['glCanvas', { static: true }]
2472
2477
  }], glAnchor: [{
2473
2478
  type: ViewChild,
2474
- args: ['glAnchor', { static: true, read: ViewContainerRef }]
2475
- }] } });
2476
-
2477
- class NgtRepeat extends NgForOf {
2478
- set ngForRepeat(count) {
2479
- this.ngForOf = Number.isInteger(count) ? Array.from({ length: count }, (_, i) => i) : [];
2480
- }
2481
- }
2482
- NgtRepeat.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtRepeat, deps: null, target: i0.ɵɵFactoryTarget.Directive });
2483
- NgtRepeat.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.1", type: NgtRepeat, isStandalone: true, selector: "[ngFor][ngForRepeat]", inputs: { ngForRepeat: "ngForRepeat" }, usesInheritance: true, ngImport: i0 });
2484
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtRepeat, decorators: [{
2485
- type: Directive,
2486
- args: [{ selector: '[ngFor][ngForRepeat]', standalone: true }]
2487
- }], propDecorators: { ngForRepeat: [{
2488
- type: Input
2479
+ args: ['glCanvas', { static: true, read: ViewContainerRef }]
2489
2480
  }] } });
2490
2481
 
2491
2482
  /**
@@ -2510,6 +2501,18 @@ function injectNgtDestroy(cb) {
2510
2501
  }
2511
2502
  }
2512
2503
 
2504
+ function injectBeforeRender(cb, priority = 0) {
2505
+ try {
2506
+ const store = inject(NgtStore);
2507
+ const sub = store.get('internal').subscribe((state) => cb(state), priority, store);
2508
+ injectNgtDestroy(() => void sub());
2509
+ return sub;
2510
+ }
2511
+ catch (e) {
2512
+ throw new Error(`[NGT] "injectBeforeRender" is invoked outside of Constructor Context`);
2513
+ }
2514
+ }
2515
+
2513
2516
  function injectNgtRef(initialValue = null) {
2514
2517
  let ref = new ElementRef(initialValue);
2515
2518
  if (is.ref(initialValue)) {
@@ -2576,6 +2579,20 @@ function injectNgtRef(initialValue = null) {
2576
2579
  return Object.assign(ref, { subscribe, $, children$, useCDR: (cdr) => void cdRefs.push(cdr) });
2577
2580
  }
2578
2581
 
2582
+ class NgtRepeat extends NgForOf {
2583
+ set ngForRepeat(count) {
2584
+ this.ngForOf = Number.isInteger(count) ? Array.from({ length: count }, (_, i) => i) : [];
2585
+ }
2586
+ }
2587
+ NgtRepeat.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtRepeat, deps: null, target: i0.ɵɵFactoryTarget.Directive });
2588
+ NgtRepeat.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.1", type: NgtRepeat, isStandalone: true, selector: "[ngFor][ngForRepeat]", inputs: { ngForRepeat: "ngForRepeat" }, usesInheritance: true, ngImport: i0 });
2589
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtRepeat, decorators: [{
2590
+ type: Directive,
2591
+ args: [{ selector: '[ngFor][ngForRepeat]', standalone: true }]
2592
+ }], propDecorators: { ngForRepeat: [{
2593
+ type: Input
2594
+ }] } });
2595
+
2579
2596
  function isPromise(value) {
2580
2597
  return ((value instanceof Promise || Object.prototype.toString.call(value) === '[object Promise]') &&
2581
2598
  typeof value['then'] === 'function');
@@ -2627,9 +2644,239 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImpor
2627
2644
  args: [{ name: 'ngtPush', pure: false, standalone: true }]
2628
2645
  }] });
2629
2646
 
2647
+ var _NgtPortal_instances, _NgtPortal_inject;
2648
+ const privateKeys = [
2649
+ 'get',
2650
+ 'set',
2651
+ 'select',
2652
+ 'setSize',
2653
+ 'setDpr',
2654
+ 'setFrameloop',
2655
+ 'events',
2656
+ 'invalidate',
2657
+ 'advance',
2658
+ 'size',
2659
+ 'viewport',
2660
+ 'addInteraction',
2661
+ 'removeInteraction',
2662
+ ];
2663
+ class NgtPortalBeforeRender {
2664
+ constructor() {
2665
+ this.portalStore = inject(NgtStore);
2666
+ this.renderPriority = 1;
2667
+ this.beforeRender = new EventEmitter();
2668
+ }
2669
+ ngOnInit() {
2670
+ let oldClear;
2671
+ this.subscription = this.portalStore.get('internal').subscribe(({ delta, frame }) => {
2672
+ this.beforeRender.emit({ ...this.portalStore.get(), delta, frame });
2673
+ const { gl, scene, camera } = this.portalStore.get();
2674
+ oldClear = gl.autoClear;
2675
+ if (this.renderPriority === 1) {
2676
+ // clear scene and render with default
2677
+ gl.autoClear = true;
2678
+ gl.render(this.parentScene, this.parentCamera);
2679
+ }
2680
+ // disable cleaning
2681
+ gl.autoClear = false;
2682
+ gl.clearDepth();
2683
+ gl.render(scene, camera);
2684
+ // restore
2685
+ gl.autoClear = oldClear;
2686
+ }, this.renderPriority, this.portalStore);
2687
+ }
2688
+ ngOnDestroy() {
2689
+ this.subscription?.();
2690
+ }
2691
+ }
2692
+ NgtPortalBeforeRender.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtPortalBeforeRender, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2693
+ NgtPortalBeforeRender.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.1", type: NgtPortalBeforeRender, isStandalone: true, selector: "ngt-portal-before-render", inputs: { renderPriority: "renderPriority", parentScene: "parentScene", parentCamera: "parentCamera" }, outputs: { beforeRender: "beforeRender" }, ngImport: i0 });
2694
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtPortalBeforeRender, decorators: [{
2695
+ type: Directive,
2696
+ args: [{
2697
+ selector: 'ngt-portal-before-render',
2698
+ standalone: true,
2699
+ }]
2700
+ }], propDecorators: { renderPriority: [{
2701
+ type: Input
2702
+ }], parentScene: [{
2703
+ type: Input
2704
+ }], parentCamera: [{
2705
+ type: Input
2706
+ }], beforeRender: [{
2707
+ type: Output
2708
+ }] } });
2709
+ class NgtPortalContent {
2710
+ constructor(vcr, parentVcr) {
2711
+ const commentNode = vcr.element.nativeElement;
2712
+ if (commentNode['__ngt_renderer_add_comment__']) {
2713
+ commentNode['__ngt_renderer_add_comment__'](parentVcr.element.nativeElement);
2714
+ delete commentNode['__ngt_renderer_add_comment__'];
2715
+ }
2716
+ }
2717
+ }
2718
+ NgtPortalContent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtPortalContent, deps: [{ token: i0.ViewContainerRef }, { token: i0.ViewContainerRef, skipSelf: true }], target: i0.ɵɵFactoryTarget.Directive });
2719
+ NgtPortalContent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.1.1", type: NgtPortalContent, isStandalone: true, selector: "ng-template[ngtPortalContent]", ngImport: i0 });
2720
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtPortalContent, decorators: [{
2721
+ type: Directive,
2722
+ args: [{ selector: 'ng-template[ngtPortalContent]', standalone: true }]
2723
+ }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: i0.ViewContainerRef, decorators: [{
2724
+ type: SkipSelf
2725
+ }] }]; } });
2726
+ class NgtPortal extends NgtRxStore {
2727
+ constructor() {
2728
+ super(...arguments);
2729
+ _NgtPortal_instances.add(this);
2730
+ this.autoRender = true;
2731
+ this.autoRenderPriority = 1;
2732
+ this.beforeRender = new EventEmitter();
2733
+ this.parentStore = inject(NgtStore, { skipSelf: true });
2734
+ this.parentScene = this.parentStore.get('scene');
2735
+ this.parentCamera = this.parentStore.get('camera');
2736
+ this.portalStore = inject(NgtStore, { self: true });
2737
+ this.raycaster = new THREE.Raycaster();
2738
+ this.pointer = new THREE.Vector2();
2739
+ this.portalContentRendered = false;
2740
+ }
2741
+ set container(container) {
2742
+ this.set({ container });
2743
+ }
2744
+ set state(state) {
2745
+ this.set({ state });
2746
+ }
2747
+ initialize() {
2748
+ super.initialize();
2749
+ this.set({ container: injectNgtRef(prepare(new THREE.Scene())) });
2750
+ }
2751
+ ngOnInit() {
2752
+ const previousState = this.parentStore.get();
2753
+ const inputsState = this.get();
2754
+ if (!inputsState.state && this.autoRender) {
2755
+ inputsState.state = { events: { priority: this.autoRenderPriority + 1 } };
2756
+ }
2757
+ const { events, size, ...restInputsState } = inputsState.state || {};
2758
+ const containerState = inputsState.container;
2759
+ const container = is.ref(containerState) ? containerState.nativeElement : containerState;
2760
+ const localState = getLocalState(container);
2761
+ if (!localState.store) {
2762
+ localState.store = this.portalStore;
2763
+ }
2764
+ this.portalStore.set({
2765
+ ...previousState,
2766
+ scene: container,
2767
+ raycaster: this.raycaster,
2768
+ pointer: this.pointer,
2769
+ previousStore: this.parentStore,
2770
+ events: { ...previousState.events, ...(events || {}) },
2771
+ size: { ...previousState.size, ...(size || {}) },
2772
+ ...restInputsState,
2773
+ get: this.portalStore.get.bind(this.portalStore),
2774
+ set: this.portalStore.set.bind(this.portalStore),
2775
+ select: this.portalStore.select.bind(this.portalStore),
2776
+ setEvents: (events) => this.portalStore.set((state) => ({ ...state, events: { ...state.events, ...events } })),
2777
+ });
2778
+ this.hold(this.parentStore.select(), (previous) => this.portalStore.set((state) => __classPrivateFieldGet(this, _NgtPortal_instances, "m", _NgtPortal_inject).call(this, previous, state)));
2779
+ requestAnimationFrame(() => {
2780
+ this.portalStore.set((injectState) => __classPrivateFieldGet(this, _NgtPortal_instances, "m", _NgtPortal_inject).call(this, this.parentStore.get(), injectState));
2781
+ });
2782
+ this.portalContentView = this.portalContentAnchor.createEmbeddedView(this.portalContentTemplate);
2783
+ this.portalContentView.detectChanges();
2784
+ this.portalContentRendered = true;
2785
+ }
2786
+ onBeforeRender(portal) {
2787
+ this.beforeRender.emit({
2788
+ root: { ...this.parentStore.get(), delta: portal.delta, frame: portal.frame },
2789
+ portal,
2790
+ });
2791
+ }
2792
+ ngOnDestroy() {
2793
+ if (this.portalContentView && !this.portalContentView.destroyed) {
2794
+ this.portalContentView.destroy();
2795
+ }
2796
+ super.ngOnDestroy();
2797
+ }
2798
+ }
2799
+ _NgtPortal_instances = new WeakSet(), _NgtPortal_inject = function _NgtPortal_inject(rootState, injectState) {
2800
+ const intersect = { ...rootState };
2801
+ Object.keys(intersect).forEach((key) => {
2802
+ if (privateKeys.includes(key) ||
2803
+ rootState[key] !== injectState[key]) {
2804
+ delete intersect[key];
2805
+ }
2806
+ });
2807
+ const inputs = this.get();
2808
+ const { size, events, ...restInputsState } = inputs.state || {};
2809
+ let viewport = undefined;
2810
+ if (injectState && size) {
2811
+ const camera = injectState.camera;
2812
+ viewport = rootState.viewport.getCurrentViewport(camera, new THREE.Vector3(), size);
2813
+ if (camera !== rootState.camera)
2814
+ updateCamera(camera, size);
2815
+ }
2816
+ return {
2817
+ ...intersect,
2818
+ scene: is.ref(inputs.container) ? inputs.container.nativeElement : inputs.container,
2819
+ raycaster: this.raycaster,
2820
+ pointer: this.pointer,
2821
+ previousStore: this.parentStore,
2822
+ events: { ...rootState.events, ...(injectState?.events || {}), ...events },
2823
+ size: { ...rootState.size, ...size },
2824
+ viewport: { ...rootState.viewport, ...(viewport || {}) },
2825
+ ...restInputsState,
2826
+ };
2827
+ };
2828
+ NgtPortal.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtPortal, deps: null, target: i0.ɵɵFactoryTarget.Component });
2829
+ NgtPortal.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.1.1", 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: `
2830
+ <ng-container #portalContentAnchor>
2831
+ <ngt-portal-before-render
2832
+ *ngIf="autoRender && portalContentRendered"
2833
+ [renderPriority]="autoRenderPriority"
2834
+ [parentScene]="parentScene"
2835
+ [parentCamera]="parentCamera"
2836
+ (beforeRender)="onBeforeRender($event)"
2837
+ />
2838
+ </ng-container>
2839
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgtPortalBeforeRender, selector: "ngt-portal-before-render", inputs: ["renderPriority", "parentScene", "parentCamera"], outputs: ["beforeRender"] }] });
2840
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.1.1", ngImport: i0, type: NgtPortal, decorators: [{
2841
+ type: Component,
2842
+ args: [{
2843
+ selector: 'ngt-portal',
2844
+ standalone: true,
2845
+ template: `
2846
+ <ng-container #portalContentAnchor>
2847
+ <ngt-portal-before-render
2848
+ *ngIf="autoRender && portalContentRendered"
2849
+ [renderPriority]="autoRenderPriority"
2850
+ [parentScene]="parentScene"
2851
+ [parentCamera]="parentCamera"
2852
+ (beforeRender)="onBeforeRender($event)"
2853
+ />
2854
+ </ng-container>
2855
+ `,
2856
+ imports: [NgIf, NgtPortalBeforeRender],
2857
+ providers: [NgtStore],
2858
+ }]
2859
+ }], propDecorators: { container: [{
2860
+ type: Input
2861
+ }], state: [{
2862
+ type: Input
2863
+ }], autoRender: [{
2864
+ type: Input
2865
+ }], autoRenderPriority: [{
2866
+ type: Input
2867
+ }], beforeRender: [{
2868
+ type: Output
2869
+ }], portalContentTemplate: [{
2870
+ type: ContentChild,
2871
+ args: [NgtPortalContent, { read: TemplateRef, static: true }]
2872
+ }], portalContentAnchor: [{
2873
+ type: ViewChild,
2874
+ args: ['portalContentAnchor', { read: ViewContainerRef, static: true }]
2875
+ }] } });
2876
+
2630
2877
  /**
2631
2878
  * Generated bundle index. Do not edit.
2632
2879
  */
2633
2880
 
2634
- export { NGT_CATALOGUE, NgtArgs, NgtCanvas, NgtCanvasContainer, NgtPush, NgtRepeat, NgtRxStore, NgtStore, checkNeedsUpdate, checkUpdate, extend, getLocalState, injectNgtDestroy, injectNgtLoader, injectNgtRef, invalidateInstance, is, prepare, rootStateMap, startWithUndefined, updateCamera };
2881
+ export { NGT_CATALOGUE, NgtArgs, NgtCanvas, NgtPortal, NgtPortalBeforeRender, NgtPortalContent, NgtPush, NgtRepeat, NgtRxStore, NgtStore, checkNeedsUpdate, checkUpdate, createAttachFunction, extend, getLocalState, injectBeforeRender, injectNgtDestroy, injectNgtLoader, injectNgtRef, invalidateInstance, is, makeDefaultCamera, makeDefaultRenderer, makeDpr, makeId, makeObjectGraph, prepare, rootStateMap, startWithUndefined, updateCamera };
2635
2882
  //# sourceMappingURL=angular-three.mjs.map