Explorar o código

Merge pull request #2904 from QuentinRillet/master

Fix bug order, select mesh. Add Slider #2827
David Catuhe %!s(int64=7) %!d(string=hai) anos
pai
achega
9177fa1737

+ 118 - 0
inspector/sass/_slider.scss

@@ -0,0 +1,118 @@
+$track-color: #3ca9f1 !default;
+$thumb-color: $color-bot !default;
+
+$thumb-radius: 0px !default;
+$thumb-height: 14px !default;
+$thumb-width: 7px !default;
+$thumb-shadow-size: 1px !default;
+$thumb-shadow-blur: 1px !default;
+$thumb-shadow-color: rgba(0, 0, 0, .2) !default;
+$thumb-border-width: 1px !default;
+$thumb-border-color: $color-bot !default;
+
+$track-width: 50% !default;
+$track-height: 5px !default;
+$track-shadow-size: 1px !default;
+$track-shadow-blur: 1px !default;
+$track-shadow-color: rgba(0, 0, 0, .2) !default;
+$track-border-width: 1px !default;
+$track-border-color: $color-bot !default;
+
+$track-radius: 5px !default;
+$contrast: 5% !default;
+
+@mixin shadow($shadow-size, $shadow-blur, $shadow-color) {
+  box-shadow: $shadow-size $shadow-size $shadow-blur $shadow-color, 0 0 $shadow-size lighten($shadow-color, 5%);
+}
+
+@mixin track {
+  cursor: pointer;
+  height: $track-height;
+  transition: all .2s ease;
+  width: $track-width;
+}
+
+@mixin thumb {
+  @include shadow($thumb-shadow-size, $thumb-shadow-blur, $thumb-shadow-color);
+  background: $thumb-color;
+  border: $thumb-border-width solid $thumb-border-color;
+  border-radius: $thumb-radius;
+  cursor: pointer;
+  height: $thumb-height;
+  width: $thumb-width;
+}
+
+[type='range'] {
+  -webkit-appearance: none;
+  margin: $thumb-height / 2 0;
+  width: $track-width;
+
+  &:focus {
+    outline: 0;
+
+    &::-webkit-slider-runnable-track {
+      background: lighten($track-color, $contrast);
+    }
+
+    &::-ms-fill-lower {
+      background: $track-color;
+    }
+
+    &::-ms-fill-upper {
+      background: lighten($track-color, $contrast);
+    }
+  }
+
+  &::-webkit-slider-runnable-track {
+    @include track;
+    @include shadow($track-shadow-size, $track-shadow-blur, $track-shadow-color);
+    background: $track-color;
+    border: $track-border-width solid $track-border-color;
+    border-radius: $track-radius;
+  }
+
+  &::-webkit-slider-thumb {
+    @include thumb;
+    -webkit-appearance: none;
+    margin-top: ((-$track-border-width * 2 + $track-height) / 2) - ($thumb-height / 2);
+  }
+
+  &::-moz-range-track {
+    @include track;
+    @include shadow($track-shadow-size, $track-shadow-blur, $track-shadow-color);
+    background: $track-color;
+    border: $track-border-width solid $track-border-color;
+    border-radius: $track-radius;
+  }
+
+  &::-moz-range-thumb {
+    @include thumb;
+  }
+
+  &::-ms-track {
+    @include track;
+    background: transparent;
+    border-color: transparent;
+    border-width: ($thumb-height / 2) 0;
+    color: transparent;
+  }
+
+  &::-ms-fill-lower {
+    @include shadow($track-shadow-size, $track-shadow-blur, $track-shadow-color);
+    background: darken($track-color, $contrast);
+    border: $track-border-width solid $track-border-color;
+    border-radius: $track-radius * 2;
+  }
+
+  &::-ms-fill-upper {
+    @include shadow($track-shadow-size, $track-shadow-blur, $track-shadow-color);
+    background: $track-color;
+    border: $track-border-width solid $track-border-color;
+    border-radius: $track-radius * 2;
+  }
+
+  &::-ms-thumb {
+    @include thumb;
+    margin-top: 0;
+  }
+}

+ 2 - 0
inspector/sass/main.scss

@@ -1,4 +1,5 @@
 
+
 .insp-wrapper {
   // Import variables, color and font files
   @import "defines";
@@ -98,4 +99,5 @@
   @import "tabbar";
   @import "toolbar";
   @import "searchbar";
+  @import "slider";
 }

