Просмотр исходного кода

Merge pull request #8502 from BabylonJS/master

Nightly
mergify[bot] 5 лет назад
Родитель
Сommit
8c71dff6c3
50 измененных файлов с 1272 добавлено и 218 удалено
  1. 36 0
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 17 0
      .github/ISSUE_TEMPLATE/feature_request.md
  3. 76 0
      CODE_OF_CONDUCT.md
  4. 4 0
      dist/preview release/babylon.d.ts
  5. 2 2
      dist/preview release/babylon.js
  6. 10 8
      dist/preview release/babylon.max.js
  7. 1 1
      dist/preview release/babylon.max.js.map
  8. 8 0
      dist/preview release/babylon.module.d.ts
  9. 27 0
      dist/preview release/documentation.d.ts
  10. 48 48
      dist/preview release/gui/babylon.gui.js
  11. 1 1
      dist/preview release/gui/babylon.gui.js.map
  12. 6 6
      dist/preview release/inspector/babylon.inspector.bundle.js
  13. 358 106
      dist/preview release/inspector/babylon.inspector.bundle.max.js
  14. 1 1
      dist/preview release/inspector/babylon.inspector.bundle.max.js.map
  15. 44 1
      dist/preview release/inspector/babylon.inspector.d.ts
  16. 93 3
      dist/preview release/inspector/babylon.inspector.module.d.ts
  17. 1 1
      dist/preview release/libktx.js
  18. BIN
      dist/preview release/libktx.wasm
  19. 31 0
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  20. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.js.map
  21. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  22. 31 0
      dist/preview release/loaders/babylon.glTFFileLoader.js
  23. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.js.map
  24. 1 1
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  25. 23 0
      dist/preview release/loaders/babylonjs.loaders.d.ts
  26. 31 0
      dist/preview release/loaders/babylonjs.loaders.js
  27. 1 1
      dist/preview release/loaders/babylonjs.loaders.js.map
  28. 1 1
      dist/preview release/loaders/babylonjs.loaders.min.js
  29. 46 0
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  30. 1 1
      dist/preview release/packagesSizeBaseLine.json
  31. 8 0
      dist/preview release/viewer/babylon.module.d.ts
  32. 5 5
      dist/preview release/viewer/babylon.viewer.js
  33. 2 2
      dist/preview release/viewer/babylon.viewer.max.js
  34. 46 0
      dist/preview release/viewer/babylonjs.loaders.module.d.ts
  35. 1 0
      dist/preview release/what's new.md
  36. 1 1
      inspector/src/components/actionTabs/tabs/propertyGrids/animations/animationPropertyGridComponent.tsx
  37. 1 1
      inspector/src/components/actionTabs/tabs/propertyGrids/animations/targetedAnimationPropertyGridComponent.tsx
  38. 42 5
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/texturePropertyGridComponent.tsx
  39. 156 0
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/textures/textureCanvasManager.ts
  40. 4 0
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/textures/textureEditor.scss
  41. 30 0
      inspector/src/components/actionTabs/tabs/propertyGrids/materials/textures/textureEditorComponent.tsx
  42. 15 5
      inspector/src/components/actionTabs/tabs/propertyGrids/variantsPropertyGridComponent.tsx
  43. 4 0
      inspector/src/components/globalState.ts
  44. 1 1
      inspector/src/components/actionTabs/tabs/propertyGrids/animations/popupComponent.tsx
  45. 35 0
      loaders/src/glTF/2.0/Extensions/KHR_materials_variants.ts
  46. 3 5
      sandbox/public/index-local.html
  47. 4 5
      src/Meshes/mesh.ts
  48. 2 2
      src/Misc/khronosTextureContainer2.ts
  49. 4 0
      src/XR/features/WebXRControllerTeleportation.ts
  50. 6 1
      src/XR/webXREnterExitUI.ts

+ 36 - 0
.github/ISSUE_TEMPLATE/bug_report.md

