Skip to content

Commit 7f9b84e

Browse files
authored
Inspector v2: Add Effect Layers to Scene Explorer (#16877)
Adds effect layers to scene explorer: - Add `uniqueId` to `EffectLayer` - Add observables for add/remove effect layers, and *move* the add/remove functions from effectLayerSceneComponent.ts to scene.ts. This seems to be a weird case unlike any other entity types where the actual array of `EffectLayer`s lives in scene.ts, but the functions for adding/removing live in effectLayerSceneComponent.ts and the `EffectLayer` constructor directly pushes the instance into the `scene.effectLayers` array. To try to make things consistent, I've moved the `addEffectLayer` and `removeEffectLayer` to scene.ts, and call those functions from the `EffectLayer` constructor and dispose function. @sebavan - Add the effect layer explorer. <img width="366" height="407" alt="image" src="https://github.com/user-attachments/assets/3d8273d6-4247-439b-adf1-4f2887b817bd" />
1 parent 38e4b39 commit 7f9b84e

File tree

6 files changed

+120
-47
lines changed

6 files changed

+120
-47
lines changed

packages/dev/core/src/Layers/effectLayer.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { _WarnImport } from "../Misc/devTools";
2323
import { GetExponentOfTwo } from "../Misc/tools.functions";
2424
import type { ShaderLanguage } from "core/Materials/shaderLanguage";
2525
import { ThinEffectLayer } from "./thinEffectLayer";
26+
import { UniqueIdGenerator } from "core/Misc/uniqueIdGenerator";
2627

2728
/**
2829
* Effect layer options. This helps customizing the behaviour
@@ -117,6 +118,11 @@ export abstract class EffectLayer {
117118
ThinEffectLayer.ForceGLSL = value;
118119
}
119120

121+
/**
122+
* The unique id of the layer
123+
*/
124+
public readonly uniqueId = UniqueIdGenerator.UniqueId;
125+
120126
/**
121127
* The name of the layer
122128
*/
@@ -310,7 +316,7 @@ export abstract class EffectLayer {
310316

311317
this._engine = this._scene.getEngine();
312318
this._maxSize = this._engine.getCaps().maxTextureSize;
313-
this._scene.effectLayers.push(this);
319+
this._scene.addEffectLayer(this);
314320

315321
this._thinEffectLayer.onDisposeObservable.add(() => {
316322
this.onDisposeObservable.notifyObservers(this);
@@ -642,10 +648,7 @@ export abstract class EffectLayer {
642648
this._disposeTextureAndPostProcesses();
643649

644650
// Remove from scene
645-
const index = this._scene.effectLayers.indexOf(this, 0);
646-
if (index > -1) {
647-
this._scene.effectLayers.splice(index, 1);
648-
}
651+
this._scene.removeEffectLayer(this);
649652

650653
// Callback
651654
this.onDisposeObservable.clear();

packages/dev/core/src/Layers/effectLayerSceneComponent.ts

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Camera } from "../Cameras/camera";
2-
import { Scene } from "../scene";
2+
import type { Scene } from "../scene";
33
import type { AbstractEngine } from "../Engines/abstractEngine";
44
import type { AbstractMesh } from "../Meshes/abstractMesh";
55
import type { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
@@ -25,37 +25,6 @@ AddParser(SceneComponentConstants.NAME_EFFECTLAYER, (parsedData: any, scene: Sce
2525
}
2626
});
2727

28-
declare module "../scene" {
29-
// eslint-disable-next-line @typescript-eslint/naming-convention
30-
export interface Scene {
31-
/**
32-
* Removes the given effect layer from this scene.
33-
* @param toRemove defines the effect layer to remove
34-
* @returns the index of the removed effect layer
35-
*/
36-
removeEffectLayer(toRemove: EffectLayer): number;
37-
38-
/**
39-
* Adds the given effect layer to this scene
40-
* @param newEffectLayer defines the effect layer to add
41-
*/
42-
addEffectLayer(newEffectLayer: EffectLayer): void;
43-
}
44-
}
45-
46-
Scene.prototype.removeEffectLayer = function (toRemove: EffectLayer): number {
47-
const index = this.effectLayers.indexOf(toRemove);
48-
if (index !== -1) {
49-
this.effectLayers.splice(index, 1);
50-
}
51-
52-
return index;
53-
};
54-
55-
Scene.prototype.addEffectLayer = function (newEffectLayer: EffectLayer): void {
56-
this.effectLayers.push(newEffectLayer);
57-
};
58-
5928
/**
6029
* Defines the layer scene component responsible to manage any effect layers
6130
* in a given scene.

packages/dev/core/src/scene.ts

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -876,11 +876,6 @@ export class Scene implements IAnimatable, IClipPlanesHolder, IAssetContainer {
876876
*/
877877
public onNewMultiMaterialAddedObservable = new Observable<MultiMaterial>();
878878

879-
/**
880-
* An event triggered when a post process is created
881-
*/
882-
public onNewPostProcessAddedObservable = new Observable<PostProcess>();
883-
884879
/**
885880
* An event triggered when a material is removed
886881
*/
@@ -911,11 +906,26 @@ export class Scene implements IAnimatable, IClipPlanesHolder, IAssetContainer {
911906
*/
912907
public onFrameGraphRemovedObservable = new Observable<FrameGraph>();
913908

909+
/**
910+
* An event triggered when a post process is created
911+
*/
912+
public onNewPostProcessAddedObservable = new Observable<PostProcess>();
913+
914914
/**
915915
* An event triggered when a post process is removed
916916
*/
917917
public onPostProcessRemovedObservable = new Observable<PostProcess>();
918918

919+
/**
920+
* An event triggered when an effect layer is created
921+
*/
922+
public onNewEffectLayerAddedObservable = new Observable<EffectLayer>();
923+
924+
/**
925+
* An event triggered when an effect layer is removed
926+
*/
927+
public onEffectLayerRemovedObservable = new Observable<EffectLayer>();
928+
919929
/**
920930
* An event triggered when render targets are about to be rendered
921931
* Can happen multiple times per frame.
@@ -3087,6 +3097,21 @@ export class Scene implements IAnimatable, IClipPlanesHolder, IAssetContainer {
30873097
return index;
30883098
}
30893099

3100+
/**
3101+
* Removes the given layer from this scene.
3102+
* @param toRemove The layer to remove
3103+
* @returns The index of the removed layer
3104+
*/
3105+
public removeEffectLayer(toRemove: EffectLayer): number {
3106+
const index = this.effectLayers.indexOf(toRemove);
3107+
if (index !== -1) {
3108+
this.effectLayers.splice(index, 1);
3109+
}
3110+
this.onEffectLayerRemovedObservable.notifyObservers(toRemove);
3111+
3112+
return index;
3113+
}
3114+
30903115
/**
30913116
* Adds the given light to this scene
30923117
* @param newLight The light to add
@@ -3307,6 +3332,20 @@ export class Scene implements IAnimatable, IClipPlanesHolder, IAssetContainer {
33073332
});
33083333
}
33093334

3335+
/**
3336+
* Adds the given effect layer to this scene.
3337+
* @param newEffectLayer The effect layer to add
3338+
*/
3339+
public addEffectLayer(newEffectLayer: EffectLayer): void {
3340+
if (this._blockEntityCollection) {
3341+
return;
3342+
}
3343+
this.effectLayers.push(newEffectLayer);
3344+
Tools.SetImmediate(() => {
3345+
this.onNewEffectLayerAddedObservable.notifyObservers(newEffectLayer);
3346+
});
3347+
}
3348+
33103349
/**
33113350
* Switch active camera
33123351
* @param newCamera defines the new active camera

packages/dev/inspector-v2/src/inspector.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { SkeletonPropertiesServiceDefinition } from "./services/panes/properties
2929
import { SpritePropertiesServiceDefinition } from "./services/panes/properties/spritePropertiesService";
3030
import { TransformPropertiesServiceDefinition } from "./services/panes/properties/transformPropertiesService";
3131
import { AnimationGroupExplorerServiceDefinition } from "./services/panes/scene/animationGroupExplorerService";
32+
import { EffectLayerExplorerServiceDefinition } from "./services/panes/scene/effectLayersExplorerService";
3233
import { FrameGraphExplorerServiceDefinition } from "./services/panes/scene/frameGraphExplorerService";
3334
import { GuiExplorerServiceDefinition } from "./services/panes/scene/guiExplorerService";
3435
import { MaterialExplorerServiceDefinition } from "./services/panes/scene/materialExplorerService";
@@ -192,6 +193,7 @@ function _ShowInspector(scene: Nullable<Scene>, options: Partial<IInspectorOptio
192193
TextureExplorerServiceDefinition,
193194
PostProcessExplorerServiceDefinition,
194195
RenderingPipelineExplorerServiceDefinition,
196+
EffectLayerExplorerServiceDefinition,
195197
ParticleSystemExplorerServiceDefinition,
196198
SpriteManagerExplorerServiceDefinition,
197199
AnimationGroupExplorerServiceDefinition,

packages/dev/inspector-v2/src/services/panes/scene/defaultSectionsMetadata.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ export const enum DefaultSectionsOrder {
55
Textures = 400,
66
PostProcesses = 500,
77
RenderingPipelines = 600,
8-
ParticleSystems = 700,
9-
SpriteManagers = 800,
10-
AnimationGroups = 900,
11-
GUIs = 1000,
12-
FrameGraphs = 1100,
8+
EffectLayers = 700,
9+
ParticleSystems = 800,
10+
SpriteManagers = 900,
11+
AnimationGroups = 1000,
12+
GUIs = 1100,
13+
FrameGraphs = 1200,
1314
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import type { ServiceDefinition } from "../../../modularity/serviceDefinition";
2+
import type { ISceneContext } from "../../sceneContext";
3+
import type { ISceneExplorerService } from "./sceneExplorerService";
4+
5+
import { LayerRegular } from "@fluentui/react-icons";
6+
7+
import { Observable } from "core/Misc";
8+
import { EffectLayer } from "core/Layers/effectLayer";
9+
import { InterceptProperty } from "../../../instrumentation/propertyInstrumentation";
10+
import { SceneContextIdentity } from "../../sceneContext";
11+
import { DefaultSectionsOrder } from "./defaultSectionsMetadata";
12+
import { SceneExplorerServiceIdentity } from "./sceneExplorerService";
13+
14+
export const EffectLayerExplorerServiceDefinition: ServiceDefinition<[], [ISceneExplorerService, ISceneContext]> = {
15+
friendlyName: "Effect Layer Explorer",
16+
consumes: [SceneExplorerServiceIdentity, SceneContextIdentity],
17+
factory: (sceneExplorerService, sceneContext) => {
18+
const scene = sceneContext.currentScene;
19+
if (!scene) {
20+
return undefined;
21+
}
22+
23+
const sectionRegistration = sceneExplorerService.addSection({
24+
displayName: "Effect Layers",
25+
order: DefaultSectionsOrder.EffectLayers,
26+
predicate: (entity) => entity instanceof EffectLayer,
27+
getRootEntities: () => scene.effectLayers,
28+
getEntityDisplayInfo: (effectLayer) => {
29+
const onChangeObservable = new Observable<void>();
30+
31+
const nameHookToken = InterceptProperty(effectLayer, "name", {
32+
afterSet: () => {
33+
onChangeObservable.notifyObservers();
34+
},
35+
});
36+
37+
return {
38+
get name() {
39+
return effectLayer.name;
40+
},
41+
onChange: onChangeObservable,
42+
dispose: () => {
43+
nameHookToken.dispose();
44+
onChangeObservable.clear();
45+
},
46+
};
47+
},
48+
entityIcon: () => <LayerRegular />,
49+
getEntityAddedObservables: () => [scene.onNewEffectLayerAddedObservable],
50+
getEntityRemovedObservables: () => [scene.onEffectLayerRemovedObservable],
51+
});
52+
53+
return {
54+
dispose: () => {
55+
sectionRegistration.dispose();
56+
},
57+
};
58+
},
59+
};

0 commit comments

Comments
 (0)