Jelajahi Sumber

Merge branch 'master' into msDestiny14/nme

David Catuhe 4 tahun lalu
induk
melakukan
231395fa1d
100 mengubah file dengan 44737 tambahan dan 66785 penghapusan
  1. 1 0
      Playground/src/scss/examples.scss
  2. 53 2
      Tools/Config/config.json
  3. 201 53
      dist/preview release/babylon.d.ts
  4. 2 2
      dist/preview release/babylon.js
  5. 697 331
      dist/preview release/babylon.max.js
  6. 1 1
      dist/preview release/babylon.max.js.map
  7. 410 112
      dist/preview release/babylon.module.d.ts
  8. 290 114
      dist/preview release/documentation.d.ts
  9. 11 0
      dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts
  10. 1 1
      dist/preview release/glTF2Interface/package.json
  11. 43 6
      dist/preview release/gui/babylon.gui.d.ts
  12. 299 112
      dist/preview release/gui/babylon.gui.js
  13. 1 1
      dist/preview release/gui/babylon.gui.js.map
  14. 2 2
      dist/preview release/gui/babylon.gui.min.js
  15. 90 13
      dist/preview release/gui/babylon.gui.module.d.ts
  16. 2 2
      dist/preview release/gui/package.json
  17. 8 8
      dist/preview release/inspector/babylon.inspector.bundle.js
  18. 29903 49406
      dist/preview release/inspector/babylon.inspector.bundle.max.js
  19. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.max.js.map
  20. 2539 2494
      dist/preview release/inspector/babylon.inspector.d.ts
  21. 4663 4573
      dist/preview release/inspector/babylon.inspector.module.d.ts
  22. 7 7
      dist/preview release/inspector/package.json
  23. 1 1
      dist/preview release/loaders/babylon.glTF1FileLoader.js.map
  24. 108 73
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  25. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js.map
  26. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  27. 108 73
      dist/preview release/loaders/babylon.glTFFileLoader.js
  28. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.js.map
  29. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  30. 4 1
      dist/preview release/loaders/babylon.objFileLoader.js
  31. 1 1
      dist/preview release/loaders/babylon.objFileLoader.js.map
  32. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  33. 33 54
      dist/preview release/loaders/babylonjs.loaders.d.ts
  34. 112 74
      dist/preview release/loaders/babylonjs.loaders.js
  35. 1 1
      dist/preview release/loaders/babylonjs.loaders.js.map
  36. 2 2
      dist/preview release/loaders/babylonjs.loaders.min.js
  37. 78 127
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  38. 3 3
      dist/preview release/loaders/package.json
  39. 2 2
      dist/preview release/materialsLibrary/package.json
  40. 72 8
      dist/preview release/nodeEditor/babylon.nodeEditor.d.ts
  41. 7 7
      dist/preview release/nodeEditor/babylon.nodeEditor.js
  42. 541 8459
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js
  43. 1 1
      dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map
  44. 148 16
      dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts
  45. 2 2
      dist/preview release/nodeEditor/package.json
  46. 1 1
      dist/preview release/package.json
  47. 1 1
      dist/preview release/packagesSizeBaseLine.json
  48. 2 2
      dist/preview release/postProcessesLibrary/package.json
  49. 2 2
      dist/preview release/proceduralTexturesLibrary/package.json
  50. 2 1
      dist/preview release/serializers/babylonjs.serializers.d.ts
  51. 6 2
      dist/preview release/serializers/babylonjs.serializers.js
  52. 1 1
      dist/preview release/serializers/babylonjs.serializers.js.map
  53. 1 1
      dist/preview release/serializers/babylonjs.serializers.min.js
  54. 4 2
      dist/preview release/serializers/babylonjs.serializers.module.d.ts
  55. 3 3
      dist/preview release/serializers/package.json
  56. 15 0
      dist/preview release/uiControls/babylon.uiControls.d.ts
  57. 29 0
      dist/preview release/uiControls/babylon.uiControls.js
  58. 2650 0
      dist/preview release/uiControls/babylon.uiControls.max.js
  59. 1 0
      dist/preview release/uiControls/babylon.uiControls.max.js.map
  60. 40 0
      dist/preview release/uiControls/babylon.uiControls.module.d.ts
  61. 35 0
      dist/preview release/uiControls/package.json
  62. 1 0
      dist/preview release/uiControls/readme-es6.md
  63. 1 0
      dist/preview release/uiControls/readme.md
  64. 410 112
      dist/preview release/viewer/babylon.module.d.ts
  65. 74 74
      dist/preview release/viewer/babylon.viewer.js
  66. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  67. 78 127
      dist/preview release/viewer/babylonjs.loaders.module.d.ts
  68. 16 2
      dist/preview release/what's new.md
  69. 37 2
      gui/src/2D/advancedDynamicTexture.ts
  70. 1 0
      gui/src/2D/controls/index.ts
  71. 6 3
      gui/src/2D/controls/inputPassword.ts
  72. 90 77
      gui/src/2D/controls/inputText.ts
  73. 8 1
      gui/src/2D/controls/multiLine.ts
  74. 90 0
      gui/src/2D/controls/textWrapper.ts
  75. 10 9
      gui/src/2D/multiLinePoint.ts
  76. 35 5
      inspector/src/components/actionTabs/actionTabs.scss
  77. 1 1
      inspector/src/components/actionTabs/lines/color3LineComponent.tsx
  78. 19 43
      inspector/src/components/actionTabs/lines/colorPickerComponent.tsx
  79. 21 3
      inspector/src/components/actionTabs/lines/floatLineComponent.tsx
  80. 5 5
      inspector/src/components/actionTabs/lines/quaternionLineComponent.tsx
  81. 12 3
      inspector/src/components/actionTabs/lines/sliderLineComponent.tsx
  82. 3 3
      inspector/src/components/actionTabs/lines/vector3LineComponent.tsx
  83. 1 1
      inspector/src/components/actionTabs/tabs/gradientStepComponent.tsx
  84. 14 14
      inspector/src/components/actionTabs/tabs/propertyGrids/animations/animationPropertyGridComponent.tsx
  85. 14 14
      inspector/src/components/actionTabs/tabs/propertyGrids/animations/targetedAnimationPropertyGridComponent.tsx
  86. 0 85
      inspector/src/components/actionTabs/tabs/propertyGrids/commonPropertyGridComponent.tsx
  87. 1 0
      inspector/src/components/actionTabs/tabs/propertyGrids/lights/commonShadowLightPropertyGridComponent.tsx
  88. 16 4
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/textures/toolBar.tsx
  89. 3 5
      inspector/src/components/actionTabs/tabs/propertyGrids/meshes/meshPropertyGridComponent.tsx
  90. 9 11
      inspector/src/components/actionTabs/tabs/propertyGrids/meshes/transformNodePropertyGridComponent.tsx
  91. 1 1
      inspector/src/components/actionTabs/tabs/propertyGrids/particleSystems/colorGradientStepGridComponent.tsx
  92. 1 1
      inspector/src/components/actionTabs/tabs/tools/gltfComponent.tsx
  93. 53 0
      inspector/src/components/controls/colorPicker/colorComponentEntry.tsx
  94. 181 0
      inspector/src/components/controls/colorPicker/colorPicker.scss
  95. 220 0
      inspector/src/components/controls/colorPicker/colorPicker.tsx
  96. 45 0
      inspector/src/components/controls/colorPicker/hexColor.tsx
  97. 1 0
      inspector/src/components/embedHost/embedHost.scss
  98. 1 1
      inspector/src/components/globalState.ts
  99. 7 7
      loaders/src/OBJ/objFileLoader.ts
  100. 0 0
      loaders/src/glTF/1.0/glTFLoader.ts

+ 1 - 0
Playground/src/scss/examples.scss

@@ -10,6 +10,7 @@
     opacity: 0;
     transition: all 0.2s ease;
     height: calc(100% - 90px);
+    z-index: 10;
 
     &.visible {
         transform: translateX(0);

+ 53 - 2
Tools/Config/config.json

@@ -47,7 +47,8 @@
         "serializers",
         "gui",
         "inspector",
-        "nodeEditor"
+        "nodeEditor",
+        "uiControls"
     ],
     "es6modules": [
         "core",
@@ -59,7 +60,8 @@
         "gui",
         "inspector",
         "viewer",
-        "nodeEditor"
+        "nodeEditor",
+        "uiControls"
     ],
     "apps": [
         "playground",
@@ -641,6 +643,55 @@
             }
         }
     },