@@ -0,0 +1,36 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Use Github issues ONLY for validated bugs. PLEASE DISCUSS THEM ON THE FORUM FIRST!**
+
+We have a really active forum to help answering questions (https://forum.babylonjs.com/)
+
+*If you are convinced that you found a bug, please use the following template for your issue:*
+
+**Repro**
+- Bug repro on [playground](https://playground.babylonjs.com):
+- Expected result:
+- Current result:
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+ - OS: [e.g. iOS]
+ - Browser [e.g. chrome, safari]
+ - Version [e.g. 22]
+
+**Smartphone (please complete the following information):**
+ - Device: [e.g. iPhone6]
+ - OS: [e.g. iOS8.1]
+ - Browser [e.g. stock browser, safari]
+ - Version [e.g. 22]
+
+**Additional context**
+Add any other context about the problem here.

+ 17 - 0
.github/ISSUE_TEMPLATE/feature_request.md

@@ -0,0 +1,17 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Discussion**
+You must provide a link to the forum post where the initial discussion happened

+ 76 - 0
CODE_OF_CONDUCT.md

@@ -0,0 +1,76 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, sex characteristics, gender identity and expression,
+level of experience, education, socio-economic status, nationality, personal
+appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. Examples of
+representing a project or community include using an official project e-mail
+address, posting via an official social media account, or acting as an appointed
+representative at an online or offline event. Representation of a project may be
+further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at david@catuhe.com. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. The project team is
+obligated to maintain confidentiality with regard to the reporter of an incident.
+Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
+available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see
+https://www.contributor-covenant.org/faq

+ 4 - 0
dist/preview release/babylon.d.ts

@@ -48149,6 +48149,10 @@ declare module BABYLON {
          * A list of optional features to init the session with
          */
         optionalFeatures?: string[];
+        /**
+         * A list of optional features to init the session with
+         */
+        requiredFeatures?: string[];
     }
     /**
      * UI to allow the user to enter/exit XR mode

Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/babylon.js


+ 10 - 8
dist/preview release/babylon.max.js

@@ -125143,7 +125143,7 @@ var Mesh = /** @class */ (function (_super) {
             var colors = new Array();
             var pstring = new Array(); //lists facet vertex positions (a,b,c) as string "a|b|c"
             var indexPtr = 0; // pointer to next available index value
-            var uniquePositions = new Array(); // unique vertex positions
+            var uniquePositions = {}; // unique vertex positions
             var ptr; // pointer to element in uniquePositions
             var facet;
             for (var i = 0; i < currentIndices.length; i += 3) {
@@ -125158,7 +125158,6 @@ var Mesh = /** @class */ (function (_super) {
                         }
                         pstring[j] += currentPositions[3 * facet[j] + k] + "|";
                     }
-                    pstring[j] = pstring[j].slice(0, -1);
                 }
                 //check facet vertices to see that none are repeated
                 // do not process any facet that has a repeated vertex, ie is a line
@@ -125167,9 +125166,9 @@ var Mesh = /** @class */ (function (_super) {
                     // if not listed add to uniquePositions and set index pointer
                     // if listed use its index in uniquePositions and new index pointer
                     for (var j = 0; j < 3; j++) {
-                        ptr = uniquePositions.indexOf(pstring[j]);
-                        if (ptr < 0) {
-                            uniquePositions.push(pstring[j]);
+                        ptr = uniquePositions[pstring[j]];
+                        if (ptr === undefined) {
+                            uniquePositions[pstring[j]] = indexPtr;
                             ptr = indexPtr++;
                             //not listed so add individual x, y, z coordinates to positions
                             for (var k = 0; k < 3; k++) {
@@ -137865,7 +137864,7 @@ var KhronosTextureContainer2 = /** @class */ (function () {
         var _this = this;
         if (!KhronosTextureContainer2._ModulePromise) {
             KhronosTextureContainer2._ModulePromise = new Promise(function (resolve) {
-                LIBKTX().then(function (module) {
+                LIBKTX({ preinitializedWebGLContext: engine._gl }).then(function (module) {
                     module.GL.makeContextCurrent(module.GL.registerContext(engine._gl, { majorVersion: engine._webGLVersion }));
                     KhronosTextureContainer2._TranscodeFormat = _this._determineTranscodeFormat(module.TranscodeTarget, engine.getCaps());
                     resolve({ module: module });
@@ -137878,7 +137877,7 @@ var KhronosTextureContainer2 = /** @class */ (function () {
             var module = moduleWrapper.module;
             var ktxTexture = new module.ktxTexture(data);
             try {
-                if (ktxTexture.isBasisSupercompressed) {
+                if (ktxTexture.needsTranscoding) {
                     ktxTexture.transcodeBasis(KhronosTextureContainer2._TranscodeFormat, 0);
                 }
                 internalTexture.width = internalTexture.baseWidth = ktxTexture.baseWidth;
@@ -182654,6 +182653,8 @@ var WebXRMotionControllerTeleportation = /** @class */ (function (_super) {
         if (!_super.prototype.attach.call(this)) {
             return false;
         }
+        // Safety reset
+        this._currentTeleportationControllerId = '';
         this._options.xrInput.controllers.forEach(this._attachController);
         this._addNewAttachObserver(this._options.xrInput.onControllerAddedObservable, this._attachController);
         this._addNewAttachObserver(this._options.xrInput.onControllerRemovedObservable, function (controller) {
@@ -182671,6 +182672,7 @@ var WebXRMotionControllerTeleportation = /** @class */ (function (_super) {
             _this._detachController(controllerId);
         });
         this._setTargetMeshVisibility(false);
+        this._currentTeleportationControllerId = '';
         return true;
     };
     WebXRMotionControllerTeleportation.prototype.dispose = function () {
@@ -186504,7 +186506,7 @@ var WebXREnterExitUI = /** @class */ (function () {
                                     _a.label = 3;
                                 case 3:
                                     _a.trys.push([3, 5, , 6]);
-                                    return [4 /*yield*/, helper.enterXRAsync(ui._buttons[i].sessionMode, ui._buttons[i].referenceSpaceType, options.renderTarget, { optionalFeatures: options.optionalFeatures })];
+                                    return [4 /*yield*/, helper.enterXRAsync(ui._buttons[i].sessionMode, ui._buttons[i].referenceSpaceType, options.renderTarget, { optionalFeatures: options.optionalFeatures, requiredFeatures: options.requiredFeatures })];
                                 case 4:
                                     _a.sent();
                                     ui._updateButtons(ui._buttons[i]);

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/babylon.max.js.map


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

@@ -49940,6 +49940,10 @@ declare module "babylonjs/XR/webXREnterExitUI" {
          * A list of optional features to init the session with
          */
         optionalFeatures?: string[];
+        /**
+         * A list of optional features to init the session with
+         */
+        requiredFeatures?: string[];
     }
     /**
      * UI to allow the user to enter/exit XR mode
@@ -126383,6 +126387,10 @@ declare module BABYLON {
          * A list of optional features to init the session with
          */
         optionalFeatures?: string[];
+        /**
+         * A list of optional features to init the session with
+         */
+        requiredFeatures?: string[];
     }
     /**
      * UI to allow the user to enter/exit XR mode

+ 27 - 0
dist/preview release/documentation.d.ts

@@ -48149,6 +48149,10 @@ declare module BABYLON {
          * A list of optional features to init the session with
          */
         optionalFeatures?: string[];
+        /**
+         * A list of optional features to init the session with
+         */
+        requiredFeatures?: string[];
     }
     /**
      * UI to allow the user to enter/exit XR mode
@@ -80808,22 +80812,45 @@ declare module BABYLON.GLTF2.Loader.Extensions {
          */
         static GetAvailableVariants(rootMesh: Mesh): string[];
         /**
+         * Gets the list of available variant tag names for this asset.
+         * @param rootMesh The glTF root mesh
+         * @returns the list of all the variant names for this model
+         */
+        getAvailableVariants(rootMesh: Mesh): string[];
+        /**
          * Select a variant given a variant tag name or a list of variant tag names.
          * @param rootMesh The glTF root mesh
          * @param variantName The variant name(s) to select.
          */
         static SelectVariant(rootMesh: Mesh, variantName: string | string[]): void;
         /**
+         * Select a variant given a variant tag name or a list of variant tag names.
+         * @param rootMesh The glTF root mesh
+         * @param variantName The variant name(s) to select.
+         */
+        selectVariant(rootMesh: Mesh, variantName: string | string[]): void;
+        /**
          * Reset back to the original before selecting a variant.
          * @param rootMesh The glTF root mesh
          */
         static Reset(rootMesh: Mesh): void;
         /**
+         * Reset back to the original before selecting a variant.
+         * @param rootMesh The glTF root mesh
+         */
+        reset(rootMesh: Mesh): void;
+        /**
          * Gets the last selected variant tag name(s) or null if original.
          * @param rootMesh The glTF root mesh
          * @returns The selected variant tag name(s).
          */
         static GetLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]>;
+        /**
+         * Gets the last selected variant tag name(s) or null if original.
+         * @param rootMesh The glTF root mesh
+         * @returns The selected variant tag name(s).
+         */
+        getLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]>;
         private static _GetExtensionMetadata;
         /** @hidden */
         _loadMeshPrimitiveAsync(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Nullable<Promise<AbstractMesh>>;

+ 48 - 48
dist/preview release/gui/babylon.gui.js

@@ -7,7 +7,7 @@
 		exports["babylonjs-gui"] = factory(require("babylonjs"));
 	else
 		root["BABYLON"] = root["BABYLON"] || {}, root["BABYLON"]["GUI"] = factory(root["BABYLON"]);
-})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_Maths_math_vector__) {
+})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__) {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
@@ -400,7 +400,7 @@ module.exports = g;
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AdvancedDynamicTextureInstrumentation", function() { return AdvancedDynamicTextureInstrumentation; });
-/* harmony import */ var babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/perfCounter */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/perfCounter */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_perfCounter__WEBPACK_IMPORTED_MODULE_0__);
 
 /**
@@ -543,7 +543,7 @@ var AdvancedDynamicTextureInstrumentation = /** @class */ (function () {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AdvancedDynamicTexture", function() { return AdvancedDynamicTexture; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _controls_container__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./controls/container */ "./2D/controls/container.ts");
 /* harmony import */ var _style__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./style */ "./2D/style.ts");
@@ -1515,7 +1515,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _textBlock__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./textBlock */ "./2D/controls/textBlock.ts");
 /* harmony import */ var _image__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./image */ "./2D/controls/image.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5__);
 
 
@@ -1747,7 +1747,7 @@ babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_5__["_TypeStore"].RegisteredTy
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Checkbox", function() { return Checkbox; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
@@ -1930,7 +1930,7 @@ babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].RegisteredT
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ColorPicker", function() { return ColorPicker; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _inputText__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./inputText */ "./2D/controls/inputText.ts");
@@ -3319,7 +3319,7 @@ babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].RegisteredT
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container", function() { return Container; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/logger */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/logger */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../measure */ "./2D/measure.ts");
@@ -3734,7 +3734,7 @@ babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].RegisteredTypes
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Control", function() { return Control; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../measure */ "./2D/measure.ts");
@@ -5660,7 +5660,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DisplayGrid", function() { return DisplayGrid; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__);
 
 
@@ -5893,7 +5893,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__);
 
 
@@ -5990,7 +5990,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__);
 
 
@@ -6448,7 +6448,7 @@ babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_4__["_TypeStore"].RegisteredTypes[
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Image", function() { return Image; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 
@@ -7375,7 +7375,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InputPassword", function() { return InputPassword; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _inputText__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./inputText */ "./2D/controls/inputText.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__);
 
 
@@ -7414,7 +7414,7 @@ babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__["_TypeStore"].RegisteredTy
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InputText", function() { return InputText; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
@@ -8427,7 +8427,7 @@ babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].RegisteredT
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Line", function() { return Line; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
@@ -8698,7 +8698,7 @@ babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].Registere
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiLine", function() { return MultiLine; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/abstractMesh */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/abstractMesh */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _multiLinePoint__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../multiLinePoint */ "./2D/multiLinePoint.ts");
@@ -8968,7 +8968,7 @@ babylonjs_Meshes_abstractMesh__WEBPACK_IMPORTED_MODULE_1__["_TypeStore"].Registe
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RadioButton", function() { return RadioButton; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
@@ -9175,7 +9175,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Rectangle", function() { return Rectangle; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__);
 
 
@@ -9325,7 +9325,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _scrollViewerWindow__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./scrollViewerWindow */ "./2D/controls/scrollViewers/scrollViewerWindow.ts");
 /* harmony import */ var _sliders_scrollBar__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../sliders/scrollBar */ "./2D/controls/sliders/scrollBar.ts");
 /* harmony import */ var _sliders_imageScrollBar__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../sliders/imageScrollBar */ "./2D/controls/sliders/imageScrollBar.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_7__);
 
 
@@ -10948,7 +10948,7 @@ var SelectionPanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BaseSlider", function() { return BaseSlider; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../control */ "./2D/controls/control.ts");
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../valueAndUnit */ "./2D/valueAndUnit.ts");
@@ -11278,7 +11278,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _baseSlider__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./baseSlider */ "./2D/controls/sliders/baseSlider.ts");
 /* harmony import */ var _measure__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../measure */ "./2D/measure.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_3__);
 
 
@@ -11871,7 +11871,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Slider", function() { return Slider; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _baseSlider__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./baseSlider */ "./2D/controls/sliders/baseSlider.ts");
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__);
 
 
@@ -12126,7 +12126,7 @@ babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_2__["_TypeStore"].RegisteredTy
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StackPanel", function() { return StackPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container */ "./2D/controls/container.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
@@ -12394,7 +12394,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextWrapping", function() { return TextWrapping; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextBlock", function() { return TextBlock; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../valueAndUnit */ "./2D/valueAndUnit.ts");
 /* harmony import */ var _control__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./control */ "./2D/controls/control.ts");
@@ -12857,7 +12857,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KeyPropertySet", function() { return KeyPropertySet; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VirtualKeyboard", function() { return VirtualKeyboard; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _stackPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./stackPanel */ "./2D/controls/stackPanel.ts");
 /* harmony import */ var _button__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./button */ "./2D/controls/button.ts");
@@ -13246,7 +13246,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Vector2WithInfo", function() { return Vector2WithInfo; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Matrix2D", function() { return Matrix2D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__);
 
 
@@ -13471,7 +13471,7 @@ var Matrix2D = /** @class */ (function () {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Measure", function() { return Measure; });
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__);
 
 var tmpRect = [
@@ -13620,7 +13620,7 @@ var Measure = /** @class */ (function () {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MultiLinePoint", function() { return MultiLinePoint; });
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./valueAndUnit */ "./2D/valueAndUnit.ts");
 
@@ -13763,7 +13763,7 @@ var MultiLinePoint = /** @class */ (function () {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Style", function() { return Style; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _valueAndUnit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./valueAndUnit */ "./2D/valueAndUnit.ts");
 
@@ -14069,7 +14069,7 @@ var ValueAndUnit = /** @class */ (function () {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "XmlLoader", function() { return XmlLoader; });
-/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/typeStore */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_typeStore__WEBPACK_IMPORTED_MODULE_0__);
 
 /**
@@ -14388,7 +14388,7 @@ var XmlLoader = /** @class */ (function () {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AbstractButton3D", function() { return AbstractButton3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control3D */ "./3D/controls/control3D.ts");
 
@@ -14431,7 +14431,7 @@ var AbstractButton3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Button3D", function() { return Button3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _abstractButton3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./abstractButton3D */ "./3D/controls/abstractButton3D.ts");
 /* harmony import */ var _2D_advancedDynamicTexture__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../2D/advancedDynamicTexture */ "./2D/advancedDynamicTexture.ts");
@@ -14612,7 +14612,7 @@ var Button3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container3D", function() { return Container3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/transformNode */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_transformNode__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _control3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./control3D */ "./3D/controls/control3D.ts");
 
@@ -14769,7 +14769,7 @@ var Container3D = /** @class */ (function (_super) {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Control3D", function() { return Control3D; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _vector3WithInfo__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../vector3WithInfo */ "./3D/vector3WithInfo.ts");
 
@@ -15175,7 +15175,7 @@ var Control3D = /** @class */ (function () {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CylinderPanel", function() { return CylinderPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
@@ -15261,7 +15261,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HolographicButton", function() { return HolographicButton; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
 /* harmony import */ var _button3D__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./button3D */ "./3D/controls/button3D.ts");
-/* harmony import */ var babylonjs_Materials_standardMaterial__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Materials/standardMaterial */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Materials_standardMaterial__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! babylonjs/Materials/standardMaterial */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Materials_standardMaterial__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_standardMaterial__WEBPACK_IMPORTED_MODULE_2__);
 /* harmony import */ var _materials_fluentMaterial__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../materials/fluentMaterial */ "./3D/materials/fluentMaterial.ts");
 /* harmony import */ var _2D_controls_stackPanel__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../2D/controls/stackPanel */ "./2D/controls/stackPanel.ts");
@@ -15755,7 +15755,7 @@ var MeshButton3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PlanePanel", function() { return PlanePanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
@@ -15810,7 +15810,7 @@ var PlanePanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ScatterPanel", function() { return ScatterPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
@@ -15937,7 +15937,7 @@ var ScatterPanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SpherePanel", function() { return SpherePanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _volumeBasedPanel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./volumeBasedPanel */ "./3D/controls/volumeBasedPanel.ts");
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
@@ -16023,7 +16023,7 @@ var SpherePanel = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StackPanel3D", function() { return StackPanel3D; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 
@@ -16148,7 +16148,7 @@ var StackPanel3D = /** @class */ (function (_super) {
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VolumeBasedPanel", function() { return VolumeBasedPanel; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _container3D__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./container3D */ "./3D/controls/container3D.ts");
 
@@ -16339,7 +16339,7 @@ var VolumeBasedPanel = /** @class */ (function (_super) {
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GUI3DManager", function() { return GUI3DManager; });
-/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/observable */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__);
 /* harmony import */ var _controls_container3D__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./controls/container3D */ "./3D/controls/container3D.ts");
 
@@ -16606,7 +16606,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FluentMaterialDefines", function() { return FluentMaterialDefines; });
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FluentMaterial", function() { return FluentMaterial; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/decorators */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/decorators */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_decorators__WEBPACK_IMPORTED_MODULE_1__);
 /* harmony import */ var _shaders_fluent_vertex__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./shaders/fluent.vertex */ "./3D/materials/shaders/fluent.vertex.ts");
 /* harmony import */ var _shaders_fluent_fragment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./shaders/fluent.fragment */ "./3D/materials/shaders/fluent.fragment.ts");
@@ -16929,7 +16929,7 @@ __webpack_require__.r(__webpack_exports__);
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fluentPixelShader", function() { return fluentPixelShader; });
-/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__);
 
 var name = 'fluentPixelShader';
@@ -16951,7 +16951,7 @@ var fluentPixelShader = { name: name, shader: shader };
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fluentVertexShader", function() { return fluentVertexShader; });
-/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/effect */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_effect__WEBPACK_IMPORTED_MODULE_0__);
 
 var name = 'fluentVertexShader';
@@ -16974,7 +16974,7 @@ var fluentVertexShader = { name: name, shader: shader };
 __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Vector3WithInfo", function() { return Vector3WithInfo; });
 /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Maths/math.vector");
+/* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/observable");
 /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__);
 
 
@@ -17276,14 +17276,14 @@ if (typeof globalObject !== "undefined") {
 
 /***/ }),
 
-/***/ "babylonjs/Maths/math.vector":
+/***/ "babylonjs/Misc/observable":
 /*!****************************************************************************************************!*\
   !*** external {"root":"BABYLON","commonjs":"babylonjs","commonjs2":"babylonjs","amd":"babylonjs"} ***!
   \****************************************************************************************************/
 /*! no static exports found */
 /***/ (function(module, exports) {
 
-module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Maths_math_vector__;
+module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__;
 
 /***/ })
 

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/gui/babylon.gui.js.map


Разница между файлами не показана из-за своего большого размера
+ 6 - 6
dist/preview release/inspector/babylon.inspector.bundle.js


+ 358 - 106
dist/preview release/inspector/babylon.inspector.bundle.max.js

@@ -1,13 +1,13 @@
 (function webpackUniversalModuleDefinition(root, factory) {
 	if(typeof exports === 'object' && typeof module === 'object')
-		module.exports = factory(require("babylonjs-gui"), require("babylonjs-loaders"), require("babylonjs-loaders"), require("babylonjs-materials"), require("babylonjs-serializers"), require("babylonjs"));
+		module.exports = factory(require("babylonjs-gui"), require("babylonjs-loaders"), require("babylonjs-materials"), require("babylonjs-serializers"), require("babylonjs"));
 	else if(typeof define === 'function' && define.amd)
-		define("babylonjs-inspector", ["babylonjs-gui", "babylonjs-loaders", "babylonjs-loaders", "babylonjs-materials", "babylonjs-serializers", "babylonjs"], factory);
+		define("babylonjs-inspector", ["babylonjs-gui", "babylonjs-loaders", "babylonjs-materials", "babylonjs-serializers", "babylonjs"], factory);
 	else if(typeof exports === 'object')
-		exports["babylonjs-inspector"] = factory(require("babylonjs-gui"), require("babylonjs-loaders"), require("babylonjs-loaders"), require("babylonjs-materials"), require("babylonjs-serializers"), require("babylonjs"));
+		exports["babylonjs-inspector"] = factory(require("babylonjs-gui"), require("babylonjs-loaders"), require("babylonjs-materials"), require("babylonjs-serializers"), require("babylonjs"));
 	else
-		root["INSPECTOR"] = factory(root["BABYLON"]["GUI"], root["BABYLON"]["GLTF2"]["Loader"]["Extensions"], root["BABYLON"], root["BABYLON"], root["BABYLON"], root["BABYLON"]);
-})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_gui_2D_controls_image__, __WEBPACK_EXTERNAL_MODULE_babylonjs_loaders_glTF_2_0_Extensions_KHR_materials_variants__, __WEBPACK_EXTERNAL_MODULE_babylonjs_loaders_glTF_index__, __WEBPACK_EXTERNAL_MODULE_babylonjs_materials_grid_gridMaterial__, __WEBPACK_EXTERNAL_MODULE_babylonjs_serializers_glTF_2_0_index__, __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__) {
+		root["INSPECTOR"] = factory(root["BABYLON"]["GUI"], root["BABYLON"], root["BABYLON"], root["BABYLON"], root["BABYLON"]);
+})((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), function(__WEBPACK_EXTERNAL_MODULE_babylonjs_gui_2D_controls_image__, __WEBPACK_EXTERNAL_MODULE_babylonjs_loaders_glTF_index__, __WEBPACK_EXTERNAL_MODULE_babylonjs_materials_grid_gridMaterial__, __WEBPACK_EXTERNAL_MODULE_babylonjs_serializers_glTF_2_0_index__, __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__) {
 return /******/ (function(modules) { // webpackBootstrap
 /******/ 	// The module cache
 /******/ 	var installedModules = {};
@@ -11322,6 +11322,24 @@ module.exports = exports;
 
 /***/ }),
 
+/***/ "../../node_modules/css-loader/dist/cjs.js!../../node_modules/sass-loader/dist/cjs.js!./components/actionTabs/tabs/propertyGrids/materials/textures/textureEditor.scss":
+/*!*********************************************************************************************************************************************************************************************************!*\
+  !*** D:/Repos/Babylon.js/node_modules/css-loader/dist/cjs.js!D:/Repos/Babylon.js/node_modules/sass-loader/dist/cjs.js!./components/actionTabs/tabs/propertyGrids/materials/textures/textureEditor.scss ***!
+  \*********************************************************************************************************************************************************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+// Imports
+var ___CSS_LOADER_API_IMPORT___ = __webpack_require__(/*! ../../../../../../../../node_modules/css-loader/dist/runtime/api.js */ "../../node_modules/css-loader/dist/runtime/api.js");
+exports = ___CSS_LOADER_API_IMPORT___(false);
+// Module
+exports.push([module.i, "#texture-canvas {\n  width: 100%;\n  height: 100%; }\n", ""]);
+// Exports
+module.exports = exports;
+
+
+/***/ }),
+
 /***/ "../../node_modules/css-loader/dist/cjs.js!../../node_modules/sass-loader/dist/cjs.js!./components/embedHost/embedHost.scss":
 /*!**************************************************************************************************************************************************************!*\
   !*** D:/Repos/Babylon.js/node_modules/css-loader/dist/cjs.js!D:/Repos/Babylon.js/node_modules/sass-loader/dist/cjs.js!./components/embedHost/embedHost.scss ***!
@@ -64893,7 +64911,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _lines_floatLineComponent__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../../lines/floatLineComponent */ "./components/actionTabs/lines/floatLineComponent.tsx");
 /* harmony import */ var _lines_textLineComponent__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../../lines/textLineComponent */ "./components/actionTabs/lines/textLineComponent.tsx");
 /* harmony import */ var _animations_animationCurveEditorComponent__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../animations/animationCurveEditorComponent */ "./components/actionTabs/tabs/propertyGrids/animations/animationCurveEditorComponent.tsx");
-/* harmony import */ var _animations_popupComponent__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../animations/popupComponent */ "./components/actionTabs/tabs/propertyGrids/animations/popupComponent.tsx");
+/* harmony import */ var _popupComponent__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../../../popupComponent */ "./components/popupComponent.tsx");
 
 
 
@@ -65033,7 +65051,7 @@ var AnimationGridComponent = /** @class */ (function (_super) {
                     animations.map(function (anim, i) {
                         return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_textLineComponent__WEBPACK_IMPORTED_MODULE_8__["TextLineComponent"], { key: anim.targetProperty + i, label: '#' + i + ' >', value: anim.targetProperty }));
                     }),
-                    this._isCurveEditorOpen && (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_animations_popupComponent__WEBPACK_IMPORTED_MODULE_10__["PopupComponent"], { id: 'curve-editor', title: 'Curve Animation Editor', size: { width: 1024, height: 490 }, onOpen: function (window) { }, onClose: function (window) {
+                    this._isCurveEditorOpen && (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_popupComponent__WEBPACK_IMPORTED_MODULE_10__["PopupComponent"], { id: 'curve-editor', title: 'Curve Animation Editor', size: { width: 1024, height: 490 }, onOpen: function (window) { }, onClose: function (window) {
                             return _this.onCloseAnimationCurveEditor(window);
                         } },
                         react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_animations_animationCurveEditorComponent__WEBPACK_IMPORTED_MODULE_9__["AnimationCurveEditorComponent"], { scene: this.props.scene, entity: animatableAsAny, close: function (event) {
@@ -66043,81 +66061,6 @@ var Notification = /** @class */ (function (_super) {
 
 /***/ }),
 
-/***/ "./components/actionTabs/tabs/propertyGrids/animations/popupComponent.tsx":
-/*!********************************************************************************!*\
-  !*** ./components/actionTabs/tabs/propertyGrids/animations/popupComponent.tsx ***!
-  \********************************************************************************/
-/*! exports provided: PopupComponent */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PopupComponent", function() { return PopupComponent; });
-/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
-/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ "../../node_modules/react/index.js");
-/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
-/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-dom */ "../../node_modules/react-dom/index.js");
-/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_2__);
-/* harmony import */ var _inspector__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../../inspector */ "./inspector.ts");
-
-
-
-
-var PopupComponent = /** @class */ (function (_super) {
-    Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"])(PopupComponent, _super);
-    function PopupComponent(props) {
-        var _this = _super.call(this, props) || this;
-        _this._container = document.createElement('div');
-        _this._container.id = _this.props.id;
-        _this._window;
-        _this.state = {
-            isComponentMounted: false,
-            blockedByBrowser: false,
-        };
-        return _this;
-    }
-    PopupComponent.prototype.componentDidMount = function () {
-        this.openPopup();
-        this.setState({ isComponentMounted: true });
-    };
-    PopupComponent.prototype.openPopup = function () {
-        var _this = this;
-        var _a = this.props, title = _a.title, size = _a.size, onClose = _a.onClose, onOpen = _a.onOpen;
-        var windowVariableName = "window_" + title;
-        this._container = _inspector__WEBPACK_IMPORTED_MODULE_3__["Inspector"]._CreatePopup(title, windowVariableName, size.width, size.height);
-        this._window = _inspector__WEBPACK_IMPORTED_MODULE_3__["Inspector"][windowVariableName];
-        if (this._window) {
-            onOpen(this._window);
-            this._window.addEventListener('beforeunload', function () { return _this._window && onClose(_this._window); });
-        }
-        else {
-            if (!this._window) {
-                this.setState({ blockedByBrowser: true }, function () {
-                    if (_this.state.blockedByBrowser) {
-                        alert("You might have blocked popups in your browser");
-                        console.warn("Popup window couldn't be created");
-                    }
-                });
-            }
-        }
-    };
-    PopupComponent.prototype.componentWillUnmount = function () {
-        if (this._window) {
-            this._window.close();
-        }
-    };
-    PopupComponent.prototype.render = function () {
-        if (!this.state.isComponentMounted || this._container === null)
-            return null;
-        return react_dom__WEBPACK_IMPORTED_MODULE_2__["createPortal"](this.props.children, this._container);
-    };
-    return PopupComponent;
-}(react__WEBPACK_IMPORTED_MODULE_1__["Component"]));
-
-
-
-/***/ }),
-
 /***/ "./components/actionTabs/tabs/propertyGrids/animations/saveSnippet.tsx":
 /*!*****************************************************************************!*\
   !*** ./components/actionTabs/tabs/propertyGrids/animations/saveSnippet.tsx ***!
@@ -66517,7 +66460,7 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _lineContainerComponent__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../lineContainerComponent */ "./components/actionTabs/lineContainerComponent.tsx");
 /* harmony import */ var _lines_textLineComponent__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../../lines/textLineComponent */ "./components/actionTabs/lines/textLineComponent.tsx");
 /* harmony import */ var _lines_textInputLineComponent__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../../lines/textInputLineComponent */ "./components/actionTabs/lines/textInputLineComponent.tsx");
-/* harmony import */ var _animations_popupComponent__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../animations/popupComponent */ "./components/actionTabs/tabs/propertyGrids/animations/popupComponent.tsx");
+/* harmony import */ var _popupComponent__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../../../popupComponent */ "./components/popupComponent.tsx");
 /* harmony import */ var _animations_animationCurveEditorComponent__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../animations/animationCurveEditorComponent */ "./components/actionTabs/tabs/propertyGrids/animations/animationCurveEditorComponent.tsx");
 
 
@@ -66582,7 +66525,7 @@ var TargetedAnimationGridComponent = /** @class */ (function (_super) {
                         return _this.props.globalState.onSelectionChangedObservable.notifyObservers(targetedAnimation);
                     } })),
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_buttonLineComponent__WEBPACK_IMPORTED_MODULE_2__["ButtonLineComponent"], { label: 'Edit animation', onClick: function () { return _this.onOpenAnimationCurveEditor(); } }),
-                this._isCurveEditorOpen && (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_animations_popupComponent__WEBPACK_IMPORTED_MODULE_6__["PopupComponent"], { id: 'curve-editor', title: 'Curve Animation Editor', size: { width: 1024, height: 512 }, onOpen: function (window) { }, onClose: function (window) {
+                this._isCurveEditorOpen && (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_popupComponent__WEBPACK_IMPORTED_MODULE_6__["PopupComponent"], { id: 'curve-editor', title: 'Curve Animation Editor', size: { width: 1024, height: 512 }, onOpen: function (window) { }, onClose: function (window) {
                         return _this.onCloseAnimationCurveEditor(window);
                     } },
                     react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_animations_animationCurveEditorComponent__WEBPACK_IMPORTED_MODULE_7__["AnimationCurveEditorComponent"], { scene: this.props.scene, entity: targetedAnimation, playOrPause: function () { return _this.playOrPause(); }, lockObject: this.props.lockObject, globalState: this.props.globalState, close: function (event) { return _this.onCloseAnimationCurveEditor(event.view); } }))),
@@ -69705,6 +69648,11 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _lines_buttonLineComponent__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../../../lines/buttonLineComponent */ "./components/actionTabs/lines/buttonLineComponent.tsx");
 /* harmony import */ var _lines_textInputLineComponent__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../../../lines/textInputLineComponent */ "./components/actionTabs/lines/textInputLineComponent.tsx");
 /* harmony import */ var _animations_animationPropertyGridComponent__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../animations/animationPropertyGridComponent */ "./components/actionTabs/tabs/propertyGrids/animations/animationPropertyGridComponent.tsx");
+/* harmony import */ var _popupComponent__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../../../../popupComponent */ "./components/popupComponent.tsx");
+/* harmony import */ var _textures_textureEditorComponent__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./textures/textureEditorComponent */ "./components/actionTabs/tabs/propertyGrids/materials/textures/textureEditorComponent.tsx");
+
+
+
 
 
 
@@ -69727,6 +69675,7 @@ var TexturePropertyGridComponent = /** @class */ (function (_super) {
     Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"])(TexturePropertyGridComponent, _super);
     function TexturePropertyGridComponent(props) {
         var _this = _super.call(this, props) || this;
+        _this._isTextureEditorOpen = false;
         var texture = _this.props.texture;
         _this.textureLineRef = react__WEBPACK_IMPORTED_MODULE_1__["createRef"]();
         if (!texture || !texture.rootContainer) {
@@ -69761,15 +69710,24 @@ var TexturePropertyGridComponent = /** @class */ (function (_super) {
                     else if (file.name.toLowerCase().indexOf(".env") > 0) {
                         extension = ".env";
                     }
-                    texture.updateURL(base64data, extension, function () { return _this.foreceRefresh(); });
+                    texture.updateURL(base64data, extension, function () { return _this.forceRefresh(); });
                 }
                 else {
-                    texture.updateURL(base64data, null, function () { return _this.foreceRefresh(); });
+                    texture.updateURL(base64data, null, function () { return _this.forceRefresh(); });
                 }
             };
         }, undefined, true);
     };
-    TexturePropertyGridComponent.prototype.foreceRefresh = function () {
+    TexturePropertyGridComponent.prototype.onOpenTextureEditor = function () {
+        this._isTextureEditorOpen = true;
+    };
+    TexturePropertyGridComponent.prototype.onCloseTextureEditor = function (window) {
+        this._isTextureEditorOpen = false;
+        if (window !== null) {
+            window.close();
+        }
+    };
+    TexturePropertyGridComponent.prototype.forceRefresh = function () {
         this.forceUpdate();
         this.textureLineRef.current.updatePreview();
     };
@@ -69804,14 +69762,21 @@ var TexturePropertyGridComponent = /** @class */ (function (_super) {
                 extension = textureUrl[index] + extension;
             }
         }
+        var editable = texture.textureType != babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_2__["Engine"].TEXTURETYPE_FLOAT && texture.textureType != babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_2__["Engine"].TEXTURETYPE_FLOAT_32_UNSIGNED_INT_24_8_REV && texture.textureType !== babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_2__["Engine"].TEXTURETYPE_HALF_FLOAT;
         return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "pane" },
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lineContainerComponent__WEBPACK_IMPORTED_MODULE_3__["LineContainerComponent"], { globalState: this.props.globalState, title: "PREVIEW" },
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_textureLineComponent__WEBPACK_IMPORTED_MODULE_7__["TextureLineComponent"], { ref: this.textureLineRef, texture: texture, width: 256, height: 256, globalState: this.props.globalState }),
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_fileButtonLineComponent__WEBPACK_IMPORTED_MODULE_10__["FileButtonLineComponent"], { label: "Load texture from file", onClick: function (file) { return _this.updateTexture(file); }, accept: ".jpg, .png, .tga, .dds, .env" }),
+                editable &&
+                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_buttonLineComponent__WEBPACK_IMPORTED_MODULE_14__["ButtonLineComponent"], { label: "View", onClick: function () { return _this.onOpenTextureEditor(); } }),
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_textInputLineComponent__WEBPACK_IMPORTED_MODULE_15__["TextInputLineComponent"], { label: "URL", value: textureUrl, lockObject: this.props.lockObject, onChange: function (url) {
                         texture.updateURL(url);
-                        _this.foreceRefresh();
+                        _this.forceRefresh();
                     } })),
+            this._isTextureEditorOpen && (react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_popupComponent__WEBPACK_IMPORTED_MODULE_17__["PopupComponent"], { id: 'texture-editor', title: 'Texture Editor', size: { width: 1024, height: 490 }, onOpen: function (window) { }, onClose: function (window) {
+                    return _this.onCloseTextureEditor(window);
+                } },
+                react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_textures_textureEditorComponent__WEBPACK_IMPORTED_MODULE_18__["TextureEditorComponent"], { globalState: this.props.globalState, texture: this.props.texture }))),
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_customPropertyGridComponent__WEBPACK_IMPORTED_MODULE_13__["CustomPropertyGridComponent"], { globalState: this.props.globalState, target: texture, lockObject: this.props.lockObject, onPropertyChangedObservable: this.props.onPropertyChangedObservable }),
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lineContainerComponent__WEBPACK_IMPORTED_MODULE_3__["LineContainerComponent"], { globalState: this.props.globalState, title: "GENERAL" },
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_textLineComponent__WEBPACK_IMPORTED_MODULE_5__["TextLineComponent"], { label: "Width", value: texture.getSize().width.toString() }),
@@ -69885,6 +69850,221 @@ var TexturePropertyGridComponent = /** @class */ (function (_super) {
 
 /***/ }),
 
+/***/ "./components/actionTabs/tabs/propertyGrids/materials/textures/textureCanvasManager.ts":
+/*!*********************************************************************************************!*\
+  !*** ./components/actionTabs/tabs/propertyGrids/materials/textures/textureCanvasManager.ts ***!
+  \*********************************************************************************************/
+/*! exports provided: TextureCanvasManager */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextureCanvasManager", function() { return TextureCanvasManager; });
+/* harmony import */ var babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Engines/engine */ "babylonjs/Misc/observable");
+/* harmony import */ var babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__);
+
+
+
+
+
+
+
+
+
+
+
+var TextureCanvasManager = /** @class */ (function () {
+    function TextureCanvasManager(targetCanvas, texture) {
+        var _this = this;
+        this._canvas = targetCanvas;
+        this._engine = new babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["Engine"](targetCanvas, true);
+        this._scene = new babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["Scene"](this._engine);
+        this._scene.clearColor = new babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["Color4"](0.2, 0.2, 0.2, 1.0);
+        this._camera = new babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["FreeCamera"]("Camera", new babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["Vector3"](0, 0, -1), this._scene);
+        this._camera.mode = babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["Camera"].ORTHOGRAPHIC_CAMERA;
+        if (texture) {
+            /* Grab image data from original texture and paint it onto the context of a DynamicTexture */
+            var pixelData = texture.readPixels();
+            var arr = new Uint8ClampedArray(pixelData.buffer);
+            var imgData = new ImageData(arr, texture.getSize().width, texture.getSize().height);
+            this._texture = new babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["DynamicTexture"]("texture", texture.getSize(), this._scene, false);
+            var ctx = this._texture.getContext();
+            ctx.putImageData(imgData, 0, 0);
+            this._texture.update();
+            this._texture.hasAlpha = texture.hasAlpha;
+        }
+        else {
+            /* If we don't have a texture to start with, just generate a white rectangle */
+            this._texture = new babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["DynamicTexture"]("texture", 256, this._scene, false);
+            var ctx = this._texture.getContext();
+            ctx.fillStyle = 'white';
+            ctx.fillRect(0, 0, 256, 256);
+            this._texture.update();
+        }
+        this._texture.updateSamplingMode(babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["Engine"].TEXTURE_NEAREST_LINEAR);
+        var textureRatio = this._texture.getSize().width / this._texture.getSize().height;
+        this._plane = babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["PlaneBuilder"].CreatePlane("plane", { width: textureRatio, height: 1 }, this._scene);
+        babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["NodeMaterial"].ParseFromSnippetAsync("#TPSEV2#3", this._scene)
+            .then(function (material) {
+            _this._planeMaterial = material;
+            _this._planeMaterial.getTextureBlocks()[0].texture = _this._texture;
+            _this._plane.material = _this._planeMaterial;
+            _this._canvas.focus();
+        });
+        this._plane.enableEdgesRendering();
+        this._plane.edgesWidth = 4.0;
+        this._plane.edgesColor = new babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["Color4"](1, 1, 1, 1);
+        this._engine.runRenderLoop(function () {
+            _this._engine.resize();
+            _this._scene.render();
+        });
+        this._scale = 1;
+        this._isPanning = false;
+        this._scene.onBeforeRenderObservable.add(function () {
+            var _a, _b;
+            var ratio = ((_a = _this._canvas) === null || _a === void 0 ? void 0 : _a.width) / ((_b = _this._canvas) === null || _b === void 0 ? void 0 : _b.height);
+            _this._camera.orthoBottom = -_this._scale;
+            _this._camera.orthoTop = _this._scale;
+            _this._camera.orthoLeft = -_this._scale * ratio;
+            _this._camera.orthoRight = _this._scale * ratio;
+        });
+        this._scene.onPointerObservable.add(function (pointerInfo) {
+            switch (pointerInfo.type) {
+                case babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["PointerEventTypes"].POINTERWHEEL:
+                    var event_1 = pointerInfo.event;
+                    _this._scale += (event_1.deltaY * TextureCanvasManager.ZOOM_MOUSE_SPEED * _this._scale);
+                    _this._scale = Math.min(Math.max(_this._scale, TextureCanvasManager.MIN_SCALE), TextureCanvasManager.MAX_SCALE);
+                    break;
+                case babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["PointerEventTypes"].POINTERDOWN:
+                    if (pointerInfo.event.button === TextureCanvasManager.PAN_BUTTON) {
+                        _this._isPanning = true;
+                        _this._mouseX = pointerInfo.event.x;
+                        _this._mouseY = pointerInfo.event.y;
+                    }
+                    break;
+                case babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["PointerEventTypes"].POINTERUP:
+                    if (pointerInfo.event.button === TextureCanvasManager.PAN_BUTTON) {
+                        _this._isPanning = false;
+                    }
+                    break;
+                case babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["PointerEventTypes"].POINTERMOVE:
+                    if (_this._isPanning) {
+                        _this._camera.position.x -= (pointerInfo.event.x - _this._mouseX) * _this._scale * TextureCanvasManager.PAN_SPEED;
+                        _this._camera.position.y += (pointerInfo.event.y - _this._mouseY) * _this._scale * TextureCanvasManager.PAN_SPEED;
+                        _this._mouseX = pointerInfo.event.x;
+                        _this._mouseY = pointerInfo.event.y;
+                    }
+                    break;
+            }
+        });
+        this._scene.onKeyboardObservable.add(function (kbInfo) {
+            switch (kbInfo.type) {
+                case babylonjs_Engines_engine__WEBPACK_IMPORTED_MODULE_0__["KeyboardEventTypes"].KEYDOWN:
+                    if (kbInfo.event.key == "+") {
+                        _this._scale -= TextureCanvasManager.ZOOM_KEYBOARD_SPEED * _this._scale;
+                    }
+                    if (kbInfo.event.key == "-") {
+                        _this._scale += TextureCanvasManager.ZOOM_KEYBOARD_SPEED * _this._scale;
+                    }
+                    _this._scale = Math.min(Math.max(_this._scale, TextureCanvasManager.MIN_SCALE), TextureCanvasManager.MAX_SCALE);
+                    break;
+            }
+        });
+    }
+    TextureCanvasManager.prototype.dispose = function () {
+        if (this._planeMaterial) {
+            this._planeMaterial.dispose();
+        }
+        this._texture.dispose();
+        this._plane.dispose();
+        this._camera.dispose();
+        this._scene.dispose();
+        this._engine.dispose();
+    };
+    TextureCanvasManager.ZOOM_MOUSE_SPEED = 0.0005;
+    TextureCanvasManager.ZOOM_KEYBOARD_SPEED = 0.2;
+    TextureCanvasManager.PAN_SPEED = 0.002;
+    TextureCanvasManager.PAN_BUTTON = 0; // left mouse button
+    TextureCanvasManager.MIN_SCALE = 0.01;
+    TextureCanvasManager.MAX_SCALE = 10;
+    return TextureCanvasManager;
+}());
+
+
+
+/***/ }),
+
+/***/ "./components/actionTabs/tabs/propertyGrids/materials/textures/textureEditor.scss":
+/*!****************************************************************************************!*\
+  !*** ./components/actionTabs/tabs/propertyGrids/materials/textures/textureEditor.scss ***!
+  \****************************************************************************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+var api = __webpack_require__(/*! ../../../../../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ "../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js");
+            var content = __webpack_require__(/*! !../../../../../../../../node_modules/css-loader/dist/cjs.js!../../../../../../../../node_modules/sass-loader/dist/cjs.js!./textureEditor.scss */ "../../node_modules/css-loader/dist/cjs.js!../../node_modules/sass-loader/dist/cjs.js!./components/actionTabs/tabs/propertyGrids/materials/textures/textureEditor.scss");
+
+            content = content.__esModule ? content.default : content;
+
+            if (typeof content === 'string') {
+              content = [[module.i, content, '']];
+            }
+
+var options = {};
+
+options.insert = "head";
+options.singleton = false;
+
+var update = api(content, options);
+
+
+
+module.exports = content.locals || {};
+
+/***/ }),
+
+/***/ "./components/actionTabs/tabs/propertyGrids/materials/textures/textureEditorComponent.tsx":
+/*!************************************************************************************************!*\
+  !*** ./components/actionTabs/tabs/propertyGrids/materials/textures/textureEditorComponent.tsx ***!
+  \************************************************************************************************/
+/*! exports provided: TextureEditorComponent */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextureEditorComponent", function() { return TextureEditorComponent; });
+/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
+/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ "../../node_modules/react/index.js");
+/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var _textureCanvasManager__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./textureCanvasManager */ "./components/actionTabs/tabs/propertyGrids/materials/textures/textureCanvasManager.ts");
+
+
+
+__webpack_require__(/*! ./textureEditor.scss */ "./components/actionTabs/tabs/propertyGrids/materials/textures/textureEditor.scss");
+var TextureEditorComponent = /** @class */ (function (_super) {
+    Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"])(TextureEditorComponent, _super);
+    function TextureEditorComponent() {
+        var _this = _super !== null && _super.apply(this, arguments) || this;
+        _this.reactCanvas = react__WEBPACK_IMPORTED_MODULE_1__["createRef"]();
+        return _this;
+    }
+    TextureEditorComponent.prototype.componentDidMount = function () {
+        this._textureCanvasManager = new _textureCanvasManager__WEBPACK_IMPORTED_MODULE_2__["TextureCanvasManager"](this.reactCanvas.current, this.props.texture);
+    };
+    TextureEditorComponent.prototype.componentWillUnmount = function () {
+        this._textureCanvasManager.dispose();
+    };
+    TextureEditorComponent.prototype.render = function () {
+        return react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { id: 'texture-editor' },
+            react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("canvas", { id: "texture-canvas", ref: this.reactCanvas, tabIndex: 1 }));
+    };
+    return TextureEditorComponent;
+}(react__WEBPACK_IMPORTED_MODULE_1__["Component"]));
+
+
+
+/***/ }),
+
 /***/ "./components/actionTabs/tabs/propertyGrids/meshes/bonePropertyGridComponent.tsx":
 /*!***************************************************************************************!*\
   !*** ./components/actionTabs/tabs/propertyGrids/meshes/bonePropertyGridComponent.tsx ***!
@@ -72790,15 +72970,12 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _lineContainerComponent__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../lineContainerComponent */ "./components/actionTabs/lineContainerComponent.tsx");
 /* harmony import */ var _lines_buttonLineComponent__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../lines/buttonLineComponent */ "./components/actionTabs/lines/buttonLineComponent.tsx");
 /* harmony import */ var _lines_checkBoxLineComponent__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../lines/checkBoxLineComponent */ "./components/actionTabs/lines/checkBoxLineComponent.tsx");
-/* harmony import */ var babylonjs_loaders_glTF_2_0_Extensions_KHR_materials_variants__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_variants */ "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_variants");
-/* harmony import */ var babylonjs_loaders_glTF_2_0_Extensions_KHR_materials_variants__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(babylonjs_loaders_glTF_2_0_Extensions_KHR_materials_variants__WEBPACK_IMPORTED_MODULE_5__);
 
 
 
 // import { OptionsLineComponent } from '../../lines/optionsLineComponent';
 
 
-
 var VariantsPropertyGridComponent = /** @class */ (function (_super) {
     Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"])(VariantsPropertyGridComponent, _super);
     function VariantsPropertyGridComponent(props) {
@@ -72807,13 +72984,21 @@ var VariantsPropertyGridComponent = /** @class */ (function (_super) {
         _this._selectedTags = [];
         return _this;
     }
+    VariantsPropertyGridComponent.prototype._getVariantsExtension = function () {
+        var _a;
+        return (_a = this.props.globalState) === null || _a === void 0 ? void 0 : _a.glTFLoaderExtenstions["KHR_materials_variants"];
+    };
     VariantsPropertyGridComponent.prototype.render = function () {
         var _this = this;
-        var variants = babylonjs_loaders_glTF_2_0_Extensions_KHR_materials_variants__WEBPACK_IMPORTED_MODULE_5__["KHR_materials_variants"].GetAvailableVariants(this.props.host);
+        var extension = this._getVariantsExtension();
+        if (!extension) {
+            return null;
+        }
+        var variants = extension.getAvailableVariants(this.props.host);
         if (!variants || variants.length === 0) {
             return null;
         }
-        var lastPickedVariants = babylonjs_loaders_glTF_2_0_Extensions_KHR_materials_variants__WEBPACK_IMPORTED_MODULE_5__["KHR_materials_variants"].GetLastSelectedVariant(this.props.host);
+        var lastPickedVariants = extension.getLastSelectedVariant(this.props.host);
         variants.sort(function (a, b) {
             var aIsActive = lastPickedVariants && lastPickedVariants.indexOf ? lastPickedVariants.indexOf(a) > -1 : lastPickedVariants === a;
             var bIsActive = lastPickedVariants && lastPickedVariants.indexOf ? lastPickedVariants.indexOf(b) > -1 : lastPickedVariants === b;
@@ -72859,7 +73044,7 @@ var VariantsPropertyGridComponent = /** @class */ (function (_super) {
                         }, onSelect: function (value) {
                             if (value) {
                                 _this._selectedTags.push(v);
-                                babylonjs_loaders_glTF_2_0_Extensions_KHR_materials_variants__WEBPACK_IMPORTED_MODULE_5__["KHR_materials_variants"].SelectVariant(_this.props.host, v);
+                                extension.selectVariant(_this.props.host, v);
                             }
                             else {
                                 // Do something on extension?
@@ -72871,7 +73056,7 @@ var VariantsPropertyGridComponent = /** @class */ (function (_super) {
                         } }));
                 }),
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_lines_buttonLineComponent__WEBPACK_IMPORTED_MODULE_3__["ButtonLineComponent"], { label: "Reset", onClick: function () {
-                        babylonjs_loaders_glTF_2_0_Extensions_KHR_materials_variants__WEBPACK_IMPORTED_MODULE_5__["KHR_materials_variants"].Reset(_this.props.host);
+                        extension.reset(_this.props.host);
                         _this._selectedTags = [];
                         _this.forceUpdate();
                     } }))));
@@ -73746,6 +73931,7 @@ var GlobalState = /** @class */ (function () {
         this.onValidationResultsUpdatedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__["Observable"]();
         this.glTFLoaderExtensionDefaults = {};
         this.glTFLoaderDefaults = { "validate": true };
+        this.glTFLoaderExtenstions = {};
         this.blockMutationUpdates = false;
         this.selectedLineContainerTitles = [];
         this.selectedLineContainerTitlesNoFocus = [];
@@ -73798,6 +73984,7 @@ var GlobalState = /** @class */ (function () {
     };
     GlobalState.prototype.prepareGLTFPlugin = function (loader) {
         var _this = this;
+        this.glTFLoaderExtenstions = {};
         var loaderState = this.glTFLoaderDefaults;
         if (loaderState !== undefined) {
             for (var key in loaderState) {
@@ -73811,6 +73998,7 @@ var GlobalState = /** @class */ (function () {
                     extension[key] = extensionState[key];
                 }
             }
+            _this.glTFLoaderExtenstions[extension.name] = extension;
         });
         if (this.validationResults) {
             this.validationResults = null;
@@ -73937,6 +74125,81 @@ var HeaderComponent = /** @class */ (function (_super) {
 
 /***/ }),
 
+/***/ "./components/popupComponent.tsx":
+/*!***************************************!*\
+  !*** ./components/popupComponent.tsx ***!
+  \***************************************/
+/*! exports provided: PopupComponent */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PopupComponent", function() { return PopupComponent; });
+/* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! tslib */ "../../node_modules/tslib/tslib.es6.js");
+/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ "../../node_modules/react/index.js");
+/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-dom */ "../../node_modules/react-dom/index.js");
+/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_2__);
+/* harmony import */ var _inspector__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../inspector */ "./inspector.ts");
+
+
+
+
+var PopupComponent = /** @class */ (function (_super) {
+    Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__extends"])(PopupComponent, _super);
+    function PopupComponent(props) {
+        var _this = _super.call(this, props) || this;
+        _this._container = document.createElement('div');
+        _this._container.id = _this.props.id;
+        _this._window;
+        _this.state = {
+            isComponentMounted: false,
+            blockedByBrowser: false,
+        };
+        return _this;
+    }
+    PopupComponent.prototype.componentDidMount = function () {
+        this.openPopup();
+        this.setState({ isComponentMounted: true });
+    };
+    PopupComponent.prototype.openPopup = function () {
+        var _this = this;
+        var _a = this.props, title = _a.title, size = _a.size, onClose = _a.onClose, onOpen = _a.onOpen;
+        var windowVariableName = "window_" + title;
+        this._container = _inspector__WEBPACK_IMPORTED_MODULE_3__["Inspector"]._CreatePopup(title, windowVariableName, size.width, size.height);
+        this._window = _inspector__WEBPACK_IMPORTED_MODULE_3__["Inspector"][windowVariableName];
+        if (this._window) {
+            onOpen(this._window);
+            this._window.addEventListener('beforeunload', function () { return _this._window && onClose(_this._window); });
+        }
+        else {
+            if (!this._window) {
+                this.setState({ blockedByBrowser: true }, function () {
+                    if (_this.state.blockedByBrowser) {
+                        alert("You might have blocked popups in your browser");
+                        console.warn("Popup window couldn't be created");
+                    }
+                });
+            }
+        }
+    };
+    PopupComponent.prototype.componentWillUnmount = function () {
+        if (this._window) {
+            this._window.close();
+        }
+    };
+    PopupComponent.prototype.render = function () {
+        if (!this.state.isComponentMounted || this._container === null)
+            return null;
+        return react_dom__WEBPACK_IMPORTED_MODULE_2__["createPortal"](this.props.children, this._container);
+    };
+    return PopupComponent;
+}(react__WEBPACK_IMPORTED_MODULE_1__["Component"]));
+
+
+
+/***/ }),
+
 /***/ "./components/propertyChangedEvent.ts":
 /*!********************************************!*\
   !*** ./components/propertyChangedEvent.ts ***!
@@ -76891,17 +77154,6 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_gui_2D_controls_image__;
 
 /***/ }),
 
-/***/ "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_variants":
-/*!************************************************************************************************************************************************************!*\
-  !*** external {"root":["BABYLON","GLTF2","Loader","Extensions"],"commonjs":"babylonjs-loaders","commonjs2":"babylonjs-loaders","amd":"babylonjs-loaders"} ***!
-  \************************************************************************************************************************************************************/
-/*! no static exports found */
-/***/ (function(module, exports) {
-
-module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_loaders_glTF_2_0_Extensions_KHR_materials_variants__;
-
-/***/ }),
-
 /***/ "babylonjs-loaders/glTF/index":
 /*!****************************************************************************************************************************!*\
   !*** external {"root":"BABYLON","commonjs":"babylonjs-loaders","commonjs2":"babylonjs-loaders","amd":"babylonjs-loaders"} ***!

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.max.js.map


+ 44 - 1
dist/preview release/inspector/babylon.inspector.d.ts

@@ -50,6 +50,9 @@ declare module INSPECTOR {
         glTFLoaderDefaults: {
             [key: string]: any;
         };
+        glTFLoaderExtenstions: {
+            [key: string]: BABYLON.IGLTFLoaderExtension;
+        };
         blockMutationUpdates: boolean;
         selectedLineContainerTitles: Array<string>;
         selectedLineContainerTitlesNoFocus: Array<string>;
@@ -1264,6 +1267,42 @@ declare module INSPECTOR {
     }
 }
 declare module INSPECTOR {
+    export class TextureCanvasManager {
+        private _engine;
+        private _scene;
+        private _texture;
+        private _camera;
+        private _canvas;
+        private _scale;
+        private _isPanning;
+        private _mouseX;
+        private _mouseY;
+        private _plane;
+        private _planeMaterial;
+        private static ZOOM_MOUSE_SPEED;
+        private static ZOOM_KEYBOARD_SPEED;
+        private static PAN_SPEED;
+        private static PAN_BUTTON;
+        private static MIN_SCALE;
+        private static MAX_SCALE;
+        constructor(targetCanvas: HTMLCanvasElement, texture: BABYLON.BaseTexture);
+        dispose(): void;
+    }
+}
+declare module INSPECTOR {
+    interface TextureEditorComponentProps {
+        globalState: GlobalState;
+        texture: BABYLON.BaseTexture;
+    }
+    export class TextureEditorComponent extends React.Component<TextureEditorComponentProps> {
+        private _textureCanvasManager;
+        private reactCanvas;
+        componentDidMount(): void;
+        componentWillUnmount(): void;
+        render(): JSX.Element;
+    }
+}
+declare module INSPECTOR {
     interface ITexturePropertyGridComponentProps {
         texture: BABYLON.BaseTexture;
         lockObject: LockObject;
@@ -1273,10 +1312,13 @@ declare module INSPECTOR {
     export class TexturePropertyGridComponent extends React.Component<ITexturePropertyGridComponentProps> {
         private _adtInstrumentation;
         private textureLineRef;
+        private _isTextureEditorOpen;
         constructor(props: ITexturePropertyGridComponentProps);
         componentWillUnmount(): void;
         updateTexture(file: File): void;
-        foreceRefresh(): void;
+        onOpenTextureEditor(): void;
+        onCloseTextureEditor(window: Window | null): void;
+        forceRefresh(): void;
         render(): JSX.Element;
     }
 }
@@ -1510,6 +1552,7 @@ declare module INSPECTOR {
     export class VariantsPropertyGridComponent extends React.Component<IVariantsPropertyGridComponentProps> {
         private _selectedTags;
         constructor(props: IVariantsPropertyGridComponentProps);
+        private _getVariantsExtension;
         render(): JSX.Element | null;
     }
 }

+ 93 - 3
dist/preview release/inspector/babylon.inspector.module.d.ts

@@ -63,6 +63,9 @@ declare module "babylonjs-inspector/components/globalState" {
         glTFLoaderDefaults: {
             [key: string]: any;
         };
+        glTFLoaderExtenstions: {
+            [key: string]: IGLTFLoaderExtension;
+        };
         blockMutationUpdates: boolean;
         selectedLineContainerTitles: Array<string>;
         selectedLineContainerTitlesNoFocus: Array<string>;
@@ -1240,7 +1243,7 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/ani
         render(): JSX.Element;
     }
 }
-declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/animations/popupComponent" {
+declare module "babylonjs-inspector/components/popupComponent" {
     import * as React from "react";
     interface IPopupComponentProps {
         id: string;
@@ -1433,6 +1436,46 @@ declare module "babylonjs-inspector/components/actionTabs/lines/textureLineCompo
         render(): JSX.Element;
     }
 }
+declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/materials/textures/textureCanvasManager" {
+    import { BaseTexture } from 'babylonjs/Materials/Textures/baseTexture';
+    export class TextureCanvasManager {
+        private _engine;
+        private _scene;
+        private _texture;
+        private _camera;
+        private _canvas;
+        private _scale;
+        private _isPanning;
+        private _mouseX;
+        private _mouseY;
+        private _plane;
+        private _planeMaterial;
+        private static ZOOM_MOUSE_SPEED;
+        private static ZOOM_KEYBOARD_SPEED;
+        private static PAN_SPEED;
+        private static PAN_BUTTON;
+        private static MIN_SCALE;
+        private static MAX_SCALE;
+        constructor(targetCanvas: HTMLCanvasElement, texture: BaseTexture);
+        dispose(): void;
+    }
+}
+declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/materials/textures/textureEditorComponent" {
+    import * as React from 'react';
+    import { GlobalState } from "babylonjs-inspector/components/globalState";
+    import { BaseTexture } from 'babylonjs/Materials/Textures/baseTexture';
+    interface TextureEditorComponentProps {
+        globalState: GlobalState;
+        texture: BaseTexture;
+    }
+    export class TextureEditorComponent extends React.Component<TextureEditorComponentProps> {
+        private _textureCanvasManager;
+        private reactCanvas;
+        componentDidMount(): void;
+        componentWillUnmount(): void;
+        render(): JSX.Element;
+    }
+}
 declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/materials/texturePropertyGridComponent" {
     import * as React from "react";
     import { Observable } from "babylonjs/Misc/observable";
@@ -1449,10 +1492,13 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/mat
     export class TexturePropertyGridComponent extends React.Component<ITexturePropertyGridComponentProps> {
         private _adtInstrumentation;
         private textureLineRef;
+        private _isTextureEditorOpen;
         constructor(props: ITexturePropertyGridComponentProps);
         componentWillUnmount(): void;
         updateTexture(file: File): void;
-        foreceRefresh(): void;
+        onOpenTextureEditor(): void;
+        onCloseTextureEditor(window: Window | null): void;
+        forceRefresh(): void;
         render(): JSX.Element;
     }
 }
@@ -1765,6 +1811,7 @@ declare module "babylonjs-inspector/components/actionTabs/tabs/propertyGrids/var
     export class VariantsPropertyGridComponent extends React.Component<IVariantsPropertyGridComponentProps> {
         private _selectedTags;
         constructor(props: IVariantsPropertyGridComponentProps);
+        private _getVariantsExtension;
         render(): JSX.Element | null;
     }
 }
@@ -3714,6 +3761,9 @@ declare module INSPECTOR {
         glTFLoaderDefaults: {
             [key: string]: any;
         };
+        glTFLoaderExtenstions: {
+            [key: string]: BABYLON.IGLTFLoaderExtension;
+        };
         blockMutationUpdates: boolean;
         selectedLineContainerTitles: Array<string>;
         selectedLineContainerTitlesNoFocus: Array<string>;
@@ -4928,6 +4978,42 @@ declare module INSPECTOR {
     }
 }
 declare module INSPECTOR {
+    export class TextureCanvasManager {
+        private _engine;
+        private _scene;
+        private _texture;
+        private _camera;
+        private _canvas;
+        private _scale;
+        private _isPanning;
+        private _mouseX;
+        private _mouseY;
+        private _plane;
+        private _planeMaterial;
+        private static ZOOM_MOUSE_SPEED;
+        private static ZOOM_KEYBOARD_SPEED;
+        private static PAN_SPEED;
+        private static PAN_BUTTON;
+        private static MIN_SCALE;
+        private static MAX_SCALE;
+        constructor(targetCanvas: HTMLCanvasElement, texture: BABYLON.BaseTexture);
+        dispose(): void;
+    }
+}
+declare module INSPECTOR {
+    interface TextureEditorComponentProps {
+        globalState: GlobalState;
+        texture: BABYLON.BaseTexture;
+    }
+    export class TextureEditorComponent extends React.Component<TextureEditorComponentProps> {
+        private _textureCanvasManager;
+        private reactCanvas;
+        componentDidMount(): void;
+        componentWillUnmount(): void;
+        render(): JSX.Element;
+    }
+}
+declare module INSPECTOR {
     interface ITexturePropertyGridComponentProps {
         texture: BABYLON.BaseTexture;
         lockObject: LockObject;
@@ -4937,10 +5023,13 @@ declare module INSPECTOR {
     export class TexturePropertyGridComponent extends React.Component<ITexturePropertyGridComponentProps> {
         private _adtInstrumentation;
         private textureLineRef;
+        private _isTextureEditorOpen;
         constructor(props: ITexturePropertyGridComponentProps);
         componentWillUnmount(): void;
         updateTexture(file: File): void;
-        foreceRefresh(): void;
+        onOpenTextureEditor(): void;
+        onCloseTextureEditor(window: Window | null): void;
+        forceRefresh(): void;
         render(): JSX.Element;
     }
 }
@@ -5174,6 +5263,7 @@ declare module INSPECTOR {
     export class VariantsPropertyGridComponent extends React.Component<IVariantsPropertyGridComponentProps> {
         private _selectedTags;
         constructor(props: IVariantsPropertyGridComponentProps);
+        private _getVariantsExtension;
         render(): JSX.Element | null;
     }
 }

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/libktx.js


BIN
dist/preview release/libktx.wasm


+ 31 - 0
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -1251,6 +1251,14 @@ var KHR_materials_variants = /** @class */ (function () {
         return Object.keys(extensionMetadata.variants);
     };
     /**
+     * Gets the list of available variant tag names for this asset.
+     * @param rootMesh The glTF root mesh
+     * @returns the list of all the variant names for this model
+     */
+    KHR_materials_variants.prototype.getAvailableVariants = function (rootMesh) {
+        return KHR_materials_variants.GetAvailableVariants(rootMesh);
+    };
+    /**
      * Select a variant given a variant tag name or a list of variant tag names.
      * @param rootMesh The glTF root mesh
      * @param variantName The variant name(s) to select.
@@ -1281,6 +1289,14 @@ var KHR_materials_variants = /** @class */ (function () {
         extensionMetadata.lastSelected = variantName;
     };
     /**
+     * Select a variant given a variant tag name or a list of variant tag names.
+     * @param rootMesh The glTF root mesh
+     * @param variantName The variant name(s) to select.
+     */
+    KHR_materials_variants.prototype.selectVariant = function (rootMesh, variantName) {
+        return KHR_materials_variants.SelectVariant(rootMesh, variantName);
+    };
+    /**
      * Reset back to the original before selecting a variant.
      * @param rootMesh The glTF root mesh
      */
@@ -1296,6 +1312,13 @@ var KHR_materials_variants = /** @class */ (function () {
         extensionMetadata.lastSelected = null;
     };
     /**
+     * Reset back to the original before selecting a variant.
+     * @param rootMesh The glTF root mesh
+     */
+    KHR_materials_variants.prototype.reset = function (rootMesh) {
+        return KHR_materials_variants.Reset(rootMesh);
+    };
+    /**
      * Gets the last selected variant tag name(s) or null if original.
      * @param rootMesh The glTF root mesh
      * @returns The selected variant tag name(s).
@@ -1307,6 +1330,14 @@ var KHR_materials_variants = /** @class */ (function () {
         }
         return extensionMetadata.lastSelected;
     };
+    /**
+     * Gets the last selected variant tag name(s) or null if original.
+     * @param rootMesh The glTF root mesh
+     * @returns The selected variant tag name(s).
+     */
+    KHR_materials_variants.prototype.getLastSelectedVariant = function (rootMesh) {
+        return KHR_materials_variants.GetLastSelectedVariant(rootMesh);
+    };
     KHR_materials_variants._GetExtensionMetadata = function (rootMesh) {
         var _a, _b;
         return ((_b = (_a = rootMesh === null || rootMesh === void 0 ? void 0 : rootMesh.metadata) === null || _a === void 0 ? void 0 : _a.gltf) === null || _b === void 0 ? void 0 : _b[NAME]) || null;

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.js.map


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 31 - 0
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -3865,6 +3865,14 @@ var KHR_materials_variants = /** @class */ (function () {
         return Object.keys(extensionMetadata.variants);
     };
     /**
+     * Gets the list of available variant tag names for this asset.
+     * @param rootMesh The glTF root mesh
+     * @returns the list of all the variant names for this model
+     */
+    KHR_materials_variants.prototype.getAvailableVariants = function (rootMesh) {
+        return KHR_materials_variants.GetAvailableVariants(rootMesh);
+    };
+    /**
      * Select a variant given a variant tag name or a list of variant tag names.
      * @param rootMesh The glTF root mesh
      * @param variantName The variant name(s) to select.
@@ -3895,6 +3903,14 @@ var KHR_materials_variants = /** @class */ (function () {
         extensionMetadata.lastSelected = variantName;
     };
     /**
+     * Select a variant given a variant tag name or a list of variant tag names.
+     * @param rootMesh The glTF root mesh
+     * @param variantName The variant name(s) to select.
+     */
+    KHR_materials_variants.prototype.selectVariant = function (rootMesh, variantName) {
+        return KHR_materials_variants.SelectVariant(rootMesh, variantName);
+    };
+    /**
      * Reset back to the original before selecting a variant.
      * @param rootMesh The glTF root mesh
      */
@@ -3910,6 +3926,13 @@ var KHR_materials_variants = /** @class */ (function () {
         extensionMetadata.lastSelected = null;
     };
     /**
+     * Reset back to the original before selecting a variant.
+     * @param rootMesh The glTF root mesh
+     */
+    KHR_materials_variants.prototype.reset = function (rootMesh) {
+        return KHR_materials_variants.Reset(rootMesh);
+    };
+    /**
      * Gets the last selected variant tag name(s) or null if original.
      * @param rootMesh The glTF root mesh
      * @returns The selected variant tag name(s).
@@ -3921,6 +3944,14 @@ var KHR_materials_variants = /** @class */ (function () {
         }
         return extensionMetadata.lastSelected;
     };
+    /**
+     * Gets the last selected variant tag name(s) or null if original.
+     * @param rootMesh The glTF root mesh
+     * @returns The selected variant tag name(s).
+     */
+    KHR_materials_variants.prototype.getLastSelectedVariant = function (rootMesh) {
+        return KHR_materials_variants.GetLastSelectedVariant(rootMesh);
+    };
     KHR_materials_variants._GetExtensionMetadata = function (rootMesh) {
         var _a, _b;
         return ((_b = (_a = rootMesh === null || rootMesh === void 0 ? void 0 : rootMesh.metadata) === null || _a === void 0 ? void 0 : _a.gltf) === null || _b === void 0 ? void 0 : _b[NAME]) || null;

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.js.map


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 23 - 0
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -1949,22 +1949,45 @@ declare module BABYLON.GLTF2.Loader.Extensions {
          */
         static GetAvailableVariants(rootMesh: Mesh): string[];
         /**
+         * Gets the list of available variant tag names for this asset.
+         * @param rootMesh The glTF root mesh
+         * @returns the list of all the variant names for this model
+         */
+        getAvailableVariants(rootMesh: Mesh): string[];
+        /**
          * Select a variant given a variant tag name or a list of variant tag names.
          * @param rootMesh The glTF root mesh
          * @param variantName The variant name(s) to select.
          */
         static SelectVariant(rootMesh: Mesh, variantName: string | string[]): void;
         /**
+         * Select a variant given a variant tag name or a list of variant tag names.
+         * @param rootMesh The glTF root mesh
+         * @param variantName The variant name(s) to select.
+         */
+        selectVariant(rootMesh: Mesh, variantName: string | string[]): void;
+        /**
          * Reset back to the original before selecting a variant.
          * @param rootMesh The glTF root mesh
          */
         static Reset(rootMesh: Mesh): void;
         /**
+         * Reset back to the original before selecting a variant.
+         * @param rootMesh The glTF root mesh
+         */
+        reset(rootMesh: Mesh): void;
+        /**
          * Gets the last selected variant tag name(s) or null if original.
          * @param rootMesh The glTF root mesh
          * @returns The selected variant tag name(s).
          */
         static GetLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]>;
+        /**
+         * Gets the last selected variant tag name(s) or null if original.
+         * @param rootMesh The glTF root mesh
+         * @returns The selected variant tag name(s).
+         */
+        getLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]>;
         private static _GetExtensionMetadata;
         /** @hidden */
         _loadMeshPrimitiveAsync(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Nullable<Promise<AbstractMesh>>;

+ 31 - 0
dist/preview release/loaders/babylonjs.loaders.js

@@ -5245,6 +5245,14 @@ var KHR_materials_variants = /** @class */ (function () {
         return Object.keys(extensionMetadata.variants);
     };
     /**
+     * Gets the list of available variant tag names for this asset.
+     * @param rootMesh The glTF root mesh
+     * @returns the list of all the variant names for this model
+     */
+    KHR_materials_variants.prototype.getAvailableVariants = function (rootMesh) {
+        return KHR_materials_variants.GetAvailableVariants(rootMesh);
+    };
+    /**
      * Select a variant given a variant tag name or a list of variant tag names.
      * @param rootMesh The glTF root mesh
      * @param variantName The variant name(s) to select.
@@ -5275,6 +5283,14 @@ var KHR_materials_variants = /** @class */ (function () {
         extensionMetadata.lastSelected = variantName;
     };
     /**
+     * Select a variant given a variant tag name or a list of variant tag names.
+     * @param rootMesh The glTF root mesh
+     * @param variantName The variant name(s) to select.
+     */
+    KHR_materials_variants.prototype.selectVariant = function (rootMesh, variantName) {
+        return KHR_materials_variants.SelectVariant(rootMesh, variantName);
+    };
+    /**
      * Reset back to the original before selecting a variant.
      * @param rootMesh The glTF root mesh
      */
@@ -5290,6 +5306,13 @@ var KHR_materials_variants = /** @class */ (function () {
         extensionMetadata.lastSelected = null;
     };
     /**
+     * Reset back to the original before selecting a variant.
+     * @param rootMesh The glTF root mesh
+     */
+    KHR_materials_variants.prototype.reset = function (rootMesh) {
+        return KHR_materials_variants.Reset(rootMesh);
+    };
+    /**
      * Gets the last selected variant tag name(s) or null if original.
      * @param rootMesh The glTF root mesh
      * @returns The selected variant tag name(s).
@@ -5301,6 +5324,14 @@ var KHR_materials_variants = /** @class */ (function () {
         }
         return extensionMetadata.lastSelected;
     };
+    /**
+     * Gets the last selected variant tag name(s) or null if original.
+     * @param rootMesh The glTF root mesh
+     * @returns The selected variant tag name(s).
+     */
+    KHR_materials_variants.prototype.getLastSelectedVariant = function (rootMesh) {
+        return KHR_materials_variants.GetLastSelectedVariant(rootMesh);
+    };
     KHR_materials_variants._GetExtensionMetadata = function (rootMesh) {
         var _a, _b;
         return ((_b = (_a = rootMesh === null || rootMesh === void 0 ? void 0 : rootMesh.metadata) === null || _a === void 0 ? void 0 : _a.gltf) === null || _b === void 0 ? void 0 : _b[NAME]) || null;

Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.js.map


Разница между файлами не показана из-за своего большого размера
+ 1 - 1
dist/preview release/loaders/babylonjs.loaders.min.js


+ 46 - 0
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -2099,22 +2099,45 @@ declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_variants" {
          */
         static GetAvailableVariants(rootMesh: Mesh): string[];
         /**
+         * Gets the list of available variant tag names for this asset.
+         * @param rootMesh The glTF root mesh
+         * @returns the list of all the variant names for this model
+         */
+        getAvailableVariants(rootMesh: Mesh): string[];
+        /**
          * Select a variant given a variant tag name or a list of variant tag names.
          * @param rootMesh The glTF root mesh
          * @param variantName The variant name(s) to select.
          */
         static SelectVariant(rootMesh: Mesh, variantName: string | string[]): void;
         /**
+         * Select a variant given a variant tag name or a list of variant tag names.
+         * @param rootMesh The glTF root mesh
+         * @param variantName The variant name(s) to select.
+         */
+        selectVariant(rootMesh: Mesh, variantName: string | string[]): void;
+        /**
          * Reset back to the original before selecting a variant.
          * @param rootMesh The glTF root mesh
          */
         static Reset(rootMesh: Mesh): void;
         /**
+         * Reset back to the original before selecting a variant.
+         * @param rootMesh The glTF root mesh
+         */
+        reset(rootMesh: Mesh): void;
+        /**
          * Gets the last selected variant tag name(s) or null if original.
          * @param rootMesh The glTF root mesh
          * @returns The selected variant tag name(s).
          */
         static GetLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]>;
+        /**
+         * Gets the last selected variant tag name(s) or null if original.
+         * @param rootMesh The glTF root mesh
+         * @returns The selected variant tag name(s).
+         */
+        getLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]>;
         private static _GetExtensionMetadata;
         /** @hidden */
         _loadMeshPrimitiveAsync(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Nullable<Promise<AbstractMesh>>;
@@ -4791,22 +4814,45 @@ declare module BABYLON.GLTF2.Loader.Extensions {
          */
         static GetAvailableVariants(rootMesh: Mesh): string[];
         /**
+         * Gets the list of available variant tag names for this asset.
+         * @param rootMesh The glTF root mesh
+         * @returns the list of all the variant names for this model
+         */
+        getAvailableVariants(rootMesh: Mesh): string[];
+        /**
          * Select a variant given a variant tag name or a list of variant tag names.
          * @param rootMesh The glTF root mesh
          * @param variantName The variant name(s) to select.
          */
         static SelectVariant(rootMesh: Mesh, variantName: string | string[]): void;
         /**
+         * Select a variant given a variant tag name or a list of variant tag names.
+         * @param rootMesh The glTF root mesh
+         * @param variantName The variant name(s) to select.
+         */
+        selectVariant(rootMesh: Mesh, variantName: string | string[]): void;
+        /**
          * Reset back to the original before selecting a variant.
          * @param rootMesh The glTF root mesh
          */
         static Reset(rootMesh: Mesh): void;
         /**
+         * Reset back to the original before selecting a variant.
+         * @param rootMesh The glTF root mesh
+         */
+        reset(rootMesh: Mesh): void;
+        /**
          * Gets the last selected variant tag name(s) or null if original.
          * @param rootMesh The glTF root mesh
          * @returns The selected variant tag name(s).
          */
         static GetLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]>;
+        /**
+         * Gets the last selected variant tag name(s) or null if original.
+         * @param rootMesh The glTF root mesh
+         * @returns The selected variant tag name(s).
+         */
+        getLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]>;
         private static _GetExtensionMetadata;
         /** @hidden */
         _loadMeshPrimitiveAsync(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Nullable<Promise<AbstractMesh>>;

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

@@ -1 +1 @@
-{"thinEngineOnly":116308,"engineOnly":152744,"sceneOnly":515374,"minGridMaterial":652717,"minStandardMaterial":801365}
+{"thinEngineOnly":116308,"engineOnly":152744,"sceneOnly":515374,"minGridMaterial":652684,"minStandardMaterial":801332}

+ 8 - 0
dist/preview release/viewer/babylon.module.d.ts

@@ -49940,6 +49940,10 @@ declare module "babylonjs/XR/webXREnterExitUI" {
          * A list of optional features to init the session with
          */
         optionalFeatures?: string[];
+        /**
+         * A list of optional features to init the session with
+         */
+        requiredFeatures?: string[];
     }
     /**
      * UI to allow the user to enter/exit XR mode
@@ -126383,6 +126387,10 @@ declare module BABYLON {
          * A list of optional features to init the session with
          */
         optionalFeatures?: string[];
+        /**
+         * A list of optional features to init the session with
+         */
+        requiredFeatures?: string[];
     }
     /**
      * UI to allow the user to enter/exit XR mode

Разница между файлами не показана из-за своего большого размера
+ 5 - 5
dist/preview release/viewer/babylon.viewer.js


Разница между файлами не показана из-за своего большого размера
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


+ 46 - 0
dist/preview release/viewer/babylonjs.loaders.module.d.ts

@@ -2099,22 +2099,45 @@ declare module "babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_variants" {
          */
         static GetAvailableVariants(rootMesh: Mesh): string[];
         /**
+         * Gets the list of available variant tag names for this asset.
+         * @param rootMesh The glTF root mesh
+         * @returns the list of all the variant names for this model
+         */
+        getAvailableVariants(rootMesh: Mesh): string[];
+        /**
          * Select a variant given a variant tag name or a list of variant tag names.
          * @param rootMesh The glTF root mesh
          * @param variantName The variant name(s) to select.
          */
         static SelectVariant(rootMesh: Mesh, variantName: string | string[]): void;
         /**
+         * Select a variant given a variant tag name or a list of variant tag names.
+         * @param rootMesh The glTF root mesh
+         * @param variantName The variant name(s) to select.
+         */
+        selectVariant(rootMesh: Mesh, variantName: string | string[]): void;
+        /**
          * Reset back to the original before selecting a variant.
          * @param rootMesh The glTF root mesh
          */
         static Reset(rootMesh: Mesh): void;
         /**
+         * Reset back to the original before selecting a variant.
+         * @param rootMesh The glTF root mesh
+         */
+        reset(rootMesh: Mesh): void;
+        /**
          * Gets the last selected variant tag name(s) or null if original.
          * @param rootMesh The glTF root mesh
          * @returns The selected variant tag name(s).
          */
         static GetLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]>;
+        /**
+         * Gets the last selected variant tag name(s) or null if original.
+         * @param rootMesh The glTF root mesh
+         * @returns The selected variant tag name(s).
+         */
+        getLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]>;
         private static _GetExtensionMetadata;
         /** @hidden */
         _loadMeshPrimitiveAsync(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Nullable<Promise<AbstractMesh>>;
@@ -4791,22 +4814,45 @@ declare module BABYLON.GLTF2.Loader.Extensions {
          */
         static GetAvailableVariants(rootMesh: Mesh): string[];
         /**
+         * Gets the list of available variant tag names for this asset.
+         * @param rootMesh The glTF root mesh
+         * @returns the list of all the variant names for this model
+         */
+        getAvailableVariants(rootMesh: Mesh): string[];
+        /**
          * Select a variant given a variant tag name or a list of variant tag names.
          * @param rootMesh The glTF root mesh
          * @param variantName The variant name(s) to select.
          */
         static SelectVariant(rootMesh: Mesh, variantName: string | string[]): void;
         /**
+         * Select a variant given a variant tag name or a list of variant tag names.
+         * @param rootMesh The glTF root mesh
+         * @param variantName The variant name(s) to select.
+         */
+        selectVariant(rootMesh: Mesh, variantName: string | string[]): void;
+        /**
          * Reset back to the original before selecting a variant.
          * @param rootMesh The glTF root mesh
          */
         static Reset(rootMesh: Mesh): void;
         /**
+         * Reset back to the original before selecting a variant.
+         * @param rootMesh The glTF root mesh
+         */
+        reset(rootMesh: Mesh): void;
+        /**
          * Gets the last selected variant tag name(s) or null if original.
          * @param rootMesh The glTF root mesh
          * @returns The selected variant tag name(s).
          */
         static GetLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]>;
+        /**
+         * Gets the last selected variant tag name(s) or null if original.
+         * @param rootMesh The glTF root mesh
+         * @returns The selected variant tag name(s).
+         */
+        getLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]>;
         private static _GetExtensionMetadata;
         /** @hidden */
         _loadMeshPrimitiveAsync(context: string, name: string, node: INode, mesh: IMesh, primitive: IMeshPrimitive, assign: (babylonMesh: AbstractMesh) => void): Nullable<Promise<AbstractMesh>>;

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

@@ -67,6 +67,7 @@
 - Added support for recording GIF ([Deltakosh](https://github.com/deltakosh))
 - Popup Window available (To be used in Curve Editor) ([pixelspace](https://github.com/devpixelspace))
 - Add support to update inspector when switching to a new scene ([belfortk](https://github.com/belfortk))
+- View textures in pop out window with zoom & pan ([DarraghBurkeMS](https://github.com/DarraghBurkeMS))
 
 ### Cameras
 

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

@@ -19,7 +19,7 @@ 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 '../animations/popupComponent';
+import { PopupComponent } from '../../../../popupComponent';
 
 interface IAnimationGridComponentProps {
   globalState: GlobalState;

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

@@ -11,7 +11,7 @@ import { TextLineComponent } from '../../../lines/textLineComponent';
 import { LockObject } from '../lockObject';
 import { GlobalState } from '../../../../globalState';
 import { TextInputLineComponent } from '../../../lines/textInputLineComponent';
-import { PopupComponent } from '../animations/popupComponent';
+import { PopupComponent } from '../../../../popupComponent';
 import { AnimationCurveEditorComponent } from '../animations/animationCurveEditorComponent';
 import { AnimationGroup } from 'babylonjs/Animations/animationGroup';
 

+ 42 - 5
inspector/src/components/actionTabs/tabs/propertyGrids/materials/texturePropertyGridComponent.tsx

@@ -27,6 +27,10 @@ import { ButtonLineComponent } from '../../../lines/buttonLineComponent';
 import { TextInputLineComponent } from '../../../lines/textInputLineComponent';
 import { AnimationGridComponent } from '../animations/animationPropertyGridComponent';
 
+import { Engine } from 'babylonjs/Engines/engine';
+import { PopupComponent } from '../../../../popupComponent';
+import { TextureEditorComponent } from './textures/textureEditorComponent';
+
 interface ITexturePropertyGridComponentProps {
     texture: BaseTexture,
     lockObject: LockObject,
@@ -38,6 +42,8 @@ export class TexturePropertyGridComponent extends React.Component<ITextureProper
 
     private _adtInstrumentation: Nullable<AdvancedDynamicTextureInstrumentation>;
     private textureLineRef: React.RefObject<TextureLineComponent>;
+
+    private _isTextureEditorOpen = false;
     
 
     constructor(props: ITexturePropertyGridComponentProps) {
@@ -83,16 +89,27 @@ export class TexturePropertyGridComponent extends React.Component<ITextureProper
                         extension = ".env";
                     }
 
-                    (texture as CubeTexture).updateURL(base64data, extension, () => this.foreceRefresh());
+                    (texture as CubeTexture).updateURL(base64data, extension, () => this.forceRefresh());
                 } else {
-                    (texture as Texture).updateURL(base64data, null, () => this.foreceRefresh());
+                    (texture as Texture).updateURL(base64data, null, () => this.forceRefresh());
                 }
             };
 
         }, undefined, true);
-    }    
+    }
+
+    onOpenTextureEditor() {
+        this._isTextureEditorOpen = true;
+    }
+    
+    onCloseTextureEditor(window: Window | null) {
+        this._isTextureEditorOpen = false;
+        if (window !== null) {
+            window.close();
+        }
+    }
 
-    foreceRefresh() {
+    forceRefresh() {
         this.forceUpdate();
         (this.textureLineRef.current as TextureLineComponent).updatePreview();
     }
@@ -132,16 +149,36 @@ export class TexturePropertyGridComponent extends React.Component<ITextureProper
             }
         }
 
+        const editable = texture.textureType != Engine.TEXTURETYPE_FLOAT && texture.textureType != Engine.TEXTURETYPE_FLOAT_32_UNSIGNED_INT_24_8_REV && texture.textureType !== Engine.TEXTURETYPE_HALF_FLOAT;
+
         return (
             <div className="pane">
                 <LineContainerComponent globalState={this.props.globalState} title="PREVIEW">
                     <TextureLineComponent ref={this.textureLineRef} texture={texture} width={256} height={256} globalState={this.props.globalState} />
                     <FileButtonLineComponent label="Load texture from file" onClick={(file) => this.updateTexture(file)} accept=".jpg, .png, .tga, .dds, .env" />
+                    {editable &&
+                        <ButtonLineComponent label="View" onClick={() => this.onOpenTextureEditor()} />
+                    }
                     <TextInputLineComponent label="URL" value={textureUrl} lockObject={this.props.lockObject} onChange={url => {
                         (texture as Texture).updateURL(url);
-                        this.foreceRefresh();
+                        this.forceRefresh();
                     }} />
                 </LineContainerComponent>
+                {this._isTextureEditorOpen && (
+                <PopupComponent
+                  id='texture-editor'
+                  title='Texture Editor'
+                  size={{ width: 1024, height: 490 }}
+                  onOpen={(window: Window) => {}}
+                  onClose={(window: Window) =>
+                    this.onCloseTextureEditor(window)
+                  }
+                >
+                    <TextureEditorComponent
+                        globalState={this.props.globalState}
+                        texture={this.props.texture}
+                    />
+                </PopupComponent>)}
                 <CustomPropertyGridComponent globalState={this.props.globalState} target={texture}
                     lockObject={this.props.lockObject}
                     onPropertyChangedObservable={this.props.onPropertyChangedObservable} />

+ 156 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/materials/textures/textureCanvasManager.ts

@@ -0,0 +1,156 @@
+import { Engine } from 'babylonjs/Engines/engine';
+import { Scene } from 'babylonjs/scene';
+import { Vector3 } from 'babylonjs/Maths/math.vector';
+import { Color4 } from 'babylonjs/Maths/math.color';
+import { FreeCamera } from 'babylonjs/Cameras/freeCamera';
+
+import { PlaneBuilder } from 'babylonjs/Meshes/Builders/planeBuilder';
+import { Mesh } from 'babylonjs/Meshes/mesh';
+import { Camera } from 'babylonjs/Cameras/camera';
+import { DynamicTexture } from 'babylonjs/Materials/Textures/dynamicTexture';
+import { BaseTexture } from 'babylonjs/Materials/Textures/baseTexture';
+import { NodeMaterial } from 'babylonjs/Materials/Node/nodeMaterial';
+
+import { PointerEventTypes } from 'babylonjs/Events/pointerEvents';
+import { KeyboardEventTypes } from 'babylonjs/Events/keyboardEvents';
+
+export class TextureCanvasManager {
+    private _engine: Engine;
+    private _scene: Scene;
+    private _texture: DynamicTexture;
+    private _camera: FreeCamera;
+    private _canvas : HTMLCanvasElement;
+
+    private _scale : number;
+    private _isPanning : boolean;
+    private _mouseX : number;
+    private _mouseY : number;
+
+    private _plane : Mesh;
+    private _planeMaterial : NodeMaterial;
+
+    private static ZOOM_MOUSE_SPEED : number = 0.0005;
+    private static ZOOM_KEYBOARD_SPEED : number = 0.2;
+    private static PAN_SPEED : number = 0.002;
+    private static PAN_BUTTON : number = 0; // left mouse button
+    private static MIN_SCALE : number = 0.01;
+    private static MAX_SCALE : number = 10;
+
+    public constructor(targetCanvas: HTMLCanvasElement, texture: BaseTexture) {
+        this._canvas = targetCanvas;
+
+        this._engine = new Engine(targetCanvas, true);
+        this._scene = new Scene(this._engine);
+        this._scene.clearColor = new Color4(0.2, 0.2, 0.2, 1.0);
+
+        this._camera = new FreeCamera("Camera", new Vector3(0, 0, -1), this._scene);
+        this._camera.mode = Camera.ORTHOGRAPHIC_CAMERA;
+
+        if (texture) {
+            /* Grab image data from original texture and paint it onto the context of a DynamicTexture */
+            const pixelData = texture.readPixels()!;
+            const arr = new Uint8ClampedArray(pixelData.buffer);
+            let imgData = new ImageData(arr, texture.getSize().width, texture.getSize().height);
+            this._texture = new DynamicTexture("texture", texture.getSize(), this._scene, false);
+            const ctx = this._texture.getContext();
+            ctx.putImageData(imgData, 0, 0);
+            this._texture.update();
+            this._texture.hasAlpha = texture.hasAlpha;
+        } else {
+            /* If we don't have a texture to start with, just generate a white rectangle */
+            this._texture = new DynamicTexture("texture",  256, this._scene, false);
+            const ctx = this._texture.getContext();
+            ctx.fillStyle = 'white';
+            ctx.fillRect(0, 0, 256, 256);
+            this._texture.update();
+        }
+
+        this._texture.updateSamplingMode(Engine.TEXTURE_NEAREST_LINEAR);
+        const textureRatio = this._texture.getSize().width / this._texture.getSize().height;
+
+        this._plane = PlaneBuilder.CreatePlane("plane", {width: textureRatio, height: 1}, this._scene);
+        NodeMaterial.ParseFromSnippetAsync("#TPSEV2#3", this._scene)
+            .then((material) => {
+                this._planeMaterial = material;
+                this._planeMaterial.getTextureBlocks()[0].texture = this._texture;
+                this._plane.material = this._planeMaterial;
+                this._canvas.focus();
+            });
+        this._plane.enableEdgesRendering();
+        this._plane.edgesWidth = 4.0;
+        this._plane.edgesColor = new Color4(1,1,1,1);
+
+        this._engine.runRenderLoop(() => {
+            this._engine.resize();
+            this._scene.render();
+
+        });
+
+        this._scale = 1;
+        this._isPanning = false;
+
+        this._scene.onBeforeRenderObservable.add(() => {
+            let ratio = this._canvas?.width / this._canvas?.height;
+            this._camera.orthoBottom = -this._scale;
+            this._camera.orthoTop = this._scale;
+            this._camera.orthoLeft = -this._scale * ratio;
+            this._camera.orthoRight = this._scale * ratio;
+        })
+
+        this._scene.onPointerObservable.add((pointerInfo) => {
+            switch (pointerInfo.type) {
+                case PointerEventTypes.POINTERWHEEL:
+                    const event = pointerInfo.event as MouseWheelEvent;
+                    this._scale += (event.deltaY * TextureCanvasManager.ZOOM_MOUSE_SPEED * this._scale);
+                    this._scale = Math.min(Math.max(this._scale, TextureCanvasManager.MIN_SCALE), TextureCanvasManager.MAX_SCALE);
+                    break;
+                case PointerEventTypes.POINTERDOWN:
+                    if (pointerInfo.event.button === TextureCanvasManager.PAN_BUTTON) {
+                        this._isPanning = true;
+                        this._mouseX = pointerInfo.event.x;
+                        this._mouseY = pointerInfo.event.y;
+                    }
+                    break;
+                case PointerEventTypes.POINTERUP:
+                    if (pointerInfo.event.button === TextureCanvasManager.PAN_BUTTON) {
+                        this._isPanning = false;
+                    }
+                    break;
+                case PointerEventTypes.POINTERMOVE:
+                    if (this._isPanning) {
+                        this._camera.position.x -= (pointerInfo.event.x - this._mouseX) * this._scale * TextureCanvasManager.PAN_SPEED;
+                        this._camera.position.y += (pointerInfo.event.y - this._mouseY) * this._scale * TextureCanvasManager.PAN_SPEED;
+                        this._mouseX = pointerInfo.event.x;
+                        this._mouseY = pointerInfo.event.y;
+                    }
+                    break;
+            }
+        })
+
+        this._scene.onKeyboardObservable.add((kbInfo) => {
+            switch(kbInfo.type) {
+                case KeyboardEventTypes.KEYDOWN:
+                    if (kbInfo.event.key == "+") {
+                        this._scale -= TextureCanvasManager.ZOOM_KEYBOARD_SPEED * this._scale;
+                    }
+                    if (kbInfo.event.key == "-") {
+                        this._scale += TextureCanvasManager.ZOOM_KEYBOARD_SPEED * this._scale;
+                    }
+                    this._scale = Math.min(Math.max(this._scale, TextureCanvasManager.MIN_SCALE), TextureCanvasManager.MAX_SCALE);
+                    break;
+            }
+        })
+
+    }
+
+    public dispose() {
+        if (this._planeMaterial) {
+            this._planeMaterial.dispose();
+        }
+        this._texture.dispose();
+        this._plane.dispose();
+        this._camera.dispose();
+        this._scene.dispose();
+        this._engine.dispose();
+    }
+} 

+ 4 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/materials/textures/textureEditor.scss

@@ -0,0 +1,4 @@
+#texture-canvas {
+    width: 100%;
+    height: 100%;
+}

+ 30 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/materials/textures/textureEditorComponent.tsx

@@ -0,0 +1,30 @@
+import * as React from 'react';
+import { GlobalState } from '../../../../../globalState';
+import { BaseTexture } from 'babylonjs/Materials/Textures/baseTexture';
+import { TextureCanvasManager } from './textureCanvasManager';
+
+require('./textureEditor.scss');
+
+interface TextureEditorComponentProps {
+    globalState: GlobalState;
+    texture: BaseTexture;
+}
+
+export class TextureEditorComponent extends React.Component<TextureEditorComponentProps> {
+    private _textureCanvasManager: TextureCanvasManager;
+    private reactCanvas = React.createRef<HTMLCanvasElement>();
+
+    componentDidMount() {
+        this._textureCanvasManager = new TextureCanvasManager(this.reactCanvas.current!, this.props.texture);
+    }
+
+    componentWillUnmount() {
+        this._textureCanvasManager.dispose();
+    }
+
+    render() {
+        return <div id='texture-editor'>
+            <canvas id="texture-canvas" ref={this.reactCanvas} tabIndex={1}></canvas>
+        </div>
+    }
+}

+ 15 - 5
inspector/src/components/actionTabs/tabs/propertyGrids/variantsPropertyGridComponent.tsx

@@ -1,6 +1,7 @@
 import * as React from "react";
 
 import { Observable } from "babylonjs/Misc/observable";
+import { Nullable } from 'babylonjs/types';
 
 import { PropertyChangedEvent } from "../../../propertyChangedEvent";
 import { LineContainerComponent } from "../../lineContainerComponent";
@@ -9,7 +10,8 @@ import { GlobalState } from "../../../globalState";
 // import { OptionsLineComponent } from '../../lines/optionsLineComponent';
 import { ButtonLineComponent } from '../../lines/buttonLineComponent';
 import { CheckBoxLineComponent } from '../../lines/checkBoxLineComponent';
-import { KHR_materials_variants } from 'babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_variants';
+
+declare type KHR_materials_variants = import("babylonjs-loaders/glTF/2.0/Extensions/KHR_materials_variants").KHR_materials_variants;
 
 interface IVariantsPropertyGridComponentProps {
     globalState: GlobalState;
@@ -26,14 +28,22 @@ export class VariantsPropertyGridComponent extends React.Component<IVariantsProp
         super(props);
     }
 
+    private _getVariantsExtension(): Nullable<KHR_materials_variants> {
+        return this.props.globalState?.glTFLoaderExtenstions["KHR_materials_variants"] as KHR_materials_variants;
+    }
+
     render() {
-        let variants: string[] = KHR_materials_variants.GetAvailableVariants(this.props.host);
+        const extension = this._getVariantsExtension();
+        if (!extension) {
+            return null;
+        }
+        let variants: string[] = extension.getAvailableVariants(this.props.host);
 
         if (!variants || variants.length === 0) {
             return null;
         }
 
-        let lastPickedVariants = KHR_materials_variants.GetLastSelectedVariant(this.props.host);
+        let lastPickedVariants = extension.getLastSelectedVariant(this.props.host);
 
         variants.sort((a, b) => {
             let aIsActive = lastPickedVariants && lastPickedVariants.indexOf ? lastPickedVariants.indexOf(a) > -1 : lastPickedVariants === a;
@@ -93,7 +103,7 @@ export class VariantsPropertyGridComponent extends React.Component<IVariantsProp
                                         onSelect={(value) => {
                                             if (value) {
                                                 this._selectedTags.push(v);
-                                                KHR_materials_variants.SelectVariant(this.props.host, v);
+                                                extension.selectVariant(this.props.host, v);
                                             } else {
                                                 // Do something on extension?
                                                 let index = this._selectedTags.indexOf(v);
@@ -135,7 +145,7 @@ export class VariantsPropertyGridComponent extends React.Component<IVariantsProp
                         }}
                     /> */}
                     <ButtonLineComponent label="Reset" onClick={() => {
-                        KHR_materials_variants.Reset(this.props.host);
+                        extension.reset(this.props.host);
                         this._selectedTags = [];
                         this.forceUpdate();
                     }} />

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

@@ -29,6 +29,7 @@ export class GlobalState {
     public onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
     public glTFLoaderExtensionDefaults: { [name: string]: { [key: string]: any } } = {};
     public glTFLoaderDefaults: { [key: string]: any } = { "validate": true };
+    public glTFLoaderExtenstions: { [key: string]: IGLTFLoaderExtension } = { };
 
     public blockMutationUpdates = false;
     public selectedLineContainerTitles:Array<string> = [];    
@@ -85,6 +86,7 @@ export class GlobalState {
     }
 
     public prepareGLTFPlugin(loader: GLTFFileLoader) {
+        this.glTFLoaderExtenstions = { };
         var loaderState = this.glTFLoaderDefaults;
         if (loaderState !== undefined) {
             for (const key in loaderState) {
@@ -99,6 +101,8 @@ export class GlobalState {
                     (extension as any)[key] = extensionState[key];
                 }
             }
+
+            this.glTFLoaderExtenstions[extension.name] = extension;
         });
 
         if (this.validationResults) {

+ 1 - 1
inspector/src/components/actionTabs/tabs/propertyGrids/animations/popupComponent.tsx

@@ -1,6 +1,6 @@
 import * as React from "react";
 import * as ReactDOM from 'react-dom';
-import { Inspector } from '../../../../../inspector';
+import { Inspector } from '../inspector';
 
 interface IPopupComponentProps {
     id: string,

+ 35 - 0
loaders/src/glTF/2.0/Extensions/KHR_materials_variants.ts

@@ -63,6 +63,15 @@ export class KHR_materials_variants implements IGLTFLoaderExtension {
     }
 
     /**
+     * Gets the list of available variant tag names for this asset.
+     * @param rootMesh The glTF root mesh
+     * @returns the list of all the variant names for this model
+     */
+    public getAvailableVariants(rootMesh: Mesh): string[] {
+        return KHR_materials_variants.GetAvailableVariants(rootMesh);
+    }
+
+    /**
      * Select a variant given a variant tag name or a list of variant tag names.
      * @param rootMesh The glTF root mesh
      * @param variantName The variant name(s) to select.
@@ -94,6 +103,15 @@ export class KHR_materials_variants implements IGLTFLoaderExtension {
     }
 
     /**
+     * Select a variant given a variant tag name or a list of variant tag names.
+     * @param rootMesh The glTF root mesh
+     * @param variantName The variant name(s) to select.
+     */
+    public selectVariant(rootMesh: Mesh, variantName: string | string[]): void {
+        return KHR_materials_variants.SelectVariant(rootMesh, variantName);
+    }
+
+    /**
      * Reset back to the original before selecting a variant.
      * @param rootMesh The glTF root mesh
      */
@@ -111,6 +129,14 @@ export class KHR_materials_variants implements IGLTFLoaderExtension {
     }
 
     /**
+     * Reset back to the original before selecting a variant.
+     * @param rootMesh The glTF root mesh
+     */
+    public reset(rootMesh: Mesh): void {
+        return KHR_materials_variants.Reset(rootMesh);
+    }
+
+    /**
      * Gets the last selected variant tag name(s) or null if original.
      * @param rootMesh The glTF root mesh
      * @returns The selected variant tag name(s).
@@ -124,6 +150,15 @@ export class KHR_materials_variants implements IGLTFLoaderExtension {
         return extensionMetadata.lastSelected;
     }
 
+    /**
+     * Gets the last selected variant tag name(s) or null if original.
+     * @param rootMesh The glTF root mesh
+     * @returns The selected variant tag name(s).
+     */
+    public getLastSelectedVariant(rootMesh: Mesh): Nullable<string | string[]> {
+        return KHR_materials_variants.GetLastSelectedVariant(rootMesh);
+    }
+
     private static _GetExtensionMetadata(rootMesh: Mesh): Nullable<IExtensionMetadata> {
         return rootMesh?.metadata?.gltf?.[NAME] || null;
     }

+ 3 - 5
sandbox/public/index-local.html

@@ -4,15 +4,13 @@
 <head>
     <title>Babylon.js Sandbox - View glTF, glb, obj and babylon files</title>
     <meta name="description" content="Viewer for glTF, glb, obj and babylon files powered by Babylon.js" />
-    <meta name="keywords"
-        content="Babylon.js, Babylon, BabylonJS, glTF, glb, obj, viewer, online viewer, 3D model viewer, 3D, webgl" />
+    <meta name="keywords" content="Babylon.js, Babylon, BabylonJS, glTF, glb, obj, viewer, online viewer, 3D model viewer, 3D, webgl" />
     <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
     <link rel="stylesheet" href="https://use.typekit.net/cta4xsb.css">
     <link rel="shortcut icon" href="https://www.babylonjs.com/favicon.ico">
     <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
-
+    <script src="../../dist/preview%20release/libktx.js"></script>
     <script src="../../Tools/DevLoader/BabylonLoader.js"></script>
-    
     <style>
         html,
         body {
@@ -25,7 +23,7 @@
 
         #host-element {
             width: 100%;
-            height: 100%;            
+            height: 100%;
         }
     </style>
 </head>

+ 4 - 5
src/Meshes/mesh.ts

@@ -2806,7 +2806,7 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
             var pstring: Array<string> = new Array(); //lists facet vertex positions (a,b,c) as string "a|b|c"
 
             var indexPtr: number = 0; // pointer to next available index value
-            var uniquePositions: Array<string> = new Array(); // unique vertex positions
+            var uniquePositions: { [key: string]: number } = {}; // unique vertex positions
             var ptr: number; // pointer to element in uniquePositions
             var facet: Array<number>;
 
@@ -2822,7 +2822,6 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
                         }
                         pstring[j] += currentPositions[3 * facet[j] + k] + "|";
                     }
-                    pstring[j] = pstring[j].slice(0, -1);
                 }
                 //check facet vertices to see that none are repeated
                 // do not process any facet that has a repeated vertex, ie is a line
@@ -2831,9 +2830,9 @@ export class Mesh extends AbstractMesh implements IGetSetVerticesData {
                     // if not listed add to uniquePositions and set index pointer
                     // if listed use its index in uniquePositions and new index pointer
                     for (var j = 0; j < 3; j++) {
-                        ptr = uniquePositions.indexOf(pstring[j]);
-                        if (ptr < 0) {
-                            uniquePositions.push(pstring[j]);
+                        ptr = uniquePositions[pstring[j]];
+                        if (ptr === undefined) {
+                            uniquePositions[pstring[j]] = indexPtr;
                             ptr = indexPtr++;
                             //not listed so add individual x, y, z coordinates to positions
                             for (var k = 0; k < 3; k++) {

+ 2 - 2
src/Misc/khronosTextureContainer2.ts

@@ -16,7 +16,7 @@ export class KhronosTextureContainer2 {
     public constructor(engine: ThinEngine) {
         if (!KhronosTextureContainer2._ModulePromise) {
             KhronosTextureContainer2._ModulePromise = new Promise((resolve) => {
-                LIBKTX().then((module: any) => {
+                LIBKTX({preinitializedWebGLContext: engine._gl}).then((module: any) => {
                     module.GL.makeContextCurrent(module.GL.registerContext(engine._gl, { majorVersion: engine._webGLVersion }));
                     KhronosTextureContainer2._TranscodeFormat = this._determineTranscodeFormat(module.TranscodeTarget, engine.getCaps());
                     resolve({ module: module });
@@ -31,7 +31,7 @@ export class KhronosTextureContainer2 {
 
             const ktxTexture = new module.ktxTexture(data);
             try {
-                if (ktxTexture.isBasisSupercompressed) {
+                if (ktxTexture.needsTranscoding) {
                     ktxTexture.transcodeBasis(KhronosTextureContainer2._TranscodeFormat, 0);
                 }
 

+ 4 - 0
src/XR/features/WebXRControllerTeleportation.ts

@@ -237,6 +237,9 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature {
             return false;
         }
 
+        // Safety reset
+        this._currentTeleportationControllerId = '';
+
         this._options.xrInput.controllers.forEach(this._attachController);
         this._addNewAttachObserver(this._options.xrInput.onControllerAddedObservable, this._attachController);
         this._addNewAttachObserver(this._options.xrInput.onControllerRemovedObservable, (controller) => {
@@ -257,6 +260,7 @@ export class WebXRMotionControllerTeleportation extends WebXRAbstractFeature {
         });
 
         this._setTargetMeshVisibility(false);
+        this._currentTeleportationControllerId = '';
 
         return true;
     }

+ 6 - 1
src/XR/webXREnterExitUI.ts

@@ -58,6 +58,11 @@ export class WebXREnterExitUIOptions {
      * A list of optional features to init the session with
      */
     optionalFeatures?: string[];
+
+    /**
+     * A list of optional features to init the session with
+     */
+    requiredFeatures?: string[];
 }
 /**
  * UI to allow the user to enter/exit XR mode
@@ -157,7 +162,7 @@ export class WebXREnterExitUI implements IDisposable {
                         } else if (helper.state == WebXRState.NOT_IN_XR) {
                             if (options.renderTarget) {
                                 try {
-                                    await helper.enterXRAsync(ui._buttons[i].sessionMode, ui._buttons[i].referenceSpaceType, options.renderTarget, {optionalFeatures: options.optionalFeatures});
+                                    await helper.enterXRAsync(ui._buttons[i].sessionMode, ui._buttons[i].referenceSpaceType, options.renderTarget, {optionalFeatures: options.optionalFeatures, requiredFeatures: options.requiredFeatures});
                                     ui._updateButtons(ui._buttons[i]);
                                 } catch (e) {
                                     // make sure button is visible