+ 4 - 0
inspector/src/details/DetailPanel.ts

@@ -84,6 +84,10 @@
                 return typeof(s) === 'string' || s instanceof String;
             };
 
+            this._detailRows.forEach((property) => {
+                property.closeDetails();
+            })
+
             this._detailRows.sort((detail1, detail2) : number => {
                 let str1 = String(detail1[property]);
                 let str2 = String(detail2[property]);

+ 81 - 25
inspector/src/details/PropertyLine.ts

@@ -83,11 +83,12 @@ module INSPECTOR {
         private _escapeInputHandler: EventListener;
         /** Handler used on focus out */
         private _focusOutInputHandler: EventListener;
-        private _input_checkbox: HTMLInputElement;
         /** Handler used to get mouse position */
         private _onMouseDownHandler: EventListener;
         private _onMouseDragHandler: EventListener;
         private _onMouseUpHandler: EventListener;
+
+        private _textValue: HTMLElement;
         /** Save previous Y mouse position */
         private _prevY: number;
         /**Save value while slider is on */
@@ -108,7 +109,7 @@ module INSPECTOR {
             // Value
             this._valueDiv = Helpers.CreateDiv('prop-value', this._div);
 
-            if (typeof this.value !== 'boolean') {
+            if (typeof this.value !== 'boolean' && !this._isSliderType()) {
                 this._valueDiv.textContent = this._displayValueContent() || '-'; // Init value text node
             }
 
@@ -119,10 +120,11 @@ module INSPECTOR {
             }
 
             this._updateValue();
-
             // If the property type is not simple, add click event to unfold its children
             if (typeof this.value === 'boolean') {
                 this._checkboxInput();
+            } else if (this._isSliderType()) {
+                this._rangeInput();
             } else if (!this._isSimple()) {
                 this._valueDiv.classList.add('clickable');
                 this._valueDiv.addEventListener('click', this._addDetails.bind(this));
@@ -175,18 +177,19 @@ module INSPECTOR {
             }
         }
 
-        public validateInput(value: any): void {
+        public validateInput(value: any, forceupdate:boolean = true): void {
             this.updateObject();
-
             if (typeof this._property.value === 'number') {
                 this._property.value = parseFloat(value);
             } else {
                 this._property.value = value;
             }
             // Remove input
-            this.update();
-            // resume scheduler
-            Scheduler.getInstance().pause = false;
+            if (forceupdate) {
+                this.update();
+                // resume scheduler
+                Scheduler.getInstance().pause = false;
+            }
         }
 
         /** 
@@ -204,23 +207,23 @@ module INSPECTOR {
         /** Removes the input without validating the new value */
         private _removeInputWithoutValidating() {
             Helpers.CleanDiv(this._valueDiv);
-            if (typeof this.value !== 'boolean') {
+            if (typeof this.value !== 'boolean' && !this._isSliderType()) {
                 this._valueDiv.textContent = "-";
             } 
             // restore elements
             for (let elem of this._elements) {
                 this._valueDiv.appendChild(elem.toHtml());
             }
-            this._valueDiv.addEventListener('click', this._displayInputHandler);
+
+            if (typeof this.value !== 'boolean' && !this._isSliderType()) {
+                this._valueDiv.addEventListener('click', this._displayInputHandler);
+            }
         }
 
         /** Replaces the default display with an input */
         private _displayInput(e) {
             // Remove the displayInput event listener
             this._valueDiv.removeEventListener('click', this._displayInputHandler);
-
-            
-
             // Set input value
             let valueTxt = this._valueDiv.textContent;
             this._valueDiv.textContent = "";
@@ -228,15 +231,11 @@ module INSPECTOR {
             this._valueDiv.appendChild(this._input);
             this._input.focus();
 
-            if (typeof this.value === 'number') {
-                // Slider
-                // let slider = Helpers.CreateDiv('slider-number', this._valueDiv);
-                // slider.style.background = '#303030';
-                // slider.style.cursor = 'ew-resize';
-                // slider.innerHTML = 'HELLO'
+            if (typeof this.value !== 'boolean' && !this._isSliderType()) {
+                this._input.addEventListener('focusout', this._focusOutInputHandler);
+            } else if (typeof this.value === 'number') {
                 this._input.addEventListener('mousedown', this._onMouseDownHandler);
             }
-            this._input.addEventListener('focusout', this._focusOutInputHandler);
 
             // Pause the scheduler
             Scheduler.getInstance().pause = true;
@@ -256,6 +255,10 @@ module INSPECTOR {
 
         // Returns the property name
         public get name(): string {
+            // let arrayName = Helpers.Capitalize(this._property.name).match(/[A-Z][a-z]+|[0-9]+/g)
+            // if (arrayName) {
+            //     return arrayName.join(" ");
+            // }
             return this._property.name;
         }
 
@@ -338,6 +341,8 @@ module INSPECTOR {
             // this._valueDiv.textContent = " "; // TOFIX this removes the elements after
             if (typeof this.value === 'boolean') {
                  this._checkboxInput();
+            } else if (this._isSliderType()) { // Add slider when parent have slider property
+                this._rangeInput();
             } else {
                 this._valueDiv.childNodes[0].nodeValue = this._displayValueContent();
             }
@@ -385,6 +390,17 @@ module INSPECTOR {
             return this._div;
         }
 
+        public closeDetails() {
+            if (this._div.classList.contains('unfolded')) {
+                // Remove class unfolded
+                this._div.classList.remove('unfolded');
+                // remove html children
+                for (let child of this._children) {
+                    this._div.parentNode.removeChild(child.toHtml());
+                }
+            }
+        }
+
         /**
          * Add sub properties in case of a complex type
          */
@@ -401,7 +417,7 @@ module INSPECTOR {
                 this._div.classList.toggle('unfolded');
                 if (this._children.length == 0) {
                     let objToDetail = this.value;
-                    let propToDisplay = PROPERTIES[Helpers.GET_TYPE(objToDetail)].properties.reverse();
+                    let propToDisplay = PROPERTIES[Helpers.GET_TYPE(objToDetail)].properties.slice().reverse();
                     let propertyLine = null;
 
                     for (let prop of propToDisplay) {
@@ -452,14 +468,54 @@ module INSPECTOR {
          */
         private _checkboxInput() {
             if(this._valueDiv.childElementCount < 1) { // Prevent display two checkbox
-                this._input_checkbox = Helpers.CreateInput('checkbox-element', this._valueDiv);
-                this._input_checkbox.type = 'checkbox'
-                this._input_checkbox.checked = this.value;
-                this._input_checkbox.addEventListener('change', () => {
+                this._input = Helpers.CreateInput('checkbox-element', this._valueDiv);
+                this._input.type = 'checkbox'
+                this._input.checked = this.value;
+                this._input.addEventListener('change', () => {
                     Scheduler.getInstance().pause = true;
                     this.validateInput(!this.value)
                 })
             }            
         }
+
+        private _rangeInput() {
+            if(this._valueDiv.childElementCount < 1) { // Prevent display two input range
+                this._input = Helpers.CreateInput('slider-element', this._valueDiv);
+                this._input.type = 'range';
+                this._input.style.display = 'inline-block';
+                this._input.min = this._getSliderProperty().min;
+                this._input.max = this._getSliderProperty().max;
+                this._input.step = this._getSliderProperty().step;
+                this._input.value = this.value;
+                
+                this._validateInputHandler = this._rangeHandler.bind(this)
+                this._input.addEventListener('input', this._validateInputHandler)
+                this._input.addEventListener('change', () => {
+                    Scheduler.getInstance().pause = false;
+                })
+
+                this._textValue = Helpers.CreateDiv('value-text', this._valueDiv);
+                this._textValue.innerText = this.value;
+                this._textValue.style.paddingLeft = '10px';
+                this._textValue.style.display = 'inline-block';
+            }
+        }
+
+        private _rangeHandler() {
+            Scheduler.getInstance().pause = true;
+            this._textValue.innerText = this._input.value;
+            this.validateInput(this._input.value, false);
+        }
+
+        private _isSliderType() { //Check if property have slider definition
+            return this._property  && 
+            PROPERTIES.hasOwnProperty(this._property.obj.constructor.name) &&
+            PROPERTIES[this._property.obj.constructor.name].hasOwnProperty('slider') && 
+            PROPERTIES[this._property.obj.constructor.name].slider.hasOwnProperty(this.name);
+        }
+
+        private _getSliderProperty() {
+            return PROPERTIES[this._property.obj.constructor.name].slider[this.name]
+        }
     }
 }

+ 4 - 0
inspector/src/helpers/Helpers.ts

@@ -195,5 +195,9 @@ module INSPECTOR {
             }
             return propertiesLines;
         }
+
+        public static Capitalize (str : string) : string {
+            return str.charAt(0).toUpperCase() + str.slice(1);
+        }
     }
 }

+ 28 - 11
inspector/src/properties.ts

@@ -16,7 +16,6 @@ module INSPECTOR {
             properties: [],
             format: () => ''
         },
-
         'Vector2': {
             type: BABYLON.Vector2,
             properties: ['x', 'y'],
@@ -30,7 +29,22 @@ module INSPECTOR {
         'Color3': {
             type: BABYLON.Color3,
             properties: ['r', 'g', 'b'],
-            format: (color: BABYLON.Color3) => { return `R:${color.r}, G:${color.g}, B:${color.b}` }
+            format: (color: BABYLON.Color3) => { return `R:${color.r}, G:${color.g}, B:${color.b}` },
+            slider: {
+                r: {min: 0, max: 1, step: 0.01},
+                g: {min: 0, max: 1, step: 0.01},
+                b: {min: 0, max: 1, step: 0.01}
+            }
+        },
+        'Color4': {
+            type: BABYLON.Color4,
+            properties: ['r', 'g', 'b'],
+            format: (color: BABYLON.Color4) => { return `R:${color.r}, G:${color.g}, B:${color.b}` },
+            slider: {
+                r: {min: 0, max: 1, step: 0.01},
+                g: {min: 0, max: 1, step: 0.01},
+                b: {min: 0, max: 1, step: 0.01}
+            }
         },
         'Quaternion': {
             type: BABYLON.Quaternion,
@@ -80,7 +94,6 @@ module INSPECTOR {
         'FontTexture': {
             type: BABYLON.FontTexture
         },
-
         'Sound': {
             type: BABYLON.Sound,
             properties: [
@@ -98,7 +111,6 @@ module INSPECTOR {
                 'isPaused'
             ]
         },
-
         'ArcRotateCamera': {
             type: BABYLON.ArcRotateCamera,
             properties: [
@@ -109,7 +121,6 @@ module INSPECTOR {
                 'angularSensibilityX',
                 'angularSensibilityY',
                 'target',
-
                 'lowerAlphaLimit',
                 'lowerBetaLimit',
                 'upperAlphaLimit',
@@ -121,9 +132,11 @@ module INSPECTOR {
                 'wheelPrecision',
                 'allowUpsideDown',
                 'checkCollisions'
-            ]
+            ],
+            slider: {
+                alpha: {min: 0, max: 1, step: 0.01}
+            }
         },
-
         'FreeCamera': {
             type: BABYLON.FreeCamera,
             properties: [
@@ -132,7 +145,6 @@ module INSPECTOR {
                 'rotationQuaternion',
                 'cameraDirection',
                 'cameraRotation',
-
                 'ellipsoid',
                 'applyGravity',
                 'angularSensibility',
@@ -155,7 +167,6 @@ module INSPECTOR {
                 'orthoRight'
             ]
         },
-
         'Scene': {
             type: BABYLON.Scene,
             properties: [
@@ -254,7 +265,10 @@ module INSPECTOR {
                 'reflectionTexture',
                 'refractionTexture'
             ],
-            format: (mat: BABYLON.StandardMaterial): string => { return mat.name; }
+            format: (mat: BABYLON.StandardMaterial): string => { return mat.name; },
+            slider: {
+                alpha: {min: 0, max: 1, step: 0.01}
+            }
         },
         'PrimitiveAlignment': {
             type: BABYLON.PrimitiveAlignment,
@@ -320,7 +334,10 @@ module INSPECTOR {
                 'cameraContrast',
                 'cameraColorGradingTexture',
                 'cameraColorCurves'
-            ]
+            ],
+            slider: {
+                alpha: {min: 0, max: 1, step: 0.01}
+            }
         },
         'Canvas2D': {
             type: BABYLON.Canvas2D

+ 1 - 0
inspector/src/tabs/PropertyTab.ts

@@ -100,6 +100,7 @@ module INSPECTOR{
                     node.active(false);
                 }
             }
+            item.getDiv().scrollIntoView();
             item.active(true);
         }
         

+ 4 - 0
inspector/src/tree/TreeItem.ts

@@ -162,5 +162,9 @@ module INSPECTOR {
                 this._div.classList.add('active');
             }
         }
+
+        public getDiv() {
+            return this._div;
+        }
     }
 }