فهرست منبع

Fix fur.dispose() + fix quaternion display in the inspector

David Catuhe 6 سال پیش
والد
کامیت
7a041e1823

+ 4 - 0
Playground/babylon.d.txt

@@ -47429,6 +47429,10 @@ declare module BABYLON {
              */
              */
             getHierarchyEmittedParticleSystems(): IParticleSystem[];
             getHierarchyEmittedParticleSystems(): IParticleSystem[];
         }
         }
+    /**
+     * @hidden
+     */
+    export var _IDoNeedToBeInTheBuild: number;
 }
 }
 declare module BABYLON {
 declare module BABYLON {
         interface Scene {
         interface Scene {

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

@@ -48065,6 +48065,10 @@ declare module BABYLON {
              */
              */
             getHierarchyEmittedParticleSystems(): IParticleSystem[];
             getHierarchyEmittedParticleSystems(): IParticleSystem[];
         }
         }
+    /**
+     * @hidden
+     */
+    export var _IDoNeedToBeInTheBuild: number;
 }
 }
 declare module BABYLON {
 declare module BABYLON {
         interface Scene {
         interface Scene {

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
dist/preview release/babylon.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 302 - 193
dist/preview release/babylon.max.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
dist/preview release/babylon.max.js.map


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

@@ -50075,6 +50075,10 @@ declare module "babylonjs/Particles/particleSystemComponent" {
             getHierarchyEmittedParticleSystems(): IParticleSystem[];
             getHierarchyEmittedParticleSystems(): IParticleSystem[];
         }
         }
     }
     }
+    /**
+     * @hidden
+     */
+    export var _IDoNeedToBeInTheBuild: number;
 }
 }
 declare module "babylonjs/Particles/index" {
 declare module "babylonjs/Particles/index" {
     export * from "babylonjs/Particles/baseParticleSystem";
     export * from "babylonjs/Particles/baseParticleSystem";

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 7 - 7
dist/preview release/gui/babylon.gui.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 7 - 7
dist/preview release/inspector/babylon.inspector.bundle.js


+ 18 - 13
dist/preview release/inspector/babylon.inspector.bundle.max.js

@@ -34582,41 +34582,46 @@ var QuaternionLineComponent = /** @class */ (function (_super) {
         });
         });
     };
     };
     QuaternionLineComponent.prototype.updateQuaternion = function () {
     QuaternionLineComponent.prototype.updateQuaternion = function () {
-        var store = this.state.value.clone();
-        var quaternion = this._eulerValue.toQuaternion();
-        this.props.target[this.props.propertyName] = quaternion;
-        this.setState({ value: quaternion });
-        this.raiseOnPropertyChanged(quaternion, store);
+        var store = this.props.target[this.props.propertyName].clone();
+        this.props.target[this.props.propertyName] = this.state.value;
+        this.setState({ value: store });
+        this.raiseOnPropertyChanged(this.state.value, store);
     };
     };
     QuaternionLineComponent.prototype.updateStateX = function (value) {
     QuaternionLineComponent.prototype.updateStateX = function (value) {
         this._localChange = true;
         this._localChange = true;
-        this._eulerValue.x = value;
+        this.state.value.x = value;
         this.updateQuaternion();
         this.updateQuaternion();
     };
     };
     QuaternionLineComponent.prototype.updateStateY = function (value) {
     QuaternionLineComponent.prototype.updateStateY = function (value) {
         this._localChange = true;
         this._localChange = true;
-        this._eulerValue.y = value;
+        this.state.value.y = value;
         this.updateQuaternion();
         this.updateQuaternion();
     };
     };
     QuaternionLineComponent.prototype.updateStateZ = function (value) {
     QuaternionLineComponent.prototype.updateStateZ = function (value) {
         this._localChange = true;
         this._localChange = true;
-        this._eulerValue.z = value;
+        this.state.value.z = value;
+        this.updateQuaternion();
+    };
+    QuaternionLineComponent.prototype.updateStateW = function (value) {
+        this._localChange = true;
+        this.state.value.w = value;
         this.updateQuaternion();
         this.updateQuaternion();
     };
     };
     QuaternionLineComponent.prototype.render = function () {
     QuaternionLineComponent.prototype.render = function () {
         var _this = this;
         var _this = this;
         var chevron = this.state.isExpanded ? react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_fortawesome_react_fontawesome__WEBPACK_IMPORTED_MODULE_3__["FontAwesomeIcon"], { icon: _fortawesome_free_solid_svg_icons__WEBPACK_IMPORTED_MODULE_4__["faMinus"] }) : react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_fortawesome_react_fontawesome__WEBPACK_IMPORTED_MODULE_3__["FontAwesomeIcon"], { icon: _fortawesome_free_solid_svg_icons__WEBPACK_IMPORTED_MODULE_4__["faPlus"] });
         var chevron = this.state.isExpanded ? react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_fortawesome_react_fontawesome__WEBPACK_IMPORTED_MODULE_3__["FontAwesomeIcon"], { icon: _fortawesome_free_solid_svg_icons__WEBPACK_IMPORTED_MODULE_4__["faMinus"] }) : react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_fortawesome_react_fontawesome__WEBPACK_IMPORTED_MODULE_3__["FontAwesomeIcon"], { icon: _fortawesome_free_solid_svg_icons__WEBPACK_IMPORTED_MODULE_4__["faPlus"] });