+    "uiControls": {
+        "libraries": [
+            {
+                "output": "babylon.uiControls.js",
+                "entry": "./legacy/legacy.ts"
+            }
+        ],
+        "build": {            
+            "ignoreInWorkerMode": true,
+            "ignoreInTestMode": true,
+            "mainFolder": "./uiControls/",
+            "uncheckedLintImports": [
+                "react",
+                "react-dom"
+            ],
+            "umd": {
+                "packageName": "babylonjs-ui-controls",
+                "webpackRoot": "UICONTROLS",
+                "processDeclaration": {
+                    "filename": "babylon.uiControls.module.d.ts",
+                    "moduleName": "UICONTROLS",
+                    "importsToRemove": [],
+                    "classMap": {
+                        "babylonjs": "BABYLON",
+                        "react": "React",
+                        "@babylonjs/core": "BABYLON",
+                        "@fortawesome": false,
+                        "react-contextmenu": false
+                    }
+                }
+            },
+            "es6": {
+                "webpackBuild": true,
+                "buildDependencies": [
+                    "Tools/**/*"
+                ],
+                "packageName": "@babylonjs/ui-controls",
+                "readme": "dist/preview release/uiControls/readme-es6.md",
+                "packagesFiles": [
+                    "babylon.uiControls.max.js",
+                    "babylon.uiControls.max.js.map",
+                    "babylon.uiControls.module.d.ts",
+                    "readme.md"
+                ],
+                "typings": "babylon.uiControls.module.d.ts",
+                "index": "babylon.uiControls.max.js"
+            }
+        }
+    },
     "ktx2Decoder": {
         "tempFileName": "babylon.ktx2Decoder.js",
         "distFile": "/dist/preview release/babylon.ktx2Decoder.js",

File diff ditekan karena terlalu besar
+ 201 - 53
dist/preview release/babylon.d.ts


File diff ditekan karena terlalu besar
+ 2 - 2
dist/preview release/babylon.js


File diff ditekan karena terlalu besar
+ 697 - 331
dist/preview release/babylon.max.js


File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/babylon.max.js.map


File diff ditekan karena terlalu besar
+ 410 - 112
dist/preview release/babylon.module.d.ts


File diff ditekan karena terlalu besar
+ 290 - 114
dist/preview release/documentation.d.ts


+ 11 - 0
dist/preview release/glTF2Interface/babylon.glTF2Interface.d.ts

@@ -1057,6 +1057,17 @@ declare module BABYLON.GLTF2 {
     }
 
     /**
+     * Interfaces from the KHR_materials_translucency extension
+     * !!! Experimental Extension Subject to Changes !!!
+     */
+
+    /** @hidden */
+    interface IKHRMaterialsTranslucency {
+        translucencyFactor?: number;
+        translucencyTexture?: ITextureInfo;
+    }
+
+    /**
      * Interfaces from the KHR_materials_variants extension
      * !!! Experimental Extension Subject to Changes !!!
      */

+ 1 - 1
dist/preview release/glTF2Interface/package.json

@@ -1,7 +1,7 @@
 {
     "name": "babylonjs-gltf2interface",
     "description": "A typescript declaration of babylon's gltf2 inteface.",
-    "version": "4.2.0-beta.14",
+    "version": "4.2.0-rc.2",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 43 - 6
dist/preview release/gui/babylon.gui.d.ts

@@ -421,6 +421,10 @@ declare module BABYLON.GUI {
         */
         premulAlpha: boolean;
         /**
+         * Gets or sets a boolean indicating that the canvas must be reverted on Y when updating the texture
+         */
+        applyYInversionOnUpdate: boolean;
+        /**
         * Gets or sets a number used to scale rendering size (2 means that the texture will be twice bigger).
         * Useful when you want more antialiasing
         */
@@ -569,6 +573,13 @@ declare module BABYLON.GUI {
         * @returns the projected position
         */
         getProjectedPosition(position: BABYLON.Vector3, worldMatrix: BABYLON.Matrix): BABYLON.Vector2;
+        /**
+        * Get screen coordinates for a vector3
+        * @param position defines the position to project
+        * @param worldMatrix defines the world matrix to use
+        * @returns the projected position with Z
+        */
+        getProjectedPositionWithZ(position: BABYLON.Vector3, worldMatrix: BABYLON.Matrix): BABYLON.Vector3;
         private _checkUpdate;
         private _clearMeasure;
         private _render;
@@ -625,6 +636,16 @@ declare module BABYLON.GUI {
          */
         static CreateForMesh(mesh: BABYLON.AbstractMesh, width?: number, height?: number, supportPointerMove?: boolean, onlyAlphaTesting?: boolean, invertY?: boolean): AdvancedDynamicTexture;
         /**
+         * Creates a new AdvancedDynamicTexture in projected mode (ie. attached to a mesh) BUT do not create a new material for the mesh. You will be responsible for connecting the texture
+         * @param mesh defines the mesh which will receive the texture
+         * @param width defines the texture width (1024 by default)
+         * @param height defines the texture height (1024 by default)
+         * @param supportPointerMove defines a boolean indicating if the texture must capture move events (true by default)
+         * @param invertY defines if the texture needs to be inverted on the y axis during loading (true by default)
+         * @returns a new AdvancedDynamicTexture
+         */
+        static CreateForMeshTexture(mesh: BABYLON.AbstractMesh, width?: number, height?: number, supportPointerMove?: boolean, invertY?: boolean): AdvancedDynamicTexture;
+        /**
         * Creates a new AdvancedDynamicTexture in fullscreen mode.
         * In this mode the texture will rely on a layer for its rendering.
         * This allows it to be treated like any other layer.
@@ -2015,12 +2036,27 @@ declare module BABYLON.GUI {
     }
 }
 declare module BABYLON.GUI {
+    /** @hidden */
+    export class TextWrapper {
+        private _text;
+        private _characters;
+        get text(): string;
+        set text(txt: string);
+        get length(): number;
+        removePart(idxStart: number, idxEnd: number, insertTxt?: string): void;
+        charAt(idx: number): string;
+        substr(from: number, length?: number): string;
+        substring(from: number, to?: number): string;
+        isWord(index: number): boolean;
+    }
+}
+declare module BABYLON.GUI {
     /**
      * Class used to create input text control
      */
     export class InputText extends Control implements IFocusableControl {
         name?: string | undefined;
-        private _text;
+        private _textWrapper;
         private _placeholderText;
         private _background;
         private _focusedBackground;
@@ -2130,6 +2166,7 @@ declare module BABYLON.GUI {
         /** Gets or sets the text displayed in the control */
         get text(): string;
         set text(value: string);
+        private _textHasChanged;
         /** Gets or sets control width */
         get width(): string | number;
         set width(value: string | number);
@@ -2172,7 +2209,7 @@ declare module BABYLON.GUI {
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, pi: BABYLON.PointerInfoBase): boolean;
         _onPointerMove(target: Control, coordinates: BABYLON.Vector2, pointerId: number, pi: BABYLON.PointerInfoBase): void;
         _onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
-        protected _beforeRenderText(text: string): string;
+        protected _beforeRenderText(textWrapper: TextWrapper): TextWrapper;
         dispose(): void;
     }
 }
@@ -2405,7 +2442,7 @@ declare module BABYLON.GUI {
      * Class used to create a password control
      */
     export class InputPassword extends InputText {
-        protected _beforeRenderText(text: string): string;
+        protected _beforeRenderText(textWrapper: TextWrapper): TextWrapper;
     }
 }
 declare module BABYLON.GUI {
@@ -2485,7 +2522,7 @@ declare module BABYLON.GUI {
         private _controlObserver;
         private _meshObserver;
         /** @hidden */
-        _point: BABYLON.Vector2;
+        _point: BABYLON.Vector3;
         /**
          * Creates a new MultiLinePoint
          * @param multiLine defines the source MultiLine object
@@ -2506,10 +2543,10 @@ declare module BABYLON.GUI {
         /** Resets links */
         resetLinks(): void;
         /**
-         * Gets a translation vector
+         * Gets a translation vector with Z component
          * @returns the translation vector
          */
-        translate(): BABYLON.Vector2;
+        translate(): BABYLON.Vector3;
         private _translatePoint;
         /** Release associated resources */
         dispose(): void;

File diff ditekan karena terlalu besar
+ 299 - 112
dist/preview release/gui/babylon.gui.js


File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/gui/babylon.gui.js.map


File diff ditekan karena terlalu besar
+ 2 - 2
dist/preview release/gui/babylon.gui.min.js


+ 90 - 13
dist/preview release/gui/babylon.gui.module.d.ts

@@ -441,6 +441,10 @@ declare module "babylonjs-gui/2D/advancedDynamicTexture" {
         */
         premulAlpha: boolean;
         /**
+         * Gets or sets a boolean indicating that the canvas must be reverted on Y when updating the texture
+         */
+        applyYInversionOnUpdate: boolean;
+        /**
         * Gets or sets a number used to scale rendering size (2 means that the texture will be twice bigger).
         * Useful when you want more antialiasing
         */
@@ -589,6 +593,13 @@ declare module "babylonjs-gui/2D/advancedDynamicTexture" {
         * @returns the projected position
         */
         getProjectedPosition(position: Vector3, worldMatrix: Matrix): Vector2;
+        /**
+        * Get screen coordinates for a vector3
+        * @param position defines the position to project
+        * @param worldMatrix defines the world matrix to use
+        * @returns the projected position with Z
+        */
+        getProjectedPositionWithZ(position: Vector3, worldMatrix: Matrix): Vector3;
         private _checkUpdate;
         private _clearMeasure;
         private _render;
@@ -645,6 +656,16 @@ declare module "babylonjs-gui/2D/advancedDynamicTexture" {
          */
         static CreateForMesh(mesh: AbstractMesh, width?: number, height?: number, supportPointerMove?: boolean, onlyAlphaTesting?: boolean, invertY?: boolean): AdvancedDynamicTexture;
         /**
+         * Creates a new AdvancedDynamicTexture in projected mode (ie. attached to a mesh) BUT do not create a new material for the mesh. You will be responsible for connecting the texture
+         * @param mesh defines the mesh which will receive the texture
+         * @param width defines the texture width (1024 by default)
+         * @param height defines the texture height (1024 by default)
+         * @param supportPointerMove defines a boolean indicating if the texture must capture move events (true by default)
+         * @param invertY defines if the texture needs to be inverted on the y axis during loading (true by default)
+         * @returns a new AdvancedDynamicTexture
+         */
+        static CreateForMeshTexture(mesh: AbstractMesh, width?: number, height?: number, supportPointerMove?: boolean, invertY?: boolean): AdvancedDynamicTexture;
+        /**
         * Creates a new AdvancedDynamicTexture in fullscreen mode.
         * In this mode the texture will rely on a layer for its rendering.
         * This allows it to be treated like any other layer.
@@ -2081,6 +2102,21 @@ declare module "babylonjs-gui/2D/controls/virtualKeyboard" {
         static CreateDefaultLayout(name?: string): VirtualKeyboard;
     }
 }
+declare module "babylonjs-gui/2D/controls/textWrapper" {
+    /** @hidden */
+    export class TextWrapper {
+        private _text;
+        private _characters;
+        get text(): string;
+        set text(txt: string);
+        get length(): number;
+        removePart(idxStart: number, idxEnd: number, insertTxt?: string): void;
+        charAt(idx: number): string;
+        substr(from: number, length?: number): string;
+        substring(from: number, to?: number): string;
+        isWord(index: number): boolean;
+    }
+}
 declare module "babylonjs-gui/2D/controls/inputText" {
     import { Nullable } from "babylonjs/types";
     import { Observable } from "babylonjs/Misc/observable";
@@ -2090,12 +2126,13 @@ declare module "babylonjs-gui/2D/controls/inputText" {
     import { IFocusableControl } from "babylonjs-gui/2D/advancedDynamicTexture";
     import { VirtualKeyboard } from "babylonjs-gui/2D/controls/virtualKeyboard";
     import { Measure } from "babylonjs-gui/2D/measure";
+    import { TextWrapper } from "babylonjs-gui/2D/controls/textWrapper";
     /**
      * Class used to create input text control
      */
     export class InputText extends Control implements IFocusableControl {
         name?: string | undefined;
-        private _text;
+        private _textWrapper;
         private _placeholderText;
         private _background;
         private _focusedBackground;
@@ -2205,6 +2242,7 @@ declare module "babylonjs-gui/2D/controls/inputText" {
         /** Gets or sets the text displayed in the control */
         get text(): string;
         set text(value: string);
+        private _textHasChanged;
         /** Gets or sets control width */
         get width(): string | number;
         set width(value: string | number);
@@ -2247,7 +2285,7 @@ declare module "babylonjs-gui/2D/controls/inputText" {
         _onPointerDown(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, pi: PointerInfoBase): boolean;
         _onPointerMove(target: Control, coordinates: Vector2, pointerId: number, pi: PointerInfoBase): void;
         _onPointerUp(target: Control, coordinates: Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
-        protected _beforeRenderText(text: string): string;
+        protected _beforeRenderText(textWrapper: TextWrapper): TextWrapper;
         dispose(): void;
     }
 }
@@ -2491,11 +2529,12 @@ declare module "babylonjs-gui/2D/controls/ellipse" {
 }
 declare module "babylonjs-gui/2D/controls/inputPassword" {
     import { InputText } from "babylonjs-gui/2D/controls/inputText";
+    import { TextWrapper } from "babylonjs-gui/2D/controls/textWrapper";
     /**
      * Class used to create a password control
      */
     export class InputPassword extends InputText {
-        protected _beforeRenderText(text: string): string;
+        protected _beforeRenderText(textWrapper: TextWrapper): TextWrapper;
     }
 }
 declare module "babylonjs-gui/2D/controls/line" {
@@ -2567,7 +2606,7 @@ declare module "babylonjs-gui/2D/controls/line" {
 }
 declare module "babylonjs-gui/2D/multiLinePoint" {
     import { Nullable } from "babylonjs/types";
-    import { Vector2 } from "babylonjs/Maths/math.vector";
+    import { Vector3 } from "babylonjs/Maths/math.vector";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { MultiLine } from "babylonjs-gui/2D/controls/multiLine";
     import { Control } from "babylonjs-gui/2D/controls/control";
@@ -2584,7 +2623,7 @@ declare module "babylonjs-gui/2D/multiLinePoint" {
         private _controlObserver;
         private _meshObserver;
         /** @hidden */
-        _point: Vector2;
+        _point: Vector3;
         /**
          * Creates a new MultiLinePoint
          * @param multiLine defines the source MultiLine object
@@ -2605,10 +2644,10 @@ declare module "babylonjs-gui/2D/multiLinePoint" {
         /** Resets links */
         resetLinks(): void;
         /**
-         * Gets a translation vector
+         * Gets a translation vector with Z component
          * @returns the translation vector
          */
-        translate(): Vector2;
+        translate(): Vector3;
         private _translatePoint;
         /** Release associated resources */
         dispose(): void;
@@ -3512,6 +3551,7 @@ declare module "babylonjs-gui/2D/controls/index" {
     export * from "babylonjs-gui/2D/controls/selector";
     export * from "babylonjs-gui/2D/controls/scrollViewers/scrollViewer";
     export * from "babylonjs-gui/2D/controls/textBlock";
+    export * from "babylonjs-gui/2D/controls/textWrapper";
     export * from "babylonjs-gui/2D/controls/virtualKeyboard";
     export * from "babylonjs-gui/2D/controls/rectangle";
     export * from "babylonjs-gui/2D/controls/displayGrid";
@@ -4857,6 +4897,10 @@ declare module BABYLON.GUI {
         */
         premulAlpha: boolean;
         /**
+         * Gets or sets a boolean indicating that the canvas must be reverted on Y when updating the texture
+         */
+        applyYInversionOnUpdate: boolean;
+        /**
         * Gets or sets a number used to scale rendering size (2 means that the texture will be twice bigger).
         * Useful when you want more antialiasing
         */
@@ -5005,6 +5049,13 @@ declare module BABYLON.GUI {
         * @returns the projected position
         */
         getProjectedPosition(position: BABYLON.Vector3, worldMatrix: BABYLON.Matrix): BABYLON.Vector2;
+        /**
+        * Get screen coordinates for a vector3
+        * @param position defines the position to project
+        * @param worldMatrix defines the world matrix to use
+        * @returns the projected position with Z
+        */
+        getProjectedPositionWithZ(position: BABYLON.Vector3, worldMatrix: BABYLON.Matrix): BABYLON.Vector3;
         private _checkUpdate;
         private _clearMeasure;
         private _render;
@@ -5061,6 +5112,16 @@ declare module BABYLON.GUI {
          */
         static CreateForMesh(mesh: BABYLON.AbstractMesh, width?: number, height?: number, supportPointerMove?: boolean, onlyAlphaTesting?: boolean, invertY?: boolean): AdvancedDynamicTexture;
         /**
+         * Creates a new AdvancedDynamicTexture in projected mode (ie. attached to a mesh) BUT do not create a new material for the mesh. You will be responsible for connecting the texture
+         * @param mesh defines the mesh which will receive the texture
+         * @param width defines the texture width (1024 by default)
+         * @param height defines the texture height (1024 by default)
+         * @param supportPointerMove defines a boolean indicating if the texture must capture move events (true by default)
+         * @param invertY defines if the texture needs to be inverted on the y axis during loading (true by default)
+         * @returns a new AdvancedDynamicTexture
+         */
+        static CreateForMeshTexture(mesh: BABYLON.AbstractMesh, width?: number, height?: number, supportPointerMove?: boolean, invertY?: boolean): AdvancedDynamicTexture;
+        /**
         * Creates a new AdvancedDynamicTexture in fullscreen mode.
         * In this mode the texture will rely on a layer for its rendering.
         * This allows it to be treated like any other layer.
@@ -6451,12 +6512,27 @@ declare module BABYLON.GUI {
     }
 }
 declare module BABYLON.GUI {
+    /** @hidden */
+    export class TextWrapper {
+        private _text;
+        private _characters;
+        get text(): string;
+        set text(txt: string);
+        get length(): number;
+        removePart(idxStart: number, idxEnd: number, insertTxt?: string): void;
+        charAt(idx: number): string;
+        substr(from: number, length?: number): string;
+        substring(from: number, to?: number): string;
+        isWord(index: number): boolean;
+    }
+}
+declare module BABYLON.GUI {
     /**
      * Class used to create input text control
      */
     export class InputText extends Control implements IFocusableControl {
         name?: string | undefined;
-        private _text;
+        private _textWrapper;
         private _placeholderText;
         private _background;
         private _focusedBackground;
@@ -6566,6 +6642,7 @@ declare module BABYLON.GUI {
         /** Gets or sets the text displayed in the control */
         get text(): string;
         set text(value: string);
+        private _textHasChanged;
         /** Gets or sets control width */
         get width(): string | number;
         set width(value: string | number);
@@ -6608,7 +6685,7 @@ declare module BABYLON.GUI {
         _onPointerDown(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, pi: BABYLON.PointerInfoBase): boolean;
         _onPointerMove(target: Control, coordinates: BABYLON.Vector2, pointerId: number, pi: BABYLON.PointerInfoBase): void;
         _onPointerUp(target: Control, coordinates: BABYLON.Vector2, pointerId: number, buttonIndex: number, notifyClick: boolean): void;
-        protected _beforeRenderText(text: string): string;
+        protected _beforeRenderText(textWrapper: TextWrapper): TextWrapper;
         dispose(): void;
     }
 }
@@ -6841,7 +6918,7 @@ declare module BABYLON.GUI {
      * Class used to create a password control
      */
     export class InputPassword extends InputText {
-        protected _beforeRenderText(text: string): string;
+        protected _beforeRenderText(textWrapper: TextWrapper): TextWrapper;
     }
 }
 declare module BABYLON.GUI {
@@ -6921,7 +6998,7 @@ declare module BABYLON.GUI {
         private _controlObserver;
         private _meshObserver;
         /** @hidden */
-        _point: BABYLON.Vector2;
+        _point: BABYLON.Vector3;
         /**
          * Creates a new MultiLinePoint
          * @param multiLine defines the source MultiLine object
@@ -6942,10 +7019,10 @@ declare module BABYLON.GUI {
         /** Resets links */
         resetLinks(): void;
         /**
-         * Gets a translation vector
+         * Gets a translation vector with Z component
          * @returns the translation vector
          */
-        translate(): BABYLON.Vector2;
+        translate(): BABYLON.Vector3;
         private _translatePoint;
         /** Release associated resources */
         dispose(): void;

+ 2 - 2
dist/preview release/gui/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-gui",
     "description": "The Babylon.js GUI library is an extension you can use to generate interactive user interface. It is build on top of the DynamicTexture.",
-    "version": "4.2.0-beta.14",
+    "version": "4.2.0-rc.2",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.2.0-beta.14"
+        "babylonjs": "4.2.0-rc.2"
     },
     "engines": {
         "node": "*"

File diff ditekan karena terlalu besar
+ 8 - 8
dist/preview release/inspector/babylon.inspector.bundle.js


File diff ditekan karena terlalu besar
+ 29903 - 49406
dist/preview release/inspector/babylon.inspector.bundle.max.js


File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.max.js.map


File diff ditekan karena terlalu besar
+ 2539 - 2494
dist/preview release/inspector/babylon.inspector.d.ts


File diff ditekan karena terlalu besar
+ 4663 - 4573
dist/preview release/inspector/babylon.inspector.module.d.ts


+ 7 - 7
dist/preview release/inspector/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-inspector",
     "description": "The Babylon.js inspector.",
-    "version": "4.2.0-beta.14",
+    "version": "4.2.0-rc.2",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -29,12 +29,12 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.2.0-beta.14",
-        "babylonjs-gui": "4.2.0-beta.14",
-        "babylonjs-loaders": "4.2.0-beta.14",
-        "babylonjs-materials": "4.2.0-beta.14",
-        "babylonjs-serializers": "4.2.0-beta.14",
-        "babylonjs-gltf2interface": "4.2.0-beta.14"
+        "babylonjs": "4.2.0-rc.2",
+        "babylonjs-gui": "4.2.0-rc.2",
+        "babylonjs-loaders": "4.2.0-rc.2",
+        "babylonjs-materials": "4.2.0-rc.2",
+        "babylonjs-serializers": "4.2.0-rc.2",
+        "babylonjs-gltf2interface": "4.2.0-rc.2"
     },
     "peerDependencies": {
         "@types/react": ">=16.7.3",

File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/loaders/babylon.glTF1FileLoader.js.map


File diff ditekan karena terlalu besar
+ 108 - 73
dist/preview release/loaders/babylon.glTF2FileLoader.js


File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.js.map


File diff ditekan karena terlalu besar
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


File diff ditekan karena terlalu besar
+ 108 - 73
dist/preview release/loaders/babylon.glTFFileLoader.js


File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.js.map


File diff ditekan karena terlalu besar
+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 4 - 1
dist/preview release/loaders/babylon.objFileLoader.js

@@ -542,7 +542,10 @@ var OBJFileLoader = /** @class */ (function () {
                 meshes: meshes,
                 particleSystems: [],
                 skeletons: [],
-                animationGroups: []
+                animationGroups: [],
+                transformNodes: [],
+                geometries: [],
+                lights: []
             };
         });
     };

File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.js.map


File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 33 - 54
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -108,19 +108,9 @@ declare module BABYLON {
         COMPLETE = 2
     }
     /** @hidden */
-    export interface IImportMeshAsyncOutput {
-        meshes: AbstractMesh[];
-        geometries: Geometry[];
-        particleSystems: IParticleSystem[];
-        skeletons: Skeleton[];
-        animationGroups: AnimationGroup[];
-        lights: Light[];
-        transformNodes: TransformNode[];
-    }
-    /** @hidden */
     export interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<IImportMeshAsyncOutput>;
+        importMeshAsync: (meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<ISceneLoaderAsyncResult>;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<void>;
     }
     /**
@@ -322,12 +312,7 @@ declare module BABYLON {
         /** @hidden */
         readFile(scene: Scene, file: File, onSuccess: (data: any) => void, onProgress?: (ev: ISceneLoaderProgressEvent) => any, useArrayBuffer?: boolean, onError?: (error: any) => void): IFileRequest;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<{
-            meshes: AbstractMesh[];
-            particleSystems: IParticleSystem[];
-            skeletons: Skeleton[];
-            animationGroups: AnimationGroup[];
-        }>;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /** @hidden */
         loadAsync(scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         /** @hidden */
@@ -890,7 +875,7 @@ declare module BABYLON.GLTF1 {
         * @param onProgress event that fires when loading progress has occured
         * @returns a promise containg the loaded meshes, particles, skeletons and animations
         */
-        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<IImportMeshAsyncOutput>;
+        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<ISceneLoaderAsyncResult>;
         private _loadAsync;
         /**
         * Imports all objects from a loaded gltf file and adds them to the scene
@@ -1409,7 +1394,7 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<IImportMeshAsyncOutput>;
+        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /** @hidden */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         private _loadAsync;
@@ -2055,6 +2040,34 @@ declare module BABYLON.GLTF2.Loader.Extensions {
 }
 declare module BABYLON.GLTF2.Loader.Extensions {
     /**
+     * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1825)
+     * !!! Experimental Extension Subject to Changes !!!
+     */
+    export class KHR_materials_translucency implements IGLTFLoaderExtension {
+        /**
+         * The name of this extension.
+         */
+        readonly name: string;
+        /**
+         * Defines whether this extension is enabled.
+         */
+        enabled: boolean;
+        /**
+         * Defines a number that determines the order the extensions are applied.
+         */
+        order: number;
+        private _loader;
+        /** @hidden */
+        constructor(loader: GLTFLoader);
+        /** @hidden */
+        dispose(): void;
+        /** @hidden */
+        loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>>;
+        private _loadTranslucentPropertiesAsync;
+    }
+}
+declare module BABYLON.GLTF2.Loader.Extensions {
+    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization)
      */
     export class KHR_mesh_quantization implements IGLTFLoaderExtension {
@@ -2115,35 +2128,6 @@ declare module BABYLON.GLTF2.Loader.Extensions {
 }
 declare module BABYLON.GLTF2.Loader.Extensions {
     /**
-     * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1553)
-     * !!! Experimental Extension Subject to Changes !!!
-     */
-    export class KHR_xmp implements IGLTFLoaderExtension {
-        /**
-         * The name of this extension.
-         */
-        readonly name: string;
-        /**
-         * Defines whether this extension is enabled.
-         */
-        enabled: boolean;
-        /**
-         * Defines a number that determines the order the extensions are applied.
-         */
-        order: number;
-        private _loader;
-        /** @hidden */
-        constructor(loader: GLTFLoader);
-        /** @hidden */
-        dispose(): void;
-        /**
-         * Called after the loader state changes to LOADING.
-         */
-        onLoading(): void;
-    }
-}
-declare module BABYLON.GLTF2.Loader.Extensions {
-    /**
      * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
      */
     export class MSFT_audio_emitter implements IGLTFLoaderExtension {
@@ -2486,12 +2470,7 @@ declare module BABYLON {
          * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<{
-            meshes: AbstractMesh[];
-            particleSystems: IParticleSystem[];
-            skeletons: Skeleton[];
-            animationGroups: AnimationGroup[];
-        }>;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /**
          * Imports all objects from the loaded OBJ data and adds them to the scene
          * @param scene the scene the objects should be added to

File diff ditekan karena terlalu besar
+ 112 - 74
dist/preview release/loaders/babylonjs.loaders.js


File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.js.map


File diff ditekan karena terlalu besar
+ 2 - 2
dist/preview release/loaders/babylonjs.loaders.min.js


+ 78 - 127
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -34,22 +34,16 @@ declare module "babylonjs-loaders/glTF/glTFFileLoader" {
     import { Nullable } from "babylonjs/types";
     import { Observable } from "babylonjs/Misc/observable";
     import { Camera } from "babylonjs/Cameras/camera";
-    import { AnimationGroup } from "babylonjs/Animations/animationGroup";
-    import { Skeleton } from "babylonjs/Bones/skeleton";
-    import { IParticleSystem } from "babylonjs/Particles/IParticleSystem";
     import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
     import { Material } from "babylonjs/Materials/material";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
-    import { ISceneLoaderPluginFactory, ISceneLoaderPlugin, ISceneLoaderPluginAsync, ISceneLoaderProgressEvent, ISceneLoaderPluginExtensions } from "babylonjs/Loading/sceneLoader";
+    import { ISceneLoaderPluginFactory, ISceneLoaderPlugin, ISceneLoaderPluginAsync, ISceneLoaderProgressEvent, ISceneLoaderPluginExtensions, ISceneLoaderAsyncResult } from "babylonjs/Loading/sceneLoader";
     import { AssetContainer } from "babylonjs/assetContainer";
     import { Scene, IDisposable } from "babylonjs/scene";
     import { WebRequest } from "babylonjs/Misc/webRequest";
     import { IFileRequest } from "babylonjs/Misc/fileRequest";
     import { IDataBuffer } from 'babylonjs/Misc/dataReader';
-    import { Light } from 'babylonjs/Lights/light';
-    import { TransformNode } from 'babylonjs/Meshes/transformNode';
     import { RequestFileError } from 'babylonjs/Misc/fileTools';
-    import { Geometry } from 'babylonjs/Meshes/geometry';
     /**
      * Mode that determines the coordinate system to use.
      */
@@ -129,19 +123,9 @@ declare module "babylonjs-loaders/glTF/glTFFileLoader" {
         COMPLETE = 2
     }
     /** @hidden */
-    export interface IImportMeshAsyncOutput {
-        meshes: AbstractMesh[];
-        geometries: Geometry[];
-        particleSystems: IParticleSystem[];
-        skeletons: Skeleton[];
-        animationGroups: AnimationGroup[];
-        lights: Light[];
-        transformNodes: TransformNode[];
-    }
-    /** @hidden */
     export interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<IImportMeshAsyncOutput>;
+        importMeshAsync: (meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<ISceneLoaderAsyncResult>;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<void>;
     }
     /**
@@ -343,12 +327,7 @@ declare module "babylonjs-loaders/glTF/glTFFileLoader" {
         /** @hidden */
         readFile(scene: Scene, file: File, onSuccess: (data: any) => void, onProgress?: (ev: ISceneLoaderProgressEvent) => any, useArrayBuffer?: boolean, onError?: (error: any) => void): IFileRequest;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<{
-            meshes: AbstractMesh[];
-            particleSystems: IParticleSystem[];
-            skeletons: Skeleton[];
-            animationGroups: AnimationGroup[];
-        }>;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /** @hidden */
         loadAsync(scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         /** @hidden */
@@ -891,9 +870,9 @@ declare module "babylonjs-loaders/glTF/1.0/glTFLoader" {
     import { Nullable } from "babylonjs/types";
     import { Material } from "babylonjs/Materials/material";
     import { Texture } from "babylonjs/Materials/Textures/texture";
-    import { ISceneLoaderProgressEvent } from "babylonjs/Loading/sceneLoader";
+    import { ISceneLoaderAsyncResult, ISceneLoaderProgressEvent } from "babylonjs/Loading/sceneLoader";
     import { Scene } from "babylonjs/scene";
-    import { IGLTFLoader, GLTFLoaderState, IGLTFLoaderData, IImportMeshAsyncOutput } from "babylonjs-loaders/glTF/glTFFileLoader";
+    import { IGLTFLoader, GLTFLoaderState, IGLTFLoaderData } from "babylonjs-loaders/glTF/glTFFileLoader";
     /**
     * Implementation of the base glTF spec
     * @hidden
@@ -928,7 +907,7 @@ declare module "babylonjs-loaders/glTF/1.0/glTFLoader" {
         * @param onProgress event that fires when loading progress has occured
         * @returns a promise containg the loaded meshes, particles, skeletons and animations
         */
-        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<IImportMeshAsyncOutput>;
+        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<ISceneLoaderAsyncResult>;
         private _loadAsync;
         /**
         * Imports all objects from a loaded gltf file and adds them to the scene
@@ -1403,12 +1382,12 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
     import { TransformNode } from "babylonjs/Meshes/transformNode";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { Mesh } from "babylonjs/Meshes/mesh";
-    import { ISceneLoaderProgressEvent } from "babylonjs/Loading/sceneLoader";
+    import { ISceneLoaderAsyncResult, ISceneLoaderProgressEvent } from "babylonjs/Loading/sceneLoader";
     import { Scene } from "babylonjs/scene";
     import { IProperty } from "babylonjs-gltf2interface";
     import { IGLTF, ISampler, INode, IScene, IMesh, IAccessor, ICamera, IAnimation, IAnimationChannel, IBufferView, IMaterial, ITextureInfo, ITexture, IImage, IMeshPrimitive, IArrayItem as IArrItem } from "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces";
     import { IGLTFLoaderExtension } from "babylonjs-loaders/glTF/2.0/glTFLoaderExtension";
-    import { IGLTFLoader, GLTFFileLoader, GLTFLoaderState, IGLTFLoaderData, IImportMeshAsyncOutput } from "babylonjs-loaders/glTF/glTFFileLoader";
+    import { IGLTFLoader, GLTFFileLoader, GLTFLoaderState, IGLTFLoaderData } from "babylonjs-loaders/glTF/glTFFileLoader";
     import { IAnimatable } from 'babylonjs/Animations/animatable.interface';
     import { IDataBuffer } from 'babylonjs/Misc/dataReader';
     import { Light } from 'babylonjs/Lights/light';
@@ -1500,7 +1479,7 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<IImportMeshAsyncOutput>;
+        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /** @hidden */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         private _loadAsync;
@@ -2214,6 +2193,39 @@ declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_transmission
         private _loadTransparentPropertiesAsync;
     }
 }
+declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_translucency" {
+    import { Nullable } from "babylonjs/types";
+    import { Material } from "babylonjs/Materials/material";
+    import { IMaterial } from "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces";
+    import { IGLTFLoaderExtension } from "babylonjs-loaders/glTF/2.0/glTFLoaderExtension";
+    import { GLTFLoader } from "babylonjs-loaders/glTF/2.0/glTFLoader";
+    /**
+     * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1825)
+     * !!! Experimental Extension Subject to Changes !!!
+     */
+    export class KHR_materials_translucency implements IGLTFLoaderExtension {
+        /**
+         * The name of this extension.
+         */
+        readonly name: string;
+        /**
+         * Defines whether this extension is enabled.
+         */
+        enabled: boolean;
+        /**
+         * Defines a number that determines the order the extensions are applied.
+         */
+        order: number;
+        private _loader;
+        /** @hidden */
+        constructor(loader: GLTFLoader);
+        /** @hidden */
+        dispose(): void;
+        /** @hidden */
+        loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>>;
+        private _loadTranslucentPropertiesAsync;
+    }
+}
 declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_mesh_quantization" {
     import { IGLTFLoaderExtension } from "babylonjs-loaders/glTF/2.0/glTFLoaderExtension";
     import { GLTFLoader } from "babylonjs-loaders/glTF/2.0/glTFLoader";
@@ -2286,37 +2298,6 @@ declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_texture_transform" {
         loadTextureInfoAsync(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>>;
     }
 }
-declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_xmp" {
-    import { IGLTFLoaderExtension } from "babylonjs-loaders/glTF/2.0/glTFLoaderExtension";
-    import { GLTFLoader } from "babylonjs-loaders/glTF/2.0/glTFLoader";
-    /**
-     * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1553)
-     * !!! Experimental Extension Subject to Changes !!!
-     */
-    export class KHR_xmp implements IGLTFLoaderExtension {
-        /**
-         * The name of this extension.
-         */
-        readonly name: string;
-        /**
-         * Defines whether this extension is enabled.
-         */
-        enabled: boolean;
-        /**
-         * Defines a number that determines the order the extensions are applied.
-         */
-        order: number;
-        private _loader;
-        /** @hidden */
-        constructor(loader: GLTFLoader);
-        /** @hidden */
-        dispose(): void;
-        /**
-         * Called after the loader state changes to LOADING.
-         */
-        onLoading(): void;
-    }
-}
 declare module "babylonjs-loaders/glTF/2.0/Extensions/MSFT_audio_emitter" {
     import { Nullable } from "babylonjs/types";
     import { AnimationGroup } from "babylonjs/Animations/animationGroup";
@@ -2514,10 +2495,10 @@ declare module "babylonjs-loaders/glTF/2.0/Extensions/index" {
     export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_ior";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_variants";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_transmission";
+    export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_translucency";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_mesh_quantization";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_texture_basisu";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_texture_transform";
-    export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_xmp";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/MSFT_audio_emitter";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/MSFT_lod";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/MSFT_minecraftMesh";
@@ -2579,11 +2560,7 @@ declare module "babylonjs-loaders/OBJ/mtlFileLoader" {
 }
 declare module "babylonjs-loaders/OBJ/objFileLoader" {
     import { Vector2 } from "babylonjs/Maths/math.vector";
-    import { AnimationGroup } from "babylonjs/Animations/animationGroup";
-    import { Skeleton } from "babylonjs/Bones/skeleton";
-    import { IParticleSystem } from "babylonjs/Particles/IParticleSystem";
-    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
-    import { ISceneLoaderPluginAsync, ISceneLoaderProgressEvent, ISceneLoaderPluginFactory, ISceneLoaderPlugin } from "babylonjs/Loading/sceneLoader";
+    import { ISceneLoaderPluginAsync, ISceneLoaderProgressEvent, ISceneLoaderPluginFactory, ISceneLoaderPlugin, ISceneLoaderAsyncResult } from "babylonjs/Loading/sceneLoader";
     import { AssetContainer } from "babylonjs/assetContainer";
     import { Scene } from "babylonjs/scene";
     /**
@@ -2740,12 +2717,7 @@ declare module "babylonjs-loaders/OBJ/objFileLoader" {
          * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<{
-            meshes: AbstractMesh[];
-            particleSystems: IParticleSystem[];
-            skeletons: Skeleton[];
-            animationGroups: AnimationGroup[];
-        }>;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /**
          * Imports all objects from the loaded OBJ data and adds them to the scene
          * @param scene the scene the objects should be added to
@@ -3012,19 +2984,9 @@ declare module BABYLON {
         COMPLETE = 2
     }
     /** @hidden */
-    export interface IImportMeshAsyncOutput {
-        meshes: AbstractMesh[];
-        geometries: Geometry[];
-        particleSystems: IParticleSystem[];
-        skeletons: Skeleton[];
-        animationGroups: AnimationGroup[];
-        lights: Light[];
-        transformNodes: TransformNode[];
-    }
-    /** @hidden */
     export interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<IImportMeshAsyncOutput>;
+        importMeshAsync: (meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<ISceneLoaderAsyncResult>;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<void>;
     }
     /**
@@ -3226,12 +3188,7 @@ declare module BABYLON {
         /** @hidden */
         readFile(scene: Scene, file: File, onSuccess: (data: any) => void, onProgress?: (ev: ISceneLoaderProgressEvent) => any, useArrayBuffer?: boolean, onError?: (error: any) => void): IFileRequest;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<{
-            meshes: AbstractMesh[];
-            particleSystems: IParticleSystem[];
-            skeletons: Skeleton[];
-            animationGroups: AnimationGroup[];
-        }>;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /** @hidden */
         loadAsync(scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         /** @hidden */
@@ -3794,7 +3751,7 @@ declare module BABYLON.GLTF1 {
         * @param onProgress event that fires when loading progress has occured
         * @returns a promise containg the loaded meshes, particles, skeletons and animations
         */
-        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<IImportMeshAsyncOutput>;
+        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<ISceneLoaderAsyncResult>;
         private _loadAsync;
         /**
         * Imports all objects from a loaded gltf file and adds them to the scene
@@ -4313,7 +4270,7 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<IImportMeshAsyncOutput>;
+        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /** @hidden */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         private _loadAsync;
@@ -4959,6 +4916,34 @@ declare module BABYLON.GLTF2.Loader.Extensions {
 }
 declare module BABYLON.GLTF2.Loader.Extensions {
     /**
+     * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1825)
+     * !!! Experimental Extension Subject to Changes !!!
+     */
+    export class KHR_materials_translucency implements IGLTFLoaderExtension {
+        /**
+         * The name of this extension.
+         */
+        readonly name: string;
+        /**
+         * Defines whether this extension is enabled.
+         */
+        enabled: boolean;
+        /**
+         * Defines a number that determines the order the extensions are applied.
+         */
+        order: number;
+        private _loader;
+        /** @hidden */
+        constructor(loader: GLTFLoader);
+        /** @hidden */
+        dispose(): void;
+        /** @hidden */
+        loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>>;
+        private _loadTranslucentPropertiesAsync;
+    }
+}
+declare module BABYLON.GLTF2.Loader.Extensions {
+    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization)
      */
     export class KHR_mesh_quantization implements IGLTFLoaderExtension {
@@ -5019,35 +5004,6 @@ declare module BABYLON.GLTF2.Loader.Extensions {
 }
 declare module BABYLON.GLTF2.Loader.Extensions {
     /**
-     * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1553)
-     * !!! Experimental Extension Subject to Changes !!!
-     */
-    export class KHR_xmp implements IGLTFLoaderExtension {
-        /**
-         * The name of this extension.
-         */
-        readonly name: string;
-        /**
-         * Defines whether this extension is enabled.
-         */
-        enabled: boolean;
-        /**
-         * Defines a number that determines the order the extensions are applied.
-         */
-        order: number;
-        private _loader;
-        /** @hidden */
-        constructor(loader: GLTFLoader);
-        /** @hidden */
-        dispose(): void;
-        /**
-         * Called after the loader state changes to LOADING.
-         */
-        onLoading(): void;
-    }
-}
-declare module BABYLON.GLTF2.Loader.Extensions {
-    /**
      * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
      */
     export class MSFT_audio_emitter implements IGLTFLoaderExtension {
@@ -5390,12 +5346,7 @@ declare module BABYLON {
          * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<{
-            meshes: AbstractMesh[];
-            particleSystems: IParticleSystem[];
-            skeletons: Skeleton[];
-            animationGroups: AnimationGroup[];
-        }>;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /**
          * Imports all objects from the loaded OBJ data and adds them to the scene
          * @param scene the scene the objects should be added to

+ 3 - 3
dist/preview release/loaders/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-loaders",
     "description": "The Babylon.js file loaders library is an extension you can use to load different 3D file types into a Babylon scene.",
-    "version": "4.2.0-beta.14",
+    "version": "4.2.0-rc.2",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,8 +28,8 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs-gltf2interface": "4.2.0-beta.14",
-        "babylonjs": "4.2.0-beta.14"
+        "babylonjs-gltf2interface": "4.2.0-rc.2",
+        "babylonjs": "4.2.0-rc.2"
     },
     "engines": {
         "node": "*"

+ 2 - 2
dist/preview release/materialsLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-materials",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.2.0-beta.14",
+    "version": "4.2.0-rc.2",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.2.0-beta.14"
+        "babylonjs": "4.2.0-rc.2"
     },
     "engines": {
         "node": "*"

+ 72 - 8
dist/preview release/nodeEditor/babylon.nodeEditor.d.ts

@@ -262,7 +262,7 @@ declare module NODEEDITOR {
         private _expandBottom;
         dispose(): void;
         private serializePortData;
-        serialize(): IFrameData;
+        serialize(saveCollapsedState: boolean): IFrameData;
         export(): void;
         static Parse(serializationData: IFrameData, canvas: GraphCanvasComponent, map?: {
             [key: number]: number;
@@ -324,6 +324,7 @@ declare module NODEEDITOR {
 declare module NODEEDITOR {
     export interface IGraphCanvasComponentProps {
         globalState: GlobalState;
+        onEmitNewBlock: (block: BABYLON.NodeMaterialBlock) => GraphNode;
     }
     export type FramePortData = {
         frame: GraphFrame;
@@ -552,20 +553,83 @@ declare module NODEEDITOR {
     }
 }
 declare module NODEEDITOR {
+    export interface IColorComponentEntryProps {
+        value: number;
+        label: string;
+        max?: number;
+        min?: number;
+        onChange: (value: number) => void;
+    }
+    export class ColorComponentEntry extends React.Component<IColorComponentEntryProps> {
+        constructor(props: IColorComponentEntryProps);
+        updateValue(valueString: string): void;
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    export interface IHexColorProps {
+        value: string;
+        expectedLength: number;
+        onChange: (value: string) => void;
+    }
+    export class HexColor extends React.Component<IHexColorProps, {
+        hex: string;
+    }> {
+        constructor(props: IHexColorProps);
+        shouldComponentUpdate(nextProps: IHexColorProps, nextState: {
+            hex: string;
+        }): boolean;
+        updateHexValue(valueString: string): void;
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    /**
+     * Interface used to specify creation options for color picker
+     */
+    export interface IColorPickerProps {
+        color: BABYLON.Color3 | BABYLON.Color4;
+        debugMode?: boolean;
+        onColorChanged?: (color: BABYLON.Color3 | BABYLON.Color4) => void;
+    }
+    /**
+     * Interface used to specify creation options for color picker
+     */
+    export interface IColorPickerState {
+        color: BABYLON.Color3;
+        alpha: number;
+    }
+    /**
+     * Class used to create a color picker
+     */
+    export class ColorPicker extends React.Component<IColorPickerProps, IColorPickerState> {
+        private _saturationRef;
+        private _hueRef;
+        private _isSaturationPointerDown;
+        private _isHuePointerDown;
+        constructor(props: IColorPickerProps);
+        onSaturationPointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
+        onSaturationPointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
+        onSaturationPointerMove(evt: React.PointerEvent<HTMLDivElement>): void;
+        onHuePointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
+        onHuePointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
+        onHuePointerMove(evt: React.PointerEvent<HTMLDivElement>): void;
+        private _evaluateSaturation;
+        private _evaluateHue;
+        componentDidUpdate(): void;
+        raiseOnColorChanged(): void;
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
     export interface IColorPickerComponentProps {
         value: BABYLON.Color4 | BABYLON.Color3;
         onColorChanged: (newOne: string) => void;
         globalState: GlobalState;
-        disableAlpha?: boolean;
     }
     interface IColorPickerComponentState {
         pickerEnabled: boolean;
-        color: {
-            r: number;
-            g: number;
-            b: number;
-            a?: number;
-        };
+        color: BABYLON.Color3 | BABYLON.Color4;
         hex: string;
     }
     export class ColorPickerLineComponent extends React.Component<IColorPickerComponentProps, IColorPickerComponentState> {

File diff ditekan karena terlalu besar
+ 7 - 7
dist/preview release/nodeEditor/babylon.nodeEditor.js


File diff ditekan karena terlalu besar
+ 541 - 8459
dist/preview release/nodeEditor/babylon.nodeEditor.max.js


File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/nodeEditor/babylon.nodeEditor.max.js.map


+ 148 - 16
dist/preview release/nodeEditor/babylon.nodeEditor.module.d.ts

@@ -361,7 +361,7 @@ declare module "babylonjs-node-editor/diagram/graphFrame" {
         private _expandBottom;
         dispose(): void;
         private serializePortData;
-        serialize(): IFrameData;
+        serialize(saveCollapsedState: boolean): IFrameData;
         export(): void;
         static Parse(serializationData: IFrameData, canvas: GraphCanvasComponent, map?: {
             [key: number]: number;
@@ -450,6 +450,7 @@ declare module "babylonjs-node-editor/diagram/graphCanvas" {
     import { FrameNodePort } from "babylonjs-node-editor/diagram/frameNodePort";
     export interface IGraphCanvasComponentProps {
         globalState: GlobalState;
+        onEmitNewBlock: (block: NodeMaterialBlock) => GraphNode;
     }
     export type FramePortData = {
         frame: GraphFrame;
@@ -698,6 +699,79 @@ declare module "babylonjs-node-editor/components/propertyTab/properties/vector2P
         render(): JSX.Element;
     }
 }
+declare module "babylonjs-node-editor/sharedComponents/colorPicker/colorComponentEntry" {
+    import * as React from "react";
+    export interface IColorComponentEntryProps {
+        value: number;
+        label: string;
+        max?: number;
+        min?: number;
+        onChange: (value: number) => void;
+    }
+    export class ColorComponentEntry extends React.Component<IColorComponentEntryProps> {
+        constructor(props: IColorComponentEntryProps);
+        updateValue(valueString: string): void;
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedComponents/colorPicker/hexColor" {
+    import * as React from "react";
+    export interface IHexColorProps {
+        value: string;
+        expectedLength: number;
+        onChange: (value: string) => void;
+    }
+    export class HexColor extends React.Component<IHexColorProps, {
+        hex: string;
+    }> {
+        constructor(props: IHexColorProps);
+        shouldComponentUpdate(nextProps: IHexColorProps, nextState: {
+            hex: string;
+        }): boolean;
+        updateHexValue(valueString: string): void;
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-node-editor/sharedComponents/colorPicker/colorPicker" {
+    import * as React from "react";
+    import { Color3, Color4 } from "babylonjs/Maths/math.color";
+    /**
+     * Interface used to specify creation options for color picker
+     */
+    export interface IColorPickerProps {
+        color: Color3 | Color4;
+        debugMode?: boolean;
+        onColorChanged?: (color: Color3 | Color4) => void;
+    }
+    /**
+     * Interface used to specify creation options for color picker
+     */
+    export interface IColorPickerState {
+        color: Color3;
+        alpha: number;
+    }
+    /**
+     * Class used to create a color picker
+     */
+    export class ColorPicker extends React.Component<IColorPickerProps, IColorPickerState> {
+        private _saturationRef;
+        private _hueRef;
+        private _isSaturationPointerDown;
+        private _isHuePointerDown;
+        constructor(props: IColorPickerProps);
+        onSaturationPointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
+        onSaturationPointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
+        onSaturationPointerMove(evt: React.PointerEvent<HTMLDivElement>): void;
+        onHuePointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
+        onHuePointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
+        onHuePointerMove(evt: React.PointerEvent<HTMLDivElement>): void;
+        private _evaluateSaturation;
+        private _evaluateHue;
+        componentDidUpdate(): void;
+        raiseOnColorChanged(): void;
+        render(): JSX.Element;
+    }
+}
 declare module "babylonjs-node-editor/sharedComponents/colorPickerComponent" {
     import * as React from "react";
     import { Color4, Color3 } from 'babylonjs/Maths/math.color';
@@ -706,16 +780,10 @@ declare module "babylonjs-node-editor/sharedComponents/colorPickerComponent" {
         value: Color4 | Color3;
         onColorChanged: (newOne: string) => void;
         globalState: GlobalState;
-        disableAlpha?: boolean;
     }
     interface IColorPickerComponentState {
         pickerEnabled: boolean;
-        color: {
-            r: number;
-            g: number;
-            b: number;
-            a?: number;
-        };
+        color: Color3 | Color4;
         hex: string;
     }
     export class ColorPickerLineComponent extends React.Component<IColorPickerComponentProps, IColorPickerComponentState> {
@@ -2198,7 +2266,7 @@ declare module NODEEDITOR {
         private _expandBottom;
         dispose(): void;
         private serializePortData;
-        serialize(): IFrameData;
+        serialize(saveCollapsedState: boolean): IFrameData;
         export(): void;
         static Parse(serializationData: IFrameData, canvas: GraphCanvasComponent, map?: {
             [key: number]: number;
@@ -2260,6 +2328,7 @@ declare module NODEEDITOR {
 declare module NODEEDITOR {
     export interface IGraphCanvasComponentProps {
         globalState: GlobalState;
+        onEmitNewBlock: (block: BABYLON.NodeMaterialBlock) => GraphNode;
     }
     export type FramePortData = {
         frame: GraphFrame;
@@ -2488,20 +2557,83 @@ declare module NODEEDITOR {
     }
 }
 declare module NODEEDITOR {
+    export interface IColorComponentEntryProps {
+        value: number;
+        label: string;
+        max?: number;
+        min?: number;
+        onChange: (value: number) => void;
+    }
+    export class ColorComponentEntry extends React.Component<IColorComponentEntryProps> {
+        constructor(props: IColorComponentEntryProps);
+        updateValue(valueString: string): void;
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    export interface IHexColorProps {
+        value: string;
+        expectedLength: number;
+        onChange: (value: string) => void;
+    }
+    export class HexColor extends React.Component<IHexColorProps, {
+        hex: string;
+    }> {
+        constructor(props: IHexColorProps);
+        shouldComponentUpdate(nextProps: IHexColorProps, nextState: {
+            hex: string;
+        }): boolean;
+        updateHexValue(valueString: string): void;
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
+    /**
+     * Interface used to specify creation options for color picker
+     */
+    export interface IColorPickerProps {
+        color: BABYLON.Color3 | BABYLON.Color4;
+        debugMode?: boolean;
+        onColorChanged?: (color: BABYLON.Color3 | BABYLON.Color4) => void;
+    }
+    /**
+     * Interface used to specify creation options for color picker
+     */
+    export interface IColorPickerState {
+        color: BABYLON.Color3;
+        alpha: number;
+    }
+    /**
+     * Class used to create a color picker
+     */
+    export class ColorPicker extends React.Component<IColorPickerProps, IColorPickerState> {
+        private _saturationRef;
+        private _hueRef;
+        private _isSaturationPointerDown;
+        private _isHuePointerDown;
+        constructor(props: IColorPickerProps);
+        onSaturationPointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
+        onSaturationPointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
+        onSaturationPointerMove(evt: React.PointerEvent<HTMLDivElement>): void;
+        onHuePointerDown(evt: React.PointerEvent<HTMLDivElement>): void;
+        onHuePointerUp(evt: React.PointerEvent<HTMLDivElement>): void;
+        onHuePointerMove(evt: React.PointerEvent<HTMLDivElement>): void;
+        private _evaluateSaturation;
+        private _evaluateHue;
+        componentDidUpdate(): void;
+        raiseOnColorChanged(): void;
+        render(): JSX.Element;
+    }
+}
+declare module NODEEDITOR {
     export interface IColorPickerComponentProps {
         value: BABYLON.Color4 | BABYLON.Color3;
         onColorChanged: (newOne: string) => void;
         globalState: GlobalState;
-        disableAlpha?: boolean;
     }
     interface IColorPickerComponentState {
         pickerEnabled: boolean;
-        color: {
-            r: number;
-            g: number;
-            b: number;
-            a?: number;
-        };
+        color: BABYLON.Color3 | BABYLON.Color4;
         hex: string;
     }
     export class ColorPickerLineComponent extends React.Component<IColorPickerComponentProps, IColorPickerComponentState> {

+ 2 - 2
dist/preview release/nodeEditor/package.json

@@ -4,14 +4,14 @@
     },
     "name": "babylonjs-node-editor",
     "description": "The Babylon.js node material editor.",
-    "version": "4.2.0-beta.14",
+    "version": "4.2.0-rc.2",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
     },
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.2.0-beta.14"
+        "babylonjs": "4.2.0-rc.2"
     },
     "files": [
         "babylon.nodeEditor.max.js.map",

+ 1 - 1
dist/preview release/package.json

@@ -7,7 +7,7 @@
     ],
     "name": "babylonjs",
     "description": "Babylon.js is a JavaScript 3D engine based on webgl.",
-    "version": "4.2.0-beta.14",
+    "version": "4.2.0-rc.2",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
dist/preview release/packagesSizeBaseLine.json

@@ -1 +1 @@
-{"thinEngineOnly":119155,"engineOnly":155595,"sceneOnly":522960,"minGridMaterial":672172,"minStandardMaterial":830801}
+{"thinEngineOnly":119220,"engineOnly":155660,"sceneOnly":523778,"minGridMaterial":673282,"minStandardMaterial":831916}

+ 2 - 2
dist/preview release/postProcessesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-post-process",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.2.0-beta.14",
+    "version": "4.2.0-rc.2",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.2.0-beta.14"
+        "babylonjs": "4.2.0-rc.2"
     },
     "engines": {
         "node": "*"

+ 2 - 2
dist/preview release/proceduralTexturesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-procedural-textures",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "4.2.0-beta.14",
+    "version": "4.2.0-rc.2",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,7 +28,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.2.0-beta.14"
+        "babylonjs": "4.2.0-rc.2"
     },
     "engines": {
         "node": "*"

+ 2 - 1
dist/preview release/serializers/babylonjs.serializers.d.ts

@@ -1250,8 +1250,9 @@ declare module BABYLON {
         * @param fileName changes the downloads fileName.
         * @param binary changes the STL to a binary type.
         * @param isLittleEndian toggle for binary type exporter.
+        * @param doNotBakeTransform toggle if meshes transforms should be baked or not.
         * @returns the STL as UTF8 string
         */
-        static CreateSTL(meshes: Mesh[], download?: boolean, fileName?: string, binary?: boolean, isLittleEndian?: boolean): any;
+        static CreateSTL(meshes: Mesh[], download?: boolean, fileName?: string, binary?: boolean, isLittleEndian?: boolean, doNotBakeTransform?: boolean): any;
     }
 }

+ 6 - 2
dist/preview release/serializers/babylonjs.serializers.js

@@ -5813,14 +5813,16 @@ var STLExport = /** @class */ (function () {
     * @param fileName changes the downloads fileName.
     * @param binary changes the STL to a binary type.
     * @param isLittleEndian toggle for binary type exporter.
+    * @param doNotBakeTransform toggle if meshes transforms should be baked or not.
     * @returns the STL as UTF8 string
     */
-    STLExport.CreateSTL = function (meshes, download, fileName, binary, isLittleEndian) {
+    STLExport.CreateSTL = function (meshes, download, fileName, binary, isLittleEndian, doNotBakeTransform) {
         //Binary support adapted from https://gist.github.com/paulkaplan/6d5f0ab2c7e8fdc68a61
         if (download === void 0) { download = true; }
         if (fileName === void 0) { fileName = 'stlmesh'; }
         if (binary === void 0) { binary = false; }
         if (isLittleEndian === void 0) { isLittleEndian = true; }
+        if (doNotBakeTransform === void 0) { doNotBakeTransform = false; }
         var getFaceData = function (indices, vertices, i) {
             var id = [indices[i] * 3, indices[i + 1] * 3, indices[i + 2] * 3];
             var v = [
@@ -5863,7 +5865,9 @@ var STLExport = /** @class */ (function () {
         }
         for (var i = 0; i < meshes.length; i++) {
             var mesh = meshes[i];
-            mesh.bakeCurrentTransformIntoVertices();
+            if (!doNotBakeTransform) {
+                mesh.bakeCurrentTransformIntoVertices();
+            }
             var vertices = mesh.getVerticesData(babylonjs_Meshes_buffer__WEBPACK_IMPORTED_MODULE_0__["VertexBuffer"].PositionKind) || [];
             var indices = mesh.getIndices() || [];
             for (var i_1 = 0; i_1 < indices.length; i_1 += 3) {

File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.js.map


File diff ditekan karena terlalu besar
+ 1 - 1
dist/preview release/serializers/babylonjs.serializers.min.js


+ 4 - 2
dist/preview release/serializers/babylonjs.serializers.module.d.ts

@@ -1342,9 +1342,10 @@ declare module "babylonjs-serializers/stl/stlSerializer" {
         * @param fileName changes the downloads fileName.
         * @param binary changes the STL to a binary type.
         * @param isLittleEndian toggle for binary type exporter.
+        * @param doNotBakeTransform toggle if meshes transforms should be baked or not.
         * @returns the STL as UTF8 string
         */
-        static CreateSTL(meshes: Mesh[], download?: boolean, fileName?: string, binary?: boolean, isLittleEndian?: boolean): any;
+        static CreateSTL(meshes: Mesh[], download?: boolean, fileName?: string, binary?: boolean, isLittleEndian?: boolean, doNotBakeTransform?: boolean): any;
     }
 }
 declare module "babylonjs-serializers/stl/index" {
@@ -2626,8 +2627,9 @@ declare module BABYLON {
         * @param fileName changes the downloads fileName.
         * @param binary changes the STL to a binary type.
         * @param isLittleEndian toggle for binary type exporter.
+        * @param doNotBakeTransform toggle if meshes transforms should be baked or not.
         * @returns the STL as UTF8 string
         */
-        static CreateSTL(meshes: Mesh[], download?: boolean, fileName?: string, binary?: boolean, isLittleEndian?: boolean): any;
+        static CreateSTL(meshes: Mesh[], download?: boolean, fileName?: string, binary?: boolean, isLittleEndian?: boolean, doNotBakeTransform?: boolean): any;
     }
 }

+ 3 - 3
dist/preview release/serializers/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-serializers",
     "description": "The Babylon.js serializers library is an extension you can use to serialize Babylon scenes.",
-    "version": "4.2.0-beta.14",
+    "version": "4.2.0-rc.2",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -28,8 +28,8 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs": "4.2.0-beta.14",
-        "babylonjs-gltf2interface": "4.2.0-beta.14"
+        "babylonjs": "4.2.0-rc.2",
+        "babylonjs-gltf2interface": "4.2.0-rc.2"
     },
     "engines": {
         "node": "*"

+ 15 - 0
dist/preview release/uiControls/babylon.uiControls.d.ts

@@ -0,0 +1,15 @@
+/// <reference types="react" />
+declare module UICONTROLS {
+    /**
+     * Interface used to specify creation options for color picker
+     */
+    export interface IColorPickerProps {
+    }
+    /**
+     * Class used to create a color picker
+     */
+    export class ColorPicker extends React.Component<IColorPickerProps> {
+        constructor(props: IColorPickerProps);
+        render(): JSX.Element;
+    }
+}

File diff ditekan karena terlalu besar
+ 29 - 0
dist/preview release/uiControls/babylon.uiControls.js


File diff ditekan karena terlalu besar
+ 2650 - 0
dist/preview release/uiControls/babylon.uiControls.max.js


File diff ditekan karena terlalu besar
+ 1 - 0
dist/preview release/uiControls/babylon.uiControls.max.js.map


+ 40 - 0
dist/preview release/uiControls/babylon.uiControls.module.d.ts

@@ -0,0 +1,40 @@
+/// <reference types="react" />
+declare module "babylonjs-ui-controls/colorPicker" {
+    import * as React from "react";
+    /**
+     * Interface used to specify creation options for color picker
+     */
+    export interface IColorPickerProps {
+    }
+    /**
+     * Class used to create a color picker
+     */
+    export class ColorPicker extends React.Component<IColorPickerProps> {
+        constructor(props: IColorPickerProps);
+        render(): JSX.Element;
+    }
+}
+declare module "babylonjs-ui-controls/index" {
+    export * from "babylonjs-ui-controls/colorPicker";
+}
+declare module "babylonjs-ui-controls/legacy/legacy" {
+    export * from "babylonjs-ui-controls/index";
+}
+declare module "babylonjs-ui-controls" {
+    export * from "babylonjs-ui-controls/legacy/legacy";
+}
+/// <reference types="react" />
+declare module UICONTROLS {
+    /**
+     * Interface used to specify creation options for color picker
+     */
+    export interface IColorPickerProps {
+    }
+    /**
+     * Class used to create a color picker
+     */
+    export class ColorPicker extends React.Component<IColorPickerProps> {
+        constructor(props: IColorPickerProps);
+        render(): JSX.Element;
+    }
+}

+ 35 - 0
dist/preview release/uiControls/package.json

@@ -0,0 +1,35 @@
+{
+    "author": {
+        "name": "David CATUHE"
+    },
+    "name": "babylonjs-ui-controls",
+    "description": "The Babylon.js UI controls are a set of react controls used by other editors / tools",
+    "version": "4.2.0-rc.2",
+    "repository": {
+        "type": "git",
+        "url": "https://github.com/BabylonJS/Babylon.js.git"
+    },
+    "main": "babylon.uiControls.min.js",
+    "files": [
+        "babylon.uiControls.js",
+        "babylon.uiControls.js.map",
+        "babylon.uiControls.min.js",
+        "babylon.uiControls.module.d.ts",
+        "readme.md",
+        "package.json"
+    ],
+    "typings": "babylon.uiControls.module.d.ts",
+    "keywords": [
+        "3D",
+        "javascript",
+        "html5",
+        "webgl"
+    ],
+    "license": "Apache-2.0",
+    "dependencies": {
+        "babylonjs": "4.2.0-rc.2"
+    },
+    "engines": {
+        "node": "*"
+    }
+}

+ 1 - 0
dist/preview release/uiControls/readme-es6.md

@@ -0,0 +1 @@
+UI controls es6

+ 1 - 0
dist/preview release/uiControls/readme.md

@@ -0,0 +1 @@
+UI controls

File diff ditekan karena terlalu besar
+ 410 - 112
dist/preview release/viewer/babylon.module.d.ts


File diff ditekan karena terlalu besar
+ 74 - 74
dist/preview release/viewer/babylon.viewer.js


File diff ditekan karena terlalu besar
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


+ 78 - 127
dist/preview release/viewer/babylonjs.loaders.module.d.ts

@@ -34,22 +34,16 @@ declare module "babylonjs-loaders/glTF/glTFFileLoader" {
     import { Nullable } from "babylonjs/types";
     import { Observable } from "babylonjs/Misc/observable";
     import { Camera } from "babylonjs/Cameras/camera";
-    import { AnimationGroup } from "babylonjs/Animations/animationGroup";
-    import { Skeleton } from "babylonjs/Bones/skeleton";
-    import { IParticleSystem } from "babylonjs/Particles/IParticleSystem";
     import { BaseTexture } from "babylonjs/Materials/Textures/baseTexture";
     import { Material } from "babylonjs/Materials/material";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
-    import { ISceneLoaderPluginFactory, ISceneLoaderPlugin, ISceneLoaderPluginAsync, ISceneLoaderProgressEvent, ISceneLoaderPluginExtensions } from "babylonjs/Loading/sceneLoader";
+    import { ISceneLoaderPluginFactory, ISceneLoaderPlugin, ISceneLoaderPluginAsync, ISceneLoaderProgressEvent, ISceneLoaderPluginExtensions, ISceneLoaderAsyncResult } from "babylonjs/Loading/sceneLoader";
     import { AssetContainer } from "babylonjs/assetContainer";
     import { Scene, IDisposable } from "babylonjs/scene";
     import { WebRequest } from "babylonjs/Misc/webRequest";
     import { IFileRequest } from "babylonjs/Misc/fileRequest";
     import { IDataBuffer } from 'babylonjs/Misc/dataReader';
-    import { Light } from 'babylonjs/Lights/light';
-    import { TransformNode } from 'babylonjs/Meshes/transformNode';
     import { RequestFileError } from 'babylonjs/Misc/fileTools';
-    import { Geometry } from 'babylonjs/Meshes/geometry';
     /**
      * Mode that determines the coordinate system to use.
      */
@@ -129,19 +123,9 @@ declare module "babylonjs-loaders/glTF/glTFFileLoader" {
         COMPLETE = 2
     }
     /** @hidden */
-    export interface IImportMeshAsyncOutput {
-        meshes: AbstractMesh[];
-        geometries: Geometry[];
-        particleSystems: IParticleSystem[];
-        skeletons: Skeleton[];
-        animationGroups: AnimationGroup[];
-        lights: Light[];
-        transformNodes: TransformNode[];
-    }
-    /** @hidden */
     export interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<IImportMeshAsyncOutput>;
+        importMeshAsync: (meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<ISceneLoaderAsyncResult>;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<void>;
     }
     /**
@@ -343,12 +327,7 @@ declare module "babylonjs-loaders/glTF/glTFFileLoader" {
         /** @hidden */
         readFile(scene: Scene, file: File, onSuccess: (data: any) => void, onProgress?: (ev: ISceneLoaderProgressEvent) => any, useArrayBuffer?: boolean, onError?: (error: any) => void): IFileRequest;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<{
-            meshes: AbstractMesh[];
-            particleSystems: IParticleSystem[];
-            skeletons: Skeleton[];
-            animationGroups: AnimationGroup[];
-        }>;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /** @hidden */
         loadAsync(scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         /** @hidden */
@@ -891,9 +870,9 @@ declare module "babylonjs-loaders/glTF/1.0/glTFLoader" {
     import { Nullable } from "babylonjs/types";
     import { Material } from "babylonjs/Materials/material";
     import { Texture } from "babylonjs/Materials/Textures/texture";
-    import { ISceneLoaderProgressEvent } from "babylonjs/Loading/sceneLoader";
+    import { ISceneLoaderAsyncResult, ISceneLoaderProgressEvent } from "babylonjs/Loading/sceneLoader";
     import { Scene } from "babylonjs/scene";
-    import { IGLTFLoader, GLTFLoaderState, IGLTFLoaderData, IImportMeshAsyncOutput } from "babylonjs-loaders/glTF/glTFFileLoader";
+    import { IGLTFLoader, GLTFLoaderState, IGLTFLoaderData } from "babylonjs-loaders/glTF/glTFFileLoader";
     /**
     * Implementation of the base glTF spec
     * @hidden
@@ -928,7 +907,7 @@ declare module "babylonjs-loaders/glTF/1.0/glTFLoader" {
         * @param onProgress event that fires when loading progress has occured
         * @returns a promise containg the loaded meshes, particles, skeletons and animations
         */
-        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<IImportMeshAsyncOutput>;
+        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<ISceneLoaderAsyncResult>;
         private _loadAsync;
         /**
         * Imports all objects from a loaded gltf file and adds them to the scene
@@ -1403,12 +1382,12 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
     import { TransformNode } from "babylonjs/Meshes/transformNode";
     import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
     import { Mesh } from "babylonjs/Meshes/mesh";
-    import { ISceneLoaderProgressEvent } from "babylonjs/Loading/sceneLoader";
+    import { ISceneLoaderAsyncResult, ISceneLoaderProgressEvent } from "babylonjs/Loading/sceneLoader";
     import { Scene } from "babylonjs/scene";
     import { IProperty } from "babylonjs-gltf2interface";
     import { IGLTF, ISampler, INode, IScene, IMesh, IAccessor, ICamera, IAnimation, IAnimationChannel, IBufferView, IMaterial, ITextureInfo, ITexture, IImage, IMeshPrimitive, IArrayItem as IArrItem } from "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces";
     import { IGLTFLoaderExtension } from "babylonjs-loaders/glTF/2.0/glTFLoaderExtension";
-    import { IGLTFLoader, GLTFFileLoader, GLTFLoaderState, IGLTFLoaderData, IImportMeshAsyncOutput } from "babylonjs-loaders/glTF/glTFFileLoader";
+    import { IGLTFLoader, GLTFFileLoader, GLTFLoaderState, IGLTFLoaderData } from "babylonjs-loaders/glTF/glTFFileLoader";
     import { IAnimatable } from 'babylonjs/Animations/animatable.interface';
     import { IDataBuffer } from 'babylonjs/Misc/dataReader';
     import { Light } from 'babylonjs/Lights/light';
@@ -1500,7 +1479,7 @@ declare module "babylonjs-loaders/glTF/2.0/glTFLoader" {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<IImportMeshAsyncOutput>;
+        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /** @hidden */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         private _loadAsync;
@@ -2214,6 +2193,39 @@ declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_transmission
         private _loadTransparentPropertiesAsync;
     }
 }
+declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_translucency" {
+    import { Nullable } from "babylonjs/types";
+    import { Material } from "babylonjs/Materials/material";
+    import { IMaterial } from "babylonjs-loaders/glTF/2.0/glTFLoaderInterfaces";
+    import { IGLTFLoaderExtension } from "babylonjs-loaders/glTF/2.0/glTFLoaderExtension";
+    import { GLTFLoader } from "babylonjs-loaders/glTF/2.0/glTFLoader";
+    /**
+     * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1825)
+     * !!! Experimental Extension Subject to Changes !!!
+     */
+    export class KHR_materials_translucency implements IGLTFLoaderExtension {
+        /**
+         * The name of this extension.
+         */
+        readonly name: string;
+        /**
+         * Defines whether this extension is enabled.
+         */
+        enabled: boolean;
+        /**
+         * Defines a number that determines the order the extensions are applied.
+         */
+        order: number;
+        private _loader;
+        /** @hidden */
+        constructor(loader: GLTFLoader);
+        /** @hidden */
+        dispose(): void;
+        /** @hidden */
+        loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>>;
+        private _loadTranslucentPropertiesAsync;
+    }
+}
 declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_mesh_quantization" {
     import { IGLTFLoaderExtension } from "babylonjs-loaders/glTF/2.0/glTFLoaderExtension";
     import { GLTFLoader } from "babylonjs-loaders/glTF/2.0/glTFLoader";
@@ -2286,37 +2298,6 @@ declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_texture_transform" {
         loadTextureInfoAsync(context: string, textureInfo: ITextureInfo, assign: (babylonTexture: BaseTexture) => void): Nullable<Promise<BaseTexture>>;
     }
 }
-declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_xmp" {
-    import { IGLTFLoaderExtension } from "babylonjs-loaders/glTF/2.0/glTFLoaderExtension";
-    import { GLTFLoader } from "babylonjs-loaders/glTF/2.0/glTFLoader";
-    /**
-     * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1553)
-     * !!! Experimental Extension Subject to Changes !!!
-     */
-    export class KHR_xmp implements IGLTFLoaderExtension {
-        /**
-         * The name of this extension.
-         */
-        readonly name: string;
-        /**
-         * Defines whether this extension is enabled.
-         */
-        enabled: boolean;
-        /**
-         * Defines a number that determines the order the extensions are applied.
-         */
-        order: number;
-        private _loader;
-        /** @hidden */
-        constructor(loader: GLTFLoader);
-        /** @hidden */
-        dispose(): void;
-        /**
-         * Called after the loader state changes to LOADING.
-         */
-        onLoading(): void;
-    }
-}
 declare module "babylonjs-loaders/glTF/2.0/Extensions/MSFT_audio_emitter" {
     import { Nullable } from "babylonjs/types";
     import { AnimationGroup } from "babylonjs/Animations/animationGroup";
@@ -2514,10 +2495,10 @@ declare module "babylonjs-loaders/glTF/2.0/Extensions/index" {
     export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_ior";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_variants";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_transmission";
+    export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_translucency";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_mesh_quantization";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_texture_basisu";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_texture_transform";
-    export * from "babylonjs-loaders/glTF/2.0/Extensions/KHR_xmp";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/MSFT_audio_emitter";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/MSFT_lod";
     export * from "babylonjs-loaders/glTF/2.0/Extensions/MSFT_minecraftMesh";
@@ -2579,11 +2560,7 @@ declare module "babylonjs-loaders/OBJ/mtlFileLoader" {
 }
 declare module "babylonjs-loaders/OBJ/objFileLoader" {
     import { Vector2 } from "babylonjs/Maths/math.vector";
-    import { AnimationGroup } from "babylonjs/Animations/animationGroup";
-    import { Skeleton } from "babylonjs/Bones/skeleton";
-    import { IParticleSystem } from "babylonjs/Particles/IParticleSystem";
-    import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
-    import { ISceneLoaderPluginAsync, ISceneLoaderProgressEvent, ISceneLoaderPluginFactory, ISceneLoaderPlugin } from "babylonjs/Loading/sceneLoader";
+    import { ISceneLoaderPluginAsync, ISceneLoaderProgressEvent, ISceneLoaderPluginFactory, ISceneLoaderPlugin, ISceneLoaderAsyncResult } from "babylonjs/Loading/sceneLoader";
     import { AssetContainer } from "babylonjs/assetContainer";
     import { Scene } from "babylonjs/scene";
     /**
@@ -2740,12 +2717,7 @@ declare module "babylonjs-loaders/OBJ/objFileLoader" {
          * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<{
-            meshes: AbstractMesh[];
-            particleSystems: IParticleSystem[];
-            skeletons: Skeleton[];
-            animationGroups: AnimationGroup[];
-        }>;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /**
          * Imports all objects from the loaded OBJ data and adds them to the scene
          * @param scene the scene the objects should be added to
@@ -3012,19 +2984,9 @@ declare module BABYLON {
         COMPLETE = 2
     }
     /** @hidden */
-    export interface IImportMeshAsyncOutput {
-        meshes: AbstractMesh[];
-        geometries: Geometry[];
-        particleSystems: IParticleSystem[];
-        skeletons: Skeleton[];
-        animationGroups: AnimationGroup[];
-        lights: Light[];
-        transformNodes: TransformNode[];
-    }
-    /** @hidden */
     export interface IGLTFLoader extends IDisposable {
         readonly state: Nullable<GLTFLoaderState>;
-        importMeshAsync: (meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<IImportMeshAsyncOutput>;
+        importMeshAsync: (meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<ISceneLoaderAsyncResult>;
         loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string) => Promise<void>;
     }
     /**
@@ -3226,12 +3188,7 @@ declare module BABYLON {
         /** @hidden */
         readFile(scene: Scene, file: File, onSuccess: (data: any) => void, onProgress?: (ev: ISceneLoaderProgressEvent) => any, useArrayBuffer?: boolean, onError?: (error: any) => void): IFileRequest;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<{
-            meshes: AbstractMesh[];
-            particleSystems: IParticleSystem[];
-            skeletons: Skeleton[];
-            animationGroups: AnimationGroup[];
-        }>;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /** @hidden */
         loadAsync(scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         /** @hidden */
@@ -3794,7 +3751,7 @@ declare module BABYLON.GLTF1 {
         * @param onProgress event that fires when loading progress has occured
         * @returns a promise containg the loaded meshes, particles, skeletons and animations
         */
-        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<IImportMeshAsyncOutput>;
+        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void): Promise<ISceneLoaderAsyncResult>;
         private _loadAsync;
         /**
         * Imports all objects from a loaded gltf file and adds them to the scene
@@ -4313,7 +4270,7 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         dispose(): void;
         /** @hidden */
-        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<IImportMeshAsyncOutput>;
+        importMeshAsync(meshesNames: any, scene: Scene, forAssetContainer: boolean, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /** @hidden */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<void>;
         private _loadAsync;
@@ -4959,6 +4916,34 @@ declare module BABYLON.GLTF2.Loader.Extensions {
 }
 declare module BABYLON.GLTF2.Loader.Extensions {
     /**
+     * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1825)
+     * !!! Experimental Extension Subject to Changes !!!
+     */
+    export class KHR_materials_translucency implements IGLTFLoaderExtension {
+        /**
+         * The name of this extension.
+         */
+        readonly name: string;
+        /**
+         * Defines whether this extension is enabled.
+         */
+        enabled: boolean;
+        /**
+         * Defines a number that determines the order the extensions are applied.
+         */
+        order: number;
+        private _loader;
+        /** @hidden */
+        constructor(loader: GLTFLoader);
+        /** @hidden */
+        dispose(): void;
+        /** @hidden */
+        loadMaterialPropertiesAsync(context: string, material: IMaterial, babylonMaterial: Material): Nullable<Promise<void>>;
+        private _loadTranslucentPropertiesAsync;
+    }
+}
+declare module BABYLON.GLTF2.Loader.Extensions {
+    /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization)
      */
     export class KHR_mesh_quantization implements IGLTFLoaderExtension {
@@ -5019,35 +5004,6 @@ declare module BABYLON.GLTF2.Loader.Extensions {
 }
 declare module BABYLON.GLTF2.Loader.Extensions {
     /**
-     * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1553)
-     * !!! Experimental Extension Subject to Changes !!!
-     */
-    export class KHR_xmp implements IGLTFLoaderExtension {
-        /**
-         * The name of this extension.
-         */
-        readonly name: string;
-        /**
-         * Defines whether this extension is enabled.
-         */
-        enabled: boolean;
-        /**
-         * Defines a number that determines the order the extensions are applied.
-         */
-        order: number;
-        private _loader;
-        /** @hidden */
-        constructor(loader: GLTFLoader);
-        /** @hidden */
-        dispose(): void;
-        /**
-         * Called after the loader state changes to LOADING.
-         */
-        onLoading(): void;
-    }
-}
-declare module BABYLON.GLTF2.Loader.Extensions {
-    /**
      * [Specification](https://github.com/najadojo/glTF/tree/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter)
      */
     export class MSFT_audio_emitter implements IGLTFLoaderExtension {
@@ -5390,12 +5346,7 @@ declare module BABYLON {
          * @param fileName Defines the name of the file to load
          * @returns a promise containg the loaded meshes, particles, skeletons and animations
          */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<{
-            meshes: AbstractMesh[];
-            particleSystems: IParticleSystem[];
-            skeletons: Skeleton[];
-            animationGroups: AnimationGroup[];
-        }>;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult>;
         /**
          * Imports all objects from the loaded OBJ data and adds them to the scene
          * @param scene the scene the objects should be added to

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

@@ -10,7 +10,6 @@
 - Added SubSurfaceScattering on PBR materials ([CraigFeldpsar](https://github.com/craigfeldspar) and ([Sebavan](https://github.com/sebavan/)))
 - Added edition of PBR materials, Post processes and Particle fragment shaders in the node material editor ([Popov72](https://github.com/Popov72))
 - Added edition of procedural texture in the node material editor ([Deltakosh](https://github.com/deltakosh))
-- Added Curve editor to manage entity's animations and edit animation groups in Inspector ([pixelspace](https://github.com/devpixelspace))
 - Added support in `ShadowGenerator` for fast fake soft transparent shadows ([Popov72](https://github.com/Popov72))
 - Added support for **thin instances** for faster mesh instances. [Doc](https://doc.babylonjs.com/how_to/how_to_use_thininstances) ([Popov72](https://github.com/Popov72))
 
@@ -45,6 +44,7 @@
 - Force compute world matrix of the newly-attached mesh of a ray helper ([RaananW](https://github.com/RaananW))
 - Allow 180 monoscopic videos on top of the video dome ([#8575](https://github.com/BabylonJS/Babylon.js/issues/8575)) ([RaananW](https://github.com/RaananW))
 - Added `AssetContainerTask` support to `AssetsManager` class ([MackeyK24](https://github.com/MackeyK24))
+- Added `fixedDragMeshBoundsSize` for boundingbox gizmo to size anchors from bounds size ([cedricguillemet](https://github.com/cedricguillemet))
 - Changed DeviceSourceManager getInput contract to no longer return nullable values ([Drigax](https://github.com/drigax))
 - Photo Dome and Video Dome now use the same abstract class and support the same parameters ([#8771](https://github.com/BabylonJS/Babylon.js/issues/8771)) ([RaananW](https://github.com/RaananW))
 - Added `getTransformNodesByTags` support to `Scene` class ([MackeyK24](https://github.com/MackeyK24))
@@ -58,6 +58,7 @@
 - Removed all references to HTML element from cameras' attach and detach control functions ([RaananW](https://github.com/RaananW))
 - Added `boundingBoxRenderer.onResourcesReadyObservable` ([aWeirdo](https://github.com/aWeirdo))
 - Added `copyTools.GenerateBase64StringFromTexture` ([aWeirdo](https://github.com/aWeirdo))
+- Updated `axisScaleGizmo` to follow pointer on drag ([aWeirdo](https://github.com/aWeirdo))
 - Added manual input for sliders on NME and inspector ([msDestiny14](https://github.com/msDestiny14))
 
 ### Engine
@@ -71,6 +72,7 @@
 - Add support for detail maps in both the standard and PBR materials ([Popov72](https://github.com/Popov72))
 - Added abstractMesh method to get all particle systems that use the mesh as an emitter ([PirateJC](https://github.com/PirateJC))
 - Added customization options to VirtualJoystick ([#7398](https://github.com/BabylonJS/Babylon.js/issues/7398)) ([Rockwell15](https://github.com/Rockwell15))
+- Handle meshes with LODs in render target textures (meaning in glow/highlight layers, shadow generators, depth renderer, etc) ([Popov72](https://github.com/Popov72))
 
 ### NME
 
@@ -149,7 +151,6 @@
 - Renamed KHR_mesh_instancing extension to EXT_mesh_gpu_instancing ([#7945](https://github.com/BabylonJS/Babylon.js/issues/7945)) ([drigax](https://github.com/Drigax))
 - Added support for KHR_materials_ior for glTF loader. ([Sebavan](https://github.com/sebavan/))
 - Added support for KHR_materials_specular for glTF loader. ([Sebavan](https://github.com/sebavan/))
-- Added support for KHR_xmp for glTF loader. ([Sebavan](https://github.com/sebavan/))
 - Added support for KHR_materials_variants for glTF loader. ([MiiBond](https://github.com/MiiBond/))
 - Added support for KHR_materials_transmission for glTF loader. ([MiiBond](https://github.com/MiiBond/))
 - Improved progress handling in glTF loader. ([bghgary](https://github.com/bghgary))
@@ -160,6 +161,7 @@
 - Added the `loadAllMaterials` property to the gLTF loader to load materials even if not used by any mesh ([Popov72](https://github.com/Popov72))
 - Added transmission prerender pass when using KHR_materials_transmission ([MiiBond](https://github.com/MiiBond/))
 - Fixed a bug when loading glTF with interleaved animation data. ([bghgary](https://github.com/bghgary))
+- Added support for KHR_materials_translucency for glTF loader. ([MiiBond](https://github.com/MiiBond/))
 
 ### Serializers
 
@@ -167,6 +169,7 @@
 - Added support for glTF Skins to glTF serializer ([Drigax](https://github.com/Drigax))
 - Added support for glTF Morph Target serialization ([Drigax](https://github.com/Drigax))
 - Fixed several bugs in stlSerializer ([aWeirdo](https://github.com/aWeirdo))
+- Added param `doNotBakeTransform` to `stlSerializer.CreateSTL` ([aWeirdo](https://github.com/aWeirdo))
 
 ### Navigation
 
@@ -190,6 +193,7 @@
 - Added `muted` setting to `VideoTexture`, fix autoplay in Chrome ([simonihmig](https://github.com/simonihmig))
 - Added `waveCount` to `WaterMaterial` used to adjust waves count according to the ground's size where the material is applied on ([julien-moreau](https://github.com/julien-moreau))
 - Alpha test `transparencyMode` no-longer requires a diffuse/albedo texture if `opacityTexture` is present ([metaobjects](https://github.com/metaobjects))
+- Added `hasTexture` override in `MultiMaterial` ([Vampiro](https://github.com/vampiro))
 
 ### Meshes
 
@@ -229,10 +233,13 @@
 - Individual post processing can be applied to the XR rig cameras ([#9038](https://github.com/BabylonJS/Babylon.js/issues/9038)) ([RaananW](https://github.com/RaananW))
 - Pointer selection improvements - single/dual hand selection, max ray distance and more ([#7974](https://github.com/BabylonJS/Babylon.js/issues/7974)) ([RaananW](https://github.com/RaananW))
 - Updated Plane Detection API ([RaananW](https://github.com/RaananW))
+- Updated anchor system's promise resolution and API ([#9258](https://github.com/BabylonJS/Babylon.js/issues/9258)) ([RaananW](https://github.com/RaananW))
+- Fixed an issue with teleportation re-attachment ([#9273](https://github.com/BabylonJS/Babylon.js/issues/9273)) ([RaananW](https://github.com/RaananW))
 
 ### Collisions
 
 - Added an option to optimize collision detection performance ([jsdream](https://github.com/jsdream)) - [PR](https://github.com/BabylonJS/Babylon.js/pull/7810)
+- Added support for collisions with unindexed meshes ([#9267](https://github.com/BabylonJS/Babylon.js/issues/9267))([Popov72](https://github.com/Popov72))
 
 ### Animation
 
@@ -272,6 +279,7 @@
 
 - Added support for custom word splitting function for `TextBlock` ([Popov72](https://github.com/Popov72))
 - Added the `fixedRatio` property to the `Control` class ([Popov72](https://github.com/Popov72))
+- Clip multilines by camera near plane when point is attached to a mesh ([cedricguillemet](https://github.com/cedricguillemet))
 
 ### Post Processes
 
@@ -347,6 +355,7 @@
 - Fixed bug in sphereBuilder where top and bottom segments added 6 indices per triangle instead of 3. (use option dedupTopBottomIndices to enable it) ([aWeirdo](https://github.com/aWeirdo))
 - Fixed issue with Babylon scene export of loaded glTF meshes.([Drigax]/(https://github.com/drigax))
 - Fixed an issue with text block wrap and unicode strings (not working in IE11) ([#8822](https://github.com/BabylonJS/Babylon.js/issues/8822)) ([RaananW](https://github.com/RaananW))
+- Fixed an issue with input text and input password and unicode strings (not working in IE11) ([#9242](https://github.com/BabylonJS/Babylon.js/issues/9242)) ([Popov72](https://github.com/Popov72))
 - Fixed an issue with compound initialization that has rotation ([#8744](https://github.com/BabylonJS/Babylon.js/issues/8744)) ([RaananW](https://github.com/RaananW))
 - Fixed an issue in `DeviceSourceManager.getDeviceSources()` where null devices are returned ([Drigax](https://github.com/drigax))
 - Fix issue in glTF2 `_Exporter.createSkinsAsync()` that exported an incorrect joint indexing list ([drigax](https://github.com/drigax))
@@ -362,6 +371,9 @@
 - Take first gamepad connected when attaching camera (and not only XBOX gamepads) ([#9136](https://github.com/BabylonJS/Babylon.js/issues/9136)) ([RaananW](https://github.com/RaananW))
 - Fixed bug in `Mesh.IncreaseVertices` assuming null value if a property didn't exist. ([aWeirdo](https://github.com/aWeirdo))
 - Fix issue when taking a screenshot with multi-cameras using method `CreateScreenshotUsingRenderTarget` ([#9201](https://github.com/BabylonJS/Babylon.js/issues/9201)) ([gabrielheming](https://github.com/gabrielheming))
+- Fix inTangent in animationGroup ([dad72](https://github.com/dad72))
+- Fixed bug in `QuadraticErrorSimplification` not correctly optimizing mesh. ([aWeirdo](https://github.com/aWeirdo))
+- Fixed bug in `ArcRotateCamera` where setting the position would recalculate the alpha value to a value outside the current limits. ([nilss0n](https://github.com/nilss0n))
 
 ## Breaking changes
 
@@ -375,3 +387,5 @@
 - Fix width/height GUI container computation to take into account paddings when `adaptWithToChildren = true` ([Popov72](https://github.com/Popov72))
 - `smoothstep` in NME is now taking any type of parameters for its `value` input. If you use generated code from the NME ("Generate code" button), you may have to move the smoothstep output connection AFTER the input connections ([Popov72](https://github.com/Popov72))
 - `SoundTrack.RemoveSound` and `SoundTrack.AddSound` were renamed to `SoundTrack.removeSound` and `SoundTrack.addSound` ([Deltakosh](https://github.com/deltakosh))
+- `PolygonPoints.add` no longer filters out points that are close to the first point ([bghgary](https://github.com/bghgary))
+- `Material` created with matching names now have auto-incrementing IDs ([Drigax](https://github.com/drigax))

+ 37 - 2
gui/src/2D/advancedDynamicTexture.ts

@@ -135,6 +135,10 @@ export class AdvancedDynamicTexture extends DynamicTexture {
     */
     public premulAlpha = false;
     /**
+     * Gets or sets a boolean indicating that the canvas must be reverted on Y when updating the texture
+     */
+    public applyYInversionOnUpdate = true;
+    /**
     * Gets or sets a number used to scale rendering size (2 means that the texture will be twice bigger).
     * Useful when you want more antialiasing
     */
@@ -549,6 +553,22 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         projectedPosition.scaleInPlace(this.renderScale);
         return new Vector2(projectedPosition.x, projectedPosition.y);
     }
+    /**
+    * Get screen coordinates for a vector3
+    * @param position defines the position to project
+    * @param worldMatrix defines the world matrix to use
+    * @returns the projected position with Z
+    */
+    public getProjectedPositionWithZ(position: Vector3, worldMatrix: Matrix): Vector3 {
+        var scene = this.getScene();
+        if (!scene) {
+            return Vector3.Zero();
+        }
+        var globalViewport = this._getGlobalViewport(scene);
+        var projectedPosition = Vector3.Project(position, worldMatrix, scene.getTransformMatrix(), globalViewport);
+        projectedPosition.scaleInPlace(this.renderScale);
+        return new Vector3(projectedPosition.x, projectedPosition.y, projectedPosition.z);
+    }
     private _checkUpdate(camera: Camera): void {
         if (this._layerToDispose) {
             if ((camera.layerMask & this._layerToDispose.layerMask) === 0) {
@@ -589,7 +609,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         }
         this._isDirty = false;
         this._render();
-        this.update(true, this.premulAlpha);
+        this.update(this.applyYInversionOnUpdate, this.premulAlpha);
     }
 
     private _clearMeasure = new Measure(0, 0, 0, 0);
@@ -807,7 +827,7 @@ export class AdvancedDynamicTexture extends DynamicTexture {
                 var uv = pi.pickInfo.getTextureCoordinates();
                 if (uv) {
                     let size = this.getSize();
-                    this._doPicking(uv.x * size.width, (1.0 - uv.y) * size.height, pi, pi.type, pointerId, pi.event.button);
+                    this._doPicking(uv.x * size.width, (this.applyYInversionOnUpdate ? (1.0 - uv.y) : uv.y) * size.height, pi, pi.type, pointerId, pi.event.button);
                 }
             } else if (pi.type === PointerEventTypes.POINTERUP) {
                 if (this._lastControlDown[pointerId]) {
@@ -920,6 +940,21 @@ export class AdvancedDynamicTexture extends DynamicTexture {
         result.attachToMesh(mesh, supportPointerMove);
         return result;
     }
+
+    /**
+     * Creates a new AdvancedDynamicTexture in projected mode (ie. attached to a mesh) BUT do not create a new material for the mesh. You will be responsible for connecting the texture
+     * @param mesh defines the mesh which will receive the texture
+     * @param width defines the texture width (1024 by default)
+     * @param height defines the texture height (1024 by default)
+     * @param supportPointerMove defines a boolean indicating if the texture must capture move events (true by default)
+     * @param invertY defines if the texture needs to be inverted on the y axis during loading (true by default)
+     * @returns a new AdvancedDynamicTexture
+     */
+    public static CreateForMeshTexture(mesh: AbstractMesh, width = 1024, height = 1024, supportPointerMove = true, invertY?: boolean): AdvancedDynamicTexture {
+        var result = new AdvancedDynamicTexture(mesh.name + " AdvancedDynamicTexture", width, height, mesh.getScene(), true, Texture.TRILINEAR_SAMPLINGMODE, invertY);
+        result.attachToMesh(mesh, supportPointerMove);
+        return result;
+    }
     /**
     * Creates a new AdvancedDynamicTexture in fullscreen mode.
     * In this mode the texture will rely on a layer for its rendering.

+ 1 - 0
gui/src/2D/controls/index.ts

@@ -15,6 +15,7 @@ export * from "./stackPanel";
 export * from "./selector";
 export * from "./scrollViewers/scrollViewer";
 export * from "./textBlock";
+export * from "./textWrapper";
 export * from "./virtualKeyboard";
 export * from "./rectangle";
 export * from "./displayGrid";

+ 6 - 3
gui/src/2D/controls/inputPassword.ts

@@ -1,16 +1,19 @@
 import { InputText } from "./inputText";
 import { _TypeStore } from 'babylonjs/Misc/typeStore';
+import { TextWrapper } from './textWrapper';
 
 /**
  * Class used to create a password control
  */
 export class InputPassword extends InputText {
-    protected _beforeRenderText(text: string): string {
+    protected _beforeRenderText(textWrapper: TextWrapper): TextWrapper {
+        const pwdTextWrapper = new TextWrapper();
         let txt = "";
-        for (let i = 0; i < text.length; i++) {
+        for (let i = 0; i < textWrapper.length; i++) {
             txt += "\u2022";
         }
-        return txt;
+        pwdTextWrapper.text = txt;
+        return pwdTextWrapper;
     }
 }
 _TypeStore.RegisteredTypes["BABYLON.GUI.InputPassword"] = InputPassword;

+ 90 - 77
gui/src/2D/controls/inputText.ts

@@ -10,12 +10,13 @@ import { ValueAndUnit } from "../valueAndUnit";
 import { VirtualKeyboard } from "./virtualKeyboard";
 import { _TypeStore } from 'babylonjs/Misc/typeStore';
 import { Measure } from '../measure';
+import { TextWrapper } from './textWrapper';
 
 /**
  * Class used to create input text control
  */
 export class InputText extends Control implements IFocusableControl {
-    private _text = "";
+    private _textWrapper: TextWrapper;
     private _placeholderText = "";
     private _background = "#222222";
     private _focusedBackground = "#000000";
@@ -291,18 +292,25 @@ export class InputText extends Control implements IFocusableControl {
 
     /** Gets or sets the text displayed in the control */
     public get text(): string {
-        return this._text;
+        return this._textWrapper.text;
     }
 
     public set text(value: string) {
         let valueAsString = value.toString(); // Forcing convertion
 
-        if (this._text === valueAsString) {
+        if (!this._textWrapper) {
+            this._textWrapper = new TextWrapper();
+        }
+
+        if (this._textWrapper.text === valueAsString) {
             return;
         }
-        this._text = valueAsString;
-        this._markAsDirty();
+        this._textWrapper.text = valueAsString;
+        this._textHasChanged();
+    }
 
+    private _textHasChanged(): void {
+        this._markAsDirty();
         this.onTextChangedObservable.notifyObservers(this);
     }
 
@@ -458,12 +466,13 @@ export class InputText extends Control implements IFocusableControl {
                 }
                 break;
             case 8: // BACKSPACE
-                if (this._text && this._text.length > 0) {
+                if (this._textWrapper.text && this._textWrapper.length > 0) {
                     //delete the highlighted text
                     if (this._isTextHighlightOn) {
-                        this.text = this._text.slice(0, this._startHighlightIndex) + this._text.slice(this._endHighlightIndex);
+                        this._textWrapper.removePart(this._startHighlightIndex, this._endHighlightIndex);
+                        this._textHasChanged();
                         this._isTextHighlightOn = false;
-                        this._cursorOffset = this.text.length - this._startHighlightIndex;
+                        this._cursorOffset = this._textWrapper.length - this._startHighlightIndex;
                         this._blinkIsEven = false;
                         if (evt) {
                             evt.preventDefault();
@@ -472,11 +481,12 @@ export class InputText extends Control implements IFocusableControl {
                     }
                     //delete single character
                     if (this._cursorOffset === 0) {
-                        this.text = this._text.substr(0, this._text.length - 1);
+                        this.text = this._textWrapper.substr(0, this._textWrapper.length - 1);
                     } else {
-                        let deletePosition = this._text.length - this._cursorOffset;
+                        let deletePosition = this._textWrapper.length - this._cursorOffset;
                         if (deletePosition > 0) {
-                            this.text = this._text.slice(0, deletePosition - 1) + this._text.slice(deletePosition);
+                            this._textWrapper.removePart(deletePosition - 1, deletePosition);
+                            this._textHasChanged();
                         }
                     }
                 }
@@ -486,21 +496,19 @@ export class InputText extends Control implements IFocusableControl {
                 return;
             case 46: // DELETE
                 if (this._isTextHighlightOn) {
-                    this.text = this._text.slice(0, this._startHighlightIndex) + this._text.slice(this._endHighlightIndex);
-                    let decrementor = (this._endHighlightIndex - this._startHighlightIndex);
-                    while (decrementor > 0 && this._cursorOffset > 0) {
-                        this._cursorOffset--;
-                    }
+                    this._textWrapper.removePart(this._startHighlightIndex, this._endHighlightIndex);
+                    this._textHasChanged();
                     this._isTextHighlightOn = false;
-                    this._cursorOffset = this.text.length - this._startHighlightIndex;
+                    this._cursorOffset = this._textWrapper.length - this._startHighlightIndex;
                     if (evt) {
                         evt.preventDefault();
                     }
                     return;
                 }
-                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);
+                if (this._textWrapper.text && this._textWrapper.length > 0 && this._cursorOffset > 0) {
+                    let deletePosition = this._textWrapper.length - this._cursorOffset;
+                    this._textWrapper.removePart(deletePosition, deletePosition + 1);
+                    this._textHasChanged();
                     this._cursorOffset--;
                 }
                 if (evt) {
@@ -518,15 +526,15 @@ export class InputText extends Control implements IFocusableControl {
                 this._markAsDirty();
                 return;
             case 36: // HOME
-                this._cursorOffset = this._text.length;
+                this._cursorOffset = this._textWrapper.length;
                 this._blinkIsEven = false;
                 this._isTextHighlightOn = false;
                 this._markAsDirty();
                 return;
             case 37: // LEFT
                 this._cursorOffset++;
-                if (this._cursorOffset > this._text.length) {
-                    this._cursorOffset = this._text.length;
+                if (this._cursorOffset > this._textWrapper.length) {
+                    this._cursorOffset = this._textWrapper.length;
                 }
 
                 if (evt && evt.shiftKey) {
@@ -535,16 +543,16 @@ export class InputText extends Control implements IFocusableControl {
                     // shift + ctrl/cmd + <-
                     if (evt.ctrlKey || evt.metaKey) {
                         if (!this._isTextHighlightOn) {
-                            if (this._text.length === this._cursorOffset) {
+                            if (this._textWrapper.length === this._cursorOffset) {
                                 return;
                             }
                             else {
-                                this._endHighlightIndex = this._text.length - this._cursorOffset + 1;
+                                this._endHighlightIndex = this._textWrapper.length - this._cursorOffset + 1;
                             }
                         }
                         this._startHighlightIndex = 0;
-                        this._cursorIndex = this._text.length - this._endHighlightIndex;
-                        this._cursorOffset = this._text.length;
+                        this._cursorIndex = this._textWrapper.length - this._endHighlightIndex;
+                        this._cursorOffset = this._textWrapper.length;
                         this._isTextHighlightOn = true;
                         this._markAsDirty();
                         return;
@@ -552,21 +560,21 @@ export class InputText extends Control implements IFocusableControl {
                     //store the starting point
                     if (!this._isTextHighlightOn) {
                         this._isTextHighlightOn = true;
-                        this._cursorIndex = (this._cursorOffset >= this._text.length) ? this._text.length : this._cursorOffset - 1;
+                        this._cursorIndex = (this._cursorOffset >= this._textWrapper.length) ? this._textWrapper.length : this._cursorOffset - 1;
                     }
                     //if text is already highlighted
                     else if (this._cursorIndex === -1) {
-                        this._cursorIndex = this._text.length - this._endHighlightIndex;
-                        this._cursorOffset = (this._startHighlightIndex === 0) ? this._text.length : this._text.length - this._startHighlightIndex + 1;
+                        this._cursorIndex = this._textWrapper.length - this._endHighlightIndex;
+                        this._cursorOffset = (this._startHighlightIndex === 0) ? this._textWrapper.length : this._textWrapper.length - this._startHighlightIndex + 1;
                     }
                     //set the highlight indexes
                     if (this._cursorIndex < this._cursorOffset) {
-                        this._endHighlightIndex = this._text.length - this._cursorIndex;
-                        this._startHighlightIndex = this._text.length - this._cursorOffset;
+                        this._endHighlightIndex = this._textWrapper.length - this._cursorIndex;
+                        this._startHighlightIndex = this._textWrapper.length - this._cursorOffset;
                     }
                     else if (this._cursorIndex > this._cursorOffset) {
-                        this._endHighlightIndex = this._text.length - this._cursorOffset;
-                        this._startHighlightIndex = this._text.length - this._cursorIndex;
+                        this._endHighlightIndex = this._textWrapper.length - this._cursorOffset;
+                        this._startHighlightIndex = this._textWrapper.length - this._cursorIndex;
                     }
                     else {
                         this._isTextHighlightOn = false;
@@ -575,11 +583,11 @@ export class InputText extends Control implements IFocusableControl {
                     return;
                 }
                 if (this._isTextHighlightOn) {
-                    this._cursorOffset = this._text.length - this._startHighlightIndex;
+                    this._cursorOffset = this._textWrapper.length - this._startHighlightIndex;
                     this._isTextHighlightOn = false;
                 }
                 if (evt && (evt.ctrlKey || evt.metaKey)) {
-                    this._cursorOffset = this.text.length;
+                    this._cursorOffset = this._textWrapper.length;
                     evt.preventDefault();
                 }
                 this._blinkIsEven = false;
@@ -602,12 +610,12 @@ export class InputText extends Control implements IFocusableControl {
                                 return;
                             }
                             else {
-                                this._startHighlightIndex = this._text.length - this._cursorOffset - 1;
+                                this._startHighlightIndex = this._textWrapper.length - this._cursorOffset - 1;
                             }
                         }
-                        this._endHighlightIndex = this._text.length;
+                        this._endHighlightIndex = this._textWrapper.length;
                         this._isTextHighlightOn = true;
-                        this._cursorIndex = this._text.length - this._startHighlightIndex;
+                        this._cursorIndex = this._textWrapper.length - this._startHighlightIndex;
                         this._cursorOffset = 0;
                         this._markAsDirty();
                         return;
@@ -619,17 +627,17 @@ export class InputText extends Control implements IFocusableControl {
                     }
                     //if text is already highlighted
                     else if (this._cursorIndex === -1) {
-                        this._cursorIndex = this._text.length - this._startHighlightIndex;
-                        this._cursorOffset = (this._text.length === this._endHighlightIndex) ? 0 : this._text.length - this._endHighlightIndex - 1;
+                        this._cursorIndex = this._textWrapper.length - this._startHighlightIndex;
+                        this._cursorOffset = (this._textWrapper.length === this._endHighlightIndex) ? 0 : this._textWrapper.length - this._endHighlightIndex - 1;
                     }
                     //set the highlight indexes
                     if (this._cursorIndex < this._cursorOffset) {
-                        this._endHighlightIndex = this._text.length - this._cursorIndex;
-                        this._startHighlightIndex = this._text.length - this._cursorOffset;
+                        this._endHighlightIndex = this._textWrapper.length - this._cursorIndex;
+                        this._startHighlightIndex = this._textWrapper.length - this._cursorOffset;
                     }
                     else if (this._cursorIndex > this._cursorOffset) {
-                        this._endHighlightIndex = this._text.length - this._cursorOffset;
-                        this._startHighlightIndex = this._text.length - this._cursorIndex;
+                        this._endHighlightIndex = this._textWrapper.length - this._cursorOffset;
+                        this._startHighlightIndex = this._textWrapper.length - this._cursorIndex;
                     }
                     else {
                         this._isTextHighlightOn = false;
@@ -638,7 +646,7 @@ export class InputText extends Control implements IFocusableControl {
                     return;
                 }
                 if (this._isTextHighlightOn) {
-                    this._cursorOffset = this._text.length - this._endHighlightIndex;
+                    this._cursorOffset = this._textWrapper.length - this._endHighlightIndex;
                     this._isTextHighlightOn = false;
                 }
                 //ctr + ->
@@ -673,8 +681,9 @@ export class InputText extends Control implements IFocusableControl {
             key = this._currentKey;
             if (this._addKey) {
                 if (this._isTextHighlightOn) {
-                    this.text = this._text.slice(0, this._startHighlightIndex) + key + this._text.slice(this._endHighlightIndex);
-                    this._cursorOffset = this.text.length - (this._startHighlightIndex + 1);
+                    this._textWrapper.removePart(this._startHighlightIndex, this._endHighlightIndex, key);
+                    this._textHasChanged();
+                    this._cursorOffset = this._textWrapper.length - (this._startHighlightIndex + 1);
                     this._isTextHighlightOn = false;
                     this._blinkIsEven = false;
                     this._markAsDirty();
@@ -682,8 +691,9 @@ export class InputText extends Control implements IFocusableControl {
                 else if (this._cursorOffset === 0) {
                     this.text += key;
                 } else {
-                    let insertPosition = this._text.length - this._cursorOffset;
-                    this.text = this._text.slice(0, insertPosition) + key + this._text.slice(insertPosition);
+                    let insertPosition = this._textWrapper.length - this._cursorOffset;
+                    this._textWrapper.removePart(insertPosition, insertPosition, key);
+                    this._textHasChanged();
                 }
             }
         }
@@ -698,12 +708,12 @@ export class InputText extends Control implements IFocusableControl {
             this._cursorIndex = offset;
         } else {
             if (this._cursorIndex < this._cursorOffset) {
-                this._endHighlightIndex = this._text.length - this._cursorIndex;
-                this._startHighlightIndex = this._text.length - this._cursorOffset;
+                this._endHighlightIndex = this._textWrapper.length - this._cursorIndex;
+                this._startHighlightIndex = this._textWrapper.length - this._cursorOffset;
             }
             else if (this._cursorIndex > this._cursorOffset) {
-                this._endHighlightIndex = this._text.length - this._cursorOffset;
-                this._startHighlightIndex = this._text.length - this._cursorIndex;
+                this._endHighlightIndex = this._textWrapper.length - this._cursorOffset;
+                this._startHighlightIndex = this._textWrapper.length - this._cursorIndex;
             }
             else {
                 this._isTextHighlightOn = false;
@@ -717,15 +727,15 @@ export class InputText extends Control implements IFocusableControl {
     /** @hidden */
     private _processDblClick(evt: PointerInfo) {
         //pre-find the start and end index of the word under cursor, speeds up the rendering
-        this._startHighlightIndex = this._text.length - this._cursorOffset;
+        this._startHighlightIndex = this._textWrapper.length - this._cursorOffset;
         this._endHighlightIndex = this._startHighlightIndex;
-        let rWord = /\w+/g, moveLeft, moveRight;
+        let moveLeft, moveRight;
         do {
-            moveRight = this._endHighlightIndex < this._text.length && (this._text[this._endHighlightIndex].search(rWord) !== -1) ? ++this._endHighlightIndex : 0;
-            moveLeft = this._startHighlightIndex > 0 && (this._text[this._startHighlightIndex - 1].search(rWord) !== -1) ? --this._startHighlightIndex : 0;
+            moveRight = this._endHighlightIndex < this._textWrapper.length && this._textWrapper.isWord(this._endHighlightIndex) ? ++this._endHighlightIndex : 0;
+            moveLeft = this._startHighlightIndex > 0 && this._textWrapper.isWord(this._startHighlightIndex - 1) ? --this._startHighlightIndex : 0;
         } while (moveLeft || moveRight);
 
-        this._cursorOffset = this.text.length - this._startHighlightIndex;
+        this._cursorOffset = this._textWrapper.length - this._startHighlightIndex;
         this.onTextHighlightObservable.notifyObservers(this);
 
         this._isTextHighlightOn = true;
@@ -740,8 +750,8 @@ export class InputText extends Control implements IFocusableControl {
         this._isTextHighlightOn = true;
 
         this._startHighlightIndex = 0;
-        this._endHighlightIndex = this._text.length;
-        this._cursorOffset = this._text.length;
+        this._endHighlightIndex = this._textWrapper.length;
+        this._cursorOffset = this._textWrapper.length;
         this._cursorIndex = -1;
         this._markAsDirty();
     }
@@ -772,9 +782,10 @@ export class InputText extends Control implements IFocusableControl {
         if (!this._highlightedText) {
             return;
         }
-        this.text = this._text.slice(0, this._startHighlightIndex) + this._text.slice(this._endHighlightIndex);
+        this._textWrapper.removePart(this._startHighlightIndex, this._endHighlightIndex);
+        this._textHasChanged();
         this._isTextHighlightOn = false;
-        this._cursorOffset = this.text.length - this._startHighlightIndex;
+        this._cursorOffset = this._textWrapper.length - this._startHighlightIndex;
         //when write permission to clipbaord data is denied
         try {
             ev.clipboardData && ev.clipboardData.setData("text/plain", this._highlightedText);
@@ -794,8 +805,9 @@ export class InputText extends Control implements IFocusableControl {
             //get the cached data; returns blank string by default
             data = this._host.clipboardData;
         }
-        let insertPosition = this._text.length - this._cursorOffset;
-        this.text = this._text.slice(0, insertPosition) + data + this._text.slice(insertPosition);
+        let insertPosition = this._textWrapper.length - this._cursorOffset;
+        this._textWrapper.removePart(insertPosition, insertPosition, data);
+        this._textHasChanged();
     }
 
     public _draw(context: CanvasRenderingContext2D, invalidatedRectangle?: Nullable<Measure>): void {
@@ -838,17 +850,18 @@ export class InputText extends Control implements IFocusableControl {
             context.fillStyle = this.color;
         }
 
-        let text = this._beforeRenderText(this._text);
+        let text = this._beforeRenderText(this._textWrapper);
 
-        if (!this._isFocused && !this._text && this._placeholderText) {
-            text = this._placeholderText;
+        if (!this._isFocused && !this._textWrapper.text && this._placeholderText) {
+            text = new TextWrapper();
+            text.text = this._placeholderText;
 
             if (this._placeholderColor) {
                 context.fillStyle = this._placeholderColor;
             }
         }
 
-        this._textWidth = context.measureText(text).width;
+        this._textWidth = context.measureText(text.text).width;
         let marginWidth = this._margin.getValueInPixel(this._host, this._tempParentMeasure.width) * 2;
         if (this._autoStretchWidth) {
             this.width = Math.min(this._maxWidth.getValueInPixel(this._host, this._tempParentMeasure.width), this._textWidth + marginWidth) + "px";
@@ -871,7 +884,7 @@ export class InputText extends Control implements IFocusableControl {
             this._scrollLeft = clipTextLeft;
         }
 
-        context.fillText(text, this._scrollLeft, this._currentMeasure.top + rootY);
+        context.fillText(text.text, this._scrollLeft, this._currentMeasure.top + rootY);
 
         // Cursor
         if (this._isFocused) {
@@ -903,7 +916,7 @@ export class InputText extends Control implements IFocusableControl {
 
             // Render cursor
             if (!this._blinkIsEven) {
-                let cursorOffsetText = this.text.substr(this._text.length - this._cursorOffset);
+                let cursorOffsetText = text.substr(text.length - this._cursorOffset);
                 let cursorOffsetWidth = context.measureText(cursorOffsetText).width;
                 let cursorLeft = this._scrollLeft + this._textWidth - cursorOffsetWidth;
 
@@ -930,16 +943,16 @@ export class InputText extends Control implements IFocusableControl {
             //show the highlighted text
             if (this._isTextHighlightOn) {
                 clearTimeout(this._blinkTimeout);
-                let highlightCursorOffsetWidth = context.measureText(this.text.substring(this._startHighlightIndex)).width;
+                let highlightCursorOffsetWidth = context.measureText(text.substring(this._startHighlightIndex)).width;
                 let highlightCursorLeft = this._scrollLeft + this._textWidth - highlightCursorOffsetWidth;
-                this._highlightedText = this.text.substring(this._startHighlightIndex, this._endHighlightIndex);
-                let width = context.measureText(this.text.substring(this._startHighlightIndex, this._endHighlightIndex)).width;
+                this._highlightedText = text.substring(this._startHighlightIndex, this._endHighlightIndex);
+                let width = context.measureText(text.substring(this._startHighlightIndex, this._endHighlightIndex)).width;
                 if (highlightCursorLeft < clipTextLeft) {
                     width = width - (clipTextLeft - highlightCursorLeft);
                     if (!width) {
                         // when using left arrow on text.length > availableWidth;
                         // assigns the width of the first letter after clipTextLeft
-                        width = context.measureText(this.text.charAt(this.text.length - this._cursorOffset)).width;
+                        width = context.measureText(text.charAt(text.length - this._cursorOffset)).width;
                     }
                     highlightCursorLeft = clipTextLeft;
                 }
@@ -1013,8 +1026,8 @@ export class InputText extends Control implements IFocusableControl {
         super._onPointerUp(target, coordinates, pointerId, buttonIndex, notifyClick);
     }
 
-    protected _beforeRenderText(text: string): string {
-        return text;
+    protected _beforeRenderText(textWrapper: TextWrapper): TextWrapper {
+        return textWrapper;
     }
 
     public dispose() {

+ 8 - 1
gui/src/2D/controls/multiLine.ts

@@ -5,6 +5,7 @@ import { Control } from "./control";
 import { MultiLinePoint } from "../multiLinePoint";
 import { Measure } from "../measure";
 import { _TypeStore } from 'babylonjs/Misc/typeStore';
+import { Vector3 } from "babylonjs/Maths/math.vector";
 
 /**
  * Class used to create multi line control
@@ -193,6 +194,7 @@ export class MultiLine extends Control {
         context.beginPath();
 
         var first: boolean = true; //first index is not necessarily 0
+        var previousPoint: Vector3;
 
         this._points.forEach((point) => {
             if (!point) {
@@ -205,8 +207,13 @@ export class MultiLine extends Control {
                 first = false;
             }
             else {
-                context.lineTo(point._point.x, point._point.y);
+                if (point._point.z < 1 && previousPoint.z < 1) {
+                    context.lineTo(point._point.x, point._point.y);
+                } else {
+                    context.moveTo(point._point.x, point._point.y);
+                }
             }
+            previousPoint = point._point;
         });
 
         context.stroke();

+ 90 - 0
gui/src/2D/controls/textWrapper.ts

@@ -0,0 +1,90 @@
+/** @hidden */
+export class TextWrapper {
+    private _text: string;
+    private _characters: string[] | undefined;
+
+    public get text(): string {
+        return this._characters ? this._characters.join("") : this._text;
+    }
+
+    public set text(txt: string) {
+        this._text = txt;
+        this._characters = Array.from && Array.from(txt);
+    }
+
+    public get length(): number {
+        return this._characters ? this._characters.length : this._text.length;
+    }
+
+    public removePart(idxStart: number, idxEnd: number, insertTxt?: string): void {
+        this._text = this._text.slice(0, idxStart) + (insertTxt ? insertTxt : "") + this._text.slice(idxEnd);
+        if (this._characters) {
+            const newCharacters = insertTxt ? Array.from(insertTxt) : [];
+            this._characters.splice(idxStart, idxEnd - idxStart, ...newCharacters);
+        }
+    }
+
+    public charAt(idx: number): string {
+        return this._characters ? this._characters[idx] : this._text.charAt(idx);
+    }
+
+    public substr(from: number, length?: number): string {
+        if (this._characters) {
+            if (isNaN(from)) {
+                from = 0;
+            } else if (from >= 0) {
+                from = Math.min(from, this._characters.length);
+            } else {
+                from = this._characters.length + Math.max(from, -this._characters.length);
+            }
+            if (length === undefined) {
+                length = this._characters.length - from;
+            } else if (isNaN(length)) {
+                length = 0;
+            } else if (length < 0) {
+                length = 0;
+            }
+            const temp = [];
+            while (--length >= 0) {
+                temp[length] = this._characters[from + length];
+            }
+            return temp.join("");
+        }
+
+        return this._text.substr(from, length);
+    }
+
+    public substring(from: number, to?: number): string {
+        if (this._characters) {
+            if (isNaN(from)) {
+                from = 0;
+            } else if (from > this._characters.length) {
+                from = this._characters.length;
+            } else if (from < 0) {
+                from = 0;
+            }
+            if (to === undefined) {
+                to = this._characters.length;
+            } else if (isNaN(to)) {
+                to = 0;
+            } else if (to > this._characters.length) {
+                to = this._characters.length;
+            } else if (to < 0) {
+                to = 0;
+            }
+            const temp = [];
+            let idx = 0;
+            while (from < to) {
+                temp[idx++] = this._characters[from++];
+            }
+            return temp.join("");
+        }
+
+        return this._text.substring(from, to);
+    }
+
+    public isWord(index: number): boolean {
+        const rWord = /\w/g;
+        return this._characters ? this._characters[index].search(rWord) !== -1 : this._text.search(rWord) !== -1;
+    }
+}

+ 10 - 9
gui/src/2D/multiLinePoint.ts

@@ -1,6 +1,7 @@
 import { Nullable } from "babylonjs/types";
 import { Observer } from "babylonjs/Misc/observable";
-import { Vector2 } from "babylonjs/Maths/math.vector";
+import { Vector3 } from "babylonjs/Maths/math.vector";
+import { Epsilon } from 'babylonjs/Maths/math.constants';
 import { Camera } from "babylonjs/Cameras/camera";
 import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
 
@@ -25,7 +26,7 @@ export class MultiLinePoint {
     private _meshObserver: Nullable<Observer<Camera>>;
 
     /** @hidden */
-    public _point: Vector2;
+    public _point: Vector3;
 
     /**
      * Creates a new MultiLinePoint
@@ -37,7 +38,7 @@ export class MultiLinePoint {
         this._x = new ValueAndUnit(0);
         this._y = new ValueAndUnit(0);
 
-        this._point = new Vector2(0, 0);
+        this._point = new Vector3(0, 0, 0);
     }
 
     /** Gets or sets x coordinate */
@@ -125,21 +126,21 @@ export class MultiLinePoint {
     }
 
     /**
-     * Gets a translation vector
+     * Gets a translation vector with Z component
      * @returns the translation vector
      */
-    public translate(): Vector2 {
+    public translate(): Vector3 {
         this._point = this._translatePoint();
 
         return this._point;
     }
 
-    private _translatePoint(): Vector2 {
+    private _translatePoint(): Vector3 {
         if (this._mesh != null) {
-            return this._multiLine._host.getProjectedPosition(this._mesh.getBoundingInfo().boundingSphere.center, this._mesh.getWorldMatrix());
+            return this._multiLine._host.getProjectedPositionWithZ(this._mesh.getBoundingInfo().boundingSphere.center, this._mesh.getWorldMatrix());
         }
         else if (this._control != null) {
-            return new Vector2(this._control.centerX, this._control.centerY);
+            return new Vector3(this._control.centerX, this._control.centerY, 1. - Epsilon);
         }
         else {
             var host: any = this._multiLine._host as any;
@@ -147,7 +148,7 @@ export class MultiLinePoint {
             var xValue: number = this._x.getValueInPixel(host, Number(host._canvas.width));
             var yValue: number = this._y.getValueInPixel(host, Number(host._canvas.height));
 
-            return new Vector2(xValue, yValue);
+            return new Vector3(xValue, yValue, 1. - Epsilon);
         }
     }
 

+ 35 - 5
inspector/src/components/actionTabs/actionTabs.scss

@@ -972,10 +972,11 @@ $line-padding-left: 2px;
                 }
 
                 .sliderLine {
-                    padding-left: 2px;
+                    padding-left: $line-padding-left;
                     height: 30px;
                     display: grid;
-                    grid-template-columns: 1fr auto;
+                    grid-template-rows: 100%;
+                    grid-template-columns: 1fr 50px;
 
                     .label {
                         grid-column: 1;
@@ -983,12 +984,41 @@ $line-padding-left: 2px;
                         align-items: center;
                     }
 
+                    .withMargins {
+                        margin-left: 5px;
+                    }
+
+                    .floatLine {
+                        padding-left: $line-padding-left;
+                    
+                        .short {
+                            grid-column: 1; 
+                            display: flex;
+                            align-items: center;
+                            
+                            input {
+                                width: 35px;
+                            }
+                            
+                            input::-webkit-outer-spin-button,
+                            input::-webkit-inner-spin-button {
+                              -webkit-appearance: none;
+                              margin: 0;
+                            }
+                
+                            input[type=number] {
+                                -moz-appearance: textfield;
+                            }
+                        }
+                    }  
+
                     .slider {
-                        grid-column: 2;
+                        grid-column: 3;
+                        grid-row: 1;
                         margin-right: 5px;
-                        
+                        width: 90%;
                         display: flex;
-                        align-items: center;
+                        align-items: center;            
 
                         .range {
                             -webkit-appearance: none;

+ 1 - 1
inspector/src/components/actionTabs/lines/color3LineComponent.tsx

@@ -145,7 +145,7 @@ export class Color3LineComponent extends React.Component<IColor3LineComponentPro
                         {this.props.label}
                     </div>
                     <div className="color3">
-                        <ColorPickerLineComponent value={this.state.color} disableAlpha={true} onColorChanged={color => {
+                        <ColorPickerLineComponent value={this.state.color} onColorChanged={color => {
                             this.onChange(color);
                         }} />                             
                     </div>

+ 19 - 43
inspector/src/components/actionTabs/lines/colorPickerComponent.tsx

@@ -1,38 +1,29 @@
 import * as React from "react";
 import { Color4, Color3 } from 'babylonjs/Maths/math.color';
-import { SketchPicker } from 'react-color';
+import { ColorPicker } from '../../controls/colorPicker/colorPicker';
 
 export interface IColorPickerComponentProps {
     value: Color4 | Color3;
     onColorChanged: (newOne: string) => void;
-    disableAlpha?: boolean;
 }
 
 interface IColorPickerComponentState {
     pickerEnabled: boolean;
-    color: {
-        r: number,
-        g: number,
-        b: number,
-        a?: number
-    },
-    hex: string
+    color: Color3 | Color4;
+    hex: string;
 }
 
 export class ColorPickerLineComponent extends React.Component<IColorPickerComponentProps, IColorPickerComponentState> {
-    private _floatRef: React.RefObject<HTMLDivElement>
-    private _floatHostRef: React.RefObject<HTMLDivElement>
+    private _floatRef: React.RefObject<HTMLDivElement>;
+    private _floatHostRef: React.RefObject<HTMLDivElement>;
 
     constructor(props: IColorPickerComponentProps) {
         super(props);
 
-        this.state = {pickerEnabled: false, color: {
-            r: this.props.value.r * 255,
-            g: this.props.value.g * 255,
-            b: this.props.value.b * 255,
-            a: this.props.value instanceof Color4 ? this.props.value.a * 100 : 100,
-        }, hex: this.props.value.toHexString()};
-        
+        this.state = {pickerEnabled: false,
+            color: this.props.value,
+            hex: this.props.value.toHexString()};
+
         this._floatRef = React.createRef();
         this._floatHostRef = React.createRef();
     }
@@ -52,7 +43,7 @@ export class ColorPickerLineComponent extends React.Component<IColorPickerCompon
             top = window.innerHeight - height - 10;
         }
 
-        div.style.top = top + "px";        
+        div.style.top = top + "px";
         div.style.left = host.getBoundingClientRect().left - div.getBoundingClientRect().width + "px";
     }
 
@@ -60,17 +51,11 @@ export class ColorPickerLineComponent extends React.Component<IColorPickerCompon
         let diffProps = nextProps.value.toHexString() !== this.props.value.toHexString();
 
         if (diffProps) {
-            nextState.color =  {
-                r: nextProps.value.r * 255,
-                g: nextProps.value.g * 255,
-                b: nextProps.value.b * 255,
-                a: nextProps.value instanceof Color4 ? nextProps.value.a : 1,
-            };
+            nextState.color =  nextProps.value;
             nextState.hex = nextProps.value.toHexString();
         }
 
         return diffProps
-            || nextProps.disableAlpha !== this.props.disableAlpha 
             || nextState.hex !== this.state.hex
             || nextState.pickerEnabled !== this.state.pickerEnabled;
     }
@@ -88,8 +73,8 @@ export class ColorPickerLineComponent extends React.Component<IColorPickerCompon
 
         return (
             <div className="color-picker">
-                <div className="color-rect"  ref={this._floatHostRef} 
-                    style={{background: this.state.hex}} 
+                <div className="color-rect"  ref={this._floatHostRef}
+                    style={{background: this.state.hex}}
                     onClick={() => this.setState({pickerEnabled: true})}>
 
                 </div>
@@ -103,27 +88,18 @@ export class ColorPickerLineComponent extends React.Component<IColorPickerCompon
                                 this.setState({pickerEnabled: false});
                             }}>
                             <div className="color-picker-float" ref={this._floatRef}>
-                                <SketchPicker color={color} 
-                                    disableAlpha={this.props.disableAlpha}
-                                    onChange={(color) => {
-                                        let hex: string;
-
-                                        if (this.props.disableAlpha) {
-                                            let newColor3 = Color3.FromInts(color.rgb.r, color.rgb.g, color.rgb.b);
-                                            hex = newColor3.toHexString();    
-                                        } else {
-                                            let newColor4 = Color4.FromInts(color.rgb.r, color.rgb.g, color.rgb.b, 255 * (color.rgb.a || 0));
-                                            hex = newColor4.toHexString();   
-                                        }
-                                        this.setState({hex: hex, color: color.rgb});
+                                <ColorPicker color={color}
+                                    onColorChanged={(color: Color3 | Color4) => {
+                                        const hex: string = color.toHexString();
+                                        this.setState({ hex, color });
                                         this.props.onColorChanged(hex);
                                     }}
                                 />
                             </div>
                         </div>
                     </>
-                }                
+                }
             </div>
         );
     }
-}
+}

+ 21 - 3
inspector/src/components/actionTabs/lines/floatLineComponent.tsx

@@ -20,6 +20,8 @@ interface IFloatLineComponentProps {
     useEuler?: boolean;
     min?: number;
     max?: number;
+    smallUI?: boolean;
+    onEnter?: (newValue:number) => void;
 }
 
 export class FloatLineComponent extends React.Component<IFloatLineComponentProps, { value: string }> {
@@ -133,6 +135,8 @@ export class FloatLineComponent extends React.Component<IFloatLineComponentProps
             valueAsNumber = parseFloat(this.state.value);
         }
 
+        let className = this.props.smallUI ? "short": "value";
+
         return (
             <div>
                 {
@@ -141,8 +145,22 @@ export class FloatLineComponent extends React.Component<IFloatLineComponentProps
                         <div className="label">
                             {this.props.label}
                         </div>
-                        <div className="value">
-                            <input type="number" step={this.props.step || this.props.isInteger ? "1" : "0.01"} className="numeric-input" value={this.state.value} onBlur={() => this.unlock()} onFocus={() => this.lock()} onChange={evt => this.updateValue(evt.target.value)} />
+                        <div className={className}>
+                            <input type="number" step={this.props.step || this.props.isInteger ? "1" : "0.01"} className="numeric-input"
+                            onKeyDown={evt => {
+                                if (evt.keyCode !== 13) {
+                                    return;
+                                }
+                                if(this.props.onEnter) {
+                                    this.props.onEnter(this._store);
+                                }
+                            }}
+                            value={this.state.value} onBlur={() => {
+                                this.unlock();
+                                if(this.props.onEnter) {
+                                    this.props.onEnter(this._store);
+                                }
+                            }} onFocus={() => this.lock()} onChange={evt => this.updateValue(evt.target.value)} />
                         </div>
                     </div>
                 }
@@ -153,4 +171,4 @@ export class FloatLineComponent extends React.Component<IFloatLineComponentProps
             </div>
         );
     }
-}
+}

+ 5 - 5
inspector/src/components/actionTabs/lines/quaternionLineComponent.tsx

@@ -6,7 +6,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { faMinus, faPlus } from "@fortawesome/free-solid-svg-icons";
 import { PropertyChangedEvent } from "../../propertyChangedEvent";
 import { Tools } from 'babylonjs/Misc/tools';
-import { SliderLineComponent } from './sliderLineComponent';
+import { FloatLineComponent } from './floatLineComponent';
 
 interface IQuaternionLineComponentProps {
     label: string;
@@ -134,7 +134,7 @@ export class QuaternionLineComponent extends React.Component<IQuaternionLineComp
             <div className="vector3Line">
                 <div className="firstLine">
                     <div className="label">
-                        {this.props.label}
+                        {this.props.label + (" (Using Quaternion)")} 
                     </div>
                     <div className="vector">
                         {
@@ -162,9 +162,9 @@ export class QuaternionLineComponent extends React.Component<IQuaternionLineComp
                 {
                     this.state.isExpanded && this.props.useEuler &&
                     <div className="secondLine">
-                        <SliderLineComponent label="x" minimum={0} maximum={360} step={0.1} directValue={Tools.ToDegrees(euler.x)} onChange={value => this.updateStateEulerX(value)} />
-                        <SliderLineComponent label="y" minimum={0} maximum={360} step={0.1} directValue={Tools.ToDegrees(euler.y)} onChange={value => this.updateStateEulerY(value)} />
-                        <SliderLineComponent label="z" minimum={0} maximum={360} step={0.1} directValue={Tools.ToDegrees(euler.z)} onChange={value => this.updateStateEulerZ(value)} />
+                        <FloatLineComponent label="x" min={0} max={360} target={euler} propertyName='x' onChange={value => {value = Tools.ToDegrees(euler.x); this.updateStateEulerX(value)} } />
+                        <FloatLineComponent label="y" min={0} max={360} target={euler} propertyName='y' onChange={value => {value = Tools.ToDegrees(euler.y); this.updateStateEulerY(value)} } />
+                        <FloatLineComponent label="z" min={0} max={360} target={euler} propertyName='z' onChange={value => {value = Tools.ToDegrees(euler.z); this.updateStateEulerZ(value)} } />
                     </div>
                 }
             </div>

+ 12 - 3
inspector/src/components/actionTabs/lines/sliderLineComponent.tsx

@@ -2,6 +2,7 @@ import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { PropertyChangedEvent } from "../../propertyChangedEvent";
 import { Tools } from 'babylonjs/Misc/tools';
+import { FloatLineComponent } from './floatLineComponent';
 
 interface ISliderLineComponentProps {
     label: string;
@@ -16,6 +17,7 @@ interface ISliderLineComponentProps {
     onInput?: (value: number) => void;    
     onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
     decimalCount?: number;
+    margin?: boolean;
 }
 
 export class SliderLineComponent extends React.Component<ISliderLineComponentProps, { value: number }> {
@@ -104,14 +106,21 @@ export class SliderLineComponent extends React.Component<ISliderLineComponentPro
     }
 
     render() {
-        let decimalCount = this.props.decimalCount !== undefined ? this.props.decimalCount : 2;
+
         return (
             <div className="sliderLine">
-                <div className="label">
+                <div className={this.props.margin ? "label withMargins" : "label"}>
                     {this.props.label}
                 </div>
+                <FloatLineComponent smallUI={true} label="" target={this.state} propertyName="value" min={this.props.minimum} max={this.props.maximum}
+                    onEnter={ () => { 
+                        var changed = this.prepareDataToRead(this.state.value); this.onChange(changed);
+                    }
+                } 
+                onChange={evt => {var changed = this.prepareDataToRead(this.state.value); this.onChange(changed)}} > 
+                </FloatLineComponent>
                 <div className="slider">
-                    {this.state.value ? this.prepareDataToRead(this.state.value).toFixed(decimalCount) : "0"}&nbsp;<input className="range" type="range" step={this.props.step} min={this.prepareDataToRead(this.props.minimum)} max={this.prepareDataToRead(this.props.maximum)} value={this.prepareDataToRead(this.state.value)}
+                    <input className="range" type="range" step={this.props.step} min={this.prepareDataToRead(this.props.minimum)} max={this.prepareDataToRead(this.props.maximum)} value={this.prepareDataToRead(this.state.value)}
                         onInput={evt => this.onInput((evt.target as HTMLInputElement).value)}
                         onChange={evt => this.onChange(evt.target.value)} />
                 </div>

+ 3 - 3
inspector/src/components/actionTabs/lines/vector3LineComponent.tsx

@@ -134,9 +134,9 @@ export class Vector3LineComponent extends React.Component<IVector3LineComponentP
                 {
                     this.state.isExpanded && this.props.useEuler && !this.props.noSlider &&
                     <div className="secondLine">
-                        <SliderLineComponent label="x" minimum={0} maximum={360} step={0.1} directValue={Tools.ToDegrees(this.state.value.x)} onChange={value => this.updateStateX(Tools.ToRadians(value))} />
-                        <SliderLineComponent label="y" minimum={0} maximum={360} step={0.1} directValue={Tools.ToDegrees(this.state.value.y)} onChange={value => this.updateStateY(Tools.ToRadians(value))} />
-                        <SliderLineComponent label="z" minimum={0} maximum={360} step={0.1} directValue={Tools.ToDegrees(this.state.value.z)} onChange={value => this.updateStateZ(Tools.ToRadians(value))} />
+                        <SliderLineComponent  margin={true} label="x" minimum={0} maximum={360} step={0.1} directValue={Tools.ToDegrees(this.state.value.x)} onChange={value => this.updateStateX(Tools.ToRadians(value))} />
+                        <SliderLineComponent  margin={true} label="y" minimum={0} maximum={360} step={0.1} directValue={Tools.ToDegrees(this.state.value.y)} onChange={value => this.updateStateY(Tools.ToRadians(value))} />
+                        <SliderLineComponent  margin={true} label="z" minimum={0} maximum={360} step={0.1} directValue={Tools.ToDegrees(this.state.value.z)} onChange={value => this.updateStateZ(Tools.ToRadians(value))} />
                     </div>
                 }
                 {

+ 1 - 1
inspector/src/components/actionTabs/tabs/gradientStepComponent.tsx

@@ -53,7 +53,7 @@ export class GradientStepComponent extends React.Component<IGradientStepComponen
                     {`#${this.props.lineIndex}`}
                 </div>
                 <div className="color">
-                    <ColorPickerLineComponent value={step.color} disableAlpha={true}
+                    <ColorPickerLineComponent value={step.color}
                             onColorChanged={color => {
                                     this.updateColor(color);
                             }} 

+ 14 - 14
inspector/src/components/actionTabs/tabs/propertyGrids/animations/animationPropertyGridComponent.tsx

@@ -18,8 +18,8 @@ import { Nullable } from "babylonjs/types";
 import { FloatLineComponent } from "../../../lines/floatLineComponent";
 import { TextLineComponent } from "../../../lines/textLineComponent";
 import { IAnimatable } from "babylonjs/Animations/animatable.interface";
-import { AnimationCurveEditorComponent } from "../animations/animationCurveEditorComponent";
-import { PopupComponent } from "../../../../popupComponent";
+// import { AnimationCurveEditorComponent } from "../animations/animationCurveEditorComponent";
+// import { PopupComponent } from "../../../../popupComponent";
 
 interface IAnimationGridComponentProps {
     globalState: GlobalState;
@@ -36,7 +36,7 @@ export class AnimationGridComponent extends React.Component<IAnimationGridCompon
     private _onBeforeRenderObserver: Nullable<Observer<Scene>>;
     private _isPlaying = false;
     private timelineRef: React.RefObject<SliderLineComponent>;
-    private _isCurveEditorOpen = false;
+    // private _isCurveEditorOpen = false;
     private _animationControl = {
         from: 0,
         to: 0,
@@ -131,16 +131,16 @@ export class AnimationGridComponent extends React.Component<IAnimationGridCompon
         }
     }
 
-    onOpenAnimationCurveEditor() {
-        this._isCurveEditorOpen = true;
-    }
+    // onOpenAnimationCurveEditor() {
+    //     this._isCurveEditorOpen = true;
+    // }
 
-    onCloseAnimationCurveEditor(window: Window | null) {
-        this._isCurveEditorOpen = false;
-        if (window !== null) {
-            window.close();
-        }
-    }
+    // onCloseAnimationCurveEditor(window: Window | null) {
+    //     this._isCurveEditorOpen = false;
+    //     if (window !== null) {
+    //         window.close();
+    //     }
+    // }
 
     render() {
         const animatable = this.props.animatable;
@@ -182,7 +182,7 @@ export class AnimationGridComponent extends React.Component<IAnimationGridCompon
                     <>
                         <LineContainerComponent globalState={this.props.globalState} title="ANIMATIONS">
                             <TextLineComponent label="Count" value={animations.length.toString()} />
-                            <ButtonLineComponent label="Edit" onClick={() => this.onOpenAnimationCurveEditor()} />
+                            {/* <ButtonLineComponent label="Edit" onClick={() => this.onOpenAnimationCurveEditor()} />
                             {animations.map((anim, i) => {
                                 return <TextLineComponent key={anim.targetProperty + i} label={"#" + i + " >"} value={anim.targetProperty} />;
                             })}
@@ -191,7 +191,7 @@ export class AnimationGridComponent extends React.Component<IAnimationGridCompon
                                 <PopupComponent id="curve-editor" title="Curve Animation Editor" size={{ width: 1024, height: 512 }} onOpen={(window: Window) => {}} onClose={(window: Window) => this.onCloseAnimationCurveEditor(window)}>
                                     <AnimationCurveEditorComponent scene={this.props.scene} entity={animatableAsAny} lockObject={this.props.lockObject} playOrPause={() => this.playOrPause()} globalState={this.props.globalState} />
                                 </PopupComponent>
-                            )}
+                            )} */}
                         </LineContainerComponent>
                         {animations.length > 0 && (
                             <LineContainerComponent globalState={this.props.globalState} title="ANIMATION GENERAL CONTROL">

+ 14 - 14
inspector/src/components/actionTabs/tabs/propertyGrids/animations/targetedAnimationPropertyGridComponent.tsx

@@ -9,8 +9,8 @@ import { TextLineComponent } from "../../../lines/textLineComponent";
 import { LockObject } from "../lockObject";
 import { GlobalState } from "../../../../globalState";
 import { TextInputLineComponent } from "../../../lines/textInputLineComponent";
-import { PopupComponent } from "../../../../popupComponent";
-import { AnimationCurveEditorComponent } from "../animations/animationCurveEditorComponent";
+// import { PopupComponent } from "../../../../popupComponent";
+// import { AnimationCurveEditorComponent } from "../animations/animationCurveEditorComponent";
 import { AnimationGroup } from "babylonjs/Animations/animationGroup";
 
 interface ITargetedAnimationGridComponentProps {
@@ -23,7 +23,7 @@ interface ITargetedAnimationGridComponentProps {
 }
 
 export class TargetedAnimationGridComponent extends React.Component<ITargetedAnimationGridComponentProps> {
-    private _isCurveEditorOpen: boolean;
+    // private _isCurveEditorOpen: boolean;
     private _animationGroup: AnimationGroup | undefined;
     constructor(props: ITargetedAnimationGridComponentProps) {
         super(props);
@@ -33,16 +33,16 @@ export class TargetedAnimationGridComponent extends React.Component<ITargetedAni
         });
     }
 
-    onOpenAnimationCurveEditor = () => {
-        this._isCurveEditorOpen = true;
-    };
+    // onOpenAnimationCurveEditor = () => {
+    //     this._isCurveEditorOpen = true;
+    // };
 
-    onCloseAnimationCurveEditor = (window: Window | null) => {
-        this._isCurveEditorOpen = false;
-        if (window !== null) {
-            window.close();
-        }
-    };
+    // onCloseAnimationCurveEditor = (window: Window | null) => {
+    //     this._isCurveEditorOpen = false;
+    //     if (window !== null) {
+    //         window.close();
+    //     }
+    // };
 
     playOrPause = () => {
         if (this._animationGroup) {
@@ -80,12 +80,12 @@ export class TargetedAnimationGridComponent extends React.Component<ITargetedAni
                     <TextLineComponent label="Class" value={targetedAnimation.getClassName()} />
                     <TextInputLineComponent lockObject={this.props.lockObject} label="Name" target={targetedAnimation.animation} propertyName="name" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                     {targetedAnimation.target.name && <TextLineComponent label="Target" value={targetedAnimation.target.name} onLink={() => this.props.globalState.onSelectionChangedObservable.notifyObservers(targetedAnimation)} />}
-                    <ButtonLineComponent label="Edit animation" onClick={this.onOpenAnimationCurveEditor} />
+                    {/* <ButtonLineComponent label="Edit animation" onClick={this.onOpenAnimationCurveEditor} />
                     {this._isCurveEditorOpen && (
                         <PopupComponent id="curve-editor" title="Curve Animation Editor" size={{ width: 1024, height: 512 }} onOpen={(window: Window) => {}} onClose={this.onCloseAnimationCurveEditor}>
                             <AnimationCurveEditorComponent scene={this.props.scene} entity={targetedAnimation as any} playOrPause={this.playOrPause} lockObject={this.props.lockObject} globalState={this.props.globalState} />
                         </PopupComponent>
-                    )}
+                    )} */}
                     <ButtonLineComponent label="Dispose" onClick={this.deleteAnimation} />
                 </LineContainerComponent>
             </div>

+ 0 - 85
inspector/src/components/actionTabs/tabs/propertyGrids/commonPropertyGridComponent.tsx

@@ -1,85 +0,0 @@
-import * as React from "react";
-
-import { Observable } from "babylonjs/Misc/observable";
-
-import { PropertyChangedEvent } from "../../../propertyChangedEvent";
-import { LineContainerComponent } from "../../lineContainerComponent";
-import { LockObject } from "./lockObject";
-import { GlobalState } from "../../../globalState";
-import { TextLineComponent } from '../../lines/textLineComponent';
-import { IndentedTextLineComponent } from '../../lines/indentedTextLineComponent';
-
-interface ICommonPropertyGridComponentProps {
-    globalState: GlobalState;
-    host: { metadata: any};
-    lockObject: LockObject;
-    onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
-}
-
-export class CommonPropertyGridComponent extends React.Component<ICommonPropertyGridComponentProps> {
-    constructor(props: ICommonPropertyGridComponentProps) {
-        super(props);
-    }
-
-    renderLevel(jsonObject: any) {
-        let components = [];
-
-        for (var data in jsonObject) {
-            let value = jsonObject[data];
-            let type = Object.prototype.toString.call(value);
-
-            switch(type) {
-                case '[object String]':
-                    components.push(
-                        <TextLineComponent key={data} label={data} ignoreValue={true}/>
-                    );
-                    components.push(
-                        <IndentedTextLineComponent key={data + value} value={value}/>
-                    );
-                    break;
-                case '[object Array]':
-                    components.push(
-                        <TextLineComponent key={data}  label={data} ignoreValue={true}/>
-                    );
-                    for (var entry of value) {
-                        components.push(
-                            <IndentedTextLineComponent key={data + entry} value={entry}/>
-                        );    
-                    }
-                    break;
-                case '[object Object]':
-                        components.push(
-                            <TextLineComponent key={data}  label={data} ignoreValue={true}/>
-                        );
-                        for (var entryKey in value) {
-                            components.push(
-                                <TextLineComponent key={data + entry} label={entryKey} value={value[entryKey]} additionalClass="reduced-opacity"/>
-                            );    
-                        }
-                        break;                    
-            }
-        }
-
-        return components;
-    }
-
-    render() {
-        if (!this.props.host.metadata) {
-            return null;
-        }
-
-        if (!this.props.host.metadata.xmp) {
-            return null;
-        }
-
-        return (
-            <div>
-                <LineContainerComponent globalState={this.props.globalState} title="XMP METADATA">
-                    {
-                        this.renderLevel(this.props.host.metadata.xmp)                        
-                    }
-                </LineContainerComponent>
-            </div>
-        );
-    }
-}

+ 1 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/lights/commonShadowLightPropertyGridComponent.tsx

@@ -40,6 +40,7 @@ export class CommonShadowLightPropertyGridComponent extends React.Component<ICom
         let generator = internals.generatorType === 0 ? new ShadowGenerator(internals.mapSize, light) : new CascadedShadowGenerator(internals.mapSize, light as DirectionalLight);
 
         scene.meshes.forEach((m) => {
+            if (m.infiniteDistance) { return; }
             generator.addShadowCaster(m);
             if (!m.isAnInstance) {
                 m.receiveShadows = true;

+ 16 - 4
inspector/src/components/actionTabs/tabs/propertyGrids/materials/textures/toolBar.tsx

@@ -1,6 +1,7 @@
 import * as React from 'react';
-import { SketchPicker } from 'react-color';
 import { IToolData, IToolType, IMetadata } from './textureEditorComponent';
+import { Color3, Color4 } from 'babylonjs/Maths/math.color';
+import { ColorPicker } from '../../../../../controls/colorPicker/colorPicker';
 
 export interface ITool extends IToolData {
     instance: IToolType;
@@ -36,9 +37,10 @@ export class ToolBar extends React.Component<IToolBarProps, IToolBarState> {
     computeRGBAColor() {
         const opacityInt = Math.floor(this.props.metadata.alpha * 255);
         const opacityHex = opacityInt.toString(16).padStart(2, '0');
-        return `${this.props.metadata.color}${opacityHex}`;
+
+        return Color4.FromHexString(`${this.props.metadata.color}${opacityHex}`);
     }
-    
+
     shouldComponentUpdate(nextProps: IToolBarProps) {
         return (nextProps.tools != this.props.tools || nextProps.activeToolIndex !== this.props.activeToolIndex || nextProps.metadata != this.props.metadata || nextProps.pickerOpen != this.props.pickerOpen);
     }
@@ -76,7 +78,17 @@ export class ToolBar extends React.Component<IToolBarProps, IToolBarState> {
             {
                 this.props.pickerOpen &&
                 <div id='color-picker' ref={this.props.pickerRef}>
-                    <SketchPicker disableAlpha={!this.props.hasAlpha} color={this.computeRGBAColor()}  onChange={color => this.props.setMetadata({color: color.hex, alpha: color.rgb.a})}/>
+                    <ColorPicker
+                        color={this.computeRGBAColor()}
+                        onColorChanged={
+                            (color: Color3 | Color4) => {
+                                const metadata = { color: color.toHexString(true), alpha: (color as unknown as Color4).a};
+                                if (metadata.color !== this.props.metadata.color ||
+                                    metadata.alpha !== this.props.metadata.alpha) {
+                                    this.props.setMetadata(metadata);
+                                }
+                            }
+                        }/>
                 </div>
             }
         </div>;

+ 3 - 5
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/meshPropertyGridComponent.tsx

@@ -30,7 +30,6 @@ import { ButtonLineComponent } from "../../../lines/buttonLineComponent";
 import { TextInputLineComponent } from "../../../lines/textInputLineComponent";
 import { AnimationGridComponent } from "../animations/animationPropertyGridComponent";
 import { RenderingManager } from "babylonjs/Rendering/renderingManager";
-import { CommonPropertyGridComponent } from "../commonPropertyGridComponent";
 import { VariantsPropertyGridComponent } from "../variantsPropertyGridComponent";
 import { HexLineComponent } from "../../../lines/hexLineComponent";
 import { SkeletonViewer } from "babylonjs/Debug/skeletonViewer";
@@ -383,10 +382,10 @@ export class MeshPropertyGridComponent extends React.Component<
             value: -1,
         });
 
-        const targetBoneOptions: ListLineOption[] = mesh.skeleton ? mesh.skeleton.bones.map((bone, idx) => {
+        const targetBoneOptions: ListLineOption[] = mesh.skeleton ? mesh.skeleton.bones.filter((bone) => bone.getIndex() >= 0).sort((bone1, bone2) => bone1.getIndex() - bone2.getIndex()).map((bone, idx) => {
             return {
                 label: bone.name,
-                value: idx,
+                value: bone.getIndex(),
             };
         }) : [];
 
@@ -435,7 +434,6 @@ export class MeshPropertyGridComponent extends React.Component<
                         }}
                     />
                 </LineContainerComponent>
-                <CommonPropertyGridComponent host={mesh} lockObject={this.props.lockObject} globalState={this.props.globalState} />
                 <VariantsPropertyGridComponent host={mesh} lockObject={this.props.lockObject} globalState={this.props.globalState} />
                 <LineContainerComponent globalState={this.props.globalState} title="TRANSFORMS">
                     <Vector3LineComponent label="Position" target={mesh} propertyName="position" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
@@ -548,7 +546,7 @@ export class MeshPropertyGridComponent extends React.Component<
                             target={mesh.reservedDataStore}
                             propertyName="displayBoneIndex"
                             minimum={0}
-                            maximum={mesh.skeleton.bones.length - 1 || 0}
+                            maximum={targetBoneOptions.length - 1 || 0}
                             step={1}
                             onChange={(value) => {
                                 this.onBoneDisplayIndexChange(value);

+ 9 - 11
inspector/src/components/actionTabs/tabs/propertyGrids/meshes/transformNodePropertyGridComponent.tsx

@@ -15,15 +15,14 @@ import { CustomPropertyGridComponent } from '../customPropertyGridComponent';
 import { ButtonLineComponent } from '../../../lines/buttonLineComponent';
 import { TextInputLineComponent } from '../../../lines/textInputLineComponent';
 import { AnimationGridComponent } from '../animations/animationPropertyGridComponent';
-import { CommonPropertyGridComponent } from '../commonPropertyGridComponent';
 import { VariantsPropertyGridComponent } from '../variantsPropertyGridComponent';
 import { Mesh } from 'babylonjs/Meshes/mesh';
 
 interface ITransformNodePropertyGridComponentProps {
     globalState: GlobalState;
-    transformNode: TransformNode,
-    lockObject: LockObject,
-    onPropertyChangedObservable?: Observable<PropertyChangedEvent>
+    transformNode: TransformNode;
+    lockObject: LockObject;
+    onPropertyChangedObservable?: Observable<PropertyChangedEvent>;
 }
 
 export class TransformNodePropertyGridComponent extends React.Component<ITransformNodePropertyGridComponentProps> {
@@ -41,20 +40,19 @@ 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}/>
+                    <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()} />                    
+                    <TextLineComponent label="Class" value={transformNode.getClassName()} />
                     <CheckBoxLineComponent label="IsEnabled" isSelected={() => transformNode.isEnabled()} onSelect={(value) => transformNode.setEnabled(value)} />
                     {
                         transformNode.parent &&
-                        <TextLineComponent label="Parent" value={transformNode.parent.name} onLink={() => this.props.globalState.onSelectionChangedObservable.notifyObservers(transformNode.parent)}/>
-                    }        
+                        <TextLineComponent label="Parent" value={transformNode.parent.name} onLink={() => this.props.globalState.onSelectionChangedObservable.notifyObservers(transformNode.parent)} />
+                    }
                     <ButtonLineComponent label="Dispose" onClick={() => {
                         transformNode.dispose();
                         this.props.globalState.onSelectionChangedObservable.notifyObservers(null);
-                    }} />              
-                </LineContainerComponent>                
-                <CommonPropertyGridComponent host={transformNode} lockObject={this.props.lockObject} globalState={this.props.globalState} />                
+                    }} />
+                </LineContainerComponent>
                 <VariantsPropertyGridComponent host={transformNode as Mesh} lockObject={this.props.lockObject} globalState={this.props.globalState} />
                 <LineContainerComponent globalState={this.props.globalState} title="TRANSFORMATIONS">
                     <Vector3LineComponent label="Position" target={transformNode} propertyName="position" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />

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

@@ -85,7 +85,7 @@ export class ColorGradientStepGridComponent extends React.Component<IColorGradie
                 <div className="color1">
                     <ColorPickerLineComponent value={gradient instanceof Color3Gradient ? gradient.color : gradient.color1} onColorChanged={color => {
                         this.updateColor1(color);
-                    }} disableAlpha={gradient instanceof Color3Gradient}/>
+                    }}/>
                 </div>
                 {
                     this.props.host instanceof ParticleSystem && gradient instanceof ColorGradient &&

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

@@ -128,7 +128,6 @@ export class GLTFComponent extends React.Component<IGLTFComponentProps> {
                     <CheckBoxLineComponent label="MSFT_minecraftMesh" isSelected={() => extensionStates["MSFT_minecraftMesh"].enabled} onSelect={(value) => (extensionStates["MSFT_minecraftMesh"].enabled = value)} />
                     <CheckBoxLineComponent label="MSFT_sRGBFactors" isSelected={() => extensionStates["MSFT_sRGBFactors"].enabled} onSelect={(value) => (extensionStates["MSFT_sRGBFactors"].enabled = value)} />
                     <CheckBoxLineComponent label="MSFT_audio_emitter" isSelected={() => extensionStates["MSFT_audio_emitter"].enabled} onSelect={(value) => (extensionStates["MSFT_audio_emitter"].enabled = value)} />
-                    <CheckBoxLineComponent label="KHR_xmp" isSelected={() => extensionStates["KHR_xmp"].enabled} onSelect={(value) => (extensionStates["KHR_xmp"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_draco_mesh_compression" isSelected={() => extensionStates["KHR_draco_mesh_compression"].enabled} onSelect={(value) => (extensionStates["KHR_draco_mesh_compression"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_mesh_quantization" isSelected={() => extensionStates["KHR_mesh_quantization"].enabled} onSelect={(value) => (extensionStates["KHR_mesh_quantization"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_materials_pbrSpecularGloss..." isSelected={() => extensionStates["KHR_materials_pbrSpecularGlossiness"].enabled} onSelect={(value) => (extensionStates["KHR_materials_pbrSpecularGlossiness"].enabled = value)} />
@@ -139,6 +138,7 @@ export class GLTFComponent extends React.Component<IGLTFComponentProps> {
                     <CheckBoxLineComponent label="KHR_materials_unlit" isSelected={() => extensionStates["KHR_materials_unlit"].enabled} onSelect={(value) => (extensionStates["KHR_materials_unlit"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_materials_variants" isSelected={() => extensionStates["KHR_materials_variants"].enabled} onSelect={(value) => (extensionStates["KHR_materials_variants"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_materials_transmission" isSelected={() => extensionStates["KHR_materials_transmission"].enabled} onSelect={(value) => (extensionStates["KHR_materials_transmission"].enabled = value)} />
+                    <CheckBoxLineComponent label="KHR_materials_translucency" isSelected={() => extensionStates["KHR_materials_translucency"].enabled} onSelect={(value) => (extensionStates["KHR_materials_translucency"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_lights_punctual" isSelected={() => extensionStates["KHR_lights_punctual"].enabled} onSelect={(value) => (extensionStates["KHR_lights_punctual"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_texture_basisu" isSelected={() => extensionStates["KHR_texture_basisu"].enabled} onSelect={(value) => (extensionStates["KHR_texture_basisu"].enabled = value)} />
                     <CheckBoxLineComponent label="KHR_texture_transform" isSelected={() => extensionStates["KHR_texture_transform"].enabled} onSelect={(value) => (extensionStates["KHR_texture_transform"].enabled = value)} />

+ 53 - 0
inspector/src/components/controls/colorPicker/colorComponentEntry.tsx

@@ -0,0 +1,53 @@
+import * as React from "react";
+
+export interface IColorComponentEntryProps {
+    value: number,
+    label: string,
+    max?: number,
+    min?: number,
+    onChange: (value: number) => void
+}
+
+export class ColorComponentEntry extends React.Component<IColorComponentEntryProps> {
+    constructor(props: IColorComponentEntryProps) {
+        super(props);
+    }
+
+    updateValue(valueString: string) {
+        if (/[^0-9\.\-]/g.test(valueString)) {
+            return;
+        }
+
+        let valueAsNumber = parseInt(valueString);
+
+        if (isNaN(valueAsNumber)) {
+            return;
+        }
+        if(this.props.max != undefined && (valueAsNumber > this.props.max)) {
+            valueAsNumber = this.props.max;
+        }
+        if(this.props.min != undefined && (valueAsNumber < this.props.min)) {
+            valueAsNumber = this.props.min;
+        }
+
+        this.props.onChange(valueAsNumber);
+    }
+
+    public render() {
+        return (
+            <div className="color-picker-component">
+                <div className="color-picker-component-value">
+                    <input type="number" step={1} className="numeric-input"
+                        value={this.props.value} 
+                        onChange={(evt) => this.updateValue(evt.target.value)} />
+                </div>                        
+                <div className="color-picker-component-label">
+                    {
+                        this.props.label
+                    }
+                </div>
+            </div>
+        )
+    }
+
+}

+ 181 - 0
inspector/src/components/controls/colorPicker/colorPicker.scss

@@ -0,0 +1,181 @@
+.color-picker-container {
+    width: 320px;
+    height: 300px;
+    background-color: white;
+    display: grid;    
+    grid-template-columns: 100%;
+    grid-template-rows: 50% 50px 60px 40px 1fr;
+    font-family: "acumin-pro-condensed";
+    font-weight: normal;   
+    font-size: 14px;
+    
+    .color-picker-saturation {
+        grid-row: 1;
+        grid-column: 1;
+        display: grid;
+        grid-template-columns: 100%;
+        grid-template-rows: 100%;
+        position: relative;
+        cursor: pointer;
+    
+        .color-picker-saturation-white {
+            grid-row: 1;
+            grid-column: 1;
+
+            background: -webkit-linear-gradient(to right, #fff, rgba(255,255,255,0));
+            background: linear-gradient(to right, #fff, rgba(255,255,255,0));
+        }
+
+        .color-picker-saturation-black {
+            grid-row: 1;
+            grid-column: 1;
+
+            background: -webkit-linear-gradient(to top, #000, rgba(0,0,0,0));
+            background: linear-gradient(to top, #000, rgba(0,0,0,0));
+        }
+
+        .color-picker-saturation-cursor {
+            pointer-events: none;
+            width: 4px;
+            height: 4px;
+            box-shadow: 0 0 0 1.5px #fff, inset 0 0 1px 1px rgba(0,0,0,.3), 0 0 1px 2px rgba(0,0,0,.4);
+            border-radius: 50%;
+            transform: translate(-2px, -2px);
+            position: absolute;
+        }
+    }
+
+    .color-picker-hue {
+        grid-row: 2;
+        grid-column: 1;
+        display: grid;
+        margin: 10px;
+        grid-template-columns: 24% 76%;
+        grid-template-rows: 100%;
+
+        .color-picker-hue-color {
+            grid-row: 1;
+            grid-column: 1;
+            align-self: center;
+            justify-self: center;
+            width: 30px;
+            height: 30px;
+            border-radius: 15px;
+            border: 1px solid black;
+        }
+
+        .color-picker-hue-slider {
+            grid-row: 1;
+            grid-column: 2;
+            align-self: center;
+            height: 16px;
+            position: relative;
+            cursor: pointer;
+            
+            background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0
+                    33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
+            background: -webkit-linear-gradient(to right, #f00 0%, #ff0
+                17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);                
+
+            .color-picker-hue-cursor {
+                pointer-events: none;
+                width: 8px;
+                height: 18px;
+                transform: translate(-4px, -2px);
+                background-color: rgb(248, 248, 248);
+                box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37);
+                position: absolute;
+            }
+        }
+    }
+
+    .color-picker-component {
+        display: grid;
+        margin: 5px;
+        grid-template-columns: 100%;
+        grid-template-rows: 50% 50%;
+
+        .color-picker-component-value {
+            justify-self: center;
+            align-self: center;
+            grid-row: 1;
+            grid-column: 1;
+            margin-bottom: 4px;
+
+            input {
+                width: 50px;
+            }
+        }
+
+        .color-picker-component-label {
+            justify-self: center;
+            align-self: center;
+            grid-row: 2;
+            grid-column: 1;
+            color:black;
+        }
+    }
+
+    .color-picker-rgb {
+        grid-row: 3;
+        grid-column: 1;
+        display: grid;
+        margin: 10px;
+        grid-template-columns: 20% 6.66% 20% 6.66% 20% 6.66% 20%;
+        grid-template-rows: 100%;
+    }
+
+    .red {
+        grid-row: 1;
+        grid-column: 1;
+    }
+
+    .green {
+        grid-row: 1;
+        grid-column: 3;
+    }
+
+    .blue {
+        grid-row: 1;
+        grid-column: 5;
+    }
+
+    .alpha {
+        grid-row: 1;
+        grid-column: 7;
+
+        &.grayed {
+            opacity: 0.5;
+        }
+    }
+
+    .color-picker-hex {
+        grid-row: 4;
+        grid-column: 1;
+        display: grid;       
+        grid-template-columns: 20% 80%;
+        grid-template-rows: 100%;
+
+        .color-picker-hex-label {
+            justify-self: center;
+            align-self: center;
+            grid-row: 1;
+            grid-column: 1;
+            margin-left: 10px;
+            color:black;
+        }
+
+        .color-picker-hex-value {
+            justify-self: left;
+            align-self: center;
+            grid-row: 1;
+            grid-column: 2;
+            margin-left: 10px;
+            margin-right: 10px;
+
+            input {
+                width: 70px;
+            }
+        }
+    }
+}

+ 220 - 0
inspector/src/components/controls/colorPicker/colorPicker.tsx

@@ -0,0 +1,220 @@
+import * as React from "react";
+import { Color3, Color4 } from "babylonjs/Maths/math.color";
+import { ColorComponentEntry } from './colorComponentEntry';
+import { HexColor } from './hexColor';
+
+require("./colorPicker.scss");
+
+/**
+ * Interface used to specify creation options for color picker
+ */
+export interface IColorPickerProps {
+    color: Color3 | Color4,
+    debugMode?: boolean,
+    onColorChanged?: (color: Color3 | Color4) => void
+}
+
+/**
+ * Interface used to specify creation options for color picker
+ */
+export interface IColorPickerState {
+    color: Color3;
+    alpha: number;
+}
+
+/**
+ * Class used to create a color picker
+ */
+export class ColorPicker extends React.Component<IColorPickerProps, IColorPickerState> {
+    private _saturationRef: React.RefObject<HTMLDivElement>;
+    private _hueRef: React.RefObject<HTMLDivElement>;
+    private _isSaturationPointerDown: boolean;
+    private _isHuePointerDown: boolean;
+
+    constructor(props: IColorPickerProps) {
+        super(props);
+        if (this.props.color instanceof Color4) {
+            this.state = {color: new Color3(this.props.color.r, this.props.color.g, this.props.color.b), alpha: this.props.color.a};
+        } else {
+            this.state = {color : this.props.color.clone(), alpha: 1};
+        }
+        this._saturationRef = React.createRef();
+        this._hueRef = React.createRef();
+    }
+
+    onSaturationPointerDown(evt: React.PointerEvent<HTMLDivElement>) {
+        this._evaluateSaturation(evt);
+        this._isSaturationPointerDown = true;
+
+        evt.currentTarget.setPointerCapture(evt.pointerId);
+    }
+    
+    onSaturationPointerUp(evt: React.PointerEvent<HTMLDivElement>) {
+        this._isSaturationPointerDown = false;
+        evt.currentTarget.releasePointerCapture(evt.pointerId);
+    }
+
+    onSaturationPointerMove(evt: React.PointerEvent<HTMLDivElement>) {
+        if (!this._isSaturationPointerDown) {
+            return;
+        }
+        this._evaluateSaturation(evt);
+    }
+
+    onHuePointerDown(evt: React.PointerEvent<HTMLDivElement>) {
+        this._evaluateHue(evt);
+        this._isHuePointerDown = true;
+
+        evt.currentTarget.setPointerCapture(evt.pointerId);
+    }
+    
+    onHuePointerUp(evt: React.PointerEvent<HTMLDivElement>) {
+        this._isHuePointerDown = false;
+        evt.currentTarget.releasePointerCapture(evt.pointerId);
+    }
+
+    onHuePointerMove(evt: React.PointerEvent<HTMLDivElement>) {
+        if (!this._isHuePointerDown) {
+            return;
+        }
+        this._evaluateHue(evt);
+    }
+
+    private _evaluateSaturation(evt: React.PointerEvent<HTMLDivElement>) {
+        let left = evt.nativeEvent.offsetX;
+        let top = evt.nativeEvent.offsetY;
+      
+        const saturation =  Math.min(1, Math.max(0.0001, left / this._saturationRef.current!.clientWidth));
+        const value = Math.min(1, Math.max(0.0001, 1 - (top / this._saturationRef.current!.clientHeight)));
+
+        if (this.props.debugMode) {
+            console.log("Saturation: " + saturation);
+            console.log("Value: " + value);
+        }
+
+        let hsv = this.state.color.toHSV();
+        Color3.HSVtoRGBToRef(hsv.r, saturation, value, this.state.color);
+        this.setState({color: this.state.color});
+    }
+
+    private _evaluateHue(evt: React.PointerEvent<HTMLDivElement>) {
+        let left = evt.nativeEvent.offsetX;
+      
+        const hue = 360 * Math.min(0.9999, Math.max(0.0001, left / this._hueRef.current!.clientWidth));
+
+        if (this.props.debugMode) {
+            console.log("Hue: " + hue);
+        }
+
+        let hsv = this.state.color.toHSV();
+        Color3.HSVtoRGBToRef(hue, Math.max(hsv.g, 0.0001), Math.max(hsv.b, 0.0001), this.state.color);
+        this.setState({color: this.state.color});
+    }
+
+    componentDidUpdate() {
+        this.raiseOnColorChanged();
+    }
+
+    raiseOnColorChanged() {
+        if (!this.props.onColorChanged) {
+            return;
+        }
+
+        if (this.props.color instanceof Color4) {
+            let newColor4 = Color4.FromColor3(this.state.color, this.state.alpha);
+
+            this.props.onColorChanged(newColor4);
+
+            return;
+        }
+
+        this.props.onColorChanged(this.state.color.clone());
+    } 
+
+    public render() {
+        let colorHex = this.state.color.toHexString();
+        let hsv = this.state.color.toHSV();
+        let colorRef = new Color3();
+        Color3.HSVtoRGBToRef(hsv.r, 1, 1, colorRef)
+        let colorHexRef = colorRef.toHexString();
+        let hasAlpha = this.props.color instanceof Color4;
+
+        return (
+            <div className="color-picker-container">
+                <div className="color-picker-saturation"  
+                    onPointerMove={e => this.onSaturationPointerMove(e)}               
+                    onPointerDown={e => this.onSaturationPointerDown(e)}
+                    onPointerUp={e => this.onSaturationPointerUp(e)}
+                    ref={this._saturationRef}
+                    style={{
+                        background: colorHexRef
+                    }}>
+                    <div className="color-picker-saturation-white">
+                    </div>
+                    <div className="color-picker-saturation-black">
+                    </div>
+                    <div className="color-picker-saturation-cursor" style={{
+                        top: `${ -(hsv.b * 100) + 100 }%`,
+                        left: `${ hsv.g * 100 }%`,
+                    }}>
+                    </div>
+                </div>
+                <div className="color-picker-hue">
+                    <div className="color-picker-hue-color" style={{
+                        background: colorHex
+                    }}>
+                    </div>
+                    <div className="color-picker-hue-slider"                    
+                        ref={this._hueRef}
+                        onPointerMove={e => this.onHuePointerMove(e)}               
+                        onPointerDown={e => this.onHuePointerDown(e)}
+                        onPointerUp={e => this.onHuePointerUp(e)}
+                    >                    
+                        <div className="color-picker-hue-cursor" style={{
+                            left: `${ (hsv.r / 360.0) * 100 }%`,
+                            border: `1px solid ` + colorHexRef
+                        }}>                    
+                        </div>
+                    </div>
+                </div>
+                <div className="color-picker-rgb">
+                    <div className="red">
+                        <ColorComponentEntry label="R" min={0} max={255} value={this.state.color.r * 255 | 0} onChange={value => {
+                            this.state.color.r = value / 255.0;
+                            this.forceUpdate();
+                        }}/>
+                    </div>   
+                    <div className="green">
+                        <ColorComponentEntry label="G" min={0} max={255}  value={this.state.color.g * 255 | 0} onChange={value => {
+                            this.state.color.g = value / 255.0;
+                            this.forceUpdate();
+                        }}/>
+                    </div>  
+                    <div className="blue">
+                        <ColorComponentEntry label="B" min={0} max={255}  value={this.state.color.b * 255 | 0} onChange={value => {
+                            this.state.color.b = value / 255.0;
+                            this.forceUpdate();
+                        }}/>
+                    </div>        
+                    <div className={"alpha" + (hasAlpha ? "" : " grayed")}>
+                        <ColorComponentEntry label="A" min={0} max={255} value={this.state.alpha * 255 | 0} onChange={value => {
+                                this.setState({alpha: value / 255.0});
+                                this.forceUpdate();
+                        }}/>
+                    </div>   
+                </div>  
+                <div className="color-picker-hex">
+                    <div className="color-picker-hex-label">
+                        Hex
+                    </div>
+                    <div className="color-picker-hex-value">     
+                        <HexColor expectedLength={6} value={colorHex} onChange={value => {
+                            this.setState({color: Color3.FromHexString(value)});
+                        }}/>            
+                    </div>
+                </div>
+            </div>
+        );
+    }
+}
+

+ 45 - 0
inspector/src/components/controls/colorPicker/hexColor.tsx

@@ -0,0 +1,45 @@
+import * as React from "react";
+
+export interface IHexColorProps {
+    value: string,
+    expectedLength: number,
+    onChange: (value: string) => void
+}
+
+export class HexColor extends React.Component<IHexColorProps, {hex: string}> {
+    constructor(props: IHexColorProps) {
+        super(props);
+
+        this.state = {hex: this.props.value.replace("#", "")}
+    }
+
+    shouldComponentUpdate(nextProps: IHexColorProps, nextState: {hex: string}) {
+        if (nextProps.value!== this.props.value) {
+            nextState.hex = nextProps.value.replace("#", "");
+        }
+
+        return true;
+    }
+
+    updateHexValue(valueString: string) {
+        if (valueString != "" && /^[0-9A-Fa-f]+$/g.test(valueString) == false) {
+            return;
+        }
+    
+        this.setState({hex: valueString});
+
+        if(valueString.length !== this.props.expectedLength) {
+            return;
+        }
+       
+        this.props.onChange("#" + valueString);
+    }
+
+    public render() {
+        return (
+            <input type="string" className="hex-input" value={this.state.hex} 
+                onChange={evt => this.updateHexValue(evt.target.value)}/>   
+        )
+    }
+
+}

+ 1 - 0
inspector/src/components/embedHost/embedHost.scss

@@ -3,6 +3,7 @@
     right: 0px;
     top:0px;
     bottom: 0px;
+    z-index: 10;
 }
 
 #__resizable_base__ {

+ 1 - 1
inspector/src/components/globalState.ts

@@ -33,7 +33,6 @@ export class GlobalState {
         MSFT_minecraftMesh: { enabled: true },
         MSFT_sRGBFactors: { enabled: true },
         MSFT_audio_emitter: { enabled: true },
-        KHR_xmp: { enabled: true },
         KHR_draco_mesh_compression: { enabled: true },
         KHR_mesh_quantization: { enabled: true },
         KHR_materials_pbrSpecularGlossiness: { enabled: true },
@@ -44,6 +43,7 @@ export class GlobalState {
         KHR_materials_unlit: { enabled: true },
         KHR_materials_variants: { enabled: true },
         KHR_materials_transmission: { enabled: true },
+        KHR_materials_translucency: { enabled: true },
         KHR_lights_punctual: { enabled: true },
         KHR_texture_basisu: { enabled: true },
         KHR_texture_transform: { enabled: true },

+ 7 - 7
loaders/src/OBJ/objFileLoader.ts

@@ -4,12 +4,9 @@ import { Color4 } from 'babylonjs/Maths/math.color';
 import { Tools } from "babylonjs/Misc/tools";
 import { VertexData } from "babylonjs/Meshes/mesh.vertexData";
 import { Geometry } from "babylonjs/Meshes/geometry";
-import { AnimationGroup } from "babylonjs/Animations/animationGroup";
-import { Skeleton } from "babylonjs/Bones/skeleton";
-import { IParticleSystem } from "babylonjs/Particles/IParticleSystem";
 import { AbstractMesh } from "babylonjs/Meshes/abstractMesh";
 import { Mesh } from "babylonjs/Meshes/mesh";
-import { SceneLoader, ISceneLoaderPluginAsync, ISceneLoaderProgressEvent, ISceneLoaderPluginFactory, ISceneLoaderPlugin } from "babylonjs/Loading/sceneLoader";
+import { SceneLoader, ISceneLoaderPluginAsync, ISceneLoaderProgressEvent, ISceneLoaderPluginFactory, ISceneLoaderPlugin, ISceneLoaderAsyncResult } from "babylonjs/Loading/sceneLoader";
 
 import { AssetContainer } from "babylonjs/assetContainer";
 import { Scene } from "babylonjs/scene";
@@ -236,14 +233,17 @@ export class OBJFileLoader implements ISceneLoaderPluginAsync, ISceneLoaderPlugi
      * @param fileName Defines the name of the file to load
      * @returns a promise containg the loaded meshes, particles, skeletons and animations
      */
-    public importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<{ meshes: AbstractMesh[], particleSystems: IParticleSystem[], skeletons: Skeleton[], animationGroups: AnimationGroup[] }> {
+    public importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onProgress?: (event: ISceneLoaderProgressEvent) => void, fileName?: string): Promise<ISceneLoaderAsyncResult> {
         //get the meshes from OBJ file
         return this._parseSolid(meshesNames, scene, data, rootUrl).then((meshes) => {
             return {
-                meshes,
+                meshes: meshes,
                 particleSystems: [],
                 skeletons: [],
-                animationGroups: []
+                animationGroups: [],
+                transformNodes: [],
+                geometries: [],
+                lights: []
             };
         });
     }

+ 0 - 0
loaders/src/glTF/1.0/glTFLoader.ts


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini