1
- import {
2
- ChangeDetectorRef ,
3
- Injector ,
4
- computed ,
5
- effect ,
6
- inject ,
7
- runInInjectionContext ,
8
- signal ,
9
- untracked ,
10
- type Signal ,
11
- } from '@angular/core' ;
1
+ import { ChangeDetectorRef , Injector , effect , inject , runInInjectionContext , signal , type Signal } from '@angular/core' ;
12
2
import type { GLTF } from 'three/examples/jsm/loaders/GLTFLoader' ;
13
3
import type {
14
4
NgtAnyRecord ,
@@ -30,6 +20,12 @@ export type NgtLoaderResults<
30
20
31
21
const cached = new Map ( ) ;
32
22
23
+ function normalizeInputs ( input : string | string [ ] | Record < string , string > ) {
24
+ if ( Array . isArray ( input ) ) return input ;
25
+ if ( typeof input === 'string' ) return [ input ] ;
26
+ return Object . values ( input ) ;
27
+ }
28
+
33
29
function load <
34
30
TData ,
35
31
TUrl extends string | string [ ] | Record < string , string > ,
@@ -45,25 +41,16 @@ function load<
45
41
onProgress ?: ( event : ProgressEvent ) => void ;
46
42
} = { }
47
43
) {
48
- const computedUrls : Signal < string [ ] > = computed ( ( ) => {
49
- const input = inputs ( ) ;
50
- if ( Array . isArray ( input ) ) return input ;
51
- if ( typeof input === 'string' ) return [ input ] ;
52
- return Object . values ( input ) ;
53
- } ) ;
54
-
55
44
return ( ) => {
56
- const urls = computedUrls ( ) ;
57
- const loaderConstructor = loaderConstructorFactory ( urls ) ;
58
- const loader = new loaderConstructor ( ) ;
45
+ const urls = normalizeInputs ( inputs ( ) ) ;
46
+ const loader = new ( loaderConstructorFactory ( urls ) ) ( ) ;
59
47
if ( extensions ) extensions ( loader ) ;
60
-
61
- return urls . map (
62
- ( url ) =>
63
- new Promise ( ( resolve , reject ) => {
64
- if ( cached . has ( url ) ) {
65
- resolve ( cached . get ( url ) ) ;
66
- } else {
48
+ // TODO: reevaluate this
49
+ return urls . map ( ( url ) => {
50
+ if ( ! cached . has ( url ) ) {
51
+ cached . set (
52
+ url ,
53
+ new Promise ( ( resolve , reject ) => {
67
54
loader . load (
68
55
url ,
69
56
( data ) => {
@@ -72,15 +59,16 @@ function load<
72
59
data as NgtAnyRecord ,
73
60
makeObjectGraph ( ( data as NgtAnyRecord ) [ 'scene' ] )
74
61
) ;
75
- cached . set ( url , data ) ;
76
62
resolve ( data ) ;
77
63
} ,
78
64
onProgress ,
79
65
( error ) => reject ( new Error ( `[NGT] Could not load ${ url } : ${ error } ` ) )
80
66
) ;
81
- }
82
- } )
83
- ) ;
67
+ } )
68
+ ) ;
69
+ }
70
+ return cached . get ( url ) ! ;
71
+ } ) ;
84
72
} ;
85
73
}
86
74
@@ -103,31 +91,30 @@ export function injectNgtLoader<
103
91
} = { }
104
92
) : Signal < NgtLoaderResults < TUrl , NgtBranchingReturn < TReturn , GLTF , GLTF & NgtObjectMap > > > {
105
93
injector = assertInjectionContext ( injectNgtLoader , injector ) ;
94
+ const response = signal < NgtLoaderResults < TUrl , NgtBranchingReturn < TReturn , GLTF , GLTF & NgtObjectMap > > > ( null ! ) ;
106
95
return runInInjectionContext ( injector , ( ) => {
107
96
const cdr = inject ( ChangeDetectorRef ) ;
108
- const response = signal < NgtLoaderResults < TUrl , NgtBranchingReturn < TReturn , GLTF , GLTF & NgtObjectMap > > > ( null ! ) ;
109
97
const effector = load ( loaderConstructorFactory , inputs , { extensions, onProgress } ) ;
110
98
111
99
requestAnimationInInjectionContext ( ( ) => {
112
- effect ( ( ) => {
113
- const originalUrls = untracked ( inputs ) ;
114
- Promise . all ( effector ( ) )
115
- . then ( ( results ) => {
116
- if ( Array . isArray ( originalUrls ) ) return results ;
117
- if ( typeof originalUrls === 'string' ) return results [ 0 ] ;
118
- const keys = Object . keys ( originalUrls ) ;
119
- return keys . reduce ( ( result , key ) => {
120
- ( result as NgtAnyRecord ) [ key ] = results [ keys . indexOf ( key ) ] ;
121
- return result ;
122
- } , { } as { [ key in keyof TUrl ] : NgtBranchingReturn < TReturn , GLTF , GLTF & NgtObjectMap > } ) ;
123
- } )
124
- . then ( ( value ) => {
125
- response . set (
126
- value as NgtLoaderResults < TUrl , NgtBranchingReturn < TReturn , GLTF , GLTF & NgtObjectMap > >
127
- ) ;
100
+ effect (
101
+ ( ) => {
102
+ const originalUrls = inputs ( ) ;
103
+ Promise . all ( effector ( ) ) . then ( ( results ) => {
104
+ response . update ( ( ) => {
105
+ if ( Array . isArray ( originalUrls ) ) return results ;
106
+ if ( typeof originalUrls === 'string' ) return results [ 0 ] ;
107
+ const keys = Object . keys ( originalUrls ) ;
108
+ return keys . reduce ( ( result , key ) => {
109
+ ( result as NgtAnyRecord ) [ key ] = results [ keys . indexOf ( key ) ] ;
110
+ return result ;
111
+ } , { } as { [ key in keyof TUrl ] : NgtBranchingReturn < TReturn , GLTF , GLTF & NgtObjectMap > } ) ;
112
+ } ) ;
128
113
safeDetectChanges ( cdr ) ;
129
114
} ) ;
130
- } ) ;
115
+ } ,
116
+ { allowSignalWrites : true }
117
+ ) ;
131
118
} ) ;
132
119
133
120
return response . asReadonly ( ) ;
0 commit comments