-        this._eulerValue = this.state.value.toEulerAngles();
+        var quat = this.state.value;
         return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "vector3Line" },
         return (react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "vector3Line" },
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "firstLine" },
             react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "firstLine" },
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "label" }, this.props.label),
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "label" }, this.props.label),
-                react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "vector" }, "X: " + this._eulerValue.x.toFixed(2) + ", Y: " + this._eulerValue.y.toFixed(2) + ", Z: " + this._eulerValue.z.toFixed(2)),
+                react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "vector" }, "X: " + quat.x.toFixed(2) + ", Y: " + quat.y.toFixed(2) + ", Z: " + quat.z.toFixed(2) + ", W: " + quat.w.toFixed(2)),
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "expand", onClick: function () { return _this.switchExpandState(); } }, chevron)),
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "expand", onClick: function () { return _this.switchExpandState(); } }, chevron)),
             this.state.isExpanded &&
             this.state.isExpanded &&
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "secondLine" },
                 react__WEBPACK_IMPORTED_MODULE_1__["createElement"]("div", { className: "secondLine" },
-                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_numericInputComponent__WEBPACK_IMPORTED_MODULE_2__["NumericInputComponent"], { label: "x", value: this._eulerValue.x, onChange: function (value) { return _this.updateStateX(value); } }),
-                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_numericInputComponent__WEBPACK_IMPORTED_MODULE_2__["NumericInputComponent"], { label: "y", value: this._eulerValue.y, onChange: function (value) { return _this.updateStateY(value); } }),
-                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_numericInputComponent__WEBPACK_IMPORTED_MODULE_2__["NumericInputComponent"], { label: "z", value: this._eulerValue.z, onChange: function (value) { return _this.updateStateZ(value); } }))));
+                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_numericInputComponent__WEBPACK_IMPORTED_MODULE_2__["NumericInputComponent"], { label: "x", value: quat.x, onChange: function (value) { return _this.updateStateX(value); } }),
+                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_numericInputComponent__WEBPACK_IMPORTED_MODULE_2__["NumericInputComponent"], { label: "y", value: quat.y, onChange: function (value) { return _this.updateStateY(value); } }),
+                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_numericInputComponent__WEBPACK_IMPORTED_MODULE_2__["NumericInputComponent"], { label: "z", value: quat.z, onChange: function (value) { return _this.updateStateZ(value); } }),
+                    react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_numericInputComponent__WEBPACK_IMPORTED_MODULE_2__["NumericInputComponent"], { label: "w", value: quat.w, onChange: function (value) { return _this.updateStateW(value); } }))));
     };
     };
     return QuaternionLineComponent;
     return QuaternionLineComponent;
 }(react__WEBPACK_IMPORTED_MODULE_1__["Component"]));
 }(react__WEBPACK_IMPORTED_MODULE_1__["Component"]));

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
dist/preview release/inspector/babylon.inspector.bundle.max.js.map


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

