Parcourir la source

Add name support for inspector + serialization for particles

David Catuhe il y a 5 ans
Parent
commit
1264ab5f8b

+ 2 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/cameras/commonCameraPropertyGridComponent.tsx

@@ -11,6 +11,7 @@ import { LockObject } from "../lockObject";
 import { GlobalState } from '../../../../globalState';
 import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
 import { ButtonLineComponent } from '../../../lines/buttonLineComponent';
+import { TextInputLineComponent } from '../../../lines/textInputLineComponent';
 
 interface ICommonCameraPropertyGridComponentProps {
     globalState: GlobalState;
@@ -41,6 +42,7 @@ export class CommonCameraPropertyGridComponent extends React.Component<ICommonCa
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
                     <TextLineComponent label="ID" value={camera.id} />
+                    <TextInputLineComponent lockObject={this.props.lockObject} label="Name" target={camera} propertyName="name" onPropertyChangedObservable={this.props.onPropertyChangedObservable}/>
                     <TextLineComponent label="Unique ID" value={camera.uniqueId.toString()} />
                     <TextLineComponent label="Class" value={camera.getClassName()} />
                     <FloatLineComponent lockObject={this.props.lockObject} label="Near plane" target={camera} propertyName="minZ" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />

+ 1 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/gui/commonControlPropertyGridComponent.tsx

@@ -73,6 +73,7 @@ export class CommonControlPropertyGridComponent extends React.Component<ICommonC
             <div>
                 <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
                     <TextLineComponent label="Class" value={control.getClassName()} />
+                    <TextInputLineComponent lockObject={this.props.lockObject} label="Name" target={control} propertyName="name" onPropertyChangedObservable={this.props.onPropertyChangedObservable}/>
                     <TextLineComponent label="Unique ID" value={control.uniqueId.toString()} />
                     <SliderLineComponent label="Alpha" target={control} propertyName="alpha" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     {

+ 2 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/lights/commonLightPropertyGridComponent.tsx

@@ -9,6 +9,7 @@ import { LockObject } from "../lockObject";
 import { GlobalState } from '../../../../globalState';
 import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
 import { ButtonLineComponent } from '../../../lines/buttonLineComponent';
+import { TextInputLineComponent } from '../../../lines/textInputLineComponent';
 
 interface ICommonLightPropertyGridComponentProps {
     globalState: GlobalState,
@@ -32,6 +33,7 @@ export class CommonLightPropertyGridComponent extends React.Component<ICommonLig
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
                     <TextLineComponent label="ID" value={light.id} />
+                    <TextInputLineComponent lockObject={this.props.lockObject} label="Name" target={light} propertyName="name" onPropertyChangedObservable={this.props.onPropertyChangedObservable}/>
                     <TextLineComponent label="Unique ID" value={light.uniqueId.toString()} />
                     <TextLineComponent label="Class" value={light.getClassName()} />
                     <FloatLineComponent lockObject={this.props.lockObject} label="Intensity" target={light} propertyName="intensity" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />

+ 2 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/materials/commonMaterialPropertyGridComponent.tsx

@@ -16,6 +16,7 @@ import { LockObject } from "../lockObject";
 import { GlobalState } from '../../../../globalState';
 import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
 import { ButtonLineComponent } from '../../../lines/buttonLineComponent';
+import { TextInputLineComponent } from '../../../lines/textInputLineComponent';
 
 interface ICommonMaterialPropertyGridComponentProps {
     globalState: GlobalState;
@@ -76,6 +77,7 @@ export class CommonMaterialPropertyGridComponent extends React.Component<ICommon
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
                     <TextLineComponent label="ID" value={material.id} />
+                    <TextInputLineComponent lockObject={this.props.lockObject} label="Name" target={material} propertyName="name" onPropertyChangedObservable={this.props.onPropertyChangedObservable}/>
                     <TextLineComponent label="Unique ID" value={material.uniqueId.toString()} />
                     <TextLineComponent label="Class" value={material.getClassName()} />
                     <CheckBoxLineComponent label="Backface culling" target={material} propertyName="backFaceCulling" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />

+ 2 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/meshPropertyGridComponent.tsx

@@ -27,6 +27,7 @@ import { MorphTarget } from 'babylonjs/Morph/morphTarget';
 import { OptionsLineComponent } from '../../../lines/optionsLineComponent';
 import { AbstractMesh } from 'babylonjs/Meshes/abstractMesh';
 import { ButtonLineComponent } from '../../../lines/buttonLineComponent';
+import { TextInputLineComponent } from '../../../lines/textInputLineComponent';
 
 interface IMeshPropertyGridComponentProps {
     globalState: GlobalState;
@@ -307,6 +308,7 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
                     <TextLineComponent label="ID" value={mesh.id} />
+                    <TextInputLineComponent lockObject={this.props.lockObject} label="Name" target={mesh} propertyName="name" onPropertyChangedObservable={this.props.onPropertyChangedObservable}/>
                     <TextLineComponent label="Unique ID" value={mesh.uniqueId.toString()} />
                     <TextLineComponent label="Class" value={mesh.getClassName()} />
                     <TextLineComponent label="Vertices" value={mesh.getTotalVertices().toString()} />

+ 2 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/transformNodePropertyGridComponent.tsx

@@ -13,6 +13,7 @@ import { LockObject } from "../lockObject";
 import { GlobalState } from '../../../../globalState';
 import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
 import { ButtonLineComponent } from '../../../lines/buttonLineComponent';
+import { TextInputLineComponent } from '../../../lines/textInputLineComponent';
 
 interface ITransformNodePropertyGridComponentProps {
     globalState: GlobalState;
@@ -36,6 +37,7 @@ export class TransformNodePropertyGridComponent extends React.Component<ITransfo
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
                     <TextLineComponent label="ID" value={transformNode.id} />
+                    <TextInputLineComponent lockObject={this.props.lockObject} label="Name" target={transformNode} propertyName="name" onPropertyChangedObservable={this.props.onPropertyChangedObservable}/>
                     <TextLineComponent label="Unique ID" value={transformNode.uniqueId.toString()} />
                     <TextLineComponent label="Class" value={transformNode.getClassName()} />                    
                     <CheckBoxLineComponent label="IsEnabled" isSelected={() => transformNode.isEnabled()} onSelect={(value) => transformNode.setEnabled(value)} />

+ 32 - 1
inspector/src/components/actionTabs/tabs/propertyGrids/particleSystems/particleSystemPropertyGridComponent.tsx

@@ -37,6 +37,9 @@ import { MeshEmitterGridComponent } from './meshEmitterGridComponent';
 import { ValueGradientGridComponent, GradientGridMode } from './valueGradientGridComponent';
 import { Color3, Color4 } from 'babylonjs/Maths/math.color';
 import { GPUParticleSystem } from 'babylonjs/Particles/gpuParticleSystem';
+import { Tools } from 'babylonjs/Misc/tools';
+import { FileButtonLineComponent } from '../../../lines/fileButtonLineComponent';
+import { TextInputLineComponent } from '../../../lines/textInputLineComponent';
 
 interface IParticleSystemPropertyGridComponentProps {
     globalState: GlobalState;
@@ -148,6 +151,29 @@ export class ParticleSystemPropertyGridComponent extends React.Component<IPartic
         )
     }
 
+    saveToFile() {        
+        const system = this.props.system;
+        let content = JSON.stringify(system.serialize());
+
+        Tools.Download(new Blob([content]), "particleSystem.json");
+    }
+
+    loadFromFile(file: File) {
+        const system = this.props.system;
+        const scene = system.getScene();
+
+        Tools.ReadFile(file, (data) => {
+            let decoder = new TextDecoder("utf-8");
+            let jsonObject = JSON.parse(decoder.decode(data));
+            
+            system.dispose();            
+            this.props.globalState.onSelectionChangedObservable.notifyObservers(null);
+
+            let newSystem = ParticleSystem.Parse(jsonObject, scene, "");
+            this.props.globalState.onSelectionChangedObservable.notifyObservers(newSystem);
+        }, undefined, true);
+    }
+
     render() {
         const system = this.props.system;
 
@@ -190,6 +216,7 @@ export class ParticleSystemPropertyGridComponent extends React.Component<IPartic
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
                     <TextLineComponent label="ID" value={system.id} />
+                    <TextInputLineComponent lockObject={this.props.lockObject} label="Name" target={system} propertyName="name" onPropertyChangedObservable={this.props.onPropertyChangedObservable}/>
                     <TextLineComponent label="Class" value={system.getClassName()} />  
                     <TextLineComponent label="Capacity" value={system.getCapacity().toString()} />  
                     <TextLineComponent label="Capacity" value={system.getActiveCount().toString()} />  
@@ -201,13 +228,17 @@ export class ParticleSystemPropertyGridComponent extends React.Component<IPartic
                     <CheckBoxLineComponent label="Is local" target={system} propertyName="isLocal" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <SliderLineComponent label="Update speed" target={system} propertyName="updateSpeed" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 </LineContainerComponent>                      
-                <LineContainerComponent globalState={this.props.globalState} title="OPTIONS">
+                <LineContainerComponent globalState={this.props.globalState} title="COMMANDS">
                     {this.renderControls()}
                     <ButtonLineComponent label={"Dispose"} onClick={() => {
                         this.props.globalState.onSelectionChangedObservable.notifyObservers(null);
                         system.dispose();
                     }} />
                 </LineContainerComponent>
+                <LineContainerComponent globalState={this.props.globalState} title="SERIALIZATION">
+                <FileButtonLineComponent label="Load" onClick={(file) => this.loadFromFile(file)} accept=".json" />
+                    <ButtonLineComponent label="Save" onClick={() => this.saveToFile()} />
+                </LineContainerComponent>
                 <LineContainerComponent globalState={this.props.globalState} title="EMITTER">
                 <OptionsLineComponent 
                         label="Emitter" 

+ 2 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/postProcesses/commonPostProcessPropertyGridComponent.tsx

@@ -12,6 +12,7 @@ import { Color3LineComponent } from '../../../lines/color3LineComponent';
 import { SliderLineComponent } from '../../../lines/sliderLineComponent';
 import { GlobalState } from '../../../../globalState';
 import { ButtonLineComponent } from '../../../lines/buttonLineComponent';
+import { TextInputLineComponent } from '../../../lines/textInputLineComponent';
 
 interface ICommonPostProcessPropertyGridComponentProps {
     globalState: GlobalState;
@@ -32,6 +33,7 @@ export class CommonPostProcessPropertyGridComponent extends React.Component<ICom
             <div>
                 <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
                     <TextLineComponent label="Class" value={postProcess.getClassName()} />
+                    <TextInputLineComponent lockObject={this.props.lockObject} label="Name" target={postProcess} propertyName="name" onPropertyChangedObservable={this.props.onPropertyChangedObservable}/>
                     {
                         postProcess.width &&
                         <TextLineComponent label="Width" value={postProcess.width.toString()} />

+ 1 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/postProcesses/commonRenderingPipelinePropertyGridComponent.tsx

@@ -29,6 +29,7 @@ export class CommonRenderingPipelinePropertyGridComponent extends React.Componen
         return (
             <div>
                 <LineContainerComponent globalState={this.props.globalState} title="GENERAL">
+                    <TextLineComponent label="Name" value={renderPipeline.name} />
                     <TextLineComponent label="Class" value={renderPipeline.getClassName()} />
                     {
                         renderPipelineAsAny.samples !== undefined &&

+ 5 - 0
inspector/src/components/globalState.ts

@@ -18,6 +18,7 @@ export class GlobalState {
     public onCodeChangedObservable = new Observable<CodeChangedEvent>();
     public onInspectorClosedObservable = new Observable<Scene>();
     public onTabChangedObservable = new Observable<number>();
+    public onSelectionRenamedObservable = new Observable<void>();
     public onPluginActivatedObserver: Nullable<Observer<ISceneLoaderPlugin | ISceneLoaderPluginAsync>>;
 
     public sceneImportDefaults: { [key: string]: any } = {};
@@ -71,6 +72,10 @@ export class GlobalState {
 
         propertyChangedObservable.add(event => {
             this.recorder.record(event);
+
+            if (event.property === "name") {
+                this.onSelectionRenamedObservable.notifyObservers();
+            }
         });
 
         this.onCodeChangedObservable.add(code => {

+ 5 - 1
inspector/src/components/sceneExplorer/entities/cameraTreeItemComponent.tsx

@@ -47,7 +47,11 @@ export class CameraTreeItemComponent extends React.Component<ICameraTreeItemComp
             if (this.state.isActive && scene.activeCameras.length <= 1 && scene.activeCamera !== camera) {
                 camera.detachControl(scene.getEngine().getRenderingCanvas()!);
             }
-            this.setState({ isActive: scene.activeCamera === camera });
+            let newState =  scene.activeCamera === camera;
+
+            if (newState !== this.state.isActive) {
+                this.setState({ isActive: newState});
+            }
             
         })
     }

+ 9 - 0
inspector/src/components/sceneExplorer/sceneExplorerComponent.tsx

@@ -58,6 +58,7 @@ interface ISceneExplorerComponentProps {
 
 export class SceneExplorerComponent extends React.Component<ISceneExplorerComponentProps, { filter: Nullable<string>, selectedEntity: any, scene: Scene }> {
     private _onSelectionChangeObserver: Nullable<Observer<any>>;
+    private _onSelectionRenamedObserver: Nullable<Observer<void>>;
     private _onNewSceneAddedObserver: Nullable<Observer<Scene>>;
     private sceneExplorerRef: React.RefObject<Resizable>;
 
@@ -91,6 +92,10 @@ export class SceneExplorerComponent extends React.Component<ISceneExplorerCompon
                 this.setState({ selectedEntity: entity });
             }
         });
+
+        this._onSelectionRenamedObserver = this.props.globalState.onSelectionRenamedObservable.add(() => {
+            this.forceUpdate();
+        })
     }
 
     componentWillUnmount() {
@@ -98,6 +103,10 @@ export class SceneExplorerComponent extends React.Component<ISceneExplorerCompon
             this.props.globalState.onSelectionChangedObservable.remove(this._onSelectionChangeObserver);
         }
 
+        if (this._onSelectionRenamedObserver) {
+            this.props.globalState.onSelectionRenamedObservable.remove(this._onSelectionRenamedObserver);
+        }
+
         if (this._onNewSceneAddedObserver) {
             EngineStore.LastCreatedEngine!.onNewSceneAddedObservable.remove(this._onNewSceneAddedObserver);
         }