sebastien 6 gadi atpakaļ
vecāks
revīzija
fd2d82bbed
44 mainītis faili ar 24037 papildinājumiem un 64577 dzēšanām
  1. 23651 23645
      dist/preview release/babylon.d.ts
  2. 1 1
      dist/preview release/babylon.js
  3. 34 0
      dist/preview release/babylon.max.js
  4. 34 0
      dist/preview release/babylon.no-module.max.js
  5. 1 1
      dist/preview release/babylon.worker.js
  6. 34 0
      dist/preview release/es6.js
  7. 1 1
      dist/preview release/gui/babylon.gui.min.js.map
  8. 12 36091
      dist/preview release/inspector/babylon.inspector.bundle.js
  9. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.js.map
  10. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  11. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  12. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  13. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  14. 1 444
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  15. 1 449
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  16. 1 2
      dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js
  17. 1 3868
      dist/preview release/serializers/babylon.glTF2Serializer.min.js
  18. 1 2
      dist/preview release/serializers/babylonjs.serializers.min.js
  19. 2 0
      dist/preview release/what's new.md
  20. 20 0
      inspector/src/components/actionTabs/actionTabs.scss
  21. 16 0
      inspector/src/components/actionTabs/lines/messageLineComponent.tsx
  22. 66 0
      inspector/src/components/actionTabs/tabs/propertyGrids/meshes/axesViewerComponent.tsx
  23. 2 0
      inspector/src/components/actionTabs/tabs/propertyGrids/meshes/meshPropertyGridComponent.tsx
  24. 4 0
      inspector/src/components/actionTabs/tabs/propertyGrids/meshes/transformNodePropertyGridComponent.tsx
  25. 14 6
      inspector/src/components/actionTabs/tabs/tools/gltfComponent.tsx
  26. 28 11
      inspector/src/components/sceneExplorer/sceneExplorer.scss
  27. 27 12
      inspector/src/components/sceneExplorer/treeItemComponent.tsx
  28. 3 2
      inspector/src/components/sceneExplorer/treeItemSelectableComponent.tsx
  29. 16 9
      loaders/src/glTF/2.0/glTFLoader.ts
  30. 3 3
      package.json
  31. 15 0
      src/Debug/axesViewer.ts
  32. 3 0
      src/Engines/engine.ts
  33. 12 0
      src/Gizmos/boundingBoxGizmo.ts
  34. 4 7
      src/Meshes/meshBuilder.ts
  35. 14 1
      src/Particles/baseParticleSystem.ts
  36. 1 1
      src/Particles/particleSystem.ts
  37. 3 5
      tests/modules/tests-karma.js
  38. 1 1
      tests/modules/tests-loader.js
  39. 0 1
      tests/modules/tests.json
  40. 2 2
      tests/modules/typescript-vanilla/src/tests-loader.ts
  41. 2 3
      tests/modules/typescript-webpack/index.ts
  42. 0 3
      tests/modules/typescript-webpack/tsconfig.json
  43. 0 1
      tests/modules/typescript-webpack/webpack.config.js
  44. 1 0
      what's new.md

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 23651 - 23645
dist/preview release/babylon.d.ts


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/babylon.js


+ 34 - 0
dist/preview release/babylon.max.js

@@ -66514,6 +66514,30 @@ var BABYLON;
                 this._zmesh.color = new BABYLON.Color3(0, 0, 1);
                 this.scene = scene;
             }
