|
1 | 1 | import { |
2 | | - afterNextRender, |
3 | 2 | ChangeDetectionStrategy, |
4 | 3 | Component, |
5 | 4 | computed, |
6 | 5 | CUSTOM_ELEMENTS_SCHEMA, |
7 | 6 | effect, |
8 | 7 | ElementRef, |
9 | | - inject, |
10 | 8 | Injector, |
11 | 9 | input, |
12 | 10 | viewChild, |
@@ -178,43 +176,40 @@ export class NgtsSampler { |
178 | 176 | options = input(defaultOptions, { transform: mergeInputs(defaultOptions) }); |
179 | 177 | parameters = omit(this.options, ['weight', 'transform', 'count']); |
180 | 178 |
|
181 | | - groupRef = viewChild.required<ElementRef<Group>>('group'); |
182 | | - |
183 | | - private sampleState = computed(() => { |
184 | | - const group = this.groupRef().nativeElement; |
185 | | - const localState = getLocalState(group); |
186 | | - if (!localState) return { mesh: null, instanced: null }; |
187 | | - |
188 | | - const [mesh, instances] = [resolveRef(this.mesh()), resolveRef(this.instances())]; |
189 | | - const objects = localState.objects(); |
190 | | - |
191 | | - return { |
192 | | - mesh: mesh ?? (objects.find((c) => c.type === 'Mesh') as Mesh), |
193 | | - instanced: |
194 | | - instances ?? (objects.find((c) => !!Object.getOwnPropertyDescriptor(c, 'instanceMatrix')) as InstancedMesh), |
195 | | - }; |
196 | | - }); |
| 179 | + // NOTE: this could have been a viewChild.required, but we need to _try_ to consume |
| 180 | + // this Signal earlier than when a viewChild.required would resolve. |
| 181 | + groupRef = viewChild<ElementRef<Group>>('group'); |
197 | 182 |
|
198 | 183 | constructor() { |
199 | 184 | extend({ Group }); |
200 | | - const injector = inject(Injector); |
201 | | - |
202 | | - afterNextRender(() => { |
203 | | - const meshToSample = pick(this.sampleState, 'mesh'); |
204 | | - const instancedToSample = pick(this.sampleState, 'instanced'); |
205 | | - |
206 | | - const sampler = injectSurfaceSampler( |
207 | | - meshToSample, |
208 | | - () => ({ |
209 | | - count: this.options().count, |
210 | | - transform: this.options().transform, |
211 | | - weight: this.options().weight, |
212 | | - instanceMesh: instancedToSample(), |
213 | | - }), |
214 | | - { injector }, |
215 | | - ); |
216 | 185 |
|
217 | | - effect(sampler, { injector }); |
| 186 | + const sampleState = computed(() => { |
| 187 | + const group = this.groupRef()?.nativeElement; |
| 188 | + const localState = getLocalState(group); |
| 189 | + if (!localState) return { mesh: null, instanced: null }; |
| 190 | + |
| 191 | + const [mesh, instances] = [resolveRef(this.mesh()), resolveRef(this.instances())]; |
| 192 | + const objects = localState.objects(); |
| 193 | + |
| 194 | + return { |
| 195 | + mesh: mesh ?? (objects.find((c) => c.type === 'Mesh') as Mesh), |
| 196 | + instanced: |
| 197 | + instances ?? (objects.find((c) => !!Object.getOwnPropertyDescriptor(c, 'instanceMatrix')) as InstancedMesh), |
| 198 | + }; |
218 | 199 | }); |
| 200 | + |
| 201 | + const meshToSample = pick(sampleState, 'mesh'); |
| 202 | + const instancedToSample = pick(sampleState, 'instanced'); |
| 203 | + |
| 204 | + // NOTE: because injectSurfaceSampler returns a computed, we need to consume |
| 205 | + // this computed in a Reactive Context (an effect) to ensure the inner logic of |
| 206 | + // injectSurfaceSampler is run properly. |
| 207 | + const sampler = injectSurfaceSampler(meshToSample, () => ({ |
| 208 | + count: this.options().count, |
| 209 | + transform: this.options().transform, |
| 210 | + weight: this.options().weight, |
| 211 | + instanceMesh: instancedToSample(), |
| 212 | + })); |
| 213 | + effect(sampler); |
219 | 214 | } |
220 | 215 | } |
0 commit comments