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' ;
122import { Group , Mesh , Object3D } from 'three' ;
133import { getLocalState } from '../instance' ;
144
155@Directive ( { standalone : true , selector : '[ngtSelection]' } )
166export class NgtSelection {
177 enabled = input ( true , { alias : 'ngtSelection' , transform : booleanAttribute } ) ;
8+
189 private source = signal < Array < ElementRef < Object3D > | Object3D > > ( [ ] ) ;
1910 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+ }
2116}
2217
2318@Directive ( { standalone : true , selector : 'ngt-group[ngtSelect], ngt-mesh[ngtSelect]' } )
@@ -27,43 +22,44 @@ export class NgtSelect {
2722 constructor ( ) {
2823 const elementRef = inject < ElementRef < Group | Mesh > > ( ElementRef ) ;
2924 const selection = inject ( NgtSelection ) ;
30- const autoEffect = injectAutoEffect ( ) ;
3125
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 ;
3733
38- const host = elementRef . nativeElement ;
39- if ( ! host ) return ;
34+ const host = elementRef . nativeElement ;
35+ if ( ! host ) return ;
4036
41- const localState = getLocalState ( host ) ;
42- if ( ! localState ) return ;
37+ const localState = getLocalState ( host ) ;
38+ if ( ! localState ) return ;
4339
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+ }
4946
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+ } ) ;
5754
58- if ( ! changed ) return ;
55+ if ( ! changed ) return ;
5956
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+ ) ;
6864 }
6965}
0 commit comments