+            Object.defineProperty(AxesViewer.prototype, "xAxisMesh", {
+                /** Gets the mesh used to render x-axis */
+                get: function () {
+                    return this._xmesh;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(AxesViewer.prototype, "yAxisMesh", {
+                /** Gets the mesh used to render x-axis */
+                get: function () {
+                    return this._ymesh;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(AxesViewer.prototype, "zAxisMesh", {
+                /** Gets the mesh used to render x-axis */
+                get: function () {
+                    return this._zmesh;
+                },
+                enumerable: true,
+                configurable: true
+            });
             /**
              * Force the viewer to update
              * @param position defines the position of the viewer
@@ -104614,6 +104638,16 @@ var BABYLON;
             mesh.position.copyFrom(oldPos);
             // Reverse parenting
             mesh.removeChild(box);
+            // Adjust scale to avoid undefined behavior when adding child
+            if (box.scaling.y === 0) {
+                box.scaling.y = BABYLON.Epsilon;
+            }
+            if (box.scaling.x === 0) {
+                box.scaling.x = BABYLON.Epsilon;
+            }
+            if (box.scaling.z === 0) {
+                box.scaling.z = BABYLON.Epsilon;
+            }
             box.addChild(mesh);
             box.visibility = 0;
             return box;

+ 34 - 0
dist/preview release/babylon.no-module.max.js

@@ -66481,6 +66481,30 @@ var BABYLON;
                 this._zmesh.color = new BABYLON.Color3(0, 0, 1);
                 this.scene = scene;
             }
+            Object.defineProperty(AxesViewer.prototype, "xAxisMesh", {
+                /** Gets the mesh used to render x-axis */
+                get: function () {
+                    return this._xmesh;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(AxesViewer.prototype, "yAxisMesh", {
+                /** Gets the mesh used to render x-axis */
+                get: function () {
+                    return this._ymesh;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(AxesViewer.prototype, "zAxisMesh", {
+                /** Gets the mesh used to render x-axis */
+                get: function () {
+                    return this._zmesh;
+                },
+                enumerable: true,
+                configurable: true
+            });
             /**
              * Force the viewer to update
              * @param position defines the position of the viewer
@@ -104581,6 +104605,16 @@ var BABYLON;
             mesh.position.copyFrom(oldPos);
             // Reverse parenting
             mesh.removeChild(box);
+            // Adjust scale to avoid undefined behavior when adding child
+            if (box.scaling.y === 0) {
+                box.scaling.y = BABYLON.Epsilon;
+            }
+            if (box.scaling.x === 0) {
+                box.scaling.x = BABYLON.Epsilon;
+            }
+            if (box.scaling.z === 0) {
+                box.scaling.z = BABYLON.Epsilon;
+            }
             box.addChild(mesh);
             box.visibility = 0;
             return box;

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/babylon.worker.js


+ 34 - 0
dist/preview release/es6.js

@@ -66481,6 +66481,30 @@ var BABYLON;
                 this._zmesh.color = new BABYLON.Color3(0, 0, 1);
                 this.scene = scene;
             }
+            Object.defineProperty(AxesViewer.prototype, "xAxisMesh", {
+                /** Gets the mesh used to render x-axis */
+                get: function () {
+                    return this._xmesh;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(AxesViewer.prototype, "yAxisMesh", {
+                /** Gets the mesh used to render x-axis */
+                get: function () {
+                    return this._ymesh;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(AxesViewer.prototype, "zAxisMesh", {
+                /** Gets the mesh used to render x-axis */
+                get: function () {
+                    return this._zmesh;
+                },
+                enumerable: true,
+                configurable: true
+            });
             /**
              * Force the viewer to update
              * @param position defines the position of the viewer
@@ -104581,6 +104605,16 @@ var BABYLON;
             mesh.position.copyFrom(oldPos);
             // Reverse parenting
             mesh.removeChild(box);
+            // Adjust scale to avoid undefined behavior when adding child
+            if (box.scaling.y === 0) {
+                box.scaling.y = BABYLON.Epsilon;
+            }
+            if (box.scaling.x === 0) {
+                box.scaling.x = BABYLON.Epsilon;
+            }
+            if (box.scaling.z === 0) {
+                box.scaling.z = BABYLON.Epsilon;
+            }
             box.addChild(mesh);
             box.visibility = 0;
             return box;

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 12 - 36091
dist/preview release/inspector/babylon.inspector.bundle.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.js.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 444
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 449
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 2
dist/preview release/postProcessesLibrary/babylonjs.postProcess.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 3868
dist/preview release/serializers/babylon.glTF2Serializer.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 2
dist/preview release/serializers/babylonjs.serializers.min.js


+ 2 - 0
dist/preview release/what's new.md

@@ -71,6 +71,7 @@
 - Added support for mesh instancing for improved performance when multiple nodes point to the same mesh ([bghgary](https://github.com/bghgary))
 - Create `TransformNode` objects instead of `Mesh` objects for glTF nodes without geometry ([bghgary](https://github.com/bghgary))
 - Added glTF JSON pointers to metadata of nodes, materials, and textures ([bghgary](https://github.com/bghgary))
+- Load KTX textures in the gltf2 loader when textureFormat is set on engine ([TrevorDev](https://github.com/TrevorDev))
 
 ### glTF Serializer
 
@@ -90,6 +91,7 @@
 - VR helper would rotate non vr camera while in VR ([TrevorDev](https://github.com/TrevorDev))
 - PointerDragBahavior using Mesh as base type, causing type-checking problems with AbstractMesh ([Poolminer](https://github.com/Poolminer/))
 - TransformNode lookAt not working in world space when node's parent has rotation ([TrevorDev](https://github.com/TrevorDev))
+- MakeNotPickableAndWrapInBoundingBox had unexpected behavior when input had scaling of 0 on an axis ([TrevorDev](https://github.com/TrevorDev))
 
 ### Core Engine
 - Fixed a bug with `mesh.alwaysSelectAsActiveMesh` preventing layerMask to be taken in account ([Deltakosh](https://github.com/deltakosh))

+ 20 - 0
inspector/src/components/actionTabs/actionTabs.scss

@@ -171,6 +171,26 @@
                     opacity: 0.6;
                 }
 
+                .iconMessageLine {
+                    padding-left: 5px;
+                    height: 30px;
+                    display: grid;
+                    grid-template-columns: 30px 1fr;
+
+                    .icon {
+                        grid-column: 1;
+                        display: grid;
+                        align-items: center;
+                        justify-items: center;
+                    }
+
+                    .value {
+                        grid-column: 2;
+                        display: flex;
+                        align-items: center;
+                    }
+                }
+
                 .textLine {
                     padding-left: 5px;
                     height: 30px;

+ 16 - 0
inspector/src/components/actionTabs/lines/messageLineComponent.tsx

@@ -1,8 +1,11 @@
 import * as React from "react";
+import { IconProp } from "@fortawesome/fontawesome-svg-core";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 
 interface IMessageLineComponentProps {
     text: string,
     color?: string,
+    icon?: IconProp
 }
 
 export class MessageLineComponent extends React.Component<IMessageLineComponentProps> {
@@ -11,6 +14,19 @@ export class MessageLineComponent extends React.Component<IMessageLineComponentP
     }
 
     render() {
+        if (this.props.icon) {
+            return (
+                <div className="iconMessageLine">
+                    <div className="icon" style={{ color: this.props.color ? this.props.color : "" }}>
+                        <FontAwesomeIcon icon={this.props.icon}/>
+                    </div>
+                    <div className="value" title={this.props.text}>
+                        {this.props.text}
+                    </div>
+                </div>
+            );
+        }
+
         return (
             <div className="messageLine">
                 <div className="value" title={this.props.text} style={{ color: this.props.color ? this.props.color : "" }}>

+ 66 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/axesViewerComponent.tsx

@@ -0,0 +1,66 @@
+import * as React from "react";
+import { TransformNode } from "babylonjs";
+import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
+
+interface IAxisViewerComponentProps {
+    node: TransformNode
+}
+
+export class AxesViewerComponent extends React.Component<IAxisViewerComponentProps, { displayAxis: boolean }> {
+    constructor(props: IAxisViewerComponentProps) {
+        super(props);
+        const node = this.props.node;
+
+        if (!node.metadata) {
+            node.metadata = {};
+        }
+
+        this.state = { displayAxis: (node.metadata && node.metadata.axisViewer) ? true : false }
+    }
+
+    displayAxes() {
+        const node = this.props.node;
+        const scene = node.getScene();
+
+        if (node.metadata.axisViewer) {
+            node.metadata.axisViewer.dispose();
+            node.metadata.axisViewer = null;
+
+            scene.onBeforeRenderObservable.remove(node.metadata.onBeforeRenderObserver);
+            node.metadata.onBeforeRenderObserver = null;
+
+            this.setState({ displayAxis: false });
+
+            return;
+        }
+
+        const viewer = new BABYLON.Debug.AxesViewer(scene);
+        node.metadata.axisViewer = viewer;
+        const x = new BABYLON.Vector3(1, 0, 0);
+        const y = new BABYLON.Vector3(0, 1, 0);
+        const z = new BABYLON.Vector3(0, 0, 1);
+
+        viewer.xAxisMesh!.metadata = { hidden: true };
+        viewer.yAxisMesh!.metadata = { hidden: true };
+        viewer.zAxisMesh!.metadata = { hidden: true };
+
+        node.metadata.onBeforeRenderObserver = scene.onBeforeRenderObservable.add(() => {
+            let matrix = node.getWorldMatrix();
+            let extend = BABYLON.Tmp.Vector3[0];
+            const worldExtend = scene.getWorldExtends();
+            worldExtend.max.subtractToRef(worldExtend.min, extend);
+            extend.scaleInPlace(0.5 * 0.5);
+
+            viewer.scaleLines = Math.max(extend.x, extend.y, extend.z) * 2;
+            viewer.update(node.getAbsolutePosition(), BABYLON.Vector3.TransformNormal(x, matrix), BABYLON.Vector3.TransformNormal(y, matrix), BABYLON.Vector3.TransformNormal(z, matrix));
+        });
+
+        this.setState({ displayAxis: true });
+    }
+
+    render() {
+        return (
+            <CheckBoxLineComponent label="Display axes" isSelected={() => this.state.displayAxis} onSelect={() => this.displayAxes()} />
+        )
+    }
+}

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

@@ -7,6 +7,7 @@ import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
 import { Vector3LineComponent } from "../../../lines/vector3LineComponent";
 import { SliderLineComponent } from "../../../lines/sliderLineComponent";
 import { QuaternionLineComponent } from "../../../lines/quaternionLineComponent";
+import { AxesViewerComponent } from "./axesViewerComponent";
 
 interface IMeshPropertyGridComponentProps {
     mesh: Mesh,
@@ -184,6 +185,7 @@ export class MeshPropertyGridComponent extends React.Component<IMeshPropertyGrid
                         mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind) &&
                         <CheckBoxLineComponent label="Render vertex normals" isSelected={() => renderNormalVectors} onSelect={() => this.renderNormalVectors()} />
                     }
+                    <AxesViewerComponent node={mesh} />
                 </LineContainerComponent>
             </div>
         );

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

@@ -6,6 +6,7 @@ import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent";
 import { Vector3LineComponent } from "../../../lines/vector3LineComponent";
 import { TextLineComponent } from "../../../lines/textLineComponent";
 import { QuaternionLineComponent } from "../../../lines/quaternionLineComponent";
+import { AxesViewerComponent } from "./axesViewerComponent";
 
 interface ITransformNodePropertyGridComponentProps {
     transformNode: TransformNode,
@@ -40,6 +41,9 @@ export class TransformNodePropertyGridComponent extends React.Component<ITransfo
                     }
                     <Vector3LineComponent label="Scaling" target={transformNode} propertyName="scaling" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                 </LineContainerComponent>
+                <LineContainerComponent title="DEBUG" closed={true}>
+                    <AxesViewerComponent node={transformNode} />
+                </LineContainerComponent>
             </div>
         );
     }

+ 14 - 6
inspector/src/components/actionTabs/tabs/tools/gltfComponent.tsx

@@ -6,7 +6,7 @@ import { GlobalState } from "../../../globalState";
 import { FloatLineComponent } from "../../lines/floatLineComponent";
 import { OptionsLineComponent } from "../../lines/optionsLineComponent";
 import { MessageLineComponent } from "../../lines/messageLineComponent";
-import { BooleanLineComponent } from "../../lines/booleanLineComponent";
+import { faCheck, faTimesCircle } from "@fortawesome/free-solid-svg-icons";
 import { TextLineComponent } from "../../lines/textLineComponent";
 
 interface IGLTFComponentProps {
@@ -65,7 +65,7 @@ export class GLTFComponent extends React.Component<IGLTFComponentProps> {
             return `${count} ${singularForm}s`;
         }
 
-        return `No ${singularForm}`;
+        return `${singularForm}`;
     }
 
     renderValidation() {
@@ -74,10 +74,18 @@ export class GLTFComponent extends React.Component<IGLTFComponentProps> {
 
         return (
             <LineContainerComponent title="GLTF VALIDATION" closed={!issues.numErrors && !issues.numWarnings}>
-                <BooleanLineComponent label={this.prepareText("error", issues.numErrors)} value={issues.numErrors === 0} />
-                <BooleanLineComponent label={this.prepareText("warning", issues.numWarnings)} value={issues.numWarnings === 0} />
-                <BooleanLineComponent label={this.prepareText("info", issues.numInfos)} value={issues.numInfos === 0} />
-                <BooleanLineComponent label={this.prepareText("hint", issues.numHints)} value={issues.numHints === 0} />
+                {
+                    issues.numErrors !== 0 &&
+                    <MessageLineComponent text="Your file has some validation issues" icon={faTimesCircle} color="Red"/>
+                }
+                {
+                    issues.numErrors === 0 &&
+                    <MessageLineComponent text="Your file is a valid glTF file" icon={faCheck} color="Green"/>
+                }
+                <TextLineComponent label="Errors" value={issues.numErrors.toString()} />
+                <TextLineComponent label="Warnings" value={issues.numWarnings.toString()} />
+                <TextLineComponent label="Infos" value={issues.numInfos.toString()} />
+                <TextLineComponent label="Hints" value={issues.numHints.toString()} />
                 <TextLineComponent label="More details" value="Click here" onLink={() => this.openValidationDetails()} />
             </LineContainerComponent>
         )

+ 28 - 11
inspector/src/components/sceneExplorer/sceneExplorer.scss

@@ -121,22 +121,39 @@
         -ms-user-select: none;    
         user-select: none;    
         
-        align-self: center;                
-        display: flex;
-        align-items: center;
+        align-self: center;     
+        display: grid;
+        align-items: center;           
 
         &:hover {
             background: #444444;
         }
-        
-        .arrow {
-            margin-left: 0px;
-            color: white;
-            cursor: pointer;
-            display: inline-block;
-            margin-right: 6px;
-            opacity: 0.5;
+
+        .expandableHeader {
+            display: grid;
+            grid-template-columns: 1fr 20px;
+
+            .text {
+                grid-column: 1;
+                display: flex;
+                align-items: center;
+
+                .arrow {
+                    margin-left: 0px;
+                    color: white;
+                    cursor: pointer;
+                    display: inline-block;
+                    margin-right: 6px;
+                    opacity: 0.5;
+                }
+            }
+
+            .expandAll {
+                grid-column: 2;
+            }
         }
+        
+
     }
 
     .icon {

+ 27 - 12
inspector/src/components/sceneExplorer/treeItemComponent.tsx

@@ -1,14 +1,15 @@
 import * as React from "react";
 import { Nullable, Observable, IExplorerExtensibilityGroup } from "babylonjs";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faPlus, faMinus, faBan } from '@fortawesome/free-solid-svg-icons';
+import { faPlus, faMinus, faBan, faExpandArrowsAlt, faCompress } from '@fortawesome/free-solid-svg-icons';
 import { TreeItemSelectableComponent } from "./treeItemSelectableComponent";
 import { Tools } from "../../tools";
 
 interface ITreeItemExpandableHeaderComponentProps {
     isExpanded: boolean,
     label: string,
-    onClick: () => void
+    onClick: () => void,
+    onExpandAll: (expand: boolean) => void
 }
 
 class TreeItemExpandableHeaderComponent extends React.Component<ITreeItemExpandableHeaderComponentProps> {
@@ -16,14 +17,24 @@ class TreeItemExpandableHeaderComponent extends React.Component<ITreeItemExpanda
         super(props);
     }
 
+    expandAll() {
+        this.props.onExpandAll(!this.props.isExpanded);
+    }
+
     render() {
         const chevron = this.props.isExpanded ? <FontAwesomeIcon icon={faMinus} /> : <FontAwesomeIcon icon={faPlus} />
+        const expandAll = this.props.isExpanded ? <FontAwesomeIcon icon={faCompress} /> : <FontAwesomeIcon icon={faExpandArrowsAlt} />
 
         return (
-            <div>
-                <span className="arrow icon" onClick={() => this.props.onClick()}>
-                    {chevron}
-                </span> {this.props.label}
+            <div className="expandableHeader">
+                <div className="text">
+                    <span className="arrow icon" onClick={() => this.props.onClick()}>
+                        {chevron}
+                    </span> {this.props.label}
+                </div>
+                <div className="expandAll icon" onClick={() => this.expandAll()} title={this.props.isExpanded ? "Collapse all" : "Expand all"}>
+                    {expandAll}
+                </div>
             </div>
         )
     }
@@ -61,15 +72,15 @@ export interface ITreeItemComponentProps {
 }
 
 
-export class TreeItemComponent extends React.Component<ITreeItemComponentProps, { isExpanded: boolean }> {
+export class TreeItemComponent extends React.Component<ITreeItemComponentProps, { isExpanded: boolean, mustExpand: boolean }> {
     constructor(props: ITreeItemComponentProps) {
         super(props);
 
-        this.state = { isExpanded: false };
+        this.state = { isExpanded: false, mustExpand: false };
     }
 
     switchExpandedState(): void {
-        this.setState({ isExpanded: !this.state.isExpanded });
+        this.setState({ isExpanded: !this.state.isExpanded, mustExpand: false });
     }
 
     shouldComponentUpdate(nextProps: ITreeItemComponentProps, nextState: { isExpanded: boolean }) {
@@ -93,6 +104,10 @@ export class TreeItemComponent extends React.Component<ITreeItemComponentProps,
         return true;
     }
 
+    expandAll(expand: boolean) {
+        this.setState({isExpanded: expand, mustExpand: expand});
+    }
+
     render() {
         const items = this.props.items;
 
@@ -121,7 +136,7 @@ export class TreeItemComponent extends React.Component<ITreeItemComponentProps,
         if (!this.state.isExpanded) {
             return (
                 <div className="groupContainer" style={marginStyle}>
-                    <TreeItemExpandableHeaderComponent isExpanded={false} label={this.props.label} onClick={() => this.switchExpandedState()} />
+                    <TreeItemExpandableHeaderComponent isExpanded={false} label={this.props.label} onClick={() => this.switchExpandedState()} onExpandAll={expand => this.expandAll(expand)} />
                 </div >
             )
         }
@@ -131,12 +146,12 @@ export class TreeItemComponent extends React.Component<ITreeItemComponentProps,
         return (
             <div>
                 <div className="groupContainer" style={marginStyle}>
-                    <TreeItemExpandableHeaderComponent isExpanded={this.state.isExpanded} label={this.props.label} onClick={() => this.switchExpandedState()} />
+                    <TreeItemExpandableHeaderComponent isExpanded={this.state.isExpanded} label={this.props.label} onClick={() => this.switchExpandedState()} onExpandAll={expand => this.expandAll(expand)} />
                 </div>
                 {
                     sortedItems.map(item => {
                         return (
-                            <TreeItemSelectableComponent extensibilityGroups={this.props.extensibilityGroups} key={item.uniqueId} offset={this.props.offset + 2} selectedEntity={this.props.selectedEntity} entity={item} onSelectionChangedObservable={this.props.onSelectionChangedObservable} filter={this.props.filter} />
+                            <TreeItemSelectableComponent mustExpand={this.state.mustExpand} extensibilityGroups={this.props.extensibilityGroups} key={item.uniqueId} offset={this.props.offset + 2} selectedEntity={this.props.selectedEntity} entity={item} onSelectionChangedObservable={this.props.onSelectionChangedObservable} filter={this.props.filter} />
                         );
                     })
                 }

+ 3 - 2
inspector/src/components/sceneExplorer/treeItemSelectableComponent.tsx

@@ -9,6 +9,7 @@ import * as React from "react";
 export interface ITreeItemSelectableComponentProps {
     entity: any,
     selectedEntity?: any,
+    mustExpand?: boolean,
     offset: number,
     extensibilityGroups?: IExplorerExtensibilityGroup[],
     onSelectionChangedObservable?: Observable<any>,
@@ -21,7 +22,7 @@ export class TreeItemSelectableComponent extends React.Component<ITreeItemSelect
     constructor(props: ITreeItemSelectableComponentProps) {
         super(props);
 
-        this.state = { isSelected: this.props.entity === this.props.selectedEntity, isExpanded: Tools.LookForItem(this.props.entity, this.props.selectedEntity) };
+        this.state = { isSelected: this.props.entity === this.props.selectedEntity, isExpanded: this.props.mustExpand || Tools.LookForItem(this.props.entity, this.props.selectedEntity) };
     }
 
     switchExpandedState(): void {
@@ -91,7 +92,7 @@ export class TreeItemSelectableComponent extends React.Component<ITreeItemSelect
             children.map(item => {
 
                 return (
-                    <TreeItemSelectableComponent extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.props.selectedEntity} key={item.uniqueId} offset={this.props.offset + 2} entity={item} onSelectionChangedObservable={this.props.onSelectionChangedObservable} filter={this.props.filter} />
+                    <TreeItemSelectableComponent mustExpand={this.props.mustExpand} extensibilityGroups={this.props.extensibilityGroups} selectedEntity={this.props.selectedEntity} key={item.uniqueId} offset={this.props.offset + 2} entity={item} onSelectionChangedObservable={this.props.onSelectionChangedObservable} filter={this.props.filter} />
                 );
             })
         )

+ 16 - 9
loaders/src/glTF/2.0/glTFLoader.ts

@@ -1713,8 +1713,15 @@ import { IGLTFLoader, GLTFFileLoader, GLTFLoaderState, IGLTFLoaderData, GLTFLoad
             const sampler = (texture.sampler == undefined ? GLTFLoader._DefaultSampler : ArrayItem.Get(`${context}/sampler`, this.gltf.samplers, texture.sampler));
             const samplerData = this._loadSampler(`/samplers/${sampler.index}`, sampler);
 
+            const image = ArrayItem.Get(`${context}/source`, this.gltf.images, texture.source);
+            let textureURL: Nullable<string> = null;
+            if (image.uri && !Tools.IsBase64(image.uri) && this.babylonScene.getEngine().textureFormatInUse) {
+                // If an image uri and a texture format is set like (eg. KTX) load from url instead of blob to support texture format and fallback
+                textureURL = this._uniqueRootUrl + image.uri;
+            }
+
             const deferred = new Deferred<void>();
-            const babylonTexture = new Texture(null, this.babylonScene, samplerData.noMipMaps, false, samplerData.samplingMode, () => {
+            const babylonTexture = new Texture(textureURL, this.babylonScene, samplerData.noMipMaps, false, samplerData.samplingMode, () => {
                 if (!this._disposed) {
                     deferred.resolve();
                 }
@@ -1725,16 +1732,16 @@ import { IGLTFLoader, GLTFFileLoader, GLTFLoaderState, IGLTFLoaderData, GLTFLoad
             });
             promises.push(deferred.promise);
 
+            if (!textureURL) {
+                promises.push(this.loadImageAsync(`/images/${image.index}`, image).then((data) => {
+                    const name = image.uri || `${this._fileName}#image${image.index}`;
+                    const dataUrl = `data:${this._uniqueRootUrl}${name}`;
+                    babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
+                }));
+            }
+
             babylonTexture.wrapU = samplerData.wrapU;
             babylonTexture.wrapV = samplerData.wrapV;
-
-            const image = ArrayItem.Get(`${context}/source`, this.gltf.images, texture.source);
-            promises.push(this.loadImageAsync(`/images/${image.index}`, image).then((data) => {
-                const name = image.uri || `${this._fileName}#image${image.index}`;
-                const dataUrl = `data:${this._uniqueRootUrl}${name}`;
-                babylonTexture.updateURL(dataUrl, new Blob([data], { type: image.mimeType }));
-            }));
-
             assign(babylonTexture);
 
             this.logClose();

+ 3 - 3
package.json

@@ -98,12 +98,12 @@
         "@fortawesome/free-regular-svg-icons": "~5.4.1",
         "@fortawesome/free-solid-svg-icons": "~5.4.1",
         "@fortawesome/react-fontawesome": "~0.1.3",
-        "@types/react": "~16.4.18",
+        "@types/react": "~16.7.3",
         "@types/react-dom": "~16.0.9",
         "file-loader": "~2.0.0",
         "re-resizable": "~4.9.1",
-        "react": "~16.5.2",
-        "react-dom": "~16.5.2",
+        "react": "~16.6.3",
+        "react-dom": "~16.6.3",
         "split.js": "^1.5.9"
     }
 }

+ 15 - 0
src/Debug/axesViewer.ts

@@ -26,6 +26,21 @@ import { LinesMesh } from "Meshes/linesMesh";
          */
         public scaleLines = 1;
 
+        /** Gets the mesh used to render x-axis */
+        public get xAxisMesh(): Nullable<LinesMesh> {
+            return this._xmesh;
+        }
+
+        /** Gets the mesh used to render x-axis */
+        public get yAxisMesh(): Nullable<LinesMesh> {
+            return this._ymesh;
+        }
+
+        /** Gets the mesh used to render x-axis */
+        public get zAxisMesh(): Nullable<LinesMesh> {
+            return this._zmesh;
+        }
+
         /**
          * Creates a new AxesViewer
          * @param scene defines the hosting scene

+ 3 - 0
src/Engines/engine.ts

@@ -4340,6 +4340,7 @@ declare type RenderTargetTexture = import("Materials/Textures/renderTargetTextur
                         excludeLoaders.push(loader);
                         Logger.Warn((loader.constructor as any).name + " failed when trying to load " + texture.url + ", falling back to the next supported loader");
                         this.createTexture(urlArg, noMipmap, invertY, scene, samplingMode, null, onError, buffer, texture, undefined, undefined, excludeLoaders);
+                        return;
                     }
                 }
 
@@ -4349,6 +4350,7 @@ declare type RenderTargetTexture = import("Materials/Textures/renderTargetTextur
                     }
                     if (Tools.UseFallbackTexture) {
                         this.createTexture(Tools.fallbackTexture, noMipmap, invertY, scene, samplingMode, null, onError, buffer, texture);
+                        return;
                     }
                 }
 
@@ -5749,6 +5751,7 @@ declare type RenderTargetTexture = import("Materials/Textures/renderTargetTextur
                     if (fallbackUrl) {
                         excludeLoaders.push(loader);
                         this.createCubeTexture(fallbackUrl, scene, files, noMipmap, onLoad, onError, format, extension, createPolynomials, lodScale, lodOffset, texture, excludeLoaders);
+                        return;
                     }
                 }
 

+ 12 - 0
src/Gizmos/boundingBoxGizmo.ts

@@ -520,6 +520,18 @@ import { StandardMaterial } from "Materials/standardMaterial";
 
             // Reverse parenting
             mesh.removeChild(box);
+
+            // Adjust scale to avoid undefined behavior when adding child
+            if (box.scaling.y === 0) {
+                box.scaling.y = BABYLON.Epsilon;
+            }
+            if (box.scaling.x === 0) {
+                box.scaling.x = BABYLON.Epsilon;
+            }
+            if (box.scaling.z === 0) {
+                box.scaling.z = BABYLON.Epsilon;
+            }
+
             box.addChild(mesh);
             box.visibility = 0;
             return box;

+ 4 - 7
src/Meshes/meshBuilder.ts

@@ -974,14 +974,11 @@ Mesh.CreateDecal = (name: string, sourceMesh: AbstractMesh, position: Vector3, n
             vertexData.applyToMesh(plane, options.updatable);
 
             if (options.sourcePlane) {
-                plane.translate(options.sourcePlane.normal, options.sourcePlane.d);
+                plane.translate(options.sourcePlane.normal, -options.sourcePlane.d);
 
-                var product = Math.acos(Vector3.Dot(options.sourcePlane.normal, Axis.Z));
-                var vectorProduct = Vector3.Cross(Axis.Z, options.sourcePlane.normal);
-
-                if (vectorProduct.lengthSquared() > Epsilon) {
-                    plane.rotate(vectorProduct, product);
-                }
+                const dot = BABYLON.Vector3.Dot(plane.position, options.sourcePlane.normal);
+                const flip = dot >= 0;
+                plane.lookAt(BABYLON.Vector3.Zero(), 0, flip ? Math.PI : 0, 0);
             }
 
             return plane;

+ 14 - 1
src/Particles/baseParticleSystem.ts

@@ -175,10 +175,23 @@ import { Constants } from "Engines/constants";
          */
         public preventAutoStart: boolean = false;
 
+        private _noiseTexture: Nullable<ProceduralTexture>;
+
         /**
          * Gets or sets a texture used to add random noise to particle positions
          */
-        public noiseTexture: Nullable<ProceduralTexture>;
+        public get noiseTexture(): Nullable<ProceduralTexture> {
+            return this._noiseTexture;
+        }
+
+        public set noiseTexture(value : Nullable<ProceduralTexture>) {
+            if (this._noiseTexture === value) {
+                return;
+            }
+
+            this._noiseTexture = value;
+            this._reset();
+        }
 
         /** Gets or sets the strength to apply to the noise value (default is (10, 10, 10)) */
         public noiseStrength = new Vector3(10, 10, 10);

+ 1 - 1
src/Particles/particleSystem.ts

@@ -336,7 +336,7 @@ import "Shaders/particles.vertex";
                     particle.position.addInPlace(this._scaledDirection);
 
                     // Noise
-                    if (noiseTextureData && noiseTextureSize) {
+                    if (noiseTextureData && noiseTextureSize && particle._randomNoiseCoordinates1) {
                         let fetchedColorR = this._fetchR(particle._randomNoiseCoordinates1.x, particle._randomNoiseCoordinates1.y, noiseTextureSize.width, noiseTextureSize.height, noiseTextureData);
                         let fetchedColorG = this._fetchR(particle._randomNoiseCoordinates1.z, particle._randomNoiseCoordinates2.x, noiseTextureSize.width, noiseTextureSize.height, noiseTextureData);
                         let fetchedColorB = this._fetchR(particle._randomNoiseCoordinates2.y, particle._randomNoiseCoordinates2.z, noiseTextureSize.width, noiseTextureSize.height, noiseTextureData);

+ 3 - 5
tests/modules/tests-karma.js

@@ -7,11 +7,9 @@ function runTests(testType, BABYLON, GUI, INSPECTOR) {
     describe(testType + ' module tests', function () {
 
         it("should have the dependencies loaded", function () {
-            assert.isDefined(BABYLON, "BABYLON should be defined");
-            assert.isDefined(GUI, "GUI should be defined");
-            assert.isDefined(INSPECTOR, "INSPECTOR should be defined");
-            // GLTF2 has migrated to BABYLON
-            // assert.isDefined(BABYLON.GLTF2, "BABYLON.GLTF2 should be defined");
+            assert.isDefined(BABYLON);
+            assert.isDefined(GUI);
+            assert.isDefined(BABYLON.GLTF2);
         })
 
         var subject;

+ 1 - 1
tests/modules/tests-loader.js

@@ -1,4 +1,4 @@
 /// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 /// <reference path="../../../../dist/preview release/gui/babylon.gui.d.ts"/>
 // an error in typescript prevents us from using types instead of path
-runTests("typescript-vanilla", BABYLON, BABYLON.GUI, window.INSPECTOR);
+runTests("typescript-vanilla", BABYLON, BABYLON.GUI);

+ 0 - 1
tests/modules/tests.json

@@ -12,7 +12,6 @@
             "dependencies": [
                 "babylon.js",
                 "gui/babylon.gui.min.js",
-                "inspector/babylon.inspector.bundle.js",
                 "loaders/babylonjs.loaders.min.js"
             ]
         }

+ 2 - 2
tests/modules/typescript-vanilla/src/tests-loader.ts

@@ -3,6 +3,6 @@
 // an error in typescript prevents us from using types instead of path
 
 
-declare function runTests(name: string, babylon: any, gui: any, inspector: any);
+declare function runTests(name: string, babylon: any, gui: any);
 
-runTests("typescript-vanilla", BABYLON, BABYLON.GUI, (<any>window).INSPECTOR);
+runTests("typescript-vanilla", BABYLON, BABYLON.GUI);

+ 2 - 3
tests/modules/typescript-webpack/index.ts

@@ -1,12 +1,11 @@
 import * as BABYLON from "babylonjs";
 import * as GUI from "babylonjs-gui";
-import * as INSPECTOR from "babylonjs-inspector";
 
 import "babylonjs-loaders";
 import "babylonjs-serializers";
 // an error in typescript prevents us from using types instead of path
 
 
-declare function runTests(name: string, babylon: any, gui: any, inspector: any);
+declare function runTests(name: string, babylon: any, gui: any);
 
-runTests("typescript-vanilla", BABYLON, GUI, INSPECTOR);
+runTests("typescript-vanilla", BABYLON, GUI);

+ 0 - 3
tests/modules/typescript-webpack/tsconfig.json

@@ -24,9 +24,6 @@
             "babylonjs-gui": [
                 "../../../dist/preview release/gui/babylon.gui.module.d.ts"
             ],
-            "babylonjs-inspector": [
-                "../../../dist/preview release/inspector/babylon.inspector.module.d.ts"
-            ],
             "babylonjs-loaders": [
                 "../../../dist/preview release/loaders/babylonjs.loaders.module.d.ts"
             ],

+ 0 - 1
tests/modules/typescript-webpack/webpack.config.js

@@ -11,7 +11,6 @@ module.exports = {
         alias: {
             "babylonjs": __dirname + '/../../../dist/preview release/babylon.max.js',
             "babylonjs-gui": __dirname + '/../../../dist/preview release/gui/babylon.gui.js',
-            "babylonjs-inspector": __dirname + '/../../../dist/preview release/inspector/babylon.inspector.bundle.js',
             "babylonjs-loaders": __dirname + '/../../../dist/preview release/loaders/babylonjs.loaders.js',
             "babylonjs-serializers": __dirname + '/../../../dist/preview release/serializers/babylonjs.serializers.js',
         }

+ 1 - 0
what's new.md

@@ -204,6 +204,7 @@
 - Spring Joint could not be removed ([TrevorDev](https://github.com/TrevorDev))
 - Sometimes duplicate controller models are loaded in VR ([TrevorDev](https://github.com/TrevorDev))
 - Particle emit rate and start size over time do not reset on every particle system start ([TrevorDev](https://github.com/TrevorDev))
+- Fix position and rotation of plane mesh created by MeshBuilder.CreatePlane when specifying a source plane ([sable](https://github.com/thscott))
 
 ### Core Engine