diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 28d9115c54..883e0ab9d7 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -880,30 +880,76 @@ div.refresh input[type="button"] { .draggable-number { position: relative; - right: 10px; +} +.draggable-number div { + height: 28px; + width: 92px; +} +.draggable-number.text { + display: inline-block; + color: #afafaf; + background-color: #252525; + font-family: FiraSans-SemiBold; + font-size: 15px; + margin: 0; + padding: 0 16px; + height: 28px; + width: 100%; + line-height: 2; +} +.draggable-number.text:hover { + cursor: ew-resize; } .draggable-number span { - position: relative; - top: -2px; + position: absolute; display: inline-block; - font-family: hifi-glyphs; + font-family: HiFi-Glyphs; font-size: 20px; z-index: 2; } +.draggable-number span:hover { + cursor: default; +} .draggable-number.left-arrow { - left: 17px; + top: -5px; + right: 106px; transform: rotate(180deg); } .draggable-number.right-arrow { - right: 17px; + top: -5px; + left: 106px; } -.draggable-number.fstuple span { +.draggable-number input[type=number] { + position: absolute; + right: 0; + width: 100%; +} +.draggable-number input[type=button] { + position: absolute; top: 0; } .draggable-number input::-webkit-inner-spin-button { -webkit-appearance: none; visibility: hidden; } +.draggable-number.fstuple { + height: 28px; + width: 124px; + left: 12px; +} +.draggable-number.fstuple + .draggable-number.fstuple { + padding-left: 28px; +} +.draggable-number.fstuple input { + right: -10px; +} +.draggable-number.fstuple .sublabel { + position: absolute; + top: 0; + left: -16px; + font-family: FiraSans-SemiBold; + font-size: 15px; +} .row .property { width: auto; @@ -921,10 +967,10 @@ div.refresh input[type="button"] { .property.texture { display: block; } -.property.texture input{ +.property.texture input { margin: 0.4rem 0; } -.texture-image img{ +.texture-image img { padding: 0; margin: 0; width: 100%; @@ -1466,12 +1512,12 @@ th#entity-hasScript { } input#property-scale-button-rescale { - margin-top: 6px; min-width: 50px; + left: 152px; } input#property-scale-button-reset { - margin-top: 6px; margin-right: 0; + left: 250px; } #property-userData-button-edit, @@ -1661,6 +1707,10 @@ input.number-slider { flex-flow: column; } +.flex-column + .flex-column { + padding-left: 50px; +} + .flex-center { align-items: center; } diff --git a/scripts/system/html/js/draggableNumber.js b/scripts/system/html/js/draggableNumber.js index e961bbb4a7..326854bc92 100644 --- a/scripts/system/html/js/draggableNumber.js +++ b/scripts/system/html/js/draggableNumber.js @@ -6,67 +6,125 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +const DELTA_X_FOCUS_THRESHOLD = 2; + function DraggableNumber(min, max, step) { this.min = min; this.max = max; this.step = step !== undefined ? step : 1; - this.startEvent = null; - this.inputChangeFunction = null; + this.initialMouseEvent = null; + this.lastMouseEvent = null; + this.valueChangeFunction = 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); + if (event.target === this.elText) { + this.initialMouseEvent = event; + this.lastMouseEvent = 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; - if (this.inputChangeFunction) { - this.inputChangeFunction(); - } - this.startEvent = event; + mouseMove: function(event) { + if (this.lastMouseEvent) { + let dx = event.clientX - this.lastMouseEvent.clientX; + let inputChanged = dx !== 0; + if (inputChanged) { + while (dx !== 0) { + if (dx > 0) { + this.stepUp(); + --dx; + } else { + this.stepDown(); + ++dx; + } + } + if (this.valueChangeFunction) { + this.valueChangeFunction(); + } + } + this.lastMouseEvent = event; } }, mouseUp: function(event) { - this.startEvent = null; - document.removeEventListener("mousemove", this.onMouseMove); - document.removeEventListener("mouseup", this.onMouseUp); + if (this.initialMouseEvent) { + let dx = event.clientX - this.initialMouseEvent.clientX; + if (dx <= DELTA_X_FOCUS_THRESHOLD) { + this.elInput.style.visibility = "visible"; + this.elText.style.visibility = "hidden"; + } + this.initialMouseEvent = null; + this.lastMouseEvent = null; + document.removeEventListener("mousemove", this.onMouseMove); + document.removeEventListener("mouseup", this.onMouseUp); + } }, - - setInputChangeFunction: function(inputChangeFunction) { - if (this.inputChangeFunction) { - this.elInput.removeEventListener('change', this.inputChangeFunction); + + stepUp: function() { + this.elInput.stepUp(); + this.inputChange(); + }, + + stepDown: function() { + this.elInput.stepDown(); + this.inputChange(); + }, + + setValue: function(newValue) { + this.elInput.value = newValue; + this.elText.firstChild.data = newValue; + }, + + setValueChangeFunction: function(valueChangeFunction) { + if (this.valueChangeFunction) { + this.elInput.removeEventListener("change", this.valueChangeFunction); } - this.inputChangeFunction = inputChangeFunction.bind(this.elInput); - this.elInput.addEventListener('change', this.inputChangeFunction); + this.valueChangeFunction = valueChangeFunction.bind(this.elInput); + this.elInput.addEventListener("change", this.valueChangeFunction); }, + + inputChange: function() { + this.setValue(this.elInput.value); + }, + + inputBlur: function() { + this.elInput.style.visibility = "hidden"; + this.elText.style.visibility = "visible"; + }, initialize: function() { + this.onMouseDown = this.mouseDown.bind(this); this.onMouseMove = this.mouseMove.bind(this); this.onMouseUp = this.mouseUp.bind(this); + this.onStepUp = this.stepUp.bind(this); + this.onStepDown = this.stepDown.bind(this); + this.onInputChange = this.inputChange.bind(this); + this.onInputBlur = this.inputBlur.bind(this); this.elDiv = document.createElement('div'); this.elDiv.className = "draggable-number"; + + this.elText = document.createElement('label'); + this.elText.className = "draggable-number text"; + this.elText.innerText = " "; + this.elText.style.visibility = "visible"; + this.elText.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.elLeftArrow.addEventListener("click", this.onStepDown); + this.elRightArrow.className = 'draggable-number right-arrow'; + this.elRightArrow.innerHTML = 'D'; + this.elRightArrow.addEventListener("click", this.onStepUp); this.elInput = document.createElement('input'); + this.elInput.className = "draggable-number input"; this.elInput.setAttribute("type", "number"); if (this.min !== undefined) { this.elInput.setAttribute("min", this.min); @@ -77,18 +135,13 @@ DraggableNumber.prototype = { 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.elInput.style.visibility = "hidden"; + this.elInput.addEventListener("change", this.onInputChange); + this.elInput.addEventListener("blur", this.onInputBlur); - this.elDiv.appendChild(this.elLeftArrow); - this.elDiv.appendChild(this.elInput); - this.elDiv.appendChild(this.elRightArrow); + this.elText.appendChild(this.elLeftArrow); + this.elText.appendChild(this.elInput); + this.elText.appendChild(this.elRightArrow); + this.elDiv.appendChild(this.elText); } }; diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index d4ea980292..cf7360b927 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1374,16 +1374,16 @@ const PROPERTY_NAME_DIVISION = { }; const VECTOR_ELEMENTS = { - X_INPUT: 0, - Y_INPUT: 1, - Z_INPUT: 2, + X_NUMBER: 0, + Y_NUMBER: 1, + Z_NUMBER: 2, }; const COLOR_ELEMENTS = { COLOR_PICKER: 0, - RED_INPUT: 1, - GREEN_INPUT: 2, - BLUE_INPUT: 3, + RED_NUMBER: 1, + GREEN_NUMBER: 2, + BLUE_NUMBER: 3, }; const TEXTURE_ELEMENTS = { @@ -1417,16 +1417,17 @@ function getPropertyInputElement(propertyID) { switch (property.data.type) { case 'string': case 'bool': - case 'number': case 'dropdown': case 'textarea': case 'texture': return property.elInput; + case 'number': + return property.elNumber.elInput; case 'vec3': case 'vec2': - return { x: property.elInputX, y: property.elInputY, z: property.elInputZ }; + return { x: property.elNumberX.elInput, y: property.elNumberY.elInput, z: property.elNumberZ.elInput }; case 'color': - return { red: property.elInputR, green: property.elInputG, blue: property.elInputB }; + return { red: property.elNumberR.elInput, green: property.elNumberG.elInput, blue: property.elNumberB.elInput }; case 'icon': return property.elLabel; default: @@ -1498,26 +1499,26 @@ function resetProperties() { } case 'number': { if (propertyData.defaultValue !== undefined) { - property.elInput.value = propertyData.defaultValue; + property.elNumber.setValue(propertyData.defaultValue); } else { - property.elInput.value = ""; + property.elNumber.setValue(""); } break; } case 'vec3': case 'vec2': { - property.elInputX.value = ""; - property.elInputY.value = ""; - if (property.elInputZ !== undefined) { - property.elInputZ.value = ""; + property.elNumberX.setValue(""); + property.elNumberY.setValue(""); + if (property.elNumberZ !== undefined) { + property.elNumberZ.setValue(""); } break; } case 'color': { property.elColorPicker.style.backgroundColor = "rgb(" + 0 + "," + 0 + "," + 0 + ")"; - property.elInputR.value = ""; - property.elInputG.value = ""; - property.elInputB.value = ""; + property.elNumberR.setValue(""); + property.elNumberG.setValue(""); + property.elNumberB.setValue(""); break; } case 'dropdown': { @@ -1819,17 +1820,17 @@ function createNumberProperty(property, elProperty) { elDraggableNumber.elInput.value = defaultValue; } - let inputChangeFunction = createEmitNumberPropertyUpdateFunction(propertyName, propertyData.multiplier, propertyData.decimals, property.isParticleProperty); - elDraggableNumber.setInputChangeFunction(inputChangeFunction); + let valueChangeFunction = createEmitNumberPropertyUpdateFunction(propertyName, propertyData.multiplier, property.isParticleProperty); + elDraggableNumber.setValueChangeFunction(valueChangeFunction); elDraggableNumber.elInput.setAttribute("id", elementID); elProperty.appendChild(elDraggableNumber.elDiv); if (propertyData.buttons !== undefined) { - addButtons(elDraggableNumber.elDiv, elementID, propertyData.buttons, false); + addButtons(elDraggableNumber.elText, elementID, propertyData.buttons, false); } - return elDraggableNumber.elInput; + return elDraggableNumber; } function createVec3Property(property, elProperty) { @@ -1839,24 +1840,24 @@ function createVec3Property(property, elProperty) { elProperty.className = propertyData.vec3Type + " fstuple"; - let elNumberX = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.X_INPUT], + let elNumberX = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.X_NUMBER], propertyData.min, propertyData.max, propertyData.step); - let elNumberY = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.Y_INPUT], + let elNumberY = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.Y_NUMBER], propertyData.min, propertyData.max, propertyData.step); - let elNumberZ = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.Z_INPUT], + let elNumberZ = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.Z_NUMBER], propertyData.min, propertyData.max, propertyData.step); - let inputChangeFunction = createEmitVec3PropertyUpdateFunction(propertyName, elNumberX.elInput, elNumberY.elInput, + let valueChangeFunction = createEmitVec3PropertyUpdateFunction(propertyName, elNumberX.elInput, elNumberY.elInput, elNumberZ.elInput, propertyData.multiplier, property.isParticleProperty); - elNumberX.setInputChangeFunction(inputChangeFunction); - elNumberY.setInputChangeFunction(inputChangeFunction); - elNumberZ.setInputChangeFunction(inputChangeFunction); + elNumberX.setValueChangeFunction(valueChangeFunction); + elNumberY.setValueChangeFunction(valueChangeFunction); + elNumberZ.setValueChangeFunction(valueChangeFunction); let elResult = []; - elResult[VECTOR_ELEMENTS.X_INPUT] = elNumberX.elInput; - elResult[VECTOR_ELEMENTS.Y_INPUT] = elNumberY.elInput; - elResult[VECTOR_ELEMENTS.Z_INPUT] = elNumberZ.elInput; + elResult[VECTOR_ELEMENTS.X_NUMBER] = elNumberX; + elResult[VECTOR_ELEMENTS.Y_NUMBER] = elNumberY; + elResult[VECTOR_ELEMENTS.Z_NUMBER] = elNumberZ; return elResult; } @@ -1872,19 +1873,19 @@ function createVec2Property(property, elProperty) { elProperty.appendChild(elTuple); - let elNumberX = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.X_INPUT], + let elNumberX = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.X_NUMBER], propertyData.min, propertyData.max, propertyData.step); - let elNumberY = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.Y_INPUT], + let elNumberY = createTupleNumberInput(elProperty, elementID, propertyData.subLabels[VECTOR_ELEMENTS.Y_NUMBER], propertyData.min, propertyData.max, propertyData.step); - let inputChangeFunction = createEmitVec2PropertyUpdateFunction(propertyName, elNumberX.elInput, elNumberY.elInput, + let valueChangeFunction = createEmitVec2PropertyUpdateFunction(propertyName, elNumberX.elInput, elNumberY.elInput, propertyData.multiplier, property.isParticleProperty); - elNumberX.setInputChangeFunction(inputChangeFunction); - elNumberY.setInputChangeFunction(inputChangeFunction); + elNumberX.setValueChangeFunction(valueChangeFunction); + elNumberY.setValueChangeFunction(valueChangeFunction); let elResult = []; - elResult[VECTOR_ELEMENTS.X_INPUT] = elNumberX.elInput; - elResult[VECTOR_ELEMENTS.Y_INPUT] = elNumberY.elInput; + elResult[VECTOR_ELEMENTS.X_NUMBER] = elNumberX; + elResult[VECTOR_ELEMENTS.Y_NUMBER] = elNumberY; return elResult; } @@ -1908,11 +1909,11 @@ function createColorProperty(property, elProperty) { 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, elNumberR.elInput, elNumberG.elInput, + let valueChangeFunction = createEmitColorPropertyUpdateFunction(propertyName, elNumberR.elInput, elNumberG.elInput, elNumberB.elInput, property.isParticleProperty); - elNumberR.setInputChangeFunction(inputChangeFunction); - elNumberG.setInputChangeFunction(inputChangeFunction); - elNumberB.setInputChangeFunction(inputChangeFunction); + elNumberR.setValueChangeFunction(valueChangeFunction); + elNumberG.setValueChangeFunction(valueChangeFunction); + elNumberB.setValueChangeFunction(valueChangeFunction); let colorPickerID = "#" + elementID; colorPickers[colorPickerID] = $(colorPickerID).colpick({ @@ -1941,9 +1942,9 @@ function createColorProperty(property, elProperty) { let elResult = []; elResult[COLOR_ELEMENTS.COLOR_PICKER] = elColorPicker; - elResult[COLOR_ELEMENTS.RED_INPUT] = elNumberR.elInput; - elResult[COLOR_ELEMENTS.GREEN_INPUT] = elNumberG.elInput; - elResult[COLOR_ELEMENTS.BLUE_INPUT] = elNumberB.elInput; + elResult[COLOR_ELEMENTS.RED_NUMBER] = elNumberR; + elResult[COLOR_ELEMENTS.GREEN_NUMBER] = elNumberG; + elResult[COLOR_ELEMENTS.BLUE_NUMBER] = elNumberB; return elResult; } @@ -2081,14 +2082,14 @@ function createTupleNumberInput(elTuple, propertyElementID, subLabel, min, max, let elementID = propertyElementID + "-" + subLabel.toLowerCase(); let elLabel = document.createElement('label'); - elLabel.className = subLabel; + elLabel.className = "sublabel " + subLabel; elLabel.innerText = subLabel[0].toUpperCase() + subLabel.slice(1); elLabel.setAttribute("for", elementID); let elDraggableNumber = new DraggableNumber(min, max, step); elDraggableNumber.elInput.setAttribute("id", elementID); elDraggableNumber.elDiv.className += " fstuple"; - elDraggableNumber.elDiv.insertBefore(elLabel, elDraggableNumber.elLeftArrow); + elDraggableNumber.elText.insertBefore(elLabel, elDraggableNumber.elLeftArrow); elTuple.appendChild(elDraggableNumber.elDiv); return elDraggableNumber; @@ -2189,7 +2190,7 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI } default: { console.log("EntityProperties - Unknown property type " + - propertyType + " set to property " + propertyID); + propertyType + " set to property " + propertyID); break; } } @@ -2716,6 +2717,85 @@ function showParentMaterialNameBox(number, elNumber, elString) { } } +function createProperty(propertyData, propertyElementID, propertyName, propertyID, elProperty) { + let property = { + data: propertyData, + elementID: propertyElementID, + name: propertyName, + elProperty: elProperty, + }; + let propertyType = propertyData.type; + + switch (propertyType) { + case 'string': { + property.elInput = createStringProperty(property, elProperty); + break; + } + case 'bool': { + property.elInput = createBoolProperty(property, elProperty); + break; + } + case 'number': { + property.elNumber = createNumberProperty(property, elProperty); + break; + } + case 'vec3': { + let elVec3 = createVec3Property(property, elProperty); + property.elNumberX = elVec3[VECTOR_ELEMENTS.X_NUMBER]; + property.elNumberY = elVec3[VECTOR_ELEMENTS.Y_NUMBER]; + property.elNumberZ = elVec3[VECTOR_ELEMENTS.Z_NUMBER]; + break; + } + case 'vec2': { + let elVec2 = createVec2Property(property, elProperty); + property.elNumberX = elVec2[VECTOR_ELEMENTS.X_NUMBER]; + property.elNumberY = elVec2[VECTOR_ELEMENTS.Y_NUMBER]; + break; + } + case 'color': { + let elColor = createColorProperty(property, elProperty); + property.elColorPicker = elColor[COLOR_ELEMENTS.COLOR_PICKER]; + property.elNumberR = elColor[COLOR_ELEMENTS.RED_NUMBER]; + property.elNumberG = elColor[COLOR_ELEMENTS.GREEN_NUMBER]; + property.elNumberB = elColor[COLOR_ELEMENTS.BLUE_NUMBER]; + break; + } + case 'dropdown': { + property.elInput = createDropdownProperty(property, propertyID, elProperty); + break; + } + case 'textarea': { + property.elInput = createTextareaProperty(property, elProperty); + break; + } + case 'icon': { + property.elSpan = createIconProperty(property, elProperty); + break; + } + case 'texture': { + let elTexture = createTextureProperty(property, elProperty); + property.elImage = elTexture[TEXTURE_ELEMENTS.IMAGE]; + property.elInput = elTexture[TEXTURE_ELEMENTS.TEXT_INPUT]; + break; + } + case 'buttons': { + property.elProperty = createButtonsProperty(property, elProperty); + break; + } + case 'placeholder': + case 'sub-header': { + break; + } + default: { + console.log("EntityProperties - Unknown property type " + + propertyType + " set to property " + propertyID); + break; + } + } + + return property; +} + function loaded() { openEventBridge(function() { @@ -3040,9 +3120,9 @@ function loaded() { value = Math.round(value.round) / propertyData.round; } if (propertyData.decimals !== undefined) { - property.elInput.value = value.toFixed(propertyData.decimals); + property.elNumber.setValue(value.toFixed(propertyData.decimals)); } else { - property.elInput.value = value; + property.elNumber.setValue(value); } break; } @@ -3058,16 +3138,16 @@ function loaded() { valueZ = Math.round(valueZ * propertyData.round) / propertyData.round; } if (propertyData.decimals !== undefined) { - property.elInputX.value = valueX.toFixed(propertyData.decimals); - property.elInputY.value = valueY.toFixed(propertyData.decimals); - if (property.elInputZ !== undefined) { - property.elInputZ.value = valueZ.toFixed(propertyData.decimals); + property.elNumberX.setValue(valueX.toFixed(propertyData.decimals)); + property.elNumberY.setValue(valueY.toFixed(propertyData.decimals)); + if (property.elNumberZ !== undefined) { + property.elNumberZ.setValue(valueZ.toFixed(propertyData.decimals)); } } else { - property.elInputX.value = valueX; - property.elInputY.value = valueY; - if (property.elInputZ !== undefined) { - property.elInputZ.value = valueZ; + property.elNumberX.setValue(valueX); + property.elNumberY.setValue(valueY); + if (property.elNumberZ !== undefined) { + property.elNumberZ.setValue(valueZ); } } break; @@ -3076,9 +3156,9 @@ function loaded() { property.elColorPicker.style.backgroundColor = "rgb(" + propertyValue.red + "," + propertyValue.green + "," + propertyValue.blue + ")"; - property.elInputR.value = propertyValue.red; - property.elInputG.value = propertyValue.green; - property.elInputB.value = propertyValue.blue; + property.elNumberR.setValue(propertyValue.red); + property.elNumberG.setValue(propertyValue.green); + property.elNumberB.setValue(propertyValue.blue); break; } case 'dropdown': {