David Catuhe 6 лет назад
Родитель
Сommit
e60e6efeed

+ 25 - 23
gui/src/2D/controls/inputText.ts

@@ -268,10 +268,12 @@ export class InputText extends Control implements IFocusableControl {
     }
 
     public set text(value: string) {
-        if (this._text === value) {
+        let valueAsString = value.toString(); // Forcing convertion
+
+        if (this._text === valueAsString) {
             return;
         }
-        this._text = value;
+        this._text = valueAsString;
         this._markAsDirty();
 
         this.onTextChangedObservable.notifyObservers(this);
@@ -352,21 +354,21 @@ export class InputText extends Control implements IFocusableControl {
 
         this._onClipboardObserver = this._host.onClipboardObservable.add((clipboardInfo) => {
             // process clipboard event, can be configured.
-             switch (clipboardInfo.type){
-                 case ClipboardEventTypes.COPY:
-                         this._onCopyText(clipboardInfo.event);
-                         this.onTextCopyObservable.notifyObservers(this);
-                         break;
-                 case ClipboardEventTypes.CUT:
-                         this._onCutText(clipboardInfo.event);
-                         this.onTextCutObservable.notifyObservers(this);
-                         break;
-                 case ClipboardEventTypes.PASTE:
-                         this._onPasteText(clipboardInfo.event);
-                         this.onTextPasteObservable.notifyObservers(this);
-                         break;
-                 default: return;
-              }
+            switch (clipboardInfo.type) {
+                case ClipboardEventTypes.COPY:
+                    this._onCopyText(clipboardInfo.event);
+                    this.onTextCopyObservable.notifyObservers(this);
+                    break;
+                case ClipboardEventTypes.CUT:
+                    this._onCutText(clipboardInfo.event);
+                    this.onTextCutObservable.notifyObservers(this);
+                    break;
+                case ClipboardEventTypes.PASTE:
+                    this._onPasteText(clipboardInfo.event);
+                    this.onTextPasteObservable.notifyObservers(this);
+                    break;
+                default: return;
+            }
         });
 
         let scene = this._host.getScene();
@@ -433,7 +435,7 @@ export class InputText extends Control implements IFocusableControl {
                     if (this._isTextHighlightOn) {
                         this.text = this._text.slice(0, this._startHighlightIndex) + this._text.slice(this._endHighlightIndex);
                         this._isTextHighlightOn = false;
-                        this._cursorOffset =  this.text.length - this._startHighlightIndex;
+                        this._cursorOffset = this.text.length - this._startHighlightIndex;
                         this._blinkIsEven = false;
                         if (evt) {
                             evt.preventDefault();
@@ -468,7 +470,7 @@ export class InputText extends Control implements IFocusableControl {
                     }
                     return;
                 }
-                if (this._text && this._text.length > 0  && this._cursorOffset > 0) {
+                if (this._text && this._text.length > 0 && this._cursorOffset > 0) {
                     let deletePosition = this._text.length - this._cursorOffset;
                     this.text = this._text.slice(0, deletePosition) + this._text.slice(deletePosition + 1);
                     this._cursorOffset--;
@@ -561,7 +563,7 @@ export class InputText extends Control implements IFocusableControl {
         this._endHighlightIndex = this._startHighlightIndex;
         for (let rWord = /\w+/g, left = 1, right = 1; this._startHighlightIndex > 0 && this._endHighlightIndex < this._text.length && (left || right);) {
             right = (this._text[this._endHighlightIndex].search(rWord) !== -1) ? ++this._endHighlightIndex : 0;
-            left =  (this._text[this._startHighlightIndex - 1 ].search(rWord) !== -1) ? --this._startHighlightIndex : 0;
+            left = (this._text[this._startHighlightIndex - 1].search(rWord) !== -1) ? --this._startHighlightIndex : 0;
         }
         this.onTextHighlightObservable.notifyObservers(this);
         this._isTextHighlightOn = true;
@@ -598,7 +600,7 @@ export class InputText extends Control implements IFocusableControl {
         try {
             ev.clipboardData.setData("text/plain", this._highlightedText);
         }
-        catch {} //pass
+        catch { } //pass
         this._host.clipboardData = this._highlightedText;
     }
     /** @hidden */
@@ -648,7 +650,7 @@ export class InputText extends Control implements IFocusableControl {
             // Background
             if (this._isFocused) {
                 if (this._focusedBackground) {
-                    context.fillStyle = this._isEnabled ?  this._focusedBackground : this._disabledColor;
+                    context.fillStyle = this._isEnabled ? this._focusedBackground : this._disabledColor;
 
                     context.fillRect(this._currentMeasure.left, this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
                 }
@@ -760,7 +762,7 @@ export class InputText extends Control implements IFocusableControl {
                     this._markAsDirty();
                 }, 500);
 
-                 //show the highlighted text
+                //show the highlighted text
                 if (this._isTextHighlightOn) {
                     clearTimeout(this._blinkTimeout);
                     let highlightCursorOffsetWidth = context.measureText(this.text.substring(this._startHighlightIndex)).width;

+ 27 - 17
inspector/src/Inspector.ts

@@ -6,6 +6,7 @@ import { SceneExplorerComponent } from "./components/sceneExplorer/sceneExplorer
 import { Scene, Observable, Observer, Nullable } from "babylonjs";
 import { EmbedHostComponent } from "./components/embedHost/embedHostComponent";
 import { PropertyChangedEvent } from "./components/propertyChangedEvent";
+import { GlobalState } from "./components/globalState";
 
 export interface IExtensibilityOption {
     label: string;
@@ -54,6 +55,7 @@ export class Inspector {
 
     public static OnSelectionChangeObservable = new BABYLON.Observable<string>();
     public static OnPropertyChangedObservable = new BABYLON.Observable<PropertyChangedEvent>();
+    private static _GlobalState = new GlobalState();
 
     private static _CopyStyles(sourceDoc: HTMLDocument, targetDoc: HTMLDocument) {
         for (var index = 0; index < sourceDoc.styleSheets.length; index++) {
@@ -77,7 +79,7 @@ export class Inspector {
         }
     }
 
-    private static _CreateSceneExplorer(scene: Scene, options: IInternalInspectorOptions, parentControlExplorer: Nullable<HTMLElement>, onSelectionChangeObservable: Observable<string>) {
+    private static _CreateSceneExplorer(scene: Scene, options: IInternalInspectorOptions, parentControlExplorer: Nullable<HTMLElement>) {
         // Duplicating the options as they can be different for each pane
         if (options.original) {
             options = {
@@ -99,7 +101,7 @@ export class Inspector {
                 this._SceneExplorerHost = parentControlExplorer.ownerDocument!.createElement("div");
 
                 this._SceneExplorerHost.id = "scene-explorer-host";
-                this._SceneExplorerHost.style.width = options.explorerWidth || "300px";
+                this._SceneExplorerHost.style.width = options.explorerWidth || "auto";
 
                 parentControlExplorer.appendChild(this._SceneExplorerHost);
 
@@ -120,7 +122,7 @@ export class Inspector {
         if (this._SceneExplorerHost) {
             Inspector._OpenedPane++;
             const sceneExplorerElement = React.createElement(SceneExplorerComponent, {
-                scene, onSelectionChangeObservable: onSelectionChangeObservable,
+                scene, globalState: this._GlobalState,
                 extensibilityGroups: options.explorerExtensibility,
                 noExpand: !options.enablePopup, popupMode: options.popup, onPopup: () => {
                     ReactDOM.unmountComponentAtNode(this._SceneExplorerHost!);
@@ -153,7 +155,7 @@ export class Inspector {
         }
     }
 
-    private static _CreateActionTabs(scene: Scene, options: IInternalInspectorOptions, parentControlActions: Nullable<HTMLElement>, onSelectionChangeObservable: Observable<string>) {
+    private static _CreateActionTabs(scene: Scene, options: IInternalInspectorOptions, parentControlActions: Nullable<HTMLElement>) {
 
         if (!options.actionTabsRoot || options.popup) {
             // Prepare the inspector host
@@ -161,7 +163,7 @@ export class Inspector {
                 const host = parentControlActions.ownerDocument!.createElement("div");
 
                 host.id = "inspector-host";
-                host.style.width = options.inspectorWidth || "300px";
+                host.style.width = options.inspectorWidth || "auto";
 
                 parentControlActions.appendChild(host);
 
@@ -183,7 +185,7 @@ export class Inspector {
         if (this._ActionTabsHost) {
             Inspector._OpenedPane++;
             const actionTabsElement = React.createElement(ActionTabsComponent, {
-                onSelectionChangeObservable: onSelectionChangeObservable, scene: scene, noExpand: !options.enablePopup, popupMode: options.popup, onPopup: () => {
+                globalState: this._GlobalState, scene: scene, noExpand: !options.enablePopup, popupMode: options.popup, onPopup: () => {
                     ReactDOM.unmountComponentAtNode(this._ActionTabsHost!);
 
                     if (options.popup) {
@@ -202,13 +204,13 @@ export class Inspector {
 
                     if (this._ActionTabsHost && this._ActionTabsHost.parentElement) {
                         this._ActionTabsHost.parentElement.removeChild(this._ActionTabsHost);
-                    }                    
+                    }
 
                     if (options.popup) {
                         this._ActionTabsWindow.close();
                     }
 
-                }, onPropertyChangedObservable: Inspector.OnPropertyChangedObservable
+                }
             });
             ReactDOM.render(actionTabsElement, this._ActionTabsHost);
         }
@@ -243,7 +245,7 @@ export class Inspector {
 
         if (this._EmbedHost) {
             const embedHostElement = React.createElement(EmbedHostComponent, {
-                onSelectionChangeObservable: onSelectionChangeObservable, scene: scene, popupMode: options.popup, onPopup: () => {
+                globalState: this._GlobalState, scene: scene, popupMode: options.popup, onPopup: () => {
                     ReactDOM.unmountComponentAtNode(this._EmbedHost!);
 
                     if (options.popup) {
@@ -264,7 +266,7 @@ export class Inspector {
 
                     if (this._EmbedHost && this._EmbedHost.parentElement) {
                         this._EmbedHost.parentElement.removeChild(this._EmbedHost);
-                    }    
+                    }
 
                     if (options.popup) {
                         this._EmbedHostWindow.close();
@@ -321,7 +323,6 @@ export class Inspector {
     }
 
     public static Show(scene: Scene, userOptions: Partial<IInspectorOptions>) {
-
         const options: IInternalInspectorOptions = {
             original: true,
             popup: false,
@@ -334,6 +335,15 @@ export class Inspector {
             ...userOptions
         };
 
+        // Prepare state
+        if (!this._GlobalState.onPropertyChangedObservable) {
+            this._GlobalState.onPropertyChangedObservable = this.OnPropertyChangedObservable;
+        }
+        if (!this._GlobalState.onSelectionChangeObservable) {
+            this._GlobalState.onSelectionChangeObservable = this.OnSelectionChangeObservable;
+        }
+
+        // Make sure it is not already opened
         if (this.IsVisible && options.original) {
             this.Hide();
         }
@@ -390,13 +400,13 @@ export class Inspector {
                 if (this._SceneExplorerHost) {
                     this._SceneExplorerHost.style.width = "0";
                 }
-                this._CreateSceneExplorer(scene, options, this._CreatePopup("SCENE EXPLORER", "_SceneExplorerWindow"), Inspector.OnSelectionChangeObservable);
+                this._CreateSceneExplorer(scene, options, this._CreatePopup("SCENE EXPLORER", "_SceneExplorerWindow"));
             }
             if (options.showInspector) {
                 if (this._ActionTabsHost) {
                     this._ActionTabsHost.style.width = "0";
                 }
-                this._CreateActionTabs(scene, options, this._CreatePopup("INSPECTOR", "_ActionTabsWindow"), Inspector.OnSelectionChangeObservable);
+                this._CreateActionTabs(scene, options, this._CreatePopup("INSPECTOR", "_ActionTabsWindow"));
             }
         } else {
             let parentControl = (options.actionTabsRoot ? options.actionTabsRoot.parentElement : canvas!.parentElement) as HTMLElement;
@@ -442,7 +452,7 @@ export class Inspector {
                     options.sceneExplorerRoot.style.width = "auto";
                 }
 
-                this._CreateSceneExplorer(scene, options, parentControl, Inspector.OnSelectionChangeObservable);
+                this._CreateSceneExplorer(scene, options, parentControl);
             }
 
             if (options.showInspector) {
@@ -450,7 +460,7 @@ export class Inspector {
                     options.actionTabsRoot.style.width = "auto";
                 }
 
-                this._CreateActionTabs(scene, options, parentControl, Inspector.OnSelectionChangeObservable);
+                this._CreateActionTabs(scene, options, parentControl);
             }
         }
     }
@@ -481,7 +491,7 @@ export class Inspector {
             if (this._SceneExplorerHost.parentElement) {
                 this._SceneExplorerHost.parentElement.removeChild(this._SceneExplorerHost);
             }
-            
+
             this._SceneExplorerHost = null;
         }
 
@@ -490,7 +500,7 @@ export class Inspector {
 
             if (this._EmbedHost.parentElement) {
                 this._EmbedHost.parentElement.removeChild(this._EmbedHost);
-            }            
+            }
             this._EmbedHost = null;
         }
 

+ 10 - 11
inspector/src/components/actionTabs/actionTabsComponent.tsx

@@ -1,5 +1,5 @@
 import * as React from "react";
-import { Observable, Observer, Scene, Nullable } from "babylonjs";
+import { Observer, Scene, Nullable } from "babylonjs";
 import { TabsComponent } from "./tabsComponent";
 import { faFileAlt, faWrench, faBug, faChartBar } from '@fortawesome/free-solid-svg-icons';
 import { StatisticsTabComponent } from "./tabs/statisticsTabComponent";
@@ -7,21 +7,20 @@ import { DebugTabComponent } from "./tabs/debugTabComponent";
 import Resizable from "re-resizable";
 import { PropertyGridTabComponent } from "./tabs/propertyGridTabComponent";
 import { HeaderComponent } from "../headerComponent";
-import { PropertyChangedEvent } from "../propertyChangedEvent";
 import { ToolsTabComponent } from "./tabs/toolsTabComponent";
+import { GlobalState } from "components/globalState";
 
 require("./actionTabs.scss");
 
 interface IActionTabsComponentProps {
-    onSelectionChangeObservable: Observable<any>,
     scene: Scene,
-    onPropertyChangedObservable?: Observable<PropertyChangedEvent>,
     noCommands?: boolean,
     noHeader?: boolean,
     noExpand?: boolean,
     popupMode?: boolean,
     onPopup?: () => void,
-    onClose?: () => void
+    onClose?: () => void,
+    globalState: GlobalState
 }
 
 export class ActionTabsComponent extends React.Component<IActionTabsComponentProps, { selectedEntity: any, selectedIndex: number }> {
@@ -35,14 +34,14 @@ export class ActionTabsComponent extends React.Component<IActionTabsComponentPro
     }
 
     componentWillMount() {
-        this._onSelectionChangeObserver = this.props.onSelectionChangeObservable.add((entity) => {
+        this._onSelectionChangeObserver = this.props.globalState.onSelectionChangeObservable.add((entity) => {
             this.setState({ selectedEntity: entity, selectedIndex: 0 });
         });
     }
 
     componentWillUnmount() {
         if (this._onSelectionChangeObserver) {
-            this.props.onSelectionChangeObservable.remove(this._onSelectionChangeObserver);
+            this.props.globalState.onSelectionChangeObservable.remove(this._onSelectionChangeObserver);
         }
     }
 
@@ -51,8 +50,8 @@ export class ActionTabsComponent extends React.Component<IActionTabsComponentPro
             <TabsComponent selectedIndex={this.state.selectedIndex} onSelectedIndexChange={(value) => this.setState({ selectedIndex: value })}>
                 <PropertyGridTabComponent
                     title="Properties" icon={faFileAlt} scene={this.props.scene} selectedEntity={this.state.selectedEntity}
-                    onSelectionChangeObservable={this.props.onSelectionChangeObservable}
-                    onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    onSelectionChangeObservable={this.props.globalState.onSelectionChangeObservable}
+                    onPropertyChangedObservable={this.props.globalState.onPropertyChangedObservable} />
                 <DebugTabComponent title="Debug" icon={faBug} scene={this.props.scene} />
                 <StatisticsTabComponent title="Statistics" icon={faChartBar} scene={this.props.scene} />
                 <ToolsTabComponent title="Tools" icon={faWrench} scene={this.props.scene} />
@@ -80,7 +79,7 @@ export class ActionTabsComponent extends React.Component<IActionTabsComponentPro
                 <div id="actionTabs">
                     {
                         !this.props.noHeader &&
-                        <HeaderComponent title="INSPECTOR" handleBack={true} noCommands={this.props.noCommands} onClose={() => this.onClose()} onPopup={() => this.onPopup()} onSelectionChangeObservable={this.props.onSelectionChangeObservable} />
+                        <HeaderComponent title="INSPECTOR" handleBack={true} noCommands={this.props.noCommands} onClose={() => this.onClose()} onPopup={() => this.onPopup()} onSelectionChangeObservable={this.props.globalState.onSelectionChangeObservable} />
                     }
                     {this.renderContent()}
                 </div>
@@ -99,7 +98,7 @@ export class ActionTabsComponent extends React.Component<IActionTabsComponentPro
             <Resizable id="actionTabs" minWidth={300} maxWidth={600} size={{ height: "100%" }} minHeight="100%" enable={{ top: false, right: false, bottom: false, left: true, topRight: false, bottomRight: false, bottomLeft: false, topLeft: false }}>
                 {
                     !this.props.noHeader &&
-                    <HeaderComponent title="INSPECTOR" handleBack={true} noExpand={this.props.noExpand} noCommands={this.props.noCommands} onClose={() => this.onClose()} onPopup={() => this.onPopup()} onSelectionChangeObservable={this.props.onSelectionChangeObservable} />
+                    <HeaderComponent title="INSPECTOR" handleBack={true} noExpand={this.props.noExpand} noCommands={this.props.noCommands} onClose={() => this.onClose()} onPopup={() => this.onPopup()} onSelectionChangeObservable={this.props.globalState.onSelectionChangeObservable} />
                 }
                 {this.renderContent()}
             </Resizable>

+ 7 - 7
inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx

@@ -56,6 +56,13 @@ export class PBRMaterialPropertyGridComponent extends React.Component<IPBRMateri
                     <Color3LineComponent label="Emissive" target={material} propertyName="emissiveColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <Color3LineComponent label="Ambient" target={material} propertyName="ambientColor" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <SliderLineComponent label="Alpha" target={material} propertyName="alpha" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                </LineContainerComponent>
+                {this.renderTextures()}
+                <LineContainerComponent title="LEVELS" closed={true}>
+                    <SliderLineComponent label="Environment intensity" target={material} propertyName="environmentIntensity" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <SliderLineComponent label="Metallic" target={material} propertyName="metallic" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <SliderLineComponent label="Micro-surface" target={material} propertyName="microSurface" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                    <SliderLineComponent label="Specular intensity" target={material} propertyName="specularIntensity" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     {
                         material.bumpTexture &&
                         <SliderLineComponent label="Bump strength" target={material.bumpTexture} propertyName="level" minimum={0} maximum={2} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
@@ -69,13 +76,6 @@ export class PBRMaterialPropertyGridComponent extends React.Component<IPBRMateri
                         <SliderLineComponent label="Reflection strength" target={material.reflectionTexture} propertyName="level" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     }
                 </LineContainerComponent>
-                {this.renderTextures()}
-                <LineContainerComponent title="LEVELS" closed={true}>
-                    <SliderLineComponent label="Environment intensity" target={material} propertyName="environmentIntensity" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    <SliderLineComponent label="Metallic" target={material} propertyName="metallic" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    <SliderLineComponent label="Micro-surface" target={material} propertyName="microSurface" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                    <SliderLineComponent label="Specular intensity" target={material} propertyName="specularIntensity" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
-                </LineContainerComponent>
                 <LineContainerComponent title="RENDERING" closed={true}>
                     <CheckBoxLineComponent label="Alpha from albedo" target={material} propertyName="useAlphaFromAlbedoTexture" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     <CheckBoxLineComponent label="Ambient in grayscale" target={material} propertyName="useAmbientInGrayScale" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />

+ 12 - 9
inspector/src/components/embedHost/embedHostComponent.tsx

@@ -3,15 +3,16 @@ import { HeaderComponent } from "../headerComponent";
 import Resizable from "re-resizable";
 import { SceneExplorerComponent } from "../sceneExplorer/sceneExplorerComponent";
 import { ActionTabsComponent } from "../actionTabs/actionTabsComponent";
-import { Scene, Observable } from "babylonjs";
+import { Scene } from "babylonjs";
+import { GlobalState } from "components/globalState";
 
-const Split = require("react-split"); 
+const Split = require("react-split");
 
 require("./embedHost.scss");
 
 interface IEmbedHostComponentProps {
     scene: Scene,
-    onSelectionChangeObservable: Observable<any>,
+    globalState: GlobalState,
     popupMode: boolean,
     onClose: () => void,
     onPopup: () => void
@@ -31,13 +32,13 @@ export class EmbedHostComponent extends React.Component<IEmbedHostComponentProps
                     <div id="topPart">
                         <SceneExplorerComponent scene={this.props.scene}
                             popupMode={true}
-                            onSelectionChangeObservable={this.props.onSelectionChangeObservable} noHeader={true} />
+                            globalState={this.props.globalState} noHeader={true} />
                     </div>
                     <div id="separator" />
                     <div id="bottomPart" style={{ marginTop: "4px", overflow: "hidden" }}>
                         <ActionTabsComponent scene={this.props.scene}
                             popupMode={true}
-                            onSelectionChangeObservable={this.props.onSelectionChangeObservable} noHeader={true} />
+                            globalState={this.props.globalState} noHeader={true} />
                     </div>
                 </div>
             )
@@ -47,13 +48,15 @@ export class EmbedHostComponent extends React.Component<IEmbedHostComponentProps
             <Split id="split" className="noPopup" direction="vertical" gutterSize={4} minSize={[200, 200]}>
                 <div id="topPart">
                     <SceneExplorerComponent scene={this.props.scene}
+                        globalState={this.props.globalState}
                         popupMode={true}
-                        onSelectionChangeObservable={this.props.onSelectionChangeObservable} noHeader={true} />
+                        noHeader={true} />
                 </div>
                 <div id="bottomPart" style={{ marginTop: "4px", overflow: "hidden" }}>
                     <ActionTabsComponent scene={this.props.scene}
+                        globalState={this.props.globalState}
                         popupMode={true}
-                        onSelectionChangeObservable={this.props.onSelectionChangeObservable} noHeader={true} />
+                        noHeader={true} />
                 </div>
             </Split>
         )
@@ -63,7 +66,7 @@ export class EmbedHostComponent extends React.Component<IEmbedHostComponentProps
         if (this.props.popupMode) {
             return (
                 <div id="embed">
-                    <HeaderComponent title="INSPECTOR" handleBack={true} onClose={() => this.props.onClose()} onPopup={() => this.props.onPopup()} onSelectionChangeObservable={this.props.onSelectionChangeObservable} />
+                    <HeaderComponent title="INSPECTOR" handleBack={true} onClose={() => this.props.onClose()} onPopup={() => this.props.onPopup()} onSelectionChangeObservable={this.props.globalState.onSelectionChangeObservable} />
                     {this.renderContent()}
                 </div>
             );
@@ -79,7 +82,7 @@ export class EmbedHostComponent extends React.Component<IEmbedHostComponentProps
 
         return (
             <Resizable id="embed" minWidth={300} maxWidth={600} size={{ height: "100%" }} minHeight="100%" enable={{ top: false, right: false, bottom: false, left: true, topRight: false, bottomRight: false, bottomLeft: false, topLeft: false }}>
-                <HeaderComponent title="INSPECTOR" handleBack={true} onClose={() => this.props.onClose()} onPopup={() => this.props.onPopup()} onSelectionChangeObservable={this.props.onSelectionChangeObservable} />
+                <HeaderComponent title="INSPECTOR" handleBack={true} onClose={() => this.props.onClose()} onPopup={() => this.props.onPopup()} onSelectionChangeObservable={this.props.globalState.onSelectionChangeObservable} />
                 {this.renderContent()}
             </Resizable>
         );

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

@@ -0,0 +1,7 @@
+import { Observable } from "babylonjs";
+import { PropertyChangedEvent } from "./propertyChangedEvent";
+
+export class GlobalState {
+    public onSelectionChangeObservable: Observable<string>;
+    public onPropertyChangedObservable: Observable<PropertyChangedEvent>;
+}

+ 14 - 11
inspector/src/components/sceneExplorer/sceneExplorerComponent.tsx

@@ -1,11 +1,12 @@
 import * as React from "react";
-import { Scene, Observable, Observer, Nullable } from "babylonjs";
+import { Scene, Observer, Nullable } from "babylonjs";
 import { TreeItemComponent } from "./treeItemComponent";
 import Resizable from "re-resizable";
 import { HeaderComponent } from "../headerComponent";
 import { SceneTreeItemComponent } from "./entities/sceneTreeItemComponent";
 import { Tools } from "../../tools";
 import { IExtensibilityGroup } from "../../inspector";
+import { GlobalState } from "components/globalState";
 
 require("./sceneExplorer.scss");
 
@@ -34,8 +35,10 @@ interface ISceneExplorerComponentProps {
     noHeader?: boolean,
     noExpand?: boolean,
     extensibilityGroups?: IExtensibilityGroup[],
-    onSelectionChangeObservable: Observable<any>, popupMode?: boolean,
-    onPopup?: () => void, onClose?: () => void
+    globalState: GlobalState,
+    popupMode?: boolean,
+    onPopup?: () => void,
+    onClose?: () => void
 }
 
 export class SceneExplorerComponent extends React.Component<ISceneExplorerComponentProps, { filter: Nullable<string>, selectedEntity: any, scene: Scene }> {
@@ -50,7 +53,7 @@ export class SceneExplorerComponent extends React.Component<ISceneExplorerCompon
     }
 
     componentWillMount() {
-        this._onSelectionChangeObserver = this.props.onSelectionChangeObservable.add((entity) => {
+        this._onSelectionChangeObserver = this.props.globalState.onSelectionChangeObservable.add((entity) => {
             if (this.state.selectedEntity !== entity) {
                 this.setState({ selectedEntity: entity });
             }
@@ -59,7 +62,7 @@ export class SceneExplorerComponent extends React.Component<ISceneExplorerCompon
 
     componentWillUnmount() {
         if (this._onSelectionChangeObserver) {
-            this.props.onSelectionChangeObservable.remove(this._onSelectionChangeObserver);
+            this.props.globalState.onSelectionChangeObservable.remove(this._onSelectionChangeObserver);
         }
 
         if (this._onNewSceneAddedObserver) {
@@ -84,13 +87,13 @@ export class SceneExplorerComponent extends React.Component<ISceneExplorerCompon
                 data.found = true;
                 if (!goNext) {
                     if (data.previousOne) {
-                        this.props.onSelectionChangeObservable.notifyObservers(data.previousOne);
+                        this.props.globalState.onSelectionChangeObservable.notifyObservers(data.previousOne);
                     }
                     return true;
                 }
             } else {
                 if (data.found) {
-                    this.props.onSelectionChangeObservable.notifyObservers(item);
+                    this.props.globalState.onSelectionChangeObservable.notifyObservers(item);
                     return true;
                 }
                 data.previousOne = item;
@@ -163,10 +166,10 @@ export class SceneExplorerComponent extends React.Component<ISceneExplorerCompon
         return (
             <div id="tree">
                 <SceneExplorerFilterComponent onFilter={(filter) => this.filterContent(filter)} />
-                <SceneTreeItemComponent extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} scene={scene} onRefresh={() => this.forceUpdate()} onSelectionChangeObservable={this.props.onSelectionChangeObservable} />
-                <TreeItemComponent extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} items={scene.rootNodes} label="Nodes" offset={1} onSelectionChangeObservable={this.props.onSelectionChangeObservable} filter={this.state.filter} />
-                <TreeItemComponent extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} items={scene.materials} label="Materials" offset={1} onSelectionChangeObservable={this.props.onSelectionChangeObservable} filter={this.state.filter} />
-                <TreeItemComponent extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} items={scene.textures} label="Textures" offset={1} onSelectionChangeObservable={this.props.onSelectionChangeObservable} filter={this.state.filter} />
+                <SceneTreeItemComponent extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} scene={scene} onRefresh={() => this.forceUpdate()} onSelectionChangeObservable={this.props.globalState.onSelectionChangeObservable} />
+                <TreeItemComponent extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} items={scene.rootNodes} label="Nodes" offset={1} onSelectionChangeObservable={this.props.globalState.onSelectionChangeObservable} filter={this.state.filter} />
+                <TreeItemComponent extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} items={scene.materials} label="Materials" offset={1} onSelectionChangeObservable={this.props.globalState.onSelectionChangeObservable} filter={this.state.filter} />
+                <TreeItemComponent extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.state.selectedEntity} items={scene.textures} label="Textures" offset={1} onSelectionChangeObservable={this.props.globalState.onSelectionChangeObservable} filter={this.state.filter} />
             </div>
         )
     }

+ 1 - 1
sandbox/index.js

@@ -316,7 +316,7 @@ if (BABYLON.Engine.isSupported()) {
         if (event.keyCode === 32 && event.target.nodeName !== "INPUT") {
             if (footer.style.display === "none") {
                 footer.style.display = "block";
-                canvas.style.height = "calc(100% - 56px)";                
+                canvas.style.height = "calc(100% - 56px)";
                 engine.resize();
             }
             else {

+ 1 - 2
src/Materials/Textures/babylon.baseTexture.ts

@@ -286,8 +286,7 @@ module BABYLON {
         constructor(scene: Nullable<Scene>) {
             this._scene = scene || Engine.LastCreatedScene;
             if (this._scene) {
-                this._scene.textures.push(this);
-                this._scene.onNewTextureAddedObservable.notifyObservers(this);
+                this._scene.addTexture(this);
                 this.uniqueId = this._scene.getUniqueId();
             }
             this._uid = null;

+ 12 - 3
src/Materials/Textures/babylon.cubeTexture.ts

@@ -272,14 +272,23 @@ module BABYLON {
          * @returns a new cube texture
          */
         public clone(): CubeTexture {
-            return SerializationHelper.Clone(() => {
-                let scene = this.getScene();
+            let scene = this.getScene();
+            let uniqueId = 0;
+
+            let newCubeTexture = SerializationHelper.Clone(() => {
 
                 if (!scene) {
                     return this;
                 }
-                return new CubeTexture(this.url, scene, this._extensions, this._noMipmap, this._files);
+                const cubeTexture = new CubeTexture(this.url, scene, this._extensions, this._noMipmap, this._files);
+                uniqueId = cubeTexture.uniqueId;
+
+                return cubeTexture;
             }, this);
+
+            newCubeTexture.uniqueId = uniqueId;
+
+            return newCubeTexture;
         }
     }
 }