1
- import type { Gizmo , Nullable } from "core/index" ;
1
+ import type { Gizmo , IObserver , Nullable } from "core/index" ;
2
2
import type { ServiceDefinition } from "../../../modularity/serviceDefinition" ;
3
3
import type { ISceneContext } from "../../sceneContext" ;
4
4
import type { ISceneExplorerService } from "./sceneExplorerService" ;
@@ -11,6 +11,8 @@ import {
11
11
Cone16Regular ,
12
12
EyeOffRegular ,
13
13
EyeRegular ,
14
+ FlashlightOffRegular ,
15
+ FlashlightRegular ,
14
16
LightbulbRegular ,
15
17
VideoFilled ,
16
18
VideoRegular ,
@@ -19,6 +21,7 @@ import {
19
21
import { Camera } from "core/Cameras/camera" ;
20
22
import { FrameGraphUtils } from "core/FrameGraph/frameGraphUtils" ;
21
23
import { CameraGizmo } from "core/Gizmos/cameraGizmo" ;
24
+ import { LightGizmo } from "core/Gizmos/lightGizmo" ;
22
25
import { Light } from "core/Lights/light" ;
23
26
import { AbstractMesh } from "core/Meshes/abstractMesh" ;
24
27
import { TransformNode } from "core/Meshes/transformNode" ;
@@ -161,7 +164,6 @@ export const NodeExplorerServiceDefinition: ServiceDefinition<[], [ISceneExplore
161
164
} ,
162
165
} ) ;
163
166
164
- const gizmos = new Set < Gizmo > ( ) ;
165
167
let utilityLayer : Nullable < UtilityLayerRenderer > = null ;
166
168
const getOrCreateUtilityLayer = ( ) => {
167
169
if ( ! utilityLayer ) {
@@ -170,76 +172,104 @@ export const NodeExplorerServiceDefinition: ServiceDefinition<[], [ISceneExplore
170
172
return utilityLayer ;
171
173
} ;
172
174
173
- const cameraGizmoCommandRegistration = sceneExplorerService . addCommand ( {
174
- predicate : ( entity : unknown ) => entity instanceof Camera ,
175
- getCommand : ( camera ) => {
176
- const onChangeObservable = new Observable < void > ( ) ;
175
+ function addGizmoCommand < NodeT extends Node , GizmoT extends Gizmo > (
176
+ nodeClass : abstract new ( ...args : any [ ] ) => NodeT ,
177
+ gizmoClass : new ( ...args : ConstructorParameters < typeof Gizmo > ) => GizmoT ,
178
+ gizmoMap : WeakMap < NodeT , GizmoT > ,
179
+ onGizmoCreated : ( node : NodeT , gizmo : GizmoT ) => void
180
+ ) {
181
+ return sceneExplorerService . addCommand ( {
182
+ predicate : ( entity : unknown ) : entity is NodeT => entity instanceof nodeClass ,
183
+ getCommand : ( node ) => {
184
+ const onChangeObservable = new Observable < void > ( ) ;
177
185
178
- const getGizmo = ( ) => {
179
- return camera . reservedDataStore ?. cameraGizmo as Nullable < CameraGizmo > ;
180
- } ;
186
+ const getGizmo = ( ) => {
187
+ return gizmoMap . get ( node ) ;
188
+ } ;
181
189
182
- const createGizmo = ( ) => {
183
- const gizmo = new CameraGizmo ( getOrCreateUtilityLayer ( ) ) ;
184
- gizmo . camera = camera ;
185
- gizmo . material . reservedDataStore = { hidden : true } ;
190
+ let nodeDisposedObserver : Nullable < IObserver > = null ;
186
191
187
- gizmos . add ( gizmo ) ;
188
- if ( ! camera . reservedDataStore ) {
189
- camera . reservedDataStore = { } ;
190
- }
191
- camera . reservedDataStore . cameraGizmo = gizmo ;
192
+ const disposeGizmo = ( ) => {
193
+ const gizmo = getGizmo ( ) ;
194
+ if ( gizmo ) {
195
+ gizmoMap . delete ( node ) ;
196
+ gizmo . dispose ( ) ;
197
+ nodeDisposedObserver ?. remove ( ) ;
198
+ onChangeObservable . notifyObservers ( ) ;
199
+ }
200
+ } ;
192
201
193
- onChangeObservable . notifyObservers ( ) ;
202
+ const createGizmo = ( ) => {
203
+ const gizmo = new gizmoClass ( getOrCreateUtilityLayer ( ) ) ;
204
+ onGizmoCreated ( node , gizmo ) ;
205
+ gizmoMap . set ( node , gizmo ) ;
206
+ nodeDisposedObserver = node . onDisposeObservable . addOnce ( disposeGizmo ) ;
207
+ onChangeObservable . notifyObservers ( ) ;
208
+ return gizmo ;
209
+ } ;
194
210
195
- return gizmo ;
196
- } ;
211
+ return {
212
+ type : "toggle" ,
213
+ get displayName ( ) {
214
+ return `Turn ${ getGizmo ( ) ? "Off" : "On" } Gizmo` ;
215
+ } ,
216
+ icon : ( ) => ( getGizmo ( ) ? < Cone16Filled /> : < Cone16Regular /> ) ,
217
+ get isEnabled ( ) {
218
+ return ! ! getGizmo ( ) ;
219
+ } ,
220
+ set isEnabled ( enabled : boolean ) {
221
+ if ( enabled ) {
222
+ if ( ! getGizmo ( ) ) {
223
+ createGizmo ( ) ;
224
+ }
225
+ } else {
226
+ disposeGizmo ( ) ;
227
+ }
228
+ } ,
229
+ onChange : onChangeObservable ,
230
+ dispose : ( ) => {
231
+ onChangeObservable . clear ( ) ;
232
+ } ,
233
+ } ;
234
+ } ,
235
+ } ) ;
236
+ }
197
237
198
- const disposeGizmo = ( ) => {
199
- const gizmo = getGizmo ( ) ;
200
- if ( gizmo ) {
201
- gizmos . delete ( gizmo ) ;
202
- delete camera . reservedDataStore . cameraGizmo ;
203
- gizmo . dispose ( ) ;
204
- }
205
-
206
- onChangeObservable . notifyObservers ( ) ;
207
- } ;
238
+ const cameraGizmos = new WeakMap < Camera , CameraGizmo > ( ) ;
239
+ const cameraGizmoCommandRegistration = addGizmoCommand ( Camera , CameraGizmo , cameraGizmos , ( camera , gizmo ) => ( gizmo . camera = camera ) ) ;
208
240
241
+ const lightEnabledCommandRegistration = sceneExplorerService . addCommand ( {
242
+ predicate : ( entity : unknown ) : entity is Light => entity instanceof Light ,
243
+ getCommand : ( light ) => {
209
244
return {
210
245
type : "toggle" ,
211
246
get displayName ( ) {
212
- return `Turn ${ getGizmo ( ) ? "Off" : "On" } Gizmo ` ;
247
+ return `Turn Light ${ light . isEnabled ( ) ? "Off" : "On" } ` ;
213
248
} ,
214
- icon : ( ) => ( getGizmo ( ) ? < Cone16Filled /> : < Cone16Regular /> ) ,
249
+ icon : ( ) => ( light . isEnabled ( ) ? < FlashlightRegular /> : < FlashlightOffRegular /> ) ,
215
250
get isEnabled ( ) {
216
- return ! ! getGizmo ( ) ;
251
+ return ! light . isEnabled ( ) ;
217
252
} ,
218
253
set isEnabled ( enabled : boolean ) {
219
- if ( enabled ) {
220
- if ( ! getGizmo ( ) ) {
221
- createGizmo ( ) ;
222
- }
223
- } else {
224
- disposeGizmo ( ) ;
225
- }
226
- } ,
227
- onChange : onChangeObservable ,
228
- dispose : ( ) => {
229
- onChangeObservable . clear ( ) ;
254
+ light . setEnabled ( ! enabled ) ;
230
255
} ,
256
+ onChange : light . onEnabledStateChangedObservable ,
231
257
} ;
232
258
} ,
233
259
} ) ;
234
260
261
+ const lightGizmos = new WeakMap < Light , LightGizmo > ( ) ;
262
+ const lightGizmoCommandRegistration = addGizmoCommand ( Light , LightGizmo , lightGizmos , ( light , gizmo ) => ( gizmo . light = light ) ) ;
263
+
235
264
return {
236
265
dispose : ( ) => {
237
266
sectionRegistration . dispose ( ) ;
238
- gizmos . forEach ( ( gizmo ) => gizmo . dispose ( ) ) ;
239
267
utilityLayer ?. dispose ( ) ;
240
268
abstractMeshVisibilityCommandRegistration . dispose ( ) ;
241
269
activeCameraCommandRegistration . dispose ( ) ;
242
270
cameraGizmoCommandRegistration . dispose ( ) ;
271
+ lightEnabledCommandRegistration . dispose ( ) ;
272
+ lightGizmoCommandRegistration . dispose ( ) ;
243
273
} ,
244
274
} ;
245
275
} ,
0 commit comments