@@ -600,7 +600,6 @@ declare module INSPECTOR {
         value: BABYLON.Quaternion;
         value: BABYLON.Quaternion;
     }> {
     }> {
         private _localChange;
         private _localChange;
-        private _eulerValue;
         constructor(props: IQuaternionLineComponentProps);
         constructor(props: IQuaternionLineComponentProps);
         shouldComponentUpdate(nextProps: IQuaternionLineComponentProps, nextState: {
         shouldComponentUpdate(nextProps: IQuaternionLineComponentProps, nextState: {
             isExpanded: boolean;
             isExpanded: boolean;
@@ -612,6 +611,7 @@ declare module INSPECTOR {
         updateStateX(value: number): void;
         updateStateX(value: number): void;
         updateStateY(value: number): void;
         updateStateY(value: number): void;
         updateStateZ(value: number): void;
         updateStateZ(value: number): void;
+        updateStateW(value: number): void;
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }

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

@@ -731,7 +731,6 @@ declare module "babylonjs-inspector/components/actionTabs/lines/quaternionLineCo
         value: Quaternion;
         value: Quaternion;
     }> {
     }> {
         private _localChange;
         private _localChange;
-        private _eulerValue;
         constructor(props: IQuaternionLineComponentProps);
         constructor(props: IQuaternionLineComponentProps);
         shouldComponentUpdate(nextProps: IQuaternionLineComponentProps, nextState: {
         shouldComponentUpdate(nextProps: IQuaternionLineComponentProps, nextState: {
             isExpanded: boolean;
             isExpanded: boolean;
@@ -743,6 +742,7 @@ declare module "babylonjs-inspector/components/actionTabs/lines/quaternionLineCo
         updateStateX(value: number): void;
         updateStateX(value: number): void;
         updateStateY(value: number): void;
         updateStateY(value: number): void;
         updateStateZ(value: number): void;
         updateStateZ(value: number): void;
+        updateStateW(value: number): void;
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }
@@ -2350,7 +2350,6 @@ declare module INSPECTOR {
         value: BABYLON.Quaternion;
         value: BABYLON.Quaternion;
     }> {
     }> {
         private _localChange;
         private _localChange;
-        private _eulerValue;
         constructor(props: IQuaternionLineComponentProps);
         constructor(props: IQuaternionLineComponentProps);
         shouldComponentUpdate(nextProps: IQuaternionLineComponentProps, nextState: {
         shouldComponentUpdate(nextProps: IQuaternionLineComponentProps, nextState: {
             isExpanded: boolean;
             isExpanded: boolean;
@@ -2362,6 +2361,7 @@ declare module INSPECTOR {
         updateStateX(value: number): void;
         updateStateX(value: number): void;
         updateStateY(value: number): void;
         updateStateY(value: number): void;
         updateStateZ(value: number): void;
         updateStateZ(value: number): void;
+        updateStateW(value: number): void;
         render(): JSX.Element;
         render(): JSX.Element;
     }
     }
 }
 }

+ 6 - 6
dist/preview release/loaders/babylonjs.loaders.js

@@ -7878,7 +7878,7 @@ if (babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__["SceneLoader"]) {
 /*!***********************!*\
 /*!***********************!*\
   !*** ./glTF/index.ts ***!
   !*** ./glTF/index.ts ***!
   \***********************/
   \***********************/
-/*! exports provided: GLTF1, GLTF2, GLTFLoaderCoordinateSystemMode, GLTFLoaderAnimationStartMode, GLTFLoaderState, GLTFFileLoader */
+/*! exports provided: GLTFLoaderCoordinateSystemMode, GLTFLoaderAnimationStartMode, GLTFLoaderState, GLTFFileLoader, GLTF1, GLTF2 */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 
 "use strict";
 "use strict";
@@ -7908,16 +7908,12 @@ __webpack_require__.r(__webpack_exports__);
 /*!******************!*\
 /*!******************!*\
   !*** ./index.ts ***!
   !*** ./index.ts ***!
   \******************/
   \******************/
-/*! exports provided: GLTF1, GLTF2, GLTFLoaderCoordinateSystemMode, GLTFLoaderAnimationStartMode, GLTFLoaderState, GLTFFileLoader, MTLFileLoader, OBJFileLoader, STLFileLoader */
+/*! exports provided: GLTFLoaderCoordinateSystemMode, GLTFLoaderAnimationStartMode, GLTFLoaderState, GLTFFileLoader, GLTF1, GLTF2, MTLFileLoader, OBJFileLoader, STLFileLoader */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 
 
 "use strict";
 "use strict";
 __webpack_require__.r(__webpack_exports__);
 __webpack_require__.r(__webpack_exports__);
 /* harmony import */ var _glTF__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./glTF */ "./glTF/index.ts");
 /* harmony import */ var _glTF__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./glTF */ "./glTF/index.ts");
-/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GLTF1", function() { return _glTF__WEBPACK_IMPORTED_MODULE_0__["GLTF1"]; });
-
-/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GLTF2", function() { return _glTF__WEBPACK_IMPORTED_MODULE_0__["GLTF2"]; });
-
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GLTFLoaderCoordinateSystemMode", function() { return _glTF__WEBPACK_IMPORTED_MODULE_0__["GLTFLoaderCoordinateSystemMode"]; });
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GLTFLoaderCoordinateSystemMode", function() { return _glTF__WEBPACK_IMPORTED_MODULE_0__["GLTFLoaderCoordinateSystemMode"]; });
 
 
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GLTFLoaderAnimationStartMode", function() { return _glTF__WEBPACK_IMPORTED_MODULE_0__["GLTFLoaderAnimationStartMode"]; });
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GLTFLoaderAnimationStartMode", function() { return _glTF__WEBPACK_IMPORTED_MODULE_0__["GLTFLoaderAnimationStartMode"]; });
@@ -7926,6 +7922,10 @@ __webpack_require__.r(__webpack_exports__);
 
 
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GLTFFileLoader", function() { return _glTF__WEBPACK_IMPORTED_MODULE_0__["GLTFFileLoader"]; });
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GLTFFileLoader", function() { return _glTF__WEBPACK_IMPORTED_MODULE_0__["GLTFFileLoader"]; });
 
 
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GLTF1", function() { return _glTF__WEBPACK_IMPORTED_MODULE_0__["GLTF1"]; });
+
+/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GLTF2", function() { return _glTF__WEBPACK_IMPORTED_MODULE_0__["GLTF2"]; });
+
 /* harmony import */ var _OBJ__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OBJ */ "./OBJ/index.ts");
 /* harmony import */ var _OBJ__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OBJ */ "./OBJ/index.ts");
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "MTLFileLoader", function() { return _OBJ__WEBPACK_IMPORTED_MODULE_1__["MTLFileLoader"]; });
 /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "MTLFileLoader", function() { return _OBJ__WEBPACK_IMPORTED_MODULE_1__["MTLFileLoader"]; });
 
 

+ 26 - 4
dist/preview release/viewer/babylon.viewer.d.ts

@@ -169,11 +169,11 @@ declare module BabylonViewer {
                 * Mainly used for help and errors
                 * Mainly used for help and errors
                 * @param subScreen the name of the subScreen. Those can be defined in the configuration object
                 * @param subScreen the name of the subScreen. Those can be defined in the configuration object
                 */
                 */
-            showOverlayScreen(subScreen: string): Promise<string> | Promise<Template>;
+            showOverlayScreen(subScreen: string): Promise<Template> | Promise<string>;
             /**
             /**
                 * Hide the overlay screen.
                 * Hide the overlay screen.
                 */
                 */
-            hideOverlayScreen(): Promise<string> | Promise<Template>;
+            hideOverlayScreen(): Promise<Template> | Promise<string>;
             /**
             /**
                 * show the viewer (in case it was hidden)
                 * show the viewer (in case it was hidden)
                 *
                 *
@@ -190,11 +190,11 @@ declare module BabylonViewer {
                 * Show the loading screen.
                 * Show the loading screen.
                 * The loading screen can be configured using the configuration object
                 * The loading screen can be configured using the configuration object
                 */
                 */
-            showLoadingScreen(): Promise<string> | Promise<Template>;
+            showLoadingScreen(): Promise<Template> | Promise<string>;
             /**
             /**
                 * Hide the loading screen
                 * Hide the loading screen
                 */
                 */
-            hideLoadingScreen(): Promise<string> | Promise<Template>;
+            hideLoadingScreen(): Promise<Template> | Promise<string>;
             dispose(): void;
             dispose(): void;
             protected _onConfigurationLoaded(configuration: ViewerConfiguration): void;
             protected _onConfigurationLoaded(configuration: ViewerConfiguration): void;
     }
     }
@@ -899,6 +899,28 @@ declare module BabylonViewer {
     }
     }
 }
 }
 declare module BabylonViewer {
 declare module BabylonViewer {
+    export interface IViewerTemplatePlugin {
+        readonly templateName: string;
+        readonly eventsToAttach?: Array<string>;
+        interactionPredicate(event: EventCallback): boolean;
+        onEvent?(event: EventCallback): void;
+        addHTMLTemplate?(template: Template): void;
+    }
+    export abstract class AbstractViewerNavbarButton implements IViewerTemplatePlugin {
+        readonly templateName: string;
+        readonly eventsToAttach: Array<string>;
+        protected _prepend: boolean;
+        protected _buttonName: string;
+        protected _buttonClass: string;
+        protected _htmlTemplate: string;
+        constructor(buttonName: string, buttonClass?: string, htmlTemplate?: string);
+        interactionPredicate(event: EventCallback): boolean;
+        abstract onEvent(event: EventCallback): void;
+        addHTMLTemplate(template: Template): void;
+        protected _generateHTMLElement(template: Template): Element | DocumentFragment;
+    }
+}
+declare module BabylonViewer {
     /**
     /**
       *
       *
       * @param name the name of the custom optimizer configuration
       * @param name the name of the custom optimizer configuration

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 21 - 17
dist/preview release/viewer/babylon.viewer.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2 - 2
dist/preview release/viewer/babylon.viewer.max.js


+ 25 - 5
dist/preview release/viewer/babylon.viewer.module.d.ts

@@ -201,11 +201,11 @@ declare module 'babylonjs-viewer/viewer/defaultViewer' {
                 * Mainly used for help and errors
                 * Mainly used for help and errors
                 * @param subScreen the name of the subScreen. Those can be defined in the configuration object
                 * @param subScreen the name of the subScreen. Those can be defined in the configuration object
                 */
                 */
-            showOverlayScreen(subScreen: string): Promise<string> | Promise<Template>;
+            showOverlayScreen(subScreen: string): Promise<Template> | Promise<string>;
             /**
             /**
                 * Hide the overlay screen.
                 * Hide the overlay screen.
                 */
                 */
-            hideOverlayScreen(): Promise<string> | Promise<Template>;
+            hideOverlayScreen(): Promise<Template> | Promise<string>;
             /**
             /**
                 * show the viewer (in case it was hidden)
                 * show the viewer (in case it was hidden)
                 *
                 *
@@ -222,11 +222,11 @@ declare module 'babylonjs-viewer/viewer/defaultViewer' {
                 * Show the loading screen.
                 * Show the loading screen.
                 * The loading screen can be configured using the configuration object
                 * The loading screen can be configured using the configuration object
                 */
                 */
-            showLoadingScreen(): Promise<string> | Promise<Template>;
+            showLoadingScreen(): Promise<Template> | Promise<string>;
             /**
             /**
                 * Hide the loading screen
                 * Hide the loading screen
                 */
                 */
-            hideLoadingScreen(): Promise<string> | Promise<Template>;
+            hideLoadingScreen(): Promise<Template> | Promise<string>;
             dispose(): void;
             dispose(): void;
             protected _onConfigurationLoaded(configuration: ViewerConfiguration): void;
             protected _onConfigurationLoaded(configuration: ViewerConfiguration): void;
     }
     }
@@ -963,7 +963,27 @@ declare module 'babylonjs-viewer/loader/plugins/loaderPlugin' {
 }
 }
 
 
 declare module 'babylonjs-viewer/templating/viewerTemplatePlugin' {
 declare module 'babylonjs-viewer/templating/viewerTemplatePlugin' {
-    
+    import { EventCallback, Template } from "babylonjs-viewer/templating/templateManager";
+    export interface IViewerTemplatePlugin {
+        readonly templateName: string;
+        readonly eventsToAttach?: Array<string>;
+        interactionPredicate(event: EventCallback): boolean;
+        onEvent?(event: EventCallback): void;
+        addHTMLTemplate?(template: Template): void;
+    }
+    export abstract class AbstractViewerNavbarButton implements IViewerTemplatePlugin {
+        readonly templateName: string;
+        readonly eventsToAttach: Array<string>;
+        protected _prepend: boolean;
+        protected _buttonName: string;
+        protected _buttonClass: string;
+        protected _htmlTemplate: string;
+        constructor(buttonName: string, buttonClass?: string, htmlTemplate?: string);
+        interactionPredicate(event: EventCallback): boolean;
+        abstract onEvent(event: EventCallback): void;
+        addHTMLTemplate(template: Template): void;
+        protected _generateHTMLElement(template: Template): Element | DocumentFragment;
+    }
 }
 }
 
 
 declare module 'babylonjs-viewer/optimizer/custom' {
 declare module 'babylonjs-viewer/optimizer/custom' {

+ 21 - 15
inspector/src/components/actionTabs/lines/quaternionLineComponent.tsx

@@ -1,6 +1,6 @@
 import * as React from "react";
 import * as React from "react";
 import { Observable } from "babylonjs/Misc/observable";
 import { Observable } from "babylonjs/Misc/observable";
-import { Quaternion, Vector3 } from "babylonjs/Maths/math";
+import { Quaternion } from "babylonjs/Maths/math";
 import { NumericInputComponent } from "./numericInputComponent";
 import { NumericInputComponent } from "./numericInputComponent";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { faMinus, faPlus } from "@fortawesome/free-solid-svg-icons";
 import { faMinus, faPlus } from "@fortawesome/free-solid-svg-icons";
@@ -15,7 +15,6 @@ interface IQuaternionLineComponentProps {
 
 
 export class QuaternionLineComponent extends React.Component<IQuaternionLineComponentProps, { isExpanded: boolean, value: Quaternion }> {
 export class QuaternionLineComponent extends React.Component<IQuaternionLineComponentProps, { isExpanded: boolean, value: Quaternion }> {
     private _localChange = false;
     private _localChange = false;
-    private _eulerValue: Vector3;
 
 
     constructor(props: IQuaternionLineComponentProps) {
     constructor(props: IQuaternionLineComponentProps) {
         super(props);
         super(props);
@@ -52,40 +51,46 @@ export class QuaternionLineComponent extends React.Component<IQuaternionLineComp
     }
     }
 
 
     updateQuaternion() {
     updateQuaternion() {
-        const store = this.state.value.clone();
-        const quaternion = this._eulerValue.toQuaternion();
-        this.props.target[this.props.propertyName] = quaternion;
+        const store = this.props.target[this.props.propertyName].clone();
+        this.props.target[this.props.propertyName] = this.state.value;
 
 
-        this.setState({ value: quaternion });
+        this.setState({ value: store });
 
 
-        this.raiseOnPropertyChanged(quaternion, store);
+        this.raiseOnPropertyChanged(this.state.value, store);
     }
     }
 
 
     updateStateX(value: number) {
     updateStateX(value: number) {
         this._localChange = true;
         this._localChange = true;
 
 
-        this._eulerValue.x = value;
+        this.state.value.x = value;
         this.updateQuaternion();
         this.updateQuaternion();
     }
     }
 
 
     updateStateY(value: number) {
     updateStateY(value: number) {
         this._localChange = true;
         this._localChange = true;
 
 
-        this._eulerValue.y = value;
+        this.state.value.y = value;
         this.updateQuaternion();
         this.updateQuaternion();
     }
     }
 
 
     updateStateZ(value: number) {
     updateStateZ(value: number) {
         this._localChange = true;
         this._localChange = true;
 
 
-        this._eulerValue.z = value;
+        this.state.value.z = value;
+        this.updateQuaternion();
+    }
+
+    updateStateW(value: number) {
+        this._localChange = true;
+
+        this.state.value.w = value;
         this.updateQuaternion();
         this.updateQuaternion();
     }
     }
 
 
     render() {
     render() {
         const chevron = this.state.isExpanded ? <FontAwesomeIcon icon={faMinus} /> : <FontAwesomeIcon icon={faPlus} />
         const chevron = this.state.isExpanded ? <FontAwesomeIcon icon={faMinus} /> : <FontAwesomeIcon icon={faPlus} />
 
 
-        this._eulerValue = this.state.value.toEulerAngles();
+        let quat = this.state.value;
 
 
         return (
         return (
             <div className="vector3Line">
             <div className="vector3Line">
@@ -94,7 +99,7 @@ export class QuaternionLineComponent extends React.Component<IQuaternionLineComp
                         {this.props.label}
                         {this.props.label}
                     </div>
                     </div>
                     <div className="vector">
                     <div className="vector">
-                        {`X: ${this._eulerValue.x.toFixed(2)}, Y: ${this._eulerValue.y.toFixed(2)}, Z: ${this._eulerValue.z.toFixed(2)}`}
+                        {`X: ${quat.x.toFixed(2)}, Y: ${quat.y.toFixed(2)}, Z: ${quat.z.toFixed(2)}, W: ${quat.w.toFixed(2)}`}
                     </div>
                     </div>
                     <div className="expand" onClick={() => this.switchExpandState()}>
                     <div className="expand" onClick={() => this.switchExpandState()}>
                         {chevron}
                         {chevron}
@@ -103,9 +108,10 @@ export class QuaternionLineComponent extends React.Component<IQuaternionLineComp
                 {
                 {
                     this.state.isExpanded &&
                     this.state.isExpanded &&
                     <div className="secondLine">
                     <div className="secondLine">
-                        <NumericInputComponent label="x" value={this._eulerValue.x} onChange={value => this.updateStateX(value)} />
-                        <NumericInputComponent label="y" value={this._eulerValue.y} onChange={value => this.updateStateY(value)} />
-                        <NumericInputComponent label="z" value={this._eulerValue.z} onChange={value => this.updateStateZ(value)} />
+                        <NumericInputComponent label="x" value={quat.x} onChange={value => this.updateStateX(value)} />
+                        <NumericInputComponent label="y" value={quat.y} onChange={value => this.updateStateY(value)} />
+                        <NumericInputComponent label="z" value={quat.z} onChange={value => this.updateStateZ(value)} />
+                        <NumericInputComponent label="w" value={quat.w} onChange={value => this.updateStateW(value)} />
                     </div>
                     </div>
                 }
                 }
             </div>
             </div>

+ 1 - 1
src/scene.ts

@@ -3271,7 +3271,7 @@ export class Scene extends AbstractScene implements IAnimatable {
      */
      */
     public removeMaterial(toRemove: Material): number {
     public removeMaterial(toRemove: Material): number {
         var index = toRemove._indexInSceneMaterialArray;
         var index = toRemove._indexInSceneMaterialArray;
-        if (index !== -1) {
+        if (index !== -1 && index < this.materials.length) {
             if (index !== this.materials.length - 1) {
             if (index !== this.materials.length - 1) {
                 const lastMaterial = this.materials[this.materials.length - 1];
                 const lastMaterial = this.materials[this.materials.length - 1];
                 this.materials[index] = lastMaterial;
                 this.materials[index] = lastMaterial;