From 615ffebb2cb4850a1c2793bce55909f31d7293d4 Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 9 Nov 2018 13:14:05 -0800 Subject: [PATCH] new draggable numbers WIP --- scripts/system/html/css/edit-style.css | 38 ++- scripts/system/html/entityProperties.html | 1 + scripts/system/html/js/draggableNumber.js | 92 ++++++++ scripts/system/html/js/entityProperties.js | 258 +++++++-------------- 4 files changed, 204 insertions(+), 185 deletions(-) create mode 100644 scripts/system/html/js/draggableNumber.js diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 8137d6e659..5107ad8a3d 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -309,6 +309,34 @@ input[type=number].hover-down::-webkit-inner-spin-button:after { color: #ffffff; } +.draggable-number { + position: relative; + right: 10px; +} +.draggable-number span { + position: relative; + top: -2px; + display: inline-block; + font-family: hifi-glyphs; + font-size: 20px; + z-index: 2; +} +.draggable-number.left-arrow { + left: 18px; + transform: rotate(180deg); +} +.draggable-number.right-arrow { + right: 18px; +} +.draggable-number input { +} +.draggable-number input::selection { +} +.draggable-number input::-webkit-inner-spin-button { + -webkit-appearance: none; + visibility: hidden; +} + input[type=range] { -webkit-appearance: none; background: #2e2e2e; @@ -1460,11 +1488,9 @@ th#entity-hasScript { } input#property-scale-button-rescale { - margin-top: 6px; min-width: 50px; } input#property-scale-button-reset { - margin-top: 6px; margin-right: 0; } @@ -1593,9 +1619,9 @@ input.rename-entity { display: flex; flex-flow: row; } -.fstuple input { - margin-left: 4px; - margin-right: 10px; +.fstuple label { + position: relative; + left: 10px; } .fstuple label.red, .fstuple label.x { color: #C62147; @@ -1609,7 +1635,7 @@ input.rename-entity { .xyz.fstuple, .pyr.fstuple { position: relative; - left: -12px; + left: -19px; } .rgb.fstuple .tuple { diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 6af8ee992a..01395368b0 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -22,6 +22,7 @@ + diff --git a/scripts/system/html/js/draggableNumber.js b/scripts/system/html/js/draggableNumber.js new file mode 100644 index 0000000000..62fa02c6f9 --- /dev/null +++ b/scripts/system/html/js/draggableNumber.js @@ -0,0 +1,92 @@ +// draggableNumber.js +// +// Created by David Back on 7 Nov 2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +debugPrint = function (message) { + console.log(message); +}; + +function DraggableNumber(min, max, step) { + this.min = min; + this.max = max; + this.step = step !== undefined ? step : 1; + this.startEvent = null; + this.initialize(); +} + +DraggableNumber.prototype = { + onMouseDown: function(event) { + let that = this.draggableNumber; + that.mouseDown(event); + }, + + mouseDown: function(event) { + this.startEvent = event; + document.addEventListener("mousemove", this.onMouseMove); + document.addEventListener("mouseup", this.onMouseUp); + }, + + mouseMove: function(event, that) { + if (this.startEvent) { + let dx = event.clientX - this.startEvent.clientX; + let valueChange = dx * this.step; + let newValue = parseFloat(this.elInput.value) + valueChange; + if (this.min !== undefined && newValue < this.min) { + newValue = this.min; + } else if (this.max !== undefined && newValue > this.max) { + newValue = this.max; + } + this.elInput.value = newValue; + this.inputChangeFunction(); + this.startEvent = event; + } + }, + + mouseUp: function(event) { + this.startEvent = null; + document.removeEventListener("mousemove", this.onMouseMove); + document.removeEventListener("mouseup", this.onMouseUp); + }, + + setInputChangeFunction: function(inputChangeFunction) { + this.inputChangeFunction = inputChangeFunction.bind(this.elInput); + this.elInput.addEventListener('change', this.inputChangeFunction); + }, + + initialize: function() { + this.onMouseMove = this.mouseMove.bind(this); + this.onMouseUp = this.mouseUp.bind(this); + + this.elDiv = document.createElement('div'); + this.elDiv.className = "draggable-number"; + + this.elInput = document.createElement('input'); + this.elInput.setAttribute("type", "number"); + if (this.min !== undefined) { + this.elInput.setAttribute("min", this.min); + } + if (this.max !== undefined) { + this.elInput.setAttribute("max", this.max); + } + if (this.step !== undefined) { + this.elInput.setAttribute("step", this.step); + } + this.elInput.draggableNumber = this; + this.elInput.addEventListener("mousedown", this.onMouseDown); + + this.elLeftArrow = document.createElement('span'); + this.elRightArrow = document.createElement('span'); + this.elLeftArrow.className = 'draggable-number left-arrow'; + this.elLeftArrow.innerHTML = 'D'; + this.elRightArrow.className = 'draggable-number right-arrow'; + this.elRightArrow.innerHTML = 'D'; + + this.elDiv.appendChild(this.elLeftArrow); + this.elDiv.appendChild(this.elInput); + this.elDiv.appendChild(this.elRightArrow); + } +}; diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index e5e7426dd2..5ea810a069 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -309,7 +309,7 @@ const GROUPS = [ }, { label: "Background Blend", - type: "slider", + type: "number", min: 0, max: 1, step: 0.01, @@ -331,7 +331,7 @@ const GROUPS = [ }, { label: "Glare Angle", - type: "slider", + type: "number", min: 0, max: 180, step: 1, @@ -347,7 +347,7 @@ const GROUPS = [ }, { label: "Bloom Intensity", - type: "slider", + type: "number", min: 0, max: 1, step: 0.01, @@ -357,7 +357,7 @@ const GROUPS = [ }, { label: "Bloom Threshold", - type: "slider", + type: "number", min: 0, max: 1, step: 0.01, @@ -367,7 +367,7 @@ const GROUPS = [ }, { label: "Bloom Size", - type: "slider", + type: "number", min: 0, max: 2, step: 0.01, @@ -615,7 +615,7 @@ const GROUPS = [ }, { label: "Lifespan", - type: "slider", + type: "number", unit: "s", min: 0.01, max: 10, @@ -625,7 +625,7 @@ const GROUPS = [ }, { label: "Max Particles", - type: "slider", + type: "number", min: 1, max: 10000, step: 1, @@ -646,7 +646,7 @@ const GROUPS = [ properties: [ { label: "Emit Rate", - type: "slider", + type: "number", min: 1, max: 1000, step: 1, @@ -654,7 +654,7 @@ const GROUPS = [ }, { label: "Emit Speed", - type: "slider", + type: "number", min: 0, max: 5, step: 0.01, @@ -663,7 +663,7 @@ const GROUPS = [ }, { label: "Speed Spread", - type: "slider", + type: "number", min: 0, max: 5, step: 0.01, @@ -682,7 +682,7 @@ const GROUPS = [ }, { label: "Emit Radius Start", - type: "slider", + type: "number", min: 0, max: 1, step: 0.01, @@ -717,7 +717,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "slider", + type: "number", min: 0, max: 4, step: 0.01, @@ -727,7 +727,7 @@ const GROUPS = [ }, { label: "Middle", - type: "slider", + type: "number", min: 0, max: 4, step: 0.01, @@ -736,7 +736,7 @@ const GROUPS = [ }, { label: "Finish", - type: "slider", + type: "number", min: 0, max: 4, step: 0.01, @@ -748,7 +748,7 @@ const GROUPS = [ }, { label: "Size Spread", - type: "slider", + type: "number", min: 0, max: 4, step: 0.01, @@ -804,7 +804,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "slider", + type: "number", min: 0, max: 1, step: 0.01, @@ -814,7 +814,7 @@ const GROUPS = [ }, { label: "Middle", - type: "slider", + type: "number", min: 0, max: 1, step: 0.01, @@ -823,7 +823,7 @@ const GROUPS = [ }, { label: "Finish", - type: "slider", + type: "number", min: 0, max: 1, step: 0.01, @@ -835,7 +835,7 @@ const GROUPS = [ }, { label: "Alpha Spread", - type: "slider", + type: "number", min: 0, max: 1, step: 0.01, @@ -880,7 +880,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "slider", + type: "number", min: -360, max: 360, step: 1, @@ -892,7 +892,7 @@ const GROUPS = [ }, { label: "Middle", - type: "slider", + type: "number", min: -360, max: 360, step: 1, @@ -903,7 +903,7 @@ const GROUPS = [ }, { label: "Finish", - type: "slider", + type: "number", min: -360, max: 360, step: 1, @@ -917,7 +917,7 @@ const GROUPS = [ }, { label: "Spin Spread", - type: "slider", + type: "number", min: 0, max: 360, step: 1, @@ -944,7 +944,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "slider", + type: "number", min: -180, max: 0, step: 1, @@ -955,7 +955,7 @@ const GROUPS = [ }, { label: "Finish", - type: "slider", + type: "number", min: 0, max: 180, step: 1, @@ -972,7 +972,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "slider", + type: "number", min: 0, max: 180, step: 1, @@ -983,7 +983,7 @@ const GROUPS = [ }, { label: "Finish", - type: "slider", + type: "number", min: 0, max: 180, step: 1, @@ -1348,11 +1348,6 @@ const COLOR_ELEMENTS = { BLUE_INPUT: 3, }; -const SLIDER_ELEMENTS = { - SLIDER: 0, - NUMBER_INPUT: 1, -}; - const ICON_ELEMENTS = { ICON: 0, LABEL: 1, @@ -1399,7 +1394,6 @@ function getPropertyInputElement(propertyID) { case 'string': case 'bool': case 'number': - case 'slider': case 'dropdown': case 'textarea': case 'texture': @@ -1478,16 +1472,12 @@ function resetProperties() { property.elInput.checked = false; break; } - case 'number': - case 'slider': { + case 'number': { if (propertyData.defaultValue !== undefined) { property.elInput.value = propertyData.defaultValue; } else { property.elInput.value = ""; } - if (property.elSlider !== undefined) { - property.elSlider.value = property.elInput.value; - } break; } case 'vec3': @@ -1782,98 +1772,21 @@ function createNumberProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; - elProperty.className = "number"; + elProperty.className = "property draggable-number"; - let elInput = document.createElement('input'); - elInput.setAttribute("id", elementID); - elInput.setAttribute("type", "number"); - if (propertyData.min !== undefined) { - elInput.setAttribute("min", propertyData.min); - } - if (propertyData.max !== undefined) { - elInput.setAttribute("max", propertyData.max); - } - if (propertyData.step !== undefined) { - elInput.setAttribute("step", propertyData.step); - } - - let defaultValue = propertyData.defaultValue; - if (defaultValue !== undefined) { - elInput.value = defaultValue; - } - - elInput.addEventListener('change', createEmitNumberPropertyUpdateFunction(propertyName, propertyData.multiplier, propertyData.decimals, property.isParticleProperty)); - - elProperty.appendChild(elInput); + let elDraggableNumber = new DraggableNumber(propertyData.min, propertyData.max, propertyData.step); + + let inputChangeFunction = createEmitNumberPropertyUpdateFunction(propertyName, propertyData.multiplier, propertyData.decimals, property.isParticleProperty); + elDraggableNumber.setInputChangeFunction(inputChangeFunction); + elDraggableNumber.elInput.setAttribute("id", elementID); + elProperty.appendChild(elDraggableNumber.elDiv); + if (propertyData.buttons !== undefined) { - addButtons(elProperty, elementID, propertyData.buttons, true); + addButtons(elDraggableNumber.elDiv, elementID, propertyData.buttons, false); } - return elInput; -} - -function createSliderProperty(property, elProperty) { - let propertyData = property.data; - - elProperty.className = "range"; - - let elDiv = document.createElement("div"); - elDiv.className = "slider-wrapper"; - - let elSlider = document.createElement("input"); - elSlider.setAttribute("type", "range"); - - let elInput = document.createElement("input"); - elInput.setAttribute("type", "number"); - - if (propertyData.min !== undefined) { - elInput.setAttribute("min", propertyData.min); - elSlider.setAttribute("min", propertyData.min); - } - if (propertyData.max !== undefined) { - elInput.setAttribute("max", propertyData.max); - elSlider.setAttribute("max", propertyData.max); - elSlider.setAttribute("data-max", propertyData.max); - } - if (propertyData.step !== undefined) { - elInput.setAttribute("step", propertyData.step); - elSlider.setAttribute("step", propertyData.step); - } - - elInput.onchange = function (event) { - let inputValue = event.target.value; - elSlider.value = inputValue; - if (propertyData.multiplier !== undefined) { - inputValue *= propertyData.multiplier; - } - updateProperty(property.name, inputValue, property.isParticleProperty); - }; - elSlider.oninput = function (event) { - let sliderValue = event.target.value; - if (propertyData.step === 1) { - if (sliderValue > 0) { - elInput.value = Math.floor(sliderValue); - } else { - elInput.value = Math.ceil(sliderValue); - } - } else { - elInput.value = sliderValue; - } - if (propertyData.multiplier !== undefined) { - sliderValue *= propertyData.multiplier; - } - updateProperty(property.name, sliderValue, property.isParticleProperty); - }; - - elDiv.appendChild(elSlider); - elDiv.appendChild(elInput); - elProperty.appendChild(elDiv); - - let elResult = []; - elResult[SLIDER_ELEMENTS.SLIDER] = elSlider; - elResult[SLIDER_ELEMENTS.NUMBER_INPUT] = elInput; - return elResult; + return elDraggableNumber.elInput; } function createVec3Property(property, elProperty) { @@ -1888,23 +1801,24 @@ function createVec3Property(property, elProperty) { //elProperty.appendChild(elTuple); - let elInputX = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.X_INPUT], - propertyData.min, propertyData.max, propertyData.step); - let elInputY = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.Y_INPUT], - propertyData.min, propertyData.max, propertyData.step); - let elInputZ = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.Z_INPUT], - propertyData.min, propertyData.max, propertyData.step); + let elNumberX = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.X_INPUT], + propertyData.min, propertyData.max, propertyData.step); + let elNumberY = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.Y_INPUT], + propertyData.min, propertyData.max, propertyData.step); + let elNumberZ = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.Z_INPUT], + propertyData.min, propertyData.max, propertyData.step); - let inputChangeFunction = createEmitVec3PropertyUpdateFunction(propertyName, elInputX, elInputY, elInputZ, - propertyData.multiplier, property.isParticleProperty); - elInputX.addEventListener('change', inputChangeFunction); - elInputY.addEventListener('change', inputChangeFunction); - elInputZ.addEventListener('change', inputChangeFunction); + let inputChangeFunction = createEmitVec3PropertyUpdateFunction(propertyName, elNumberX.elInput, elNumberY.elInput, + elNumberZ.elInput, propertyData.multiplier, + property.isParticleProperty); + elNumberX.setInputChangeFunction(inputChangeFunction); + elNumberY.setInputChangeFunction(inputChangeFunction); + elNumberZ.setInputChangeFunction(inputChangeFunction); let elResult = []; - elResult[VECTOR_ELEMENTS.X_INPUT] = elInputX; - elResult[VECTOR_ELEMENTS.Y_INPUT] = elInputY; - elResult[VECTOR_ELEMENTS.Z_INPUT] = elInputZ; + elResult[VECTOR_ELEMENTS.X_INPUT] = elNumberX.elInput; + elResult[VECTOR_ELEMENTS.Y_INPUT] = elNumberY.elInput; + elResult[VECTOR_ELEMENTS.Z_INPUT] = elNumberZ.elInput; return elResult; } @@ -1920,19 +1834,19 @@ function createVec2Property(property, elProperty) { elProperty.appendChild(elTuple); - let elInputX = createTupleNumberInput(elTuple, elementID, propertyData.subLabels[VECTOR_ELEMENTS.X_INPUT], - propertyData.min, propertyData.max, propertyData.step); - let elInputY = createTupleNumberInput(elTuple, elementID, propertyData.subLabels[VECTOR_ELEMENTS.Y_INPUT], - propertyData.min, propertyData.max, propertyData.step); + let elNumberX = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.X_INPUT], + propertyData.min, propertyData.max, propertyData.step); + let elNumberY = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.Y_INPUT], + propertyData.min, propertyData.max, propertyData.step); - let inputChangeFunction = createEmitVec2PropertyUpdateFunction(propertyName, elInputX, elInputY, + let inputChangeFunction = createEmitVec3PropertyUpdateFunction(propertyName, elNumberX.elInput, elNumberY.elInput, propertyData.multiplier, property.isParticleProperty); - elInputX.addEventListener('change', inputChangeFunction); - elInputY.addEventListener('change', inputChangeFunction); + elNumberX.setInputChangeFunction(inputChangeFunction); + elNumberY.setInputChangeFunction(inputChangeFunction); let elResult = []; - elResult[VECTOR_ELEMENTS.X_INPUT] = elInputX; - elResult[VECTOR_ELEMENTS.Y_INPUT] = elInputY; + elResult[VECTOR_ELEMENTS.X_INPUT] = elNumberX.elInput; + elResult[VECTOR_ELEMENTS.Y_INPUT] = elNumberY.elInput; return elResult; } @@ -1952,15 +1866,15 @@ function createColorProperty(property, elProperty) { elProperty.appendChild(elColorPicker); elProperty.appendChild(elTuple); - let elInputR = createTupleNumberInput(elTuple, elementID, "red", COLOR_MIN, COLOR_MAX, COLOR_STEP); - let elInputG = createTupleNumberInput(elTuple, elementID, "green", COLOR_MIN, COLOR_MAX, COLOR_STEP); - let elInputB = createTupleNumberInput(elTuple, elementID, "blue", COLOR_MIN, COLOR_MAX, COLOR_STEP); + let elNumberR = createTupleNumberInput(elTuple, elementID, "red", COLOR_MIN, COLOR_MAX, COLOR_STEP); + let elNumberG = createTupleNumberInput(elTuple, elementID, "green", COLOR_MIN, COLOR_MAX, COLOR_STEP); + let elNumberB = createTupleNumberInput(elTuple, elementID, "blue", COLOR_MIN, COLOR_MAX, COLOR_STEP); - let inputChangeFunction = createEmitColorPropertyUpdateFunction(propertyName, elInputR, elInputG, elInputB, - property.isParticleProperty); - elInputR.addEventListener('change', inputChangeFunction); - elInputG.addEventListener('change', inputChangeFunction); - elInputB.addEventListener('change', inputChangeFunction); + let inputChangeFunction = createEmitColorPropertyUpdateFunction(propertyName, elNumberR.elInput, elNumberG.elInput, + elNumberB.elInput, property.isParticleProperty); + elNumberR.setInputChangeFunction(inputChangeFunction); + elNumberG.setInputChangeFunction(inputChangeFunction); + elNumberB.setInputChangeFunction(inputChangeFunction); let colorPickerID = "#" + elementID; colorPickers[colorPickerID] = $(colorPickerID).colpick({ @@ -1989,9 +1903,9 @@ function createColorProperty(property, elProperty) { let elResult = []; elResult[COLOR_ELEMENTS.COLOR_PICKER] = elColorPicker; - elResult[COLOR_ELEMENTS.RED_INPUT] = elInputR; - elResult[COLOR_ELEMENTS.GREEN_INPUT] = elInputG; - elResult[COLOR_ELEMENTS.BLUE_INPUT] = elInputB; + elResult[COLOR_ELEMENTS.RED_INPUT] = elNumberR.elInput; + elResult[COLOR_ELEMENTS.GREEN_INPUT] = elNumberG.elInput; + elResult[COLOR_ELEMENTS.BLUE_INPUT] = elNumberB.elInput; return elResult; } @@ -2125,7 +2039,7 @@ function createButtonsProperty(property, elProperty, elLabel) { } if (propertyData.buttons !== undefined) { - addButtons(elProperty, elementID, propertyData.buttons, hasLabel); + addButtons(elProperty, elementID, propertyData.buttons, false); } return elProperty; @@ -2134,25 +2048,17 @@ function createButtonsProperty(property, elProperty, elLabel) { function createTupleNumberInput(elTuple, propertyElementID, subLabel, min, max, step) { let elementID = propertyElementID + "-" + subLabel.toLowerCase(); - let elDiv = document.createElement('div'); let elLabel = document.createElement('label'); elLabel.className = subLabel; elLabel.innerText = subLabel[0].toUpperCase() + subLabel.slice(1); elLabel.setAttribute("for", elementID); - let elInput = document.createElement('input'); - elInput.className = subLabel + " number-slider"; - elInput.setAttribute("id", elementID); - elInput.setAttribute("type", "number"); - elInput.setAttribute("min", min); - elInput.setAttribute("max", max); - elInput.setAttribute("step", step); + let elDraggableNumber = new DraggableNumber(min, max, step); + elDraggableNumber.elInput.setAttribute("id", elementID); + elDraggableNumber.elDiv.insertBefore(elLabel, elDraggableNumber.elLeftArrow); + elTuple.appendChild(elDraggableNumber.elDiv); - elDiv.appendChild(elLabel); - elDiv.appendChild(elInput); - elTuple.appendChild(elDiv); - - return elInput; + return elDraggableNumber; } function addButtons(elProperty, propertyID, buttons, newRow) { @@ -2720,12 +2626,6 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI property.elInput = createNumberProperty(property, elProperty); break; } - case 'slider': { - let elSlider = createSliderProperty(property, elProperty); - property.elSlider = elSlider[SLIDER_ELEMENTS.SLIDER]; - property.elInput = elSlider[SLIDER_ELEMENTS.NUMBER_INPUT]; - break; - } case 'vec3': { let elVec3 = createVec3Property(property, elProperty); property.elInputX = elVec3[VECTOR_ELEMENTS.X_INPUT];