1
- import {
2
- afterNextRender ,
3
- booleanAttribute ,
4
- Directive ,
5
- ElementRef ,
6
- inject ,
7
- input ,
8
- signal ,
9
- untracked ,
10
- } from '@angular/core' ;
11
- import { injectAutoEffect } from 'ngxtension/auto-effect' ;
1
+ import { booleanAttribute , Directive , effect , ElementRef , inject , input , signal , untracked } from '@angular/core' ;
12
2
import { Group , Mesh , Object3D } from 'three' ;
13
3
import { getLocalState } from '../instance' ;
14
4
15
5
@Directive ( { standalone : true , selector : '[ngtSelection]' } )
16
6
export class NgtSelection {
17
7
enabled = input ( true , { alias : 'ngtSelection' , transform : booleanAttribute } ) ;
8
+
18
9
private source = signal < Array < ElementRef < Object3D > | Object3D > > ( [ ] ) ;
19
10
selected = this . source . asReadonly ( ) ;
20
- update = this . source . update . bind ( this . source ) ;
11
+
12
+ update ( ...args : Parameters < typeof this . source . update > ) {
13
+ if ( ! this . enabled ( ) ) return ;
14
+ this . source . update ( ...args ) ;
15
+ }
21
16
}
22
17
23
18
@Directive ( { standalone : true , selector : 'ngt-group[ngtSelect], ngt-mesh[ngtSelect]' } )
@@ -27,43 +22,44 @@ export class NgtSelect {
27
22
constructor ( ) {
28
23
const elementRef = inject < ElementRef < Group | Mesh > > ( ElementRef ) ;
29
24
const selection = inject ( NgtSelection ) ;
30
- const autoEffect = injectAutoEffect ( ) ;
31
25
32
- afterNextRender ( ( ) => {
33
- autoEffect (
34
- ( ) => {
35
- const enabled = this . enabled ( ) ;
36
- if ( ! enabled ) return ;
26
+ effect (
27
+ ( onCleanup ) => {
28
+ const selectionEnabled = selection . enabled ( ) ;
29
+ if ( ! selectionEnabled ) return ;
30
+
31
+ const enabled = this . enabled ( ) ;
32
+ if ( ! enabled ) return ;
37
33
38
- const host = elementRef . nativeElement ;
39
- if ( ! host ) return ;
34
+ const host = elementRef . nativeElement ;
35
+ if ( ! host ) return ;
40
36
41
- const localState = getLocalState ( host ) ;
42
- if ( ! localState ) return ;
37
+ const localState = getLocalState ( host ) ;
38
+ if ( ! localState ) return ;
43
39
44
- // ngt-mesh[ngtSelect]
45
- if ( host . type === 'Mesh' ) {
46
- selection . update ( ( prev ) => [ ...prev , host ] ) ;
47
- return ( ) => selection . update ( ( prev ) => prev . filter ( ( el ) => el !== host ) ) ;
48
- }
40
+ // ngt-mesh[ngtSelect]
41
+ if ( host . type === 'Mesh' ) {
42
+ selection . update ( ( prev ) => [ ...prev , host ] ) ;
43
+ onCleanup ( ( ) => selection . update ( ( prev ) => prev . filter ( ( el ) => el !== host ) ) ) ;
44
+ return ;
45
+ }
49
46
50
- const [ collection ] = [ untracked ( selection . selected ) , localState . objects ( ) ] ;
51
- let changed = false ;
52
- const current : Object3D [ ] = [ ] ;
53
- host . traverse ( ( child ) => {
54
- child . type === 'Mesh' && current . push ( child ) ;
55
- if ( collection . indexOf ( child ) === - 1 ) changed = true ;
56
- } ) ;
47
+ const [ collection ] = [ untracked ( selection . selected ) , localState . objects ( ) ] ;
48
+ let changed = false ;
49
+ const current : Object3D [ ] = [ ] ;
50
+ host . traverse ( ( child ) => {
51
+ child . type === 'Mesh' && current . push ( child ) ;
52
+ if ( collection . indexOf ( child ) === - 1 ) changed = true ;
53
+ } ) ;
57
54
58
- if ( ! changed ) return ;
55
+ if ( ! changed ) return ;
59
56
60
- selection . update ( ( prev ) => [ ...prev , ...current ] ) ;
61
- return ( ) => {
62
- selection . update ( ( prev ) => prev . filter ( ( el ) => ! current . includes ( el as Object3D ) ) ) ;
63
- } ;
64
- } ,
65
- { allowSignalWrites : true } ,
66
- ) ;
67
- } ) ;
57
+ selection . update ( ( prev ) => [ ...prev , ...current ] ) ;
58
+ onCleanup ( ( ) => {
59
+ selection . update ( ( prev ) => prev . filter ( ( el ) => ! current . includes ( el as Object3D ) ) ) ;
60
+ } ) ;
61
+ } ,
62
+ { allowSignalWrites : true } ,
63
+ ) ;
68
64
}
69
65
}
0 commit comments