diff --git a/packages/dev/core/src/Layers/effectLayer.ts b/packages/dev/core/src/Layers/effectLayer.ts index 8f939da56d7..705d69aa0d2 100644 --- a/packages/dev/core/src/Layers/effectLayer.ts +++ b/packages/dev/core/src/Layers/effectLayer.ts @@ -23,6 +23,7 @@ import { _WarnImport } from "../Misc/devTools"; import { GetExponentOfTwo } from "../Misc/tools.functions"; import type { ShaderLanguage } from "core/Materials/shaderLanguage"; import { ThinEffectLayer } from "./thinEffectLayer"; +import { UniqueIdGenerator } from "core/Misc/uniqueIdGenerator"; /** * Effect layer options. This helps customizing the behaviour @@ -117,6 +118,11 @@ export abstract class EffectLayer { ThinEffectLayer.ForceGLSL = value; } + /** + * The unique id of the layer + */ + public readonly uniqueId = UniqueIdGenerator.UniqueId; + /** * The name of the layer */ @@ -310,7 +316,7 @@ export abstract class EffectLayer { this._engine = this._scene.getEngine(); this._maxSize = this._engine.getCaps().maxTextureSize; - this._scene.effectLayers.push(this); + this._scene.addEffectLayer(this); this._thinEffectLayer.onDisposeObservable.add(() => { this.onDisposeObservable.notifyObservers(this); @@ -642,10 +648,7 @@ export abstract class EffectLayer { this._disposeTextureAndPostProcesses(); // Remove from scene - const index = this._scene.effectLayers.indexOf(this, 0); - if (index > -1) { - this._scene.effectLayers.splice(index, 1); - } + this._scene.removeEffectLayer(this); // Callback this.onDisposeObservable.clear(); diff --git a/packages/dev/core/src/Layers/effectLayerSceneComponent.ts b/packages/dev/core/src/Layers/effectLayerSceneComponent.ts index d499f6a77bf..48ac89e7d74 100644 --- a/packages/dev/core/src/Layers/effectLayerSceneComponent.ts +++ b/packages/dev/core/src/Layers/effectLayerSceneComponent.ts @@ -1,5 +1,5 @@ import { Camera } from "../Cameras/camera"; -import { Scene } from "../scene"; +import type { Scene } from "../scene"; import type { AbstractEngine } from "../Engines/abstractEngine"; import type { AbstractMesh } from "../Meshes/abstractMesh"; import type { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture"; @@ -25,37 +25,6 @@ AddParser(SceneComponentConstants.NAME_EFFECTLAYER, (parsedData: any, scene: Sce } }); -declare module "../scene" { - // eslint-disable-next-line @typescript-eslint/naming-convention - export interface Scene { - /** - * Removes the given effect layer from this scene. - * @param toRemove defines the effect layer to remove - * @returns the index of the removed effect layer - */ - removeEffectLayer(toRemove: EffectLayer): number; - - /** - * Adds the given effect layer to this scene - * @param newEffectLayer defines the effect layer to add - */ - addEffectLayer(newEffectLayer: EffectLayer): void; - } -} - -Scene.prototype.removeEffectLayer = function (toRemove: EffectLayer): number { - const index = this.effectLayers.indexOf(toRemove); - if (index !== -1) { - this.effectLayers.splice(index, 1); - } - - return index; -}; - -Scene.prototype.addEffectLayer = function (newEffectLayer: EffectLayer): void { - this.effectLayers.push(newEffectLayer); -}; - /** * Defines the layer scene component responsible to manage any effect layers * in a given scene. diff --git a/packages/dev/core/src/scene.ts b/packages/dev/core/src/scene.ts index efec6e46020..10d8d5af169 100644 --- a/packages/dev/core/src/scene.ts +++ b/packages/dev/core/src/scene.ts @@ -876,11 +876,6 @@ export class Scene implements IAnimatable, IClipPlanesHolder, IAssetContainer { */ public onNewMultiMaterialAddedObservable = new Observable(); - /** - * An event triggered when a post process is created - */ - public onNewPostProcessAddedObservable = new Observable(); - /** * An event triggered when a material is removed */ @@ -911,11 +906,26 @@ export class Scene implements IAnimatable, IClipPlanesHolder, IAssetContainer { */ public onFrameGraphRemovedObservable = new Observable(); + /** + * An event triggered when a post process is created + */ + public onNewPostProcessAddedObservable = new Observable(); + /** * An event triggered when a post process is removed */ public onPostProcessRemovedObservable = new Observable(); + /** + * An event triggered when an effect layer is created + */ + public onNewEffectLayerAddedObservable = new Observable(); + + /** + * An event triggered when an effect layer is removed + */ + public onEffectLayerRemovedObservable = new Observable(); + /** * An event triggered when render targets are about to be rendered * Can happen multiple times per frame. @@ -3087,6 +3097,21 @@ export class Scene implements IAnimatable, IClipPlanesHolder, IAssetContainer { return index; } + /** + * Removes the given layer from this scene. + * @param toRemove The layer to remove + * @returns The index of the removed layer + */ + public removeEffectLayer(toRemove: EffectLayer): number { + const index = this.effectLayers.indexOf(toRemove); + if (index !== -1) { + this.effectLayers.splice(index, 1); + } + this.onEffectLayerRemovedObservable.notifyObservers(toRemove); + + return index; + } + /** * Adds the given light to this scene * @param newLight The light to add @@ -3307,6 +3332,20 @@ export class Scene implements IAnimatable, IClipPlanesHolder, IAssetContainer { }); } + /** + * Adds the given effect layer to this scene. + * @param newEffectLayer The effect layer to add + */ + public addEffectLayer(newEffectLayer: EffectLayer): void { + if (this._blockEntityCollection) { + return; + } + this.effectLayers.push(newEffectLayer); + Tools.SetImmediate(() => { + this.onNewEffectLayerAddedObservable.notifyObservers(newEffectLayer); + }); + } + /** * Switch active camera * @param newCamera defines the new active camera diff --git a/packages/dev/inspector-v2/src/inspector.tsx b/packages/dev/inspector-v2/src/inspector.tsx index e75f9dad5b3..cd6e644d757 100644 --- a/packages/dev/inspector-v2/src/inspector.tsx +++ b/packages/dev/inspector-v2/src/inspector.tsx @@ -28,6 +28,7 @@ import { SkeletonPropertiesServiceDefinition } from "./services/panes/properties import { SpritePropertiesServiceDefinition } from "./services/panes/properties/spritePropertiesService"; import { TransformPropertiesServiceDefinition } from "./services/panes/properties/transformPropertiesService"; import { AnimationGroupExplorerServiceDefinition } from "./services/panes/scene/animationGroupExplorerService"; +import { EffectLayerExplorerServiceDefinition } from "./services/panes/scene/effectLayersExplorerService"; import { FrameGraphExplorerServiceDefinition } from "./services/panes/scene/frameGraphExplorerService"; import { GuiExplorerServiceDefinition } from "./services/panes/scene/guiExplorerService"; import { MaterialExplorerServiceDefinition } from "./services/panes/scene/materialExplorerService"; @@ -191,6 +192,7 @@ function _ShowInspector(scene: Nullable, options: Partial = { + friendlyName: "Effect Layer Explorer", + consumes: [SceneExplorerServiceIdentity, SceneContextIdentity], + factory: (sceneExplorerService, sceneContext) => { + const scene = sceneContext.currentScene; + if (!scene) { + return undefined; + } + + const sectionRegistration = sceneExplorerService.addSection({ + displayName: "Effect Layers", + order: DefaultSectionsOrder.EffectLayers, + predicate: (entity) => entity instanceof EffectLayer, + getRootEntities: () => scene.effectLayers, + getEntityDisplayInfo: (effectLayer) => { + const onChangeObservable = new Observable(); + + const nameHookToken = InterceptProperty(effectLayer, "name", { + afterSet: () => { + onChangeObservable.notifyObservers(); + }, + }); + + return { + get name() { + return effectLayer.name; + }, + onChange: onChangeObservable, + dispose: () => { + nameHookToken.dispose(); + onChangeObservable.clear(); + }, + }; + }, + entityIcon: () => , + getEntityAddedObservables: () => [scene.onNewEffectLayerAddedObservable], + getEntityRemovedObservables: () => [scene.onEffectLayerRemovedObservable], + }); + + return { + dispose: () => { + sectionRegistration.dispose(); + }, + }; + }, +};