6
6
InjectionToken ,
7
7
Injector ,
8
8
Signal ,
9
+ Type ,
9
10
afterNextRender ,
10
11
computed ,
11
12
inject ,
@@ -15,17 +16,23 @@ import {
15
16
} from '@angular/core' ;
16
17
import { takeUntilDestroyed } from '@angular/core/rxjs-interop' ;
17
18
import { CylinderArgs , Triplet } from '@pmndrs/cannon-worker-api' ;
18
- import { NgtArgs , extend , injectBeforeRender , injectStore } from 'angular-three' ;
19
+ import { NgtArgs , injectBeforeRender , injectStore } from 'angular-three' ;
19
20
import { NgtcPhysics } from 'angular-three-cannon' ;
20
21
import { injectBox , injectCylinder , injectSphere } from 'angular-three-cannon/body' ;
21
22
import { injectConeTwist } from 'angular-three-cannon/constraint' ;
22
23
import { NgtcDebug } from 'angular-three-cannon/debug' ;
23
- import * as THREE from 'three' ;
24
24
import { Color , ColorRepresentation , Mesh , Object3D } from 'three' ;
25
25
26
- extend ( THREE ) ;
26
+ interface Handle {
27
+ position : Signal < Triplet > | ( ( ) => Triplet ) ;
28
+ ref : Signal < ElementRef < Object3D > > ;
29
+ }
30
+
31
+ const Parent = new InjectionToken < Handle > ( 'PARENT' ) ;
27
32
28
- const Parent = new InjectionToken < { position : Signal < Triplet > ; ref : Signal < ElementRef < Object3D > > } > ( 'PARENT' ) ;
33
+ function provideParent < THandle extends object > ( handle : Type < THandle > , factory : ( h : THandle ) => Handle ) {
34
+ return { provide : Parent , useFactory : factory , deps : [ handle ] } ;
35
+ }
29
36
30
37
@Component ( {
31
38
selector : 'app-chain-link' ,
@@ -40,35 +47,26 @@ const Parent = new InjectionToken<{ position: Signal<Triplet>; ref: Signal<Eleme
40
47
imports : [ NgtArgs ] ,
41
48
schemas : [ CUSTOM_ELEMENTS_SCHEMA ] ,
42
49
changeDetection : ChangeDetectionStrategy . OnPush ,
43
- providers : [
44
- {
45
- provide : Parent ,
46
- useFactory : ( chainLink : ChainLink ) => ( { ref : chainLink . mesh , position : chainLink . position } ) ,
47
- deps : [ ChainLink ] ,
48
- } ,
49
- ] ,
50
+ providers : [ provideParent ( ChainLink , ( chainLink ) => ( { ref : chainLink . mesh , position : chainLink . position } ) ) ] ,
50
51
} )
51
52
export class ChainLink {
52
- parent = inject ( Parent , { skipSelf : true } ) ;
53
+ private parent = inject ( Parent , { skipSelf : true } ) ;
53
54
54
55
maxMultiplier = input < number > ( ) ;
55
56
color = input < ColorRepresentation > ( '#575757' ) ;
56
57
args = input < CylinderArgs > ( [ 0.5 , 0.5 , 2 , 16 ] ) ;
57
58
58
- height = computed ( ( ) => this . args ( ) [ 2 ] ?? 2 ) ;
59
- position = computed < Triplet > ( ( ) => {
59
+ private height = computed ( ( ) => this . args ( ) [ 2 ] ?? 2 ) ;
60
+ protected position = computed < Triplet > ( ( ) => {
60
61
const [ [ x , y , z ] , height ] = [ this . parent . position ( ) , this . height ( ) ] ;
61
62
return [ x , y - height , z ] ;
62
63
} ) ;
63
64
64
- mesh = viewChild . required < ElementRef < Mesh > > ( 'mesh' ) ;
65
-
66
- cylinder = injectCylinder (
67
- ( ) => ( { mass : 1 , args : this . args ( ) , linearDamping : 0.8 , position : this . position ( ) } ) ,
68
- this . mesh ,
69
- ) ;
65
+ protected mesh = viewChild . required < ElementRef < Mesh > > ( 'mesh' ) ;
70
66
71
67
constructor ( ) {
68
+ injectCylinder ( ( ) => ( { mass : 1 , args : this . args ( ) , linearDamping : 0.8 , position : this . position ( ) } ) , this . mesh ) ;
69
+
72
70
const injector = inject ( Injector ) ;
73
71
// NOTE: we want to run this in afterNextRender because we want the input to resolve
74
72
afterNextRender ( ( ) => {
@@ -111,7 +109,7 @@ export class Chain {
111
109
length = input . required < number > ( ) ;
112
110
maxMultiplier = input < number > ( ) ;
113
111
114
- color = computed ( ( ) => {
112
+ protected color = computed ( ( ) => {
115
113
const maxMultiplier = this . maxMultiplier ( ) ;
116
114
if ( maxMultiplier === undefined ) return '#575757' ;
117
115
@@ -128,7 +126,7 @@ export class Chain {
128
126
template : `
129
127
<ngt-group>
130
128
<ngt-mesh #mesh>
131
- <ngt-box-geometry *args="args() " />
129
+ <ngt-box-geometry *args="args" />
132
130
<ngt-mesh-standard-material [roughness]="0.3" color="#575757" />
133
131
</ngt-mesh>
134
132
<ng-content />
@@ -137,26 +135,19 @@ export class Chain {
137
135
imports : [ NgtArgs ] ,
138
136
schemas : [ CUSTOM_ELEMENTS_SCHEMA ] ,
139
137
changeDetection : ChangeDetectionStrategy . OnPush ,
140
- providers : [
141
- {
142
- provide : Parent ,
143
- useFactory : ( handle : PointerHandle ) => ( { ref : handle . mesh , position : ( ) => handle . position } ) ,
144
- deps : [ PointerHandle ] ,
145
- } ,
146
- ] ,
138
+ providers : [ provideParent ( PointerHandle , ( handle ) => ( { ref : handle . mesh , position : ( ) => handle . position } ) ) ] ,
147
139
} )
148
140
export class PointerHandle {
149
- size = input . required < number > ( ) ;
150
- args = computed < Triplet > ( ( ) => [ this . size ( ) , this . size ( ) , this . size ( ) * 2 ] ) ;
141
+ protected args = [ 1.5 , 1.5 , 1.5 * 2 ] as Triplet ;
151
142
152
- position : Triplet = [ 0 , 0 , 0 ] ;
153
- mesh = viewChild . required < ElementRef < Mesh > > ( 'mesh' ) ;
154
-
155
- boxApi = injectBox ( ( ) => ( { args : this . args ( ) , position : this . position , type : 'Kinematic' } ) , this . mesh ) ;
143
+ protected position : Triplet = [ 0 , 0 , 0 ] ;
144
+ protected mesh = viewChild . required < ElementRef < Mesh > > ( 'mesh' ) ;
156
145
157
146
constructor ( ) {
147
+ const boxApi = injectBox ( ( ) => ( { args : this . args , position : this . position , type : 'Kinematic' } ) , this . mesh ) ;
148
+
158
149
injectBeforeRender ( ( { pointer : { x, y } , viewport : { width, height } } ) => {
159
- this . boxApi ( ) ?. position . set ( ( x * width ) / 2 , ( y * height ) / 2 , 0 ) ;
150
+ boxApi ( ) ?. position . set ( ( x * width ) / 2 , ( y * height ) / 2 , 0 ) ;
160
151
} ) ;
161
152
}
162
153
}
@@ -167,29 +158,25 @@ export class PointerHandle {
167
158
template : `
168
159
<ngt-group>
169
160
<ngt-mesh #mesh>
170
- <ngt-sphere-geometry *args="[radius() , 64, 64]" />
161
+ <ngt-sphere-geometry *args="[1.5 , 64, 64]" />
171
162
<ngt-mesh-standard-material [roughness]="0.3" color="#575757" />
172
163
</ngt-mesh>
173
164
<ng-content />
174
165
</ngt-group>
175
166
` ,
176
167
imports : [ NgtArgs ] ,
177
- providers : [
178
- {
179
- provide : Parent ,
180
- useFactory : ( handle : StaticHandle ) => ( { ref : handle . mesh , position : handle . position } ) ,
181
- deps : [ StaticHandle ] ,
182
- } ,
183
- ] ,
168
+ providers : [ provideParent ( StaticHandle , ( handle ) => ( { ref : handle . mesh , position : handle . position } ) ) ] ,
184
169
schemas : [ CUSTOM_ELEMENTS_SCHEMA ] ,
185
170
changeDetection : ChangeDetectionStrategy . OnPush ,
186
171
} )
187
172
export class StaticHandle {
188
173
position = input . required < Triplet > ( ) ;
189
- radius = input . required < number > ( ) ;
190
- mesh = viewChild . required < ElementRef < Mesh > > ( 'mesh' ) ;
191
174
192
- sphere = injectSphere ( ( ) => ( { args : [ this . radius ( ) ] , position : this . position ( ) , type : 'Static' } ) , this . mesh ) ;
175
+ protected mesh = viewChild . required < ElementRef < Mesh > > ( 'mesh' ) ;
176
+
177
+ constructor ( ) {
178
+ injectSphere ( ( ) => ( { args : [ 1.5 ] , position : this . position ( ) , type : 'Static' } ) , this . mesh ) ;
179
+ }
193
180
}
194
181
195
182
@Component ( {
@@ -208,12 +195,12 @@ export class StaticHandle {
208
195
/>
209
196
210
197
<ngtc-physics [options]="{ gravity: [0, -40, 0], allowSleep: false }">
211
- <app-pointer-handle [size]="1.5" >
198
+ <app-pointer-handle>
212
199
<app-chain [length]="7" />
213
200
</app-pointer-handle>
214
201
215
202
@for (maxMultiplier of maxMultiplierExamples(); track maxMultiplier.key) {
216
- <app-static-handle [radius]="1.5" [ position]="maxMultiplier.position">
203
+ <app-static-handle [position]="maxMultiplier.position">
217
204
<app-chain [maxMultiplier]="maxMultiplier.value" [length]="8" />
218
205
</app-static-handle>
219
206
}
@@ -225,12 +212,12 @@ export class StaticHandle {
225
212
host : { class : 'chain-experience' } ,
226
213
} )
227
214
export class Experience {
228
- Math = Math ;
215
+ protected Math = Math ;
229
216
230
217
private store = injectStore ( ) ;
231
218
232
- resetCount = signal ( 0 ) ;
233
- maxMultiplierExamples = computed ( ( ) =>
219
+ private resetCount = signal ( 0 ) ;
220
+ protected maxMultiplierExamples = computed ( ( ) =>
234
221
maxMultiplierExamples . map ( ( value , index , array ) => ( {
235
222
value,
236
223
key : `${ value } -${ this . resetCount ( ) } ` ,
0 commit comments