From 11a240e2db79671bbd1a41b4a3909034afc1d83f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 18 Jun 2018 12:47:13 -0700 Subject: [PATCH 001/117] Exploring the performance profile of the render engine --- interface/src/SecondaryCamera.cpp | 4 +- libraries/task/src/task/Config.h | 6 +- scripts/developer/utilities/lib/jet/jet.js | 114 ++++++++++++++ .../utilities/lib/jet/qml/TaskListView.qml | 128 ++++++++-------- .../lib/jet/qml/TaskTimeFrameView.qml | 141 ++++++++++++++++++ .../developer/utilities/lib/jet/qml/qmldir | 3 +- .../utilities/render/engineInspector.js | 10 +- .../utilities/render/engineInspector.qml | 3 +- 8 files changed, 338 insertions(+), 71 deletions(-) create mode 100644 scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index b9a767f700..766c64043d 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -196,11 +196,13 @@ public: void run(const render::RenderContextPointer& renderContext, const RenderArgsPointer& cachedArgs) { auto args = renderContext->args; + if (cachedArgs) { args->_blitFramebuffer = cachedArgs->_blitFramebuffer; args->_viewport = cachedArgs->_viewport; - args->popViewFrustum(); args->_displayMode = cachedArgs->_displayMode; args->_renderMode = cachedArgs->_renderMode; + } + args->popViewFrustum(); gpu::doInBatch("EndSecondaryCameraFrame::run", args->_context, [&](gpu::Batch& batch) { batch.restoreContextStereo(); diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 00fa01808b..c94ed5f8ce 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -98,10 +98,10 @@ public: JobConfig() = default; JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} - bool isEnabled() { return alwaysEnabled || enabled; } - void setEnabled(bool enable) { enabled = alwaysEnabled || enable; emit dirtyEnabled(); } + bool isEnabled() { return /*alwaysEnabled ||*/ enabled; } + void setEnabled(bool enable) { enabled = /*alwaysEnabled ||*/ enable; emit dirtyEnabled(); } - bool alwaysEnabled{ true }; + bool alwaysEnabled{ false }; bool enabled{ true }; virtual void setPresetList(const QJsonObject& object); diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js index 16840e59bd..041be0f8a6 100644 --- a/scripts/developer/utilities/lib/jet/jet.js +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -73,6 +73,120 @@ function job_print_functor(printout, showProps, maxDepth) { } } +// Use this function to create a functor that will build a tree datastructure of the Job visited + +function job_tree_model_array_functor(jobTreeArray, newNodeFunctor) { + var jobsRoot; + var numJobs = 0; + var jobTreePath = [] + if (newNodeFunctor === undefined) newNodeFunctor = function (node) {} + + return function (job, depth, index) { + var id = numJobs + var newItem = {"name": job.objectName, "level": depth, "index": index, "id": id, "subNode": [], "path": ""} + if (depth == 0) { + newNodeFunctor(newItem) + jobTreeArray.push(newItem) + numJobs++ + jobsRoot = jobTreeArray[0].subNode; + } else { + if (jobTreePath.length < depth) { + var node = jobsRoot; + var path; + for (var n = 0; n < jobTreePath.length; n++) { + newItem.path += (n > 0 ? "." : "") + node[jobTreePath[n]].name + node = node[jobTreePath[n]].subNode + } + + newNodeFunctor(newItem) + node.push((newItem)) + numJobs++ + jobTreePath.push(0); + } else if (jobTreePath.length >= depth) { + var node = jobsRoot; + for (var n = 0; n < (depth - 1); n++) { + newItem.path += (n > 0 ? "." : "") + node[jobTreePath[n]].name + node = node[jobTreePath[n]].subNode + } + + newNodeFunctor(newItem) + node.push((newItem)) + numJobs++ + jobTreePath[depth-1] = index; + while (jobTreePath.length > depth) { + jobTreePath.pop(); + } + } + } + return true; + } +} + +function job_tree_model_functor(jobTreeModel, maxLevel, newNodeFunctor) { + var jobsRoot; + var numJobs = 0; + var jobTreePath = [] + if (newNodeFunctor === undefined) newNodeFunctor = function (node) {} + + return function (job, depth, index) { + var id = numJobs + var newItem = {"name": job.objectName, "level": depth, "index": index, "id": id, "subNode": [], "path": "", "init": (depth < maxLevel), "ud": {}} + if (depth == 0) { + newNodeFunctor(newItem) + jobTreeModel.append(newItem) + numJobs++ + jobsRoot = jobTreeModel.get(0).subNode; + } else { + if (jobTreePath.length < depth) { + var node = jobsRoot; + var path; + for (var n = 0; n < jobTreePath.length; n++) { + newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name + node = node.get(jobTreePath[n]).subNode + } + + newNodeFunctor(newItem) + node.append((newItem)) + numJobs++ + jobTreePath.push(0); + } else if (jobTreePath.length >= depth) { + var node = jobsRoot; + for (var n = 0; n < (depth - 1); n++) { + newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name + node = node.get(jobTreePath[n]).subNode + } + + newNodeFunctor(newItem) + node.append((newItem)) + numJobs++ + jobTreePath[depth-1] = index; + while (jobTreePath.length > depth) { + jobTreePath.pop(); + } + } + } + return true; + } +} + + +// Traverse the jobTreenode data structure created above +function job_traverseTreeNode(root, functor, depth) { + // if (root.subNode.length) { + depth++; + for (var i = 0; i 0 ? "." : "") + node.get(jobTreePath[n]).name - node = node.get(jobTreePath[n]).subNode - } - node.append(newItem) - jobTreePath.push(0); - } else if (jobTreePath.length >= depth) { - var node = jobsRoot; - for (var n = 0; n < (depth - 1); n++) { - newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name - node = node.get(jobTreePath[n]).subNode - } - node.append(newItem) - jobTreePath[depth-1] = index; - while (jobTreePath.length > depth) { - jobTreePath.pop(); - } - } - } - return true; - } - + //var functor = Jet.job_tree_model_functor(jobsModel) + /* var functor = Jet.job_tree_model_functor(jobsModel, 1, function(node) { + node["cpuT"] = 0.0 + }) Jet.task_traverseTree(rootConfig, functor); - } + */ + + var tfunctor = Jet.job_tree_model_array_functor(jobsModel.engineJobItemModel, function(node) { + node["init"] = (node.level < 3) + node["fullpath"] = (node.path + "." + node.name) + node["cpuT"] = 0.0 + }) + + Jet.task_traverseTree(rootConfig, tfunctor); + + // var currentParentStach = [] + // currentParentStach.push(jobsModel); + + + Jet.job_traverseTreeNodeRoot(jobsModel.engineJobItemModel[0], function(node, depth, index) { + print(node.name + depth + " - " + index) + return true + }) + } + ListModel { id: jobsModel + property var engineJobItemModel : [] } Component { @@ -77,30 +64,49 @@ Rectangle { id: objRecursiveColumn clip: true visible: model.init - - MouseArea { - width: objRow.implicitWidth - height: objRow.implicitHeight - onDoubleClicked: { - for(var i = 1; i < parent.children.length - 1; ++i) { - parent.children[i].visible = !parent.children[i].visible - } - } - Row { - id: objRow - Item { - height: 1 - width: model.level * 15 - } - HifiControls.CheckBox { - property var config: root.rootConfig.getConfig(model.path + "." + model.name); - text: (objRecursiveColumn.children.length > 2 ? - objRecursiveColumn.children[1].visible ? - qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name + " ms=" + config.cpuRunTime.toFixed(2) - checked: config.enabled - } + // visible: (node.level < 2) + + function switchFold() { + for(var i = 1; i < children.length - 1; ++i) { + children[i].visible = !children[i].visible } } + + Row { + id: objRow + Item { + height: 1 + width: model.level * 15 + } + + HifiControls.CheckBox { + id: objCheck + property var config: root.rootConfig.getConfig(model.path + "." + model.name); + text: " " + checked: config.enabled + onCheckedChanged: { config.enabled = checked } + } + + MouseArea { + width: objLabel.implicitWidth + height: objLabel.implicitHeight + onDoubleClicked: { + parent.parent.switchFold() + } + + HifiControls.Label { + id: objLabel + colorScheme: hifi.colorSchemes.dark + // property var config: root.rootConfig.getConfig(model.path + "." + model.name); + text: (objRecursiveColumn.children.length > 2 ? + objRecursiveColumn.children[1].visible ? + qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name + + " ms=" + root.rootConfig.getConfig(model.path + "." + model.name).cpuRunTime.toFixed(3) + + " id=" + model.id + } + } + } + Repeater { model: subNode delegate: objRecursiveDelegate diff --git a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml new file mode 100644 index 0000000000..ed1649a47a --- /dev/null +++ b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml @@ -0,0 +1,141 @@ +// +// jet/TaskTimeFrameView.qml +// +// Created by Sam Gateau, 2018/06/15 +// 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 +// + +import QtQuick 2.7 +import QtQuick.Controls 1.4 as Original +import QtQuick.Controls.Styles 1.4 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls + +import "../jet.js" as Jet + +Rectangle { + HifiConstants { id: hifi;} + color: hifi.colors.baseGray; + id: root; + + property var rootConfig : Workload + + property var jobsTree + property var jobsArray + + Component.onCompleted: { + if (!jobsTree) { jobsTree = new Array(); } + if (!jobsArray) { jobsArray = new Array(); } + + var tfunctor = Jet.job_tree_model_array_functor(jobsTree, function(node) { + var job = { "fullpath": (node.path + "." + node.name), "cpuT": 0.0, "depth": node.level } + jobsArray.push(job) + }) + Jet.task_traverseTree(rootConfig, tfunctor); + + for (var j = 0; j 0) { + + var rangeStack =new Array() + var frameDuration = Math.max(jobsArray[0].cpuT, 1) + rangeStack.push( { "b": 0.0, "e": frameDuration } ) + var timeScale = width * 0.9 / frameDuration; + + drawJob(ctx, 0, 0, jobsArray[0].cpuT, 0, timeScale) + + for (var i = 1; i lastDepth) { + timeOffset = rangeStack[lastDepth].b + while(rangeStack.length <= depth) { + rangeStack.push( { "b": timeOffset, "e": duration } ) + } + + } else { + if (depth < lastDepth) { + while(rangeStack.length != (depth + 1)) { + rangeStack.pop() + } + } + + timeOffset = rangeStack[depth].e + rangeStack[depth].b = timeOffset + rangeStack[depth].e = timeOffset + duration + } + + print("j " + i + " depth " + depth + " lastDepth " + lastDepth + " off " + timeOffset + " dur " + duration) + drawJob(ctx, depth, i, duration, timeOffset, timeScale) + } + } + } + } + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/lib/jet/qml/qmldir b/scripts/developer/utilities/lib/jet/qml/qmldir index 3134545625..930641b10b 100644 --- a/scripts/developer/utilities/lib/jet/qml/qmldir +++ b/scripts/developer/utilities/lib/jet/qml/qmldir @@ -1,2 +1,3 @@ TaskList 1.0 TaskList.qml -TaskViewList 1.0 TaskViewList.qml \ No newline at end of file +TaskViewList 1.0 TaskViewList.qml +TaskTimeFrameView 1.0 TaskTimeFrameView.qml \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.js b/scripts/developer/utilities/render/engineInspector.js index dcf13157b5..348ae8f54f 100644 --- a/scripts/developer/utilities/render/engineInspector.js +++ b/scripts/developer/utilities/render/engineInspector.js @@ -4,10 +4,12 @@ var window = new OverlayWindow({ title: 'Render Engine', source: qml, - width: 300, - height: 400 + width: 500, + height: 100 }); window.setPosition(200, 50); - //window.closed.connect(function() { Script.stop(); }); + window.closed.connect(function() { Script.stop(); }); } - openEngineTaskView(); \ No newline at end of file + openEngineTaskView(); + + \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml index 1b9941e64e..d2a6e01524 100644 --- a/scripts/developer/utilities/render/engineInspector.qml +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -23,7 +23,8 @@ Item { property var mainViewTask: Render.getConfig("RenderMainView") - Jet.TaskListView { + //Jet.TaskListView { + Jet.TaskTimeFrameView { rootConfig: Render anchors.fill: render } From 3a910489c8b88b0c5d2a4de0f3cd3354deff3c62 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 20 Jun 2018 16:56:35 -0700 Subject: [PATCH 002/117] Regfining --- libraries/task/src/task/Config.h | 5 +- .../lib/jet/qml/TaskTimeFrameView.qml | 176 +++++++++++++++--- .../utilities/render/engineInspector.js | 60 +++++- .../utilities/render/engineInspector.qml | 7 +- 4 files changed, 217 insertions(+), 31 deletions(-) diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index c94ed5f8ce..a1e05cd043 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -123,7 +123,7 @@ public: // Running Time measurement // The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated - void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration(runtime).count(); emit newStats(); } + void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration(runtime).count(); /* emit newStats();*/ } double getCPURunTime() const { return _msCPURunTime; } // Describe the node graph data connections of the associated Job/Task @@ -230,7 +230,8 @@ public: auto tokens = path.split('.', QString::SkipEmptyParts); if (tokens.empty()) { - tokens.push_back(QString()); + return dynamic_cast(const_cast (root)); + // tokens.push_back(QString()); } else { while (tokens.size() > 1) { auto name = tokens.front(); diff --git a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml index ed1649a47a..4eca5075d0 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml @@ -27,27 +27,32 @@ Rectangle { property var jobsTree property var jobsArray + Component.onCompleted: { if (!jobsTree) { jobsTree = new Array(); } if (!jobsArray) { jobsArray = new Array(); } var tfunctor = Jet.job_tree_model_array_functor(jobsTree, function(node) { - var job = { "fullpath": (node.path + "." + node.name), "cpuT": 0.0, "depth": node.level } + var job = { "fullpath": (node.path + "." + node.name), "cpuT": 0.0, "depth": node.level, "name": node.name } jobsArray.push(job) }) Jet.task_traverseTree(rootConfig, tfunctor); for (var j = 0; j ") + height: 24 + width: 24 + onClicked: { + print("list of highlight styles") + myCanvasTimer.running = !myCanvasTimer.running + } + } + } Canvas { id: mycanvas - anchors.fill:parent + anchors.top:myHeaderRow.bottom + anchors.bottom:parent.bottom + anchors.left:parent.left + anchors.right:parent.right - onPaint: { - print("mycanvasOnPaint " + jobsArray.length) - var lineHeight = 12; - var frameWidth = width; + property var frameDuration: 10 + property var frameViewBegin: 0 + property var frameViewRange: width - + function reset() { + frameViewBegin = 0 + frameViewRange = width + } + + function checkView() { + if (frameViewBegin > width * 0.9) { + frameViewBegin = width * 0.9 + } else if (frameViewBegin + frameViewRange < width * 0.1) { + frameViewBegin = width * 0.1 -frameViewRange + } + } + + function drag(deltaX) { + frameViewBegin -= deltaX + checkView() + } + + function pivotScale(pivotX, deltaX) { + var newRange = frameViewRange + 2 * deltaX + if (newRange <= 1) { + newRange = 2; + } + frameViewBegin = pivotX - frameViewRange * (pivotX - frameViewBegin) / newRange + frameViewRange = newRange + print( "pivot= " + pivotX + " deltaX= " + (deltaX)) + checkView() + } + + + onPaint: { + // print("mycanvasOnPaint " + jobsArray.length) + var lineHeight = 12; + + function getXFromTime(t) { + return (t / mycanvas.frameDuration) * mycanvas.frameViewRange - (mycanvas.frameViewBegin) + } + function getWFromDuration(d) { + return (d / mycanvas.frameDuration) * mycanvas.frameViewRange + } function displayBackground(ctx) { ctx.fillStyle = Qt.rgba(0, 0, 0, root.backgroundOpacity); ctx.fillRect(0, 0, width, height); @@ -80,15 +147,34 @@ Rectangle { ctx.lineTo(width, lineHeight + 1); ctx.moveTo(0, height); ctx.lineTo(width, height); + + var x0 = getXFromTime(0) + ctx.moveTo(x0, 0); + ctx.lineTo(x0, height); + + x0 = getXFromTime(5) + ctx.moveTo(x0, 0); + ctx.lineTo(x0, height); + + x0 = getXFromTime(10) + ctx.moveTo(x0, 0); + ctx.lineTo(x0, height); + ctx.stroke(); } - function drawJob(ctx, depth, index, duration, timeOffset, timeScale) { + function drawJob(ctx, depth, index, duration, timeOffset) { //print(root.jobsArray[index].cpuT) // ctx.fillStyle = Qt.rgba(255, 255, 0, root.backgroundOpacity); ctx.fillStyle = ( depth % 2 ? ( index % 2 ? "blue" : "yellow") : ( index % 2 ? "green" : "red")) - ctx.fillRect(timeOffset * timeScale, lineHeight * depth, duration * timeScale, lineHeight * 0.6); - + ctx.fillRect(getXFromTime(timeOffset), lineHeight * 2 * depth,getWFromDuration(duration), lineHeight); + + if (depth,getWFromDuration(duration) >= width * 0.1) { + ctx.fillStyle = "grey"; + ctx.textAlign = "center"; + ctx.fillText( root.jobsArray[index].name, getXFromTime(timeOffset + duration * 0.5), lineHeight * 2 * depth); + + } } var ctx = getContext("2d"); @@ -97,26 +183,22 @@ Rectangle { displayBackground(ctx); if (jobsArray.length > 0) { - + mycanvas.frameDuration = Math.max(jobsArray[0].cpuT, 1) var rangeStack =new Array() - var frameDuration = Math.max(jobsArray[0].cpuT, 1) - rangeStack.push( { "b": 0.0, "e": frameDuration } ) - var timeScale = width * 0.9 / frameDuration; - - drawJob(ctx, 0, 0, jobsArray[0].cpuT, 0, timeScale) + rangeStack.push( { "b": 0.0, "e": mycanvas.frameDuration } ) + + drawJob(ctx, 0, 0, jobsArray[0].cpuT, 0) for (var i = 1; i lastDepth) { timeOffset = rangeStack[lastDepth].b while(rangeStack.length <= depth) { - rangeStack.push( { "b": timeOffset, "e": duration } ) + rangeStack.push( { "b": timeOffset, "e": timeOffset + duration } ) } } else { @@ -130,12 +212,54 @@ Rectangle { rangeStack[depth].b = timeOffset rangeStack[depth].e = timeOffset + duration } - - print("j " + i + " depth " + depth + " lastDepth " + lastDepth + " off " + timeOffset + " dur " + duration) - drawJob(ctx, depth, i, duration, timeOffset, timeScale) + if (duration > 0.0) { + drawJob(ctx, depth, i, duration, timeOffset) } } } } } + + MouseArea { + id: hitbox + anchors.fill: mycanvas + acceptedButtons: Qt.LeftButton | Qt.RightButton + + property var pivotX + property var dragPos + onPressed: { + dragPos = { "x":mouse.x, "y":mouse.y } + pivotX = mouse.x + } + onPositionChanged: { + if (dragPos !== undefined) { + var delta = mouse.x - dragPos.x + + if (mouse.buttons & Qt.LeftButton) { + mycanvas.drag(delta) + } + + if (mouse.buttons & Qt.RightButton) { + mycanvas.pivotScale(pivotX, delta) + } + + dragPos.x = mouse.x + dragPos.y = mouse.y + mycanvas.requestPaint() + } + } + onReleased: { + dragPos = undefined + } + + onWheel: { + mycanvas.pivotScale(wheel.x, mycanvas.frameViewRange * 0.02 * (wheel.angleDelta.y / 120.0)) + mycanvas.requestPaint() + } + + onDoubleClicked: { + mycanvas.reset() + mycanvas.requestPaint() + } + } } \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.js b/scripts/developer/utilities/render/engineInspector.js index 348ae8f54f..e6be7f1c3c 100644 --- a/scripts/developer/utilities/render/engineInspector.js +++ b/scripts/developer/utilities/render/engineInspector.js @@ -1,4 +1,4 @@ - function openEngineTaskView() { + /*function openEngineTaskView() { // Set up the qml ui var qml = Script.resolvePath('engineInspector.qml'); var window = new OverlayWindow({ @@ -10,6 +10,62 @@ window.setPosition(200, 50); window.closed.connect(function() { Script.stop(); }); } - openEngineTaskView(); + openEngineTaskView();*/ + (function() { + var TABLET_BUTTON_NAME = "Render Engine"; + var QMLAPP_URL = Script.resolvePath("./engineInspector.qml"); + var ICON_URL = Script.resolvePath("../../../system/assets/images/lod-i.svg"); + var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/lod-a.svg"); + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: TABLET_BUTTON_NAME, + icon: ICON_URL, + activeIcon: ACTIVE_ICON_URL + }); + + Script.scriptEnding.connect(function () { + killWindow() + button.clicked.disconnect(onClicked); + tablet.removeButton(button); + }); + + button.clicked.connect(onClicked); + + var onScreen = false; + var window; + + function onClicked() { + if (onScreen) { + killWindow() + } else { + createWindow() + } + } + + function createWindow() { + var qml = Script.resolvePath(QMLAPP_URL); + window = new OverlayWindow({ + title: 'Render Engine', + source: qml, + width: 500, + height: 100 + }); + window.setPosition(200, 50); + window.closed.connect(killWindow); + onScreen = true + button.editProperties({isActive: true}); + } + + function killWindow() { + if (window !== undefined) { + window.closed.disconnect(killWindow); + window.close() + window = undefined + } + onScreen = false + button.editProperties({isActive: false}) + } + }()); \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml index d2a6e01524..d3bd2e96fd 100644 --- a/scripts/developer/utilities/render/engineInspector.qml +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -23,9 +23,14 @@ Item { property var mainViewTask: Render.getConfig("RenderMainView") - //Jet.TaskListView { + Jet.TaskTimeFrameView { rootConfig: Render anchors.fill: render } + /* Jet.TaskListView { + rootConfig: Render + anchors.fill: render + } */ + } \ No newline at end of file From 0f3cb0fb84a2928c699b888dbfa454ef394286c2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 3 Jul 2018 12:50:52 +0200 Subject: [PATCH 003/117] INtroducing th eGraphics Engine to group al the graphics related (render and gpu) elements --- interface/src/Application.cpp | 176 ++++++------------ interface/src/Application.h | 33 ++-- interface/src/Application_render.cpp | 139 +++++++------- interface/src/Util.cpp | 108 ----------- interface/src/Util.h | 5 - interface/src/graphics/GraphicsEngine.cpp | 167 +++++++++++++++++ interface/src/graphics/GraphicsEngine.h | 57 ++++++ interface/src/graphics/RenderEventHandler.cpp | 71 +++++++ interface/src/graphics/RenderEventHandler.h | 47 +++++ interface/src/graphics/WorldBox.cpp | 138 ++++++++++++++ interface/src/graphics/WorldBox.h | 43 +++++ interface/src/ui/ApplicationOverlay.cpp | 2 +- .../src/DeferredLightingEffect.cpp | 7 +- .../render-utils/src/DeferredLightingEffect.h | 3 +- libraries/render-utils/src/LightStage.cpp | 10 +- 15 files changed, 686 insertions(+), 320 deletions(-) create mode 100644 interface/src/graphics/GraphicsEngine.cpp create mode 100644 interface/src/graphics/GraphicsEngine.h create mode 100644 interface/src/graphics/RenderEventHandler.cpp create mode 100644 interface/src/graphics/RenderEventHandler.h create mode 100644 interface/src/graphics/WorldBox.cpp create mode 100644 interface/src/graphics/WorldBox.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a60d72073c..dc7a34e728 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -83,7 +83,7 @@ #include #include #include -#include +//#include #include #include #include @@ -116,8 +116,8 @@ #include #include #include -#include -#include +//#include +//#include #include #include #include @@ -247,71 +247,7 @@ extern "C" { #include "AndroidHelper.h" #endif -enum ApplicationEvent { - // Execute a lambda function - Lambda = QEvent::User + 1, - // Trigger the next render - Render, - // Trigger the next idle - Idle, -}; - -class RenderEventHandler : public QObject { - using Parent = QObject; - Q_OBJECT -public: - RenderEventHandler(QOpenGLContext* context) { - _renderContext = new OffscreenGLCanvas(); - _renderContext->setObjectName("RenderContext"); - _renderContext->create(context); - if (!_renderContext->makeCurrent()) { - qFatal("Unable to make rendering context current"); - } - _renderContext->doneCurrent(); - - // Deleting the object with automatically shutdown the thread - connect(qApp, &QCoreApplication::aboutToQuit, this, &QObject::deleteLater); - - // Transfer to a new thread - moveToNewNamedThread(this, "RenderThread", [this](QThread* renderThread) { - hifi::qt::addBlockingForbiddenThread("Render", renderThread); - _renderContext->moveToThreadWithContext(renderThread); - qApp->_lastTimeRendered.start(); - }, std::bind(&RenderEventHandler::initialize, this), QThread::HighestPriority); - } - -private: - void initialize() { - setObjectName("Render"); - PROFILE_SET_THREAD_NAME("Render"); - setCrashAnnotation("render_thread_id", std::to_string((size_t)QThread::currentThreadId())); - if (!_renderContext->makeCurrent()) { - qFatal("Unable to make rendering context current on render thread"); - } - } - - void render() { - if (qApp->shouldPaint()) { - qApp->paintGL(); - } - } - - bool event(QEvent* event) override { - switch ((int)event->type()) { - case ApplicationEvent::Render: - render(); - qApp->_pendingRenderEvent.store(false); - return true; - - default: - break; - } - return Parent::event(event); - } - - OffscreenGLCanvas* _renderContext { nullptr }; -}; - +#include "graphics/RenderEventHandler.h" Q_LOGGING_CATEGORY(trace_app_input_mouse, "trace.app.input.mouse") @@ -2254,7 +2190,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->preloadSounds(); _pendingIdleEvent = false; - _pendingRenderEvent = false; + // _pendingRenderEvent = false; + _graphicsEngine.startup(); qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); @@ -2469,8 +2406,8 @@ void Application::cleanupBeforeQuit() { // The cleanup process enqueues the transactions but does not process them. Calling this here will force the actual // removal of the items. // See https://highfidelity.fogbugz.com/f/cases/5328 - _main3DScene->enqueueFrame(); // flush all the transactions - _main3DScene->processTransactionQueue(); // process and apply deletions + // _main3DScene->enqueueFrame(); // flush all the transactions + // _main3DScene->processTransactionQueue(); // process and apply deletions // first stop all timers directly or by invokeMethod // depending on what thread they run in @@ -2485,7 +2422,7 @@ void Application::cleanupBeforeQuit() { } _window->saveGeometry(); - _gpuContext->shutdown(); + // _gpuContext->shutdown(); // Destroy third party processes after scripts have finished using them. #ifdef HAVE_DDE @@ -2539,9 +2476,10 @@ Application::~Application() { assert(_shapeManager.getNumShapes() == 0); // shutdown render engine - _main3DScene = nullptr; - _renderEngine = nullptr; - + //_main3DScene = nullptr; + //_renderEngine = nullptr; + _graphicsEngine.shutdown(); + _gameWorkload.shutdown(); DependencyManager::destroy(); @@ -2655,7 +2593,7 @@ void Application::initializeGL() { } } - // Build an offscreen GL context for the main thread. + /* // Build an offscreen GL context for the main thread. _offscreenContext = new OffscreenGLCanvas(); _offscreenContext->setObjectName("MainThreadContext"); _offscreenContext->create(_glWidget->qglContext()); @@ -2664,34 +2602,36 @@ void Application::initializeGL() { } _offscreenContext->doneCurrent(); _offscreenContext->setThreadContext(); - +*/ _glWidget->makeCurrent(); glClearColor(0.2f, 0.2f, 0.2f, 1); glClear(GL_COLOR_BUFFER_BIT); _glWidget->swapBuffers(); // Move the GL widget context to the render event handler thread - _renderEventHandler = new RenderEventHandler(_glWidget->qglContext()); - if (!_offscreenContext->makeCurrent()) { - qFatal("Unable to make offscreen context current"); - } + // _renderEventHandler = new RenderEventHandler(_glWidget->qglContext()); + // if (!_offscreenContext->makeCurrent()) { + // qFatal("Unable to make offscreen context current"); + // } // Create the GPU backend - // Requires the window context, because that's what's used in the actual rendering - // and the GPU backend will make things like the VAO which cannot be shared across - // contexts - _glWidget->makeCurrent(); - gpu::Context::init(); - qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK, - QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram))); - _glWidget->makeCurrent(); - _gpuContext = std::make_shared(); + //// Requires the window context, because that's what's used in the actual rendering + //// and the GPU backend will make things like the VAO which cannot be shared across + //// contexts + //_glWidget->makeCurrent(); + //gpu::Context::init(); + //qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK, + // QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram))); + //_glWidget->makeCurrent(); + //_gpuContext = std::make_shared(); - DependencyManager::get()->setGPUContext(_gpuContext); + //DependencyManager::get()->setGPUContext(_gpuContext); - // Restore the default main thread context - _offscreenContext->makeCurrent(); + //// Restore the default main thread context + //_offscreenContext->makeCurrent(); + + _graphicsEngine.initializeGPU(_glWidget); } static const QString SPLASH_SKYBOX{ "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" }; @@ -2705,7 +2645,7 @@ void Application::initializeDisplayPlugins() { // Once time initialization code DisplayPluginPointer targetDisplayPlugin; foreach(auto displayPlugin, displayPlugins) { - displayPlugin->setContext(_gpuContext); + displayPlugin->setContext(_graphicsEngine.getGPUContext()); if (displayPlugin->getName() == lastActiveDisplayPluginName) { targetDisplayPlugin = displayPlugin; } @@ -2719,14 +2659,14 @@ void Application::initializeDisplayPlugins() { setDisplayPlugin(defaultDisplayPlugin); // Now set the desired plugin if it's not the same as the default plugin - if (targetDisplayPlugin != defaultDisplayPlugin) { + if (targetDisplayPlugin && (targetDisplayPlugin != defaultDisplayPlugin)) { setDisplayPlugin(targetDisplayPlugin); } // Submit a default frame to render until the engine starts up updateRenderArgs(0.0f); - _offscreenContext->makeCurrent(); + _graphicsEngine._offscreenContext->makeCurrent(); #define ENABLE_SPLASH_FRAME 0 #if ENABLE_SPLASH_FRAME @@ -2769,11 +2709,12 @@ void Application::initializeDisplayPlugins() { } void Application::initializeRenderEngine() { - _offscreenContext->makeCurrent(); + // _offscreenContext->makeCurrent(); // FIXME: on low end systems os the shaders take up to 1 minute to compile, so we pause the deadlock watchdog thread. DeadlockWatchdogThread::withPause([&] { - // Set up the render engine + _graphicsEngine.initializeRender(DISABLE_DEFERRED); + /* // Set up the render engine render::CullFunctor cullFunctor = LODManager::shouldRender; _renderEngine->addJob("UpdateScene"); #ifndef Q_OS_ANDROID @@ -2785,7 +2726,7 @@ void Application::initializeRenderEngine() { // Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success. DependencyManager::get()->initializeShapePipelines(); - }); + */ }); } extern void setupPreferences(); @@ -2999,7 +2940,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { surfaceContext->setContextProperty("LODManager", DependencyManager::get().data()); surfaceContext->setContextProperty("HMD", DependencyManager::get().data()); surfaceContext->setContextProperty("Scene", DependencyManager::get().data()); - surfaceContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); + surfaceContext->setContextProperty("Render", _graphicsEngine.getRenderEngine()->getConfiguration().get()); surfaceContext->setContextProperty("Workload", _gameWorkload._engine->getConfiguration().get()); surfaceContext->setContextProperty("Reticle", getApplicationCompositor().getReticleInterface()); surfaceContext->setContextProperty("Snapshot", DependencyManager::get().data()); @@ -3454,8 +3395,8 @@ void Application::onPresent(quint32 frameCount) { postEvent(this, new QEvent((QEvent::Type)ApplicationEvent::Idle), Qt::HighEventPriority); } expected = false; - if (_renderEventHandler && !isAboutToQuit() && _pendingRenderEvent.compare_exchange_strong(expected, true)) { - postEvent(_renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render)); + if (_graphicsEngine.checkPendingRenderEvent() && !isAboutToQuit()) { + postEvent(_graphicsEngine._renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render)); } } @@ -4229,7 +4170,8 @@ bool Application::shouldPaint() const { #endif // Throttle if requested - if (displayPlugin->isThrottled() && (_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { + //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { + if (displayPlugin->isThrottled() && _graphicsEngine.shouldPaint()) { return false; } @@ -4481,7 +4423,7 @@ void Application::idle() { if (offscreenUi->size() != fromGlm(uiSize)) { qCDebug(interfaceapp) << "Device pixel ratio changed, triggering resize to " << uiSize; offscreenUi->resize(fromGlm(uiSize)); - _offscreenContext->makeCurrent(); + _graphicsEngine._offscreenContext->makeCurrent(); } } @@ -4493,8 +4435,8 @@ void Application::idle() { PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", int, ResourceCache::getPendingRequestCount()); PROFILE_COUNTER_IF_CHANGED(app, "currentProcessing", int, DependencyManager::get()->getStat("Processing").toInt()); PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get()->getStat("PendingProcessing").toInt()); - auto renderConfig = _renderEngine->getConfiguration(); - PROFILE_COUNTER_IF_CHANGED(render, "gpuTime", float, (float)_gpuContext->getFrameTimerGPUAverage()); + auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration(); + PROFILE_COUNTER_IF_CHANGED(render, "gpuTime", float, (float)_graphicsEngine.getGPUContext()->getFrameTimerGPUAverage()); auto opaqueRangeTimer = renderConfig->getConfig("OpaqueRangeTimer"); auto linearDepth = renderConfig->getConfig("LinearDepth"); auto surfaceGeometry = renderConfig->getConfig("SurfaceGeometry"); @@ -4536,7 +4478,7 @@ void Application::idle() { bool showWarnings = getLogger()->extraDebugging(); PerformanceWarning warn(showWarnings, "idle()"); - if (!_offscreenContext->makeCurrent()) { + if (!_graphicsEngine._offscreenContext->makeCurrent()) { qFatal("Unable to make main thread context current"); } @@ -4866,12 +4808,12 @@ QVector Application::pasteEntities(float x, float y, float z) { } void Application::init() { - _offscreenContext->makeCurrent(); + _graphicsEngine._offscreenContext->makeCurrent(); // Make sure Login state is up to date DependencyManager::get()->toggleLoginDialog(); - if (!DISABLE_DEFERRED) { - DependencyManager::get()->init(); - } +// if (!DISABLE_DEFERRED) { + // DependencyManager::get()->init(); + // } DependencyManager::get()->init(); _timerStart.start(); @@ -4940,7 +4882,7 @@ void Application::init() { } }, Qt::QueuedConnection); - _gameWorkload.startup(getEntities()->getWorkloadSpace(), _main3DScene, _entitySimulation); + _gameWorkload.startup(getEntities()->getWorkloadSpace(), _graphicsEngine.getRenderScene(), _entitySimulation); _entitySimulation->setWorkloadSpace(getEntities()->getWorkloadSpace()); } @@ -4974,7 +4916,7 @@ void Application::updateLOD(float deltaTime) const { // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode if (!isThrottleRendering()) { float presentTime = getActiveDisplayPlugin()->getAveragePresentTime(); - float engineRunTime = (float)(_renderEngine->getConfiguration().get()->getCPURunTime()); + float engineRunTime = (float)(_graphicsEngine.getRenderEngine()->getConfiguration().get()->getCPURunTime()); float gpuTime = getGPUContext()->getFrameTimerGPUAverage(); auto lodManager = DependencyManager::get(); lodManager->setRenderTimes(presentTime, engineRunTime, gpuTime); @@ -5364,7 +5306,7 @@ void Application::updateSecondaryCameraViewFrustum() { // camera should be. // Code based on SecondaryCameraJob - auto renderConfig = _renderEngine->getConfiguration(); + auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration(); assert(renderConfig); auto camera = dynamic_cast(renderConfig->getConfig("SecondaryCamera")); @@ -5935,7 +5877,7 @@ void Application::updateRenderArgs(float deltaTime) { _viewFrustum.setProjection(adjustedProjection); _viewFrustum.calculate(); } - appRenderArgs._renderArgs = RenderArgs(_gpuContext, lodManager->getOctreeSizeScale(), + appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getOctreeSizeScale(), lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); appRenderArgs._renderArgs._scene = getMain3DScene(); @@ -6597,7 +6539,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerFunction("HMD", "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0); scriptEngine->registerGlobalObject("Scene", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("Render", _renderEngine->getConfiguration().get()); + scriptEngine->registerGlobalObject("Render", _graphicsEngine.getRenderEngine()->getConfiguration().get()); scriptEngine->registerGlobalObject("Workload", _gameWorkload._engine->getConfiguration().get()); GraphicsScriptingInterface::registerMetaTypes(scriptEngine.data()); @@ -8241,7 +8183,7 @@ QOpenGLContext* Application::getPrimaryContext() { } bool Application::makeRenderingContextCurrent() { - return _offscreenContext->makeCurrent(); + return _graphicsEngine._offscreenContext->makeCurrent(); } bool Application::isForeground() const { diff --git a/interface/src/Application.h b/interface/src/Application.h index 346ea258da..249c5a723a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -73,6 +73,7 @@ #include "UndoStackScriptingInterface.h" #include "workload/GameWorkload.h" +#include "graphics/GraphicsEngine.h" #include #include @@ -157,6 +158,7 @@ public: void updateSecondaryCameraViewFrustum(); void updateCamera(RenderArgs& renderArgs, float deltaTime); + bool shouldPaint() const; void paintGL(); void resizeGL(); @@ -271,10 +273,16 @@ public: void setMaxOctreePacketsPerSecond(int maxOctreePPS); int getMaxOctreePacketsPerSecond() const; - render::ScenePointer getMain3DScene() override { return _main3DScene; } +/* render::ScenePointer getMain3DScene() override { return _main3DScene; } const render::ScenePointer& getMain3DScene() const { return _main3DScene; } render::EnginePointer getRenderEngine() override { return _renderEngine; } gpu::ContextPointer getGPUContext() const { return _gpuContext; } + */ + render::ScenePointer getMain3DScene() override { return _graphicsEngine.getRenderScene(); } + const render::ScenePointer& getMain3DScene() const { return _graphicsEngine.getRenderScene(); } + render::EnginePointer getRenderEngine() override { return _graphicsEngine.getRenderEngine(); } + gpu::ContextPointer getGPUContext() const { return _graphicsEngine.getGPUContext(); } + const GameWorkload& getGameWorkload() const { return _gameWorkload; } @@ -490,7 +498,6 @@ private: bool handleFileOpenEvent(QFileOpenEvent* event); void cleanupBeforeQuit(); - bool shouldPaint() const; void idle(); void update(float deltaTime); @@ -510,7 +517,7 @@ private: void initializeAcceptedFiles(); - void runRenderFrame(RenderArgs* renderArgs/*, Camera& whichCamera, bool selfAvatarOnly = false*/); + // void runRenderFrame(RenderArgs* renderArgs/*, Camera& whichCamera, bool selfAvatarOnly = false*/); bool importJSONFromURL(const QString& urlString); bool importSVOFromURL(const QString& urlString); @@ -551,7 +558,7 @@ private: bool _previousSessionCrashed; - OffscreenGLCanvas* _offscreenContext { nullptr }; + // OffscreenGLCanvas* _offscreenContext { nullptr }; DisplayPluginPointer _displayPlugin; QMetaObject::Connection _displayPluginPresentConnection; mutable std::mutex _displayPluginLock; @@ -573,7 +580,7 @@ private: QTimer _minimizedWindowTimer; QElapsedTimer _timerStart; QElapsedTimer _lastTimeUpdated; - QElapsedTimer _lastTimeRendered; + // QElapsedTimer _lastTimeRendered; ShapeManager _shapeManager; PhysicalEntitySimulationPointer _entitySimulation; @@ -657,12 +664,14 @@ private: quint64 _lastFaceTrackerUpdate; - render::ScenePointer _main3DScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) }; - render::EnginePointer _renderEngine{ new render::RenderEngine() }; - gpu::ContextPointer _gpuContext; // initialized during window creation + // render::ScenePointer _main3DScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) }; + // render::EnginePointer _renderEngine{ new render::RenderEngine() }; + // gpu::ContextPointer _gpuContext; // initialized during window creation GameWorkload _gameWorkload; + GraphicsEngine _graphicsEngine; + mutable QMutex _renderArgsMutex{ QMutex::Recursive }; struct AppRenderArgs { render::Args _renderArgs; @@ -720,8 +729,6 @@ private: bool _keyboardDeviceHasFocus { true }; - QString _returnFromFullScreenMirrorTo; - ConnectionMonitor _connectionMonitor; QTimer _addAssetToWorldResizeTimer; @@ -754,12 +761,12 @@ private: QUrl _avatarOverrideUrl; bool _saveAvatarOverrideUrl { false }; - QObject* _renderEventHandler{ nullptr }; + // QObject* _renderEventHandler{ nullptr }; - friend class RenderEventHandler; + // friend class RenderEventHandler; std::atomic _pendingIdleEvent { true }; - std::atomic _pendingRenderEvent { true }; + // std::atomic _pendingRenderEvent { true }; bool quitWhenFinished { false }; }; diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index 2daa49dcf7..9fe259ea36 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -32,7 +32,8 @@ void Application::paintGL() { // Some plugins process message events, allowing paintGL to be called reentrantly. _renderFrameCount++; - _lastTimeRendered.start(); + // SG: Moved into the RenderEventHandler + //_lastTimeRendered.start(); auto lastPaintBegin = usecTimestampNow(); PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount); @@ -88,10 +89,10 @@ void Application::paintGL() { { PROFILE_RANGE(render, "/gpuContextReset"); - _gpuContext->beginFrame(_appRenderArgs._view, HMDSensorPose); + _graphicsEngine.getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose); // Reset the gpu::Context Stages // Back to the default framebuffer; - gpu::doInBatch("Application_render::gpuContextReset", _gpuContext, [&](gpu::Batch& batch) { + gpu::doInBatch("Application_render::gpuContextReset", _graphicsEngine.getGPUContext(), [&](gpu::Batch& batch) { batch.resetStages(); }); } @@ -132,10 +133,10 @@ void Application::paintGL() { renderArgs._hudOperator = displayPlugin->getHUDOperator(); renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); renderArgs._blitFramebuffer = finalFramebuffer; - runRenderFrame(&renderArgs); + _graphicsEngine.render_runRenderFrame(&renderArgs); } - auto frame = _gpuContext->endFrame(); + auto frame = _graphicsEngine.getGPUContext()->endFrame(); frame->frameIndex = _renderFrameCount; frame->framebuffer = finalFramebuffer; frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) { @@ -163,68 +164,68 @@ void Application::paintGL() { // WorldBox Render Data & rendering functions - -class WorldBoxRenderData { -public: - typedef render::Payload Payload; - typedef Payload::DataPointer Pointer; - - int _val = 0; - static render::ItemID _item; // unique WorldBoxRenderData -}; - -render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID }; - -namespace render { - template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); } - template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); } - template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { - if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) { - PerformanceTimer perfTimer("worldBox"); - - auto& batch = *args->_batch; - DependencyManager::get()->bindSimpleProgram(batch); - renderWorldBox(args, batch); - } - } -} - -void Application::runRenderFrame(RenderArgs* renderArgs) { - PROFILE_RANGE(render, __FUNCTION__); - PerformanceTimer perfTimer("display"); - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()"); - - // The pending changes collecting the changes here - render::Transaction transaction; - - if (DependencyManager::get()->shouldRenderEntities()) { - // render models... - PerformanceTimer perfTimer("entities"); - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::runRenderFrame() ... entities..."); - - RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE; - - renderArgs->_debugFlags = renderDebugFlags; - } - - // Make sure the WorldBox is in the scene - // For the record, this one RenderItem is the first one we created and added to the scene. - // We could move that code elsewhere but you know... - if (!render::Item::isValidID(WorldBoxRenderData::_item)) { - auto worldBoxRenderData = std::make_shared(); - auto worldBoxRenderPayload = std::make_shared(worldBoxRenderData); - - WorldBoxRenderData::_item = _main3DScene->allocateID(); - - transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload); - _main3DScene->enqueueTransaction(transaction); - } - - { - PerformanceTimer perfTimer("EngineRun"); - _renderEngine->getRenderContext()->args = renderArgs; - _renderEngine->run(); - } -} +// +//class WorldBoxRenderData { +//public: +// typedef render::Payload Payload; +// typedef Payload::DataPointer Pointer; +// +// int _val = 0; +// static render::ItemID _item; // unique WorldBoxRenderData +//}; +// +//render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID }; +// +//namespace render { +// template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); } +// template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); } +// template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { +// if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) { +// PerformanceTimer perfTimer("worldBox"); +// +// auto& batch = *args->_batch; +// DependencyManager::get()->bindSimpleProgram(batch); +// renderWorldBox(args, batch); +// } +// } +//} +// +//void Application::runRenderFrame(RenderArgs* renderArgs) { +// PROFILE_RANGE(render, __FUNCTION__); +// PerformanceTimer perfTimer("display"); +// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()"); +// +// // The pending changes collecting the changes here +// render::Transaction transaction; +// +// if (DependencyManager::get()->shouldRenderEntities()) { +// // render models... +// PerformanceTimer perfTimer("entities"); +// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), +// "Application::runRenderFrame() ... entities..."); +// +// RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE; +// +// renderArgs->_debugFlags = renderDebugFlags; +// } +// +// // Make sure the WorldBox is in the scene +// // For the record, this one RenderItem is the first one we created and added to the scene. +// // We could move that code elsewhere but you know... +// if (!render::Item::isValidID(WorldBoxRenderData::_item)) { +// auto worldBoxRenderData = std::make_shared(); +// auto worldBoxRenderPayload = std::make_shared(worldBoxRenderData); +// +// WorldBoxRenderData::_item = _main3DScene->allocateID(); +// +// transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload); +// _main3DScene->enqueueTransaction(transaction); +// } +// +// { +// PerformanceTimer perfTimer("EngineRun"); +// _renderEngine->getRenderContext()->args = renderArgs; +// _renderEngine->run(); +// } +//} diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index e5e94da68a..e09872434a 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -36,114 +36,6 @@ using namespace std; -void renderWorldBox(RenderArgs* args, gpu::Batch& batch) { - auto geometryCache = DependencyManager::get(); - - // Show center of world - static const glm::vec3 RED(1.0f, 0.0f, 0.0f); - static const glm::vec3 GREEN(0.0f, 1.0f, 0.0f); - static const glm::vec3 BLUE(0.0f, 0.0f, 1.0f); - static const glm::vec3 GREY(0.5f, 0.5f, 0.5f); - static const glm::vec4 GREY4(0.5f, 0.5f, 0.5f, 1.0f); - - static const glm::vec4 DASHED_RED(1.0f, 0.0f, 0.0f, 1.0f); - static const glm::vec4 DASHED_GREEN(0.0f, 1.0f, 0.0f, 1.0f); - static const glm::vec4 DASHED_BLUE(0.0f, 0.0f, 1.0f, 1.0f); - static const float DASH_LENGTH = 1.0f; - static const float GAP_LENGTH = 1.0f; - auto transform = Transform{}; - static std::array geometryIds; - static std::once_flag initGeometryIds; - std::call_once(initGeometryIds, [&] { - for (size_t i = 0; i < geometryIds.size(); ++i) { - geometryIds[i] = geometryCache->allocateID(); - } - }); - - batch.setModelTransform(transform); - - geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(HALF_TREE_SCALE, 0.0f, 0.0f), RED, geometryIds[0]); - geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-HALF_TREE_SCALE, 0.0f, 0.0f), DASHED_RED, - DASH_LENGTH, GAP_LENGTH, geometryIds[1]); - - geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, HALF_TREE_SCALE, 0.0f), GREEN, geometryIds[2]); - geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -HALF_TREE_SCALE, 0.0f), DASHED_GREEN, - DASH_LENGTH, GAP_LENGTH, geometryIds[3]); - - geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, HALF_TREE_SCALE), BLUE, geometryIds[4]); - geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -HALF_TREE_SCALE), DASHED_BLUE, - DASH_LENGTH, GAP_LENGTH, geometryIds[5]); - - // X center boundaries - geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f), - glm::vec3(HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f), GREY, - geometryIds[6]); - geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f), - glm::vec3(-HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY, - geometryIds[7]); - geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), - glm::vec3(HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY, - geometryIds[8]); - geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f), - glm::vec3(HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY, - geometryIds[9]); - - // Z center boundaries - geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, -HALF_TREE_SCALE), - glm::vec3(0.0f, -HALF_TREE_SCALE, HALF_TREE_SCALE), GREY, - geometryIds[10]); - geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, -HALF_TREE_SCALE), - glm::vec3(0.0f, HALF_TREE_SCALE, -HALF_TREE_SCALE), GREY, - geometryIds[11]); - geometryCache->renderLine(batch, glm::vec3(0.0f, HALF_TREE_SCALE, -HALF_TREE_SCALE), - glm::vec3(0.0f, HALF_TREE_SCALE, HALF_TREE_SCALE), GREY, - geometryIds[12]); - geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, HALF_TREE_SCALE), - glm::vec3(0.0f, HALF_TREE_SCALE, HALF_TREE_SCALE), GREY, - geometryIds[13]); - - // Center boundaries - geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE), - glm::vec3(-HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY, - geometryIds[14]); - geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE), - glm::vec3(HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE), GREY, - geometryIds[15]); - geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE), - glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY, - geometryIds[16]); - geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), - glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY, - geometryIds[17]); - - - geometryCache->renderWireCubeInstance(args, batch, GREY4); - - // Draw meter markers along the 3 axis to help with measuring things - const float MARKER_DISTANCE = 1.0f; - const float MARKER_RADIUS = 0.05f; - - transform = Transform().setScale(MARKER_RADIUS); - batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(args, batch, RED); - - transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)).setScale(MARKER_RADIUS); - batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(args, batch, RED); - - transform = Transform().setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)).setScale(MARKER_RADIUS); - batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(args, batch, GREEN); - - transform = Transform().setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS); - batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(args, batch, BLUE); - - transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS); - batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(args, batch, GREY); -} - // Do some basic timing tests and report the results void runTimingTests() { // How long does it take to make a call to get the time? diff --git a/interface/src/Util.h b/interface/src/Util.h index 976a26ce82..ef289f5416 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -15,14 +15,9 @@ #include #include -#include -#include - class ShapeEntityItem; class ShapeInfo; -void renderWorldBox(RenderArgs* args, gpu::Batch& batch); - void runTimingTests(); void runUnitTests(); diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp new file mode 100644 index 0000000000..af207b988a --- /dev/null +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -0,0 +1,167 @@ +// +// GraphicsEngine.cpp +// +// Created by Sam Gateau on 29/6/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 +// +#include "GraphicsEngine.h" + +#include + +#include "WorldBox.h" +#include "LODManager.h" + +#include +#include +#include +#include +#include + +#include "RenderEventHandler.h" + +#include +#include +#include + +GraphicsEngine::GraphicsEngine() { +} + +GraphicsEngine::~GraphicsEngine() { +} + +void GraphicsEngine::initializeGPU(GLWidget* glwidget) { + + // Build an offscreen GL context for the main thread. + _offscreenContext = new OffscreenGLCanvas(); + _offscreenContext->setObjectName("MainThreadContext"); + _offscreenContext->create(glwidget->qglContext()); + if (!_offscreenContext->makeCurrent()) { + qFatal("Unable to make offscreen context current"); + } + _offscreenContext->doneCurrent(); + _offscreenContext->setThreadContext(); + + _renderEventHandler = new RenderEventHandler(glwidget->qglContext()); + if (!_offscreenContext->makeCurrent()) { + qFatal("Unable to make offscreen context current"); + } + + // Requires the window context, because that's what's used in the actual rendering + // and the GPU backend will make things like the VAO which cannot be shared across + // contexts + glwidget->makeCurrent(); + gpu::Context::init(); + qApp->setProperty(hifi::properties::gl::MAKE_PROGRAM_CALLBACK, + QVariant::fromValue((void*)(&gpu::gl::GLBackend::makeProgram))); + glwidget->makeCurrent(); + _gpuContext = std::make_shared(); + + DependencyManager::get()->setGPUContext(_gpuContext); + + // Restore the default main thread context + _offscreenContext->makeCurrent(); +} + +void GraphicsEngine::initializeRender(bool disableDeferred) { + + // Set up the render engine + render::CullFunctor cullFunctor = LODManager::shouldRender; + _renderEngine->addJob("UpdateScene"); +#ifndef Q_OS_ANDROID + _renderEngine->addJob("SecondaryCameraJob", cullFunctor, !disableDeferred); +#endif + _renderEngine->addJob("RenderMainView", cullFunctor, !disableDeferred, render::ItemKey::TAG_BITS_0, render::ItemKey::TAG_BITS_0); + _renderEngine->load(); + _renderEngine->registerScene(_renderScene); + + // Now that OpenGL is initialized, we are sure we have a valid context and can create the various pipeline shaders with success. + DependencyManager::get()->initializeShapePipelines(); + + +} + +void GraphicsEngine::startup() { + + + static_cast(_renderEventHandler)->resumeThread(); +} + +void GraphicsEngine::shutdown() { + // The cleanup process enqueues the transactions but does not process them. Calling this here will force the actual + // removal of the items. + // See https://highfidelity.fogbugz.com/f/cases/5328 + _renderScene->enqueueFrame(); // flush all the transactions + _renderScene->processTransactionQueue(); // process and apply deletions + + _gpuContext->shutdown(); + + + // shutdown render engine + _renderScene = nullptr; + _renderEngine = nullptr; +} + + +void GraphicsEngine::render_runRenderFrame(RenderArgs* renderArgs) { + PROFILE_RANGE(render, __FUNCTION__); + PerformanceTimer perfTimer("render"); +// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()"); + + // The pending changes collecting the changes here + render::Transaction transaction; + + // this is not in use at all anymore + //if (DependencyManager::get()->shouldRenderEntities()) { + // render models... + // PerformanceTimer perfTimer("entities"); + // PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + // "Application::runRenderFrame() ... entities..."); + + //RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE; + + //renderArgs->_debugFlags = renderDebugFlags; + //} + + // Make sure the WorldBox is in the scene + // For the record, this one RenderItem is the first one we created and added to the scene. + // We could move that code elsewhere but you know... + if (!render::Item::isValidID(WorldBoxRenderData::_item)) { + auto worldBoxRenderData = std::make_shared(); + auto worldBoxRenderPayload = std::make_shared(worldBoxRenderData); + + WorldBoxRenderData::_item = _renderScene->allocateID(); + + transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload); + _renderScene->enqueueTransaction(transaction); + } + + { + // PerformanceTimer perfTimer("EngineRun"); + _renderEngine->getRenderContext()->args = renderArgs; + _renderEngine->run(); + } +} + +static const unsigned int THROTTLED_SIM_FRAMERATE = 15; +static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SIM_FRAMERATE; + + + + +bool GraphicsEngine::shouldPaint() const { + + // Throttle if requested + if ((static_cast(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { + return false; + } + + return true; +} + +bool GraphicsEngine::checkPendingRenderEvent() { + bool expected = false; + return (_renderEventHandler && static_cast(_renderEventHandler)->_pendingRenderEvent.compare_exchange_strong(expected, true)); +} diff --git a/interface/src/graphics/GraphicsEngine.h b/interface/src/graphics/GraphicsEngine.h new file mode 100644 index 0000000000..29128daafd --- /dev/null +++ b/interface/src/graphics/GraphicsEngine.h @@ -0,0 +1,57 @@ +// +// GraphicsEngine.h +// +// Created by Sam Gateau on 29/6/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 +// +#ifndef hifi_GraphicsEngine_h +#define hifi_GraphicsEngine_h + +#include +#include + +#include + +#include + +class GraphicsEngine { +public: + GraphicsEngine(); + ~GraphicsEngine(); + + void initializeGPU(GLWidget*); + void initializeRender(bool disableDeferred); + void startup(); + void shutdown(); + + render::ScenePointer getRenderScene() const { return _renderScene; } + render::EnginePointer getRenderEngine() const { return _renderEngine; } + gpu::ContextPointer getGPUContext() const { return _gpuContext; } + + // Same as the one in application + bool shouldPaint() const; + bool checkPendingRenderEvent(); + +private: + // THread specific calls + void render_runRenderFrame(RenderArgs* renderArgs); + +protected: + + render::ScenePointer _renderScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) }; + render::EnginePointer _renderEngine{ new render::RenderEngine() }; + + gpu::ContextPointer _gpuContext; // initialized during window creation + + QObject* _renderEventHandler{ nullptr }; + friend class RenderEventHandler; + + OffscreenGLCanvas* _offscreenContext{ nullptr }; + + friend class Application; +}; + +#endif // hifi_GraphicsEngine_h diff --git a/interface/src/graphics/RenderEventHandler.cpp b/interface/src/graphics/RenderEventHandler.cpp new file mode 100644 index 0000000000..0ca82201d5 --- /dev/null +++ b/interface/src/graphics/RenderEventHandler.cpp @@ -0,0 +1,71 @@ +// +// RenderEventHandler.cpp +// +// Created by Bradley Austin Davis on 29/6/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 +// +#include "RenderEventHandler.h" + +#include "Application.h" +#include +#include + +#include "CrashHandler.h" + +RenderEventHandler::RenderEventHandler(QOpenGLContext* context) { + _renderContext = new OffscreenGLCanvas(); + _renderContext->setObjectName("RenderContext"); + _renderContext->create(context); + if (!_renderContext->makeCurrent()) { + qFatal("Unable to make rendering context current"); + } + _renderContext->doneCurrent(); + + // Deleting the object with automatically shutdown the thread + connect(qApp, &QCoreApplication::aboutToQuit, this, &QObject::deleteLater); + + // Transfer to a new thread + moveToNewNamedThread(this, "RenderThread", [this](QThread* renderThread) { + hifi::qt::addBlockingForbiddenThread("Render", renderThread); + _renderContext->moveToThreadWithContext(renderThread); + _lastTimeRendered.start(); + }, std::bind(&RenderEventHandler::initialize, this), QThread::HighestPriority); +} + +void RenderEventHandler::initialize() { + setObjectName("Render"); + PROFILE_SET_THREAD_NAME("Render"); + setCrashAnnotation("render_thread_id", std::to_string((size_t)QThread::currentThreadId())); + if (!_renderContext->makeCurrent()) { + qFatal("Unable to make rendering context current on render thread"); + } + +} + +void RenderEventHandler::resumeThread() { + _pendingRenderEvent = false; +} + +void RenderEventHandler::render() { + if (qApp->shouldPaint()) { + _lastTimeRendered.start(); + qApp->paintGL(); + } +} + +bool RenderEventHandler::event(QEvent* event) { + switch ((int)event->type()) { + case ApplicationEvent::Render: + render(); + _pendingRenderEvent.store(false); + return true; + + default: + break; + } + return Parent::event(event); +} + diff --git a/interface/src/graphics/RenderEventHandler.h b/interface/src/graphics/RenderEventHandler.h new file mode 100644 index 0000000000..8b0e4c5e15 --- /dev/null +++ b/interface/src/graphics/RenderEventHandler.h @@ -0,0 +1,47 @@ +// +// RenderEventHandler.h +// +// Created by Bradley Austin Davis on 29/6/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 +// +#ifndef hifi_RenderEventHandler_h +#define hifi_RenderEventHandler_h + +#include "gl/OffscreenGLCanvas.h" +#include +#include + +enum ApplicationEvent { + // Execute a lambda function + Lambda = QEvent::User + 1, + // Trigger the next render + Render, + // Trigger the next idle + Idle, +}; + +class RenderEventHandler : public QObject { + using Parent = QObject; + Q_OBJECT +public: + RenderEventHandler(QOpenGLContext* context); + + QElapsedTimer _lastTimeRendered; + std::atomic _pendingRenderEvent{ true }; + + void resumeThread(); + +private: + void initialize(); + + void render(); + + bool event(QEvent* event) override; + + OffscreenGLCanvas* _renderContext{ nullptr }; +}; + +#endif // #include hifi_RenderEventHandler_h \ No newline at end of file diff --git a/interface/src/graphics/WorldBox.cpp b/interface/src/graphics/WorldBox.cpp new file mode 100644 index 0000000000..908055e9c6 --- /dev/null +++ b/interface/src/graphics/WorldBox.cpp @@ -0,0 +1,138 @@ +// +// WorldBox.cpp +// +// Created by Sam Gateau on 01/07/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 +// +#include "WorldBox.h" + +#include "OctreeConstants.h" + +render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID }; + + +namespace render { + template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); } + template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); } + template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { + if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) { + PerformanceTimer perfTimer("worldBox"); + + auto& batch = *args->_batch; + DependencyManager::get()->bindSimpleProgram(batch); + WorldBoxRenderData::renderWorldBox(args, batch); + } + } +} + +void WorldBoxRenderData::renderWorldBox(RenderArgs* args, gpu::Batch& batch) { + auto geometryCache = DependencyManager::get(); + + // Show center of world + static const glm::vec3 RED(1.0f, 0.0f, 0.0f); + static const glm::vec3 GREEN(0.0f, 1.0f, 0.0f); + static const glm::vec3 BLUE(0.0f, 0.0f, 1.0f); + static const glm::vec3 GREY(0.5f, 0.5f, 0.5f); + static const glm::vec4 GREY4(0.5f, 0.5f, 0.5f, 1.0f); + + static const glm::vec4 DASHED_RED(1.0f, 0.0f, 0.0f, 1.0f); + static const glm::vec4 DASHED_GREEN(0.0f, 1.0f, 0.0f, 1.0f); + static const glm::vec4 DASHED_BLUE(0.0f, 0.0f, 1.0f, 1.0f); + static const float DASH_LENGTH = 1.0f; + static const float GAP_LENGTH = 1.0f; + auto transform = Transform{}; + static std::array geometryIds; + static std::once_flag initGeometryIds; + std::call_once(initGeometryIds, [&] { + for (size_t i = 0; i < geometryIds.size(); ++i) { + geometryIds[i] = geometryCache->allocateID(); + } + }); + + batch.setModelTransform(transform); + + geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(HALF_TREE_SCALE, 0.0f, 0.0f), RED, geometryIds[0]); + geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(-HALF_TREE_SCALE, 0.0f, 0.0f), DASHED_RED, + DASH_LENGTH, GAP_LENGTH, geometryIds[1]); + + geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, HALF_TREE_SCALE, 0.0f), GREEN, geometryIds[2]); + geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, -HALF_TREE_SCALE, 0.0f), DASHED_GREEN, + DASH_LENGTH, GAP_LENGTH, geometryIds[3]); + + geometryCache->renderLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, HALF_TREE_SCALE), BLUE, geometryIds[4]); + geometryCache->renderDashedLine(batch, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -HALF_TREE_SCALE), DASHED_BLUE, + DASH_LENGTH, GAP_LENGTH, geometryIds[5]); + + // X center boundaries + geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f), + glm::vec3(HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f), GREY, + geometryIds[6]); + geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f), + glm::vec3(-HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY, + geometryIds[7]); + geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), + glm::vec3(HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY, + geometryIds[8]); + geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, -HALF_TREE_SCALE, 0.0f), + glm::vec3(HALF_TREE_SCALE, HALF_TREE_SCALE, 0.0f), GREY, + geometryIds[9]); + + // Z center boundaries + geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, -HALF_TREE_SCALE), + glm::vec3(0.0f, -HALF_TREE_SCALE, HALF_TREE_SCALE), GREY, + geometryIds[10]); + geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, -HALF_TREE_SCALE), + glm::vec3(0.0f, HALF_TREE_SCALE, -HALF_TREE_SCALE), GREY, + geometryIds[11]); + geometryCache->renderLine(batch, glm::vec3(0.0f, HALF_TREE_SCALE, -HALF_TREE_SCALE), + glm::vec3(0.0f, HALF_TREE_SCALE, HALF_TREE_SCALE), GREY, + geometryIds[12]); + geometryCache->renderLine(batch, glm::vec3(0.0f, -HALF_TREE_SCALE, HALF_TREE_SCALE), + glm::vec3(0.0f, HALF_TREE_SCALE, HALF_TREE_SCALE), GREY, + geometryIds[13]); + + // Center boundaries + geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE), + glm::vec3(-HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY, + geometryIds[14]); + geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE), + glm::vec3(HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE), GREY, + geometryIds[15]); + geometryCache->renderLine(batch, glm::vec3(HALF_TREE_SCALE, 0.0f, -HALF_TREE_SCALE), + glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY, + geometryIds[16]); + geometryCache->renderLine(batch, glm::vec3(-HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), + glm::vec3(HALF_TREE_SCALE, 0.0f, HALF_TREE_SCALE), GREY, + geometryIds[17]); + + + geometryCache->renderWireCubeInstance(args, batch, GREY4); + + // Draw meter markers along the 3 axis to help with measuring things + const float MARKER_DISTANCE = 1.0f; + const float MARKER_RADIUS = 0.05f; + + transform = Transform().setScale(MARKER_RADIUS); + batch.setModelTransform(transform); + geometryCache->renderSolidSphereInstance(args, batch, RED); + + transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)).setScale(MARKER_RADIUS); + batch.setModelTransform(transform); + geometryCache->renderSolidSphereInstance(args, batch, RED); + + transform = Transform().setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)).setScale(MARKER_RADIUS); + batch.setModelTransform(transform); + geometryCache->renderSolidSphereInstance(args, batch, GREEN); + + transform = Transform().setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS); + batch.setModelTransform(transform); + geometryCache->renderSolidSphereInstance(args, batch, BLUE); + + transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS); + batch.setModelTransform(transform); + geometryCache->renderSolidSphereInstance(args, batch, GREY); +} + diff --git a/interface/src/graphics/WorldBox.h b/interface/src/graphics/WorldBox.h new file mode 100644 index 0000000000..114777ba0f --- /dev/null +++ b/interface/src/graphics/WorldBox.h @@ -0,0 +1,43 @@ +// +// WorldBox.h +// +// Created by Sam Gateau on 01/07/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 +// +#ifndef hifi_WorldBox_h +#define hifi_WorldBox_h + +#include + +#include +#include + +#include +#include +#include "Menu.h" + + + +class WorldBoxRenderData { +public: + typedef render::Payload Payload; + typedef Payload::DataPointer Pointer; + + int _val = 0; + static render::ItemID _item; // unique WorldBoxRenderData + + + + static void renderWorldBox(RenderArgs* args, gpu::Batch& batch); +}; + +namespace render { + template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff); + template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff); + template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args); +} + +#endif // hifi_WorldBox_h \ No newline at end of file diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index ea660fb0e2..a0b4f856a1 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -55,7 +55,7 @@ ApplicationOverlay::~ApplicationOverlay() { // Renders the overlays either to a texture or to the screen void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { PROFILE_RANGE(render, __FUNCTION__); - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); +// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); buildFramebufferObject(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 9223e0fa03..6b6d8f00b7 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -712,11 +712,16 @@ void RenderDeferredCleanup::run(const render::RenderContextPointer& renderContex } } +RenderDeferred::RenderDeferred(bool renderShadows): + _renderShadows(renderShadows) +{ + DependencyManager::get()->init(); +} + void RenderDeferred::configure(const Config& config) { } void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs) { - PROFILE_RANGE(render, "DeferredLighting"); auto deferredTransform = inputs.get0(); auto deferredFramebuffer = inputs.get1(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 9b55083ad7..96d3f42958 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -167,8 +167,7 @@ public: using Config = RenderDeferredConfig; using JobModel = render::Job::ModelI; - RenderDeferred() {} - RenderDeferred(bool renderShadows) : _renderShadows(renderShadows) {} + RenderDeferred(bool renderShadows = false); void configure(const Config& config); diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index ceac4ae3c8..9d6a8e6016 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -424,10 +424,12 @@ LightStageSetup::LightStageSetup() { } void LightStageSetup::run(const render::RenderContextPointer& renderContext) { - auto stage = renderContext->_scene->getStage(LightStage::getName()); - if (!stage) { - stage = std::make_shared(); - renderContext->_scene->resetStage(LightStage::getName(), stage); + if (renderContext->_scene) { + auto stage = renderContext->_scene->getStage(LightStage::getName()); + if (!stage) { + stage = std::make_shared(); + renderContext->_scene->resetStage(LightStage::getName(), stage); + } } } From f9bd6f5d039eec7c4f797cf6d4a8635d1d1daf36 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 4 Jul 2018 11:34:58 +0200 Subject: [PATCH 004/117] slowly clening up --- interface/src/Application.cpp | 4 ++-- interface/src/graphics/GraphicsEngine.cpp | 2 ++ interface/src/graphics/GraphicsEngine.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 12d5c537d1..dc091f3809 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2536,7 +2536,7 @@ Application::~Application() { // Can't log to file passed this point, FileLogger about to be deleted qInstallMessageHandler(LogHandler::verboseMessageHandler); - _renderEventHandler->deleteLater(); +// _renderEventHandler->deleteLater(); } void Application::initializeGL() { @@ -4178,7 +4178,7 @@ bool Application::shouldPaint() const { // Throttle if requested //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { - if (displayPlugin->isThrottled() && _graphicsEngine.shouldPaint()) { + if (displayPlugin->isThrottled() && !_graphicsEngine.shouldPaint()) { return false; } diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index af207b988a..eea54c7b8a 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -102,6 +102,8 @@ void GraphicsEngine::shutdown() { // shutdown render engine _renderScene = nullptr; _renderEngine = nullptr; + + _renderEventHandler->deleteLater(); } diff --git a/interface/src/graphics/GraphicsEngine.h b/interface/src/graphics/GraphicsEngine.h index 29128daafd..89d1eb1d94 100644 --- a/interface/src/graphics/GraphicsEngine.h +++ b/interface/src/graphics/GraphicsEngine.h @@ -36,7 +36,7 @@ public: bool checkPendingRenderEvent(); private: - // THread specific calls + // Thread specific calls void render_runRenderFrame(RenderArgs* renderArgs); protected: From d2a66b9e7de8a1f4a3a68c95a9de7665ec0e5295 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 4 Jul 2018 17:26:24 +0200 Subject: [PATCH 005/117] Moving the paintGL to a true GraphicsEngine::render_performFrame() --- interface/src/Application.cpp | 19 +- interface/src/Application.h | 29 +- interface/src/Application_render.cpp | 279 +++++++++--------- interface/src/graphics/GraphicsEngine.cpp | 180 +++++++++-- interface/src/graphics/GraphicsEngine.h | 35 +++ interface/src/graphics/RenderEventHandler.cpp | 6 +- interface/src/graphics/RenderEventHandler.h | 6 +- libraries/task/src/task/Config.h | 7 +- libraries/task/src/task/Task.h | 4 +- 9 files changed, 360 insertions(+), 205 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cbe0212a0b..fbba8c5c87 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1886,7 +1886,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto displayPlugin = qApp->getActiveDisplayPlugin(); - properties["render_rate"] = _renderLoopCounter.rate(); + properties["render_rate"] = getRenderLoopRate(); properties["target_render_rate"] = getTargetRenderFrameRate(); properties["present_rate"] = displayPlugin->presentRate(); properties["new_frame_present_rate"] = displayPlugin->newFramePresentRate(); @@ -2900,7 +2900,7 @@ void Application::onDesktopRootContextCreated(QQmlContext* surfaceContext) { surfaceContext->setContextProperty("Recording", DependencyManager::get().data()); surfaceContext->setContextProperty("Preferences", DependencyManager::get().data()); surfaceContext->setContextProperty("AddressManager", DependencyManager::get().data()); - surfaceContext->setContextProperty("FrameTimings", &_frameTimingsScriptingInterface); + surfaceContext->setContextProperty("FrameTimings", &_graphicsEngine._frameTimingsScriptingInterface); surfaceContext->setContextProperty("Rates", new RatesScriptingInterface(this)); surfaceContext->setContextProperty("TREE_SCALE", TREE_SCALE); @@ -4437,7 +4437,7 @@ void Application::idle() { if (displayPlugin) { PROFILE_COUNTER_IF_CHANGED(app, "present", float, displayPlugin->presentRate()); } - PROFILE_COUNTER_IF_CHANGED(app, "renderLoopRate", float, _renderLoopCounter.rate()); + PROFILE_COUNTER_IF_CHANGED(app, "renderLoopRate", float, getRenderLoopRate()); PROFILE_COUNTER_IF_CHANGED(app, "currentDownloads", int, ResourceCache::getLoadingRequests().length()); PROFILE_COUNTER_IF_CHANGED(app, "pendingDownloads", int, ResourceCache::getPendingRequestCount()); PROFILE_COUNTER_IF_CHANGED(app, "currentProcessing", int, DependencyManager::get()->getStat("Processing").toInt()); @@ -5382,7 +5382,7 @@ void Application::updateSecondaryCameraViewFrustum() { static bool domainLoadingInProgress = false; void Application::update(float deltaTime) { - PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_renderFrameCount + 1); + PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_graphicsEngine._renderFrameCount + 1); if (!_physicsEnabled) { if (!domainLoadingInProgress) { @@ -5839,7 +5839,7 @@ void Application::update(float deltaTime) { // load the view frustum // FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering. // Then we can move this logic into the Avatar::simulate call. - myAvatar->preDisplaySide(&_appRenderArgs._renderArgs); +// myAvatar->preDisplaySide(&_appRenderArgs._renderArgs); { @@ -5855,7 +5855,7 @@ void Application::update(float deltaTime) { } void Application::updateRenderArgs(float deltaTime) { - editRenderArgs([this, deltaTime](AppRenderArgs& appRenderArgs) { + _graphicsEngine.editRenderArgs([this, deltaTime](AppRenderArgs& appRenderArgs) { PerformanceTimer perfTimer("editRenderArgs"); appRenderArgs._headPose = getHMDSensorPose(); @@ -5969,6 +5969,13 @@ void Application::updateRenderArgs(float deltaTime) { QMutexLocker viewLocker(&_viewMutex); appRenderArgs._renderArgs.setViewFrustum(_displayViewFrustum); } + + + // HACK + // load the view frustum + // FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering. + // Then we can move this logic into the Avatar::simulate call. + myAvatar->preDisplaySide(&appRenderArgs._renderArgs); }); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 249c5a723a..6f4b24c434 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -78,7 +78,6 @@ #include #include #include -#include "FrameTimingsScriptingInterface.h" #include "Sound.h" @@ -159,7 +158,7 @@ public: void updateCamera(RenderArgs& renderArgs, float deltaTime); bool shouldPaint() const; - void paintGL(); +// void paintGL(); void resizeGL(); bool event(QEvent* event) override; @@ -208,8 +207,8 @@ public: Overlays& getOverlays() { return _overlays; } - size_t getRenderFrameCount() const { return _renderFrameCount; } - float getRenderLoopRate() const { return _renderLoopCounter.rate(); } + size_t getRenderFrameCount() const { return _graphicsEngine.getRenderFrameCount(); } + float getRenderLoopRate() const { return _graphicsEngine.getRenderLoopRate(); } float getTargetRenderFrameRate() const; // frames/second float getFieldOfView() { return _fieldOfView.get(); } @@ -569,14 +568,10 @@ private: QUndoStack _undoStack; UndoStackScriptingInterface _undoStackScriptingInterface; - uint32_t _renderFrameCount { 0 }; // Frame Rate Measurement - RateCounter<500> _renderLoopCounter; RateCounter<500> _gameLoopCounter; - FrameTimingsScriptingInterface _frameTimingsScriptingInterface; - QTimer _minimizedWindowTimer; QElapsedTimer _timerStart; QElapsedTimer _lastTimeUpdated; @@ -671,24 +666,6 @@ private: GameWorkload _gameWorkload; GraphicsEngine _graphicsEngine; - - mutable QMutex _renderArgsMutex{ QMutex::Recursive }; - struct AppRenderArgs { - render::Args _renderArgs; - glm::mat4 _eyeToWorld; - glm::mat4 _view; - glm::mat4 _eyeOffsets[2]; - glm::mat4 _eyeProjections[2]; - glm::mat4 _headPose; - glm::mat4 _sensorToWorld; - float _sensorToWorldScale { 1.0f }; - bool _isStereo{ false }; - }; - AppRenderArgs _appRenderArgs; - - - using RenderArgsEditor = std::function ; - void editRenderArgs(RenderArgsEditor editor); void updateRenderArgs(float deltaTime); diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index ab38096895..82010fa18f 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -19,151 +19,144 @@ #include "Util.h" -// Statically provided display and input plugins -extern DisplayPluginList getDisplayPlugins(); - -void Application::editRenderArgs(RenderArgsEditor editor) { - QMutexLocker renderLocker(&_renderArgsMutex); - editor(_appRenderArgs); - -} - -void Application::paintGL() { - // Some plugins process message events, allowing paintGL to be called reentrantly. - - _renderFrameCount++; - // SG: Moved into the RenderEventHandler - //_lastTimeRendered.start(); - - auto lastPaintBegin = usecTimestampNow(); - PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount); - PerformanceTimer perfTimer("paintGL"); - - if (nullptr == _displayPlugin) { - return; - } - - DisplayPluginPointer displayPlugin; - { - PROFILE_RANGE(render, "/getActiveDisplayPlugin"); - displayPlugin = getActiveDisplayPlugin(); - } - - { - PROFILE_RANGE(render, "/pluginBeginFrameRender"); - // If a display plugin loses it's underlying support, it - // needs to be able to signal us to not use it - if (!displayPlugin->beginFrameRender(_renderFrameCount)) { - QMetaObject::invokeMethod(this, "updateDisplayMode"); - return; - } - } - - RenderArgs renderArgs; - glm::mat4 HMDSensorPose; - glm::mat4 eyeToWorld; - glm::mat4 sensorToWorld; - - bool isStereo; - glm::mat4 stereoEyeOffsets[2]; - glm::mat4 stereoEyeProjections[2]; - - { - QMutexLocker viewLocker(&_renderArgsMutex); - renderArgs = _appRenderArgs._renderArgs; - - // don't render if there is no context. - if (!_appRenderArgs._renderArgs._context) { - return; - } - - HMDSensorPose = _appRenderArgs._headPose; - eyeToWorld = _appRenderArgs._eyeToWorld; - sensorToWorld = _appRenderArgs._sensorToWorld; - isStereo = _appRenderArgs._isStereo; - for_each_eye([&](Eye eye) { - stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye]; - stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye]; - }); - } - - { - PROFILE_RANGE(render, "/gpuContextReset"); - _graphicsEngine.getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose); - // Reset the gpu::Context Stages - // Back to the default framebuffer; - gpu::doInBatch("Application_render::gpuContextReset", _graphicsEngine.getGPUContext(), [&](gpu::Batch& batch) { - batch.resetStages(); - }); - } - { - PROFILE_RANGE(render, "/renderOverlay"); - PerformanceTimer perfTimer("renderOverlay"); - // NOTE: There is no batch associated with this renderArgs - // the ApplicationOverlay class assumes it's viewport is setup to be the device size - renderArgs._viewport = glm::ivec4(0, 0, getDeviceSize() * getRenderResolutionScale()); - _applicationOverlay.renderOverlay(&renderArgs); - } - - { - PROFILE_RANGE(render, "/updateCompositor"); - getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); - } - - gpu::FramebufferPointer finalFramebuffer; - QSize finalFramebufferSize; - { - PROFILE_RANGE(render, "/getOutputFramebuffer"); - // Primary rendering pass - auto framebufferCache = DependencyManager::get(); - finalFramebufferSize = framebufferCache->getFrameBufferSize(); - // Final framebuffer that will be handled to the display-plugin - finalFramebuffer = framebufferCache->getFramebuffer(); - } - - { - if (isStereo) { - renderArgs._context->enableStereo(true); - renderArgs._context->setStereoProjections(stereoEyeProjections); - renderArgs._context->setStereoViews(stereoEyeOffsets); - } - - renderArgs._hudOperator = displayPlugin->getHUDOperator(); - renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); - renderArgs._blitFramebuffer = finalFramebuffer; - _graphicsEngine.render_runRenderFrame(&renderArgs); - } - - auto frame = _graphicsEngine.getGPUContext()->endFrame(); - frame->frameIndex = _renderFrameCount; - frame->framebuffer = finalFramebuffer; - frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) { - auto frameBufferCache = DependencyManager::get(); - if (frameBufferCache) { - frameBufferCache->releaseFramebuffer(framebuffer); - } - }; - // deliver final scene rendering commands to the display plugin - { - PROFILE_RANGE(render, "/pluginOutput"); - PerformanceTimer perfTimer("pluginOutput"); - _renderLoopCounter.increment(); - displayPlugin->submitFrame(frame); - } - - // Reset the framebuffer and stereo state - renderArgs._blitFramebuffer.reset(); - renderArgs._context->enableStereo(false); - - { - Stats::getInstance()->setRenderDetails(renderArgs._details); - } - - uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; - _frameTimingsScriptingInterface.addValue(lastPaintDuration); -} +//void Application::paintGL() { +// // Some plugins process message events, allowing paintGL to be called reentrantly. +// +// _renderFrameCount++; +// // SG: Moved into the RenderEventHandler +// //_lastTimeRendered.start(); +// +// auto lastPaintBegin = usecTimestampNow(); +// PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount); +// PerformanceTimer perfTimer("paintGL"); +// +// if (nullptr == _displayPlugin) { +// return; +// } +// +// DisplayPluginPointer displayPlugin; +// { +// PROFILE_RANGE(render, "/getActiveDisplayPlugin"); +// displayPlugin = getActiveDisplayPlugin(); +// } +// +// { +// PROFILE_RANGE(render, "/pluginBeginFrameRender"); +// // If a display plugin loses it's underlying support, it +// // needs to be able to signal us to not use it +// if (!displayPlugin->beginFrameRender(_renderFrameCount)) { +// QMetaObject::invokeMethod(this, "updateDisplayMode"); +// return; +// } +// } +// +// RenderArgs renderArgs; +// glm::mat4 HMDSensorPose; +// glm::mat4 eyeToWorld; +// glm::mat4 sensorToWorld; +// +// bool isStereo; +// glm::mat4 stereoEyeOffsets[2]; +// glm::mat4 stereoEyeProjections[2]; +// +// { +// QMutexLocker viewLocker(&_renderArgsMutex); +// renderArgs = _appRenderArgs._renderArgs; +// +// // don't render if there is no context. +// if (!_appRenderArgs._renderArgs._context) { +// return; +// } +// +// HMDSensorPose = _appRenderArgs._headPose; +// eyeToWorld = _appRenderArgs._eyeToWorld; +// sensorToWorld = _appRenderArgs._sensorToWorld; +// isStereo = _appRenderArgs._isStereo; +// for_each_eye([&](Eye eye) { +// stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye]; +// stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye]; +// }); +// } +// +// { +// PROFILE_RANGE(render, "/gpuContextReset"); +// _graphicsEngine.getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose); +// // Reset the gpu::Context Stages +// // Back to the default framebuffer; +// gpu::doInBatch("Application_render::gpuContextReset", _graphicsEngine.getGPUContext(), [&](gpu::Batch& batch) { +// batch.resetStages(); +// }); +// } +// +// +// { +// PROFILE_RANGE(render, "/renderOverlay"); +// PerformanceTimer perfTimer("renderOverlay"); +// // NOTE: There is no batch associated with this renderArgs +// // the ApplicationOverlay class assumes it's viewport is setup to be the device size +// renderArgs._viewport = glm::ivec4(0, 0, getDeviceSize() * getRenderResolutionScale()); +// _applicationOverlay.renderOverlay(&renderArgs); +// } +// +// { +// PROFILE_RANGE(render, "/updateCompositor"); +// getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); +// } +// +// gpu::FramebufferPointer finalFramebuffer; +// QSize finalFramebufferSize; +// { +// PROFILE_RANGE(render, "/getOutputFramebuffer"); +// // Primary rendering pass +// auto framebufferCache = DependencyManager::get(); +// finalFramebufferSize = framebufferCache->getFrameBufferSize(); +// // Final framebuffer that will be handled to the display-plugin +// finalFramebuffer = framebufferCache->getFramebuffer(); +// } +// +// { +// if (isStereo) { +// renderArgs._context->enableStereo(true); +// renderArgs._context->setStereoProjections(stereoEyeProjections); +// renderArgs._context->setStereoViews(stereoEyeOffsets); +// } +// +// renderArgs._hudOperator = displayPlugin->getHUDOperator(); +// renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); +// renderArgs._blitFramebuffer = finalFramebuffer; +// _graphicsEngine.render_runRenderFrame(&renderArgs); +// } +// +// auto frame = _graphicsEngine.getGPUContext()->endFrame(); +// frame->frameIndex = _renderFrameCount; +// frame->framebuffer = finalFramebuffer; +// frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) { +// auto frameBufferCache = DependencyManager::get(); +// if (frameBufferCache) { +// frameBufferCache->releaseFramebuffer(framebuffer); +// } +// }; +// // deliver final scene rendering commands to the display plugin +// { +// PROFILE_RANGE(render, "/pluginOutput"); +// PerformanceTimer perfTimer("pluginOutput"); +// _renderLoopCounter.increment(); +// displayPlugin->submitFrame(frame); +// } +// +// // Reset the framebuffer and stereo state +// renderArgs._blitFramebuffer.reset(); +// renderArgs._context->enableStereo(false); +// +// { +// Stats::getInstance()->setRenderDetails(renderArgs._details); +// } +// +// uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; +// _frameTimingsScriptingInterface.addValue(lastPaintDuration); +//} // WorldBox Render Data & rendering functions diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index eea54c7b8a..f256b0dfb5 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -25,6 +26,12 @@ #include #include #include +#include + +#include +#include +#include "ui/Stats.h" +#include "Application.h" GraphicsEngine::GraphicsEngine() { } @@ -44,7 +51,11 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) { _offscreenContext->doneCurrent(); _offscreenContext->setThreadContext(); - _renderEventHandler = new RenderEventHandler(glwidget->qglContext()); + _renderEventHandler = new RenderEventHandler( + glwidget->qglContext(), + [this]() { this->render_performFrame(); } + ); + if (!_offscreenContext->makeCurrent()) { qFatal("Unable to make offscreen context current"); } @@ -84,8 +95,6 @@ void GraphicsEngine::initializeRender(bool disableDeferred) { } void GraphicsEngine::startup() { - - static_cast(_renderEventHandler)->resumeThread(); } @@ -110,27 +119,12 @@ void GraphicsEngine::shutdown() { void GraphicsEngine::render_runRenderFrame(RenderArgs* renderArgs) { PROFILE_RANGE(render, __FUNCTION__); PerformanceTimer perfTimer("render"); -// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()"); - - // The pending changes collecting the changes here - render::Transaction transaction; - - // this is not in use at all anymore - //if (DependencyManager::get()->shouldRenderEntities()) { - // render models... - // PerformanceTimer perfTimer("entities"); - // PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - // "Application::runRenderFrame() ... entities..."); - - //RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE; - - //renderArgs->_debugFlags = renderDebugFlags; - //} // Make sure the WorldBox is in the scene // For the record, this one RenderItem is the first one we created and added to the scene. // We could move that code elsewhere but you know... if (!render::Item::isValidID(WorldBoxRenderData::_item)) { + render::Transaction transaction; auto worldBoxRenderData = std::make_shared(); auto worldBoxRenderPayload = std::make_shared(worldBoxRenderData); @@ -141,7 +135,6 @@ void GraphicsEngine::render_runRenderFrame(RenderArgs* renderArgs) { } { - // PerformanceTimer perfTimer("EngineRun"); _renderEngine->getRenderContext()->args = renderArgs; _renderEngine->run(); } @@ -154,7 +147,6 @@ static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SI bool GraphicsEngine::shouldPaint() const { - // Throttle if requested if ((static_cast(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { return false; @@ -167,3 +159,149 @@ bool GraphicsEngine::checkPendingRenderEvent() { bool expected = false; return (_renderEventHandler && static_cast(_renderEventHandler)->_pendingRenderEvent.compare_exchange_strong(expected, true)); } + + + +void GraphicsEngine::render_performFrame() { + // Some plugins process message events, allowing paintGL to be called reentrantly. + + _renderFrameCount++; + // SG: Moved into the RenderEventHandler + //_lastTimeRendered.start(); + + auto lastPaintBegin = usecTimestampNow(); + PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount); + PerformanceTimer perfTimer("paintGL"); + + /* if (nullptr == _displayPlugin) { + return; + }*/ + + DisplayPluginPointer displayPlugin; + { + PROFILE_RANGE(render, "/getActiveDisplayPlugin"); + displayPlugin = qApp->getActiveDisplayPlugin(); + } + + { + PROFILE_RANGE(render, "/pluginBeginFrameRender"); + // If a display plugin loses it's underlying support, it + // needs to be able to signal us to not use it + if (!displayPlugin->beginFrameRender(_renderFrameCount)) { + QMetaObject::invokeMethod(qApp, "updateDisplayMode"); + return; + } + } + + RenderArgs renderArgs; + glm::mat4 HMDSensorPose; + glm::mat4 eyeToWorld; + glm::mat4 sensorToWorld; + + bool isStereo; + glm::mat4 stereoEyeOffsets[2]; + glm::mat4 stereoEyeProjections[2]; + + { + QMutexLocker viewLocker(&_renderArgsMutex); + renderArgs = _appRenderArgs._renderArgs; + + // don't render if there is no context. + if (!_appRenderArgs._renderArgs._context) { + return; + } + + HMDSensorPose = _appRenderArgs._headPose; + eyeToWorld = _appRenderArgs._eyeToWorld; + sensorToWorld = _appRenderArgs._sensorToWorld; + isStereo = _appRenderArgs._isStereo; + for_each_eye([&](Eye eye) { + stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye]; + stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye]; + }); + } + + { + PROFILE_RANGE(render, "/gpuContextReset"); + getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose); + // Reset the gpu::Context Stages + // Back to the default framebuffer; + gpu::doInBatch("Application_render::gpuContextReset", getGPUContext(), [&](gpu::Batch& batch) { + batch.resetStages(); + }); + } + + + { + PROFILE_RANGE(render, "/renderOverlay"); + PerformanceTimer perfTimer("renderOverlay"); + // NOTE: There is no batch associated with this renderArgs + // the ApplicationOverlay class assumes it's viewport is setup to be the device size + renderArgs._viewport = glm::ivec4(0, 0, qApp->getDeviceSize() * qApp->getRenderResolutionScale()); + qApp->getApplicationOverlay().renderOverlay(&renderArgs); + } + + { + PROFILE_RANGE(render, "/updateCompositor"); + qApp->getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); + } + + gpu::FramebufferPointer finalFramebuffer; + QSize finalFramebufferSize; + { + PROFILE_RANGE(render, "/getOutputFramebuffer"); + // Primary rendering pass + auto framebufferCache = DependencyManager::get(); + finalFramebufferSize = framebufferCache->getFrameBufferSize(); + // Final framebuffer that will be handled to the display-plugin + finalFramebuffer = framebufferCache->getFramebuffer(); + } + + { + if (isStereo) { + renderArgs._context->enableStereo(true); + renderArgs._context->setStereoProjections(stereoEyeProjections); + renderArgs._context->setStereoViews(stereoEyeOffsets); + } + + renderArgs._hudOperator = displayPlugin->getHUDOperator(); + renderArgs._hudTexture = qApp->getApplicationOverlay().getOverlayTexture(); + renderArgs._blitFramebuffer = finalFramebuffer; + render_runRenderFrame(&renderArgs); + } + + auto frame = getGPUContext()->endFrame(); + frame->frameIndex = _renderFrameCount; + frame->framebuffer = finalFramebuffer; + frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) { + auto frameBufferCache = DependencyManager::get(); + if (frameBufferCache) { + frameBufferCache->releaseFramebuffer(framebuffer); + } + }; + // deliver final scene rendering commands to the display plugin + { + PROFILE_RANGE(render, "/pluginOutput"); + PerformanceTimer perfTimer("pluginOutput"); + _renderLoopCounter.increment(); + displayPlugin->submitFrame(frame); + } + + // Reset the framebuffer and stereo state + renderArgs._blitFramebuffer.reset(); + renderArgs._context->enableStereo(false); + + { + Stats::getInstance()->setRenderDetails(renderArgs._details); + } + + uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; + _frameTimingsScriptingInterface.addValue(lastPaintDuration); +} + + +void GraphicsEngine::editRenderArgs(RenderArgsEditor editor) { + QMutexLocker renderLocker(&_renderArgsMutex); + editor(_appRenderArgs); + +} \ No newline at end of file diff --git a/interface/src/graphics/GraphicsEngine.h b/interface/src/graphics/GraphicsEngine.h index 89d1eb1d94..780b4020d2 100644 --- a/interface/src/graphics/GraphicsEngine.h +++ b/interface/src/graphics/GraphicsEngine.h @@ -12,10 +12,30 @@ #include #include +#include #include #include +#include + +#include "FrameTimingsScriptingInterface.h" + + +struct AppRenderArgs { + render::Args _renderArgs; + glm::mat4 _eyeToWorld; + glm::mat4 _view; + glm::mat4 _eyeOffsets[2]; + glm::mat4 _eyeProjections[2]; + glm::mat4 _headPose; + glm::mat4 _sensorToWorld; + float _sensorToWorldScale{ 1.0f }; + bool _isStereo{ false }; +}; + +using RenderArgsEditor = std::function ; + class GraphicsEngine { public: @@ -35,12 +55,25 @@ public: bool shouldPaint() const; bool checkPendingRenderEvent(); + size_t getRenderFrameCount() const { return _renderFrameCount; } + float getRenderLoopRate() const { return _renderLoopCounter.rate(); } + + // Feed GRaphics Engine with new frame configuration + void editRenderArgs(RenderArgsEditor editor); + private: // Thread specific calls + void render_performFrame(); void render_runRenderFrame(RenderArgs* renderArgs); protected: + mutable QMutex _renderArgsMutex{ QMutex::Recursive }; + AppRenderArgs _appRenderArgs; + + RateCounter<500> _renderLoopCounter; + + uint32_t _renderFrameCount{ 0 }; render::ScenePointer _renderScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) }; render::EnginePointer _renderEngine{ new render::RenderEngine() }; @@ -51,6 +84,8 @@ protected: OffscreenGLCanvas* _offscreenContext{ nullptr }; + FrameTimingsScriptingInterface _frameTimingsScriptingInterface; + friend class Application; }; diff --git a/interface/src/graphics/RenderEventHandler.cpp b/interface/src/graphics/RenderEventHandler.cpp index 0ca82201d5..95e931ebd8 100644 --- a/interface/src/graphics/RenderEventHandler.cpp +++ b/interface/src/graphics/RenderEventHandler.cpp @@ -15,7 +15,9 @@ #include "CrashHandler.h" -RenderEventHandler::RenderEventHandler(QOpenGLContext* context) { +RenderEventHandler::RenderEventHandler(QOpenGLContext* context, RenderCall renderCall) : + _renderCall(renderCall) +{ _renderContext = new OffscreenGLCanvas(); _renderContext->setObjectName("RenderContext"); _renderContext->create(context); @@ -52,7 +54,7 @@ void RenderEventHandler::resumeThread() { void RenderEventHandler::render() { if (qApp->shouldPaint()) { _lastTimeRendered.start(); - qApp->paintGL(); + _renderCall(); } } diff --git a/interface/src/graphics/RenderEventHandler.h b/interface/src/graphics/RenderEventHandler.h index 8b0e4c5e15..913898eb7f 100644 --- a/interface/src/graphics/RenderEventHandler.h +++ b/interface/src/graphics/RenderEventHandler.h @@ -27,7 +27,11 @@ class RenderEventHandler : public QObject { using Parent = QObject; Q_OBJECT public: - RenderEventHandler(QOpenGLContext* context); + + using RenderCall = std::function ; + RenderCall _renderCall; + + RenderEventHandler(QOpenGLContext* context, RenderCall renderCall); QElapsedTimer _lastTimeRendered; std::atomic _pendingRenderEvent{ true }; diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 1ebc6aa967..0ecfa9bfd7 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -50,10 +50,10 @@ public: _default = toJsonValue(*this).toObject().toVariantMap(); _presets.unite(list.toVariantMap()); - if (C::alwaysEnabled || C::enabled) { + if (C::enabled) { _presets.insert(DEFAULT, _default); } - if (!C::alwaysEnabled) { + if (false) { //!C::alwaysEnabled) { _presets.insert(NONE, QVariantMap{{ "enabled", false }}); } @@ -96,12 +96,11 @@ public: using Persistent = PersistentConfig; JobConfig() = default; - JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} + JobConfig(bool enabled): enabled{ enabled } {} bool isEnabled() { return /*alwaysEnabled ||*/ enabled; } void setEnabled(bool enable) { enabled = /*alwaysEnabled ||*/ enable; emit dirtyEnabled(); } - bool alwaysEnabled{ false }; bool enabled{ true }; virtual void setPresetList(const QJsonObject& object); diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 60ccd26b70..c15c0ceb13 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -164,7 +164,7 @@ public: void run(const ContextPointer& jobContext) override { jobContext->jobConfig = std::static_pointer_cast(Concept::_config); - if (jobContext->jobConfig->alwaysEnabled || jobContext->jobConfig->isEnabled()) { + if (/*jobContext->jobConfig->alwaysEnabled || */jobContext->jobConfig->isEnabled()) { jobRun(_data, jobContext, _input.get(), _output.edit()); } jobContext->jobConfig.reset(); @@ -339,7 +339,7 @@ public: void run(const ContextPointer& jobContext) override { auto config = std::static_pointer_cast(Concept::_config); - if (config->alwaysEnabled || config->enabled) { + if (config->enabled) { for (auto job : TaskConcept::_jobs) { job.run(jobContext); if (jobContext->taskFlow.doAbortTask()) { From 2eec5b01fa69874c580fb49febe32dbe16d7c41f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 6 Jul 2018 10:53:09 +0200 Subject: [PATCH 006/117] debugging and fixing the problem to get Config for complex path --- interface/src/Application.cpp | 6 ++--- libraries/task/src/task/Config.h | 23 ++++++++++++++----- .../utilities/lib/jet/qml/TaskListView.qml | 15 ++++++------ .../utilities/render/engineInspector.qml | 8 +++---- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fbba8c5c87..487fafe2df 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4444,7 +4444,7 @@ void Application::idle() { PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get()->getStat("PendingProcessing").toInt()); auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration(); PROFILE_COUNTER_IF_CHANGED(render, "gpuTime", float, (float)_graphicsEngine.getGPUContext()->getFrameTimerGPUAverage()); - auto opaqueRangeTimer = renderConfig->getConfig("OpaqueRangeTimer"); +/* auto opaqueRangeTimer = renderConfig->getConfig("OpaqueRangeTimer"); auto linearDepth = renderConfig->getConfig("LinearDepth"); auto surfaceGeometry = renderConfig->getConfig("SurfaceGeometry"); auto renderDeferred = renderConfig->getConfig("RenderDeferred"); @@ -4456,7 +4456,7 @@ void Application::idle() { { "SurfaceGeometry", surfaceGeometry ? surfaceGeometry->property("gpuRunTime") : 0 }, { "RenderDeferred", renderDeferred ? renderDeferred->property("gpuRunTime") : 0 }, { "ToneAndPostRangeTimer", toneAndPostRangeTimer ? toneAndPostRangeTimer->property("gpuRunTime") : 0 } - }); + });*/ PROFILE_RANGE(app, __FUNCTION__); @@ -5759,7 +5759,7 @@ void Application::update(float deltaTime) { // TODO: Fix this by modeling the way the secondary camera works on how the main camera works // ie. Use a camera object stored in the game logic and informs the Engine on where the secondary // camera should be. - updateSecondaryCameraViewFrustum(); + // updateSecondaryCameraViewFrustum(); } quint64 now = usecTimestampNow(); diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 0ecfa9bfd7..4a9414fd42 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -219,30 +219,41 @@ public: // optional sub_parent_names and finally from there looking for the job_name (assuming every job in the path were found) // // getter for qml integration, prefer the templated getter +#pragma optimize("", off) Q_INVOKABLE QObject* getConfig(const QString& name) { return getConfig(name.toStdString()); } // getter for cpp (strictly typed), prefer this getter template typename T::Config* getConfig(std::string job = "") const { const TaskConfig* root = this; - QString path = (job.empty() ? QString() : QString(job.c_str())); // an empty string is not a null string - auto tokens = path.split('.', QString::SkipEmptyParts); + std::string jobPath = (job); + //QString path = (job.empty() ? QString() : QString(job.c_str())); // an empty string is not a null string + //auto tokens = path.split('.', QString::SkipEmptyParts); + std::list tokens; + std::size_t pos = 0, found; + while ((found = jobPath.find_first_of('.', pos)) != std::string::npos) { + tokens.push_back(jobPath.substr(pos, found - pos)); + pos = found + 1; + } + tokens.push_back(jobPath.substr(pos)); + QString jobToken; if (tokens.empty()) { // return dynamic_cast(const_cast (root)); - tokens.push_back(QString()); + //tokens.push_back(std::string()); } else { while (tokens.size() > 1) { auto name = tokens.front(); tokens.pop_front(); - root = QObject::findChild(name); + root = root->findChild((name.empty() ? QString() : QString(name.c_str()))); if (!root) { return nullptr; } } + jobToken = QString(tokens.front().c_str()); } - return root->findChild(tokens.front()); + return root->findChild(jobToken); } - +#pragma optimize("", on) Q_INVOKABLE bool isTask() const override { return true; } Q_INVOKABLE QObjectList getSubConfigs() const override { auto list = findChildren(QRegExp(".*"), Qt::FindDirectChildrenOnly); diff --git a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml index 7c077f495a..f8997dfaf4 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml @@ -27,29 +27,29 @@ Rectangle { Component.onCompleted: { //var functor = Jet.job_tree_model_functor(jobsModel) - /* var functor = Jet.job_tree_model_functor(jobsModel, 1, function(node) { + var functor = Jet.job_tree_model_functor(jobsModel, 3, function(node) { node["cpuT"] = 0.0 }) Jet.task_traverseTree(rootConfig, functor); - */ + - var tfunctor = Jet.job_tree_model_array_functor(jobsModel.engineJobItemModel, function(node) { + /* var tfunctor = Jet.job_tree_model_array_functor(jobsModel.engineJobItemModel, function(node) { node["init"] = (node.level < 3) node["fullpath"] = (node.path + "." + node.name) node["cpuT"] = 0.0 }) Jet.task_traverseTree(rootConfig, tfunctor); - +*/ // var currentParentStach = [] // currentParentStach.push(jobsModel); - Jet.job_traverseTreeNodeRoot(jobsModel.engineJobItemModel[0], function(node, depth, index) { + /* Jet.job_traverseTreeNodeRoot(jobsModel.engineJobItemModel[0], function(node, depth, index) { print(node.name + depth + " - " + index) return true - }) + })*/ } @@ -64,8 +64,7 @@ Rectangle { id: objRecursiveColumn clip: true visible: model.init - // visible: (node.level < 2) - + function switchFold() { for(var i = 1; i < children.length - 1; ++i) { children[i].visible = !children[i].visible diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml index d3bd2e96fd..7a2dfcc9e2 100644 --- a/scripts/developer/utilities/render/engineInspector.qml +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -24,13 +24,13 @@ Item { property var mainViewTask: Render.getConfig("RenderMainView") - Jet.TaskTimeFrameView { + /* Jet.TaskTimeFrameView { rootConfig: Render anchors.fill: render - } - /* Jet.TaskListView { + }*/ + Jet.TaskListView { rootConfig: Render anchors.fill: render - } */ + } } \ No newline at end of file From 07299291fca218aea3167950227362d5af2ba23d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 6 Jul 2018 19:29:06 +0200 Subject: [PATCH 007/117] clarifying the engine inspector and engine profiler --- interface/src/SecondaryCamera.cpp | 2 +- libraries/task/src/task/Config.cpp | 54 +++++++++++++++++ libraries/task/src/task/Config.h | 37 ++---------- .../utilities/lib/jet/qml/TaskListView.qml | 2 +- .../lib/jet/qml/TaskTimeFrameView.qml | 2 +- .../utilities/render/deferredLighting.qml | 19 ++++-- .../utilities/render/engineInspector.js | 2 +- .../utilities/render/engineInspector.qml | 20 +++---- .../utilities/render/engineProfiler.js | 59 +++++++++++++++++++ .../utilities/render/engineProfiler.qml | 31 ++++++++++ scripts/developer/utilities/render/luci.js | 32 ++++++++-- 11 files changed, 202 insertions(+), 58 deletions(-) create mode 100644 scripts/developer/utilities/render/engineProfiler.js create mode 100644 scripts/developer/utilities/render/engineProfiler.qml diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index a940aab4db..184762632f 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -171,7 +171,7 @@ void SecondaryCameraJobConfig::setOrientation(glm::quat orient) { } void SecondaryCameraJobConfig::enableSecondaryCameraRenderConfigs(bool enabled) { - qApp->getRenderEngine()->getConfiguration()->getConfig()->setEnabled(enabled); + qApp->getRenderEngine()->getConfiguration()->getConfig("SecondaryCameraJob")->setEnabled(enabled); setEnabled(enabled); } diff --git a/libraries/task/src/task/Config.cpp b/libraries/task/src/task/Config.cpp index b378237c9c..ac7105be29 100644 --- a/libraries/task/src/task/Config.cpp +++ b/libraries/task/src/task/Config.cpp @@ -68,3 +68,57 @@ void TaskConfig::refresh() { _task->applyConfiguration(); } +TaskConfig* TaskConfig::getRootConfig(const std::string& jobPath, std::string& jobName) const { + TaskConfig* root = const_cast (this); + + std::list tokens; + std::size_t pos = 0, sepPos; + while ((sepPos = jobPath.find_first_of('.', pos)) != std::string::npos) { + std::string token = jobPath.substr(pos, sepPos - pos); + if (!token.empty()) { + tokens.push_back(token); + } + pos = sepPos + 1; + } + { + std::string token = jobPath.substr(pos, sepPos - pos); + if (!token.empty()) { + tokens.push_back(token); + } + } + + if (tokens.empty()) { + return root; + } + else { + while (tokens.size() > 1) { + auto taskName = tokens.front(); + tokens.pop_front(); + root = root->findChild((taskName.empty() ? QString() : QString(taskName.c_str()))); + if (!root) { + return nullptr; + } + } + jobName = tokens.front(); + } + return root; +} + +JobConfig* TaskConfig::getJobConfig(const std::string& jobPath) const { + std::string jobName; + auto root = getRootConfig(jobPath, jobName); + + if (!root) { + return nullptr; + } + if (jobName.empty()) { + return root; + } else { + + auto found = root->findChild((jobName.empty() ? QString() : QString(jobName.c_str()))); + if (!found) { + return nullptr; + } + return found; + } +} diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index 4a9414fd42..b76c57521f 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -219,41 +219,16 @@ public: // optional sub_parent_names and finally from there looking for the job_name (assuming every job in the path were found) // // getter for qml integration, prefer the templated getter -#pragma optimize("", off) Q_INVOKABLE QObject* getConfig(const QString& name) { return getConfig(name.toStdString()); } + // getter for cpp (strictly typed), prefer this getter - template typename T::Config* getConfig(std::string job = "") const { - const TaskConfig* root = this; - std::string jobPath = (job); - //QString path = (job.empty() ? QString() : QString(job.c_str())); // an empty string is not a null string - //auto tokens = path.split('.', QString::SkipEmptyParts); - std::list tokens; - std::size_t pos = 0, found; - while ((found = jobPath.find_first_of('.', pos)) != std::string::npos) { - tokens.push_back(jobPath.substr(pos, found - pos)); - pos = found + 1; - } - tokens.push_back(jobPath.substr(pos)); + TaskConfig* getRootConfig(const std::string& jobPath, std::string& jobName) const; + JobConfig* getJobConfig(const std::string& jobPath) const; - QString jobToken; - if (tokens.empty()) { - // return dynamic_cast(const_cast (root)); - //tokens.push_back(std::string()); - } else { - while (tokens.size() > 1) { - auto name = tokens.front(); - tokens.pop_front(); - root = root->findChild((name.empty() ? QString() : QString(name.c_str()))); - if (!root) { - return nullptr; - } - } - jobToken = QString(tokens.front().c_str()); - } - - return root->findChild(jobToken); + template typename T::Config* getConfig(std::string jobPath = "") const { + return dynamic_cast(getJobConfig(jobPath)); } -#pragma optimize("", on) + Q_INVOKABLE bool isTask() const override { return true; } Q_INVOKABLE QObjectList getSubConfigs() const override { auto list = findChildren(QRegExp(".*"), Qt::FindDirectChildrenOnly); diff --git a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml index f8997dfaf4..1229ef7dc7 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml @@ -19,7 +19,7 @@ import "../jet.js" as Jet Rectangle { HifiConstants { id: hifi;} - color: hifi.colors.baseGray; + // color: hifi.colors.baseGray; id: root; property var rootConfig : Workload diff --git a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml index 4eca5075d0..267344fca5 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml @@ -19,7 +19,7 @@ import "../jet.js" as Jet Rectangle { HifiConstants { id: hifi;} - color: hifi.colors.baseGray; + // color: hifi.colors.baseGray; id: root; property var rootConfig : Workload diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 8a4a8f0622..abb15d5a38 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -277,11 +277,20 @@ Rectangle { } } Separator {} - HifiControls.Button { - text: "Engine" - // activeFocusOnPress: false - onClicked: { - sendToScript({method: "openEngineView"}); + Row { + HifiControls.Button { + text: "Inspector" + // activeFocusOnPress: false + onClicked: { + sendToScript({method: "openEngineInspector"}); + } + } + HifiControls.Button { + text: "EnProfilergine" + // activeFocusOnPress: false + onClicked: { + sendToScript({method: "openEngineProfiler"}); + } } } } diff --git a/scripts/developer/utilities/render/engineInspector.js b/scripts/developer/utilities/render/engineInspector.js index e6be7f1c3c..868a421c8d 100644 --- a/scripts/developer/utilities/render/engineInspector.js +++ b/scripts/developer/utilities/render/engineInspector.js @@ -47,7 +47,7 @@ function createWindow() { var qml = Script.resolvePath(QMLAPP_URL); window = new OverlayWindow({ - title: 'Render Engine', + title: 'Render Engine Inspector', source: qml, width: 500, height: 100 diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml index 7a2dfcc9e2..52a9879038 100644 --- a/scripts/developer/utilities/render/engineInspector.qml +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -1,7 +1,7 @@ // -// deferredLighting.qml +// EngineInspector.qml // -// Created by Sam Gateau on 6/6/2016 +// Created by Sam Gateau on 06/07/2018 // Copyright 2016 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -18,19 +18,13 @@ import "../lib/jet/qml" as Jet Item { HifiConstants { id: hifi;} - id: render; + id: root; anchors.fill: parent - property var mainViewTask: Render.getConfig("RenderMainView") + property var rootConfig: Render.getConfig("RenderMainView") - - /* Jet.TaskTimeFrameView { - rootConfig: Render - anchors.fill: render - }*/ Jet.TaskListView { - rootConfig: Render - anchors.fill: render - } - + rootConfig: root.rootConfig + anchors.fill: root + } } \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineProfiler.js b/scripts/developer/utilities/render/engineProfiler.js new file mode 100644 index 0000000000..b9443da1e9 --- /dev/null +++ b/scripts/developer/utilities/render/engineProfiler.js @@ -0,0 +1,59 @@ + + + (function() { + var TABLET_BUTTON_NAME = "Render Engine Profiler"; + var QMLAPP_URL = Script.resolvePath("./engineProfiler.qml"); + var ICON_URL = Script.resolvePath("../../../system/assets/images/lod-i.svg"); + var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/lod-a.svg"); + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: TABLET_BUTTON_NAME, + icon: ICON_URL, + activeIcon: ACTIVE_ICON_URL + }); + + Script.scriptEnding.connect(function () { + killWindow() + button.clicked.disconnect(onClicked); + tablet.removeButton(button); + }); + + button.clicked.connect(onClicked); + + var onScreen = false; + var window; + + function onClicked() { + if (onScreen) { + killWindow() + } else { + createWindow() + } + } + + function createWindow() { + var qml = Script.resolvePath(QMLAPP_URL); + window = new OverlayWindow({ + title: 'Render Engine Profiler', + source: qml, + width: 500, + height: 100 + }); + window.setPosition(200, 50); + window.closed.connect(killWindow); + onScreen = true + button.editProperties({isActive: true}); + } + + function killWindow() { + if (window !== undefined) { + window.closed.disconnect(killWindow); + window.close() + window = undefined + } + onScreen = false + button.editProperties({isActive: false}) + } + }()); + \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineProfiler.qml b/scripts/developer/utilities/render/engineProfiler.qml new file mode 100644 index 0000000000..bfa049d089 --- /dev/null +++ b/scripts/developer/utilities/render/engineProfiler.qml @@ -0,0 +1,31 @@ +// +// EngineProfiler.qml +// +// Created by Sam Gateau on 06/07/2018 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls + +import "../lib/jet/qml" as Jet + +Item { + HifiConstants { id: hifi;} + id: root; + anchors.fill: parent + + property var rootConfig: Render.getConfig("") + + + Jet.TaskTimeFrameView { + rootConfig: root.rootConfig + anchors.fill: root + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/render/luci.js b/scripts/developer/utilities/render/luci.js index 005d96780a..9f0f32ee41 100644 --- a/scripts/developer/utilities/render/luci.js +++ b/scripts/developer/utilities/render/luci.js @@ -90,19 +90,22 @@ function fromQml(message) { switch (message.method) { - case "openEngineView": - openEngineTaskView(); + case "openEngineInspector": + openEngineInspector(); + break; + case "openEngineProfiler": + openEngineProfiler(); break; } } var engineInspectorView = null - function openEngineTaskView() { + function openEngineInspector() { if (engineInspectorView == null) { var qml = Script.resolvePath('engineInspector.qml'); var window = new OverlayWindow({ - title: 'Render Engine', + title: 'Render Engine Inspector', source: qml, width: 300, height: 400 @@ -115,7 +118,23 @@ } } - + var engineProfilerView = null + function openEngineProfiler() { + if (engineProfilerView == null) { + var qml = Script.resolvePath('engineProfiler.qml'); + var window = new OverlayWindow({ + title: 'Render Engine Profiler', + source: qml, + width: 300, + height: 400 + }); + window.setPosition(200, 50); + engineProfilerView = window + window.closed.connect(function() { engineProfilerView = null; }); + } else { + engineProfilerView.setPosition(200, 50); + } + } Script.scriptEnding.connect(function () { if (onLuciScreen) { @@ -128,5 +147,8 @@ if (engineInspectorView !== null) { engineInspectorView.close() } + if (engineProfilerView !== null) { + engineProfilerView.close() + } }); }()); \ No newline at end of file From 66199e9aab72362238647ad57fa089d5d8c4064d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 11 Jul 2018 11:57:18 +0200 Subject: [PATCH 008/117] Cleaning up the isENabled interface andthe qml --- libraries/render-utils/src/BloomEffect.cpp | 3 ++- .../render-utils/src/RenderShadowTask.cpp | 2 +- libraries/render/src/render/DrawSceneOctree.h | 2 -- libraries/render/src/render/DrawStatus.cpp | 2 +- libraries/task/src/task/Config.cpp | 14 ++++++++++++ libraries/task/src/task/Config.h | 22 +++++++++++-------- libraries/task/src/task/Task.h | 2 +- .../utilities/lib/jet/qml/TaskListView.qml | 10 ++++----- .../lib/jet/qml/TaskTimeFrameView.qml | 5 +++-- .../utilities/render/engineInspector.js | 10 ++++----- .../utilities/render/engineInspector.qml | 2 +- .../utilities/render/engineProfiler.js | 6 ++--- 12 files changed, 49 insertions(+), 31 deletions(-) diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index ee06e17578..b198442b15 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -333,7 +333,8 @@ void Bloom::configure(const Config& config) { for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { blurName.back() = '0' + i; auto blurConfig = config.getConfig(blurName); - blurConfig->setProperty("filterScale", 1.0f); + blurConfig->filterScale = 1.0f; + //blurConfig->setProperty("filterScale", 1.0f); } } diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 91eb777199..d9ae0caade 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -282,7 +282,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende } void RenderShadowTask::configure(const Config& configuration) { - DependencyManager::get()->setShadowMapEnabled(configuration.enabled); + DependencyManager::get()->setShadowMapEnabled(configuration.isEnabled()); // This is a task, so must still propogate configure() to its Jobs // Task::configure(configuration); } diff --git a/libraries/render/src/render/DrawSceneOctree.h b/libraries/render/src/render/DrawSceneOctree.h index 9c416262ca..97cf45ebcf 100644 --- a/libraries/render/src/render/DrawSceneOctree.h +++ b/libraries/render/src/render/DrawSceneOctree.h @@ -20,7 +20,6 @@ namespace render { class DrawSceneOctreeConfig : public Job::Config { Q_OBJECT - Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty()) Q_PROPERTY(bool showVisibleCells READ getShowVisibleCells WRITE setShowVisibleCells NOTIFY dirty()) Q_PROPERTY(bool showEmptyCells READ getShowEmptyCells WRITE setShowEmptyCells NOTIFY dirty()) Q_PROPERTY(int numAllocatedCells READ getNumAllocatedCells) @@ -82,7 +81,6 @@ namespace render { class DrawItemSelectionConfig : public Job::Config { Q_OBJECT - Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty()) Q_PROPERTY(bool showInsideItems READ getShowInsideItems WRITE setShowInsideItems NOTIFY dirty()) Q_PROPERTY(bool showInsideSubcellItems READ getShowInsideSubcellItems WRITE setShowInsideSubcellItems NOTIFY dirty()) Q_PROPERTY(bool showPartialItems READ getShowPartialItems WRITE setShowPartialItems NOTIFY dirty()) diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 496b2000a9..b1e7620b19 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -29,7 +29,7 @@ using namespace render; void DrawStatusConfig::dirtyHelper() { - enabled = showNetwork || showDisplay; + _isEnabled = showNetwork || showDisplay; emit dirty(); } diff --git a/libraries/task/src/task/Config.cpp b/libraries/task/src/task/Config.cpp index ac7105be29..c0e9c41468 100644 --- a/libraries/task/src/task/Config.cpp +++ b/libraries/task/src/task/Config.cpp @@ -18,6 +18,17 @@ using namespace task; +JobConfig::~JobConfig() { + +} + +void JobConfig::setEnabled(bool enable) { + if (_isEnabled != enable) { + _isEnabled = enable; + emit dirtyEnabled(); + } +} + void JobConfig::setPresetList(const QJsonObject& object) { for (auto it = object.begin(); it != object.end(); it++) { JobConfig* child = findChild(it.key(), Qt::FindDirectChildrenOnly); @@ -30,6 +41,7 @@ void JobConfig::setPresetList(const QJsonObject& object) { void TaskConfig::connectChildConfig(QConfigPointer childConfig, const std::string& name) { childConfig->setParent(this); childConfig->setObjectName(name.c_str()); + // childConfig->propagateParentEnabled((_isParentEnabled ? _isEnabled : false)); // Connect loaded->refresh QObject::connect(childConfig.get(), SIGNAL(loaded()), this, SLOT(refresh())); @@ -57,6 +69,8 @@ void TaskConfig::transferChildrenConfigs(QConfigPointer source) { QObject::connect(child, SIGNAL(dirtyEnabled()), this, SLOT(refresh())); } } + + // propagateParentEnabledToSubs(); } void TaskConfig::refresh() { diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index b76c57521f..ab3303110b 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -50,12 +50,10 @@ public: _default = toJsonValue(*this).toObject().toVariantMap(); _presets.unite(list.toVariantMap()); - if (C::enabled) { + if (C::isEnabled()) { _presets.insert(DEFAULT, _default); } - if (false) { //!C::alwaysEnabled) { - _presets.insert(NONE, QVariantMap{{ "enabled", false }}); - } + _presets.insert(NONE, QVariantMap{{ "enabled", false }}); auto preset = _preset.get(); if (preset != _preset.getDefault() && _presets.contains(preset)) { @@ -92,16 +90,21 @@ class JobConfig : public QObject { Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY dirtyEnabled()) double _msCPURunTime{ 0.0 }; + +protected: + friend class TaskConfig; + + bool _isEnabled{ true }; + public: using Persistent = PersistentConfig; JobConfig() = default; - JobConfig(bool enabled): enabled{ enabled } {} + JobConfig(bool enabled): _isEnabled{ enabled } {} + ~JobConfig(); - bool isEnabled() { return /*alwaysEnabled ||*/ enabled; } - void setEnabled(bool enable) { enabled = /*alwaysEnabled ||*/ enable; emit dirtyEnabled(); } - - bool enabled{ true }; + bool isEnabled() const { return _isEnabled; } + void setEnabled(bool enable); virtual void setPresetList(const QJsonObject& object); @@ -199,6 +202,7 @@ public: */ class TaskConfig : public JobConfig { Q_OBJECT + public: using Persistent = PersistentConfig; diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index c15c0ceb13..8d2fd867c4 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -339,7 +339,7 @@ public: void run(const ContextPointer& jobContext) override { auto config = std::static_pointer_cast(Concept::_config); - if (config->enabled) { + if (config->isEnabled()) { for (auto job : TaskConcept::_jobs) { job.run(jobContext); if (jobContext->taskFlow.doAbortTask()) { diff --git a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml index 1229ef7dc7..02225aba62 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml @@ -19,7 +19,7 @@ import "../jet.js" as Jet Rectangle { HifiConstants { id: hifi;} - // color: hifi.colors.baseGray; + color: Qt.rgba(hifi.colors.baseGray.r, hifi.colors.baseGray.g, hifi.colors.baseGray.b, 0.8); id: root; property var rootConfig : Workload @@ -82,8 +82,8 @@ Rectangle { id: objCheck property var config: root.rootConfig.getConfig(model.path + "." + model.name); text: " " - checked: config.enabled - onCheckedChanged: { config.enabled = checked } + checked: root.rootConfig.getConfig(model.path + "." + model.name).enabled + onCheckedChanged: { root.rootConfig.getConfig(model.path + "." + model.name).enabled = checked } } MouseArea { @@ -95,12 +95,12 @@ Rectangle { HifiControls.Label { id: objLabel - colorScheme: hifi.colorSchemes.dark // property var config: root.rootConfig.getConfig(model.path + "." + model.name); + colorScheme: (root.rootConfig.getConfig(model.path + "." + model.name) ? hifi.colorSchemes.dark : hifi.colorSchemes.light) text: (objRecursiveColumn.children.length > 2 ? objRecursiveColumn.children[1].visible ? qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name - + " ms=" + root.rootConfig.getConfig(model.path + "." + model.name).cpuRunTime.toFixed(3) + // + " ms=" + config.cpuRunTime.toFixed(3) + " id=" + model.id } } diff --git a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml index 267344fca5..e1d9bd7ce1 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml @@ -19,7 +19,7 @@ import "../jet.js" as Jet Rectangle { HifiConstants { id: hifi;} - // color: hifi.colors.baseGray; + color: Qt.rgba(hifi.colors.baseGray.r, hifi.colors.baseGray.g, hifi.colors.baseGray.b, 0.8); id: root; property var rootConfig : Workload @@ -59,7 +59,8 @@ Rectangle { function pullFreshValues() { for (var j = 0; j Date: Fri, 13 Jul 2018 13:12:06 +0200 Subject: [PATCH 009/117] typo --- libraries/gpu/src/gpu/Buffer.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/libraries/gpu/src/gpu/Buffer.cpp b/libraries/gpu/src/gpu/Buffer.cpp index d085b4df76..b3716c3490 100644 --- a/libraries/gpu/src/gpu/Buffer.cpp +++ b/libraries/gpu/src/gpu/Buffer.cpp @@ -163,13 +163,6 @@ Buffer::Size Buffer::getSize() const { const Element BufferView::DEFAULT_ELEMENT = Element( gpu::SCALAR, gpu::UINT8, gpu::RAW ); - -BufferPointer _buffer; -Size _offset{ 0 }; -Size _size{ 0 }; -Element _element{ DEFAULT_ELEMENT }; -uint16 _stride{ 0 }; - BufferView::BufferView(const BufferView& view) : _buffer(view._buffer), _offset(view._offset), From c24083c1f0c981458552c84ff3fe04d3de0c9720 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 25 Jul 2018 10:50:15 +0200 Subject: [PATCH 010/117] drafting along the RenderTHread class --- interface/src/Application.cpp | 67 ++++++----- interface/src/Application.h | 2 +- interface/src/graphics/GraphicsEngine.cpp | 38 +++++- interface/src/graphics/GraphicsEngine.h | 6 + interface/src/graphics/RenderEventHandler.cpp | 5 +- interface/src/graphics/RenderEventHandler.h | 5 +- interface/src/graphics/RenderThread.cpp | 1 + interface/src/graphics/RenderThread.h | 108 ++++++++++++++++++ 8 files changed, 187 insertions(+), 45 deletions(-) create mode 100644 interface/src/graphics/RenderThread.cpp create mode 100644 interface/src/graphics/RenderThread.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0ad27e0dd3..24dcf4ce72 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2425,6 +2425,7 @@ void Application::cleanupBeforeQuit() { } _window->saveGeometry(); + // _gpuContext->shutdown(); // Destroy third party processes after scripts have finished using them. @@ -4178,41 +4179,37 @@ bool Application::acceptSnapshot(const QString& urlString) { } return true; } - -static uint32_t _renderedFrameIndex { INVALID_FRAME }; - -bool Application::shouldPaint() const { - if (_aboutToQuit || _window->isMinimized()) { - return false; - } - - - auto displayPlugin = getActiveDisplayPlugin(); - -#ifdef DEBUG_PAINT_DELAY - static uint64_t paintDelaySamples{ 0 }; - static uint64_t paintDelayUsecs{ 0 }; - - paintDelayUsecs += displayPlugin->getPaintDelayUsecs(); - - static const int PAINT_DELAY_THROTTLE = 1000; - if (++paintDelaySamples % PAINT_DELAY_THROTTLE == 0) { - qCDebug(interfaceapp).nospace() << - "Paint delay (" << paintDelaySamples << " samples): " << - (float)paintDelaySamples / paintDelayUsecs << "us"; - } -#endif - - // Throttle if requested - //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { - if (displayPlugin->isThrottled() && !_graphicsEngine.shouldPaint()) { - return false; - } - - // Sync up the _renderedFrameIndex - _renderedFrameIndex = displayPlugin->presentCount(); - return true; -} +// +//bool Application::shouldPaint() const { +// if (_aboutToQuit || _window->isMinimized()) { +// return false; +// } +// +// +// auto displayPlugin = getActiveDisplayPlugin(); +// +//#ifdef DEBUG_PAINT_DELAY +// static uint64_t paintDelaySamples{ 0 }; +// static uint64_t paintDelayUsecs{ 0 }; +// +// paintDelayUsecs += displayPlugin->getPaintDelayUsecs(); +// +// static const int PAINT_DELAY_THROTTLE = 1000; +// if (++paintDelaySamples % PAINT_DELAY_THROTTLE == 0) { +// qCDebug(interfaceapp).nospace() << +// "Paint delay (" << paintDelaySamples << " samples): " << +// (float)paintDelaySamples / paintDelayUsecs << "us"; +// } +//#endif +// +// // Throttle if requested +// //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { +// if (displayPlugin->isThrottled() && !_graphicsEngine.shouldPaint()) { +// return false; +// } +// +// return true; +//} #ifdef Q_OS_WIN #include diff --git a/interface/src/Application.h b/interface/src/Application.h index fb8edf3b86..6d57ca9d8d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -157,7 +157,7 @@ public: void updateSecondaryCameraViewFrustum(); void updateCamera(RenderArgs& renderArgs, float deltaTime); - bool shouldPaint() const; + // bool shouldPaint() const; // void paintGL(); void resizeGL(); diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index 21c9a9b22d..d115d8914c 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -53,6 +53,7 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) { _renderEventHandler = new RenderEventHandler( glwidget->qglContext(), + [this]() { return this->shouldPaint(); }, [this]() { this->render_performFrame(); } ); @@ -147,12 +148,37 @@ static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SI bool GraphicsEngine::shouldPaint() const { - // Throttle if requested - if ((static_cast(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { - return false; - } - - return true; + +// if (_aboutToQuit || _window->isMinimized()) { +// return false; + // } + + + auto displayPlugin = qApp->getActiveDisplayPlugin(); + +#ifdef DEBUG_PAINT_DELAY + static uint64_t paintDelaySamples{ 0 }; + static uint64_t paintDelayUsecs{ 0 }; + + paintDelayUsecs += displayPlugin->getPaintDelayUsecs(); + + static const int PAINT_DELAY_THROTTLE = 1000; + if (++paintDelaySamples % PAINT_DELAY_THROTTLE == 0) { + qCDebug(interfaceapp).nospace() << + "Paint delay (" << paintDelaySamples << " samples): " << + (float)paintDelaySamples / paintDelayUsecs << "us"; + } +#endif + + // Throttle if requested + //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { + if ( displayPlugin->isThrottled() && + (static_cast(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { + return false; + } + + return true; + // } } bool GraphicsEngine::checkPendingRenderEvent() { diff --git a/interface/src/graphics/GraphicsEngine.h b/interface/src/graphics/GraphicsEngine.h index 780b4020d2..bc2121429a 100644 --- a/interface/src/graphics/GraphicsEngine.h +++ b/interface/src/graphics/GraphicsEngine.h @@ -16,6 +16,8 @@ #include +#include "RenderThread.h" + #include #include @@ -51,6 +53,8 @@ public: render::EnginePointer getRenderEngine() const { return _renderEngine; } gpu::ContextPointer getGPUContext() const { return _gpuContext; } + FrameQueuePointer getFrameQueue() const { return _frameQueue; } + // Same as the one in application bool shouldPaint() const; bool checkPendingRenderEvent(); @@ -79,6 +83,8 @@ protected: gpu::ContextPointer _gpuContext; // initialized during window creation + FrameQueuePointer _frameQueue{ new FrameQueue() }; + QObject* _renderEventHandler{ nullptr }; friend class RenderEventHandler; diff --git a/interface/src/graphics/RenderEventHandler.cpp b/interface/src/graphics/RenderEventHandler.cpp index 95e931ebd8..5b587ab171 100644 --- a/interface/src/graphics/RenderEventHandler.cpp +++ b/interface/src/graphics/RenderEventHandler.cpp @@ -15,7 +15,8 @@ #include "CrashHandler.h" -RenderEventHandler::RenderEventHandler(QOpenGLContext* context, RenderCall renderCall) : +RenderEventHandler::RenderEventHandler(QOpenGLContext* context, CheckCall checkCall, RenderCall renderCall) : + _checkCall(checkCall), _renderCall(renderCall) { _renderContext = new OffscreenGLCanvas(); @@ -52,7 +53,7 @@ void RenderEventHandler::resumeThread() { } void RenderEventHandler::render() { - if (qApp->shouldPaint()) { + if (_checkCall()) { _lastTimeRendered.start(); _renderCall(); } diff --git a/interface/src/graphics/RenderEventHandler.h b/interface/src/graphics/RenderEventHandler.h index 913898eb7f..43b16a76bd 100644 --- a/interface/src/graphics/RenderEventHandler.h +++ b/interface/src/graphics/RenderEventHandler.h @@ -28,10 +28,13 @@ class RenderEventHandler : public QObject { Q_OBJECT public: + using CheckCall = std::function ; using RenderCall = std::function ; + + CheckCall _checkCall; RenderCall _renderCall; - RenderEventHandler(QOpenGLContext* context, RenderCall renderCall); + RenderEventHandler(QOpenGLContext* context, CheckCall checkCall, RenderCall renderCall); QElapsedTimer _lastTimeRendered; std::atomic _pendingRenderEvent{ true }; diff --git a/interface/src/graphics/RenderThread.cpp b/interface/src/graphics/RenderThread.cpp new file mode 100644 index 0000000000..63df2033e8 --- /dev/null +++ b/interface/src/graphics/RenderThread.cpp @@ -0,0 +1 @@ +#include "RenderThread.h" \ No newline at end of file diff --git a/interface/src/graphics/RenderThread.h b/interface/src/graphics/RenderThread.h new file mode 100644 index 0000000000..abddf746e6 --- /dev/null +++ b/interface/src/graphics/RenderThread.h @@ -0,0 +1,108 @@ +#ifndef PRODUCERCONSUMERPIPE_H +#define PRODUCERCONSUMERPIPE_H + +#include +#include +#include +#include +#include + +// Producer is blocked if the consumer doesn't consume enough +// Consumer reads same value if producer doesn't produce enough +template +class ProducerConsumerPipe { +public: + + ProducerConsumerPipe(); + ProducerConsumerPipe(const T& initValue); + + const T& read(); + void read(T& value, const T& resetValue); + void write(const T& value); + bool isWritePossible(); + +private: + + short _readIndex; + short _writeIndex; + std::array _values; + std::array _used; + + void initialize(); + void updateReadIndex(); +}; + +template +ProducerConsumerPipe::ProducerConsumerPipe() { + initialize(); +} + +template +ProducerConsumerPipe::ProducerConsumerPipe(const T& initValue) { + _values.fill(initValue); + initialize(); +} + +template +void ProducerConsumerPipe::initialize() { + _readIndex = 0; + _writeIndex = 2; + _used[_readIndex].test_and_set(std::memory_order_acquire); + _used[_writeIndex].test_and_set(std::memory_order_acquire); + _used[1].clear(); +} + +template +void ProducerConsumerPipe::updateReadIndex() { + int nextReadIndex = (_readIndex + 1) % _values.size(); + + if (!_used[nextReadIndex].test_and_set(std::memory_order_acquire)) { + int readIndex = _readIndex; + _used[readIndex].clear(std::memory_order_release); + _readIndex = nextReadIndex; + } +} + +template +const T& ProducerConsumerPipe::read() { + updateReadIndex(); + return _values[_readIndex]; +} + +template +void ProducerConsumerPipe::read(T& value, const T& resetValue) { + updateReadIndex(); + value = _values[_readIndex]; + _values[_readIndex] = resetValue; +} + +template +bool ProducerConsumerPipe::isWritePossible() { + int nextWriteIndex = (_writeIndex + 1) % _values.size(); + return (_used[nextWriteIndex].test_and_set(std::memory_order_acquire)); +} + +template +void ProducerConsumerPipe::write(const T& value) { + int nextWriteIndex = (_writeIndex + 1) % _values.size(); + int writeIndex = _writeIndex; + + _values[writeIndex] = value; + + while (_used[nextWriteIndex].test_and_set(std::memory_order_acquire)) { + // spin + std::this_thread::yield(); + } + _used[writeIndex].clear(std::memory_order_release); + _writeIndex = nextWriteIndex; +} + + +#include + +using FrameQueue = ProducerConsumerPipe; + +using FrameQueuePointer = std::shared_ptr; + + +#endif From c0bbe1599b2cd5fc1eda5af267dc4414e277089d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 30 Jul 2018 11:28:56 +0200 Subject: [PATCH 011/117] Trying to sync the thotling for all render threads --- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 6 +++--- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 11 ++++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index d8b8cbd54a..7e95727fcc 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -165,11 +165,11 @@ static const uint32_t MIN_THROTTLE_CHECK_FRAMES = 60; bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { static auto lastCheck = presentCount(); // Don't access the menu API every single frame - if ((presentCount() - lastCheck) > MIN_THROTTLE_CHECK_FRAMES) { + // if ((presentCount() - lastCheck) > MIN_THROTTLE_CHECK_FRAMES) { static const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus"; // FIXME - this value duplicated in Menu.h _isThrottled = (!_container->isForeground() && _container->isOptionChecked(ThrottleFPSIfNotFocus)); - lastCheck = presentCount(); - } + // lastCheck = presentCount(); + // } return _isThrottled; } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 9200843cf8..b18f9f988b 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -198,7 +198,16 @@ public: // If there's no active plugin, just sleep if (currentPlugin == nullptr) { // Minimum sleep ends up being about 2 ms anyway - QThread::msleep(1); + QThread::msleep(16); + continue; + } + + static uint _vsyncLoopIndex = 0; + _vsyncLoopIndex++; + + if (currentPlugin->isThrottled() && (_vsyncLoopIndex % 8)) { + // Minimum sleep ends up being about 2 ms anyway + QThread::msleep(16); continue; } From 0eead13fb95d78ff8ee856a64db6523c8c82535d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 25 Oct 2018 15:03:47 +1300 Subject: [PATCH 012/117] Make Create not grab tablet if editing an entity with hand --- .../nearParentGrabOverlay.js | 35 ++++++++++++++++--- .../libraries/controllerDispatcherUtils.js | 4 +++ .../system/libraries/entitySelectionTool.js | 13 ++++++- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js index 763a0a0a27..69aaad4247 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js @@ -9,7 +9,7 @@ /* global Script, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, getControllerJointIndex, enableDispatcherModule, disableDispatcherModule, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, makeDispatcherModuleParameters, Overlays, makeRunningValues, Vec3, resizeTablet, getTabletWidthFromSettings, - NEAR_GRAB_RADIUS, HMD, Uuid + NEAR_GRAB_RADIUS, HMD, Uuid, HIFI_EDIT_MANIPULATION_CHANNEL */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -172,10 +172,14 @@ Script.include("/~/system/libraries/utils.js"); return null; }; + this.isEditing = false; + this.setIsEditing = function (editing) { + this.isEditing = editing; + }; this.isReady = function (controllerData) { - if ((controllerData.triggerClicks[this.hand] === 0 && - controllerData.secondaryValues[this.hand] === 0)) { + if ((controllerData.triggerClicks[this.hand] === 0 && controllerData.secondaryValues[this.hand] === 0) + || this.isEditing) { this.robbed = false; return makeRunningValues(false, [], []); } @@ -198,7 +202,8 @@ Script.include("/~/system/libraries/utils.js"); }; this.run = function (controllerData) { - if (controllerData.triggerClicks[this.hand] === 0 && controllerData.secondaryValues[this.hand] === 0) { + if ((controllerData.triggerClicks[this.hand] === 0 && controllerData.secondaryValues[this.hand] === 0) + || this.isEditing) { this.endNearParentingGrabOverlay(); this.robbed = false; return makeRunningValues(false, [], []); @@ -226,6 +231,28 @@ Script.include("/~/system/libraries/utils.js"); enableDispatcherModule("LeftNearParentingGrabOverlay", leftNearParentingGrabOverlay); enableDispatcherModule("RightNearParentingGrabOverlay", rightNearParentingGrabOverlay); + function onMessageReceived(channel, data, senderID) { + var message; + + if (channel !== HIFI_EDIT_MANIPULATION_CHANNEL || senderID !== MyAvatar.sessionUUID) { + return; + } + + try { + message = JSON.parse(data); + } catch (e) { + return; + } + + if (message.hand === Controller.Standard.LeftHand) { + leftNearParentingGrabOverlay.setIsEditing(message.action === "startEdit"); + } else if (message.hand === Controller.Standard.RightHand) { + rightNearParentingGrabOverlay.setIsEditing(message.action === "startEdit"); + } + } + Messages.subscribe(HIFI_EDIT_MANIPULATION_CHANNEL); + Messages.messageReceived.connect(onMessageReceived); + function cleanup() { leftNearParentingGrabOverlay.cleanup(); rightNearParentingGrabOverlay.cleanup(); diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index e9d5255d28..f7b997a897 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -24,6 +24,7 @@ HAPTIC_PULSE_DURATION:true, DISPATCHER_HOVERING_LIST:true, DISPATCHER_HOVERING_STYLE:true, + HIFI_EDIT_MANIPULATION_CHANNEL:true, Entities, makeDispatcherModuleParameters:true, makeRunningValues:true, @@ -149,6 +150,8 @@ DISPATCHER_PROPERTIES = [ "userData" ]; +HIFI_EDIT_MANIPULATION_CHANNEL = "HiFi-Edit-Manipulation"; + // priority -- a lower priority means the module will be asked sooner than one with a higher priority in a given update step // activitySlots -- indicates which "slots" must not yet be in use for this module to start // requiredDataForReady -- which "situation" parts this module looks at to decide if it will start @@ -590,6 +593,7 @@ if (typeof module !== 'undefined') { TRIGGER_OFF_VALUE: TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE: TRIGGER_ON_VALUE, DISPATCHER_HOVERING_LIST: DISPATCHER_HOVERING_LIST, + HIFI_EDIT_MANIPULATION_CHANNEL: HIFI_EDIT_MANIPULATION_CHANNEL, worldPositionToRegistrationFrameMatrix: worldPositionToRegistrationFrameMatrix }; } diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 3bb36d632e..8f972e14c2 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -14,7 +14,7 @@ // /* global SelectionManager, SelectionDisplay, grid, rayPlaneIntersection, rayPlaneIntersection2, pushCommandForSelections, - getMainTabletIDs, getControllerWorldLocation, TRIGGER_ON_VALUE */ + getMainTabletIDs, getControllerWorldLocation, TRIGGER_ON_VALUE, HIFI_EDIT_MANIPULATION_CHANNEL */ const SPACE_LOCAL = "local"; const SPACE_WORLD = "world"; @@ -983,6 +983,7 @@ SelectionDisplay = (function() { that.triggerPressMapping = Controller.newMapping(Script.resolvePath('') + '-press'); that.triggeredHand = NO_HAND; that.pressedHand = NO_HAND; + that.editingHand = NO_HAND; that.triggered = function() { return that.triggeredHand !== NO_HAND; }; @@ -1115,6 +1116,11 @@ SelectionDisplay = (function() { activeTool = hitTool; that.clearDebugPickPlane(); if (activeTool.onBegin) { + Messages.sendLocalMessage(HIFI_EDIT_MANIPULATION_CHANNEL, JSON.stringify({ + action: "startEdit", + hand: that.triggeredHand + })); + that.editingHand = that.triggeredHand; activeTool.onBegin(event, pickRay, results); } else { print("ERROR: entitySelectionTool.mousePressEvent - ActiveTool(" + activeTool.mode + ") missing onBegin"); @@ -1263,6 +1269,11 @@ SelectionDisplay = (function() { if (wantDebug) { print(" Triggering ActiveTool(" + activeTool.mode + ")'s onEnd"); } + Messages.sendLocalMessage(HIFI_EDIT_MANIPULATION_CHANNEL, JSON.stringify({ + action: "finishEdit", + hand: that.editingHand + })); + that.editingHand = NO_HAND; activeTool.onEnd(event); } else if (wantDebug) { print(" ActiveTool(" + activeTool.mode + ")'s missing onEnd"); From 1460e43f6e1348850a965f93f926af67f43a397d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 25 Oct 2018 15:04:59 +1300 Subject: [PATCH 013/117] Make tablet highlight not display if editing an entity with hand --- .../controllerModules/nearTabletHighlight.js | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/controllerModules/nearTabletHighlight.js b/scripts/system/controllers/controllerModules/nearTabletHighlight.js index c24464ab38..3ced0a9e87 100644 --- a/scripts/system/controllers/controllerModules/nearTabletHighlight.js +++ b/scripts/system/controllers/controllerModules/nearTabletHighlight.js @@ -11,7 +11,7 @@ // /* global LEFT_HAND, RIGHT_HAND, makeDispatcherModuleParameters, makeRunningValues, enableDispatcherModule, - * disableDispatcherModule */ + * disableDispatcherModule, HIFI_EDIT_MANIPULATION_CHANNEL */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -66,12 +66,17 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); 100 ); + this.isEditing = false; + this.setIsEditing = function (editing) { + this.isEditing = editing; + }; + this.isNearTablet = function (controllerData) { return HMD.tabletID && controllerData.nearbyOverlayIDs[this.hand].indexOf(HMD.tabletID) !== -1; }; this.isReady = function (controllerData) { - if (this.isNearTablet(controllerData)) { + if (!this.isEditing && this.isNearTablet(controllerData)) { return makeRunningValues(true, [], []); } setTabletNearGrabbable(this.hand, false); @@ -79,7 +84,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); }; this.run = function (controllerData) { - if (!this.isNearTablet(controllerData)) { + if (this.isEditing || !this.isNearTablet(controllerData)) { setTabletNearGrabbable(this.hand, false); return makeRunningValues(false, [], []); } @@ -111,6 +116,28 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); HMD.mountedChanged.connect(onDisplayModeChanged); onDisplayModeChanged(); + function onMessageReceived(channel, data, senderID) { + var message; + + if (channel !== HIFI_EDIT_MANIPULATION_CHANNEL || senderID !== MyAvatar.sessionUUID) { + return; + } + + try { + message = JSON.parse(data); + } catch (e) { + return; + } + + if (message.hand === Controller.Standard.LeftHand) { + leftNearTabletHighlight.setIsEditing(message.action === "startEdit"); + } else if (message.hand === Controller.Standard.RightHand) { + rightNearTabletHighlight.setIsEditing(message.action === "startEdit"); + } + } + Messages.subscribe(HIFI_EDIT_MANIPULATION_CHANNEL); + Messages.messageReceived.connect(onMessageReceived); + function cleanUp() { disableDispatcherModule("LeftNearTabletHighlight"); disableDispatcherModule("RightNearTabletHighlight"); From e8c5324e3936b368ce8517f635a06435bfc7bda2 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 25 Oct 2018 11:59:04 -0700 Subject: [PATCH 014/117] start removing branching --- libraries/gpu/src/gpu/Noise.slh | 3 +- .../src/graphics/MaterialTextures.slh | 48 ++++++++++++------- .../render-utils/src/DeferredBufferRead.slh | 33 +++++-------- .../render-utils/src/DeferredBufferWrite.slh | 6 ++- .../render-utils/src/DeferredTransform.slh | 3 +- libraries/render-utils/src/Fade.slh | 10 ++-- libraries/render-utils/src/Haze.slh | 42 ++++++++-------- libraries/render-utils/src/Highlight.slh | 32 ++++++------- .../render-utils/src/LightClusterGrid.slh | 3 +- .../src/LightClusterGrid_shared.slh | 31 +++++------- libraries/render-utils/src/LightPoint.slh | 24 +++++----- libraries/render-utils/src/LightSpot.slh | 22 ++++----- libraries/render-utils/src/Shadow.slh | 20 ++++---- libraries/render/src/render/BlurTask.slh | 12 ++--- 14 files changed, 144 insertions(+), 145 deletions(-) diff --git a/libraries/gpu/src/gpu/Noise.slh b/libraries/gpu/src/gpu/Noise.slh index d300e71ba9..a6a658cbd1 100644 --- a/libraries/gpu/src/gpu/Noise.slh +++ b/libraries/gpu/src/gpu/Noise.slh @@ -231,7 +231,8 @@ float snoise(vec2 v) { // Other corners vec2 i1; - i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + float check = float(x0.x > x0.y); + i1 = vec2(check, 1.0 - check); vec4 x12 = x0.xyxy + C.xxzz; x12.xy -= i1; diff --git a/libraries/graphics/src/graphics/MaterialTextures.slh b/libraries/graphics/src/graphics/MaterialTextures.slh index db329c3852..d393d0bcbd 100644 --- a/libraries/graphics/src/graphics/MaterialTextures.slh +++ b/libraries/graphics/src/graphics/MaterialTextures.slh @@ -151,29 +151,37 @@ float fetchScatteringMap(vec2 uv) { <@func fetchMaterialTexturesCoord0(matKey, texcoord0, albedo, roughness, normal, metallic, emissive, scattering)@> + float check; <@if albedo@> - vec4 <$albedo$> = (((<$matKey$> & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(<$texcoord0$>) : vec4(1.0)); + check = float((<$matKey$> & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0); + vec4 <$albedo$> = check * fetchAlbedoMap(<$texcoord0$>) + vec4(1.0 - check); <@endif@> <@if roughness@> - float <$roughness$> = (((<$matKey$> & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(<$texcoord0$>) : 1.0); + check = float((<$matKey$> & ROUGHNESS_MAP_BIT) != 0); + float <$roughness$> = check * fetchRoughnessMap(<$texcoord0$>) + (1.0 - check); <@endif@> <@if normal@> - vec3 <$normal$> = (((<$matKey$> & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(<$texcoord0$>) : vec3(0.0, 1.0, 0.0)); + check = float((<$matKey$> & NORMAL_MAP_BIT) != 0); + vec3 <$normal$> = check * fetchNormalMap(<$texcoord0$>) + vec3(0.0, 1.0 - check, 0.0); <@endif@> <@if metallic@> - float <$metallic$> = (((<$matKey$> & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(<$texcoord0$>) : 0.0); + check = float((<$matKey$> & METALLIC_MAP_BIT) != 0); + float <$metallic$> = check * fetchMetallicMap(<$texcoord0$>); <@endif@> <@if emissive@> - vec3 <$emissive$> = (((<$matKey$> & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(<$texcoord0$>) : vec3(0.0)); + check = float((<$matKey$> & EMISSIVE_MAP_BIT) != 0); + vec3 <$emissive$> = check * fetchEmissiveMap(<$texcoord0$>); <@endif@> <@if scattering@> - float <$scattering$> = (((<$matKey$> & SCATTERING_MAP_BIT) != 0) ? fetchScatteringMap(<$texcoord0$>) : 0.0); + check = float((<$matKey$> & SCATTERING_MAP_BIT) != 0); + float <$scattering$> = check * fetchScatteringMap(<$texcoord0$>); <@endif@> <@endfunc@> <@func fetchMaterialTexturesCoord1(matKey, texcoord1, occlusion, lightmapVal)@> <@if occlusion@> - float <$occlusion$> = (((<$matKey$> & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(<$texcoord1$>) : 1.0); + float check1 = float((<$matKey$> & OCCLUSION_MAP_BIT) != 0); + float <$occlusion$> = check1 * fetchOcclusionMap(<$texcoord1$>) + (1.0 - check1); <@endif@> <@if lightmapVal@> vec3 <$lightmapVal$> = fetchLightmapMap(<$texcoord1$>); @@ -217,20 +225,20 @@ vec3 fetchLightmapMap(vec2 uv) { <@func evalMaterialAlbedo(fetchedAlbedo, materialAlbedo, matKey, albedo)@> { - <$albedo$>.xyz = (((<$matKey$> & ALBEDO_VAL_BIT) != 0) ? <$materialAlbedo$> : vec3(1.0)); + float check = float((<$matKey$> & ALBEDO_VAL_BIT) != 0); + <$albedo$>.xyz = check * <$materialAlbedo$> + vec3(1.0 - check); - if (((<$matKey$> & ALBEDO_MAP_BIT) != 0)) { - <$albedo$>.xyz *= <$fetchedAlbedo$>.xyz; - } + check = float((<$matKey$> & ALBEDO_MAP_BIT) != 0); + <$albedo$>.xyz *= check * <$fetchedAlbedo$>.xyz + vec3(1.0 - check); } <@endfunc@> <@func evalMaterialOpacity(fetchedOpacity, materialOpacity, matKey, opacity)@> { const float OPACITY_MASK_THRESHOLD = 0.5; - <$opacity$> = (((<$matKey$> & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0) ? - (((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0) ? step(OPACITY_MASK_THRESHOLD, <$fetchedOpacity$>) : <$fetchedOpacity$>) : - 1.0) * <$materialOpacity$>; + float check = float((<$matKey$> & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0); + float check2 = float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0); + <$opacity$> = (check * (check2 * step(OPACITY_MASK_THRESHOLD, <$fetchedOpacity$>) + (1.0 - check2) * <$fetchedOpacity$>) + (1.0 - check)) * <$materialOpacity$>; } <@endfunc@> @@ -251,19 +259,22 @@ vec3 fetchLightmapMap(vec2 uv) { <@func evalMaterialRoughness(fetchedRoughness, materialRoughness, matKey, roughness)@> { - <$roughness$> = (((<$matKey$> & ROUGHNESS_MAP_BIT) != 0) ? <$fetchedRoughness$> : <$materialRoughness$>); + float check = float((<$matKey$> & ROUGHNESS_MAP_BIT) != 0); + <$roughness$> = check * <$fetchedRoughness$> + (1.0 - check) * <$materialRoughness$>; } <@endfunc@> <@func evalMaterialMetallic(fetchedMetallic, materialMetallic, matKey, metallic)@> { - <$metallic$> = (((<$matKey$> & METALLIC_MAP_BIT) != 0) ? <$fetchedMetallic$> : <$materialMetallic$>); + float check = float((<$matKey$> & METALLIC_MAP_BIT) != 0); + <$metallic$> = check * <$fetchedMetallic$> + (1.0 - check) * <$materialMetallic$>; } <@endfunc@> <@func evalMaterialEmissive(fetchedEmissive, materialEmissive, matKey, emissive)@> { - <$emissive$> = (((<$matKey$> & EMISSIVE_MAP_BIT) != 0) ? <$fetchedEmissive$> : <$materialEmissive$>); + float check = float((<$matKey$> & EMISSIVE_MAP_BIT) != 0); + <$emissive$> = check * <$fetchedEmissive$> + (1.0 - check) * <$materialEmissive$>; } <@endfunc@> @@ -275,7 +286,8 @@ vec3 fetchLightmapMap(vec2 uv) { <@func evalMaterialScattering(fetchedScattering, materialScattering, matKey, scattering)@> { - <$scattering$> = (((<$matKey$> & SCATTERING_MAP_BIT) != 0) ? <$fetchedScattering$> : <$materialScattering$>); + float check = float((<$matKey$> & SCATTERING_MAP_BIT) != 0); + <$scattering$> = check * <$fetchedScattering$> + (1.0 - check) * <$materialScattering$>; } <@endfunc@> diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh index f3b8c0404a..bf0100d0d3 100644 --- a/libraries/render-utils/src/DeferredBufferRead.slh +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -76,14 +76,12 @@ DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { // Diffuse color and unpack the mode and the metallicness frag.albedo = diffuseVal.xyz; - frag.scattering = 0.0; unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic); frag.obscurance = min(specularVal.w, frag.obscurance); - if (frag.mode == FRAG_MODE_SCATTERING) { - frag.scattering = specularVal.x; - } + float check = float(frag.mode == FRAG_MODE_SCATTERING); + frag.scattering = check * specularVal.x; frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz); @@ -122,14 +120,11 @@ DeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) { <$declareDeferredFrameTransform()$> vec4 unpackDeferredPosition(float depthValue, vec2 texcoord) { - int side = 0; - if (isStereo()) { - if (texcoord.x > 0.5) { - texcoord.x -= 0.5; - side = 1; - } - texcoord.x *= 2.0; - } + float check = float(isStereo()); + float check2 = float(texcoord.x > 0.5); + texcoord.x -= check * check2 * 0.5; + int side = int(check * check2); + texcoord.x *= check * 2.0 + (1.0 - check) * 1.0; return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0); } @@ -142,19 +137,15 @@ vec4 unpackDeferredPositionFromZdb(vec2 texcoord) { vec4 unpackDeferredPositionFromZeye(vec2 texcoord) { float Zeye = -texture(linearZeyeMap, texcoord).x; - int side = 0; - if (isStereo()) { - if (texcoord.x > 0.5) { - texcoord.x -= 0.5; - side = 1; - } - texcoord.x *= 2.0; - } + float check = float(isStereo()); + float check2 = float(texcoord.x > 0.5); + texcoord.x -= check * check2 * 0.5; + int side = int(check * check2); + texcoord.x *= check * 2.0 + (1.0 - check) * 1.0; return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0); } DeferredFragment unpackDeferredFragment(DeferredFrameTransform deferredTransform, vec2 texcoord) { - float depthValue = texture(depthMap, texcoord).r; DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord); diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 769e602dc5..a531affd85 100644 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -32,9 +32,11 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness if (alpha != 1.0) { discard; } - _fragColor0 = vec4(albedo, ((scattering > 0.0) ? packScatteringMetallic(metallic) : packShadedMetallic(metallic))); + + float check = float(scattering > 0.0); + _fragColor0 = vec4(albedo, check * packScatteringMetallic(metallic) + (1.0 - check) * packShadedMetallic(metallic)); _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0)); - _fragColor2 = vec4(((scattering > 0.0) ? vec3(scattering) : emissive), occlusion); + _fragColor2 = vec4(check * vec3(scattering) + (1.0 - check) * emissive, occlusion); _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0); } diff --git a/libraries/render-utils/src/DeferredTransform.slh b/libraries/render-utils/src/DeferredTransform.slh index 8a8805e928..3ec763efe2 100644 --- a/libraries/render-utils/src/DeferredTransform.slh +++ b/libraries/render-utils/src/DeferredTransform.slh @@ -126,7 +126,8 @@ vec2 getSideImageSize(int resolutionLevel) { ivec4 getStereoSideInfo(int xPos, int resolutionLevel) { int sideWidth = int(getStereoSideWidth(resolutionLevel)); - return ivec4(xPos < sideWidth ? ivec2(0, 0) : ivec2(1, sideWidth), sideWidth, isStereo()); + int check = int(xPos < sideWidth); + return ivec4((1 - check) * ivec2(1, sideWidth), sideWidth, isStereo()); } float evalZeyeFromZdb(float depth) { diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index a7523f969b..6770f53200 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -85,7 +85,12 @@ float evalFadeGradient(FadeObjectParams params, vec3 position) { } float evalFadeAlpha(FadeObjectParams params, vec3 position) { - return evalFadeGradient(params, position)-params.threshold; + float alpha = evalFadeGradient(params, position) - params.threshold; + + float check = float(fadeParameters[params.category]._isInverted != 0); + alpha *= -check + (1.0 - check); + + return alpha; } void applyFadeClip(FadeObjectParams params, vec3 position) { @@ -96,9 +101,6 @@ void applyFadeClip(FadeObjectParams params, vec3 position) { void applyFade(FadeObjectParams params, vec3 position, out vec3 emissive) { float alpha = evalFadeAlpha(params, position); - if (fadeParameters[params.category]._isInverted!=0) { - alpha = -alpha; - } if (alpha < 0.0) { discard; diff --git a/libraries/render-utils/src/Haze.slh b/libraries/render-utils/src/Haze.slh index a7654da8d2..f5795565cc 100644 --- a/libraries/render-utils/src/Haze.slh +++ b/libraries/render-utils/src/Haze.slh @@ -63,20 +63,18 @@ vec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 // Height at which haze density is reduced by 95% (default set to 2000.0 for safety ,this should never happen) float height_95p = 2000.0; const float log_p_005 = log(0.05); - if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) { - height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor; + + { + float check = float(hazeParams.hazeKeyLightAltitudeFactor > 0.0f); + height_95p = check * -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor + (1.0 - check) * height_95p; } // Note that we need the sine to be positive - float sin_pitch = abs(lightDirectionWS.y); - - float distance; const float minimumSinPitch = 0.001; - if (sin_pitch < minimumSinPitch) { - distance = height_95p / minimumSinPitch; - } else { - distance = height_95p / sin_pitch; - } + float sin_pitch = abs(lightDirectionWS.y); + sin_pitch = max(sin_pitch, minimumSinPitch); + + float distance = height_95p / sin_pitch; // Integration is from the fragment towards the light source // Note that the haze base reference affects only the haze density as function of altitude @@ -128,6 +126,7 @@ vec4 computeHazeColor(vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePosition } vec4 potentialFragColor; + const float EPSILON = 0.0000001f; if ((hazeParams.hazeMode & HAZE_MODE_IS_MODULATE_COLOR) == HAZE_MODE_IS_MODULATE_COLOR) { // Compute separately for each colour @@ -143,9 +142,10 @@ vec4 computeHazeColor(vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePosition const float slopeThreshold = 0.01; float deltaHeight = fragPositionWS.y - eyeWorldHeight; - if (abs(deltaHeight) > slopeThreshold) { - float t = hazeParams.hazeHeightFactor * deltaHeight; - hazeIntegral *= (1.0 - exp (-t)) / t; + float t = hazeParams.hazeHeightFactor * deltaHeight; + if (abs(t) > EPSILON) { + float check = float(abs(deltaHeight) > slopeThreshold); + hazeIntegral *= check * (1.0 - exp(-t)) / t + (1.0 - check); } vec3 hazeAmount = 1.0 - exp(-hazeIntegral); @@ -171,13 +171,10 @@ vec4 computeHazeColor(vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePosition const float slopeThreshold = 0.01; float deltaHeight = fragPositionWS.y - eyeWorldHeight; - if (abs(deltaHeight) > slopeThreshold) { - float t = hazeParams.hazeHeightFactor * deltaHeight; - // Protect from wild values - const float EPSILON = 0.0000001f; - if (abs(t) > EPSILON) { - hazeIntegral *= (1.0 - exp (-t)) / t; - } + float t = hazeParams.hazeHeightFactor * deltaHeight; + if (abs(t) > EPSILON) { + float check = float(abs(deltaHeight) > slopeThreshold); + hazeIntegral *= check * (1.0 - exp(-t)) / t + (1.0 - check); } float hazeAmount = 1.0 - exp(-hazeIntegral); @@ -189,9 +186,8 @@ vec4 computeHazeColor(vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePosition // Mix with background at far range const float BLEND_DISTANCE = 27000.0f; vec4 outFragColor = potentialFragColor; - if (distance > BLEND_DISTANCE) { - outFragColor.a *= hazeParams.backgroundBlend; - } + float check = float(distance > BLEND_DISTANCE); + outFragColor.a *= check * hazeParams.backgroundBlend + (1.0 - check); return outFragColor; } diff --git a/libraries/render-utils/src/Highlight.slh b/libraries/render-utils/src/Highlight.slh index 264b57acbb..eee22ecb0a 100644 --- a/libraries/render-utils/src/Highlight.slh +++ b/libraries/render-utils/src/Highlight.slh @@ -45,11 +45,9 @@ void main(void) { highlightedDepth = -evalZeyeFromZdb(highlightedDepth); sceneDepth = -evalZeyeFromZdb(sceneDepth); - if (sceneDepth < highlightedDepth) { - outFragColor = vec4(params._fillOccludedColor, params._fillOccludedAlpha); - } else { - outFragColor = vec4(params._fillUnoccludedColor, params._fillUnoccludedAlpha); - } + float check = float(sceneDepth < highlightedDepth); + outFragColor = check * vec4(params._fillOccludedColor, params._fillOccludedAlpha) + + (1.0 - check) * vec4(params._fillUnoccludedColor, params._fillUnoccludedAlpha); <@else@> discard; <@endif@> @@ -67,14 +65,13 @@ void main(void) { float outlinedDepth = 0.0; float sumOutlineDepth = 0.0; - for (y=0 ; y=0.0 && uv.y<=1.0) { - for (x=0 ; x=0.0 && uv.x<=1.0) - { + if (uv.y >= 0.0 && uv.y <= 1.0) { + for (x = 0; x < params._blurKernelSize; x++) { + if (uv.x >= 0.0 && uv.x <= 1.0) { outlinedDepth = texture(highlightedDepthMap, uv).x; float touch = (outlinedDepth < FAR_Z) ? 1.0 : 0.0; sumOutlineDepth = max(outlinedDepth * touch, sumOutlineDepth); @@ -86,10 +83,9 @@ void main(void) { } } - if (intensity > 0.0) { - // sumOutlineDepth /= intensity; - } else { - sumOutlineDepth = FAR_Z; + { + float check = float(intensity > 0.0); + sumOutlineDepth = check * sumOutlineDepth + (1.0 - check) * FAR_Z; } intensity /= weight; @@ -106,10 +102,10 @@ void main(void) { sceneDepth = -evalZeyeFromZdb(sceneDepth); // Are we occluded? - if (sceneDepth < outlinedDepth) { - outFragColor = vec4(params._outlineOccludedColor, intensity * params._outlineOccludedAlpha); - } else { - outFragColor = vec4(params._outlineUnoccludedColor, intensity * params._outlineUnoccludedAlpha); + { + float check = float(sceneDepth < outlinedDepth); + outFragColor = check * vec4(params._outlineOccludedColor, intensity * params._outlineOccludedAlpha) + + (1.0 - check) * vec4(params._outlineUnoccludedColor, intensity * params._outlineUnoccludedAlpha); } } } diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 62af92e6ce..46eba68fff 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -83,7 +83,8 @@ int clusterGrid_getClusterLightId(int index, int offset) { return element; */ int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))]; - return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF; + int check = int((elementIndex & 0x00000001) == 1); + return (check * (element >> 16) + (1 - check) * element) & 0x0000FFFF; } diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index 6d43e71920..be9d980062 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -5,6 +5,12 @@ #define float_exp2 exp2 #endif +#ifdef __cplusplus +# define _MIN glm::min +#else +# define _MIN min +#endif + float frustumGrid_depthRampGridToVolume(float ngrid) { // return ngrid; // return sqrt(ngrid); @@ -87,14 +93,9 @@ ivec3 frustumGrid_indexToCluster(int index) { } vec3 frustumGrid_clusterPosToEye(vec3 clusterPos) { - vec3 cvpos = clusterPos; - - vec3 volumePos = frustumGrid_gridToVolume(cvpos, frustumGrid.dims); - vec3 eyePos = frustumGrid_volumeToEye(volumePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); - return eyePos; } @@ -116,27 +117,19 @@ int frustumGrid_eyeDepthToClusterLayer(float eyeZ) { int gridZ = int(frustumGrid_volumeToGridDepth(volumeZ, frustumGrid.dims)); - if (gridZ >= frustumGrid.dims.z) { - gridZ = frustumGrid.dims.z; - } - - - return gridZ; + return _MIN(gridZ, frustumGrid.dims.z); } ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { // make sure the frontEyePos is always in the front to eval the grid pos correctly vec3 frontEyePos = eyePos; - frontEyePos.z = (eyePos.z > 0.0f ? -eyePos.z : eyePos.z); + frontEyePos.z = -abs(eyePos.z); vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); vec3 gridPos = frustumGrid_volumeToGrid(volumePos, frustumGrid.dims); - - if (gridPos.z >= float(frustumGrid.dims.z)) { - gridPos.z = float(frustumGrid.dims.z); - } + gridPos.z = _MIN(gridPos.z, float(frustumGrid.dims.z)); ivec3 igridPos = ivec3(floor(gridPos)); @@ -154,7 +147,8 @@ ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { int frustumGrid_eyeToClusterDirH(vec3 eyeDir) { if (eyeDir.z >= 0.0f) { - return (eyeDir.x > 0.0f ? frustumGrid.dims.x : -1); + int check = int(eyeDir.x > 0.0f); + return check * frustumGrid.dims.x + (check - 1); } float eyeDepth = -eyeDir.z; @@ -168,7 +162,8 @@ int frustumGrid_eyeToClusterDirH(vec3 eyeDir) { int frustumGrid_eyeToClusterDirV(vec3 eyeDir) { if (eyeDir.z >= 0.0f) { - return (eyeDir.y > 0.0f ? frustumGrid.dims.y : -1); + int check = int(eyeDir.y > 0.0f); + return check * frustumGrid.dims.y + (check - 1); } float eyeDepth = -eyeDir.z; diff --git a/libraries/render-utils/src/LightPoint.slh b/libraries/render-utils/src/LightPoint.slh index 1a361e3717..f5cda3d9d4 100644 --- a/libraries/render-utils/src/LightPoint.slh +++ b/libraries/render-utils/src/LightPoint.slh @@ -39,14 +39,13 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, lightEnergy *= isPointEnabled(); diffuse *= lightEnergy * isDiffuseEnabled(); specular *= lightEnergy * isSpecularEnabled(); - - if (isShowLightContour() > 0.0) { - // Show edge + + { + // Show edges float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0); - if (edge < 1.0) { - float edgeCoord = exp2(-8.0*edge*edge); - diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light)); - } + float check = float(isShowLightContour() > 0.0 && edge < 1.0); + float edgeCoord = exp2(-8.0 * edge * edge); + diffuse = check * vec3(edgeCoord * edgeCoord * getLightColor(light)) + (1.0 - check) * diffuse; } } @@ -59,12 +58,13 @@ bool evalLightPointEdge(out vec3 color, Light light, vec4 fragLightDirLen, vec3 // Allright we re valid in the volume float fragLightDistance = fragLightDirLen.w; vec3 fragLightDir = fragLightDirLen.xyz; - - // Show edges + float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0); - if (edge < 1.0) { - float edgeCoord = exp2(-8.0*edge*edge); - color = vec3(edgeCoord * edgeCoord * getLightColor(light)); + { + // Show edges + float check = float(edge < 1.0); + float edgeCoord = exp2(-8.0 * edge * edge); + color = check * vec3(edgeCoord * edgeCoord * getLightColor(light)) + (1.0 - check) * color; } return (edge < 1.0); diff --git a/libraries/render-utils/src/LightSpot.slh b/libraries/render-utils/src/LightSpot.slh index 2546c0225c..395fe892e7 100644 --- a/libraries/render-utils/src/LightSpot.slh +++ b/libraries/render-utils/src/LightSpot.slh @@ -40,17 +40,16 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light, lightEnergy *= isSpotEnabled(); diffuse *= lightEnergy * isDiffuseEnabled(); specular *= lightEnergy * isSpecularEnabled(); - - if (isShowLightContour() > 0.0) { + + { // Show edges float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance); float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume)); float edgeDist = min(edgeDistR, edgeDistS); float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0); - if (edge < 1.0) { - float edgeCoord = exp2(-8.0*edge*edge); - diffuse = vec3(edgeCoord * edgeCoord * getLightColor(light)); - } + float check = float(isShowLightContour() > 0.0 && edge < 1.0); + float edgeCoord = exp2(-8.0 * edge * edge); + diffuse = check * vec3(edgeCoord * edgeCoord * getLightColor(light)) + (1.0 - check) * diffuse; } } @@ -63,19 +62,18 @@ bool evalLightSpotEdge(out vec3 color, Light light, vec4 fragLightDirLen, float float fragLightDistance = fragLightDirLen.w; vec3 fragLightDir = fragLightDirLen.xyz; - // Show edges float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance); float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume)); float edgeDist = min(edgeDistR, edgeDistS); float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0); - if (edge < 1.0) { - float edgeCoord = exp2(-8.0*edge*edge); - color = vec3(edgeCoord * edgeCoord * getLightColor(light)); + { + // Show edges + float check = float(edge < 1.0); + float edgeCoord = exp2(-8.0 * edge * edge); + color = check * vec3(edgeCoord * edgeCoord * getLightColor(light)) + (1.0 - check) * color; } return (edge < 1.0); } <@endfunc@> - - diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index 9506c9805d..10922350ed 100644 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -115,17 +115,21 @@ float evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDe isPixelOnCascade.z = isShadowCascadeProjectedOnPixel(cascadeShadowCoords[2]); isPixelOnCascade.w = isShadowCascadeProjectedOnPixel(cascadeShadowCoords[3]); - if (isPixelOnCascade.x) { - cascadeAttenuations.x = evalShadowCascadeAttenuation(0, offsets, cascadeShadowCoords[0], oneMinusNdotL); + { + float check = float(isPixelOnCascade.x); + cascadeAttenuations.x = check * evalShadowCascadeAttenuation(0, offsets, cascadeShadowCoords[0], oneMinusNdotL) + (1.0 - check); } - if (isPixelOnCascade.y) { - cascadeAttenuations.y = evalShadowCascadeAttenuation(1, offsets, cascadeShadowCoords[1], oneMinusNdotL); + { + float check = float(isPixelOnCascade.y); + cascadeAttenuations.y = check * evalShadowCascadeAttenuation(1, offsets, cascadeShadowCoords[1], oneMinusNdotL) + (1.0 - check); } - if (isPixelOnCascade.z) { - cascadeAttenuations.z = evalShadowCascadeAttenuation(2, offsets, cascadeShadowCoords[2], oneMinusNdotL); + { + float check = float(isPixelOnCascade.z); + cascadeAttenuations.z = check * evalShadowCascadeAttenuation(2, offsets, cascadeShadowCoords[2], oneMinusNdotL) + (1.0 - check); } - if (isPixelOnCascade.w) { - cascadeAttenuations.w = evalShadowCascadeAttenuation(3, offsets, cascadeShadowCoords[3], oneMinusNdotL); + { + float check = float(isPixelOnCascade.w); + cascadeAttenuations.w = check * evalShadowCascadeAttenuation(3, offsets, cascadeShadowCoords[3], oneMinusNdotL) + (1.0 - check); } cascadeWeights.x = evalShadowCascadeWeight(cascadeShadowCoords[0]); diff --git a/libraries/render/src/render/BlurTask.slh b/libraries/render/src/render/BlurTask.slh index db6b8e3bab..1133435b4d 100644 --- a/libraries/render/src/render/BlurTask.slh +++ b/libraries/render/src/render/BlurTask.slh @@ -99,9 +99,9 @@ vec4 pixelShaderGaussian(vec2 texcoord, vec2 direction, vec2 pixelStep) { } } - if (totalWeight>0.0) { - srcBlurred /= totalWeight; - } + float check = float(totalWeight > 0.0); + srcBlurred *= check / totalWeight + (1.0 - check); + srcBlurred.a = getOutputAlpha(); return srcBlurred; } @@ -160,9 +160,9 @@ vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep } } - if (totalWeight>0.0) { - srcBlurred /= totalWeight; - } + float check = float(totalWeight > 0.0); + srcBlurred *= check / totalWeight + (1.0 - check); + return srcBlurred; } From dc9405775f05bf38a4818bdfdfbe0ea4c0678f2a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 25 Oct 2018 14:29:14 -0700 Subject: [PATCH 015/117] more branching removal --- .../InterleavedSrgbToLinear.slf | 4 +- .../src/display-plugins/SrgbToLinear.slf | 2 +- .../src/textured_particle.slv | 9 +- .../src/graphics/MaterialTextures.slh | 49 ++++----- libraries/graphics/src/graphics/skybox.slf | 10 +- .../render-utils/src/DeferredBufferRead.slh | 23 ++-- .../render-utils/src/DeferredBufferWrite.slh | 4 +- .../render-utils/src/DeferredTransform.slh | 3 +- libraries/render-utils/src/Fade.slh | 4 +- libraries/render-utils/src/Haze.slf | 15 ++- libraries/render-utils/src/Haze.slh | 14 +-- libraries/render-utils/src/Highlight.slh | 19 ++-- .../render-utils/src/LightClusterGrid.slh | 3 +- .../src/LightClusterGrid_shared.slh | 12 ++- libraries/render-utils/src/LightPoint.slh | 22 ++-- libraries/render-utils/src/LightSpot.slh | 30 +++--- libraries/render-utils/src/Shadow.slh | 20 +--- libraries/render-utils/src/Skinning.slh | 15 ++- .../render-utils/src/SubsurfaceScattering.slh | 5 +- .../src/deferred_light_limited.slv | 8 +- .../render-utils/src/deferred_light_point.slv | 4 +- .../render-utils/src/deferred_light_spot.slv | 4 +- .../src/directional_ambient_light.slf | 11 +- .../src/directional_ambient_light_shadow.slf | 12 +-- .../src/directional_skybox_light.slf | 12 +-- .../src/directional_skybox_light_shadow.slf | 12 +-- .../render-utils/src/drawWorkloadProxy.slv | 4 +- .../render-utils/src/forward_model_unlit.slf | 3 - libraries/render-utils/src/glowLine.slv | 10 +- libraries/render-utils/src/grid.slf | 10 +- .../src/lightClusters_drawClusterContent.slf | 2 +- .../src/lightClusters_drawClusterContent.slv | 2 +- .../lightClusters_drawClusterFromDepth.slf | 12 +-- .../lightClusters_drawClusterFromDepth.slv | 2 +- .../src/lightClusters_drawGrid.slv | 2 +- .../src/local_lights_drawOutline.slf | 11 +- libraries/render-utils/src/parabola.slv | 7 +- libraries/render-utils/src/sdf_text3D.slf | 20 +--- .../src/sdf_text3D_transparent.slf | 43 ++++---- libraries/render-utils/src/simple.slf | 2 +- .../render-utils/src/simple_textured.slf | 5 +- .../render-utils/src/simple_textured_fade.slf | 18 ++-- .../src/simple_textured_unlit.slf | 18 ++-- .../src/simple_textured_unlit_fade.slf | 18 ++-- .../src/simple_transparent_textured.slf | 9 +- .../src/simple_transparent_textured_fade.slf | 19 ++-- .../src/simple_transparent_textured_unlit.slf | 13 ++- ...simple_transparent_textured_unlit_fade.slf | 13 ++- libraries/render-utils/src/ssao.slh | 47 +++----- .../render-utils/src/ssao_debugOcclusion.slf | 27 ++--- .../render-utils/src/ssao_makeOcclusion.slf | 9 +- .../render-utils/src/stencil_drawMask.slf | 7 +- .../subsurfaceScattering_drawScattering.slf | 12 +-- .../src/surfaceGeometry_makeCurvature.slf | 12 +-- libraries/render-utils/src/taa.slf | 16 +-- libraries/render-utils/src/taa.slh | 100 ++++++++---------- libraries/render-utils/src/taa_blend.slf | 38 ++----- .../render-utils/src/zone_drawAmbient.slf | 2 +- .../render-utils/src/zone_drawSkybox.slf | 11 +- libraries/render/src/render/BlurTask.slh | 14 +-- .../render/src/render/drawCellBounds.slv | 2 +- .../render/src/render/drawItemBounds.slf | 10 +- .../render/src/render/drawItemBounds.slv | 7 +- .../render/src/render/drawItemStatus.slf | 11 +- 64 files changed, 356 insertions(+), 538 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/InterleavedSrgbToLinear.slf b/libraries/display-plugins/src/display-plugins/InterleavedSrgbToLinear.slf index e70053dcd9..66acff616c 100644 --- a/libraries/display-plugins/src/display-plugins/InterleavedSrgbToLinear.slf +++ b/libraries/display-plugins/src/display-plugins/InterleavedSrgbToLinear.slf @@ -14,8 +14,6 @@ void main(void) { ivec2 texCoord = ivec2(floor(varTexCoord0 * vec2(textureData.textureSize))); texCoord.x /= 2; int row = int(floor(gl_FragCoord.y)); - if (row % 2 > 0) { - texCoord.x += (textureData.textureSize.x / 2); - } + texCoord.x += int(row % 2 > 0) * (textureData.textureSize.x / 2); outFragColor = vec4(pow(texelFetch(colorMap, texCoord, 0).rgb, vec3(2.2)), 1.0); } diff --git a/libraries/display-plugins/src/display-plugins/SrgbToLinear.slf b/libraries/display-plugins/src/display-plugins/SrgbToLinear.slf index aad9e71e0e..8b324c81a5 100644 --- a/libraries/display-plugins/src/display-plugins/SrgbToLinear.slf +++ b/libraries/display-plugins/src/display-plugins/SrgbToLinear.slf @@ -9,7 +9,7 @@ layout(location=0) out vec4 outFragColor; float sRGBFloatToLinear(float value) { const float SRGB_ELBOW = 0.04045; - return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4); + return mix(pow((value + 0.055) / 1.055, 2.4), value / 12.92, float(value <= SRGB_ELBOW)); } vec3 colorToLinearRGB(vec3 srgb) { diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 4d17fe132b..98d25eae2e 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -80,10 +80,11 @@ float interpolate3Points(float y1, float y2, float y3, float u) { halfSlope = (y3 - y1) / 2.0f; float slope12 = y2 - y1; float slope23 = y3 - y2; - if (abs(halfSlope) > abs(slope12)) { - halfSlope = slope12; - } else if (abs(halfSlope) > abs(slope23)) { - halfSlope = slope23; + + { + float check = float(abs(halfSlope) > abs(slope12)); + halfSlope = mix(halfSlope, slope12, check); + halfSlope = mix(halfSlope, slope23, (1.0 - check) * float(abs(halfSlope) > abs(slope23))); } } diff --git a/libraries/graphics/src/graphics/MaterialTextures.slh b/libraries/graphics/src/graphics/MaterialTextures.slh index d393d0bcbd..615582dea5 100644 --- a/libraries/graphics/src/graphics/MaterialTextures.slh +++ b/libraries/graphics/src/graphics/MaterialTextures.slh @@ -151,37 +151,29 @@ float fetchScatteringMap(vec2 uv) { <@func fetchMaterialTexturesCoord0(matKey, texcoord0, albedo, roughness, normal, metallic, emissive, scattering)@> - float check; <@if albedo@> - check = float((<$matKey$> & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0); - vec4 <$albedo$> = check * fetchAlbedoMap(<$texcoord0$>) + vec4(1.0 - check); + vec4 <$albedo$> = mix(vec4(1.0), fetchAlbedoMap(<$texcoord0$>), float((<$matKey$> & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0)); <@endif@> <@if roughness@> - check = float((<$matKey$> & ROUGHNESS_MAP_BIT) != 0); - float <$roughness$> = check * fetchRoughnessMap(<$texcoord0$>) + (1.0 - check); + float <$roughness$> = mix(1.0, fetchRoughnessMap(<$texcoord0$>), float((<$matKey$> & ROUGHNESS_MAP_BIT) != 0)); <@endif@> <@if normal@> - check = float((<$matKey$> & NORMAL_MAP_BIT) != 0); - vec3 <$normal$> = check * fetchNormalMap(<$texcoord0$>) + vec3(0.0, 1.0 - check, 0.0); + vec3 <$normal$> = mix(vec3(0.0, 1.0, 0.0), fetchNormalMap(<$texcoord0$>), float((<$matKey$> & NORMAL_MAP_BIT) != 0)); <@endif@> <@if metallic@> - check = float((<$matKey$> & METALLIC_MAP_BIT) != 0); - float <$metallic$> = check * fetchMetallicMap(<$texcoord0$>); + float <$metallic$> = float((<$matKey$> & METALLIC_MAP_BIT) != 0) * fetchMetallicMap(<$texcoord0$>); <@endif@> <@if emissive@> - check = float((<$matKey$> & EMISSIVE_MAP_BIT) != 0); - vec3 <$emissive$> = check * fetchEmissiveMap(<$texcoord0$>); + vec3 <$emissive$> = float((<$matKey$> & EMISSIVE_MAP_BIT) != 0) * fetchEmissiveMap(<$texcoord0$>); <@endif@> <@if scattering@> - check = float((<$matKey$> & SCATTERING_MAP_BIT) != 0); - float <$scattering$> = check * fetchScatteringMap(<$texcoord0$>); + float <$scattering$> = float((<$matKey$> & SCATTERING_MAP_BIT) != 0) * fetchScatteringMap(<$texcoord0$>); <@endif@> <@endfunc@> <@func fetchMaterialTexturesCoord1(matKey, texcoord1, occlusion, lightmapVal)@> <@if occlusion@> - float check1 = float((<$matKey$> & OCCLUSION_MAP_BIT) != 0); - float <$occlusion$> = check1 * fetchOcclusionMap(<$texcoord1$>) + (1.0 - check1); + float <$occlusion$> = mix(1.0, fetchOcclusionMap(<$texcoord1$>), float((<$matKey$> & OCCLUSION_MAP_BIT) != 0)); <@endif@> <@if lightmapVal@> vec3 <$lightmapVal$> = fetchLightmapMap(<$texcoord1$>); @@ -225,20 +217,19 @@ vec3 fetchLightmapMap(vec2 uv) { <@func evalMaterialAlbedo(fetchedAlbedo, materialAlbedo, matKey, albedo)@> { - float check = float((<$matKey$> & ALBEDO_VAL_BIT) != 0); - <$albedo$>.xyz = check * <$materialAlbedo$> + vec3(1.0 - check); - - check = float((<$matKey$> & ALBEDO_MAP_BIT) != 0); - <$albedo$>.xyz *= check * <$fetchedAlbedo$>.xyz + vec3(1.0 - check); + <$albedo$>.xyz = mix(vec3(1.0), <$materialAlbedo$>, float((<$matKey$> & ALBEDO_VAL_BIT) != 0)); + <$albedo$>.xyz *= mix(vec3(1.0), <$fetchedAlbedo$>.xyz, float((<$matKey$> & ALBEDO_MAP_BIT) != 0)); } <@endfunc@> <@func evalMaterialOpacity(fetchedOpacity, materialOpacity, matKey, opacity)@> { const float OPACITY_MASK_THRESHOLD = 0.5; - float check = float((<$matKey$> & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0); - float check2 = float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0); - <$opacity$> = (check * (check2 * step(OPACITY_MASK_THRESHOLD, <$fetchedOpacity$>) + (1.0 - check2) * <$fetchedOpacity$>) + (1.0 - check)) * <$materialOpacity$>; + <$opacity$> = mix(1.0, + mix(<$fetchedOpacity$>, + step(OPACITY_MASK_THRESHOLD, <$fetchedOpacity$>), + float((<$matKey$> & OPACITY_MASK_MAP_BIT) != 0)), + float((<$matKey$> & (OPACITY_TRANSLUCENT_MAP_BIT | OPACITY_MASK_MAP_BIT)) != 0)) * <$materialOpacity$>; } <@endfunc@> @@ -259,22 +250,19 @@ vec3 fetchLightmapMap(vec2 uv) { <@func evalMaterialRoughness(fetchedRoughness, materialRoughness, matKey, roughness)@> { - float check = float((<$matKey$> & ROUGHNESS_MAP_BIT) != 0); - <$roughness$> = check * <$fetchedRoughness$> + (1.0 - check) * <$materialRoughness$>; + <$roughness$> = mix(<$materialRoughness$>, <$fetchedRoughness$>, float((<$matKey$> & ROUGHNESS_MAP_BIT) != 0)); } <@endfunc@> <@func evalMaterialMetallic(fetchedMetallic, materialMetallic, matKey, metallic)@> { - float check = float((<$matKey$> & METALLIC_MAP_BIT) != 0); - <$metallic$> = check * <$fetchedMetallic$> + (1.0 - check) * <$materialMetallic$>; + <$metallic$> = mix(<$materialMetallic$>, <$fetchedMetallic$>, float((<$matKey$> & METALLIC_MAP_BIT) != 0)); } <@endfunc@> <@func evalMaterialEmissive(fetchedEmissive, materialEmissive, matKey, emissive)@> { - float check = float((<$matKey$> & EMISSIVE_MAP_BIT) != 0); - <$emissive$> = check * <$fetchedEmissive$> + (1.0 - check) * <$materialEmissive$>; + <$emissive$> = mix(<$materialEmissive$>, <$fetchedEmissive$>, float((<$matKey$> & EMISSIVE_MAP_BIT) != 0)); } <@endfunc@> @@ -286,8 +274,7 @@ vec3 fetchLightmapMap(vec2 uv) { <@func evalMaterialScattering(fetchedScattering, materialScattering, matKey, scattering)@> { - float check = float((<$matKey$> & SCATTERING_MAP_BIT) != 0); - <$scattering$> = check * <$fetchedScattering$> + (1.0 - check) * <$materialScattering$>; + <$scattering$> = mix(<$materialScattering$>, <$fetchedScattering$>, float((<$matKey$> & SCATTERING_MAP_BIT) != 0)); } <@endfunc@> diff --git a/libraries/graphics/src/graphics/skybox.slf b/libraries/graphics/src/graphics/skybox.slf index b24bf0f583..c20dd94bf4 100755 --- a/libraries/graphics/src/graphics/skybox.slf +++ b/libraries/graphics/src/graphics/skybox.slf @@ -30,11 +30,9 @@ void main(void) { vec3 color = skybox.color.rgb; // blend is only set if there is a cubemap - if (skybox.color.a > 0.0) { - color = texture(cubeMap, coord).rgb; - if (skybox.color.a < 1.0) { - color *= skybox.color.rgb; - } - } + float check = float(skybox.color.a > 0.0); + color = mix(color, texture(cubeMap, coord).rgb, check); + color *= mix(vec3(1.0), skybox.color.rgb, check * float(skybox.color.a < 1.0)); + _fragColor = vec4(color, 0.0); } diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh index bf0100d0d3..a6a6a6b1ac 100644 --- a/libraries/render-utils/src/DeferredBufferRead.slh +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -79,10 +79,7 @@ DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { unpackModeMetallic(diffuseVal.w, frag.mode, frag.metallic); frag.obscurance = min(specularVal.w, frag.obscurance); - - float check = float(frag.mode == FRAG_MODE_SCATTERING); - frag.scattering = check * specularVal.x; - + frag.scattering = float(frag.mode == FRAG_MODE_SCATTERING) * specularVal.x; frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz); return frag; @@ -121,10 +118,10 @@ DeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) { vec4 unpackDeferredPosition(float depthValue, vec2 texcoord) { float check = float(isStereo()); - float check2 = float(texcoord.x > 0.5); - texcoord.x -= check * check2 * 0.5; - int side = int(check * check2); - texcoord.x *= check * 2.0 + (1.0 - check) * 1.0; + float check2 = check * float(texcoord.x > 0.5); + texcoord.x -= check2 * 0.5; + int side = int(check2); + texcoord.x *= mix(1.0, 2.0, check); return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0); } @@ -137,11 +134,13 @@ vec4 unpackDeferredPositionFromZdb(vec2 texcoord) { vec4 unpackDeferredPositionFromZeye(vec2 texcoord) { float Zeye = -texture(linearZeyeMap, texcoord).x; + float check = float(isStereo()); - float check2 = float(texcoord.x > 0.5); - texcoord.x -= check * check2 * 0.5; - int side = int(check * check2); - texcoord.x *= check * 2.0 + (1.0 - check) * 1.0; + float check2 = check * float(texcoord.x > 0.5); + texcoord.x -= check2 * 0.5; + int side = int(check2); + texcoord.x *= mix(1.0, 2.0, check); + return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0); } diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index a531affd85..fe2f518665 100644 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -34,9 +34,9 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness } float check = float(scattering > 0.0); - _fragColor0 = vec4(albedo, check * packScatteringMetallic(metallic) + (1.0 - check) * packShadedMetallic(metallic)); + _fragColor0 = vec4(albedo, mix(packShadedMetallic(metallic), packScatteringMetallic(metallic), check)); _fragColor1 = vec4(packNormal(normal), clamp(roughness, 0.0, 1.0)); - _fragColor2 = vec4(check * vec3(scattering) + (1.0 - check) * emissive, occlusion); + _fragColor2 = vec4(mix(emissive, vec3(scattering), check), occlusion); _fragColor3 = vec4(isEmissiveEnabled() * emissive, 1.0); } diff --git a/libraries/render-utils/src/DeferredTransform.slh b/libraries/render-utils/src/DeferredTransform.slh index 3ec763efe2..434cc18c1f 100644 --- a/libraries/render-utils/src/DeferredTransform.slh +++ b/libraries/render-utils/src/DeferredTransform.slh @@ -126,8 +126,7 @@ vec2 getSideImageSize(int resolutionLevel) { ivec4 getStereoSideInfo(int xPos, int resolutionLevel) { int sideWidth = int(getStereoSideWidth(resolutionLevel)); - int check = int(xPos < sideWidth); - return ivec4((1 - check) * ivec2(1, sideWidth), sideWidth, isStereo()); + return ivec4((1 - int(xPos < sideWidth)) * ivec2(1, sideWidth), sideWidth, isStereo()); } float evalZeyeFromZdb(float depth) { diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 6770f53200..1ff0e2c01d 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -86,9 +86,7 @@ float evalFadeGradient(FadeObjectParams params, vec3 position) { float evalFadeAlpha(FadeObjectParams params, vec3 position) { float alpha = evalFadeGradient(params, position) - params.threshold; - - float check = float(fadeParameters[params.category]._isInverted != 0); - alpha *= -check + (1.0 - check); + alpha *= mix(1.0, -1.0, float(fadeParameters[params.category]._isInverted != 0)); return alpha; } diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index 8d90b4c816..b64d4172c6 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -25,14 +25,13 @@ LAYOUT(binding=RENDER_UTILS_TEXTURE_HAZE_LINEAR_DEPTH) uniform sampler2D linearD vec4 unpackPositionFromZeye(vec2 texcoord) { float Zeye = -texture(linearDepthMap, texcoord).x; - int side = 0; - if (isStereo()) { - if (texcoord.x > 0.5) { - texcoord.x -= 0.5; - side = 1; - } - texcoord.x *= 2.0; - } + + float check = float(isStereo()); + float check2 = check * float(texcoord.x > 0.5); + texcoord.x -= check2 * 0.5; + int side = int(check2); + texcoord.x *= mix(1.0, 2.0, check); + return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0); } diff --git a/libraries/render-utils/src/Haze.slh b/libraries/render-utils/src/Haze.slh index f5795565cc..0bf1d5d689 100644 --- a/libraries/render-utils/src/Haze.slh +++ b/libraries/render-utils/src/Haze.slh @@ -64,9 +64,8 @@ vec3 computeHazeColorKeyLightAttenuation(vec3 color, vec3 lightDirectionWS, vec3 float height_95p = 2000.0; const float log_p_005 = log(0.05); - { - float check = float(hazeParams.hazeKeyLightAltitudeFactor > 0.0f); - height_95p = check * -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor + (1.0 - check) * height_95p; + if (hazeParams.hazeKeyLightAltitudeFactor > 0.0f) { + height_95p = -log_p_005 / hazeParams.hazeKeyLightAltitudeFactor; } // Note that we need the sine to be positive @@ -144,8 +143,7 @@ vec4 computeHazeColor(vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePosition float deltaHeight = fragPositionWS.y - eyeWorldHeight; float t = hazeParams.hazeHeightFactor * deltaHeight; if (abs(t) > EPSILON) { - float check = float(abs(deltaHeight) > slopeThreshold); - hazeIntegral *= check * (1.0 - exp(-t)) / t + (1.0 - check); + hazeIntegral *= mix(1.0, (1.0 - exp(-t)) / t, float(abs(deltaHeight) > slopeThreshold)); } vec3 hazeAmount = 1.0 - exp(-hazeIntegral); @@ -173,8 +171,7 @@ vec4 computeHazeColor(vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePosition float deltaHeight = fragPositionWS.y - eyeWorldHeight; float t = hazeParams.hazeHeightFactor * deltaHeight; if (abs(t) > EPSILON) { - float check = float(abs(deltaHeight) > slopeThreshold); - hazeIntegral *= check * (1.0 - exp(-t)) / t + (1.0 - check); + hazeIntegral *= mix(1.0, (1.0 - exp(-t)) / t, float(abs(deltaHeight) > slopeThreshold)); } float hazeAmount = 1.0 - exp(-hazeIntegral); @@ -186,8 +183,7 @@ vec4 computeHazeColor(vec3 fragPositionES, vec3 fragPositionWS, vec3 eyePosition // Mix with background at far range const float BLEND_DISTANCE = 27000.0f; vec4 outFragColor = potentialFragColor; - float check = float(distance > BLEND_DISTANCE); - outFragColor.a *= check * hazeParams.backgroundBlend + (1.0 - check); + outFragColor.a *= mix(1.0, hazeParams.backgroundBlend, float(distance > BLEND_DISTANCE)); return outFragColor; } diff --git a/libraries/render-utils/src/Highlight.slh b/libraries/render-utils/src/Highlight.slh index eee22ecb0a..85ff352207 100644 --- a/libraries/render-utils/src/Highlight.slh +++ b/libraries/render-utils/src/Highlight.slh @@ -45,9 +45,9 @@ void main(void) { highlightedDepth = -evalZeyeFromZdb(highlightedDepth); sceneDepth = -evalZeyeFromZdb(sceneDepth); - float check = float(sceneDepth < highlightedDepth); - outFragColor = check * vec4(params._fillOccludedColor, params._fillOccludedAlpha) + - (1.0 - check) * vec4(params._fillUnoccludedColor, params._fillUnoccludedAlpha); + outFragColor = mix(vec4(params._fillUnoccludedColor, params._fillUnoccludedAlpha), + vec4(params._fillOccludedColor, params._fillOccludedAlpha), + float(sceneDepth < highlightedDepth)); <@else@> discard; <@endif@> @@ -83,10 +83,7 @@ void main(void) { } } - { - float check = float(intensity > 0.0); - sumOutlineDepth = check * sumOutlineDepth + (1.0 - check) * FAR_Z; - } + sumOutlineDepth = mix(FAR_Z, sumOutlineDepth, float(intensity > 0.0)); intensity /= weight; if (intensity < OPACITY_EPSILON) { @@ -102,11 +99,9 @@ void main(void) { sceneDepth = -evalZeyeFromZdb(sceneDepth); // Are we occluded? - { - float check = float(sceneDepth < outlinedDepth); - outFragColor = check * vec4(params._outlineOccludedColor, intensity * params._outlineOccludedAlpha) + - (1.0 - check) * vec4(params._outlineUnoccludedColor, intensity * params._outlineUnoccludedAlpha); - } + outFragColor = mix(vec4(params._outlineUnoccludedColor, intensity * params._outlineUnoccludedAlpha), + vec4(params._outlineOccludedColor, intensity * params._outlineOccludedAlpha), + float(sceneDepth < outlinedDepth)); } } diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index 46eba68fff..df8ba001f5 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -83,8 +83,7 @@ int clusterGrid_getClusterLightId(int index, int offset) { return element; */ int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))]; - int check = int((elementIndex & 0x00000001) == 1); - return (check * (element >> 16) + (1 - check) * element) & 0x0000FFFF; + return int(mix(element, element >> 16, int((elementIndex & 0x00000001) == 1))) & 0x0000FFFF; } diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index be9d980062..476ca6284f 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -7,8 +7,12 @@ #ifdef __cplusplus # define _MIN glm::min +# define _MIX(x, y, a) glm::mix((float)x, (float)y, (float)a) +# define _ABS(x) (int)fabsf() #else # define _MIN min +# define _MIX mix +# define _ABS abs #endif float frustumGrid_depthRampGridToVolume(float ngrid) { @@ -124,7 +128,7 @@ ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { // make sure the frontEyePos is always in the front to eval the grid pos correctly vec3 frontEyePos = eyePos; - frontEyePos.z = -abs(eyePos.z); + frontEyePos.z = -_ABS(eyePos.z); vec3 volumePos = frustumGrid_eyeToVolume(frontEyePos, frustumGrid.eyeToGridProj, frustumGrid.rangeNear, frustumGrid.rangeFar); @@ -147,8 +151,7 @@ ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { int frustumGrid_eyeToClusterDirH(vec3 eyeDir) { if (eyeDir.z >= 0.0f) { - int check = int(eyeDir.x > 0.0f); - return check * frustumGrid.dims.x + (check - 1); + return int(_MIX(-1, frustumGrid.dims.x, int(eyeDir.x > 0.0f))); } float eyeDepth = -eyeDir.z; @@ -162,8 +165,7 @@ int frustumGrid_eyeToClusterDirH(vec3 eyeDir) { int frustumGrid_eyeToClusterDirV(vec3 eyeDir) { if (eyeDir.z >= 0.0f) { - int check = int(eyeDir.y > 0.0f); - return check * frustumGrid.dims.y + (check - 1); + return int(_MIX(-1, frustumGrid.dims.y, int(eyeDir.y > 0.0f))); } float eyeDepth = -eyeDir.z; diff --git a/libraries/render-utils/src/LightPoint.slh b/libraries/render-utils/src/LightPoint.slh index f5cda3d9d4..7c59cf85ef 100644 --- a/libraries/render-utils/src/LightPoint.slh +++ b/libraries/render-utils/src/LightPoint.slh @@ -39,14 +39,11 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, lightEnergy *= isPointEnabled(); diffuse *= lightEnergy * isDiffuseEnabled(); specular *= lightEnergy * isSpecularEnabled(); - - { - // Show edges - float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0); - float check = float(isShowLightContour() > 0.0 && edge < 1.0); - float edgeCoord = exp2(-8.0 * edge * edge); - diffuse = check * vec3(edgeCoord * edgeCoord * getLightColor(light)) + (1.0 - check) * diffuse; - } + + // Show edges + float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0); + float edgeCoord = exp2(-8.0 * edge * edge); + diffuse = mix(diffuse, vec3(edgeCoord * edgeCoord * getLightColor(light)), float(isShowLightContour() > 0.0 && edge < 1.0)); } <@endfunc@> @@ -59,13 +56,10 @@ bool evalLightPointEdge(out vec3 color, Light light, vec4 fragLightDirLen, vec3 float fragLightDistance = fragLightDirLen.w; vec3 fragLightDir = fragLightDirLen.xyz; + // Show edges float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0); - { - // Show edges - float check = float(edge < 1.0); - float edgeCoord = exp2(-8.0 * edge * edge); - color = check * vec3(edgeCoord * edgeCoord * getLightColor(light)) + (1.0 - check) * color; - } + float edgeCoord = exp2(-8.0 * edge * edge); + color = mix(color, vec3(edgeCoord * edgeCoord * getLightColor(light)), float(edge < 1.0)); return (edge < 1.0); } diff --git a/libraries/render-utils/src/LightSpot.slh b/libraries/render-utils/src/LightSpot.slh index 395fe892e7..799021c459 100644 --- a/libraries/render-utils/src/LightSpot.slh +++ b/libraries/render-utils/src/LightSpot.slh @@ -40,17 +40,14 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light, lightEnergy *= isSpotEnabled(); diffuse *= lightEnergy * isDiffuseEnabled(); specular *= lightEnergy * isSpecularEnabled(); - - { - // Show edges - float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance); - float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume)); - float edgeDist = min(edgeDistR, edgeDistS); - float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0); - float check = float(isShowLightContour() > 0.0 && edge < 1.0); - float edgeCoord = exp2(-8.0 * edge * edge); - diffuse = check * vec3(edgeCoord * edgeCoord * getLightColor(light)) + (1.0 - check) * diffuse; - } + + // Show edges + float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance); + float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume)); + float edgeDist = min(edgeDistR, edgeDistS); + float edge = abs(2.0 * (edgeDist * 10.0) - 1.0); + float edgeCoord = exp2(-8.0 * edge * edge); + diffuse = mix(diffuse, vec3(edgeCoord * edgeCoord * getLightColor(light)), float(isShowLightContour() > 0.0 && edge < 1.0)); } <@endfunc@> @@ -62,16 +59,13 @@ bool evalLightSpotEdge(out vec3 color, Light light, vec4 fragLightDirLen, float float fragLightDistance = fragLightDirLen.w; vec3 fragLightDir = fragLightDirLen.xyz; + // Show edges float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance); float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume)); float edgeDist = min(edgeDistR, edgeDistS); - float edge = abs(2.0 * (edgeDist / (0.1)) - 1.0); - { - // Show edges - float check = float(edge < 1.0); - float edgeCoord = exp2(-8.0 * edge * edge); - color = check * vec3(edgeCoord * edgeCoord * getLightColor(light)) + (1.0 - check) * color; - } + float edge = abs(2.0 * (edgeDist * 10.0) - 1.0); + float edgeCoord = exp2(-8.0 * edge * edge); + color = mix(color, vec3(edgeCoord * edgeCoord * getLightColor(light)), float(edge < 1.0)); return (edge < 1.0); } diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index 10922350ed..b503844554 100644 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -115,22 +115,10 @@ float evalShadowAttenuation(vec3 worldLightDir, vec4 worldPosition, float viewDe isPixelOnCascade.z = isShadowCascadeProjectedOnPixel(cascadeShadowCoords[2]); isPixelOnCascade.w = isShadowCascadeProjectedOnPixel(cascadeShadowCoords[3]); - { - float check = float(isPixelOnCascade.x); - cascadeAttenuations.x = check * evalShadowCascadeAttenuation(0, offsets, cascadeShadowCoords[0], oneMinusNdotL) + (1.0 - check); - } - { - float check = float(isPixelOnCascade.y); - cascadeAttenuations.y = check * evalShadowCascadeAttenuation(1, offsets, cascadeShadowCoords[1], oneMinusNdotL) + (1.0 - check); - } - { - float check = float(isPixelOnCascade.z); - cascadeAttenuations.z = check * evalShadowCascadeAttenuation(2, offsets, cascadeShadowCoords[2], oneMinusNdotL) + (1.0 - check); - } - { - float check = float(isPixelOnCascade.w); - cascadeAttenuations.w = check * evalShadowCascadeAttenuation(3, offsets, cascadeShadowCoords[3], oneMinusNdotL) + (1.0 - check); - } + cascadeAttenuations.x = mix(1.0, evalShadowCascadeAttenuation(0, offsets, cascadeShadowCoords[0], oneMinusNdotL), float(isPixelOnCascade.x)); + cascadeAttenuations.y = mix(1.0, evalShadowCascadeAttenuation(1, offsets, cascadeShadowCoords[1], oneMinusNdotL), float(isPixelOnCascade.y)); + cascadeAttenuations.z = mix(1.0, evalShadowCascadeAttenuation(2, offsets, cascadeShadowCoords[2], oneMinusNdotL), float(isPixelOnCascade.z)); + cascadeAttenuations.w = mix(1.0, evalShadowCascadeAttenuation(3, offsets, cascadeShadowCoords[3], oneMinusNdotL), float(isPixelOnCascade.w)); cascadeWeights.x = evalShadowCascadeWeight(cascadeShadowCoords[0]); cascadeWeights.y = evalShadowCascadeWeight(cascadeShadowCoords[1]); diff --git a/libraries/render-utils/src/Skinning.slh b/libraries/render-utils/src/Skinning.slh index 63246e85a1..30d5efd64e 100644 --- a/libraries/render-utils/src/Skinning.slh +++ b/libraries/render-utils/src/Skinning.slh @@ -81,9 +81,7 @@ void evalSkinning(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPositio // to ensure that we rotate along the shortest arc, reverse dual quaternions with negative polarity. float dqClusterWeight = clusterWeight; - if (dot(real, polarityReference) < 0.0) { - dqClusterWeight = -clusterWeight; - } + dqClusterWeight *= mix(1.0, -1.0, float(dot(real, polarityReference) < 0.0)); sAccum += scale * clusterWeight; rAccum += real * dqClusterWeight; @@ -102,12 +100,11 @@ void evalSkinning(ivec4 skinClusterIndex, vec4 skinClusterWeight, vec4 inPositio // sAccum.w indicates the amount of cauterization for this vertex. // 0 indicates no cauterization and 1 indicates full cauterization. // TODO: make this cauterization smoother or implement full dual-quaternion scale support. - const float CAUTERIZATION_THRESHOLD = 0.1; - if (sAccum.w > CAUTERIZATION_THRESHOLD) { - skinnedPosition = cAccum; - } else { - sAccum.w = 1.0; - skinnedPosition = m * (sAccum * inPosition); + { + const float CAUTERIZATION_THRESHOLD = 0.1; + float check = float(sAccum.w > CAUTERIZATION_THRESHOLD); + sAccum.w = mix(1.0, sAccum.w, check); + skinnedPosition = mix(m * (sAccum * inPosition), cAccum, check); } <@if USE_NORMAL@> diff --git a/libraries/render-utils/src/SubsurfaceScattering.slh b/libraries/render-utils/src/SubsurfaceScattering.slh index 66b3ab1ea0..b4981110f2 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.slh +++ b/libraries/render-utils/src/SubsurfaceScattering.slh @@ -82,8 +82,6 @@ vec3 integrate(float cosTheta, float skinRadius) { while (a <= (_PI)) { float sampleAngle = theta + a; float diffuse = clamp(cos(sampleAngle), 0.0, 1.0); - //if (diffuse < 0.0) diffuse = 0.0; - //if (diffuse > 1.0) diffuse = 1.0; // Distance. float sampleDist = abs(2.0 * skinRadius * sin(a * 0.5)); @@ -180,7 +178,8 @@ vec3 evalSkinBRDF(vec3 lightDir, vec3 normal, vec3 midNormal, vec3 lowNormal, fl return lowNormal * 0.5 + vec3(0.5); } if (showCurvature()) { - return (curvature > 0.0 ? vec3(curvature, 0.0, 0.0) : vec3(0.0, 0.0, -curvature)); + float check = float(curvature > 0.0); + return vec3(check * curvature, 0.0, (1.0 - check) * -curvature); } vec3 bentNdotL = evalScatteringBentNdotL(normal, midNormal, lowNormal, lightDir); diff --git a/libraries/render-utils/src/deferred_light_limited.slv b/libraries/render-utils/src/deferred_light_limited.slv index 1c835aacf7..0126d54664 100644 --- a/libraries/render-utils/src/deferred_light_limited.slv +++ b/libraries/render-utils/src/deferred_light_limited.slv @@ -37,9 +37,7 @@ void main(void) { #ifdef GPU_TRANSFORM_IS_STEREO #ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN #else - if (cam_isStereo()) { - projected.x = 0.5 * (projected.x + cam_getStereoSide()); - } + projected.x = mix(projected.x, 0.5 * (projected.x + cam_getStereoSide()), float(cam_isStereo())); #endif #endif _texCoord01 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; @@ -66,9 +64,7 @@ void main(void) { #ifdef GPU_TRANSFORM_IS_STEREO #ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN #else - if (cam_isStereo()) { - _texCoord01.x = 0.5 * (_texCoord01.x + cam_getStereoSide()); - } + _texCoord01.x = mix(_texCoord01.x, 0.5 * (_texCoord01.x + cam_getStereoSide()), float(cam_isStereo())); #endif #endif diff --git a/libraries/render-utils/src/deferred_light_point.slv b/libraries/render-utils/src/deferred_light_point.slv index 3e6329be83..c77ead439c 100644 --- a/libraries/render-utils/src/deferred_light_point.slv +++ b/libraries/render-utils/src/deferred_light_point.slv @@ -47,8 +47,6 @@ void main(void) { vec4 projected = gl_Position / gl_Position.w; projected.xy = (projected.xy + 1.0) * 0.5; - if (cam_isStereo()) { - projected.x = 0.5 * (projected.x + cam_getStereoSide()); - } + projected.x = mix(projected.x, 0.5 * (projected.x + cam_getStereoSide()), float(cam_isStereo())); _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; } diff --git a/libraries/render-utils/src/deferred_light_spot.slv b/libraries/render-utils/src/deferred_light_spot.slv index 0370acc6bc..332bb96167 100644 --- a/libraries/render-utils/src/deferred_light_spot.slv +++ b/libraries/render-utils/src/deferred_light_spot.slv @@ -60,9 +60,7 @@ void main(void) { #ifdef GPU_TRANSFORM_IS_STEREO #ifdef GPU_TRANSFORM_STEREO_SPLIT_SCREEN #else - if (cam_isStereo()) { - projected.x = 0.5 * (projected.x + cam_getStereoSide()); - } + projected.x = mix(projected.x, 0.5 * (projected.x + cam_getStereoSide()), float(cam_isStereo())); #endif #endif _texCoord0 = vec4(projected.xy, 0.0, 1.0) * gl_Position.w; diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index 15d00f713e..b1cfc26c66 100644 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -33,16 +33,15 @@ void main(void) { float shadowAttenuation = 1.0; - if (frag.mode == FRAG_MODE_UNLIT) { - discard; - } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { + if (frag.mode == FRAG_MODE_UNLIT || frag.mode == FRAG_MODE_LIGHTMAPPED) { discard; } else { vec4 midNormalCurvature = vec4(0); vec4 lowNormalCurvature = vec4(0); - if (frag.mode == FRAG_MODE_SCATTERING) { - unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature); - } + unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature); + float check = float(frag.mode == FRAG_MODE_SCATTERING); + midNormalCurvature = check * midNormalCurvature; + lowNormalCurvature = check * lowNormalCurvature; vec3 color = evalAmbientSphereGlobalColor( getViewInverse(), diff --git a/libraries/render-utils/src/directional_ambient_light_shadow.slf b/libraries/render-utils/src/directional_ambient_light_shadow.slf index d6cdf78f19..6b9fb80232 100644 --- a/libraries/render-utils/src/directional_ambient_light_shadow.slf +++ b/libraries/render-utils/src/directional_ambient_light_shadow.slf @@ -35,16 +35,16 @@ void main(void) { vec3 worldLightDirection = getLightDirection(shadowLight); float shadowAttenuation = evalShadowAttenuation(worldLightDirection, worldPos, -viewPos.z, frag.normal); - if (frag.mode == FRAG_MODE_UNLIT) { - discard; - } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { + if (frag.mode == FRAG_MODE_UNLIT || frag.mode == FRAG_MODE_LIGHTMAPPED) { discard; } else { vec4 midNormalCurvature = vec4(0); vec4 lowNormalCurvature = vec4(0); - if (frag.mode == FRAG_MODE_SCATTERING) { - unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature); - } + unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature); + float check = float(frag.mode == FRAG_MODE_SCATTERING); + midNormalCurvature = check * midNormalCurvature; + lowNormalCurvature = check * lowNormalCurvature; + vec3 color = evalAmbientSphereGlobalColor( getViewInverse(), shadowAttenuation, diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index b27d759dd4..b820b3d17f 100644 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -31,16 +31,16 @@ void main(void) { float shadowAttenuation = 1.0; // Light mapped or not ? - if (frag.mode == FRAG_MODE_UNLIT) { - discard; - } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { + if (frag.mode == FRAG_MODE_UNLIT || frag.mode == FRAG_MODE_LIGHTMAPPED) { discard; } else { vec4 midNormalCurvature = vec4(0); vec4 lowNormalCurvature = vec4(0); - if (frag.mode == FRAG_MODE_SCATTERING) { - unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature); - } + unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature); + float check = float(frag.mode == FRAG_MODE_SCATTERING); + midNormalCurvature = check * midNormalCurvature; + lowNormalCurvature = check * lowNormalCurvature; + vec3 color = evalSkyboxGlobalColor( getViewInverse(), shadowAttenuation, diff --git a/libraries/render-utils/src/directional_skybox_light_shadow.slf b/libraries/render-utils/src/directional_skybox_light_shadow.slf index 292f7348e3..8716d60d54 100644 --- a/libraries/render-utils/src/directional_skybox_light_shadow.slf +++ b/libraries/render-utils/src/directional_skybox_light_shadow.slf @@ -36,16 +36,16 @@ void main(void) { float shadowAttenuation = evalShadowAttenuation(worldLightDirection, worldPos, -viewPos.z, frag.normal); // Light mapped or not ? - if (frag.mode == FRAG_MODE_UNLIT) { - discard; - } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { + if (frag.mode == FRAG_MODE_UNLIT || frag.mode == FRAG_MODE_LIGHTMAPPED) { discard; } else { vec4 midNormalCurvature = vec4(0); vec4 lowNormalCurvature = vec4(0); - if (frag.mode == FRAG_MODE_SCATTERING) { - unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature); - } + unpackMidLowNormalCurvature(_texCoord0, midNormalCurvature, lowNormalCurvature); + float check = float(frag.mode == FRAG_MODE_SCATTERING); + midNormalCurvature = check * midNormalCurvature; + lowNormalCurvature = check * lowNormalCurvature; + vec3 color = evalSkyboxGlobalColor( getViewInverse(), shadowAttenuation, diff --git a/libraries/render-utils/src/drawWorkloadProxy.slv b/libraries/render-utils/src/drawWorkloadProxy.slv index 7a01702107..9dfcf8415c 100644 --- a/libraries/render-utils/src/drawWorkloadProxy.slv +++ b/libraries/render-utils/src/drawWorkloadProxy.slv @@ -62,7 +62,5 @@ void main(void) { varColor = vec4(REGION_COLOR[region].xyz, proxy.sphere.w); - if (region == 4) { - gl_Position = vec4(0.0); - } + gl_Position = mix(gl_Position, vec4(0.0), float(region == 4)); } diff --git a/libraries/render-utils/src/forward_model_unlit.slf b/libraries/render-utils/src/forward_model_unlit.slf index 19b40d884c..fb6c94a3f2 100644 --- a/libraries/render-utils/src/forward_model_unlit.slf +++ b/libraries/render-utils/src/forward_model_unlit.slf @@ -40,8 +40,5 @@ void main(void) { <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; albedo *= _color.rgb; - if (opacity != 1.0) { - discard; - } _fragColor0 = vec4(albedo * isUnlitEnabled(), 1.0); } diff --git a/libraries/render-utils/src/glowLine.slv b/libraries/render-utils/src/glowLine.slv index 167aeb8c9e..609082878b 100644 --- a/libraries/render-utils/src/glowLine.slv +++ b/libraries/render-utils/src/glowLine.slv @@ -53,13 +53,9 @@ void main(void) { // Add or subtract the orthogonal vector based on a different vertex ID // calculation - if (gl_VertexID < 2) { - distanceFromCenter = -1.0; - eye.xyz -= orthogonal; - } else { - distanceFromCenter = 1.0; - eye.xyz += orthogonal; - } + float check = float(gl_VertexID < 2); + distanceFromCenter = mix(1.0, -1.0, check); + eye.xyz += mix(orthogonal, -orthogonal, check); // Finally, put the eyespace vertex into clip space <$transformEyeToClipPos(cam, eye, gl_Position)$> diff --git a/libraries/render-utils/src/grid.slf b/libraries/render-utils/src/grid.slf index 8e9b35dace..408a9ca190 100644 --- a/libraries/render-utils/src/grid.slf +++ b/libraries/render-utils/src/grid.slf @@ -34,12 +34,10 @@ layout(location=0) out vec4 outFragColor; void main(void) { Grid grid = getGrid(); - float alpha; - if (grid.edge.z == 0.0) { - alpha = paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy); - } else { - alpha = paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge); - } + float alpha = mix(paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge), + paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy), + float(grid.edge.z == 0.0)); + if (alpha == 0.0) { discard; } diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slf b/libraries/render-utils/src/lightClusters_drawClusterContent.slf index 27cb838566..80013bc3cc 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slf @@ -90,6 +90,6 @@ void main(void) { numLightTouching++; } - _fragColor = vec4(colorRamp(1.0 - (float(numLightTouching) / 12.0f)), (numLightTouching > 0 ? 0.5 + 0.5 * numLightsScale : 0.0)); + _fragColor = vec4(colorRamp(1.0 - (float(numLightTouching) / 12.0f)), float(numLightTouching > 0) * (0.5 + 0.5 * numLightsScale)); } diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slv b/libraries/render-utils/src/lightClusters_drawClusterContent.slv index 1303cf3926..51718e6d8f 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slv +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slv @@ -69,5 +69,5 @@ void main(void) { TransformCamera cam = getTransformCamera(); <$transformWorldToClipPos(cam, worldPos, gl_Position)$> - varColor = vec4(colorWheel(fract(float(gpu_InstanceID()) / float(frustumGrid_numClusters()))), (numLights >0 ? 0.9 : 0.1)); + varColor = vec4(colorWheel(fract(float(gpu_InstanceID()) / float(frustumGrid_numClusters()))), mix(0.1, 0.9, float(numLights > 0))); } \ No newline at end of file diff --git a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf index abbd86dd70..0e3f8a5ea5 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf +++ b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slf @@ -62,12 +62,10 @@ void main(void) { float relClusterId = float(clusterPos.z * summedDims.x + clusterPos.y * summedDims.y + clusterPos.x) / float(frustumGrid_numClusters()); - if (relClusterId < 0.0) { - _fragColor = vec4(0.0); - } else if (relClusterId >= 1.0) { - _fragColor = vec4(vec3(1.0), 0.2); - } else { - _fragColor = vec4(colorWheel(fract(relClusterId)), (numLights > 0 ? 0.05 + 0.95 * numLightsScale : 0.0)); - } + _fragColor = mix(mix(vec4(colorWheel(fract(relClusterId)), float(numLights > 0) * (0.05 + 0.95 * numLightsScale)), + vec4(vec3(1.0), 0.2), + float(relClusterId >= 1.0)), + vec4(0.0), + float(relClusterId < 0.0)); } diff --git a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slv b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slv index d35c7cb20b..a5c037cc7a 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slv +++ b/libraries/render-utils/src/lightClusters_drawClusterFromDepth.slv @@ -62,5 +62,5 @@ void main(void) { TransformCamera cam = getTransformCamera(); <$transformWorldToClipPos(cam, worldPos, gl_Position)$> - varColor = vec4(colorWheel(fract(float(gpu_InstanceID()) / float(frustumGrid_numClusters()))), 0.9); + varColor = vec4(colorWheel(fract(float(gpu_InstanceID()) / float(frustumGrid_numClusters()))), 0.9); } \ No newline at end of file diff --git a/libraries/render-utils/src/lightClusters_drawGrid.slv b/libraries/render-utils/src/lightClusters_drawGrid.slv index c4aff45beb..8d557d01c8 100644 --- a/libraries/render-utils/src/lightClusters_drawGrid.slv +++ b/libraries/render-utils/src/lightClusters_drawGrid.slv @@ -69,5 +69,5 @@ void main(void) { TransformCamera cam = getTransformCamera(); <$transformWorldToClipPos(cam, worldPos, gl_Position)$> - varColor = vec4(colorWheel(fract(float(gpu_InstanceID()) / float(frustumGrid_numClusters()))), (numLights > 0 ? 0.9 : 0.0)); + varColor = vec4(colorWheel(fract(float(gpu_InstanceID()) / float(frustumGrid_numClusters()))), float(numLights > 0) * 0.9); } \ No newline at end of file diff --git a/libraries/render-utils/src/local_lights_drawOutline.slf b/libraries/render-utils/src/local_lights_drawOutline.slf index fc1d416f96..a2b4cc1d10 100644 --- a/libraries/render-utils/src/local_lights_drawOutline.slf +++ b/libraries/render-utils/src/local_lights_drawOutline.slf @@ -96,9 +96,8 @@ void main(void) { vec3 fragLightDir = fragLightDirLen.xyz; vec3 color = vec3(0.0); - if (evalLightPointEdge(color, light, fragLightDirLen, fragEyeDir)) { - _fragColor.rgb += color; - } + float check = float(evalLightPointEdge(color, light, fragLightDirLen, fragEyeDir)); + _fragColor.rgb += check * color; } for (int i = cluster.x; i < numLights; i++) { @@ -130,10 +129,8 @@ void main(void) { numLightTouching++; vec3 color = vec3(0.0); - - if (evalLightSpotEdge(color, light, fragLightDirLen, cosSpotAngle, fragEyeDir)) { - _fragColor.rgb += color; - } + float check = float(evalLightSpotEdge(color, light, fragLightDirLen, cosSpotAngle, fragEyeDir)); + _fragColor.rgb += check * color; } } diff --git a/libraries/render-utils/src/parabola.slv b/libraries/render-utils/src/parabola.slv index 53dfc75cfe..f220c656aa 100644 --- a/libraries/render-utils/src/parabola.slv +++ b/libraries/render-utils/src/parabola.slv @@ -48,11 +48,8 @@ void main(void) { } else { normal = vec4(normalize(cross(_parabolaData.velocity, _parabolaData.acceleration)), 0); } - if (gl_VertexID % 2 == 0) { - pos += 0.5 * _parabolaData.width * normal; - } else { - pos -= 0.5 * _parabolaData.width * normal; - } + + pos += 0.5 * _parabolaData.width * normal * mix(-1.0, 1.0, float(gl_VertexID % 2 == 0)); <$transformModelToClipPos(cam, obj, pos, gl_Position)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/sdf_text3D.slf b/libraries/render-utils/src/sdf_text3D.slf index 35e670eef8..b070fc44cf 100644 --- a/libraries/render-utils/src/sdf_text3D.slf +++ b/libraries/render-utils/src/sdf_text3D.slf @@ -39,13 +39,8 @@ const float taaBias = pow(2.0, TAA_TEXTURE_LOD_BIAS); float evalSDF(vec2 texCoord) { // retrieve signed distance float sdf = textureLod(Font, texCoord, TAA_TEXTURE_LOD_BIAS).g; - if (params.outline.x > 0.0) { - if (sdf > interiorCutoff) { - sdf = 1.0 - sdf; - } else { - sdf += outlineExpansion; - } - } + sdf = mix(sdf, mix(sdf + outlineExpansion, 1.0 - sdf, float(sdf > interiorCutoff)), float(params.outline.x > 0.0)); + // Rely on TAA for anti-aliasing return step(0.5, sdf); } @@ -57,16 +52,11 @@ void main() { // Perform 4x supersampling for anisotropic filtering float a; a = evalSDF(_texCoord0); - a += evalSDF(_texCoord0+dxTexCoord); - a += evalSDF(_texCoord0+dyTexCoord); - a += evalSDF(_texCoord0+dxTexCoord+dyTexCoord); + a += evalSDF(_texCoord0 + dxTexCoord); + a += evalSDF(_texCoord0 + dyTexCoord); + a += evalSDF(_texCoord0 + dxTexCoord + dyTexCoord); a *= 0.25; - // discard if invisible - if (a < 0.01) { - discard; - } - packDeferredFragment( normalize(_normalWS), a * params.color.a, diff --git a/libraries/render-utils/src/sdf_text3D_transparent.slf b/libraries/render-utils/src/sdf_text3D_transparent.slf index 6e271e1463..ae5f10a5fd 100644 --- a/libraries/render-utils/src/sdf_text3D_transparent.slf +++ b/libraries/render-utils/src/sdf_text3D_transparent.slf @@ -30,31 +30,32 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord0 _texCoord01.xy #define _texCoord1 _texCoord01.zw -const float gamma = 2.2; -const float smoothing = 32.0; +#define TAA_TEXTURE_LOD_BIAS -3.0 + const float interiorCutoff = 0.8; const float outlineExpansion = 0.2; +const float taaBias = pow(2.0, TAA_TEXTURE_LOD_BIAS); + +float evalSDF(vec2 texCoord) { + // retrieve signed distance + float sdf = textureLod(Font, texCoord, TAA_TEXTURE_LOD_BIAS).g; + sdf = mix(sdf, mix(sdf + outlineExpansion, 1.0 - sdf, float(sdf > interiorCutoff)), float(params.outline.x > 0.0)); + + // Rely on TAA for anti-aliasing + return step(0.5, sdf); +} void main() { - // retrieve signed distance - float sdf = texture(Font, _texCoord0).g; - if (params.outline.x > 0.0) { - if (sdf > interiorCutoff) { - sdf = 1.0 - sdf; - } else { - sdf += outlineExpansion; - } - } - // perform adaptive anti-aliasing of the edges - // The larger we're rendering, the less anti-aliasing we need - float s = smoothing * length(fwidth(_texCoord0)); - float w = clamp(s, 0.0, 0.5); - float a = smoothstep(0.5 - w, 0.5 + w, sdf); - - // discard if invisible - if (a < 0.01) { - discard; - } + vec2 dxTexCoord = dFdx(_texCoord0) * 0.5 * taaBias; + vec2 dyTexCoord = dFdy(_texCoord0) * 0.5 * taaBias; + + // Perform 4x supersampling for anisotropic filtering + float a; + a = evalSDF(_texCoord0); + a += evalSDF(_texCoord0 + dxTexCoord); + a += evalSDF(_texCoord0 + dyTexCoord); + a += evalSDF(_texCoord0 + dxTexCoord + dyTexCoord); + a *= 0.25; packDeferredFragmentTranslucent( normalize(_normalWS), diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 039dbc4278..2107ec1272 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -54,7 +54,7 @@ void main(void) { vec3 specular = DEFAULT_SPECULAR; float shininess = DEFAULT_SHININESS; float emissiveAmount = 0.0; - + #ifdef PROCEDURAL #ifdef PROCEDURAL_V1 diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index b308b57345..9494edb890 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -12,6 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Color.slh@> <@include DeferredBufferWrite.slh@> <@include render-utils/ShaderConstants.h@> @@ -28,11 +29,13 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); + texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel.rgb *= _color.rgb; packDeferredFragment( normalize(_normalWS), 1.0, - _color.rgb * texel.rgb, + texel.rgb, DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, diff --git a/libraries/render-utils/src/simple_textured_fade.slf b/libraries/render-utils/src/simple_textured_fade.slf index ad2b636708..f8ca72c7b5 100644 --- a/libraries/render-utils/src/simple_textured_fade.slf +++ b/libraries/render-utils/src/simple_textured_fade.slf @@ -39,27 +39,25 @@ void main(void) { <$fetchFadeObjectParamsInstanced(fadeParams)$> applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - + vec4 texel = texture(originalTexture, _texCoord0); - float colorAlpha = _color.a; - if (_color.a <= 0.0) { - texel = color_sRGBAToLinear(texel); - colorAlpha = -_color.a; - } + texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel.rgb *= _color.rgb; + texel.a = abs(_color.a); const float ALPHA_THRESHOLD = 0.999; - if (colorAlpha * texel.a < ALPHA_THRESHOLD) { + if (texel.a < ALPHA_THRESHOLD) { packDeferredFragmentTranslucent( normalize(_normalWS), - colorAlpha * texel.a, - _color.rgb * texel.rgb + fadeEmissive, + texel.a, + texel.rgb + fadeEmissive, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); } else { packDeferredFragment( normalize(_normalWS), 1.0, - _color.rgb * texel.rgb, + texel.rgb, DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE + fadeEmissive, diff --git a/libraries/render-utils/src/simple_textured_unlit.slf b/libraries/render-utils/src/simple_textured_unlit.slf index f33cb704dc..d57b72a521 100644 --- a/libraries/render-utils/src/simple_textured_unlit.slf +++ b/libraries/render-utils/src/simple_textured_unlit.slf @@ -28,25 +28,23 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; #define _texCoord1 _texCoord01.zw void main(void) { - vec4 texel = texture(originalTexture, _texCoord0.st); - float colorAlpha = _color.a; - if (_color.a <= 0.0) { - texel = color_sRGBAToLinear(texel); - colorAlpha = -_color.a; - } + vec4 texel = texture(originalTexture, _texCoord0); + texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel.rgb *= _color.rgb; + texel.a = abs(_color.a); const float ALPHA_THRESHOLD = 0.999; - if (colorAlpha * texel.a < ALPHA_THRESHOLD) { + if (texel.a < ALPHA_THRESHOLD) { packDeferredFragmentTranslucent( normalize(_normalWS), - colorAlpha * texel.a, - _color.rgb * texel.rgb, + texel.a, + texel.rgb, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); } else { packDeferredFragmentUnlit( normalize(_normalWS), 1.0, - _color.rgb * texel.rgb); + texel.rgb); } } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_unlit_fade.slf b/libraries/render-utils/src/simple_textured_unlit_fade.slf index 494920b363..2c0f4b005c 100644 --- a/libraries/render-utils/src/simple_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_textured_unlit_fade.slf @@ -40,25 +40,23 @@ void main(void) { <$fetchFadeObjectParamsInstanced(fadeParams)$> applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - vec4 texel = texture(originalTexture, _texCoord0.st); - float colorAlpha = _color.a; - if (_color.a <= 0.0) { - texel = color_sRGBAToLinear(texel); - colorAlpha = -_color.a; - } + vec4 texel = texture(originalTexture, _texCoord0); + texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel.rgb *= _color.rgb; + texel.a = abs(_color.a); const float ALPHA_THRESHOLD = 0.999; - if (colorAlpha * texel.a < ALPHA_THRESHOLD) { + if (texel.a < ALPHA_THRESHOLD) { packDeferredFragmentTranslucent( normalize(_normalWS), - colorAlpha * texel.a, - _color.rgb * texel.rgb+fadeEmissive, + texel.a, + texel.rgb + fadeEmissive, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); } else { packDeferredFragmentUnlit( normalize(_normalWS), 1.0, - _color.rgb * texel.rgb+fadeEmissive); + texel.rgb + fadeEmissive); } } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf index ef83914096..63214bd76b 100644 --- a/libraries/render-utils/src/simple_transparent_textured.slf +++ b/libraries/render-utils/src/simple_transparent_textured.slf @@ -12,6 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Color.slh@> <@include DeferredBufferWrite.slh@> <@include render-utils/ShaderConstants.h@> @@ -28,12 +29,14 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); - float colorAlpha = _color.a * texel.a; + texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel.rgb *= _color.rgb; + texel.a *= abs(_color.a); packDeferredFragmentTranslucent( normalize(_normalWS), - colorAlpha, - _color.rgb * texel.rgb, + texel.a, + texel.rgb, DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf index 5fac67e1d2..75a88dc581 100644 --- a/libraries/render-utils/src/simple_transparent_textured_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_fade.slf @@ -46,14 +46,10 @@ void main(void) { <$fetchFadeObjectParamsInstanced(fadeParams)$> applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - vec4 texel = texture(originalTexture, _texCoord0.st); - float opacity = _color.a; - if (_color.a <= 0.0) { - texel = color_sRGBAToLinear(texel); - opacity = -_color.a; - } - opacity *= texel.a; - vec3 albedo = _color.rgb * texel.rgb; + vec4 texel = texture(originalTexture, _texCoord0); + texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel.rgb *= _color.rgb; + texel.a *= abs(_color.a); vec3 fragPosition = _positionES.xyz; vec3 fragNormal = normalize(_normalWS); @@ -66,12 +62,11 @@ void main(void) { 1.0, fragPosition, fragNormal, - albedo, + texel.rgb, DEFAULT_FRESNEL, 0.0f, fadeEmissive, DEFAULT_ROUGHNESS, - opacity), - opacity); - + texel.a), + texel.a); } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit.slf b/libraries/render-utils/src/simple_transparent_textured_unlit.slf index bf3dbbdf88..3f4abfc730 100644 --- a/libraries/render-utils/src/simple_transparent_textured_unlit.slf +++ b/libraries/render-utils/src/simple_transparent_textured_unlit.slf @@ -27,11 +27,10 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; layout(location=0) out vec4 _fragColor0; void main(void) { - vec4 texel = texture(originalTexture, _texCoord0.st); - float colorAlpha = _color.a; - if (_color.a <= 0.0) { - texel = color_sRGBAToLinear(texel); - colorAlpha = -_color.a; - } - _fragColor0 = vec4(_color.rgb * texel.rgb, colorAlpha * texel.a); + vec4 texel = texture(originalTexture, _texCoord0); + texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel.rgb *= _color.rgb; + texel.a *= abs(_color.a); + + _fragColor0 = texel; } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf index 943f361ead..e46426ec7a 100644 --- a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf @@ -39,11 +39,10 @@ void main(void) { <$fetchFadeObjectParamsInstanced(fadeParams)$> applyFade(fadeParams, _positionWS.xyz, fadeEmissive); - vec4 texel = texture(originalTexture, _texCoord0.st); - float colorAlpha = _color.a; - if (_color.a <= 0.0) { - texel = color_sRGBAToLinear(texel); - colorAlpha = -_color.a; - } - _fragColor0 = vec4(_color.rgb * texel.rgb + fadeEmissive, colorAlpha * texel.a); + vec4 texel = texture(originalTexture, _texCoord0); + texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel.rgb *= _color.rgb; + texel.a *= abs(_color.a); + + _fragColor0 = vec4(texel.rgb + fadeEmissive, texel.a); } \ No newline at end of file diff --git a/libraries/render-utils/src/ssao.slh b/libraries/render-utils/src/ssao.slh index f0d522a41c..0f0fb65705 100644 --- a/libraries/render-utils/src/ssao.slh +++ b/libraries/render-utils/src/ssao.slh @@ -183,43 +183,24 @@ vec3 getTapLocationClamped(int sampleNumber, float spinAngle, float outerRadius, } bool redoTap = false; - if ((tapPos.x < 0.5)) { - tapPos.x = -tapPos.x; - redoTap = true; - } else if ((tapPos.x > imageSize.x - 0.5)) { - tapPos.x -= (imageSize.x - tapPos.x); - redoTap = true; + { + float check1 = float(tapPos.x < 0.5); + float check2 = (1.0 - check1) * float(tapPos.x > imageSize.x - 0.5); + tapPos.x = mix(tapPos.x, -tapPos.x, check1) - check2 * (imageSize.x - tapPos.x); + redoTap = (check1 > 0.0 || check2 > 0.0); } - if ((tapPos.y < 0.5)) { - tapPos.y = -tapPos.y; - redoTap = true; - } else if ((tapPos.y > imageSize.y - 0.5)) { - tapPos.y -= (imageSize.y - tapPos.y); - redoTap = true; - } -/* - if ((tapPos.x < 0.5)) { - tapPos.x = 0.5; - redoTap = true; - } else if ((tapPos.x > imageSize.x - 0.5)) { - tapPos.x = imageSize.x - 0.5; - redoTap = true; + { + float check1 = float(tapPos.y < 0.5); + float check2 = (1.0 - check1) * float(tapPos.y > imageSize.y - 0.5); + tapPos.y = mix(tapPos.y, -tapPos.y, check1) - check2 * (imageSize.y - tapPos.y); + redoTap = (check1 > 0.0 || check2 > 0.0); } - if ((tapPos.y < 0.5)) { - tapPos.y = 0.5; - redoTap = true; - } else if ((tapPos.y > imageSize.y - 0.5)) { - tapPos.y = imageSize.y - 0.5; - redoTap = true; - } -*/ - - if (redoTap) { - tap.xy = tapPos - pixelPos; - tap.z = length(tap.xy); - tap.z = 0.0; + { + float check = float(redoTap); + tap.xy = mix(tap.xy, tapPos - pixelPos, check); + tap.z = (1.0 - check) * tap.z; } return tap; diff --git a/libraries/render-utils/src/ssao_debugOcclusion.slf b/libraries/render-utils/src/ssao_debugOcclusion.slf index e15e52f448..43c3d15ece 100644 --- a/libraries/render-utils/src/ssao_debugOcclusion.slf +++ b/libraries/render-utils/src/ssao_debugOcclusion.slf @@ -40,9 +40,9 @@ void main(void) { vec2 imageSize = getSideImageSize(getResolutionLevel()); // In debug adjust the correct frag pixel based on base resolution - vec2 fragCoord = gl_FragCoord.xy; + vec2 fragCoord = gl_FragCoord.xy; if (getResolutionLevel() > 0) { - fragCoord /= float (1 << getResolutionLevel()); + fragCoord /= float(1 << getResolutionLevel()); } // Pixel Debugged @@ -90,10 +90,11 @@ void main(void) { // The occluding point in camera space vec2 fragToTap = vec2(ssC) + tap.xy - fragCoord.xy; - if (dot(fragToTap,fragToTap) < keepTapRadius) { - keep = true; - keepedMip = evalMipFromRadius(tap.z * float(doFetchMips())); - } + { + bool check = dot(fragToTap,fragToTap) < keepTapRadius; + keep = keep || check; + keepedMip = int(mix(keepedMip, evalMipFromRadius(tap.z * float(doFetchMips())), int(check))); + } vec3 tapUVZ = fetchTap(side, ssC, tap, imageSize); @@ -108,12 +109,8 @@ void main(void) { outFragColor = vec4(packOcclusionDepth(A, CSZToDephtKey(Cp.z)), 1.0); @@ -124,9 +121,5 @@ void main(void) { return; } - if (!keep) { - outFragColor = vec4(0.1); - } else { - outFragColor.rgb = colorWheel(float(keepedMip)/float(MAX_MIP_LEVEL)); - } + outFragColor = mix(vec4(0.1), vec4(colorWheel(float(keepedMip) / float(MAX_MIP_LEVEL)), outFragColor.a), float(keep)); } diff --git a/libraries/render-utils/src/ssao_makeOcclusion.slf b/libraries/render-utils/src/ssao_makeOcclusion.slf index 3934b9eddc..f437c94814 100644 --- a/libraries/render-utils/src/ssao_makeOcclusion.slf +++ b/libraries/render-utils/src/ssao_makeOcclusion.slf @@ -68,13 +68,8 @@ void main(void) { // KEEP IT for Debugging // Bilateral box-filter over a quad for free, respecting depth edges // (the difference that this makes is subtle) - if (abs(dFdx(Cp.z)) < 0.02) { - A -= dFdx(A) * (float(ssC.x & 1) - 0.5); - } - if (abs(dFdy(Cp.z)) < 0.02) { - A -= dFdy(A) * (float(ssC.y & 1) - 0.5); - } - + A -= float(abs(dFdx(Cp.z)) < 0.02) * dFdx(A) * (float(ssC.x & 1) - 0.5); + A -= float(abs(dFdy(Cp.z)) < 0.02) * dFdy(A) * (float(ssC.y & 1) - 0.5); outFragColor = vec4(packOcclusionDepth(A, CSZToDephtKey(Cp.z)), 1.0); diff --git a/libraries/render-utils/src/stencil_drawMask.slf b/libraries/render-utils/src/stencil_drawMask.slf index 5ba09a8264..2ae5853960 100644 --- a/libraries/render-utils/src/stencil_drawMask.slf +++ b/libraries/render-utils/src/stencil_drawMask.slf @@ -18,6 +18,9 @@ float aspectRatio = 0.95; void main(void) { vec2 pos = varTexCoord0 * 2.0 - vec2(1.0); - pos.x = aspectRatio * (pos.x * (pos.x > 0.0 ? 2.0 : -2.0) - 1.0); - if (1.0 - dot(pos.xy, pos.xy) > 0.0 ) discard; + pos.x = aspectRatio * (pos.x * mix(-2.0, 2.0, float(pos.x > 0.0)) - 1.0); + + if (1.0 - dot(pos.xy, pos.xy) > 0.0) { + discard; + } } diff --git a/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf b/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf index 877c31c23d..ac5907803c 100644 --- a/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf +++ b/libraries/render-utils/src/subsurfaceScattering_drawScattering.slf @@ -93,14 +93,14 @@ vec3 drawScatteringTableUV(vec2 cursor, vec2 texcoord) { vec3 color = vec3(0.0); bool keep = false; for (int c = 0; c < 3; c++) { - if (distance[c] > threshold) { - keep = true; - color[c] += 1.0; - } + bool check = distance[c] > threshold; + keep = keep || check; + color[c] += float(check); } - if (!keep) - discard; + if (!keep) { + discard; + } return color; } diff --git a/libraries/render-utils/src/surfaceGeometry_makeCurvature.slf b/libraries/render-utils/src/surfaceGeometry_makeCurvature.slf index 363fd0d4f8..433b3e97dc 100644 --- a/libraries/render-utils/src/surfaceGeometry_makeCurvature.slf +++ b/libraries/render-utils/src/surfaceGeometry_makeCurvature.slf @@ -67,11 +67,7 @@ vec3 getRawNormal(vec2 texcoord) { vec3 getWorldNormal(vec2 texcoord) { vec3 rawNormal = getRawNormal(texcoord); - if (isFullResolution()) { - return unpackNormal(rawNormal); - } else { - return normalize((rawNormal - vec3(0.5)) * 2.0); - } + return mix(normalize((rawNormal - vec3(0.5)) * 2.0), unpackNormal(rawNormal), float(isFullResolution())); } vec3 getWorldNormalDiff(vec2 texcoord, vec2 delta) { @@ -93,7 +89,7 @@ void main(void) { vec2 texcoordPos; ivec4 stereoSide; ivec2 framePixelPos = getPixelPosTexcoordPosAndSide(gl_FragCoord.xy, pixelPos, texcoordPos, stereoSide); - vec2 stereoSideClip = vec2(stereoSide.x, (isStereo() ? 0.5 : 1.0)); + vec2 stereoSideClip = vec2(stereoSide.x, mix(1.0, 0.5, float(isStereo()))); // Texcoord to fetch in the deferred texture are the exact UVs comming from vertex shader // sideToFrameTexcoord(stereoSideClip, texcoordPos); @@ -128,8 +124,8 @@ void main(void) { // Calculate dF/du and dF/dv vec2 viewportScale = perspectiveScale * getInvWidthHeight(); - vec2 du = vec2( viewportScale.x * (float(stereoSide.w) > 0.0 ? 0.5 : 1.0), 0.0f ); - vec2 dv = vec2( 0.0f, viewportScale.y ); + vec2 du = vec2(viewportScale.x * mix(1.0, 0.5, float(float(stereoSide.w) > 0.0)), 0.0); + vec2 dv = vec2( 0.0f, viewportScale.y); vec4 dFdu = vec4(getWorldNormalDiff(frameTexcoordPos, du), getEyeDepthDiff(frameTexcoordPos, du)); vec4 dFdv = vec4(getWorldNormalDiff(frameTexcoordPos, dv), getEyeDepthDiff(frameTexcoordPos, dv)); diff --git a/libraries/render-utils/src/taa.slf b/libraries/render-utils/src/taa.slf index a2b58d3050..25320179f5 100644 --- a/libraries/render-utils/src/taa.slf +++ b/libraries/render-utils/src/taa.slf @@ -35,17 +35,11 @@ void main() { vec2 prevFragUV = taa_fetchSourceAndHistory(fragUV, fragVel, sourceColor, historyColor); vec3 nextColor = sourceColor; - - if (taa_constrainColor()) { - // clamp history to neighbourhood of current sample - historyColor = taa_evalConstrainColor(sourceColor, fragUV, fragVel, historyColor); - } - - if (taa_feedbackColor()) { - nextColor = taa_evalFeedbackColor(sourceColor, historyColor, params.blend); - } else { - nextColor = mix(historyColor, sourceColor, params.blend); - } + + // clamp history to neighbourhood of current sample + historyColor = mix(historyColor, taa_evalConstrainColor(sourceColor, fragUV, fragVel, historyColor), float(taa_constrainColor())); + + nextColor = mix(mix(historyColor, sourceColor, params.blend), taa_evalFeedbackColor(sourceColor, historyColor, params.blend), float(taa_feedbackColor())); outFragColor = vec4(taa_resolveColor(nextColor), 1.0); } diff --git a/libraries/render-utils/src/taa.slh b/libraries/render-utils/src/taa.slh index 784c0824d5..827bcec644 100644 --- a/libraries/render-utils/src/taa.slh +++ b/libraries/render-utils/src/taa.slh @@ -121,21 +121,17 @@ float taa_fetchDepth(vec2 uv) { } -#define ZCMP_GT(a, b) (a > b) +#define ZCMP_GT(a, b) float(a > b) vec2 taa_getImageSize() { vec2 imageSize = getWidthHeight(0); - if (isStereo()) { - imageSize.x *= 2.0; - } + imageSize.x *= mix(1.0, 2.0, float(isStereo())); return imageSize; } vec2 taa_getTexelSize() { vec2 texelSize = getInvWidthHeight(); - if (isStereo()) { - texelSize.x *= 0.5; - } + texelSize.x *= mix(1.0, 0.5, float(isStereo())); return texelSize; } @@ -158,16 +154,16 @@ vec3 taa_findClosestFragment3x3(vec2 uv) vec3 dbr = vec3( 1, 1, taa_fetchDepth(uv + dv + du)); vec3 dmin = dtl; - if (ZCMP_GT(dmin.z, dtc.z)) dmin = dtc; - if (ZCMP_GT(dmin.z, dtr.z)) dmin = dtr; + dmin = mix(dmin, dtc, ZCMP_GT(dmin.z, dtc.z)); + dmin = mix(dmin, dtr, ZCMP_GT(dmin.z, dtr.z)); - if (ZCMP_GT(dmin.z, dml.z)) dmin = dml; - if (ZCMP_GT(dmin.z, dmc.z)) dmin = dmc; - if (ZCMP_GT(dmin.z, dmr.z)) dmin = dmr; + dmin = mix(dmin, dml, ZCMP_GT(dmin.z, dml.z)); + dmin = mix(dmin, dmc, ZCMP_GT(dmin.z, dmc.z)); + dmin = mix(dmin, dmr, ZCMP_GT(dmin.z, dmr.z)); - if (ZCMP_GT(dmin.z, dbl.z)) dmin = dbl; - if (ZCMP_GT(dmin.z, dbc.z)) dmin = dbc; - if (ZCMP_GT(dmin.z, dbr.z)) dmin = dbr; + dmin = mix(dmin, dbl, ZCMP_GT(dmin.z, dbl.z)); + dmin = mix(dmin, dbc, ZCMP_GT(dmin.z, dbc.z)); + dmin = mix(dmin, dbr, ZCMP_GT(dmin.z, dbr.z)); return vec3(uv + dd.xy * dmin.xy, dmin.z); } @@ -189,49 +185,46 @@ vec2 taa_fetchVelocityMapBest(vec2 uv) { vec2 dbc = taa_fetchVelocityMap(uv + dv); vec2 dbr = taa_fetchVelocityMap(uv + dv + du); - vec3 best = vec3(dtl, dot(dtl,dtl)); + vec3 best = vec3(dtl, dot(dtl, dtl)); - float testSpeed = dot(dtc,dtc); - if (testSpeed > best.z) { best = vec3(dtc, testSpeed); } - testSpeed = dot(dtr,dtr); - if (testSpeed > best.z) { best = vec3(dtr, testSpeed); } + float testSpeed = dot(dtc, dtc); + mix(best, vec3(dtc, testSpeed), float(testSpeed > best.z)); + testSpeed = dot(dtr, dtr); + mix(best, vec3(dtr, testSpeed), float(testSpeed > best.z)); - testSpeed = dot(dml,dml); - if (testSpeed > best.z) { best = vec3(dml, testSpeed); } - testSpeed = dot(dmc,dmc); - if (testSpeed > best.z) { best = vec3(dmc, testSpeed); } - testSpeed = dot(dmr,dmr); - if (testSpeed > best.z) { best = vec3(dmr, testSpeed); } + testSpeed = dot(dml, dml); + mix(best, vec3(dml, testSpeed), float(testSpeed > best.z)); + testSpeed = dot(dmc, dmc); + mix(best, vec3(dmc, testSpeed), float(testSpeed > best.z)); + testSpeed = dot(dmr, dmr); + mix(best, vec3(dmr, testSpeed), float(testSpeed > best.z)); - testSpeed = dot(dbl,dbl); - if (testSpeed > best.z) { best = vec3(dbl, testSpeed); } - testSpeed = dot(dbc,dbc); - if (testSpeed > best.z) { best = vec3(dbc, testSpeed); } - testSpeed = dot(dbr,dbr); - if (testSpeed > best.z) { best = vec3(dbr, testSpeed); } + testSpeed = dot(dbl, dbl); + mix(best, vec3(dbl, testSpeed), float(testSpeed > best.z)); + testSpeed = dot(dbc, dbc); + mix(best, vec3(dbc, testSpeed), float(testSpeed > best.z)); + testSpeed = dot(dbr, dbr); + mix(best, vec3(dbr, testSpeed), float(testSpeed > best.z)); return best.xy; } vec2 taa_fromFragUVToEyeUVAndSide(vec2 fragUV, out int stereoSide) { vec2 eyeUV = fragUV; - stereoSide = 0; - if (isStereo()) { - if (eyeUV.x > 0.5) { - eyeUV.x -= 0.5; - stereoSide = 1; - } - eyeUV.x *= 2.0; - } + + float check = float(isStereo()); + float check2 = float(eyeUV.x > 0.5); + eyeUV.x -= check * check2 * 0.5; + stereoSide = int(check * check2); + eyeUV.x *= mix(1.0, 2.0, check); return eyeUV; } vec2 taa_fromEyeUVToFragUV(vec2 eyeUV, int stereoSide) { vec2 fragUV = eyeUV; - if (isStereo()) { - fragUV.x *= 0.5; - fragUV.x += float(stereoSide)*0.5; - } + float check = float(isStereo()); + fragUV.x *= mix(1.0, 0.5, check); + fragUV.x += check * float(stereoSide) * 0.5; return fragUV; } @@ -247,10 +240,8 @@ vec2 taa_fetchSourceAndHistory(vec2 fragUV, vec2 fragVelocity, out vec3 sourceCo vec2 prevFragUV = taa_computePrevFragAndEyeUV(fragUV, fragVelocity, prevEyeUV); sourceColor = taa_fetchSourceMap(fragUV).xyz; - historyColor = sourceColor; - if (!(any(lessThan(prevEyeUV, vec2(0.0))) || any(greaterThan(prevEyeUV, vec2(1.0))))) { - historyColor = taa_fetchHistoryMap(prevFragUV).xyz; - } + historyColor = mix(sourceColor, taa_fetchHistoryMap(prevFragUV).xyz, float(!(any(lessThan(prevEyeUV, vec2(0.0))) || any(greaterThan(prevEyeUV, vec2(1.0)))))); + return prevFragUV; } @@ -405,10 +396,11 @@ vec3 taa_clampColor(vec3 colorMin, vec3 colorMax, vec3 colorSource, vec3 color) vec3 a_unit = abs(v_unit); float ma_unit = max(a_unit.x, max(a_unit.y, a_unit.z)); - if (ma_unit > 1.0) + if (ma_unit > 1.0) { return p_clip + v_clip / ma_unit; - else - return q;// point inside aabb + } else { + return q;// point inside aabb + } } vec3 taa_evalConstrainColor(vec3 sourceColor, vec2 sourceUV, vec2 sourceVel, vec3 candidateColor) { @@ -514,10 +506,6 @@ vec3 taa_evalFXAA(vec2 fragUV) { // compare luma of new samples to the luma range of the original neighborhood // if the new samples exceed this range, just use the first two samples instead of all four - if (lumaB < lumaMin || lumaB > lumaMax) { - return rgbA; - } else { - return rgbB; - } + return mix(rgbB, rgbA, float(lumaB < lumaMin || lumaB > lumaMax)); } diff --git a/libraries/render-utils/src/taa_blend.slf b/libraries/render-utils/src/taa_blend.slf index 50575a6a07..0999b2482f 100644 --- a/libraries/render-utils/src/taa_blend.slf +++ b/libraries/render-utils/src/taa_blend.slf @@ -83,32 +83,21 @@ void main(void) { if ((prevOrbPosToPixLength < tenPercentHeight) && (cursorVelocityLength > 0.5)) { vec2 prevOrbPosToPix_uv = cursorPrevUV + prevOrbPosToPix * texelSize / taa_getDebugOrbZoom(); vec3 preOrbColor = vec3(0.0); - if (!(any(lessThan(prevOrbPosToPix_uv, vec2(0.0))) || any(greaterThan(prevOrbPosToPix_uv, vec2(1.0))))) { - preOrbColor = texture(historyMap, prevOrbPosToPix_uv).xyz; - } - if (prevOrbPosToPixLength < orbPixThreshold) { - preOrbColor = vec3(1.0, 0.0, 1.0); - } + + preOrbColor = mix(preOrbColor, texture(historyMap, prevOrbPosToPix_uv).xyz, float(!(any(lessThan(prevOrbPosToPix_uv, vec2(0.0))) || any(greaterThan(prevOrbPosToPix_uv, vec2(1.0)))))); + preOrbColor = mix(preOrbColor, vec3(1.0, 0.0, 1.0), float(prevOrbPosToPixLength < orbPixThreshold)); float distanceToNext = length(imageSize * (cursorUV - prevOrbPosToPix_uv)); - if (distanceToNext < orbPixThreshold) { - preOrbColor = vec3(1.0, 0.5, 0.0); - } + preOrbColor = mix(preOrbColor, vec3(1.0, 0.5, 0.0), float(distanceToNext < orbPixThreshold)); outFragColor = vec4(preOrbColor, 1.0); return; } if (nextOrbPosToPixLength < tenPercentHeight) { vec2 nextOrbPosToPix_uv = cursorUV + nextOrbPosToPix * texelSize / taa_getDebugOrbZoom(); vec3 nextOrbColor = vec3(0.0); - if (!(any(lessThan(nextOrbPosToPix_uv, vec2(0.0))) || any(greaterThan(nextOrbPosToPix_uv, vec2(1.0))))) { - nextOrbColor = texture(nextMap, nextOrbPosToPix_uv).xyz; - } + nextOrbColor = mix(nextOrbColor, texture(nextMap, nextOrbPosToPix_uv).xyz, float(!(any(lessThan(nextOrbPosToPix_uv, vec2(0.0))) || any(greaterThan(nextOrbPosToPix_uv, vec2(1.0)))))); float distanceToPrev = length(imageSize * (cursorPrevUV - nextOrbPosToPix_uv)); - if (distanceToPrev < orbPixThreshold) { - nextOrbColor = vec3(1.0, 0.0, 1.0); - } - if (nextOrbPosToPixLength < orbPixThreshold) { - nextOrbColor = vec3(1.0, 0.5, 0.0); - } + nextOrbColor = mix(nextOrbColor, vec3(1.0, 0.0, 1.0), float(distanceToPrev < orbPixThreshold)); + nextOrbColor = mix(nextOrbColor, vec3(1.0, 0.5, 0.0), float(nextOrbPosToPixLength < orbPixThreshold)); outFragColor = vec4(nextOrbColor, 1.0); return; @@ -141,16 +130,9 @@ void main(void) { outFragColor = vec4(nextColor, 1.0); vec3 prevColor = nextColor; + prevColor = mix(prevColor, texture(historyMap, prevTexCoord).xyz, float(!(any(lessThan(prevTexCoord, vec2(0.0))) || any(greaterThan(prevTexCoord, vec2(1.0)))))); - if (!(any(lessThan(prevTexCoord, vec2(0.0))) || any(greaterThan(prevTexCoord, vec2(1.0))))) { - prevColor = texture(historyMap, prevTexCoord).xyz; - } + outFragColor.xyz = mix(prevColor, vec3(1, 0, 1), clamp(distance(prevColor, nextColor) - 0.01, 0.0, 1.0)); - outFragColor.xyz = mix(prevColor, vec3(1,0,1), clamp(distance(prevColor, nextColor) - 0.01, 0.0, 1.0)); - - if (pixVelocityLength > params.debugShowVelocityThreshold) { - vec3 speedColor = taa_getVelocityColorAboveThreshold(pixVelocityLength); - - outFragColor = vec4(0.0, 1.0, 1.0, 1.0); - } + outFragColor = mix(outFragColor, vec4(0.0, 1.0, 1.0, 1.0), float(pixVelocityLength > params.debugShowVelocityThreshold)); } diff --git a/libraries/render-utils/src/zone_drawAmbient.slf b/libraries/render-utils/src/zone_drawAmbient.slf index f20d83e913..d780fd0de2 100644 --- a/libraries/render-utils/src/zone_drawAmbient.slf +++ b/libraries/render-utils/src/zone_drawAmbient.slf @@ -44,7 +44,7 @@ void main(void) { // vec3 ambient = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(lightAmbient), fragNormal).xyz; // _fragColor = vec4( 0.5 * (fragNormal + vec3(1.0)), 1.0); - vec3 color = (sphereUV.x > 0.0 ? ambientMap : ambientSH); + vec3 color = mix(ambientSH, ambientMap, float(sphereUV.x > 0.0)); color = color * 1.0 - base.w + base.xyz * base.w; const float INV_GAMMA_22 = 1.0 / 2.2; diff --git a/libraries/render-utils/src/zone_drawSkybox.slf b/libraries/render-utils/src/zone_drawSkybox.slf index f8d1326b3a..743b48d0bf 100644 --- a/libraries/render-utils/src/zone_drawSkybox.slf +++ b/libraries/render-utils/src/zone_drawSkybox.slf @@ -35,16 +35,11 @@ void main(void) { vec3 color = skybox.color.rgb; // blend is only set if there is a cubemap - if (skybox.color.a > 0.0) { - color = texture(skyboxMap, direction).rgb; - if (skybox.color.a < 1.0) { - color *= skybox.color.rgb; - } - } + float check = float(skybox.color.a > 0.0); + color = mix(color, texture(skyboxMap, direction).rgb, check); + color *= mix(vec3(1.0), skybox.color.rgb, check * float(skybox.color.a < 1.0)); color = color * 1.0 - base.w + base.xyz * base.w; const float INV_GAMMA_22 = 1.0 / 2.2; _fragColor = vec4(pow(color, vec3(INV_GAMMA_22)), 1.0); } - - diff --git a/libraries/render/src/render/BlurTask.slh b/libraries/render/src/render/BlurTask.slh index 1133435b4d..e0ded6d8c3 100644 --- a/libraries/render/src/render/BlurTask.slh +++ b/libraries/render/src/render/BlurTask.slh @@ -98,9 +98,10 @@ vec4 pixelShaderGaussian(vec2 texcoord, vec2 direction, vec2 pixelStep) { totalWeight += weight; } } - - float check = float(totalWeight > 0.0); - srcBlurred *= check / totalWeight + (1.0 - check); + + if (totalWeight > 0.0) { + srcBlurred /= totalWeight; + } srcBlurred.a = getOutputAlpha(); return srcBlurred; @@ -159,9 +160,10 @@ vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep totalWeight += weight; } } - - float check = float(totalWeight > 0.0); - srcBlurred *= check / totalWeight + (1.0 - check); + + if (totalWeight > 0.0) { + srcBlurred /= totalWeight; + } return srcBlurred; } diff --git a/libraries/render/src/render/drawCellBounds.slv b/libraries/render/src/render/drawCellBounds.slv index 24cc6254fd..4b5356741b 100644 --- a/libraries/render/src/render/drawCellBounds.slv +++ b/libraries/render/src/render/drawCellBounds.slv @@ -51,7 +51,7 @@ void main(void) { vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; int cellIsEmpty = sign(inCellLocation.w); - ivec4 cellLocation = ivec4(inCellLocation.xyz, (inCellLocation.w < 0 ? -inCellLocation.w : inCellLocation.w)); + ivec4 cellLocation = ivec4(inCellLocation.xyz, cellIsEmpty * inCellLocation.w); vec4 cellBound = evalBound(cellLocation); pos.xyz = cellBound.xyz + vec3(cellBound.w) * pos.xyz; diff --git a/libraries/render/src/render/drawItemBounds.slf b/libraries/render/src/render/drawItemBounds.slf index 90faaff05c..ab78f93064 100644 --- a/libraries/render/src/render/drawItemBounds.slf +++ b/libraries/render/src/render/drawItemBounds.slf @@ -18,11 +18,7 @@ layout(location=0) out vec4 outFragColor; void main(void) { float var = step(fract(varTexcoord.x * varTexcoord.y * 1.0), 0.5); - if (varColor.a == 0.0) { - outFragColor = vec4(mix(vec3(0.0), varColor.xyz, var), mix(0.0, 1.0, var)); - - } else { - outFragColor = vec4(mix(vec3(1.0), varColor.xyz, var), varColor.a); - } - + outFragColor = mix(vec4(mix(vec3(1.0), varColor.xyz, var), varColor.a), + vec4(mix(vec3(0.0), varColor.xyz, var), mix(0.0, 1.0, var)), + float(varColor.a == 0.0)); } diff --git a/libraries/render/src/render/drawItemBounds.slv b/libraries/render/src/render/drawItemBounds.slv index 0a9615c9c2..808a23599b 100644 --- a/libraries/render/src/render/drawItemBounds.slv +++ b/libraries/render/src/render/drawItemBounds.slv @@ -98,11 +98,6 @@ void main(void) { TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, pos, gl_Position)$> - if (params.color.w < 0.0) { - varColor = vec4(colorWheel(float(boundID)/(-params.color.w)), 1.0); - } else { - varColor = vec4(colorWheel(float(params.color.w)), 1.0); - } + varColor = mix(vec4(colorWheel(float(params.color.w)), 1.0), vec4(colorWheel(float(boundID)/(-params.color.w)), 1.0), float(params.color.w < 0.0)); varTexcoord = vec2(cubeVec.w, length(boundDim)); - } \ No newline at end of file diff --git a/libraries/render/src/render/drawItemStatus.slf b/libraries/render/src/render/drawItemStatus.slf index e88cf4c920..ca7f2273cd 100644 --- a/libraries/render/src/render/drawItemStatus.slf +++ b/libraries/render/src/render/drawItemStatus.slf @@ -22,10 +22,9 @@ vec2 getIconTexcoord(float icon, vec2 uv) { } void main(void) { - if (varTexcoord.z < 254.5) { - outFragColor = texture(_icons, getIconTexcoord(varTexcoord.z, varTexcoord.xy)) * varColor; - } else { - vec2 centerDir = varTexcoord.xy * 2.0f - 1.0f; - outFragColor = vec4(varColor.xyz, 1.0 - step(1.0f, dot(centerDir.xy, centerDir.xy))); - } + vec2 centerDir = varTexcoord.xy * 2.0f - 1.0f; + + outFragColor = mix(vec4(varColor.xyz, 1.0 - step(1.0f, dot(centerDir.xy, centerDir.xy))), + texture(_icons, getIconTexcoord(varTexcoord.z, varTexcoord.xy)) * varColor, + float(varTexcoord.z < 254.5)); } From 1e3549d2637bd7ee30f67f0cd32c6b7ed239cbc3 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 2 Nov 2018 08:33:14 +1300 Subject: [PATCH 016/117] Increase delay in shrinking the mini tablet after start of trigger --- scripts/system/miniTablet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/miniTablet.js b/scripts/system/miniTablet.js index a2f0d074f0..63ee91d976 100644 --- a/scripts/system/miniTablet.js +++ b/scripts/system/miniTablet.js @@ -551,7 +551,7 @@ // Trigger values. leftTriggerOn = 0, rightTriggerOn = 0, - MAX_TRIGGER_ON_TIME = 100, + MAX_TRIGGER_ON_TIME = 400, // Visibility. MAX_HAND_CAMERA_ANGLE = 30, From e534e09801ec664784959711b73779f1d4b53311 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Mon, 29 Oct 2018 17:38:28 -0700 Subject: [PATCH 017/117] Update LightClusterGrid_shared.slh --- .../render-utils/src/DeferredBufferRead.slh | 4 ++-- libraries/render-utils/src/Haze.slf | 2 +- libraries/render-utils/src/LightClusterGrid.slh | 2 +- .../render-utils/src/LightClusterGrid_shared.slh | 10 ++++------ libraries/render-utils/src/LightPoint.slh | 10 ++++++---- libraries/render-utils/src/LightSpot.slh | 16 +++++++++------- libraries/render-utils/src/glowLine.slv | 5 ++--- .../src/lightClusters_drawClusterContent.slv | 2 +- .../render-utils/src/ssao_debugOcclusion.slf | 3 ++- .../src/surfaceGeometry_makeCurvature.slf | 4 ++-- libraries/render-utils/src/taa.slh | 8 ++++---- libraries/render/src/render/drawItemBounds.slf | 2 +- 12 files changed, 35 insertions(+), 33 deletions(-) diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh index a6a6a6b1ac..868b93ff91 100644 --- a/libraries/render-utils/src/DeferredBufferRead.slh +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -121,7 +121,7 @@ vec4 unpackDeferredPosition(float depthValue, vec2 texcoord) { float check2 = check * float(texcoord.x > 0.5); texcoord.x -= check2 * 0.5; int side = int(check2); - texcoord.x *= mix(1.0, 2.0, check); + texcoord.x *= 1.0 + check; return vec4(evalEyePositionFromZdb(side, depthValue, texcoord), 1.0); } @@ -139,7 +139,7 @@ vec4 unpackDeferredPositionFromZeye(vec2 texcoord) { float check2 = check * float(texcoord.x > 0.5); texcoord.x -= check2 * 0.5; int side = int(check2); - texcoord.x *= mix(1.0, 2.0, check); + texcoord.x *= 1.0 + check; return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0); } diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index b64d4172c6..170e69eb2d 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -30,7 +30,7 @@ vec4 unpackPositionFromZeye(vec2 texcoord) { float check2 = check * float(texcoord.x > 0.5); texcoord.x -= check2 * 0.5; int side = int(check2); - texcoord.x *= mix(1.0, 2.0, check); + texcoord.x *= 1.0 + check; return vec4(evalEyePositionFromZeye(side, Zeye, texcoord), 1.0); } diff --git a/libraries/render-utils/src/LightClusterGrid.slh b/libraries/render-utils/src/LightClusterGrid.slh index df8ba001f5..cd944489ec 100644 --- a/libraries/render-utils/src/LightClusterGrid.slh +++ b/libraries/render-utils/src/LightClusterGrid.slh @@ -83,7 +83,7 @@ int clusterGrid_getClusterLightId(int index, int offset) { return element; */ int element = _clusterGridContent[GRID_FETCH_BUFFER((elementIndex >> 1))]; - return int(mix(element, element >> 16, int((elementIndex & 0x00000001) == 1))) & 0x0000FFFF; + return (element >> (16 * int((elementIndex & 0x00000001) == 1))) & 0x0000FFFF; } diff --git a/libraries/render-utils/src/LightClusterGrid_shared.slh b/libraries/render-utils/src/LightClusterGrid_shared.slh index 476ca6284f..cf58ce56ff 100644 --- a/libraries/render-utils/src/LightClusterGrid_shared.slh +++ b/libraries/render-utils/src/LightClusterGrid_shared.slh @@ -7,11 +7,9 @@ #ifdef __cplusplus # define _MIN glm::min -# define _MIX(x, y, a) glm::mix((float)x, (float)y, (float)a) -# define _ABS(x) (int)fabsf() +# define _ABS(x) (int)fabsf(x) #else # define _MIN min -# define _MIX mix # define _ABS abs #endif @@ -151,7 +149,7 @@ ivec3 frustumGrid_eyeToClusterPos(vec3 eyePos) { int frustumGrid_eyeToClusterDirH(vec3 eyeDir) { if (eyeDir.z >= 0.0f) { - return int(_MIX(-1, frustumGrid.dims.x, int(eyeDir.x > 0.0f))); + return int(eyeDir.x > 0.0f) * (frustumGrid.dims.x + 1) - 1; } float eyeDepth = -eyeDir.z; @@ -165,7 +163,7 @@ int frustumGrid_eyeToClusterDirH(vec3 eyeDir) { int frustumGrid_eyeToClusterDirV(vec3 eyeDir) { if (eyeDir.z >= 0.0f) { - return int(_MIX(-1, frustumGrid.dims.y, int(eyeDir.y > 0.0f))); + return int(eyeDir.y > 0.0f) * (frustumGrid.dims.y + 1) - 1; } float eyeDepth = -eyeDir.z; @@ -193,4 +191,4 @@ vec4 frustumGrid_worldToEye(vec4 worldPos) { // <@if 1@> // Trigger Scribe include - // <@endif@> End C++ compatible \ No newline at end of file + // <@endif@> End C++ compatible diff --git a/libraries/render-utils/src/LightPoint.slh b/libraries/render-utils/src/LightPoint.slh index 7c59cf85ef..6100627105 100644 --- a/libraries/render-utils/src/LightPoint.slh +++ b/libraries/render-utils/src/LightPoint.slh @@ -40,10 +40,12 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, diffuse *= lightEnergy * isDiffuseEnabled(); specular *= lightEnergy * isSpecularEnabled(); - // Show edges - float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0); - float edgeCoord = exp2(-8.0 * edge * edge); - diffuse = mix(diffuse, vec3(edgeCoord * edgeCoord * getLightColor(light)), float(isShowLightContour() > 0.0 && edge < 1.0)); + if (isShowLightContour() > 0.0) { + // Show edges + float edge = abs(2.0 * ((lightVolume_getRadius(light.volume) - fragLightDistance) / (0.1)) - 1.0); + float edgeCoord = exp2(-8.0 * edge * edge); + diffuse = mix(diffuse, vec3(edgeCoord * edgeCoord * getLightColor(light)), float(edge < 1.0)); + } } <@endfunc@> diff --git a/libraries/render-utils/src/LightSpot.slh b/libraries/render-utils/src/LightSpot.slh index 799021c459..7fea9856d8 100644 --- a/libraries/render-utils/src/LightSpot.slh +++ b/libraries/render-utils/src/LightSpot.slh @@ -41,13 +41,15 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light, diffuse *= lightEnergy * isDiffuseEnabled(); specular *= lightEnergy * isSpecularEnabled(); - // Show edges - float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance); - float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume)); - float edgeDist = min(edgeDistR, edgeDistS); - float edge = abs(2.0 * (edgeDist * 10.0) - 1.0); - float edgeCoord = exp2(-8.0 * edge * edge); - diffuse = mix(diffuse, vec3(edgeCoord * edgeCoord * getLightColor(light)), float(isShowLightContour() > 0.0 && edge < 1.0)); + if (isShowLightContour() > 0.0) { + // Show edges + float edgeDistR = (lightVolume_getRadius(light.volume) - fragLightDistance); + float edgeDistS = dot(fragLightDistance * vec2(cosSpotAngle, sqrt(1.0 - cosSpotAngle * cosSpotAngle)), -lightVolume_getSpotOutsideNormal2(light.volume)); + float edgeDist = min(edgeDistR, edgeDistS); + float edge = abs(2.0 * (edgeDist * 10.0) - 1.0); + float edgeCoord = exp2(-8.0 * edge * edge); + diffuse = mix(diffuse, vec3(edgeCoord * edgeCoord * getLightColor(light)), float(edge < 1.0)); + } } <@endfunc@> diff --git a/libraries/render-utils/src/glowLine.slv b/libraries/render-utils/src/glowLine.slv index 609082878b..ecb1152d52 100644 --- a/libraries/render-utils/src/glowLine.slv +++ b/libraries/render-utils/src/glowLine.slv @@ -53,9 +53,8 @@ void main(void) { // Add or subtract the orthogonal vector based on a different vertex ID // calculation - float check = float(gl_VertexID < 2); - distanceFromCenter = mix(1.0, -1.0, check); - eye.xyz += mix(orthogonal, -orthogonal, check); + distanceFromCenter = mix(1.0, -1.0, float(gl_VertexID < 2)); + eye.xyz += distanceFromCenter * orthogonal; // Finally, put the eyespace vertex into clip space <$transformEyeToClipPos(cam, eye, gl_Position)$> diff --git a/libraries/render-utils/src/lightClusters_drawClusterContent.slv b/libraries/render-utils/src/lightClusters_drawClusterContent.slv index 51718e6d8f..c30252da41 100644 --- a/libraries/render-utils/src/lightClusters_drawClusterContent.slv +++ b/libraries/render-utils/src/lightClusters_drawClusterContent.slv @@ -69,5 +69,5 @@ void main(void) { TransformCamera cam = getTransformCamera(); <$transformWorldToClipPos(cam, worldPos, gl_Position)$> - varColor = vec4(colorWheel(fract(float(gpu_InstanceID()) / float(frustumGrid_numClusters()))), mix(0.1, 0.9, float(numLights > 0))); + varColor = vec4(colorWheel(fract(float(gpu_InstanceID()) / float(frustumGrid_numClusters()))), 0.1 + 0.8 * float(numLights > 0)); } \ No newline at end of file diff --git a/libraries/render-utils/src/ssao_debugOcclusion.slf b/libraries/render-utils/src/ssao_debugOcclusion.slf index 43c3d15ece..612e5b862b 100644 --- a/libraries/render-utils/src/ssao_debugOcclusion.slf +++ b/libraries/render-utils/src/ssao_debugOcclusion.slf @@ -93,7 +93,8 @@ void main(void) { { bool check = dot(fragToTap,fragToTap) < keepTapRadius; keep = keep || check; - keepedMip = int(mix(keepedMip, evalMipFromRadius(tap.z * float(doFetchMips())), int(check))); + int checki = int(check); + keepedMip = checki * evalMipFromRadius(tap.z * float(doFetchMips())) + (1 - checki) * keepedMip; } vec3 tapUVZ = fetchTap(side, ssC, tap, imageSize); diff --git a/libraries/render-utils/src/surfaceGeometry_makeCurvature.slf b/libraries/render-utils/src/surfaceGeometry_makeCurvature.slf index 433b3e97dc..dd9b98b5e5 100644 --- a/libraries/render-utils/src/surfaceGeometry_makeCurvature.slf +++ b/libraries/render-utils/src/surfaceGeometry_makeCurvature.slf @@ -89,7 +89,7 @@ void main(void) { vec2 texcoordPos; ivec4 stereoSide; ivec2 framePixelPos = getPixelPosTexcoordPosAndSide(gl_FragCoord.xy, pixelPos, texcoordPos, stereoSide); - vec2 stereoSideClip = vec2(stereoSide.x, mix(1.0, 0.5, float(isStereo()))); + vec2 stereoSideClip = vec2(stereoSide.x, 1.0 - 0.5 * float(isStereo())); // Texcoord to fetch in the deferred texture are the exact UVs comming from vertex shader // sideToFrameTexcoord(stereoSideClip, texcoordPos); @@ -124,7 +124,7 @@ void main(void) { // Calculate dF/du and dF/dv vec2 viewportScale = perspectiveScale * getInvWidthHeight(); - vec2 du = vec2(viewportScale.x * mix(1.0, 0.5, float(float(stereoSide.w) > 0.0)), 0.0); + vec2 du = vec2(viewportScale.x * (1.0 - 0.5 * float(stereoSide.w > 0)), 0.0); vec2 dv = vec2( 0.0f, viewportScale.y); vec4 dFdu = vec4(getWorldNormalDiff(frameTexcoordPos, du), getEyeDepthDiff(frameTexcoordPos, du)); diff --git a/libraries/render-utils/src/taa.slh b/libraries/render-utils/src/taa.slh index 827bcec644..ed9162516e 100644 --- a/libraries/render-utils/src/taa.slh +++ b/libraries/render-utils/src/taa.slh @@ -125,13 +125,13 @@ float taa_fetchDepth(vec2 uv) { vec2 taa_getImageSize() { vec2 imageSize = getWidthHeight(0); - imageSize.x *= mix(1.0, 2.0, float(isStereo())); + imageSize.x *= 1.0 + float(isStereo()); return imageSize; } vec2 taa_getTexelSize() { vec2 texelSize = getInvWidthHeight(); - texelSize.x *= mix(1.0, 0.5, float(isStereo())); + texelSize.x *= 1.0 - 0.5 * float(isStereo()); return texelSize; } @@ -216,14 +216,14 @@ vec2 taa_fromFragUVToEyeUVAndSide(vec2 fragUV, out int stereoSide) { float check2 = float(eyeUV.x > 0.5); eyeUV.x -= check * check2 * 0.5; stereoSide = int(check * check2); - eyeUV.x *= mix(1.0, 2.0, check); + eyeUV.x *= 1.0 + check; return eyeUV; } vec2 taa_fromEyeUVToFragUV(vec2 eyeUV, int stereoSide) { vec2 fragUV = eyeUV; float check = float(isStereo()); - fragUV.x *= mix(1.0, 0.5, check); + fragUV.x *= 1.0 - 0.5 * check; fragUV.x += check * float(stereoSide) * 0.5; return fragUV; } diff --git a/libraries/render/src/render/drawItemBounds.slf b/libraries/render/src/render/drawItemBounds.slf index ab78f93064..0fed67beb6 100644 --- a/libraries/render/src/render/drawItemBounds.slf +++ b/libraries/render/src/render/drawItemBounds.slf @@ -19,6 +19,6 @@ void main(void) { float var = step(fract(varTexcoord.x * varTexcoord.y * 1.0), 0.5); outFragColor = mix(vec4(mix(vec3(1.0), varColor.xyz, var), varColor.a), - vec4(mix(vec3(0.0), varColor.xyz, var), mix(0.0, 1.0, var)), + vec4(mix(vec3(0.0), varColor.xyz, var), var), float(varColor.a == 0.0)); } From 8924f0832a547068fb73989b72fe63bb58eeafc0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 2 Nov 2018 18:06:00 +1300 Subject: [PATCH 018/117] Use half angles relative to palm normal for mini tablet visibility --- scripts/system/miniTablet.js | 65 +++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/scripts/system/miniTablet.js b/scripts/system/miniTablet.js index 63ee91d976..16673d373f 100644 --- a/scripts/system/miniTablet.js +++ b/scripts/system/miniTablet.js @@ -250,11 +250,8 @@ } - function getUIPositionAndRotation(hand) { - return { - position: MINI_POSITIONS[hand], - rotation: MINI_ROTATIONS[hand] - }; + function getUIPosition(hand) { + return MINI_POSITIONS[hand]; } function getMiniTabletID() { @@ -492,7 +489,7 @@ create(); return { - getUIPositionAndRotation: getUIPositionAndRotation, + getUIPosition: getUIPosition, getMiniTabletID: getMiniTabletID, getMiniTabletProperties: getMiniTabletProperties, isLaserPointingAt: isLaserPointingAt, @@ -554,13 +551,22 @@ MAX_TRIGGER_ON_TIME = 400, // Visibility. - MAX_HAND_CAMERA_ANGLE = 30, - MAX_CAMERA_HAND_ANGLE = 30, + MAX_MEDIAL_FINGER_CAMERA_ANGLE = 25, // From palm normal along palm towards fingers. + MAX_MEDIAL_WRIST_CAMERA_ANGLE = 65, // From palm normal along palm towards wrist. + MAX_LATERAL_THUMB_CAMERA_ANGLE = 25, // From palm normal across palm towards of thumb. + MAX_LATERAL_PINKY_CAMERA_ANGLE = 25, // From palm normal across palm towards pinky. DEGREES_180 = 180, - MAX_HAND_CAMERA_ANGLE_COS = Math.cos(Math.PI * MAX_HAND_CAMERA_ANGLE / DEGREES_180), - MAX_CAMERA_HAND_ANGLE_COS = Math.cos(Math.PI * MAX_CAMERA_HAND_ANGLE / DEGREES_180), + DEGREES_TO_RADIANS = Math.PI / DEGREES_180, + MAX_MEDIAL_FINGER_CAMERA_ANGLE_RAD = DEGREES_TO_RADIANS * MAX_MEDIAL_FINGER_CAMERA_ANGLE, + MAX_MEDIAL_WRIST_CAMERA_ANGLE_RAD = DEGREES_TO_RADIANS * MAX_MEDIAL_WRIST_CAMERA_ANGLE, + MAX_LATERAL_THUMB_CAMERA_ANGLE_RAD = DEGREES_TO_RADIANS * MAX_LATERAL_THUMB_CAMERA_ANGLE, + MAX_LATERAL_PINKY_CAMERA_ANGLE_RAD = DEGREES_TO_RADIANS * MAX_LATERAL_PINKY_CAMERA_ANGLE, + MAX_CAMERA_MINI_ANGLE = 30, + MAX_CAMERA_MINI_ANGLE_COS = Math.cos(MAX_CAMERA_MINI_ANGLE * DEGREES_TO_RADIANS), HIDING_DELAY = 1000, // ms - lastVisible = [0, 0]; + lastVisible = [0, 0], + + HALF_PI = Math.PI / 2; function enterMiniDisabled() { @@ -597,11 +603,13 @@ jointIndex, handPosition, handOrientation, - uiPositionAndOrientation, miniPosition, - miniOrientation, miniToCameraDirection, - cameraToHand; + medialHandVector, + lateralHandVector, + medialAngle, + lateralAngle, + cameraToMini; // Shouldn't show mini tablet if hand isn't being controlled. pose = Controller.getPoseValue(hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand); @@ -646,15 +654,24 @@ Vec3.multiplyQbyV(MyAvatar.orientation, MyAvatar.getAbsoluteJointTranslationInObjectFrame(jointIndex))); handOrientation = Quat.multiply(MyAvatar.orientation, MyAvatar.getAbsoluteJointRotationInObjectFrame(jointIndex)); - uiPositionAndOrientation = ui.getUIPositionAndRotation(hand); + var uiPosition = ui.getUIPosition(hand); miniPosition = Vec3.sum(handPosition, Vec3.multiply(MyAvatar.sensorToWorldScale, - Vec3.multiplyQbyV(handOrientation, uiPositionAndOrientation.position))); - miniOrientation = Quat.multiply(handOrientation, uiPositionAndOrientation.rotation); + Vec3.multiplyQbyV(handOrientation, uiPosition))); miniToCameraDirection = Vec3.normalize(Vec3.subtract(Camera.position, miniPosition)); - show = Vec3.dot(miniToCameraDirection, Quat.getForward(miniOrientation)) > MAX_HAND_CAMERA_ANGLE_COS; - show = show || (-Vec3.dot(miniToCameraDirection, Quat.getForward(handOrientation)) > MAX_HAND_CAMERA_ANGLE_COS); - cameraToHand = -Vec3.dot(miniToCameraDirection, Quat.getForward(Camera.orientation)); - show = show && (cameraToHand > MAX_CAMERA_HAND_ANGLE_COS); + + // Mini tablet aimed toward camera? + medialHandVector = Vec3.multiplyQbyV(handOrientation, Vec3.UNIT_NEG_Y); + lateralHandVector = Vec3.multiplyQbyV(handOrientation, hand === LEFT_HAND ? Vec3.UNIT_X : Vec3.UNIT_NEG_X); + medialAngle = Math.acos(Vec3.dot(medialHandVector, miniToCameraDirection)) - HALF_PI; + lateralAngle = Math.acos(Vec3.dot(lateralHandVector, miniToCameraDirection)) - HALF_PI; + show = -MAX_MEDIAL_WRIST_CAMERA_ANGLE_RAD <= medialAngle + && medialAngle <= MAX_MEDIAL_FINGER_CAMERA_ANGLE_RAD + && -MAX_LATERAL_PINKY_CAMERA_ANGLE_RAD <= lateralAngle + && lateralAngle <= MAX_LATERAL_THUMB_CAMERA_ANGLE_RAD; + + // Camera looking at mini tablet? + cameraToMini = -Vec3.dot(miniToCameraDirection, Quat.getForward(Camera.orientation)); + show = show && (cameraToMini > MAX_CAMERA_MINI_ANGLE_COS); // Persist showing for a while after it would otherwise be hidden. if (show) { @@ -666,7 +683,7 @@ return { show: show, - cameraToHand: cameraToHand + cameraToMini: cameraToMini }; } @@ -689,7 +706,7 @@ showRight = shouldShowMini(RIGHT_HAND); if (showLeft.show && showRight.show) { // Both hands would be pointing at camera; show the one the camera is gazing at. - if (showLeft.cameraToHand > showRight.cameraToHand) { + if (showLeft.cameraToMini > showRight.cameraToMini) { setState(MINI_SHOWING, LEFT_HAND); } else { setState(MINI_SHOWING, RIGHT_HAND); @@ -751,7 +768,7 @@ showLeft = shouldShowMini(LEFT_HAND); showRight = shouldShowMini(RIGHT_HAND); if (showLeft.show && showRight.show) { - if (showLeft.cameraToHand > showRight.cameraToHand) { + if (showLeft.cameraToMini > showRight.cameraToMini) { if (miniHand !== LEFT_HAND) { setState(MINI_HIDING); } From 55d0822b1a3224af0c95de0ed41de965693a80b7 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 2 Nov 2018 18:18:41 +1300 Subject: [PATCH 019/117] Delay showing mini tablet --- scripts/system/miniTablet.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/scripts/system/miniTablet.js b/scripts/system/miniTablet.js index 16673d373f..a4cd0baf45 100644 --- a/scripts/system/miniTablet.js +++ b/scripts/system/miniTablet.js @@ -563,6 +563,8 @@ MAX_LATERAL_PINKY_CAMERA_ANGLE_RAD = DEGREES_TO_RADIANS * MAX_LATERAL_PINKY_CAMERA_ANGLE, MAX_CAMERA_MINI_ANGLE = 30, MAX_CAMERA_MINI_ANGLE_COS = Math.cos(MAX_CAMERA_MINI_ANGLE * DEGREES_TO_RADIANS), + SHOWING_DELAY = 1000, // ms + lastInvisible = [0, 0], HIDING_DELAY = 1000, // ms lastVisible = [0, 0], @@ -609,7 +611,8 @@ lateralHandVector, medialAngle, lateralAngle, - cameraToMini; + cameraToMini, + now; // Shouldn't show mini tablet if hand isn't being controlled. pose = Controller.getPoseValue(hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand); @@ -673,11 +676,19 @@ cameraToMini = -Vec3.dot(miniToCameraDirection, Quat.getForward(Camera.orientation)); show = show && (cameraToMini > MAX_CAMERA_MINI_ANGLE_COS); + // Delay showing for a while after it would otherwise be shown, unless it was showing on the other hand. + now = Date.now(); + if (show) { + show = now - lastInvisible[hand] >= SHOWING_DELAY || now - lastVisible[otherHand(hand)] <= HIDING_DELAY; + } else { + lastInvisible[hand] = now; + } + // Persist showing for a while after it would otherwise be hidden. if (show) { - lastVisible[hand] = Date.now(); + lastVisible[hand] = now; } else { - show = Date.now() - lastVisible[hand] <= HIDING_DELAY; + show = now - lastVisible[hand] <= HIDING_DELAY; } } From b3abd977078649cd189497fbe3867ab445eb9cac Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 8 Nov 2018 14:53:45 -0800 Subject: [PATCH 020/117] projected materials and repeat property --- .../src/RenderableMaterialEntityItem.cpp | 2 +- .../entities/src/EntityItemProperties.cpp | 15 ++++- libraries/entities/src/EntityItemProperties.h | 1 + .../entities/src/EntityPropertyFlags.cpp | 1 + libraries/entities/src/EntityPropertyFlags.h | 2 + libraries/entities/src/MaterialEntityItem.cpp | 62 +++++++++++++++++-- libraries/entities/src/MaterialEntityItem.h | 12 +++- libraries/graphics/src/graphics/Material.cpp | 9 ++- libraries/graphics/src/graphics/Material.h | 10 ++- libraries/graphics/src/graphics/Material.slh | 15 +++-- .../src/graphics/MaterialTextures.slh | 5 +- libraries/graphics/src/graphics/TextureMap.h | 9 +++ .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- libraries/render-utils/src/deformed_model.slv | 8 +-- .../render-utils/src/deformed_model_dq.slv | 8 +-- .../src/deformed_model_normal_map.slv | 8 +-- .../src/deformed_model_normal_map_dq.slv | 8 +-- libraries/render-utils/src/model.slv | 8 +-- .../render-utils/src/model_normal_map.slv | 8 +-- scripts/system/html/js/entityProperties.js | 13 ++++ 21 files changed, 164 insertions(+), 45 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index c607f678b6..6451e873c9 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -126,7 +126,7 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { batch.setModelTransform(renderTransform); if (args->_renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) { - drawMaterial->setTextureTransforms(textureTransform); + drawMaterial->setTextureTransforms(textureTransform, MaterialMappingMode::UV, true); // bind the material RenderPipelines::bindMaterial(drawMaterial, batch, args->_enableTexturing); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index c243f772e2..2b7135413d 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -385,6 +385,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_DATA, materialData); + CHECK_PROPERTY_CHANGE(PROP_MATERIAL_REPEAT, materialRepeat); CHECK_PROPERTY_CHANGE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera); CHECK_PROPERTY_CHANGE(PROP_PARTICLE_SPIN, particleSpin); CHECK_PROPERTY_CHANGE(PROP_SPIN_SPREAD, spinSpread); @@ -754,7 +755,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * Otherwise the property value is parsed as an unsigned integer, specifying the mesh index to modify. Invalid values are * parsed to 0. * @property {string} materialMappingMode="uv" - How the material is mapped to the entity. Either "uv" or - * "projected". Currently, only "uv" is supported. + * "projected". In "uv" mode, the material will be evaluated within the UV space of the mesh it is applied to. In + * "projected" mode, the 3D transform of the Material Entity will be used to evaluate the texture coordinates for the material. * @property {Vec2} materialMappingPos=0,0 - Offset position in UV-space of the top left of the material, range * { x: 0, y: 0 }{ x: 1, y: 1 }. * @property {Vec2} materialMappingScale=1,1 - How much to scale the material within the parent's UV-space. @@ -762,6 +764,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {string} materialData="" - Used to store {@link MaterialResource} data as a JSON string. You can use * JSON.parse() to parse the string into a JavaScript object which you can manipulate the properties of, and * use JSON.stringify() to convert the object into a string to put in the property. + * @property {boolean} materialRepeat=true - If true, the material will repeat. If false, fragments outside of texCoord 0 - 1 will be discarded. + * Works in both "uv" and "projected" modes. * @example Color a sphere using a Material entity. * var entityID = Entities.addEntity({ * type: "Sphere", @@ -1485,6 +1489,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_DATA, materialData); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_REPEAT, materialRepeat); } /**jsdoc @@ -1666,6 +1671,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingScale, vec2, setMaterialMappingScale); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingRot, float, setMaterialMappingRot); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialData, QString, setMaterialData); + COPY_PROPERTY_FROM_QSCRIPTVALUE(materialRepeat, bool, setMaterialRepeat); COPY_PROPERTY_FROM_QSCRIPTVALUE(isVisibleInSecondaryCamera, bool, setIsVisibleInSecondaryCamera); COPY_PROPERTY_FROM_QSCRIPTVALUE(particleSpin, float, setParticleSpin); COPY_PROPERTY_FROM_QSCRIPTVALUE(spinSpread, float, setSpinSpread); @@ -2061,6 +2067,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, vec2); ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float); ADD_PROPERTY_TO_MAP(PROP_MATERIAL_DATA, MaterialData, materialData, QString); + ADD_PROPERTY_TO_MAP(PROP_MATERIAL_REPEAT, MaterialRepeat, materialRepeat, bool); ADD_PROPERTY_TO_MAP(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool); @@ -2511,6 +2518,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, properties.getMaterialMappingScale()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, properties.getMaterialMappingRot()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_DATA, properties.getMaterialData()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_REPEAT, properties.getMaterialRepeat()); } APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName()); @@ -2898,6 +2906,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_SCALE, vec2, setMaterialMappingScale); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_ROT, float, setMaterialMappingRot); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_DATA, QString, setMaterialData); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_REPEAT, bool, setMaterialRepeat); } READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName); @@ -3137,6 +3146,7 @@ void EntityItemProperties::markAllChanged() { _materialMappingScaleChanged = true; _materialMappingRotChanged = true; _materialDataChanged = true; + _materialRepeatChanged = true; // Certifiable Properties _itemNameChanged = true; @@ -3587,6 +3597,9 @@ QList EntityItemProperties::listChangedProperties() { if (materialDataChanged()) { out += "materialData"; } + if (materialRepeatChanged()) { + out += "materialRepeat"; + } if (isVisibleInSecondaryCameraChanged()) { out += "isVisibleInSecondaryCamera"; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index c91ccda5aa..87fefb5c1b 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -241,6 +241,7 @@ public: DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, glm::vec2, glm::vec2(1.0f)); DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float, 0); DEFINE_PROPERTY_REF(PROP_MATERIAL_DATA, MaterialData, materialData, QString, ""); + DEFINE_PROPERTY_REF(PROP_MATERIAL_REPEAT, MaterialRepeat, materialRepeat, bool, true); DEFINE_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool, ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA); diff --git a/libraries/entities/src/EntityPropertyFlags.cpp b/libraries/entities/src/EntityPropertyFlags.cpp index c077b153b8..4f3c35ce0a 100644 --- a/libraries/entities/src/EntityPropertyFlags.cpp +++ b/libraries/entities/src/EntityPropertyFlags.cpp @@ -175,6 +175,7 @@ QDebug& operator<<(QDebug& dbg, const EntityPropertyFlags& f) { result = f.getHasProperty(PROP_MATERIAL_MAPPING_SCALE) ? result + "materialMappingScale " : result; result = f.getHasProperty(PROP_MATERIAL_MAPPING_ROT) ? result + "materialMappingRot " : result; result = f.getHasProperty(PROP_MATERIAL_DATA) ? result + "materialData " : result; + result = f.getHasProperty(PROP_MATERIAL_REPEAT) ? result + "materialRepeat " : result; result = f.getHasProperty(PROP_VISIBLE_IN_SECONDARY_CAMERA) ? result + "visibleInSecondaryCamera " : result; result = f.getHasProperty(PROP_PARTICLE_SPIN) ? result + "particleSpin " : result; result = f.getHasProperty(PROP_SPIN_START) ? result + "spinStart " : result; diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index d2f687fbd3..e6649f74aa 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -275,6 +275,8 @@ enum EntityPropertyList { PROP_GRAB_EQUIPPABLE_INDICATOR_SCALE, PROP_GRAB_EQUIPPABLE_INDICATOR_OFFSET, + PROP_MATERIAL_REPEAT, + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp index 825dd83348..cec602a5e1 100644 --- a/libraries/entities/src/MaterialEntityItem.cpp +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -41,6 +41,7 @@ EntityItemProperties MaterialEntityItem::getProperties(const EntityPropertyFlags COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingScale, getMaterialMappingScale); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingRot, getMaterialMappingRot); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialData, getMaterialData); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialRepeat, getMaterialRepeat); return properties; } @@ -55,6 +56,7 @@ bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingScale, setMaterialMappingScale); SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingRot, setMaterialMappingRot); SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialData, setMaterialData); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialRepeat, setMaterialRepeat); if (somethingChanged) { bool wantDebug = false; @@ -85,6 +87,7 @@ int MaterialEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da READ_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, glm::vec2, setMaterialMappingScale); READ_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, float, setMaterialMappingRot); READ_ENTITY_PROPERTY(PROP_MATERIAL_DATA, QString, setMaterialData); + READ_ENTITY_PROPERTY(PROP_MATERIAL_REPEAT, bool, setMaterialRepeat); return bytesRead; } @@ -99,6 +102,7 @@ EntityPropertyFlags MaterialEntityItem::getEntityProperties(EncodeBitstreamParam requestedProperties += PROP_MATERIAL_MAPPING_SCALE; requestedProperties += PROP_MATERIAL_MAPPING_ROT; requestedProperties += PROP_MATERIAL_DATA; + requestedProperties += PROP_MATERIAL_REPEAT; return requestedProperties; } @@ -119,6 +123,7 @@ void MaterialEntityItem::appendSubclassData(OctreePacketData* packetData, Encode APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, getMaterialMappingScale()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, getMaterialMappingRot()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_DATA, getMaterialData()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_REPEAT, getMaterialRepeat()); } void MaterialEntityItem::debugDump() const { @@ -128,6 +133,7 @@ void MaterialEntityItem::debugDump() const { qCDebug(entities) << " material url:" << _materialURL; qCDebug(entities) << " current material name:" << _currentMaterialName.c_str(); qCDebug(entities) << " material mapping mode:" << _materialMappingMode; + qCDebug(entities) << " material repeat:" << _materialRepeat; qCDebug(entities) << " priority:" << _priority; qCDebug(entities) << " parent material name:" << _parentMaterialName; qCDebug(entities) << " material mapping pos:" << _materialMappingPos; @@ -140,7 +146,12 @@ void MaterialEntityItem::debugDump() const { } void MaterialEntityItem::setUnscaledDimensions(const glm::vec3& value) { - EntityItem::setUnscaledDimensions(ENTITY_ITEM_DEFAULT_DIMENSIONS); + _desiredDimensions = value; + if (_materialMappingMode == MaterialMappingMode::UV) { + EntityItem::setUnscaledDimensions(ENTITY_ITEM_DEFAULT_DIMENSIONS); + } else if (_materialMappingMode == MaterialMappingMode::PROJECTED) { + EntityItem::setUnscaledDimensions(value); + } } std::shared_ptr MaterialEntityItem::getMaterial() const { @@ -208,6 +219,23 @@ void MaterialEntityItem::setMaterialData(const QString& materialData) { } } +void MaterialEntityItem::setMaterialMappingMode(MaterialMappingMode mode) { + if (_materialMappingMode != mode) { + removeMaterial(); + _materialMappingMode = mode; + setUnscaledDimensions(_desiredDimensions); + applyMaterial(); + } +} + +void MaterialEntityItem::setMaterialRepeat(bool repeat) { + if (_materialRepeat != repeat) { + removeMaterial(); + _materialRepeat = repeat; + applyMaterial(); + } +} + void MaterialEntityItem::setMaterialMappingPos(const glm::vec2& materialMappingPos) { if (_materialMappingPos != materialMappingPos) { removeMaterial(); @@ -256,6 +284,22 @@ void MaterialEntityItem::setParentID(const QUuid& parentID) { } } +void MaterialEntityItem::locationChanged(bool tellPhysics) { + EntityItem::locationChanged(); + if (_materialMappingMode == MaterialMappingMode::PROJECTED) { + removeMaterial(); + applyMaterial(); + } +} + +void MaterialEntityItem::dimensionsChanged() { + EntityItem::dimensionsChanged(); + if (_materialMappingMode == MaterialMappingMode::PROJECTED) { + removeMaterial(); + applyMaterial(); + } +} + void MaterialEntityItem::removeMaterial() { graphics::MaterialPointer material = getMaterial(); if (!material) { @@ -289,11 +333,19 @@ void MaterialEntityItem::applyMaterial() { if (!material || parentID.isNull()) { return; } + Transform textureTransform; - textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0.0f)); - textureTransform.setRotation(glm::vec3(0.0f, 0.0f, glm::radians(_materialMappingRot))); - textureTransform.setScale(glm::vec3(_materialMappingScale, 1.0f)); - material->setTextureTransforms(textureTransform); + if (_materialMappingMode == MaterialMappingMode::UV) { + textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0.0f)); + textureTransform.setRotation(glm::vec3(0.0f, 0.0f, glm::radians(_materialMappingRot))); + textureTransform.setScale(glm::vec3(_materialMappingScale, 1.0f)); + } else if (_materialMappingMode == MaterialMappingMode::PROJECTED) { + textureTransform = getTransform(); + textureTransform.postScale(getUnscaledDimensions()); + // Pass the inverse transform here so we don't need to compute it in the shaders + textureTransform.evalFromRawMatrix(textureTransform.getInverseMatrix()); + } + material->setTextureTransforms(textureTransform, _materialMappingMode, _materialRepeat); graphics::MaterialLayer materialLayer = graphics::MaterialLayer(material, getPriority()); diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h index 8aaa833db9..ba142d7719 100644 --- a/libraries/entities/src/MaterialEntityItem.h +++ b/libraries/entities/src/MaterialEntityItem.h @@ -58,7 +58,10 @@ public: void setCurrentMaterialName(const std::string& currentMaterialName); MaterialMappingMode getMaterialMappingMode() const { return _materialMappingMode; } - void setMaterialMappingMode(MaterialMappingMode mode) { _materialMappingMode = mode; } + void setMaterialMappingMode(MaterialMappingMode mode); + + bool getMaterialRepeat() const { return _materialRepeat; } + void setMaterialRepeat(bool repeat); quint16 getPriority() const { return _priority; } void setPriority(quint16 priority); @@ -80,6 +83,9 @@ public: void setParentID(const QUuid& parentID) override; + void locationChanged(bool tellPhysics) override; + void dimensionsChanged() override; + void applyMaterial(); void removeMaterial(); @@ -104,8 +110,10 @@ private: // emissiveMap, albedoMap (set opacityMap = albedoMap for transparency), metallicMap or specularMap, roughnessMap or glossMap, // normalMap or bumpMap, occlusionMap, lightmapMap (broken, FIXME), scatteringMap (only works if normal mapped) QString _materialURL; - // Type of material. "uv" or "projected". NOT YET IMPLEMENTED, only UV is used + // Type of material. "uv" or "projected". MaterialMappingMode _materialMappingMode { UV }; + bool _materialRepeat { true }; + glm::vec3 _desiredDimensions; // Priority for this material when applying it to its parent. Only the highest priority material will be used. Materials with the same priority are (essentially) randomly sorted. // Base materials that come with models always have priority 0. quint16 _priority { 0 }; diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index ab890cecca..5cf3ef9871 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -135,9 +135,11 @@ void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textur if (channel == MaterialKey::LIGHTMAP_MAP) { // update the texcoord1 with lightmap _schemaBuffer.edit()._texcoordTransforms[1] = (textureMap ? textureMap->getTextureTransform().getMatrix() : glm::mat4()); - _schemaBuffer.edit()._lightmapParams = (textureMap ? glm::vec4(textureMap->getLightmapOffsetScale(), 0.0, 0.0) : glm::vec4(0.0, 1.0, 0.0, 0.0)); + _schemaBuffer.edit()._lightmapParams = (textureMap ? glm::vec2(textureMap->getLightmapOffsetScale()) : glm::vec2(0.0, 1.0)); } + _schemaBuffer.edit()._materialParms = (textureMap ? glm::vec2(textureMap->getMappingMode(), textureMap->getRepeat()) : glm::vec2(MaterialMappingMode::UV, 1.0)); + _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); } @@ -216,13 +218,16 @@ bool Material::calculateMaterialInfo() const { return _hasCalculatedTextureInfo; } -void Material::setTextureTransforms(const Transform& transform) { +void Material::setTextureTransforms(const Transform& transform, MaterialMappingMode mode, bool repeat) { for (auto &textureMapItem : _textureMaps) { if (textureMapItem.second) { textureMapItem.second->setTextureTransform(transform); + textureMapItem.second->setMappingMode(mode); + textureMapItem.second->setRepeat(repeat); } } for (int i = 0; i < NUM_TEXCOORD_TRANSFORMS; i++) { _schemaBuffer.edit()._texcoordTransforms[i] = transform.getMatrix(); } + _schemaBuffer.edit()._materialParms = glm::vec2(mode, repeat); } \ No newline at end of file diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 0db78ab349..196c0d595c 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -22,6 +22,8 @@ #include #include +#include "MaterialMappingMode.h" + class Transform; namespace graphics { @@ -332,7 +334,11 @@ public: // Texture Coord Transform Array glm::mat4 _texcoordTransforms[NUM_TEXCOORD_TRANSFORMS]; - glm::vec4 _lightmapParams{ 0.0, 1.0, 0.0, 0.0 }; + glm::vec2 _lightmapParams { 0.0, 1.0 }; + + // x: material mode (0 for UV, 1 for PROJECTED) + // x: 1 for texture repeat, 0 for discard outside of 0 - 1 + glm::vec2 _materialParms { 0.0, 1.0 }; Schema() {} }; @@ -355,7 +361,7 @@ public: size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; } bool hasTextureInfo() const { return _hasCalculatedTextureInfo; } - void setTextureTransforms(const Transform& transform); + void setTextureTransforms(const Transform& transform, MaterialMappingMode mode, bool repeat); const std::string& getName() const { return _name; } diff --git a/libraries/graphics/src/graphics/Material.slh b/libraries/graphics/src/graphics/Material.slh index d2055b9a59..48b8415df5 100644 --- a/libraries/graphics/src/graphics/Material.slh +++ b/libraries/graphics/src/graphics/Material.slh @@ -19,20 +19,25 @@ const int MAX_TEXCOORDS = 2; struct TexMapArray { mat4 _texcoordTransforms0; mat4 _texcoordTransforms1; - vec4 _lightmapParams; + vec2 _lightmapParams; + vec2 _materialParams; }; <@func declareMaterialTexMapArrayBuffer()@> -<@func evalTexMapArrayTexcoord0(texMapArray, inTexcoord0, outTexcoord0)@> +<@func evalTexMapArrayTexcoord0(texMapArray, inTexcoord0, worldPosition, outTexcoord0)@> { - <$outTexcoord0$> = (<$texMapArray$>._texcoordTransforms0 * vec4(<$inTexcoord0$>.st, 0.0, 1.0)).st; + <$outTexcoord0$> = mix(<$texMapArray$>._texcoordTransforms0 * vec4(<$inTexcoord0$>.st, 0.0, 1.0), + <$texMapArray$>._texcoordTransforms0 * <$worldPosition$> + vec4(0.5), + <$texMapArray$>._materialParams.x).st; } <@endfunc@> -<@func evalTexMapArrayTexcoord1(texMapArray, inTexcoord1, outTexcoord1)@> +<@func evalTexMapArrayTexcoord1(texMapArray, inTexcoord1, worldPosition, outTexcoord1)@> { - <$outTexcoord1$> = (<$texMapArray$>._texcoordTransforms1 * vec4(<$inTexcoord1$>.st, 0.0, 1.0)).st; + <$outTexcoord1$> = mix(<$texMapArray$>._texcoordTransforms1 * vec4(<$inTexcoord1$>.st, 0.0, 1.0), + <$texMapArray$>._texcoordTransforms1 * <$worldPosition$> + vec4(0.5), + <$texMapArray$>._materialParams.x).st; } <@endfunc@> diff --git a/libraries/graphics/src/graphics/MaterialTextures.slh b/libraries/graphics/src/graphics/MaterialTextures.slh index db329c3852..82d89faf41 100644 --- a/libraries/graphics/src/graphics/MaterialTextures.slh +++ b/libraries/graphics/src/graphics/MaterialTextures.slh @@ -151,6 +151,9 @@ float fetchScatteringMap(vec2 uv) { <@func fetchMaterialTexturesCoord0(matKey, texcoord0, albedo, roughness, normal, metallic, emissive, scattering)@> + if (getTexMapArray()._materialParams.y != 1.0 && clamp(<$texcoord0$>, vec2(0.0), vec2(1.0)) != <$texcoord0$>) { + discard; + } <@if albedo@> vec4 <$albedo$> = (((<$matKey$> & (ALBEDO_MAP_BIT | OPACITY_MASK_MAP_BIT | OPACITY_TRANSLUCENT_MAP_BIT)) != 0) ? fetchAlbedoMap(<$texcoord0$>) : vec4(1.0)); <@endif@> @@ -188,7 +191,7 @@ float fetchScatteringMap(vec2 uv) { LAYOUT(binding=GRAPHICS_TEXTURE_MATERIAL_EMISSIVE_LIGHTMAP) uniform sampler2D emissiveMap; vec3 fetchLightmapMap(vec2 uv) { - vec2 lightmapParams = getTexMapArray()._lightmapParams.xy; + vec2 lightmapParams = getTexMapArray()._lightmapParams; return (vec3(lightmapParams.x) + lightmapParams.y * texture(emissiveMap, uv).rgb); } <@endfunc@> diff --git a/libraries/graphics/src/graphics/TextureMap.h b/libraries/graphics/src/graphics/TextureMap.h index 1678d9df98..eea9d2b31b 100755 --- a/libraries/graphics/src/graphics/TextureMap.h +++ b/libraries/graphics/src/graphics/TextureMap.h @@ -14,6 +14,7 @@ #include "gpu/Texture.h" #include "Transform.h" +#include "MaterialMappingMode.h" namespace graphics { @@ -30,6 +31,12 @@ public: void setTextureTransform(const Transform& texcoordTransform); const Transform& getTextureTransform() const { return _texcoordTransform; } + void setMappingMode(MaterialMappingMode mode) { _mappingMode = mode; } + MaterialMappingMode getMappingMode() const { return _mappingMode; } + + void setRepeat(bool repeat) { _repeat = repeat; } + bool getRepeat() const { return _repeat; } + void setUseAlphaChannel(bool useAlpha) { _useAlphaChannel = useAlpha; } bool useAlphaChannel() const { return _useAlphaChannel; } @@ -41,6 +48,8 @@ protected: Transform _texcoordTransform; glm::vec2 _lightmapOffsetScale{ 0.0f, 1.0f }; + MaterialMappingMode _mappingMode { MaterialMappingMode::UV }; + bool _repeat { true }; bool _useAlphaChannel{ false }; }; diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 9eed463d2d..fe61a6ad3f 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::FixedLightSerialization); + return static_cast(EntityVersion::MaterialRepeat); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 37a4b32940..d81d6e4931 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -245,7 +245,8 @@ enum class EntityVersion : PacketVersion { BloomEffect, GrabProperties, ScriptGlmVectors, - FixedLightSerialization + FixedLightSerialization, + MaterialRepeat }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/libraries/render-utils/src/deformed_model.slv b/libraries/render-utils/src/deformed_model.slv index 039ad0a7d9..8c6d3d049d 100644 --- a/libraries/render-utils/src/deformed_model.slv +++ b/libraries/render-utils/src/deformed_model.slv @@ -44,13 +44,13 @@ void main(void) { _color.rgb = color_sRGBToLinear(inColor.rgb); _color.a = inColor.a; - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _texCoord01.zw)$> - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToWorldAndEyeAndClipPos(cam, obj, deformedPosition, _positionWS, _positionES, gl_Position)$> <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS.xyz)$> + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> } diff --git a/libraries/render-utils/src/deformed_model_dq.slv b/libraries/render-utils/src/deformed_model_dq.slv index c6540c90b1..8f5f064022 100644 --- a/libraries/render-utils/src/deformed_model_dq.slv +++ b/libraries/render-utils/src/deformed_model_dq.slv @@ -42,13 +42,13 @@ void main(void) { _color.rgb = color_sRGBToLinear(inColor.rgb); _color.a = inColor.a; - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _texCoord01.zw)$> - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToWorldAndEyeAndClipPos(cam, obj, deformedPosition, _positionWS, _positionES, gl_Position)$> <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS.xyz)$> + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> } diff --git a/libraries/render-utils/src/deformed_model_normal_map.slv b/libraries/render-utils/src/deformed_model_normal_map.slv index 8627b5b856..85e164b639 100644 --- a/libraries/render-utils/src/deformed_model_normal_map.slv +++ b/libraries/render-utils/src/deformed_model_normal_map.slv @@ -43,14 +43,14 @@ void main(void) { _color.rgb = color_sRGBToLinear(inColor.rgb); _color.a = inColor.a; - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _texCoord01.zw)$> - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToWorldAndEyeAndClipPos(cam, obj, deformedPosition, _positionWS, _positionES, gl_Position)$> <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS.xyz)$> <$transformModelToWorldDir(cam, obj, deformedTangent, _tangentWS.xyz)$> + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> } diff --git a/libraries/render-utils/src/deformed_model_normal_map_dq.slv b/libraries/render-utils/src/deformed_model_normal_map_dq.slv index b45d94938a..807d343643 100644 --- a/libraries/render-utils/src/deformed_model_normal_map_dq.slv +++ b/libraries/render-utils/src/deformed_model_normal_map_dq.slv @@ -44,14 +44,14 @@ void main(void) { _color.rgb = color_sRGBToLinear(inColor.rgb); _color.a = inColor.a; - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _texCoord01.zw)$> - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToWorldAndEyeAndClipPos(cam, obj, deformedPosition, _positionWS, _positionES, gl_Position)$> <$transformModelToWorldDir(cam, obj, deformedNormal, _normalWS.xyz)$> <$transformModelToWorldDir(cam, obj, deformedTangent, _tangentWS.xyz)$> + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> } diff --git a/libraries/render-utils/src/model.slv b/libraries/render-utils/src/model.slv index f3d315c7a4..88cbd1e18c 100644 --- a/libraries/render-utils/src/model.slv +++ b/libraries/render-utils/src/model.slv @@ -31,13 +31,13 @@ void main(void) { _color.rgb = color_sRGBToLinear(inColor.rgb); _color.a = inColor.a; - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _texCoord01.zw)$> - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToWorldAndEyeAndClipPos(cam, obj, inPosition, _positionWS, _positionES, gl_Position)$> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> } diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv index 94d8a43b6e..0fd9a8b582 100644 --- a/libraries/render-utils/src/model_normal_map.slv +++ b/libraries/render-utils/src/model_normal_map.slv @@ -32,14 +32,14 @@ void main(void) { _color.rgb = color_sRGBToLinear(inColor.rgb); _color.a = inColor.a; - TexMapArray texMapArray = getTexMapArray(); - <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord01.xy)$> - <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _texCoord01.zw)$> - // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToWorldAndEyeAndClipPos(cam, obj, inPosition, _positionWS, _positionES, gl_Position)$> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normalWS)$> <$transformModelToWorldDir(cam, obj, inTangent.xyz, _tangentWS)$> + + TexMapArray texMapArray = getTexMapArray(); + <$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _positionWS, _texCoord01.xy)$> + <$evalTexMapArrayTexcoord1(texMapArray, inTexCoord1, _positionWS, _texCoord01.zw)$> } diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index c7c75a243b..1d9ec74ef6 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -565,6 +565,14 @@ const GROUPS = [ min: 0, propertyID: "priority", }, + { + label: "Material Mapping Mode", + type: "dropdown", + options: { + uv: "UV space", projected: "3D projected" + }, + propertyID: "materialMappingMode", + }, { label: "Material Position", type: "vec2", @@ -594,6 +602,11 @@ const GROUPS = [ unit: "deg", propertyID: "materialMappingRot", }, + { + label: "Material Repeat", + type: "bool", + propertyID: "materialRepeat", + }, ] }, { From 079d1dcbd694bd498d59a226b1ca550123467891 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 12 Nov 2018 18:00:28 -0800 Subject: [PATCH 021/117] convert clientOnly to entityHost and add local entities --- interface/src/AvatarBookmarks.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 5 +- .../scripting/WalletScriptingInterface.cpp | 2 +- .../ui/overlays/ContextOverlayInterface.cpp | 4 +- .../src/avatars-renderer/Avatar.cpp | 4 +- .../src/RenderableEntityItem.cpp | 13 +-- .../entities/src/EntityEditPacketSender.cpp | 9 ++- libraries/entities/src/EntityItem.cpp | 17 ++-- libraries/entities/src/EntityItem.h | 18 ++++- .../entities/src/EntityItemProperties.cpp | 79 +++++++++++++------ libraries/entities/src/EntityItemProperties.h | 4 +- .../entities/src/EntityPropertyFlags.cpp | 2 +- libraries/entities/src/EntityPropertyFlags.h | 2 +- .../entities/src/EntityPsuedoPropertyFlags.h | 2 + .../entities/src/EntityScriptingInterface.cpp | 31 +++++--- .../entities/src/EntityScriptingInterface.h | 39 +++++++-- libraries/entities/src/EntityTree.cpp | 12 ++- .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- libraries/physics/src/EntityMotionState.cpp | 10 +-- .../physics/src/PhysicalEntitySimulation.cpp | 4 +- scripts/system/attachedEntitiesManager.js | 2 +- scripts/system/avatarapp.js | 8 +- scripts/system/libraries/WebTablet.js | 3 +- .../system/libraries/entitySelectionTool.js | 2 +- scripts/system/marketplaces/marketplace.js | 2 +- scripts/system/nameTag.js | 4 +- scripts/system/tablet-ui/tabletUI.js | 2 +- 28 files changed, 187 insertions(+), 100 deletions(-) diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index ce21c68c3d..df7620013c 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -58,7 +58,7 @@ void addAvatarEntities(const QVariantList& avatarEntities) { EntityItemPropertiesFromScriptValueHonorReadOnly(scriptProperties, entityProperties); entityProperties.setParentID(myNodeID); - entityProperties.setClientOnly(true); + entityProperties.setEntityHost(EntityHost::AVATAR_ENTITY); entityProperties.setOwningAvatarID(myNodeID); entityProperties.setSimulationOwner(myNodeID, AVATAR_ENTITY_SIMULATION_PRIORITY); entityProperties.markAllChanged(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 876e64c592..ff6c7e4710 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -911,8 +911,7 @@ void MyAvatar::simulate(float deltaTime) { moveOperator.addEntityToMoveList(entity, newCube); } // send an edit packet to update the entity-server about the queryAABox - // unless it is client-only - if (packetSender && !entity->getClientOnly()) { + if (packetSender && entity->isDomainEntity()) { EntityItemProperties properties = entity->getProperties(); properties.setQueryAACubeDirty(); properties.setLastEdited(now); @@ -923,7 +922,7 @@ void MyAvatar::simulate(float deltaTime) { entity->forEachDescendant([&](SpatiallyNestablePointer descendant) { EntityItemPointer entityDescendant = std::dynamic_pointer_cast(descendant); - if (entityDescendant && !entityDescendant->getClientOnly() && descendant->updateQueryAACube()) { + if (entityDescendant && entityDescendant->isDomainEntity() && descendant->updateQueryAACube()) { EntityItemProperties descendantProperties; descendantProperties.setQueryAACube(descendant->getQueryAACube()); descendantProperties.setLastEdited(now); diff --git a/interface/src/scripting/WalletScriptingInterface.cpp b/interface/src/scripting/WalletScriptingInterface.cpp index 93ee60ba5b..6ad81f0e2b 100644 --- a/interface/src/scripting/WalletScriptingInterface.cpp +++ b/interface/src/scripting/WalletScriptingInterface.cpp @@ -35,7 +35,7 @@ void WalletScriptingInterface::proveAvatarEntityOwnershipVerification(const QUui QSharedPointer contextOverlayInterface = DependencyManager::get(); EntityItemProperties entityProperties = DependencyManager::get()->getEntityProperties(entityID, contextOverlayInterface->getEntityPropertyFlags()); - if (entityProperties.getClientOnly()) { + if (entityProperties.getEntityHost() == EntityHost::AVATAR_ENTITY) { if (!entityID.isNull() && entityProperties.getCertificateID().length() > 0) { contextOverlayInterface->requestOwnershipVerification(entityID); } else { diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index 11c268dd48..f6c213163d 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -46,7 +46,7 @@ ContextOverlayInterface::ContextOverlayInterface() { _entityPropertyFlags += PROP_DIMENSIONS; _entityPropertyFlags += PROP_REGISTRATION_POINT; _entityPropertyFlags += PROP_CERTIFICATE_ID; - _entityPropertyFlags += PROP_CLIENT_ONLY; + _entityPropertyFlags += PROP_ENTITY_HOST; _entityPropertyFlags += PROP_OWNING_AVATAR_ID; auto entityScriptingInterface = DependencyManager::get().data(); @@ -296,7 +296,7 @@ void ContextOverlayInterface::requestOwnershipVerification(const QUuid& entityID auto nodeList = DependencyManager::get(); if (entityProperties.verifyStaticCertificateProperties()) { - if (entityProperties.getClientOnly()) { + if (entityProperties.getEntityHost() == EntityHost::AVATAR_ENTITY) { SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer); if (entityServer) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index f694148b30..fcac61a0bd 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -310,7 +310,7 @@ void Avatar::updateAvatarEntities() { PerformanceTimer perfTimer("attachments"); // AVATAR ENTITY UPDATE FLOW - // - if queueEditEntityMessage sees clientOnly flag it does _myAvatar->updateAvatarEntity() + // - if queueEditEntityMessage sees avatarEntity flag it does _myAvatar->updateAvatarEntity() // - updateAvatarEntity saves the bytes and flags the trait instance for the entity as updated // - ClientTraitsHandler::sendChangedTraitsToMixer sends the entity bytes to the mixer which relays them to other interfaces // - AvatarHashMap::processBulkAvatarTraits on other interfaces calls avatar->processTraitInstace @@ -389,7 +389,7 @@ void Avatar::updateAvatarEntities() { QScriptValue scriptProperties = variantMapToScriptValue(asMap, scriptEngine); EntityItemProperties properties; EntityItemPropertiesFromScriptValueHonorReadOnly(scriptProperties, properties); - properties.setClientOnly(true); + properties.setEntityHost(EntityHost::AVATAR_ENTITY); properties.setOwningAvatarID(getID()); // there's no entity-server to tell us we're the simulation owner, so always set the diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index aa335bb7d5..9b9d0bb7a9 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -39,7 +39,7 @@ enum class RenderItemStatusIcon { SIMULATION_OWNER = 3, HAS_ACTIONS = 4, OTHER_SIMULATION_OWNER = 5, - CLIENT_ONLY = 6, + ENTITY_HOST = 6, NONE = 255 }; @@ -115,17 +115,20 @@ void EntityRenderer::makeStatusGetters(const EntityItemPointer& entity, Item::St }); statusGetters.push_back([entity, myNodeID] () -> render::Item::Status::Value { - if (entity->getClientOnly()) { + if (entity->isAvatarEntity()) { if (entity->getOwningAvatarID() == myNodeID) { return render::Item::Status::Value(1.0f, render::Item::Status::Value::GREEN, - (unsigned char)RenderItemStatusIcon::CLIENT_ONLY); + (unsigned char)RenderItemStatusIcon::ENTITY_HOST); } else { return render::Item::Status::Value(1.0f, render::Item::Status::Value::RED, - (unsigned char)RenderItemStatusIcon::CLIENT_ONLY); + (unsigned char)RenderItemStatusIcon::ENTITY_HOST); } + } else if (entity->isLocalEntity()) { + return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE, + (unsigned char)RenderItemStatusIcon::ENTITY_HOST); } return render::Item::Status::Value(0.0f, render::Item::Status::Value::GREEN, - (unsigned char)RenderItemStatusIcon::CLIENT_ONLY); + (unsigned char)RenderItemStatusIcon::ENTITY_HOST); }); } diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index 4aa66db227..0169bb6d9c 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -84,16 +84,19 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, EntityTreePointer entityTree, EntityItemID entityItemID, const EntityItemProperties& properties) { - if (properties.getClientOnly()) { + if (properties.getEntityHost() == EntityHost::AVATAR_ENTITY) { if (!_myAvatar) { - qCWarning(entities) << "Suppressing entity edit message: cannot send clientOnly edit with no myAvatar"; + qCWarning(entities) << "Suppressing entity edit message: cannot send avatar entity edit with no myAvatar"; } else if (properties.getOwningAvatarID() == _myAvatar->getID()) { // this is an avatar-based entity --> update our avatar-data rather than sending to the entity-server queueEditAvatarEntityMessage(type, entityTree, entityItemID, properties); } else { - qCWarning(entities) << "Suppressing entity edit message: cannot send clientOnly edit for another avatar"; + qCWarning(entities) << "Suppressing entity edit message: cannot send avatar entity edit for another avatar"; } return; + } else if (properties.getEntityHost() == EntityHost::LOCAL_ENTITY) { + // Don't send edits for local entities + return; } if (entityTree && entityTree->isServerlessMode()) { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 36ffc68fd3..8ffde04b23 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -119,7 +119,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_PARENT_JOINT_INDEX; requestedProperties += PROP_QUERY_AA_CUBE; - requestedProperties += PROP_CLIENT_ONLY; + requestedProperties += PROP_ENTITY_HOST; requestedProperties += PROP_OWNING_AVATAR_ID; requestedProperties += PROP_LAST_EDITED_BY; @@ -172,7 +172,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet EntityPropertyFlags propertyFlags(PROP_LAST_ITEM); EntityPropertyFlags requestedProperties = getEntityProperties(params); - requestedProperties -= PROP_CLIENT_ONLY; + requestedProperties -= PROP_ENTITY_HOST; requestedProperties -= PROP_OWNING_AVATAR_ID; // If we are being called for a subsequent pass at appendEntityData() that failed to completely encode this item, @@ -1278,10 +1278,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire EntityItemProperties properties(propertyFlags); properties._id = getID(); properties._idSet = true; - properties._created = getCreated(); properties._lastEdited = getLastEdited(); - properties.setClientOnly(getClientOnly()); - properties.setOwningAvatarID(getOwningAvatarID()); properties._type = getType(); @@ -1337,7 +1334,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire COPY_ENTITY_PROPERTY_TO_PROPERTIES(localPosition, getLocalPosition); COPY_ENTITY_PROPERTY_TO_PROPERTIES(localRotation, getLocalOrientation); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(clientOnly, getClientOnly); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(entityHost, getEntityHost); COPY_ENTITY_PROPERTY_TO_PROPERTIES(owningAvatarID, getOwningAvatarID); COPY_ENTITY_PROPERTY_TO_PROPERTIES(lastEditedBy, getLastEditedBy); @@ -1479,7 +1476,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex); SET_ENTITY_PROPERTY_FROM_PROPERTIES(queryAACube, setQueryAACube); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(clientOnly, setClientOnly); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(entityHost, setEntityHost); SET_ENTITY_PROPERTY_FROM_PROPERTIES(owningAvatarID, setOwningAvatarID); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lastEditedBy, setLastEditedBy); @@ -2496,7 +2493,7 @@ void EntityItem::dimensionsChanged() { bool EntityItem::getScalesWithParent() const { // keep this logic the same as in EntityItemProperties::getScalesWithParent - if (getClientOnly()) { + if (isAvatarEntity()) { QUuid ancestorID = findAncestorOfType(NestableType::Avatar); return !ancestorID.isNull(); } else { @@ -3277,7 +3274,7 @@ void EntityItem::prepareForSimulationOwnershipBid(EntityItemProperties& properti properties.setSimulationOwner(Physics::getSessionUUID(), priority); setPendingOwnershipPriority(priority); - properties.setClientOnly(getClientOnly()); + properties.setEntityHost(getEntityHost()); properties.setOwningAvatarID(getOwningAvatarID()); setLastBroadcast(now); // for debug/physics status icons -} +} \ No newline at end of file diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index c49017b2e0..e119595eb6 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -64,6 +64,12 @@ const uint64_t MAX_INCOMING_SIMULATION_UPDATE_PERIOD = MAX_OUTGOING_SIMULATION_U class MeshProxyList; +enum class EntityHost { + DOMAIN_ENTITY = 0, + AVATAR_ENTITY, + LOCAL_ENTITY +}; + /// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available /// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate /// one directly, instead you must only construct one of it's derived classes with additional features. @@ -478,9 +484,13 @@ public: void setScriptHasFinishedPreload(bool value); bool isScriptPreloadFinished(); - bool getClientOnly() const { return _clientOnly; } - virtual void setClientOnly(bool clientOnly) { _clientOnly = clientOnly; } - // if this entity is client-only, which avatar is it associated with? + bool isDomainEntity() const { return _entityHost == EntityHost::DOMAIN_ENTITY; } + bool isAvatarEntity() const { return _entityHost == EntityHost::AVATAR_ENTITY; } + bool isLocalEntity() const { return _entityHost == EntityHost::LOCAL_ENTITY; } + EntityHost getEntityHost() const { return _entityHost; } + virtual void setEntityHost(EntityHost entityHost) { _entityHost = entityHost; } + + // if this entity is an avatar entity, which avatar is it associated with? QUuid getOwningAvatarID() const { return _owningAvatarID; } virtual void setOwningAvatarID(const QUuid& owningAvatarID) { _owningAvatarID = owningAvatarID; } @@ -673,7 +683,7 @@ protected: QUuid _sourceUUID; /// the server node UUID we came from - bool _clientOnly { false }; + EntityHost _entityHost { EntityHost::DOMAIN_ENTITY }; bool _transitingWithAvatar{ false }; QUuid _owningAvatarID; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index c243f772e2..ff8da64f60 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -306,6 +306,29 @@ void EntityItemProperties::setMaterialMappingModeFromString(const QString& mater } } +QString EntityItemProperties::getEntityHostAsString() const { + switch (_entityHost) { + case EntityHost::DOMAIN_ENTITY: + return "domain"; + case EntityHost::AVATAR_ENTITY: + return "avatar"; + case EntityHost::LOCAL_ENTITY: + return "local"; + default: + return ""; + } +} + +void EntityItemProperties::setEntityHostFromString(const QString& entityHost) { + if (entityHost == "domain") { + _entityHost = EntityHost::DOMAIN_ENTITY; + } else if (entityHost == "avatar") { + _entityHost = EntityHost::AVATAR_ENTITY; + } else if (entityHost == "local") { + _entityHost = EntityHost::LOCAL_ENTITY; + } +} + EntityPropertyFlags EntityItemProperties::getChangedProperties() const { EntityPropertyFlags changedProperties; @@ -453,7 +476,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_GHOSTING_ALLOWED, ghostingAllowed); CHECK_PROPERTY_CHANGE(PROP_FILTER_URL, filterURL); - CHECK_PROPERTY_CHANGE(PROP_CLIENT_ONLY, clientOnly); + CHECK_PROPERTY_CHANGE(PROP_ENTITY_HOST, entityHost); CHECK_PROPERTY_CHANGE(PROP_OWNING_AVATAR_ID, owningAvatarID); CHECK_PROPERTY_CHANGE(PROP_SHAPE, shape); @@ -489,12 +512,18 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Entities.EntityType} type - The entity type. You cannot change the type of an entity after it's created. (Though * its value may switch among "Box", "Shape", and "Sphere" depending on changes to * the shape property set for entities of these types.) Read-only. - * @property {boolean} clientOnly=false - If true then the entity is an avatar entity; otherwise it is a server - * entity. An avatar entity follows you to each domain you visit, rendering at the same world coordinates unless it's - * parented to your avatar. Value cannot be changed after the entity is created.
- * The value can also be set at entity creation by using the clientOnly parameter in + * @property {EntityHost} entityHost="domain" - How this entity will behave, including if and how it is sent to other people. + * The value can only be set at entity creation by using the entityHost parameter in * {@link Entities.addEntity}. - * @property {Uuid} owningAvatarID=Uuid.NULL - The session ID of the owning avatar if clientOnly is + * @property {boolean} avatarEntity=false - If true then the entity is an avatar entity; An avatar entity follows you to each domain you visit, + * rendering at the same world coordinates unless it's parented to your avatar. Value cannot be changed after the entity is created.
+ * The value can only be set at entity creation by using the entityHost parameter in + * {@link Entities.addEntity}. clientOnly is an alias. + * @property {boolean} localEntity=false - If true then the entity is a local entity; Local entities only render for you and are not sent over the wire. + * Value cannot be changed after the entity is created.
+ * The value can only be set at entity creation by using the entityHost parameter in + * {@link Entities.addEntity}. + * @property {Uuid} owningAvatarID=Uuid.NULL - The session ID of the owning avatar if avatarEntity is * true, otherwise {@link Uuid|Uuid.NULL}. Read-only. * * @property {string} created - The UTC date and time that the entity was created, in ISO 8601 format as @@ -594,7 +623,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} parentJointIndex=65535 - The joint of the entity or avatar that this entity is parented to. Use * 65535 or -1 to parent to the entity or avatar's position and orientation rather than a joint. * @property {Vec3} localPosition=0,0,0 - The position of the entity relative to its parent if the entity is parented, - * otherwise the same value as position. If the entity is parented to an avatar and is clientOnly + * otherwise the same value as position. If the entity is parented to an avatar and is an avatarEntity * so that it scales with the avatar, this value remains the original local position value while the avatar scale changes. * @property {Quat} localRotation=0,0,0,1 - The rotation of the entity relative to its parent if the entity is parented, * otherwise the same value as rotation. @@ -602,8 +631,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * otherwise the same value as velocity. * @property {Vec3} localAngularVelocity=0,0,0 - The angular velocity of the entity relative to its parent if the entity is * parented, otherwise the same value as position. - * @property {Vec3} localDimensions - The dimensions of the entity. If the entity is parented to an avatar and is - * clientOnly so that it scales with the avatar, this value remains the original dimensions value while the + * @property {Vec3} localDimensions - The dimensions of the entity. If the entity is parented to an avatar and is an + * avatarEntity so that it scales with the avatar, this value remains the original dimensions value while the * avatar scale changes. * * @property {Entities.BoundingBox} boundingBox - The axis-aligned bounding box that tightly encloses the entity. @@ -628,7 +657,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {boolean} cloneDynamic=false - If true then clones created from this entity will have their * dynamic property set to true. * @property {boolean} cloneAvatarEntity=false - If true then clones created from this entity will be created as - * avatar entities: their clientOnly property will be set to true. + * avatar entities: their avatarEntity property will be set to true. * @property {Uuid} cloneOriginID - The ID of the entity that this entity was cloned from. * * @property {Entities.Grab} grab - The grab-related properties. @@ -739,7 +768,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * overlay's ID. * To apply a material to an avatar, set the material entity's parentID property to the avatar's session UUID. * To apply a material to your avatar such that it persists across domains and log-ins, create the material as an avatar entity - * by setting the clientOnly parameter in {@link Entities.addEntity} to true. + * by setting the entityHost parameter in {@link Entities.addEntity} to "avatar". * Material entities render as non-scalable spheres if they don't have their parent set. * @typedef {object} Entities.EntityProperties-Material * @property {string} materialURL="" - URL to a {@link MaterialResource}. If you append ?name to the URL, the @@ -1527,8 +1556,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ANGULAR_VELOCITY, localAngularVelocity); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_DIMENSIONS, localDimensions); - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLIENT_ONLY, clientOnly); // Gettable but not settable except at entity creation - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_OWNING_AVATAR_ID, owningAvatarID); // Gettable but not settable + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ENTITY_HOST, entityHost, getEntityHostAsString()); // Gettable but not settable except at entity creation + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_OWNING_AVATAR_ID, owningAvatarID); // Gettable but not settable COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONEABLE, cloneable); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONE_LIFETIME, cloneLifetime); @@ -1567,12 +1596,14 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(renderInfo, renderInfo); // Gettable but not settable } - // FIXME: These properties should already have been set above. if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::ClientOnly)) { - properties.setProperty("clientOnly", convertScriptValue(engine, getClientOnly())); + properties.setProperty("clientOnly", convertScriptValue(engine, getEntityHost() == EntityHost::AVATAR_ENTITY)); } - if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::OwningAvatarID)) { - properties.setProperty("owningAvatarID", convertScriptValue(engine, getOwningAvatarID())); + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::AvatarEntity)) { + properties.setProperty("avatarEntity", convertScriptValue(engine, getEntityHost() == EntityHost::AVATAR_ENTITY)); + } + if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::LocalEntity)) { + properties.setProperty("localEntity", convertScriptValue(engine, getEntityHost() == EntityHost::LOCAL_ENTITY)); } // FIXME - I don't think these properties are supported any more @@ -1761,7 +1792,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(ghostingAllowed, bool, setGhostingAllowed); COPY_PROPERTY_FROM_QSCRIPTVALUE(filterURL, QString, setFilterURL); - COPY_PROPERTY_FROM_QSCRIPTVALUE(clientOnly, bool, setClientOnly); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(entityHost, EntityHost); COPY_PROPERTY_FROM_QSCRIPTVALUE(owningAvatarID, QUuid, setOwningAvatarID); COPY_PROPERTY_FROM_QSCRIPTVALUE(dpi, uint16_t, setDPI); @@ -1927,7 +1958,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(ghostingAllowed); COPY_PROPERTY_IF_CHANGED(filterURL); - COPY_PROPERTY_IF_CHANGED(clientOnly); + COPY_PROPERTY_IF_CHANGED(entityHost); COPY_PROPERTY_IF_CHANGED(owningAvatarID); COPY_PROPERTY_IF_CHANGED(dpi); @@ -3213,7 +3244,7 @@ void EntityItemProperties::markAllChanged() { _ghostingAllowedChanged = true; _filterURLChanged = true; - _clientOnlyChanged = true; + _entityHostChanged = true; _owningAvatarIDChanged = true; _dpiChanged = true; @@ -3712,8 +3743,8 @@ QList EntityItemProperties::listChangedProperties() { out += "queryAACube"; } - if (clientOnlyChanged()) { - out += "clientOnly"; + if (entityHostChanged()) { + out += "entityHost"; } if (owningAvatarIDChanged()) { out += "owningAvatarID"; @@ -3788,7 +3819,7 @@ bool EntityItemProperties::getScalesWithParent() const { if (success && parent) { bool avatarAncestor = (parent->getNestableType() == NestableType::Avatar || parent->hasAncestorOfType(NestableType::Avatar)); - scalesWithParent = getClientOnly() && avatarAncestor; + scalesWithParent = getEntityHost() == EntityHost::AVATAR_ENTITY && avatarAncestor; } } return scalesWithParent; @@ -3946,7 +3977,7 @@ void EntityItemProperties::convertToCloneProperties(const EntityItemID& entityID setParentJointIndex(-1); setLifetime(getCloneLifetime()); setDynamic(getCloneDynamic()); - setClientOnly(getCloneAvatarEntity()); + setEntityHost(getCloneAvatarEntity() ? EntityHost::AVATAR_ENTITY : EntityHost::DOMAIN_ENTITY); setCreated(usecTimestampNow()); setLastEdited(usecTimestampNow()); setCloneable(ENTITY_ITEM_DEFAULT_CLONEABLE); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index c91ccda5aa..9e666bca1b 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -279,7 +279,7 @@ public: DEFINE_PROPERTY(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool, ZoneEntityItem::DEFAULT_GHOSTING_ALLOWED); DEFINE_PROPERTY(PROP_FILTER_URL, FilterURL, filterURL, QString, ZoneEntityItem::DEFAULT_FILTER_URL); - DEFINE_PROPERTY(PROP_CLIENT_ONLY, ClientOnly, clientOnly, bool, false); + DEFINE_PROPERTY_REF_ENUM(PROP_ENTITY_HOST, EntityHost, entityHost, EntityHost, EntityHost::DOMAIN_ENTITY); DEFINE_PROPERTY_REF(PROP_OWNING_AVATAR_ID, OwningAvatarID, owningAvatarID, QUuid, UNKNOWN_ENTITY_ID); DEFINE_PROPERTY_REF(PROP_DPI, DPI, dpi, uint16_t, ENTITY_ITEM_DEFAULT_DPI); @@ -589,7 +589,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, GhostingAllowed, ghostingAllowed, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, FilterURL, filterURL, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, ClientOnly, clientOnly, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EntityHostAsString, entityHost, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, OwningAvatarID, owningAvatarID, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, LastEditedBy, lastEditedBy, ""); diff --git a/libraries/entities/src/EntityPropertyFlags.cpp b/libraries/entities/src/EntityPropertyFlags.cpp index c077b153b8..ff95e40fde 100644 --- a/libraries/entities/src/EntityPropertyFlags.cpp +++ b/libraries/entities/src/EntityPropertyFlags.cpp @@ -121,7 +121,7 @@ QDebug& operator<<(QDebug& dbg, const EntityPropertyFlags& f) { result = f.getHasProperty(PROP_FALLOFF_RADIUS) ? result + "falloffRadius " : result; result = f.getHasProperty(PROP_FLYING_ALLOWED) ? result + "flyingAllowed " : result; result = f.getHasProperty(PROP_GHOSTING_ALLOWED) ? result + "ghostingAllowed " : result; - result = f.getHasProperty(PROP_CLIENT_ONLY) ? result + "clientOnly " : result; + result = f.getHasProperty(PROP_ENTITY_HOST) ? result + "entityHost " : result; result = f.getHasProperty(PROP_OWNING_AVATAR_ID) ? result + "owningAvatarID " : result; result = f.getHasProperty(PROP_SHAPE) ? result + "shape " : result; result = f.getHasProperty(PROP_DPI) ? result + "dpi " : result; diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index d2f687fbd3..7f1d48acdf 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -176,7 +176,7 @@ enum EntityPropertyList { PROP_FLYING_ALLOWED, // can avatars in a zone fly? PROP_GHOSTING_ALLOWED, // can avatars in a zone turn off physics? - PROP_CLIENT_ONLY, // doesn't go over wire + PROP_ENTITY_HOST, // doesn't go over wire PROP_OWNING_AVATAR_ID, // doesn't go over wire PROP_SHAPE, diff --git a/libraries/entities/src/EntityPsuedoPropertyFlags.h b/libraries/entities/src/EntityPsuedoPropertyFlags.h index 0b051a4c74..26c2a14015 100644 --- a/libraries/entities/src/EntityPsuedoPropertyFlags.h +++ b/libraries/entities/src/EntityPsuedoPropertyFlags.h @@ -32,6 +32,8 @@ namespace EntityPsuedoPropertyFlag { RenderInfo, ClientOnly, OwningAvatarID, + AvatarEntity, + LocalEntity, NumFlags }; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 3491688588..969e69f048 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -470,7 +470,7 @@ void synchronizeEditedGrabProperties(EntityItemProperties& properties, const QSt } -QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties, bool clientOnly) { +QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties, const QString& entityHostString) { PROFILE_RANGE(script_entities, __FUNCTION__); _activityTracking.addedEntityCount++; @@ -479,8 +479,8 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties const auto sessionID = nodeList->getSessionUUID(); EntityItemProperties propertiesWithSimID = properties; - if (clientOnly) { - propertiesWithSimID.setClientOnly(clientOnly); + propertiesWithSimID.setEntityHostFromString(entityHostString); + if (propertiesWithSimID.getEntityHost() == EntityHost::AVATAR_ENTITY) { propertiesWithSimID.setOwningAvatarID(sessionID); } @@ -568,8 +568,11 @@ QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) { bool cloneAvatarEntity = properties.getCloneAvatarEntity(); properties.convertToCloneProperties(entityIDToClone); - if (cloneAvatarEntity) { - return addEntity(properties, true); + if (properties.getEntityHost() == EntityHost::LOCAL_ENTITY) { + // Local entities are only cloned locally + return addEntity(properties, "local"); + } else if (cloneAvatarEntity) { + return addEntity(properties, "avatar"); } else { // setLastEdited timestamp to 0 to ensure this entity gets updated with the properties // from the server-created entity, don't change this unless you know what you are doing @@ -681,6 +684,10 @@ QScriptValue EntityScriptingInterface::getMultipleEntityPropertiesInternal(QScri psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::ClientOnly); } else if (extendedPropertyString == "owningAvatarID") { psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::OwningAvatarID); + } else if (extendedPropertyString == "avatarEntity") { + psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::AvatarEntity); + } else if (extendedPropertyString == "localEntity") { + psuedoPropertyFlags.set(EntityPsuedoPropertyFlag::LocalEntity); } }; @@ -784,7 +791,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& return; } - if (entity->getClientOnly() && entity->getOwningAvatarID() != sessionID) { + if (entity->isAvatarEntity() && entity->getOwningAvatarID() != sessionID) { // don't edit other avatar's avatarEntities properties = EntityItemProperties(); return; @@ -827,7 +834,7 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& } // set these to make EntityItemProperties::getScalesWithParent() work correctly - properties.setClientOnly(entity->getClientOnly()); + properties.setEntityHost(entity->getEntityHost()); properties.setOwningAvatarID(entity->getOwningAvatarID()); // make sure the properties has a type, so that the encode can know which properties to include @@ -952,7 +959,7 @@ void EntityScriptingInterface::deleteEntity(QUuid id) { auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); - if (entity->getClientOnly() && entity->getOwningAvatarID() != myNodeID) { + if (entity->isAvatarEntity() && entity->getOwningAvatarID() != myNodeID) { // don't delete other avatar's avatarEntities // If you actually own the entity but the onwership property is not set because of a domain switch // The lines below makes sure the entity is deleted once its properties are set. @@ -967,11 +974,11 @@ void EntityScriptingInterface::deleteEntity(QUuid id) { shouldSendDeleteToServer = false; } else { // only delete local entities, server entities will round trip through the server filters - if (entity->getClientOnly() || _entityTree->isServerlessMode()) { + if (entity->isAvatarEntity() || _entityTree->isServerlessMode()) { shouldSendDeleteToServer = false; _entityTree->deleteEntity(entityID); - if (entity->getClientOnly() && getEntityPacketSender()->getMyAvatar()) { + if (entity->isAvatarEntity() && getEntityPacketSender()->getMyAvatar()) { getEntityPacketSender()->getMyAvatar()->clearAvatarEntity(entityID, false); } } @@ -1638,14 +1645,14 @@ bool EntityScriptingInterface::actionWorker(const QUuid& entityID, return; } - if (entity->getClientOnly() && entity->getOwningAvatarID() != myNodeID) { + if (entity->isAvatarEntity() && entity->getOwningAvatarID() != myNodeID) { return; } doTransmit = actor(simulation, entity); _entityTree->entityChanged(entity); if (doTransmit) { - properties.setClientOnly(entity->getClientOnly()); + properties.setEntityHost(entity->getEntityHost()); properties.setOwningAvatarID(entity->getOwningAvatarID()); } }); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index df7b0df9a1..78d71ac76b 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -233,13 +233,29 @@ public slots: */ Q_INVOKABLE bool canReplaceContent(); + /**jsdoc + *

How an entity is sent over the wire.

+ * + * + * + * + * + * + * + * + * + *
ValueDescription
domainDomain entities are sent over the entity server to everyone else
avatarAvatar entities are sent over the avatar entity and are associated with one avatar
localLocal entities are not sent over the wire and will only render for you, locally
+ * @typedef {string} EntityHost + */ + /**jsdoc * Add a new entity with specified properties. * @function Entities.addEntity * @param {Entities.EntityProperties} properties - The properties of the entity to create. - * @param {boolean} [clientOnly=false] - If true, or if clientOnly is set true in - * the properties, the entity is created as an avatar entity; otherwise it is created on the server. An avatar entity + * @param {EntityHost} [entityHost="domain"] - If "avatar" the entity is created as an avatar entity. An avatar entity * follows you to each domain you visit, rendering at the same world coordinates unless it's parented to your avatar. + * If "local", the entity is created as a local entity, which will only render for you and isn't sent over the wire. + * Otherwise it is created as a normal entity and sent over the entity server. * @returns {Uuid} The ID of the entity if successfully created, otherwise {@link Uuid|Uuid.NULL}. * @example Create a box entity in front of your avatar. * var entityID = Entities.addEntity({ @@ -250,7 +266,19 @@ public slots: * }); * print("Entity created: " + entityID); */ - Q_INVOKABLE QUuid addEntity(const EntityItemProperties& properties, bool clientOnly = false); + Q_INVOKABLE QUuid addEntity(const EntityItemProperties& properties, const QString& entityHostString); + + /**jsdoc + * Add a new entity with specified properties. + * @function Entities.addEntity + * @param {Entities.EntityProperties} properties - The properties of the entity to create. + * @param {boolean} [avatarEntity=false] - Whether to create an avatar entity or a domain entity + * @returns {Uuid} The ID of the entity if successfully created, otherwise {@link Uuid|Uuid.NULL}. + */ + Q_INVOKABLE QUuid addEntity(const EntityItemProperties& properties, bool avatarEntity = false) { + QString entityHost = avatarEntity ? "avatar" : "domain"; + return addEntity(properties, entityHost); + } /// temporary method until addEntity can be used from QJSEngine /// Deliberately not adding jsdoc, only used internally. @@ -896,8 +924,7 @@ public slots: Q_INVOKABLE bool appendPoint(QUuid entityID, const glm::vec3& point); /**jsdoc - * Dumps debug information about all entities in Interface's local in-memory tree of entities it knows about — domain - * and client-only — to the program log. + * Dumps debug information about all entities in Interface's local in-memory tree of entities it knows about to the program log. * @function Entities.dumpTree */ Q_INVOKABLE void dumpTree() const; @@ -1870,7 +1897,7 @@ signals: /**jsdoc * Triggered when an entity is added to Interface's local in-memory tree of entities it knows about. This may occur when * entities are loaded upon visiting a domain, when the user rotates their view so that more entities become visible, and - * when a domain or client-only entity is added (e.g., by {@Entities.addEntity|addEntity}). + * when any type of entity is added (e.g., by {@Entities.addEntity|addEntity}). * @function Entities.addingEntity * @param {Uuid} entityID - The ID of the entity added. * @returns {Signal} diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 16d7e74703..1abdd15314 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -541,7 +541,7 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti return nullptr; } - if (!properties.getClientOnly() && getIsClient() && + if (properties.getEntityHost() == EntityHost::DOMAIN_ENTITY && getIsClient() && !nodeList->getThisNodeCanRez() && !nodeList->getThisNodeCanRezTmp() && !nodeList->getThisNodeCanRezCertified() && !nodeList->getThisNodeCanRezTmpCertified() && !_serverlessDomain && !isClone) { return nullptr; @@ -2668,7 +2668,15 @@ bool EntityTree::readFromMap(QVariantMap& map) { entityItemID = EntityItemID(QUuid::createUuid()); } - if (properties.getClientOnly()) { + // Convert old clientOnly bool to new entityHost enum + // (must happen before setOwningAvatarID below) + if (contentVersion < (int)EntityVersion::EntityHosts) { + if (entityMap.contains("clientOnly")) { + properties.setEntityHost(entityMap["clientOnly"].toBool() ? EntityHost::AVATAR_ENTITY : EntityHost::DOMAIN_ENTITY); + } + } + + if (properties.getEntityHost() == EntityHost::AVATAR_ENTITY) { auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); properties.setOwningAvatarID(myNodeID); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 9eed463d2d..62ff742793 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::FixedLightSerialization); + return static_cast(EntityVersion::EntityHosts); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 37a4b32940..284760ea38 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -245,7 +245,8 @@ enum class EntityVersion : PacketVersion { BloomEffect, GrabProperties, ScriptGlmVectors, - FixedLightSerialization + FixedLightSerialization, + EntityHosts }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index c920665279..aaae31abb1 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -80,8 +80,8 @@ EntityMotionState::EntityMotionState(btCollisionShape* shape, EntityItemPointer // rather than pass the legit shape pointer to the ObjectMotionState ctor above. setShape(shape); - if (_entity->getClientOnly() && _entity->getOwningAvatarID() != Physics::getSessionUUID()) { - // client-only entities are always thus, so we cache this fact in _ownershipState + if (_entity->isAvatarEntity() && _entity->getOwningAvatarID() != Physics::getSessionUUID()) { + // avatar entities entities are always thus, so we cache this fact in _ownershipState _ownershipState = EntityMotionState::OwnershipState::Unownable; } @@ -430,7 +430,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) { assert(entityTreeIsLocked()); // this case is prevented by setting _ownershipState to UNOWNABLE in EntityMotionState::ctor - assert(!(_entity->getClientOnly() && _entity->getOwningAvatarID() != Physics::getSessionUUID())); + assert(!(_entity->isAvatarEntity() && _entity->getOwningAvatarID() != Physics::getSessionUUID())); if (_entity->getTransitingWithAvatar()) { return false; @@ -595,7 +595,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ EntityTreeElementPointer element = _entity->getElement(); EntityTreePointer tree = element ? element->getTree() : nullptr; - properties.setClientOnly(_entity->getClientOnly()); + properties.setEntityHost(_entity->getEntityHost()); properties.setOwningAvatarID(_entity->getOwningAvatarID()); entityPacketSender->queueEditEntityMessage(PacketType::EntityPhysics, tree, id, properties); @@ -610,7 +610,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ EntityItemProperties newQueryCubeProperties; newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube()); newQueryCubeProperties.setLastEdited(properties.getLastEdited()); - newQueryCubeProperties.setClientOnly(entityDescendant->getClientOnly()); + newQueryCubeProperties.setEntityHost(entityDescendant->getEntityHost()); newQueryCubeProperties.setOwningAvatarID(entityDescendant->getOwningAvatarID()); entityPacketSender->queueEditEntityMessage(PacketType::EntityPhysics, tree, diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index ab8bfb8290..8e5248f6a9 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -79,7 +79,7 @@ void PhysicalEntitySimulation::removeEntityInternal(EntityItemPointer entity) { _deadEntities.insert(entity); } } - if (entity->getClientOnly()) { + if (entity->isAvatarEntity()) { _deadAvatarEntities.insert(entity); } } @@ -339,7 +339,7 @@ void PhysicalEntitySimulation::handleDeactivatedMotionStates(const VectorOfMotio EntityItemPointer entity = entityState->getEntity(); _entitiesToSort.insert(entity); if (!serverlessMode) { - if (entity->getClientOnly()) { + if (entity->isAvatarEntity()) { switch (entityState->getOwnershipState()) { case EntityMotionState::OwnershipState::PendingBid: _bids.removeFirst(entityState); diff --git a/scripts/system/attachedEntitiesManager.js b/scripts/system/attachedEntitiesManager.js index c0144e772f..061e27f595 100644 --- a/scripts/system/attachedEntitiesManager.js +++ b/scripts/system/attachedEntitiesManager.js @@ -186,7 +186,7 @@ function AttachedEntitiesManager() { delete wearProps.actionData; delete wearProps.sittingPoints; delete wearProps.boundingBox; - delete wearProps.clientOnly; + delete wearProps.avatarEntity; delete wearProps.owningAvatarID; delete wearProps.localPosition; delete wearProps.localRotation; diff --git a/scripts/system/avatarapp.js b/scripts/system/avatarapp.js index a55ed74a86..16a5760358 100644 --- a/scripts/system/avatarapp.js +++ b/scripts/system/avatarapp.js @@ -328,8 +328,8 @@ function isGrabbable(entityID) { return false; } - var properties = Entities.getEntityProperties(entityID, ['clientOnly', 'grab.grabbable']); - if (properties.clientOnly) { + var properties = Entities.getEntityProperties(entityID, ['avatarEntity', 'grab.grabbable']); + if (properties.avatarEntity) { return properties.grab.grabbable; } @@ -337,8 +337,8 @@ function isGrabbable(entityID) { } function setGrabbable(entityID, grabbable) { - var properties = Entities.getEntityProperties(entityID, ['clientOnly']); - if (properties.clientOnly) { + var properties = Entities.getEntityProperties(entityID, ['avatarEntity']); + if (properties.avatarEntity) { Entities.editEntity(entityID, { grab: { grabbable: grabbable }}); } } diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index 8e5b41deda..f29edd8ff9 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -97,9 +97,8 @@ cleanUpOldMaterialEntities = function() { * @param width [number] width in meters of the tablet model * @param dpi [number] dpi of web surface used to show the content. * @param hand [number] -1 indicates no hand, Controller.Standard.RightHand or Controller.Standard.LeftHand - * @param clientOnly [bool] true indicates tablet model is only visible to client. */ -WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) { +WebTablet = function (url, width, dpi, hand, location, visible) { var _this = this; diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 168c81db1f..d1dbd31019 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -264,7 +264,7 @@ SelectionManager = (function() { if (properties === undefined) { properties = Entities.getEntityProperties(originalEntityID); } - if (!properties.locked && (!properties.clientOnly || properties.owningAvatarID === MyAvatar.sessionUUID)) { + if (!properties.locked && (!properties.avatarEntity || properties.owningAvatarID === MyAvatar.sessionUUID)) { if (nonDynamicEntityIsBeingGrabbedByAvatar(properties)) { properties.parentID = null; properties.parentJointIndex = null; diff --git a/scripts/system/marketplaces/marketplace.js b/scripts/system/marketplaces/marketplace.js index d90695c767..d3e5c96739 100644 --- a/scripts/system/marketplaces/marketplace.js +++ b/scripts/system/marketplaces/marketplace.js @@ -30,7 +30,7 @@ var TOOLBAR_MARGIN_Y = 0; var marketplaceVisible = false; var marketplaceWebTablet; -// We persist clientOnly data in the .ini file, and reconsistitute it on restart. +// We persist avatarEntity data in the .ini file, and reconsistitute it on restart. // To keep things consistent, we pickle the tablet data in Settings, and kill any existing such on restart and domain change. var persistenceKey = "io.highfidelity.lastDomainTablet"; diff --git a/scripts/system/nameTag.js b/scripts/system/nameTag.js index 69e5dac1bf..147da25779 100644 --- a/scripts/system/nameTag.js +++ b/scripts/system/nameTag.js @@ -12,7 +12,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -const CLIENTONLY = false; +const AVATARENTITY = false; const ENTITY_CHECK_INTERVAL = 5000; // ms = 5 seconds const STARTUP_DELAY = 2000; // ms = 2 second const OLD_AGE = 3500; // we recreate the entity if older than this time in seconds @@ -43,7 +43,7 @@ function addNameTag() { dimensions: dimensionsFromName(), position: nameTagPosition } - nameTagEntityID = Entities.addEntity(nameTagProperties, CLIENTONLY); + nameTagEntityID = Entities.addEntity(nameTagProperties, AVATARENTITY); } function updateNameTag() { diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 9a22014895..f9e9165f2e 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -108,7 +108,7 @@ tabletScalePercentage = getTabletScalePercentageFromSettings(); UIWebTablet = new WebTablet("hifi/tablet/TabletRoot.qml", DEFAULT_WIDTH * (tabletScalePercentage / 100), - null, activeHand, true, null, false); + null, activeHand, null, false); UIWebTablet.register(); HMD.tabletID = UIWebTablet.tabletEntityID; HMD.homeButtonID = UIWebTablet.homeButtonID; From 8dbb2d806be046a38500ca1de49a015b10045aff Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 14 Nov 2018 14:48:07 -0800 Subject: [PATCH 022/117] local entities are always collisionless --- libraries/entities/src/EntityItemProperties.cpp | 8 +++++++- libraries/entities/src/EntityScriptingInterface.cpp | 10 +++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index ff8da64f60..bcd53a2420 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -3977,7 +3977,13 @@ void EntityItemProperties::convertToCloneProperties(const EntityItemID& entityID setParentJointIndex(-1); setLifetime(getCloneLifetime()); setDynamic(getCloneDynamic()); - setEntityHost(getCloneAvatarEntity() ? EntityHost::AVATAR_ENTITY : EntityHost::DOMAIN_ENTITY); + if (getEntityHost() != EntityHost::LOCAL_ENTITY) { + setEntityHost(getCloneAvatarEntity() ? EntityHost::AVATAR_ENTITY : EntityHost::DOMAIN_ENTITY); + } else { + // Local Entities clone as local entities + setEntityHost(EntityHost::LOCAL_ENTITY); + setCollisionless(true); + } setCreated(usecTimestampNow()); setLastEdited(usecTimestampNow()); setCloneable(ENTITY_ITEM_DEFAULT_CLONEABLE); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 969e69f048..ffd7748c37 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -482,6 +482,10 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties propertiesWithSimID.setEntityHostFromString(entityHostString); if (propertiesWithSimID.getEntityHost() == EntityHost::AVATAR_ENTITY) { propertiesWithSimID.setOwningAvatarID(sessionID); + } else if (propertiesWithSimID.getEntityHost() == EntityHost::LOCAL_ENTITY) { + // For now, local entities are always collisionless + // TODO: create a separate, local physics simulation that just handles local entities (and MyAvatar?) + propertiesWithSimID.setCollisionless(true); } propertiesWithSimID.setLastEditedBy(sessionID); @@ -834,7 +838,11 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& } // set these to make EntityItemProperties::getScalesWithParent() work correctly - properties.setEntityHost(entity->getEntityHost()); + EntityHost entityHost = entity->getEntityHost(); + properties.setEntityHost(entityHost); + if (entityHost == EntityHost::LOCAL_ENTITY) { + properties.setCollisionless(true); + } properties.setOwningAvatarID(entity->getOwningAvatarID()); // make sure the properties has a type, so that the encode can know which properties to include From a5fe4709a932db636b67651aa2e58ede6fa30c01 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Wed, 14 Nov 2018 17:50:21 -0800 Subject: [PATCH 023/117] Update Fade.slh --- libraries/render-utils/src/Fade.slh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/Fade.slh b/libraries/render-utils/src/Fade.slh index 686289217c..cd1e06f52e 100644 --- a/libraries/render-utils/src/Fade.slh +++ b/libraries/render-utils/src/Fade.slh @@ -86,7 +86,7 @@ float evalFadeGradient(FadeObjectParams params, vec3 position) { float evalFadeAlpha(FadeObjectParams params, vec3 position) { float alpha = evalFadeGradient(params, position) - params.threshold; - alpha *= 1.0 - 2.0 * fadeParameters[params.category]._isInverted; + alpha *= 1.0 - 2.0 * float(fadeParameters[params.category]._isInverted); return alpha; } @@ -164,4 +164,4 @@ layout(location=RENDER_UTILS_ATTR_FADE3) out vec4 _fadeData3; _fadeData3 = inTexCoord4; <@endfunc@> -<@endif@> \ No newline at end of file +<@endif@> From 17404863e7e3971f7b4e21d62c939f3f2af62c9b Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 15 Nov 2018 17:42:51 -0800 Subject: [PATCH 024/117] entity list reordering WIP --- scripts/system/html/css/edit-style.css | 4 ++ scripts/system/html/js/entityList.js | 97 ++++++++++++++++++++------ 2 files changed, 81 insertions(+), 20 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 3a291bf27b..a00dc4d57c 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1383,6 +1383,10 @@ input[type=button]#export { cursor: col-resize; } +#entity-table .dragging { + background-color: #b3ecff; +} + #entity-table td { box-sizing: border-box; } diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index 00c50169a6..6f12dd1e7c 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -21,6 +21,8 @@ const MAX_LENGTH_RADIUS = 9; const MINIMUM_COLUMN_WIDTH = 24; const SCROLLBAR_WIDTH = 20; const RESIZER_WIDTH = 10; +const DELTA_X_MOVE_COLUMNS_THRESHOLD = 2; +const DELTA_X_COLUMN_SWAP_POSITION = 5; const COLUMNS = { type: { @@ -177,10 +179,12 @@ let isFilterInView = false; let columns = []; let columnsByID = {}; -let currentResizeEl = null; -let startResizeEvent = null; +let lastResizeEvent = null; let resizeColumnIndex = 0; -let startThClick = null; +let elTargetTh = null; +let targetColumnIndex = 0; +let lastColumnSwapPosition = -1; +let initialThEvent = null; let elEntityTable, elEntityTableHeader, @@ -319,7 +323,7 @@ function loaded() { let thID = "entity-" + columnID; let elTh = document.createElement("th"); elTh.setAttribute("id", thID); - elTh.setAttribute("data-resizable-column-id", thID); + elTh.setAttribute("columnIndex", columnIndex); if (columnData.glyph) { let elGlyph = document.createElement("span"); elGlyph.className = "glyph"; @@ -328,14 +332,10 @@ function loaded() { } else { elTh.innerText = columnData.columnHeader; } - elTh.onmousedown = function() { - startThClick = this; - }; - elTh.onmouseup = function() { - if (startThClick === this) { - setSortColumn(columnID); - } - startThClick = null; + elTh.onmousedown = function(event) { + elTargetTh = event.target; + initialThEvent = event; + targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex")); }; let elResizer = document.createElement("span"); @@ -1030,7 +1030,7 @@ function loaded() { } function onStartResize(event) { - startResizeEvent = event; + lastResizeEvent = event; resizeColumnIndex = parseInt(this.getAttribute("columnIndex")); event.stopPropagation(); } @@ -1074,8 +1074,33 @@ function loaded() { entityList.refresh(); } - document.onmousemove = function(ev) { - if (startResizeEvent) { + function swapColumns(columnAIndex, columnBIndex) { + let columnA = columns[columnAIndex]; + let columnB = columns[columnBIndex]; + let columnATh = columns[columnAIndex].elTh; + let columnBTh = columns[columnBIndex].elTh; + let columnThParent = columnATh.parentNode; + columnThParent.removeChild(columnBTh); + columnThParent.insertBefore(columnBTh, columnATh); + columnATh.setAttribute("columnIndex", columnBIndex); + columnBTh.setAttribute("columnIndex", columnAIndex); + columnA.elResizer.setAttribute("columnIndex", columnBIndex); + columnB.elResizer.setAttribute("columnIndex", columnAIndex); + + for (let i = 0; i < visibleEntities.length; ++i) { + let elRow = visibleEntities[i].elRow; + let columnACell = elRow.childNodes[columnAIndex]; + let columnBCell = elRow.childNodes[columnBIndex]; + elRow.removeChild(columnBCell); + elRow.insertBefore(columnBCell, columnACell); + } + + columns[columnAIndex] = columnB; + columns[columnBIndex] = columnA; + } + + document.onmousemove = function(event) { + if (lastResizeEvent) { startTh = null; let column = columns[resizeColumnIndex]; @@ -1087,7 +1112,7 @@ function loaded() { } let fullWidth = elEntityTableBody.offsetWidth; - let dx = ev.clientX - startResizeEvent.clientX; + let dx = event.clientX - lastResizeEvent.clientX; let dPct = dx / fullWidth; let newColWidth = column.width + dPct; @@ -1097,14 +1122,46 @@ function loaded() { column.width += dPct; nextColumn.width -= dPct; updateColumnWidths(); - startResizeEvent = ev; + lastResizeEvent = event; + } + } else if (elTargetTh) { + let dxFromInitial = event.clientX - initialThEvent.clientX; + if (Math.abs(dxFromInitial) >= DELTA_X_MOVE_COLUMNS_THRESHOLD) { + elTargetTh.className = "dragging"; + } + if (targetColumnIndex < columns.length - 1) { + let nextColumnIndex = targetColumnIndex + 1; + let nextColumnTh = columns[nextColumnIndex].elTh; + let nextColumnStartX = nextColumnTh.getBoundingClientRect().left; + if (event.clientX >= nextColumnStartX && event.clientX - lastColumnSwapPosition >= DELTA_X_COLUMN_SWAP_POSITION) { + swapColumns(targetColumnIndex, nextColumnIndex); + targetColumnIndex = nextColumnIndex; + lastColumnSwapPosition = event.clientX; + } + } + if (targetColumnIndex >= 1) { + let prevColumnIndex = targetColumnIndex - 1; + let prevColumnTh = columns[prevColumnIndex].elTh; + let prevColumnEndX = prevColumnTh.getBoundingClientRect().right; + if (event.clientX <= prevColumnEndX && event.clientX - lastColumnSwapPosition >= DELTA_X_COLUMN_SWAP_POSITION) { + swapColumns(prevColumnIndex, targetColumnIndex); + targetColumnIndex = prevColumnIndex; + } } } } - document.onmouseup = function(ev) { - startResizeEvent = null; - ev.stopPropagation(); + document.onmouseup = function(event) { + if (elTargetTh) { + if (elTargetTh.className !== "dragging" && elTargetTh === event.target) { + let columnID = columns[targetColumnIndex].columnID; + setSortColumn(columnID); + } + elTargetTh.className = ""; + } + lastResizeEvent = null; + elTargetTh = null; + initialThEvent = null; } function setSpaceMode(spaceMode) { From b24c4827433eaae0c1e6fa1746f7f0f1ac3a70b9 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 16 Nov 2018 16:29:57 +1300 Subject: [PATCH 025/117] Terminate Create far grab etc. upon laser intersecting tablet --- .../controllerModules/inEditMode.js | 42 +++++++++++++++---- .../system/libraries/entitySelectionTool.js | 5 ++- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index 6adfa88fb2..5d0b64606d 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -20,6 +20,7 @@ Script.include("/~/system/libraries/utils.js"); var MARGIN = 25; function InEditMode(hand) { this.hand = hand; + this.running = false; this.triggerClicked = false; this.selectedTarget = null; this.reticleMinX = MARGIN; @@ -62,25 +63,27 @@ Script.include("/~/system/libraries/utils.js"); return point2d; }; + this.ENTITY_TOOL_UPDATES_CHANNEL = "entityToolUpdates"; + this.sendPickData = function(controllerData) { if (controllerData.triggerClicks[this.hand]) { var hand = this.hand === RIGHT_HAND ? Controller.Standard.RightHand : Controller.Standard.LeftHand; if (!this.triggerClicked) { this.selectedTarget = controllerData.rayPicks[this.hand]; if (!this.selectedTarget.intersects) { - Messages.sendLocalMessage("entityToolUpdates", JSON.stringify({ + Messages.sendLocalMessage(this.ENTITY_TOOL_UPDATES_CHANNEL, JSON.stringify({ method: "clearSelection", hand: hand })); } else { if (this.selectedTarget.type === Picks.INTERSECTED_ENTITY) { - Messages.sendLocalMessage("entityToolUpdates", JSON.stringify({ + Messages.sendLocalMessage(this.ENTITY_TOOL_UPDATES_CHANNEL, JSON.stringify({ method: "selectEntity", entityID: this.selectedTarget.objectID, hand: hand })); } else if (this.selectedTarget.type === Picks.INTERSECTED_OVERLAY) { - Messages.sendLocalMessage("entityToolUpdates", JSON.stringify({ + Messages.sendLocalMessage(this.ENTITY_TOOL_UPDATES_CHANNEL, JSON.stringify({ method: "selectOverlay", overlayID: this.selectedTarget.objectID, hand: hand @@ -102,7 +105,7 @@ Script.include("/~/system/libraries/utils.js"); var desktopWindow = Window.isPointOnDesktopWindow(point2d); var tablet = this.pointingAtTablet(rayPick.objectID); var rightHand = this.hand === RIGHT_HAND; - Messages.sendLocalMessage("entityToolUpdates", JSON.stringify({ + Messages.sendLocalMessage(this.ENTITY_TOOL_UPDATES_CHANNEL, JSON.stringify({ method: "pointingAt", desktopWindow: desktopWindow, tablet: tablet, @@ -110,7 +113,27 @@ Script.include("/~/system/libraries/utils.js"); })); }; + this.runModule = function() { + if (!this.running) { + Messages.sendLocalMessage(this.ENTITY_TOOL_UPDATES_CHANNEL, JSON.stringify({ + method: "moduleRunning", + hand: this.hand, + running: true + })); + this.running = true; + } + return makeRunningValues(true, [], []); + }; + this.exitModule = function() { + if (this.running) { + Messages.sendLocalMessage(this.ENTITY_TOOL_UPDATES_CHANNEL, JSON.stringify({ + method: "moduleRunning", + hand: this.hand, + running: false + })); + this.running = false; + } return makeRunningValues(false, [], []); }; @@ -120,13 +143,15 @@ Script.include("/~/system/libraries/utils.js"); this.triggerClicked = false; } Messages.sendLocalMessage('Hifi-unhighlight-all', ''); - return makeRunningValues(true, [], []); + return this.runModule(); } this.triggerClicked = false; - return makeRunningValues(false, [], []); + return this.exitModule(); }; this.run = function(controllerData) { + + // Tablet stylus. var tabletStylusInput = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightTabletStylusInput" : "LeftTabletStylusInput"); if (tabletStylusInput) { @@ -136,6 +161,7 @@ Script.include("/~/system/libraries/utils.js"); } } + // Tablet surface. var webLaser = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightWebSurfaceLaserInput" : "LeftWebSurfaceLaserInput"); if (webLaser) { @@ -147,6 +173,7 @@ Script.include("/~/system/libraries/utils.js"); } } + // HUD overlay. if (!controllerData.triggerClicks[this.hand]) { // Don't grab if trigger pressed when laser starts intersecting. var hudLaser = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightHudOverlayPointer" : "LeftHudOverlayPointer"); @@ -168,6 +195,7 @@ Script.include("/~/system/libraries/utils.js"); } } + // Teleport. var teleport = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightTeleporter" : "LeftTeleporter"); if (teleport) { var teleportReady = teleport.isReady(controllerData); @@ -176,8 +204,6 @@ Script.include("/~/system/libraries/utils.js"); } } - var stopRunning = false; - if ((controllerData.triggerClicks[this.hand] === 0 && controllerData.secondaryValues[this.hand] === 0)) { var stopRunning = false; controllerData.nearbyOverlayIDs[this.hand].forEach(function(overlayID) { diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 4552ed27fb..191a961228 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -58,7 +58,10 @@ SelectionManager = (function() { return; } - if (messageParsed.method === "selectEntity") { + if (messageParsed.method === "moduleRunning") { + // Terminate any current laser or mouse action. + SelectionDisplay.mouseReleaseEvent({}); + } else if (messageParsed.method === "selectEntity") { if (!SelectionDisplay.triggered() || SelectionDisplay.triggeredHand === messageParsed.hand) { if (wantDebug) { print("setting selection to " + messageParsed.entityID); From eb00435353ae2b7925a8fc41680ae91b354f75c4 Mon Sep 17 00:00:00 2001 From: amantley Date: Fri, 16 Nov 2018 10:35:50 -0800 Subject: [PATCH 026/117] removed whitespace --- libraries/animation/src/Rig.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 128ac05b81..baa8ac94ce 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -363,7 +363,6 @@ void Rig::reset(const HFMModel& hfmModel) { _animSkeleton = std::make_shared(hfmModel); - _internalPoseSet._relativePoses.clear(); _internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses(); From cbe5814c64347ecfdcf8ca1770d6fabfccf6e924 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 16 Nov 2018 14:53:53 -0800 Subject: [PATCH 027/117] shader compilation prototype --- interface/src/Application.cpp | 44 +------------- interface/src/Application.h | 2 + interface/src/Application_render.cpp | 60 ++++++++++++------- .../display-plugins/OpenGLDisplayPlugin.cpp | 15 +++++ .../src/display-plugins/OpenGLDisplayPlugin.h | 3 + .../gpu-gl-common/src/gpu/gl/GLShader.cpp | 1 + libraries/plugins/src/plugins/DisplayPlugin.h | 4 ++ 7 files changed, 65 insertions(+), 64 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 969a05a792..6d13305af7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2382,6 +2382,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo checkLoginTimer->start(); } #endif + + const QString SPLASH_SKYBOX { "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" }; + _splashScreen->parse(SPLASH_SKYBOX); } void Application::updateVerboseLogging() { @@ -2862,8 +2865,6 @@ void Application::initializeGL() { DependencyManager::get()->setGPUContext(_gpuContext); } -static const QString SPLASH_SKYBOX{ "{\"ProceduralEntity\":{ \"version\":2, \"shaderUrl\":\"qrc:///shaders/splashSkybox.frag\" } }" }; - void Application::initializeDisplayPlugins() { auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); Setting::Handle activeDisplayPluginSetting{ ACTIVE_DISPLAY_PLUGIN_SETTING_NAME, displayPlugins.at(0)->getName() }; @@ -2899,45 +2900,6 @@ void Application::initializeDisplayPlugins() { // Submit a default frame to render until the engine starts up updateRenderArgs(0.0f); - -#define ENABLE_SPLASH_FRAME 0 -#if ENABLE_SPLASH_FRAME - { - QMutexLocker viewLocker(&_renderArgsMutex); - - if (_appRenderArgs._isStereo) { - _gpuContext->enableStereo(true); - _gpuContext->setStereoProjections(_appRenderArgs._eyeProjections); - _gpuContext->setStereoViews(_appRenderArgs._eyeOffsets); - } - - // Frame resources - auto framebufferCache = DependencyManager::get(); - gpu::FramebufferPointer finalFramebuffer = framebufferCache->getFramebuffer(); - std::shared_ptr procedural = std::make_shared(); - procedural->parse(SPLASH_SKYBOX); - - _gpuContext->beginFrame(_appRenderArgs._view, _appRenderArgs._headPose); - gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { - batch.resetStages(); - batch.enableStereo(false); - batch.setFramebuffer(finalFramebuffer); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0, 0, 0, 1 }); - batch.enableSkybox(true); - batch.enableStereo(_appRenderArgs._isStereo); - batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); - procedural->render(batch, _appRenderArgs._renderArgs.getViewFrustum()); - }); - auto frame = _gpuContext->endFrame(); - frame->frameIndex = 0; - frame->framebuffer = finalFramebuffer; - frame->pose = _appRenderArgs._headPose; - frame->framebufferRecycler = [framebufferCache, procedural](const gpu::FramebufferPointer& framebuffer) { - framebufferCache->releaseFramebuffer(framebuffer); - }; - _displayPlugin->submitFrame(frame); - } -#endif } void Application::initializeRenderEngine() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 9b8aac425a..fb1c916c36 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -793,5 +793,7 @@ private: bool _showTrackedObjects { false }; bool _prevShowTrackedObjects { false }; + + std::shared_ptr _splashScreen { std::make_shared() }; }; #endif // hifi_Application_h diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index a87caeb9a8..47cde80ab3 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -62,6 +62,7 @@ void Application::paintGL() { glm::mat4 HMDSensorPose; glm::mat4 eyeToWorld; glm::mat4 sensorToWorld; + ViewFrustum viewFrustum; bool isStereo; glm::mat4 stereoEyeOffsets[2]; @@ -84,6 +85,7 @@ void Application::paintGL() { stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye]; stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye]; }); + viewFrustum = _appRenderArgs._renderArgs.getViewFrustum(); } { @@ -94,21 +96,12 @@ void Application::paintGL() { gpu::doInBatch("Application_render::gpuContextReset", _gpuContext, [&](gpu::Batch& batch) { batch.resetStages(); }); - } - - { - PROFILE_RANGE(render, "/renderOverlay"); - PerformanceTimer perfTimer("renderOverlay"); - // NOTE: There is no batch associated with this renderArgs - // the ApplicationOverlay class assumes it's viewport is setup to be the device size - renderArgs._viewport = glm::ivec4(0, 0, getDeviceSize()); - _applicationOverlay.renderOverlay(&renderArgs); - } - - { - PROFILE_RANGE(render, "/updateCompositor"); - getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); + if (isStereo) { + renderArgs._context->enableStereo(true); + renderArgs._context->setStereoProjections(stereoEyeProjections); + renderArgs._context->setStereoViews(stereoEyeOffsets); + } } gpu::FramebufferPointer finalFramebuffer; @@ -122,17 +115,38 @@ void Application::paintGL() { finalFramebuffer = framebufferCache->getFramebuffer(); } - { - if (isStereo) { - renderArgs._context->enableStereo(true); - renderArgs._context->setStereoProjections(stereoEyeProjections); - renderArgs._context->setStereoViews(stereoEyeOffsets); + if (!displayPlugin->areAllProgramsLoaded()) { + gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setFramebuffer(finalFramebuffer); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0, 0, 0, 1 }); + batch.enableSkybox(true); + batch.enableStereo(isStereo); + batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); + _splashScreen->render(batch, viewFrustum); + }); + } else { + { + PROFILE_RANGE(render, "/renderOverlay"); + PerformanceTimer perfTimer("renderOverlay"); + // NOTE: There is no batch associated with this renderArgs + // the ApplicationOverlay class assumes it's viewport is setup to be the device size + renderArgs._viewport = glm::ivec4(0, 0, getDeviceSize()); + _applicationOverlay.renderOverlay(&renderArgs); } - renderArgs._hudOperator = displayPlugin->getHUDOperator(); - renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); - renderArgs._blitFramebuffer = finalFramebuffer; - runRenderFrame(&renderArgs); + { + PROFILE_RANGE(render, "/updateCompositor"); + getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); + } + + { + PROFILE_RANGE(render, "/runRenderFrame"); + renderArgs._hudOperator = displayPlugin->getHUDOperator(); + renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); + renderArgs._blitFramebuffer = finalFramebuffer; + runRenderFrame(&renderArgs); + } } auto frame = _gpuContext->endFrame(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 190d4d4104..f562efbe22 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -637,6 +638,17 @@ void OpenGLDisplayPlugin::present() { auto frameId = (uint64_t)presentCount(); PROFILE_RANGE_EX(render, __FUNCTION__, 0xffffff00, frameId) uint64_t startPresent = usecTimestampNow(); + + if (!_allProgramsLoaded) { + const auto& programIDs = shader::allPrograms(); + if (_currentLoadingProgramIndex < programIDs.size()) { + auto shader = gpu::Shader::createProgram(programIDs.at(_currentLoadingProgramIndex++)); + gpu::gl::GLShader::sync(*getGLBackend(), *shader); + } else { + _allProgramsLoaded = true; + } + } + { PROFILE_RANGE_EX(render, "updateFrameData", 0xff00ff00, frameId) updateFrameData(); @@ -829,6 +841,9 @@ void OpenGLDisplayPlugin::render(std::function f) { _gpuContext->executeBatch(batch); } +OpenGLDisplayPlugin::OpenGLDisplayPlugin() : DisplayPlugin() { + _allProgramsLoaded = false; +} OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 1cc060161b..1e3983d366 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -38,6 +38,7 @@ protected: using Lock = std::unique_lock; using Condition = std::condition_variable; public: + OpenGLDisplayPlugin(); ~OpenGLDisplayPlugin(); // These must be final to ensure proper ordering of operations // between the main thread and the presentation thread @@ -180,5 +181,7 @@ protected: // be serialized through this mutex mutable Mutex _presentMutex; float _hudAlpha{ 1.0f }; + + size_t _currentLoadingProgramIndex { 0 }; }; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLShader.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLShader.cpp index 44d2bd6ca0..cf123a3f66 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLShader.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLShader.cpp @@ -37,6 +37,7 @@ GLShader* GLShader::sync(GLBackend& backend, const Shader& shader, const Shader: if (object) { return object; } + PROFILE_RANGE(render, "/GLShader::sync"); // need to have a gpu object? if (shader.isProgram()) { GLShader* tempObject = backend.compileBackendProgram(shader, handler); diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index ad49ceafe6..e925309042 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -217,6 +217,8 @@ public: static const QString& MENU_PATH(); + bool areAllProgramsLoaded() { return _allProgramsLoaded; } + signals: void recommendedFramebufferSizeChanged(const QSize& size); void resetSensorsRequested(); @@ -233,6 +235,8 @@ protected: float _renderResolutionScale { 1.0f }; + std::atomic _allProgramsLoaded { true }; + private: QMutex _presentMutex; QWaitCondition _presentCondition; From a0f79f988194a74f19e82e104241572da7ff7d30 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 Nov 2018 17:14:30 -0800 Subject: [PATCH 028/117] entity list reordering columns --- scripts/system/html/js/entityList.js | 68 ++++++++++++++++++---------- scripts/system/html/js/listView.js | 4 -- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index e1581b7877..963611f059 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -110,8 +110,8 @@ const COLUMNS = { }; const COMPARE_ASCENDING = function(a, b) { - let va = a[currentSortColumn]; - let vb = b[currentSortColumn]; + let va = a[currentSortColumnID]; + let vb = b[currentSortColumnID]; if (va < vb) { return -1; @@ -171,7 +171,7 @@ let entityList = null; // The ListView */ let entityListContextMenu = null; -let currentSortColumn = 'type'; +let currentSortColumnID = 'type'; let currentSortOrder = ASCENDING_SORT; let elSortOrders = {}; let typeFilters = []; @@ -182,6 +182,7 @@ let columnsByID = {}; let lastResizeEvent = null; let resizeColumnIndex = 0; let elTargetTh = null; +let elTargetSpan = null; let targetColumnIndex = 0; let lastColumnSwapPosition = -1; let initialThEvent = null; @@ -226,10 +227,6 @@ const PROFILE = !ENABLE_PROFILING ? PROFILE_NOOP : function(name, fn, args) { console.log("PROFILE-Web " + profileIndent + "(" + name + ") End " + delta + "ms"); }; -debugPrint = function (message) { - console.log(message); -}; - function loaded() { openEventBridge(function() { elEntityTable = document.getElementById("entity-table"); @@ -320,10 +317,11 @@ function loaded() { for (let columnID in COLUMNS) { let columnData = COLUMNS[columnID]; - let thID = "entity-" + columnID; let elTh = document.createElement("th"); + let thID = "entity-" + columnID; elTh.setAttribute("id", thID); elTh.setAttribute("columnIndex", columnIndex); + elTh.setAttribute("columnID", columnID); if (columnData.glyph) { let elGlyph = document.createElement("span"); elGlyph.className = "glyph"; @@ -333,15 +331,19 @@ function loaded() { elTh.innerText = columnData.columnHeader; } elTh.onmousedown = function(event) { - elTargetTh = event.target; + if (event.target.nodeName === 'TH') { + elTargetTh = event.target; + targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex")); + lastColumnSwapPosition = event.clientX; + } else if (event.target.nodeName === 'SPAN') { + elTargetSpan = event.target; + } initialThEvent = event; - targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex")); }; let elResizer = document.createElement("span"); elResizer.className = "resizer"; elResizer.innerHTML = " "; - elResizer.setAttribute("columnIndex", columnIndex); elResizer.onmousedown = onStartResize; elTh.appendChild(elResizer); @@ -699,13 +701,13 @@ function loaded() { refreshNoEntitiesMessage(); } - function setSortColumn(column) { + function setSortColumn(columnID) { PROFILE("set-sort-column", function() { - if (currentSortColumn === column) { + if (currentSortColumnID === columnID) { currentSortOrder *= -1; } else { - elSortOrders[currentSortColumn].innerHTML = ""; - currentSortColumn = column; + elSortOrders[currentSortColumnID].innerHTML = ""; + currentSortColumnID = columnID; currentSortOrder = ASCENDING_SORT; } refreshSortOrder(); @@ -714,7 +716,7 @@ function loaded() { } function refreshSortOrder() { - elSortOrders[currentSortColumn].innerHTML = currentSortOrder === ASCENDING_SORT ? ASCENDING_STRING : DESCENDING_STRING; + elSortOrders[currentSortColumnID].innerHTML = currentSortOrder === ASCENDING_SORT ? ASCENDING_STRING : DESCENDING_STRING; } function refreshEntities() { @@ -1031,7 +1033,7 @@ function loaded() { function onStartResize(event) { lastResizeEvent = event; - resizeColumnIndex = parseInt(this.getAttribute("columnIndex")); + resizeColumnIndex = parseInt(this.parentNode.getAttribute("columnIndex")); event.stopPropagation(); } @@ -1089,14 +1091,18 @@ function loaded() { for (let i = 0; i < visibleEntities.length; ++i) { let elRow = visibleEntities[i].elRow; - let columnACell = elRow.childNodes[columnAIndex]; - let columnBCell = elRow.childNodes[columnBIndex]; - elRow.removeChild(columnBCell); - elRow.insertBefore(columnBCell, columnACell); + if (elRow) { + let columnACell = elRow.childNodes[columnAIndex]; + let columnBCell = elRow.childNodes[columnBIndex]; + elRow.removeChild(columnBCell); + elRow.insertBefore(columnBCell, columnACell); + } } columns[columnAIndex] = columnB; columns[columnBIndex] = columnA; + + updateColumnWidths(); } document.onmousemove = function(event) { @@ -1143,24 +1149,38 @@ function loaded() { let prevColumnIndex = targetColumnIndex - 1; let prevColumnTh = columns[prevColumnIndex].elTh; let prevColumnEndX = prevColumnTh.getBoundingClientRect().right; - if (event.clientX <= prevColumnEndX && event.clientX - lastColumnSwapPosition >= DELTA_X_COLUMN_SWAP_POSITION) { + if (event.clientX <= prevColumnEndX && lastColumnSwapPosition - event.clientX >= DELTA_X_COLUMN_SWAP_POSITION) { swapColumns(prevColumnIndex, targetColumnIndex); - targetColumnIndex = prevColumnIndex; + targetColumnIndex = prevColumnIndex; + lastColumnSwapPosition = event.clientX; } } + } else if (elTargetSpan) { + let dxFromInitial = event.clientX - initialThEvent.clientX; + if (Math.abs(dxFromInitial) >= DELTA_X_MOVE_COLUMNS_THRESHOLD) { + elTargetTh = elTargetSpan.parentNode; + elTargetTh.className = "dragging"; + targetColumnIndex = parseInt(elTargetTh.getAttribute("columnIndex")); + lastColumnSwapPosition = event.clientX; + elTargetSpan = null; + } } } document.onmouseup = function(event) { if (elTargetTh) { if (elTargetTh.className !== "dragging" && elTargetTh === event.target) { - let columnID = columns[targetColumnIndex].columnID; + let columnID = elTargetTh.getAttribute("columnID"); setSortColumn(columnID); } elTargetTh.className = ""; + } else if (elTargetSpan) { + let columnID = elTargetSpan.parentNode.getAttribute("columnID"); + setSortColumn(columnID); } lastResizeEvent = null; elTargetTh = null; + elTargetSpan = null; initialThEvent = null; } diff --git a/scripts/system/html/js/listView.js b/scripts/system/html/js/listView.js index f775a4cb24..77e1ba99b1 100644 --- a/scripts/system/html/js/listView.js +++ b/scripts/system/html/js/listView.js @@ -9,10 +9,6 @@ const SCROLL_ROWS = 2; // number of rows used as scrolling buffer, each time we pass this number of rows we scroll const FIRST_ROW_INDEX = 2; // the first elRow element's index in the child nodes of the table body -debugPrint = function (message) { - console.log(message); -}; - function ListView(elTableBody, elTableScroll, elTableHeaderRow, createRowFunction, updateRowFunction, clearRowFunction, WINDOW_NONVARIABLE_HEIGHT) { this.elTableBody = elTableBody; From fd9c05ce8055d72bbc5540f38d0f2e88744b8437 Mon Sep 17 00:00:00 2001 From: amantley Date: Fri, 16 Nov 2018 17:39:46 -0800 Subject: [PATCH 029/117] joint mapping. adding to fbx reader and avatar classes to get non standard names to map to hifi --- .../src/avatars-renderer/Avatar.cpp | 15 +++++++++++++++ libraries/fbx/src/FBXReader.cpp | 18 ++++++++++++++++++ libraries/fbx/src/FSTReader.h | 1 + libraries/hfm/src/hfm/HFM.h | 1 + 4 files changed, 35 insertions(+) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index fceb146470..4b730fccda 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1437,6 +1437,21 @@ int Avatar::getJointIndex(const QString& name) const { withValidJointIndicesCache([&]() { if (_modelJointIndicesCache.contains(name)) { result = _modelJointIndicesCache[name] - 1; + if (_skeletonModel && _skeletonModel->isActive()) { + qCDebug(avatars_renderer) << "the other head id is this" << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]; + qCDebug(avatars_renderer) << "joint indices cache " << name << " " << _modelJointIndicesCache[name]; + if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"])) { + qCDebug(avatars_renderer) << "joint alternate name " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"] << " " << _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]]; + } + } + } else { + // doesn't contain name. + qCDebug(avatars_renderer) << "name is not here"; + if (_skeletonModel && _skeletonModel->isActive()) { + if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"])) { + qCDebug(avatars_renderer) << "the other head id is this" << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"] << " " << _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]];; + } + } } }); return result; diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index dd10cd30b3..343f7e6c6d 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -417,6 +417,21 @@ QByteArray fileOnUrl(const QByteArray& filepath, const QString& url) { return filepath.mid(filepath.lastIndexOf('/') + 1); } +QMap getJointNameMapping(const QVariantHash& mapping) { + static const QString JOINT_NAME_MAPPING_FIELD = "jointMap"; + QMap fbxToHifiJointNameMap; + if (!mapping.isEmpty() && mapping.contains(JOINT_NAME_MAPPING_FIELD) && mapping[JOINT_NAME_MAPPING_FIELD].type() == QVariant::Hash) { + auto jointNames = mapping[JOINT_NAME_MAPPING_FIELD].toHash(); + for (auto itr = jointNames.begin(); itr != jointNames.end(); itr++) { + qCDebug(modelformat) << "found a joint mapping field key " << itr.key() << " value " << itr.value().toString(); + fbxToHifiJointNameMap.insert(itr.key(), itr.value().toString()); + qCDebug(modelformat) << "the mapped key (Head) has a value of " << fbxToHifiJointNameMap[itr.key()]; + } + + } + return fbxToHifiJointNameMap; +} + QMap getJointRotationOffsets(const QVariantHash& mapping) { QMap jointRotationOffsets; static const QString JOINT_ROTATION_OFFSET_FIELD = "jointRotationOffset"; @@ -1830,6 +1845,9 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& qCDebug(modelformat) << "Joint Rotation Offset added to Rig._jointRotationOffsets : " << " jointName: " << jointName << " jointIndex: " << jointIndex << " rotation offset: " << rotationOffset; } + hfmModel.fbxToHifiJointNameMapping.clear(); + hfmModel.fbxToHifiJointNameMapping = getJointNameMapping(mapping); + return hfmModelPtr; } diff --git a/libraries/fbx/src/FSTReader.h b/libraries/fbx/src/FSTReader.h index 4a8574f0cf..00244877b3 100644 --- a/libraries/fbx/src/FSTReader.h +++ b/libraries/fbx/src/FSTReader.h @@ -29,6 +29,7 @@ static const QString JOINT_FIELD = "joint"; static const QString FREE_JOINT_FIELD = "freeJoint"; static const QString BLENDSHAPE_FIELD = "bs"; static const QString SCRIPT_FIELD = "script"; +static const QString JOINT_NAME_MAPPING_FIELD = "jointMap"; class FSTReader { public: diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index 05e48b6534..b33417666f 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -313,6 +313,7 @@ public: QList blendshapeChannelNames; QMap jointRotationOffsets; + QMap fbxToHifiJointNameMapping; }; }; From 0fccb4c73c048a381b2024bc31eeeebee8750786 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 16 Nov 2018 18:30:30 -0800 Subject: [PATCH 030/117] move to batch, try to use static --- interface/src/Application_render.cpp | 2 -- .../display-plugins/OpenGLDisplayPlugin.cpp | 23 +++++++++++-------- .../src/display-plugins/OpenGLDisplayPlugin.h | 6 +++-- .../gpu-gl-common/src/gpu/gl/GLBackend.cpp | 7 ++++++ .../gpu-gl-common/src/gpu/gl/GLBackend.h | 2 ++ libraries/gpu/src/gpu/Batch.cpp | 6 +++++ libraries/gpu/src/gpu/Batch.h | 4 ++++ libraries/plugins/src/plugins/DisplayPlugin.h | 4 +--- 8 files changed, 37 insertions(+), 17 deletions(-) diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index 47cde80ab3..8d9cdc980a 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -117,9 +117,7 @@ void Application::paintGL() { if (!displayPlugin->areAllProgramsLoaded()) { gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { - batch.enableStereo(false); batch.setFramebuffer(finalFramebuffer); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, { 0, 0, 0, 1 }); batch.enableSkybox(true); batch.enableStereo(isStereo); batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index f562efbe22..45e0bbc2a6 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -634,18 +633,26 @@ void OpenGLDisplayPlugin::internalPresent() { _presentRate.increment(); } +std::atomic OpenGLDisplayPlugin::_allProgramsLoaded { false }; +unsigned int OpenGLDisplayPlugin::_currentLoadingProgramIndex { 0 }; + +bool OpenGLDisplayPlugin::areAllProgramsLoaded() const { + return OpenGLDisplayPlugin::_allProgramsLoaded.load(); +} + void OpenGLDisplayPlugin::present() { auto frameId = (uint64_t)presentCount(); PROFILE_RANGE_EX(render, __FUNCTION__, 0xffffff00, frameId) uint64_t startPresent = usecTimestampNow(); - if (!_allProgramsLoaded) { + if (!OpenGLDisplayPlugin::_allProgramsLoaded.load()) { const auto& programIDs = shader::allPrograms(); - if (_currentLoadingProgramIndex < programIDs.size()) { - auto shader = gpu::Shader::createProgram(programIDs.at(_currentLoadingProgramIndex++)); - gpu::gl::GLShader::sync(*getGLBackend(), *shader); + if (OpenGLDisplayPlugin::_currentLoadingProgramIndex < programIDs.size()) { + gpu::doInBatch("createAndSyncProgram", _gpuContext, [&programIDs](gpu::Batch& batch) { + batch.createAndSyncProgram(programIDs.at(OpenGLDisplayPlugin::_currentLoadingProgramIndex++)); + }); } else { - _allProgramsLoaded = true; + OpenGLDisplayPlugin::_allProgramsLoaded.store(true); } } @@ -841,10 +848,6 @@ void OpenGLDisplayPlugin::render(std::function f) { _gpuContext->executeBatch(batch); } -OpenGLDisplayPlugin::OpenGLDisplayPlugin() : DisplayPlugin() { - _allProgramsLoaded = false; -} - OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 1e3983d366..acb12aa69a 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -38,7 +38,6 @@ protected: using Lock = std::unique_lock; using Condition = std::condition_variable; public: - OpenGLDisplayPlugin(); ~OpenGLDisplayPlugin(); // These must be final to ensure proper ordering of operations // between the main thread and the presentation thread @@ -84,6 +83,8 @@ public: void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override; + bool areAllProgramsLoaded() const override; + protected: friend class PresentThread; @@ -182,6 +183,7 @@ protected: mutable Mutex _presentMutex; float _hudAlpha{ 1.0f }; - size_t _currentLoadingProgramIndex { 0 }; + static std::atomic _allProgramsLoaded; + static unsigned int _currentLoadingProgramIndex; }; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index c1ce05c18b..415c5135d9 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -102,6 +102,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::gl::GLBackend::do_pushProfileRange), (&::gpu::gl::GLBackend::do_popProfileRange), + + (&::gpu::gl::GLBackend::do_createAndSyncProgram), }; #define GL_GET_INTEGER(NAME) glGetIntegerv(GL_##NAME, &const_cast(NAME)); @@ -706,6 +708,11 @@ void GLBackend::do_glColor4f(const Batch& batch, size_t paramOffset) { (void)CHECK_GL_ERROR(); } +void GLBackend::do_createAndSyncProgram(const Batch& batch, size_t paramOffset) { + auto shader = gpu::Shader::createProgram(batch._params[paramOffset + 0]._uint); + gpu::gl::GLShader::sync(*this, *shader); +} + void GLBackend::releaseBuffer(GLuint id, Size size) const { Lock lock(_trashMutex); _currentFrameTrash.buffersTrash.push_back({ id, size }); diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 37dde5b08e..0a2c1b92ff 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -380,6 +380,8 @@ public: virtual void do_setStateBlendFactor(const Batch& batch, size_t paramOffset) final; virtual void do_setStateScissorRect(const Batch& batch, size_t paramOffset) final; + virtual void do_createAndSyncProgram(const Batch& batch, size_t paramOffset) final; + virtual GLuint getFramebufferID(const FramebufferPointer& framebuffer) = 0; virtual GLuint getTextureID(const TexturePointer& texture) final; virtual GLuint getBufferID(const Buffer& buffer) = 0; diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index e3ea210ecb..43c1c69287 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -760,3 +760,9 @@ void Batch::flush() { buffer->flush(); } } + +void Batch::createAndSyncProgram(unsigned int programID) { + ADD_COMMAND(createAndSyncProgram); + + _params.emplace_back(programID); +} \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 96a45d3111..aff6cf5ddd 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -289,6 +289,8 @@ public: void _glColor4f(float red, float green, float blue, float alpha); + void createAndSyncProgram(unsigned int programID); + // Maybe useful but shoudln't be public. Please convince me otherwise // Well porting to gles i need it... void runLambda(std::function f); @@ -368,6 +370,8 @@ public: COMMAND_pushProfileRange, COMMAND_popProfileRange, + COMMAND_createAndSyncProgram, + NUM_COMMANDS, }; typedef std::vector Commands; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index e925309042..e9fbd71689 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -217,7 +217,7 @@ public: static const QString& MENU_PATH(); - bool areAllProgramsLoaded() { return _allProgramsLoaded; } + virtual bool areAllProgramsLoaded() const { return true; } signals: void recommendedFramebufferSizeChanged(const QSize& size); @@ -235,8 +235,6 @@ protected: float _renderResolutionScale { 1.0f }; - std::atomic _allProgramsLoaded { true }; - private: QMutex _presentMutex; QWaitCondition _presentCondition; From fe43c733f8dbe193298915729f58abe848ab92d9 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Sat, 17 Nov 2018 22:56:59 +0530 Subject: [PATCH 031/117] FB19400 during shutdown -- TypeError: Cannot read property 'buttons' --- interface/resources/qml/hifi/Desktop.qml | 4 ++-- interface/resources/qml/hifi/tablet/TabletHome.qml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/hifi/Desktop.qml b/interface/resources/qml/hifi/Desktop.qml index f57c612b98..354c8095a0 100644 --- a/interface/resources/qml/hifi/Desktop.qml +++ b/interface/resources/qml/hifi/Desktop.qml @@ -70,8 +70,8 @@ OriginalDesktop.Desktop { anchors.horizontalCenter: settings.constrainToolbarToCenterX ? desktop.horizontalCenter : undefined; // Literal 50 is overwritten by settings from previous session, and sysToolbar.x comes from settings when not constrained. x: sysToolbar.x - buttonModel: tablet.buttons; - shown: tablet.toolbarMode; + buttonModel: tablet ? tablet.buttons : null; + shown: tablet ? tablet.toolbarMode : false; } Settings { diff --git a/interface/resources/qml/hifi/tablet/TabletHome.qml b/interface/resources/qml/hifi/tablet/TabletHome.qml index f1f54e8419..cbfb3c1337 100644 --- a/interface/resources/qml/hifi/tablet/TabletHome.qml +++ b/interface/resources/qml/hifi/tablet/TabletHome.qml @@ -115,9 +115,9 @@ Item { property int previousIndex: -1 Repeater { id: pageRepeater - model: Math.ceil(tabletProxy.buttons.rowCount() / TabletEnums.ButtonsOnPage) + model: tabletProxy != null ? Math.ceil(tabletProxy.buttons.rowCount() / TabletEnums.ButtonsOnPage) : 0 onItemAdded: { - item.proxyModel.sourceModel = tabletProxy.buttons; + item.proxyModel.sourceModel = tabletProxy != null ? tabletProxy.buttons : null; item.proxyModel.pageIndex = index; } From 837b321004e0901330c5f131753911f67b734495 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sat, 17 Nov 2018 10:35:05 -0800 Subject: [PATCH 032/117] merging with master --- interface/src/graphics/RenderEventHandler.cpp | 2 +- libraries/render-utils/src/AmbientOcclusionEffect.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/graphics/RenderEventHandler.cpp b/interface/src/graphics/RenderEventHandler.cpp index 3ac48b894d..42af3bb9c0 100644 --- a/interface/src/graphics/RenderEventHandler.cpp +++ b/interface/src/graphics/RenderEventHandler.cpp @@ -25,7 +25,7 @@ RenderEventHandler::RenderEventHandler(CheckCall checkCall, RenderCall renderCal // Transfer to a new thread moveToNewNamedThread(this, "RenderThread", [this](QThread* renderThread) { hifi::qt::addBlockingForbiddenThread("Render", renderThread); - _renderContext->moveToThreadWithContext(renderThread); + //_renderContext->moveToThreadWithContext(renderThread); _lastTimeRendered.start(); }, std::bind(&RenderEventHandler::initialize, this), QThread::HighestPriority); } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 864aef09e4..af6f6b21a3 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -78,7 +78,6 @@ using AmbientOcclusionFramebufferPointer = std::shared_ptr Date: Sun, 18 Nov 2018 00:24:45 +0530 Subject: [PATCH 033/117] second attempt to fix all other shutdown QML warnings at once --- libraries/qml/src/qml/OffscreenSurface.cpp | 4 ++++ libraries/qml/src/qml/impl/SharedObject.cpp | 15 +++++++++++++++ libraries/qml/src/qml/impl/SharedObject.h | 4 +++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp index 91532534e3..abab5391e2 100644 --- a/libraries/qml/src/qml/OffscreenSurface.cpp +++ b/libraries/qml/src/qml/OffscreenSurface.cpp @@ -389,6 +389,10 @@ void OffscreenSurface::finishQmlLoad(QQmlComponent* qmlComponent, } // Allow child windows to be destroyed from JS QQmlEngine::setObjectOwnership(newObject, QQmlEngine::JavaScriptOwnership); + + // add object to the manual deletion list + _sharedObject->addToDeletionList(newObject); + newObject->setParent(parent); newItem->setParentItem(parent); } else { diff --git a/libraries/qml/src/qml/impl/SharedObject.cpp b/libraries/qml/src/qml/impl/SharedObject.cpp index 259defdb48..5bcca0821f 100644 --- a/libraries/qml/src/qml/impl/SharedObject.cpp +++ b/libraries/qml/src/qml/impl/SharedObject.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -96,6 +97,15 @@ SharedObject::~SharedObject() { } #endif + // already deleted objects will be reset to null by QPointer so it should be safe just iterate here + for (auto qmlObject : _deletionList) { + if (qmlObject) { + // manually delete not-deleted-yet qml items + QQmlEngine::setObjectOwnership(qmlObject, QQmlEngine::CppOwnership); + delete qmlObject; + } + } + if (_rootItem) { delete _rootItem; _rootItem = nullptr; @@ -412,6 +422,11 @@ bool SharedObject::fetchTexture(TextureAndFence& textureAndFence) { return true; } +void hifi::qml::impl::SharedObject::addToDeletionList(QObject * object) +{ + _deletionList.append(QPointer(object)); +} + void SharedObject::setProxyWindow(QWindow* window) { #ifndef DISABLE_QML _proxyWindow = window; diff --git a/libraries/qml/src/qml/impl/SharedObject.h b/libraries/qml/src/qml/impl/SharedObject.h index 002679c44d..ce9fcd46d2 100644 --- a/libraries/qml/src/qml/impl/SharedObject.h +++ b/libraries/qml/src/qml/impl/SharedObject.h @@ -66,7 +66,7 @@ public: void resume(); bool isPaused() const; bool fetchTexture(TextureAndFence& textureAndFence); - + void addToDeletionList(QObject* object); private: bool event(QEvent* e) override; @@ -91,6 +91,8 @@ private: void onAboutToQuit(); void updateTextureAndFence(const TextureAndFence& newTextureAndFence); + QList> _deletionList; + // Texture management TextureAndFence _latestTextureAndFence{ 0, 0 }; QQuickItem* _item{ nullptr }; From 372f4390e8f5c9cca94da1fbee648ee75f051cfb Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 19 Nov 2018 19:14:07 -0500 Subject: [PATCH 034/117] replicate default skybox --- interface/resources/shaders/splashSkybox.frag | 71 ++++++++----------- 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/interface/resources/shaders/splashSkybox.frag b/interface/resources/shaders/splashSkybox.frag index 38c89b4d26..244dad3356 100644 --- a/interface/resources/shaders/splashSkybox.frag +++ b/interface/resources/shaders/splashSkybox.frag @@ -1,47 +1,32 @@ -const vec3 COLOR = vec3(0x00, 0xD8, 0x02) / vec3(0xFF); -const float CUTOFF = 0.65; -const float NOISE_MULT = 8.0; -const float NOISE_POWER = 1.0; +// Replicate the default skybox texture -float noise4D(vec4 p) { - return fract(sin(dot(p ,vec4(12.9898,78.233,126.7235, 593.2241))) * 43758.5453); -} - -float worley4D(vec4 p) { - float r = 3.0; - vec4 f = floor(p); - vec4 x = fract(p); - for(int i = -1; i<=1; i++) - { - for(int j = -1; j<=1; j++) - { - for(int k = -1; k<=1; k++) - { - for (int l = -1; l <= 1; l++) { - vec4 q = vec4(float(i),float(j),float(k), float(l)); - vec4 v = q + vec4(noise4D((q+f)*1.11), noise4D((q+f)*1.14), noise4D((q+f)*1.17), noise4D((q+f)*1.20)) - x; - float d = dot(v, v); - r = min(r, d); - } - } - } - } - return sqrt(r); -} - - -vec3 mainColor(vec3 direction) { - float n = worley4D(vec4(direction * NOISE_MULT, iGlobalTime / 3.0)); - n = 1.0 - n; - n = pow(n, NOISE_POWER); - if (n < CUTOFF) { - return vec3(0.0); - } - - n = (n - CUTOFF) / (1.0 - CUTOFF); - return COLOR * (1.0 - n); -} +const int NUM_COLORS = 5; +const vec3 WHITISH = vec3(0.471, 0.725, 0.825); +const vec3 GREENISH = vec3(0.157, 0.529, 0.588); +const vec3 COLORS[NUM_COLORS] = vec3[]( + GREENISH, + GREENISH, + WHITISH, + WHITISH, + vec3(0.6, 0.275, 0.706) // purple +); +const float PI = 3.14159265359; +const vec3 BLACK = vec3(0.0); +const vec3 SPACE_BLUE = vec3(0.0, 0.118, 0.392); +const float HORIZONTAL_OFFSET = 3.75; vec3 getSkyboxColor() { - return mainColor(normalize(_normal)); + vec2 horizontal = vec2(_normal.x, _normal.z); + horizontal = normalize(horizontal); + float theta = atan(horizontal.y, horizontal.x); + theta = 0.5 * (theta / PI + 1.0); + float index = theta * NUM_COLORS; + index = mod(index + HORIZONTAL_OFFSET, NUM_COLORS); + int index1 = int(index) % NUM_COLORS; + int index2 = (index1 + 1) % NUM_COLORS; + vec3 horizonColor = mix(COLORS[index1], COLORS[index2], index - index1); + horizonColor = mix(horizonColor, SPACE_BLUE, smoothstep(0.0, 0.08, _normal.y)); + horizonColor = mix(horizonColor, BLACK, smoothstep(0.04, 0.15, _normal.y)); + horizonColor = mix(BLACK, horizonColor, smoothstep(-0.01, 0.0, _normal.y)); + return pow(horizonColor, vec3(0.4545));; } From 1fd03102c5c690f38745e83e4a229b7441ca5b09 Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 19 Nov 2018 17:40:43 -0800 Subject: [PATCH 035/117] debugging name mapping code --- libraries/animation/src/AnimSkeleton.cpp | 33 +++++++++++++++---- libraries/animation/src/AnimSkeleton.h | 4 ++- libraries/animation/src/Rig.cpp | 5 +++ .../src/avatars-renderer/Avatar.cpp | 12 ++++--- libraries/fbx/src/FBXReader.cpp | 2 +- 5 files changed, 43 insertions(+), 13 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 91ca2359b4..908b4eb1d3 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -23,6 +23,8 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { for (auto& joint : hfmModel.joints) { joints.push_back(joint); } + + _fbxToHifiJointNameMapping = hfmModel.fbxToHifiJointNameMapping; buildSkeletonFromJoints(joints, hfmModel.jointRotationOffsets); // we make a copy of the inverseBindMatrices in order to prevent mutating the model bind pose @@ -59,7 +61,16 @@ AnimSkeleton::AnimSkeleton(const std::vector& joints, const QMap AnimSkeleton::getChildrenOfJoint(int jointIndex) const { return result; } -const QString& AnimSkeleton::getJointName(int jointIndex) const { - return _joints[jointIndex].name; +const QString AnimSkeleton::getJointName(int jointIndex) const { + + QString jointName = _joints[jointIndex].name; + QMapIterator i(_fbxToHifiJointNameMapping); + while (i.hasNext()) { + i.next(); + if (i.value() == _joints[jointIndex].name) { + jointName = i.key(); + break; + } + } + return jointName; //;_joints[jointIndex].name; } AnimPose AnimSkeleton::getAbsolutePose(int jointIndex, const AnimPoseVec& relativePoses) const { @@ -245,9 +266,9 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, _nonMirroredIndices.clear(); _mirrorMap.reserve(_jointsSize); for (int i = 0; i < _jointsSize; i++) { - if (_joints[i].name != "Hips" && _joints[i].name != "Spine" && - _joints[i].name != "Spine1" && _joints[i].name != "Spine2" && - _joints[i].name != "Neck" && _joints[i].name != "Head" && + if (_joints[i].name != "Hips" && _joints[i].name != _fbxToHifiJointNameMapping["Hips"] && _joints[i].name != "Spine" && _joints[i].name != _fbxToHifiJointNameMapping["Spine"] && + _joints[i].name != "Spine1" && _joints[i].name != _fbxToHifiJointNameMapping["Spine1"] && _joints[i].name != "Spine2" && _joints[i].name != _fbxToHifiJointNameMapping["Spine2"] && + _joints[i].name != "Neck" && _joints[i].name != _fbxToHifiJointNameMapping["Neck"] && _joints[i].name != "Head" && _joints[i].name != _fbxToHifiJointNameMapping["Head"] && !((_joints[i].name.startsWith("Left") || _joints[i].name.startsWith("Right")) && _joints[i].name != "LeftEye" && _joints[i].name != "RightEye")) { // HACK: we don't want to mirror some joints so we remember their indices @@ -327,7 +348,7 @@ std::vector AnimSkeleton::lookUpJointIndices(const std::vector& jo for (auto& name : jointNames) { int index = nameToJointIndex(name); if (index == -1) { - qWarning(animation) << "AnimSkeleton::lookUpJointIndices(): could not find bone with named " << name; + qWarning(animation) << "AnimSkeleton::lookUpJointIndices(): could not find bone with name " << name; } result.push_back(index); } diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index ab89eb643d..bcbfe628c7 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -27,7 +27,7 @@ public: explicit AnimSkeleton(const std::vector& joints, const QMap jointOffsets); int nameToJointIndex(const QString& jointName) const; - const QString& getJointName(int jointIndex) const; + const QString getJointName(int jointIndex) const; int getNumJoints() const; int getChainDepth(int jointIndex) const; @@ -64,6 +64,7 @@ public: std::vector lookUpJointIndices(const std::vector& jointNames) const; const HFMCluster getClusterBindMatricesOriginalValues(const int meshIndex, const int clusterIndex) const { return _clusterBindMatrixOriginalValues[meshIndex][clusterIndex]; } + const QMap getFBXToHifiJointNameMapping() const { return _fbxToHifiJointNameMapping; } protected: void buildSkeletonFromJoints(const std::vector& joints, const QMap jointOffsets); @@ -79,6 +80,7 @@ protected: std::vector _mirrorMap; QHash _jointIndicesByName; std::vector> _clusterBindMatrixOriginalValues; + QMap _fbxToHifiJointNameMapping; // no copies AnimSkeleton(const AnimSkeleton&) = delete; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index baa8ac94ce..0c30a7696f 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -420,7 +420,12 @@ static const uint32_t MAX_JOINT_NAME_WARNING_COUNT = 100; int Rig::indexOfJoint(const QString& jointName) const { if (_animSkeleton) { + int result = _animSkeleton->nameToJointIndex(jointName); + if (_animSkeleton->getFBXToHifiJointNameMapping().contains(jointName)) { + qCDebug(animation) << "the alternate name for the joint " << jointName << " is " << _animSkeleton->getFBXToHifiJointNameMapping()[jointName] << " " << _animSkeleton->nameToJointIndex(_animSkeleton->getFBXToHifiJointNameMapping()[jointName]); + result = _animSkeleton->nameToJointIndex(jointName); + } // This is a content error, so we should issue a warning. if (result < 0 && _jointNameWarningCount < MAX_JOINT_NAME_WARNING_COUNT) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 4b730fccda..e5435a9a8c 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1438,18 +1438,20 @@ int Avatar::getJointIndex(const QString& name) const { if (_modelJointIndicesCache.contains(name)) { result = _modelJointIndicesCache[name] - 1; if (_skeletonModel && _skeletonModel->isActive()) { - qCDebug(avatars_renderer) << "the other head id is this" << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]; - qCDebug(avatars_renderer) << "joint indices cache " << name << " " << _modelJointIndicesCache[name]; + // qCDebug(avatars_renderer) << "the other head id is this" << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]; + // qCDebug(avatars_renderer) << "joint indices cache " << name << " " << _modelJointIndicesCache[name]; if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"])) { - qCDebug(avatars_renderer) << "joint alternate name " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"] << " " << _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]]; + // qCDebug(avatars_renderer) << "joint alternate name " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"] << " " << _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]]; } } } else { // doesn't contain name. qCDebug(avatars_renderer) << "name is not here"; if (_skeletonModel && _skeletonModel->isActive()) { - if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"])) { - qCDebug(avatars_renderer) << "the other head id is this" << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"] << " " << _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]];; + + if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name])) { + result = _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name]] - 1; + qCDebug(avatars_renderer) << "joint " << name << " remapped to " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name] << result; } } } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 343f7e6c6d..2e43573ec2 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -425,7 +425,7 @@ QMap getJointNameMapping(const QVariantHash& mapping) { for (auto itr = jointNames.begin(); itr != jointNames.end(); itr++) { qCDebug(modelformat) << "found a joint mapping field key " << itr.key() << " value " << itr.value().toString(); fbxToHifiJointNameMap.insert(itr.key(), itr.value().toString()); - qCDebug(modelformat) << "the mapped key (Head) has a value of " << fbxToHifiJointNameMap[itr.key()]; + qCDebug(modelformat) << "the mapped key " << itr.key() << " has a value of " << fbxToHifiJointNameMap[itr.key()]; } } From a94fec75b47cf1372797521424c7057fe5322373 Mon Sep 17 00:00:00 2001 From: David Back Date: Mon, 19 Nov 2018 17:59:42 -0800 Subject: [PATCH 036/117] prevent drag drop onto edit --- scripts/system/html/entityList.html | 1 + scripts/system/html/entityProperties.html | 1 + scripts/system/html/gridControls.html | 1 + scripts/system/html/js/entityList.js | 3 ++- scripts/system/html/js/entityProperties.js | 1 + scripts/system/html/js/gridControls.js | 1 + scripts/system/html/js/utils.js | 23 ++++++++++++++++++++++ 7 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 scripts/system/html/js/utils.js diff --git a/scripts/system/html/entityList.html b/scripts/system/html/entityList.html index 6915a45f19..f9948bc8b0 100644 --- a/scripts/system/html/entityList.html +++ b/scripts/system/html/entityList.html @@ -18,6 +18,7 @@ + diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 01395368b0..a8bcabbfea 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -23,6 +23,7 @@ + diff --git a/scripts/system/html/gridControls.html b/scripts/system/html/gridControls.html index 4be002619a..8d6ee34bc0 100644 --- a/scripts/system/html/gridControls.html +++ b/scripts/system/html/gridControls.html @@ -16,6 +16,7 @@ + diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index 84ad59df36..eb3e9ed882 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -1286,8 +1286,9 @@ function loaded() { }); augmentSpinButtons(); + disableDragDrop(); - document.addEventListener("contextmenu", function (event) { + document.addEventListener("contextmenu", function(event) { entityListContextMenu.close(); // Disable default right-click context menu which is not visible in the HMD and makes it seem like the app has locked diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index d3e0751732..6dc563b102 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -3479,6 +3479,7 @@ function loaded() { }); augmentSpinButtons(); + disableDragDrop(); // Disable right-click context menu which is not visible in the HMD and makes it seem like the app has locked document.addEventListener("contextmenu", function(event) { diff --git a/scripts/system/html/js/gridControls.js b/scripts/system/html/js/gridControls.js index b2d5988938..c2183130e9 100644 --- a/scripts/system/html/js/gridControls.js +++ b/scripts/system/html/js/gridControls.js @@ -108,6 +108,7 @@ function loaded() { }); augmentSpinButtons(); + disableDragDrop(); EventBridge.emitWebEvent(JSON.stringify({ type: 'init' })); }); diff --git a/scripts/system/html/js/utils.js b/scripts/system/html/js/utils.js new file mode 100644 index 0000000000..fe96e8b79e --- /dev/null +++ b/scripts/system/html/js/utils.js @@ -0,0 +1,23 @@ +// +// utils.js +// +// Created by David Back on 19 Nov 2018 +// Copyright 2016 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 +// + +function disableDragDrop() { + document.addEventListener("drop", function(event) { + event.preventDefault(); + event.dataTransfer.effectAllowed = "none"; + event.dataTransfer.dropEffect = "none"; + }, false); + + document.addEventListener("dragover", function(event) { + event.preventDefault(); + event.dataTransfer.effectAllowed = "none"; + event.dataTransfer.dropEffect = "none"; + }, false); +} From 0f7afb133ad817225d1febc13819767acc7d1a93 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Mon, 19 Nov 2018 17:59:50 -0800 Subject: [PATCH 037/117] Ensure that hand is in grasp pose during desktop handshake animation --- scripts/system/makeUserConnection.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index d205d368dd..4b59f050c9 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -229,6 +229,15 @@ } animationData.rightHandRotation = Quat.fromPitchYawRollDegrees(90, 0, 90); animationData.rightHandType = 0; // RotationAndPosition, see IKTargets.h + + // turn on the right hand grip overlay + animationData.rightHandOverlayAlpha = 1.0; + + // make sure the right hand grip animation is the "grasp", not pointing or thumbs up. + animationData.isRightHandGrasp = true; + animationData.isRightIndexPoint = false; + animationData.isRightThumbRaise = false; + animationData.isRightIndexPointAndThumbRaise = false; } function shakeHandsAnimation() { return animationData; From 58408497d1177006b462625175dfb0fa6715ef98 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 19 Nov 2018 21:27:23 -0500 Subject: [PATCH 038/117] hopefully fix hud crash --- .../display-plugins/OpenGLDisplayPlugin.cpp | 20 +++++++++---- .../display-plugins/hmd/HmdDisplayPlugin.cpp | 28 ++++++++++++------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 190d4d4104..9991130efc 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -534,18 +534,26 @@ void OpenGLDisplayPlugin::updateFrameData() { } std::function OpenGLDisplayPlugin::getHUDOperator() { - return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { - if (_hudPipeline && hudTexture) { + auto hudPipeline = _hudPipeline; + auto hudMirrorPipeline = _mirrorHUDPipeline; + auto hudStereo = isStereo(); + auto hudCompositeFramebufferSize = _compositeFramebuffer->getSize(); + glm::ivec4 hudEyeViewports[2]; + for_each_eye([&](Eye eye) { + hudEyeViewports[eye] = eyeViewport(eye); + }); + return [hudPipeline, hudMirrorPipeline, hudStereo, hudEyeViewports, hudCompositeFramebufferSize](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { + if (hudPipeline && hudTexture) { batch.enableStereo(false); - batch.setPipeline(mirror ? _mirrorHUDPipeline : _hudPipeline); + batch.setPipeline(mirror ? hudMirrorPipeline : hudPipeline); batch.setResourceTexture(0, hudTexture); - if (isStereo()) { + if (hudStereo) { for_each_eye([&](Eye eye) { - batch.setViewportTransform(eyeViewport(eye)); + batch.setViewportTransform(hudEyeViewports[eye]); batch.draw(gpu::TRIANGLE_STRIP, 4); }); } else { - batch.setViewportTransform(ivec4(uvec2(0), _compositeFramebuffer->getSize())); + batch.setViewportTransform(ivec4(uvec2(0), hudCompositeFramebufferSize)); batch.draw(gpu::TRIANGLE_STRIP, 4); } } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index d76b211ede..c0b1a7b753 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -420,18 +420,26 @@ void HmdDisplayPlugin::HUDRenderer::updatePipeline() { std::function HmdDisplayPlugin::HUDRenderer::render(HmdDisplayPlugin& plugin) { updatePipeline(); - return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { - if (pipeline && hudTexture) { - batch.setPipeline(pipeline); - batch.setInputFormat(format); - gpu::BufferView posView(vertices, VERTEX_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::POSITION)._element); - gpu::BufferView uvView(vertices, TEXTURE_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::TEXCOORD)._element); + auto hudPipeline = pipeline; + auto hudFormat = format; + auto hudVertices = vertices; + auto hudIndices = indices; + auto hudUniformBuffer = uniformsBuffer; + auto hudUniforms = uniforms; + auto hudIndexCount = indexCount; + return [hudPipeline, hudFormat, hudVertices, hudIndices, hudUniformBuffer, hudUniforms, hudIndexCount](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { + if (hudPipeline && hudTexture) { + batch.setPipeline(hudPipeline); + + batch.setInputFormat(hudFormat); + gpu::BufferView posView(hudVertices, VERTEX_OFFSET, hudVertices->getSize(), VERTEX_STRIDE, hudFormat->getAttributes().at(gpu::Stream::POSITION)._element); + gpu::BufferView uvView(hudVertices, TEXTURE_OFFSET, hudVertices->getSize(), VERTEX_STRIDE, hudFormat->getAttributes().at(gpu::Stream::TEXCOORD)._element); batch.setInputBuffer(gpu::Stream::POSITION, posView); batch.setInputBuffer(gpu::Stream::TEXCOORD, uvView); - batch.setIndexBuffer(gpu::UINT16, indices, 0); - uniformsBuffer->setSubData(0, uniforms); - batch.setUniformBuffer(0, uniformsBuffer); + batch.setIndexBuffer(gpu::UINT16, hudIndices, 0); + hudUniformBuffer->setSubData(0, hudUniforms); + batch.setUniformBuffer(0, hudUniformBuffer); auto compositorHelper = DependencyManager::get(); glm::mat4 modelTransform = compositorHelper->getUiTransform(); @@ -441,7 +449,7 @@ std::function HmdDis batch.setModelTransform(modelTransform); batch.setResourceTexture(0, hudTexture); - batch.drawIndexed(gpu::TRIANGLES, indexCount); + batch.drawIndexed(gpu::TRIANGLES, hudIndexCount); } }; } From e8d45c46c186863b304cacffb3a217650cf72f55 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 19 Nov 2018 23:31:20 -0500 Subject: [PATCH 039/117] shouldn't be able to write actionData --- libraries/entities/src/EntityScriptingInterface.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 3d68a27bc9..5487ae33b0 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -486,6 +486,8 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties propertiesWithSimID.setLastEditedBy(sessionID); + propertiesWithSimID.setActionData(QByteArray()); + bool scalesWithParent = propertiesWithSimID.getScalesWithParent(); propertiesWithSimID = convertPropertiesFromScriptSemantics(propertiesWithSimID, scalesWithParent); @@ -830,6 +832,8 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& properties.setClientOnly(entity->getClientOnly()); properties.setOwningAvatarID(entity->getOwningAvatarID()); + properties.setActionData(entity->getDynamicData()); + // make sure the properties has a type, so that the encode can know which properties to include properties.setType(entity->getType()); From 44efd18882ee8454a1c9c27d10f659b049a001e9 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 21 Nov 2018 08:38:30 +1300 Subject: [PATCH 040/117] Make Create and Shapes lasers ignore tablet while editing --- .../controllers/controllerDispatcher.js | 33 ++++++++++++++++--- .../controllerModules/inEditMode.js | 17 ---------- .../system/libraries/entitySelectionTool.js | 5 +-- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index b657faefba..a393205b5b 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -12,7 +12,7 @@ LEFT_HAND, RIGHT_HAND, NEAR_GRAB_PICK_RADIUS, DEFAULT_SEARCH_SPHERE_DISTANCE, DISPATCHER_PROPERTIES, getGrabPointSphereOffset, HMD, MyAvatar, Messages, findHandChildEntities, Picks, PickType, Pointers, PointerManager, getGrabPointSphereOffset, HMD, MyAvatar, Messages, findHandChildEntities, Picks, PickType, Pointers, - PointerManager, print, Selection, DISPATCHER_HOVERING_LIST, DISPATCHER_HOVERING_STYLE + PointerManager, print, Selection, DISPATCHER_HOVERING_LIST, DISPATCHER_HOVERING_STYLE, HIFI_EDIT_MANIPULATION_CHANNEL */ controllerDispatcherPlugins = {}; @@ -427,9 +427,19 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); } }; + this.leftBlacklistTabletIDs = []; + this.rightBlacklistTabletIDs = []; + + this.setLeftBlacklist = function () { + Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist.concat(_this.leftBlacklistTabletIDs)); + }; + this.setRightBlacklist = function () { + Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist.concat(_this.rightBlacklistTabletIDs)); + }; + this.setBlacklist = function() { - Pointers.setIgnoreItems(_this.leftPointer, this.blacklist); - Pointers.setIgnoreItems(_this.rightPointer, this.blacklist); + _this.setLeftBlacklist(); + _this.setRightBlacklist(); }; var MAPPING_NAME = "com.highfidelity.controllerDispatcher"; @@ -493,7 +503,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); filter: Picks.PICK_OVERLAYS | Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_NONCOLLIDABLE, enabled: true }); - this.handleHandMessage = function(channel, data, sender) { + this.handleMessage = function (channel, data, sender) { var message; if (sender === MyAvatar.sessionUUID) { try { @@ -514,6 +524,17 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); _this.setBlacklist(); } } + } else if (channel === HIFI_EDIT_MANIPULATION_CHANNEL) { + message = JSON.parse(data); + var tabletIDs = message.action === "startEdit" ? + [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID, HMD.homeButtonHighlightID] : []; + if (message.hand === Controller.Standard.LeftHand) { + _this.leftBlacklistTabletIDs = tabletIDs; + _this.setLeftBlacklist(); + } else if (message.hand === Controller.Standard.RightHand) { + _this.rightBlacklistTabletIDs = tabletIDs; + _this.setRightBlacklist(); + } } } catch (e) { print("WARNING: handControllerGrab.js -- error parsing message: " + data); @@ -554,7 +575,9 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); var controllerDispatcher = new ControllerDispatcher(); Messages.subscribe('Hifi-Hand-RayPick-Blacklist'); - Messages.messageReceived.connect(controllerDispatcher.handleHandMessage); + Messages.subscribe(HIFI_EDIT_MANIPULATION_CHANNEL); + Messages.messageReceived.connect(controllerDispatcher.handleMessage); + Script.scriptEnding.connect(controllerDispatcher.cleanup); Script.setTimeout(controllerDispatcher.update, BASIC_TIMER_INTERVAL_MS); }()); diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index 5d0b64606d..3a1b835146 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -20,7 +20,6 @@ Script.include("/~/system/libraries/utils.js"); var MARGIN = 25; function InEditMode(hand) { this.hand = hand; - this.running = false; this.triggerClicked = false; this.selectedTarget = null; this.reticleMinX = MARGIN; @@ -114,26 +113,10 @@ Script.include("/~/system/libraries/utils.js"); }; this.runModule = function() { - if (!this.running) { - Messages.sendLocalMessage(this.ENTITY_TOOL_UPDATES_CHANNEL, JSON.stringify({ - method: "moduleRunning", - hand: this.hand, - running: true - })); - this.running = true; - } return makeRunningValues(true, [], []); }; this.exitModule = function() { - if (this.running) { - Messages.sendLocalMessage(this.ENTITY_TOOL_UPDATES_CHANNEL, JSON.stringify({ - method: "moduleRunning", - hand: this.hand, - running: false - })); - this.running = false; - } return makeRunningValues(false, [], []); }; diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 191a961228..4552ed27fb 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -58,10 +58,7 @@ SelectionManager = (function() { return; } - if (messageParsed.method === "moduleRunning") { - // Terminate any current laser or mouse action. - SelectionDisplay.mouseReleaseEvent({}); - } else if (messageParsed.method === "selectEntity") { + if (messageParsed.method === "selectEntity") { if (!SelectionDisplay.triggered() || SelectionDisplay.triggeredHand === messageParsed.hand) { if (wantDebug) { print("setting selection to " + messageParsed.entityID); From c3a0805db1eadb9386297452b2a8692296c77cd3 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 21 Nov 2018 10:28:46 +1300 Subject: [PATCH 041/117] Make far grab ignore tablet while grabbing an entity --- .../farActionGrabEntityDynOnly.js | 14 +++++++++----- .../controllerModules/farParentGrabEntity.js | 17 +++++++++-------- .../controllers/controllerModules/farTrigger.js | 2 +- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntityDynOnly.js b/scripts/system/controllers/controllerModules/farActionGrabEntityDynOnly.js index f983ed1e7d..0ba3dd6e6b 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntityDynOnly.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntityDynOnly.js @@ -48,6 +48,7 @@ Script.include("/~/system/libraries/controllers.js"); function FarActionGrabEntity(hand) { this.hand = hand; + this.grabbing = false; this.grabbedThingID = null; this.targetObject = null; this.actionID = null; // action this script created... @@ -151,6 +152,7 @@ Script.include("/~/system/libraries/controllers.js"); Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); this.previousRoomControllerPosition = roomControllerPosition; + this.grabbing = true; }; this.continueDistanceHolding = function(controllerData) { @@ -246,6 +248,7 @@ Script.include("/~/system/libraries/controllers.js"); this.grabbedThingID = null; this.targetObject = null; this.potentialEntityWithContextOverlay = false; + this.grabbing = false; }; this.updateRecommendedArea = function() { @@ -357,8 +360,7 @@ Script.include("/~/system/libraries/controllers.js"); }; this.run = function (controllerData) { - if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || - this.notPointingAtEntity(controllerData) || this.targetIsNull()) { + if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || this.targetIsNull()) { this.endFarGrabAction(); Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", this.highlightedEntity); @@ -375,10 +377,12 @@ Script.include("/~/system/libraries/controllers.js"); this.hand === RIGHT_HAND ? "RightScaleAvatar" : "LeftScaleAvatar", this.hand === RIGHT_HAND ? "RightFarTriggerEntity" : "LeftFarTriggerEntity", this.hand === RIGHT_HAND ? "RightNearActionGrabEntity" : "LeftNearActionGrabEntity", - this.hand === RIGHT_HAND ? "RightNearParentingGrabEntity" : "LeftNearParentingGrabEntity", - this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay", - this.hand === RIGHT_HAND ? "RightNearTabletHighlight" : "LeftNearTabletHighlight" + this.hand === RIGHT_HAND ? "RightNearParentingGrabEntity" : "LeftNearParentingGrabEntity" ]; + if (!this.grabbing) { + nearGrabNames.push(this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay"); + nearGrabNames.push(this.hand === RIGHT_HAND ? "RightNearTabletHighlight" : "LeftNearTabletHighlight"); + } var nearGrabReadiness = []; for (var i = 0; i < nearGrabNames.length; i++) { diff --git a/scripts/system/controllers/controllerModules/farParentGrabEntity.js b/scripts/system/controllers/controllerModules/farParentGrabEntity.js index f85869aa7f..c023c4032d 100644 --- a/scripts/system/controllers/controllerModules/farParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farParentGrabEntity.js @@ -47,6 +47,7 @@ Script.include("/~/system/libraries/controllers.js"); function FarParentGrabEntity(hand) { this.hand = hand; + this.grabbing = false; this.targetEntityID = null; this.targetObject = null; this.previouslyUnhooked = {}; @@ -453,8 +454,7 @@ Script.include("/~/system/libraries/controllers.js"); }; this.run = function (controllerData) { - if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || - this.notPointingAtEntity(controllerData) || this.targetIsNull()) { + if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || this.targetIsNull()) { this.endFarParentGrab(controllerData); Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", this.highlightedEntity); this.highlightedEntity = null; @@ -470,10 +470,12 @@ Script.include("/~/system/libraries/controllers.js"); this.hand === RIGHT_HAND ? "RightScaleAvatar" : "LeftScaleAvatar", this.hand === RIGHT_HAND ? "RightFarTriggerEntity" : "LeftFarTriggerEntity", this.hand === RIGHT_HAND ? "RightNearActionGrabEntity" : "LeftNearActionGrabEntity", - this.hand === RIGHT_HAND ? "RightNearParentingGrabEntity" : "LeftNearParentingGrabEntity", - this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay", - this.hand === RIGHT_HAND ? "RightNearTabletHighlight" : "LeftNearTabletHighlight" + this.hand === RIGHT_HAND ? "RightNearParentingGrabEntity" : "LeftNearParentingGrabEntity" ]; + if (!this.grabbing) { + nearGrabNames.push(this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay"); + nearGrabNames.push(this.hand === RIGHT_HAND ? "RightNearTabletHighlight" : "LeftNearTabletHighlight"); + } var nearGrabReadiness = []; for (var i = 0; i < nearGrabNames.length; i++) { @@ -483,11 +485,10 @@ Script.include("/~/system/libraries/controllers.js"); } if (this.targetEntityID) { - // if we are doing a distance grab and the object or tablet gets close enough to the controller, + // if we are doing a distance grab and the object gets close enough to the controller, // stop the far-grab so the near-grab or equip can take over. for (var k = 0; k < nearGrabReadiness.length; k++) { - if (nearGrabReadiness[k].active && (nearGrabReadiness[k].targets[0] === this.targetEntityID || - HMD.tabletID && nearGrabReadiness[k].targets[0] === HMD.tabletID)) { + if (nearGrabReadiness[k].active && (nearGrabReadiness[k].targets[0] === this.targetEntityID)) { this.endFarParentGrab(controllerData); return makeRunningValues(false, [], []); } diff --git a/scripts/system/controllers/controllerModules/farTrigger.js b/scripts/system/controllers/controllerModules/farTrigger.js index 2b003e4732..c9c9d3deee 100644 --- a/scripts/system/controllers/controllerModules/farTrigger.js +++ b/scripts/system/controllers/controllerModules/farTrigger.js @@ -37,7 +37,7 @@ Script.include("/~/system/libraries/controllers.js"); this.getTargetProps = function (controllerData) { var targetEntity = controllerData.rayPicks[this.hand].objectID; - if (targetEntity) { + if (targetEntity && controllerData.rayPicks[this.hand].type === RayPick.INTERSECTED_ENTITY) { var targetProperties = Entities.getEntityProperties(targetEntity, DISPATCHER_PROPERTIES); if (entityWantsFarTrigger(targetProperties)) { return targetProperties; From b0aa1b2af28bf573ba27c07793f45d3c54512c25 Mon Sep 17 00:00:00 2001 From: birarda Date: Tue, 20 Nov 2018 11:54:57 -0800 Subject: [PATCH 042/117] make domain settings maps keyed case insensitively --- .../resources/web/js/base-settings.js | 8 ++-- domain-server/src/DomainServer.cpp | 38 ++++++++++++------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/domain-server/resources/web/js/base-settings.js b/domain-server/resources/web/js/base-settings.js index fd404aff20..bd96f636a8 100644 --- a/domain-server/resources/web/js/base-settings.js +++ b/domain-server/resources/web/js/base-settings.js @@ -364,7 +364,7 @@ function validateInputs() { if (keyVal.length === 0) { empty = true - markParentRowInvalid(input); + markParentRowInvalid(input) return; } @@ -373,11 +373,13 @@ function validateInputs() { _.each(otherKeys, function(otherKeyCell) { var keyInput = $(otherKeyCell).children('input'); + var lowerNewValue = keyVal.toLowerCase(); + if (keyInput.length) { - if ($(keyInput).val() == keyVal) { + if ($(keyInput).val().toLowerCase() == lowerNewValue) { duplicateKey = true; } - } else if ($(otherKeyCell).html() == keyVal) { + } else if ($(otherKeyCell).html().toLowerCase() == lowerNewValue) { duplicateKey = true; } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 69f16af8b3..258038b8f1 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -3172,24 +3172,34 @@ void DomainServer::processPathQueryPacket(QSharedPointer messag const QString PATH_VIEWPOINT_KEY = "viewpoint"; const QString INDEX_PATH = "/"; - // check out paths in the _configMap to see if we have a match - auto keypath = QString(PATHS_SETTINGS_KEYPATH_FORMAT).arg(SETTINGS_PATHS_KEY).arg(pathQuery); - QVariant pathMatch = _settingsManager.valueForKeyPath(keypath); + QString responseViewpoint; - if (pathMatch.isValid() || pathQuery == INDEX_PATH) { + // check out paths in the _configMap to see if we have a match + auto pathsVariant = _settingsManager.valueForKeyPath(SETTINGS_PATHS_KEY); + + auto lowerPathQuery = pathQuery.toLower(); + + if (pathsVariant.canConvert()) { + auto pathsMap = pathsVariant.toMap(); + + // enumerate the paths and look case-insensitively for a matching one + for (auto it = pathsMap.constKeyValueBegin(); it != pathsMap.constKeyValueEnd(); ++it) { + if ((*it).first.toLower() == lowerPathQuery) { + responseViewpoint = (*it).second.toMap()[PATH_VIEWPOINT_KEY].toString().toLower(); + break; + } + } + } + + if (responseViewpoint.isEmpty() && pathQuery == INDEX_PATH) { + const QString DEFAULT_INDEX_PATH = "/0,0,0/0,0,0,1"; + responseViewpoint = DEFAULT_INDEX_PATH; + } + + if (!responseViewpoint.isEmpty()) { // we got a match, respond with the resulting viewpoint auto nodeList = DependencyManager::get(); - QString responseViewpoint; - - // if we didn't match the path BUT this is for the index path then send back our default - if (pathMatch.isValid()) { - responseViewpoint = pathMatch.toMap()[PATH_VIEWPOINT_KEY].toString(); - } else { - const QString DEFAULT_INDEX_PATH = "/0,0,0/0,0,0,1"; - responseViewpoint = DEFAULT_INDEX_PATH; - } - if (!responseViewpoint.isEmpty()) { QByteArray viewpointUTF8 = responseViewpoint.toUtf8(); From b2bd0d99de4b05f41c5f66b1f819c713437a0df0 Mon Sep 17 00:00:00 2001 From: birarda Date: Tue, 20 Nov 2018 16:07:48 -0800 Subject: [PATCH 043/117] add a warning for cloud domain ID changes --- .../resources/web/settings/js/settings.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/domain-server/resources/web/settings/js/settings.js b/domain-server/resources/web/settings/js/settings.js index 3888277c00..2950b8de75 100644 --- a/domain-server/resources/web/settings/js/settings.js +++ b/domain-server/resources/web/settings/js/settings.js @@ -18,9 +18,6 @@ $(document).ready(function(){ Settings.extraGroupsAtIndex = Settings.extraDomainGroupsAtIndex; Settings.afterReloadActions = function() { - // append the domain selection modal - appendDomainIDButtons(); - // call our method to setup the HF account button setupHFAccountButton(); @@ -52,6 +49,11 @@ $(document).ready(function(){ if (cloudWizardExit != undefined) { $('#cloud-domains-alert').show(); } + + $(Settings.DOMAIN_ID_SELECTOR).siblings('span').append("
Changing the domain ID for a Cloud Domain may result in an incorrect status for the domain on your Cloud Domains page."); + } else { + // append the domain selection modal + appendDomainIDButtons(); } handleAction(); @@ -59,9 +61,9 @@ $(document).ready(function(){ Settings.handlePostSettings = function(formJSON) { - if (!verifyAvatarHeights()) { - return false; - } + if (!verifyAvatarHeights()) { + return false; + } // check if we've set the basic http password if (formJSON["security"]) { From 572cdcd008f4758debd3c80ea8abb79fcd27c9b3 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 20 Nov 2018 17:09:37 -0800 Subject: [PATCH 044/117] remapping is now able to work remains to clean up code and check for gotchas from old fst code --- libraries/animation/src/AnimSkeleton.cpp | 102 +++++++++++++++--- libraries/animation/src/AnimSkeleton.h | 3 + libraries/animation/src/Rig.cpp | 2 +- .../src/avatars-renderer/Avatar.cpp | 4 +- .../src/avatars-renderer/SkeletonModel.cpp | 1 + libraries/fbx/src/FBXReader.cpp | 28 ++--- 6 files changed, 110 insertions(+), 30 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 908b4eb1d3..6e71ef0184 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -54,6 +54,7 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { } _clusterBindMatrixOriginalValues.push_back(dummyClustersList); } + //dump(false); } AnimSkeleton::AnimSkeleton(const std::vector& joints, const QMap jointOffsets) { @@ -64,16 +65,18 @@ int AnimSkeleton::nameToJointIndex(const QString& jointName) const { auto itr = _jointIndicesByName.find(jointName); - if (getFBXToHifiJointNameMapping().contains(jointName)) { - qCDebug(animation) << "failing joint name is " << jointName; + if (_fbxToHifiJointNameMapping.contains(jointName)) { + //qCDebug(animation) << "failing joint name is " << jointName; itr = _jointIndicesByName.find(_fbxToHifiJointNameMapping[jointName]); - qCDebug(animation) << "the alternate name for the joint " << jointName << " is " << - _fbxToHifiJointNameMapping[jointName] << " " << itr.value(); + //qCDebug(animation) << "the alternate name for the joint " << jointName << " is " << + //_fbxToHifiJointNameMapping[jointName] << " " << itr.value(); } if (_jointIndicesByName.end() != itr) { + //qCDebug(animation) << "returning " << itr.value() << " for " << jointName; return itr.value(); } + //qCDebug(animation) << "returning -1 " << " for " << jointName; return -1; } @@ -142,6 +145,7 @@ const QString AnimSkeleton::getJointName(int jointIndex) const { break; } } + //qCDebug(animation) << "reverse lookup: returning " << jointName << " for " << jointIndex; return jointName; //;_joints[jointIndex].name; } @@ -215,6 +219,81 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const { } } +bool AnimSkeleton::checkNonMirrored(QString jointName) const { + + //bool isNonMirrored = false; + QMapIterator i(_fbxToHifiJointNameMapping); + while (i.hasNext()) { + i.next(); + if (i.value() == jointName) { + // check for left right in the key + if (i.key() != "Hips" && i.key() != "Spine" && + i.key() != "Spine1" && i.key() != "Spine2" && + i.key() != "Neck" && i.key() != "Head" && + !((i.key().startsWith("Left") || i.key().startsWith("Right")) && + i.key() != "LeftEye" && i.key() != "RightEye")) { + //return true + return true; + } else { + return false; + } + } + } + // check the unmapped name + if (jointName != "Hips" && jointName != "Spine" && + jointName != "Spine1" && jointName != "Spine2" && + jointName != "Neck" && jointName != "Head" && + !((jointName.startsWith("Left") || jointName.startsWith("Right")) && + jointName != "LeftEye" && jointName != "RightEye")) { + //return true + return true; + } else { + return false; + } + +} + +int AnimSkeleton::containsLeft(QString jointName) const { + QMapIterator i(_fbxToHifiJointNameMapping); + int mirrorJointIndex = -1; + while (i.hasNext()) { + i.next(); + if (i.value() == jointName) { + // check for left right in the key + if (i.key().startsWith("Left")) { + QString mirrorJointName = QString(i.key()).replace(0, 4, "Right"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + //return true + } + } + } + if (jointName.startsWith("Left")) { + QString mirrorJointName = QString(i.key()).replace(0, 4, "Right"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + } + return mirrorJointIndex; +} + +int AnimSkeleton::containsRight(QString jointName) const { + QMapIterator i(_fbxToHifiJointNameMapping); + int mirrorJointIndex = -1; + while (i.hasNext()) { + i.next(); + if (i.value() == jointName) { + // check for left right in the key + if (i.key().startsWith("Right")) { + QString mirrorJointName = QString(i.key()).replace(0, 5, "Left"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + } + } + } + if (jointName.startsWith("Right")) { + QString mirrorJointName = QString(i.key()).replace(0, 5, "Left"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + } + return mirrorJointIndex; +} + void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, const QMap jointOffsets) { _joints = joints; @@ -266,22 +345,15 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, _nonMirroredIndices.clear(); _mirrorMap.reserve(_jointsSize); for (int i = 0; i < _jointsSize; i++) { - if (_joints[i].name != "Hips" && _joints[i].name != _fbxToHifiJointNameMapping["Hips"] && _joints[i].name != "Spine" && _joints[i].name != _fbxToHifiJointNameMapping["Spine"] && - _joints[i].name != "Spine1" && _joints[i].name != _fbxToHifiJointNameMapping["Spine1"] && _joints[i].name != "Spine2" && _joints[i].name != _fbxToHifiJointNameMapping["Spine2"] && - _joints[i].name != "Neck" && _joints[i].name != _fbxToHifiJointNameMapping["Neck"] && _joints[i].name != "Head" && _joints[i].name != _fbxToHifiJointNameMapping["Head"] && - !((_joints[i].name.startsWith("Left") || _joints[i].name.startsWith("Right")) && - _joints[i].name != "LeftEye" && _joints[i].name != "RightEye")) { + if (checkNonMirrored(_joints[i].name)) { // HACK: we don't want to mirror some joints so we remember their indices // so we can restore them after a future mirror operation _nonMirroredIndices.push_back(i); } int mirrorJointIndex = -1; - if (_joints[i].name.startsWith("Left")) { - QString mirrorJointName = QString(_joints[i].name).replace(0, 4, "Right"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); - } else if (_joints[i].name.startsWith("Right")) { - QString mirrorJointName = QString(_joints[i].name).replace(0, 5, "Left"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); + mirrorJointIndex = containsLeft(_joints[i].name); + if (mirrorJointIndex > -1) { + mirrorJointIndex = containsRight(_joints[i].name); } if (mirrorJointIndex >= 0) { _mirrorMap.push_back(mirrorJointIndex); diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index bcbfe628c7..5581976d74 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -56,6 +56,9 @@ public: void saveNonMirroredPoses(const AnimPoseVec& poses) const; void restoreNonMirroredPoses(AnimPoseVec& poses) const; + bool checkNonMirrored(QString jointName) const; + int containsLeft(QString jointName) const; + int containsRight(QString jointName) const; void mirrorRelativePoses(AnimPoseVec& poses) const; void mirrorAbsolutePoses(AnimPoseVec& poses) const; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 0c30a7696f..1675ea8e90 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -423,7 +423,7 @@ int Rig::indexOfJoint(const QString& jointName) const { int result = _animSkeleton->nameToJointIndex(jointName); if (_animSkeleton->getFBXToHifiJointNameMapping().contains(jointName)) { - qCDebug(animation) << "the alternate name for the joint " << jointName << " is " << _animSkeleton->getFBXToHifiJointNameMapping()[jointName] << " " << _animSkeleton->nameToJointIndex(_animSkeleton->getFBXToHifiJointNameMapping()[jointName]); + //qCDebug(animation) << "the alternate name for the joint " << jointName << " is " << _animSkeleton->getFBXToHifiJointNameMapping()[jointName] << " " << _animSkeleton->nameToJointIndex(_animSkeleton->getFBXToHifiJointNameMapping()[jointName]); result = _animSkeleton->nameToJointIndex(jointName); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index e5435a9a8c..14e97a5bf9 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1446,12 +1446,12 @@ int Avatar::getJointIndex(const QString& name) const { } } else { // doesn't contain name. - qCDebug(avatars_renderer) << "name is not here"; + //qCDebug(avatars_renderer) << "name is not here"; if (_skeletonModel && _skeletonModel->isActive()) { if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name])) { result = _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name]] - 1; - qCDebug(avatars_renderer) << "joint " << name << " remapped to " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name] << result; + // qCDebug(avatars_renderer) << "joint " << name << " remapped to " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name] << result; } } } diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index 36e37dd3d4..a97ba4bf4b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -317,6 +317,7 @@ bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& seco } glm::vec3 SkeletonModel::getDefaultEyeModelPosition() const { + //qCDebug(avatars_renderer) << "default eye model position " << _defaultEyeModelPosition; return _owningAvatar->getModelScale() * _defaultEyeModelPosition; } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 2e43573ec2..3ddcd75255 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -485,7 +485,7 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& QString jointNeckName = processID(getString(joints.value("jointNeck", "jointNeck"))); QString jointRootName = processID(getString(joints.value("jointRoot", "jointRoot"))); QString jointLeanName = processID(getString(joints.value("jointLean", "jointLean"))); - QString jointHeadName = processID(getString(joints.value("jointHead", "jointHead"))); + QString jointHeadName = "Head";// processID(getString(joints.value("jointHead", "jointHead"))); QString jointLeftHandName = processID(getString(joints.value("jointLeftHand", "jointLeftHand"))); QString jointRightHandName = processID(getString(joints.value("jointRightHand", "jointRightHand"))); QString jointEyeLeftID; @@ -534,6 +534,8 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& HFMModel& hfmModel = *hfmModelPtr; hfmModel.originalURL = url; + hfmModel.fbxToHifiJointNameMapping.clear(); + hfmModel.fbxToHifiJointNameMapping = getJointNameMapping(mapping); float unitScaleFactor = 1.0f; glm::vec3 ambientColor; @@ -602,34 +604,34 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& hifiGlobalNodeID = id; } - if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye") { + if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye" || (hfmModel.fbxToHifiJointNameMapping.contains(jointEyeLeftName) && (name == hfmModel.fbxToHifiJointNameMapping[jointEyeLeftName]))) { jointEyeLeftID = getID(object.properties); - } else if (name == jointEyeRightName || name == "EyeR" || name == "joint_Reye") { + } else if (name == jointEyeRightName || name == "EyeR" || name == "joint_Reye" || (hfmModel.fbxToHifiJointNameMapping.contains(jointEyeRightName) && (name == hfmModel.fbxToHifiJointNameMapping[jointEyeRightName]))) { jointEyeRightID = getID(object.properties); - } else if (name == jointNeckName || name == "NeckRot" || name == "joint_neck") { + } else if (name == jointNeckName || name == "NeckRot" || name == "joint_neck" || (hfmModel.fbxToHifiJointNameMapping.contains(jointNeckName) && (name == hfmModel.fbxToHifiJointNameMapping[jointNeckName]))) { jointNeckID = getID(object.properties); - } else if (name == jointRootName) { + } else if (name == jointRootName || (hfmModel.fbxToHifiJointNameMapping.contains(jointRootName) && (name == hfmModel.fbxToHifiJointNameMapping[jointRootName]))) { jointRootID = getID(object.properties); } else if (name == jointLeanName) { jointLeanID = getID(object.properties); - } else if (name == jointHeadName) { + } else if ((name == jointHeadName) || (hfmModel.fbxToHifiJointNameMapping.contains(jointHeadName) && (name == hfmModel.fbxToHifiJointNameMapping[jointHeadName]))) { jointHeadID = getID(object.properties); - } else if (name == jointLeftHandName || name == "LeftHand" || name == "joint_L_hand") { + } else if (name == jointLeftHandName || name == "LeftHand" || name == "joint_L_hand" || (hfmModel.fbxToHifiJointNameMapping.contains(jointLeftHandName) && (name == hfmModel.fbxToHifiJointNameMapping[jointLeftHandName]))) { jointLeftHandID = getID(object.properties); - } else if (name == jointRightHandName || name == "RightHand" || name == "joint_R_hand") { + } else if (name == jointRightHandName || name == "RightHand" || name == "joint_R_hand" || (hfmModel.fbxToHifiJointNameMapping.contains(jointRightHandName) && (name == hfmModel.fbxToHifiJointNameMapping[jointRightHandName]))) { jointRightHandID = getID(object.properties); - } else if (name == "LeftToe" || name == "joint_L_toe" || name == "LeftToe_End") { + } else if (name == "LeftToe" || name == "joint_L_toe" || name == "LeftToe_End" || (hfmModel.fbxToHifiJointNameMapping.contains("LeftToe") && (name == hfmModel.fbxToHifiJointNameMapping["LeftToe"]))) { jointLeftToeID = getID(object.properties); - } else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End") { + } else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End" || (hfmModel.fbxToHifiJointNameMapping.contains("RightToe") && (name == hfmModel.fbxToHifiJointNameMapping["RightToe"]))) { jointRightToeID = getID(object.properties); } @@ -1839,14 +1841,16 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& QString jointName = itr.key(); glm::quat rotationOffset = itr.value(); int jointIndex = hfmModel.getJointIndex(jointName); + if (hfmModel.fbxToHifiJointNameMapping.contains(jointName)) { + jointIndex = hfmModel.getJointIndex(hfmModel.fbxToHifiJointNameMapping[jointName]); + } if (jointIndex != -1) { hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); } qCDebug(modelformat) << "Joint Rotation Offset added to Rig._jointRotationOffsets : " << " jointName: " << jointName << " jointIndex: " << jointIndex << " rotation offset: " << rotationOffset; } - hfmModel.fbxToHifiJointNameMapping.clear(); - hfmModel.fbxToHifiJointNameMapping = getJointNameMapping(mapping); + return hfmModelPtr; } From a4883649760c15a6ff148720e3f49874c6277c6f Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 20 Nov 2018 17:14:35 -0800 Subject: [PATCH 045/117] fixed mirroring helper functions contains left and contains right --- libraries/animation/src/AnimSkeleton.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 6e71ef0184..e928658366 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -268,7 +268,7 @@ int AnimSkeleton::containsLeft(QString jointName) const { } } if (jointName.startsWith("Left")) { - QString mirrorJointName = QString(i.key()).replace(0, 4, "Right"); + QString mirrorJointName = QString(jointName).replace(0, 4, "Right"); mirrorJointIndex = nameToJointIndex(mirrorJointName); } return mirrorJointIndex; @@ -288,7 +288,7 @@ int AnimSkeleton::containsRight(QString jointName) const { } } if (jointName.startsWith("Right")) { - QString mirrorJointName = QString(i.key()).replace(0, 5, "Left"); + QString mirrorJointName = QString(jointName).replace(0, 5, "Left"); mirrorJointIndex = nameToJointIndex(mirrorJointName); } return mirrorJointIndex; From 44b9b92450f9f2c884a9cad8194dcc8225c6719a Mon Sep 17 00:00:00 2001 From: sam gateau Date: Tue, 20 Nov 2018 17:32:04 -0800 Subject: [PATCH 046/117] Getting ready for merge --- interface/src/Application.cpp | 39 +---- interface/src/Application.h | 18 -- interface/src/graphics/GraphicsEngine.cpp | 31 +--- interface/src/graphics/GraphicsEngine.h | 6 - interface/src/graphics/RenderEventHandler.cpp | 4 - interface/src/graphics/RenderThread.cpp | 1 - interface/src/graphics/RenderThread.h | 108 ------------ interface/src/ui/ApplicationOverlay.cpp | 2 - .../utilities/render/GlobalLighting.js | 155 ------------------ .../utilities/render/engineInspector.js | 71 -------- .../utilities/render/engineInspector.qml | 30 ---- .../utilities/render/engineProfiler.js | 59 ------- .../utilities/render/engineProfiler.qml | 31 ---- 13 files changed, 10 insertions(+), 545 deletions(-) delete mode 100644 interface/src/graphics/RenderThread.cpp delete mode 100644 interface/src/graphics/RenderThread.h delete mode 100644 scripts/developer/utilities/render/GlobalLighting.js delete mode 100644 scripts/developer/utilities/render/engineInspector.js delete mode 100644 scripts/developer/utilities/render/engineInspector.qml delete mode 100644 scripts/developer/utilities/render/engineProfiler.js delete mode 100644 scripts/developer/utilities/render/engineProfiler.qml diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f4bd15403e..dae9e3dad2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -87,7 +87,6 @@ #include #include #include -//#include #include #include #include @@ -2313,7 +2312,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->createKeyboard(); _pendingIdleEvent = false; - // _pendingRenderEvent = false; _graphicsEngine.startup(); qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); @@ -2578,11 +2576,6 @@ void Application::cleanupBeforeQuit() { // Cleanup all overlays after the scripts, as scripts might add more _overlays.cleanupAllOverlays(); - // The cleanup process enqueues the transactions but does not process them. Calling this here will force the actual - // removal of the items. - // See https://highfidelity.fogbugz.com/f/cases/5328 - // _main3DScene->enqueueFrame(); // flush all the transactions - // _main3DScene->processTransactionQueue(); // process and apply deletions // first stop all timers directly or by invokeMethod // depending on what thread they run in @@ -2598,8 +2591,6 @@ void Application::cleanupBeforeQuit() { _window->saveGeometry(); - // _gpuContext->shutdown(); - // Destroy third party processes after scripts have finished using them. #ifdef HAVE_DDE DependencyManager::destroy(); @@ -2655,9 +2646,7 @@ Application::~Application() { _shapeManager.collectGarbage(); assert(_shapeManager.getNumShapes() == 0); - // shutdown render engine - //_main3DScene = nullptr; - //_renderEngine = nullptr; + // shutdown graphics engine _graphicsEngine.shutdown(); _gameWorkload.shutdown(); @@ -2717,9 +2706,6 @@ Application::~Application() { // Can't log to file passed this point, FileLogger about to be deleted qInstallMessageHandler(LogHandler::verboseMessageHandler); - - -// _renderEventHandler->deleteLater(); } void Application::initializeGL() { @@ -4681,19 +4667,6 @@ void Application::idle() { PROFILE_COUNTER_IF_CHANGED(app, "pendingProcessing", int, DependencyManager::get()->getStat("PendingProcessing").toInt()); auto renderConfig = _graphicsEngine.getRenderEngine()->getConfiguration(); PROFILE_COUNTER_IF_CHANGED(render, "gpuTime", float, (float)_graphicsEngine.getGPUContext()->getFrameTimerGPUAverage()); -/* auto opaqueRangeTimer = renderConfig->getConfig("OpaqueRangeTimer"); - auto linearDepth = renderConfig->getConfig("LinearDepth"); - auto surfaceGeometry = renderConfig->getConfig("SurfaceGeometry"); - auto renderDeferred = renderConfig->getConfig("RenderDeferred"); - auto toneAndPostRangeTimer = renderConfig->getConfig("ToneAndPostRangeTimer"); - - PROFILE_COUNTER(render_detail, "gpuTimes", { - { "OpaqueRangeTimer", opaqueRangeTimer ? opaqueRangeTimer->property("gpuRunTime") : 0 }, - { "LinearDepth", linearDepth ? linearDepth->property("gpuRunTime") : 0 }, - { "SurfaceGeometry", surfaceGeometry ? surfaceGeometry->property("gpuRunTime") : 0 }, - { "RenderDeferred", renderDeferred ? renderDeferred->property("gpuRunTime") : 0 }, - { "ToneAndPostRangeTimer", toneAndPostRangeTimer ? toneAndPostRangeTimer->property("gpuRunTime") : 0 } - });*/ PROFILE_RANGE(app, __FUNCTION__); @@ -5062,9 +5035,6 @@ QVector Application::pasteEntities(float x, float y, float z) { void Application::init() { // Make sure Login state is up to date DependencyManager::get()->toggleLoginDialog(); -// if (!DISABLE_DEFERRED) { - // DependencyManager::get()->init(); - // } DependencyManager::get()->init(); _timerStart.start(); @@ -6129,13 +6099,6 @@ void Application::update(float deltaTime) { updateRenderArgs(deltaTime); - // HACK - // load the view frustum - // FIXME: This preDisplayRender call is temporary until we create a separate render::scene for the mirror rendering. - // Then we can move this logic into the Avatar::simulate call. -// myAvatar->preDisplaySide(&_appRenderArgs._renderArgs); - - { PerformanceTimer perfTimer("AnimDebugDraw"); AnimDebugDraw::getInstance().update(); diff --git a/interface/src/Application.h b/interface/src/Application.h index b5ce040c94..2f23fc72d7 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -153,8 +153,6 @@ public: void updateSecondaryCameraViewFrustum(); void updateCamera(RenderArgs& renderArgs, float deltaTime); - // bool shouldPaint() const; -// void paintGL(); void resizeGL(); bool event(QEvent* event) override; @@ -276,11 +274,6 @@ public: void setMaxOctreePacketsPerSecond(int maxOctreePPS); int getMaxOctreePacketsPerSecond() const; -/* render::ScenePointer getMain3DScene() override { return _main3DScene; } - const render::ScenePointer& getMain3DScene() const { return _main3DScene; } - render::EnginePointer getRenderEngine() override { return _renderEngine; } - gpu::ContextPointer getGPUContext() const { return _gpuContext; } - */ render::ScenePointer getMain3DScene() override { return _graphicsEngine.getRenderScene(); } const render::ScenePointer& getMain3DScene() const { return _graphicsEngine.getRenderScene(); } render::EnginePointer getRenderEngine() override { return _graphicsEngine.getRenderEngine(); } @@ -541,8 +534,6 @@ private: void initializeAcceptedFiles(); - // void runRenderFrame(RenderArgs* renderArgs/*, Camera& whichCamera, bool selfAvatarOnly = false*/); - bool importJSONFromURL(const QString& urlString); bool importSVOFromURL(const QString& urlString); bool importFromZIP(const QString& filePath); @@ -598,7 +589,6 @@ private: QTimer _minimizedWindowTimer; QElapsedTimer _timerStart; QElapsedTimer _lastTimeUpdated; - // QElapsedTimer _lastTimeRendered; int _minimumGPUTextureMemSizeStabilityCount { 30 }; @@ -684,10 +674,6 @@ private: quint64 _lastFaceTrackerUpdate; - // render::ScenePointer _main3DScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) }; - // render::EnginePointer _renderEngine{ new render::RenderEngine() }; - // gpu::ContextPointer _gpuContext; // initialized during window creation - GameWorkload _gameWorkload; GraphicsEngine _graphicsEngine; @@ -769,12 +755,8 @@ private: QUrl _avatarOverrideUrl; bool _saveAvatarOverrideUrl { false }; - // QObject* _renderEventHandler{ nullptr }; - - // friend class RenderEventHandler; std::atomic _pendingIdleEvent { true }; - // std::atomic _pendingRenderEvent { true }; bool quitWhenFinished { false }; diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index 55be37ba60..aecaa74d12 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -127,12 +127,7 @@ static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SI bool GraphicsEngine::shouldPaint() const { -// if (_aboutToQuit || _window->isMinimized()) { -// return false; - // } - - - auto displayPlugin = qApp->getActiveDisplayPlugin(); + auto displayPlugin = qApp->getActiveDisplayPlugin(); #ifdef DEBUG_PAINT_DELAY static uint64_t paintDelaySamples{ 0 }; @@ -148,15 +143,14 @@ bool GraphicsEngine::shouldPaint() const { } #endif - // Throttle if requested - //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { - if ( displayPlugin->isThrottled() && - (static_cast(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { - return false; - } + // Throttle if requested + //if (displayPlugin->isThrottled() && (_graphicsEngine._renderEventHandler->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { + if ( displayPlugin->isThrottled() && + (static_cast(_renderEventHandler)->_lastTimeRendered.elapsed() < THROTTLED_SIM_FRAME_PERIOD_MS)) { + return false; + } - return true; - // } + return true; } bool GraphicsEngine::checkPendingRenderEvent() { @@ -170,17 +164,11 @@ void GraphicsEngine::render_performFrame() { // Some plugins process message events, allowing paintGL to be called reentrantly. _renderFrameCount++; - // SG: Moved into the RenderEventHandler - //_lastTimeRendered.start(); auto lastPaintBegin = usecTimestampNow(); PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount); PerformanceTimer perfTimer("paintGL"); - /* if (nullptr == _displayPlugin) { - return; - }*/ - DisplayPluginPointer displayPlugin; { PROFILE_RANGE(render, "/getActiveDisplayPlugin"); @@ -310,5 +298,4 @@ void GraphicsEngine::render_performFrame() { void GraphicsEngine::editRenderArgs(RenderArgsEditor editor) { QMutexLocker renderLocker(&_renderArgsMutex); editor(_appRenderArgs); - -} \ No newline at end of file +} diff --git a/interface/src/graphics/GraphicsEngine.h b/interface/src/graphics/GraphicsEngine.h index 6efddce51a..490f5312b5 100644 --- a/interface/src/graphics/GraphicsEngine.h +++ b/interface/src/graphics/GraphicsEngine.h @@ -16,8 +16,6 @@ #include -#include "RenderThread.h" - #include #include @@ -53,8 +51,6 @@ public: render::EnginePointer getRenderEngine() const { return _renderEngine; } gpu::ContextPointer getGPUContext() const { return _gpuContext; } - FrameQueuePointer getFrameQueue() const { return _frameQueue; } - // Same as the one in application bool shouldPaint() const; bool checkPendingRenderEvent(); @@ -83,8 +79,6 @@ protected: gpu::ContextPointer _gpuContext; // initialized during window creation - FrameQueuePointer _frameQueue{ new FrameQueue() }; - QObject* _renderEventHandler{ nullptr }; friend class RenderEventHandler; diff --git a/interface/src/graphics/RenderEventHandler.cpp b/interface/src/graphics/RenderEventHandler.cpp index 42af3bb9c0..bdb2cae060 100644 --- a/interface/src/graphics/RenderEventHandler.cpp +++ b/interface/src/graphics/RenderEventHandler.cpp @@ -19,13 +19,9 @@ RenderEventHandler::RenderEventHandler(CheckCall checkCall, RenderCall renderCal _checkCall(checkCall), _renderCall(renderCall) { - // Deleting the object with automatically shutdown the thread - // connect(qApp, &QCoreApplication::aboutToQuit, this, &QObject::deleteLater); - // Transfer to a new thread moveToNewNamedThread(this, "RenderThread", [this](QThread* renderThread) { hifi::qt::addBlockingForbiddenThread("Render", renderThread); - //_renderContext->moveToThreadWithContext(renderThread); _lastTimeRendered.start(); }, std::bind(&RenderEventHandler::initialize, this), QThread::HighestPriority); } diff --git a/interface/src/graphics/RenderThread.cpp b/interface/src/graphics/RenderThread.cpp deleted file mode 100644 index 63df2033e8..0000000000 --- a/interface/src/graphics/RenderThread.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "RenderThread.h" \ No newline at end of file diff --git a/interface/src/graphics/RenderThread.h b/interface/src/graphics/RenderThread.h deleted file mode 100644 index abddf746e6..0000000000 --- a/interface/src/graphics/RenderThread.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef PRODUCERCONSUMERPIPE_H -#define PRODUCERCONSUMERPIPE_H - -#include -#include -#include -#include -#include - -// Producer is blocked if the consumer doesn't consume enough -// Consumer reads same value if producer doesn't produce enough -template -class ProducerConsumerPipe { -public: - - ProducerConsumerPipe(); - ProducerConsumerPipe(const T& initValue); - - const T& read(); - void read(T& value, const T& resetValue); - void write(const T& value); - bool isWritePossible(); - -private: - - short _readIndex; - short _writeIndex; - std::array _values; - std::array _used; - - void initialize(); - void updateReadIndex(); -}; - -template -ProducerConsumerPipe::ProducerConsumerPipe() { - initialize(); -} - -template -ProducerConsumerPipe::ProducerConsumerPipe(const T& initValue) { - _values.fill(initValue); - initialize(); -} - -template -void ProducerConsumerPipe::initialize() { - _readIndex = 0; - _writeIndex = 2; - _used[_readIndex].test_and_set(std::memory_order_acquire); - _used[_writeIndex].test_and_set(std::memory_order_acquire); - _used[1].clear(); -} - -template -void ProducerConsumerPipe::updateReadIndex() { - int nextReadIndex = (_readIndex + 1) % _values.size(); - - if (!_used[nextReadIndex].test_and_set(std::memory_order_acquire)) { - int readIndex = _readIndex; - _used[readIndex].clear(std::memory_order_release); - _readIndex = nextReadIndex; - } -} - -template -const T& ProducerConsumerPipe::read() { - updateReadIndex(); - return _values[_readIndex]; -} - -template -void ProducerConsumerPipe::read(T& value, const T& resetValue) { - updateReadIndex(); - value = _values[_readIndex]; - _values[_readIndex] = resetValue; -} - -template -bool ProducerConsumerPipe::isWritePossible() { - int nextWriteIndex = (_writeIndex + 1) % _values.size(); - return (_used[nextWriteIndex].test_and_set(std::memory_order_acquire)); -} - -template -void ProducerConsumerPipe::write(const T& value) { - int nextWriteIndex = (_writeIndex + 1) % _values.size(); - int writeIndex = _writeIndex; - - _values[writeIndex] = value; - - while (_used[nextWriteIndex].test_and_set(std::memory_order_acquire)) { - // spin - std::this_thread::yield(); - } - _used[writeIndex].clear(std::memory_order_release); - _writeIndex = nextWriteIndex; -} - - -#include - -using FrameQueue = ProducerConsumerPipe; - -using FrameQueuePointer = std::shared_ptr; - - -#endif diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index aed54463ba..46cdbd5b3e 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -55,8 +55,6 @@ ApplicationOverlay::~ApplicationOverlay() { // Renders the overlays either to a texture or to the screen void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { PROFILE_RANGE(render, __FUNCTION__); -// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); - buildFramebufferObject(); if (!_overlayFramebuffer) { diff --git a/scripts/developer/utilities/render/GlobalLighting.js b/scripts/developer/utilities/render/GlobalLighting.js deleted file mode 100644 index 766b87314f..0000000000 --- a/scripts/developer/utilities/render/GlobalLighting.js +++ /dev/null @@ -1,155 +0,0 @@ -// -// Global lighting.js -// -// Sam Gateau, created on 6/7/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 -// -var createdOverlays = []; -var overlayFrames = {}; - -Script.scriptEnding.connect(function () { - for (var i = 0; i < createdOverlays.length; i++) { - Overlays.deleteOverlay(createdOverlays[i]); - } -}); - - -var DIM = {x: 0.1, y: 0.13, z: 0.1}; -var avatarHeadJoint = MyAvatar.getJointIndex("Head"); - -function createOrb(i) { - - var props = { - dimensions: DIM, - } - - props["url"] = "https://github.com/highfidelity/hifi_tests/blob/master/assets/models/material_matrix_models/fbx/blender/hifi_metallicV_albedoV_ao.fbx?raw=true" - props["position"] = getCamePos(i) - // props["localPosition"] = { x: 0.4 * i, y: 0, z: 0} - props["rotation"] = getCameOri() - - if (createdOverlays.length > 0) { - props["parentID"] = createdOverlays[0] - - } - - var oID = Overlays.addOverlay("model", props); - - /* { - position: getCamePos(), - // position: MyAvatar.getJointPosition(avatarHeadJoint), - // localPosition: {x: 0, y: 1, z: 0}, - // localRotation: {x: 0, y: 0, z: 0, w:1}, - url: "https://github.com/highfidelity/hifi_tests/blob/master/assets/models/material_matrix_models/fbx/blender/hifi_metallicV_albedoV_ao.fbx?raw=true", - dimensions: DIM, - // parentID: MyAvatar.SELF_ID, - // parentJointIndex: avatarHeadJoint, - })*/ - - overlayFrames[oID] = { position: getCamePos(), rotation: getCameOri() } - - // Overlays.editOverlay(oID, overlayFrames[oID]) - - props = Overlays.getProperties(oID, ["position", "rotation"]) - print("createOrb" + oID + JSON.stringify(props)) - - return oID; -} - - -function createSnap(i) { - - var props = { - // dimensions: DIM, - // url: "resource://spectatorCameraFrame", - emissive: true, - url: "https://hifi-public.s3.amazonaws.com/sam/2018-oct/code/PackagedApp/asset/CarrotHunt.png", - dimensions: DIM, - // parentID: MyAvatar.SELF_ID, - // parentJointIndex: avatarHeadJoint, - alpha: 1, - // localRotation: { w: 1, x: 0, y: 0, z: 0 }, - // localPosition: { x: 0, y: 0.0, z: -1.0 }, - dimensions: DIM - } - - // props["url"] = "https://github.com/highfidelity/hifi_tests/blob/master/assets/models/material_matrix_models/fbx/blender/hifi_metallicV_albedoV_ao.fbx?raw=true" - props["position"] = getCamePos(i) - // props["localPosition"] = { x: 0.4 * i, y: 0, z: 0} - props["rotation"] = getCameOri() - - if (createdOverlays.length > 0) { - props["parentID"] = createdOverlays[0] - - } - - var oID = Overlays.addOverlay("image3d", props); - - /* { - position: getCamePos(), - // position: MyAvatar.getJointPosition(avatarHeadJoint), - // localPosition: {x: 0, y: 1, z: 0}, - // localRotation: {x: 0, y: 0, z: 0, w:1}, - url: "https://github.com/highfidelity/hifi_tests/blob/master/assets/models/material_matrix_models/fbx/blender/hifi_metallicV_albedoV_ao.fbx?raw=true", - dimensions: DIM, - // parentID: MyAvatar.SELF_ID, - // parentJointIndex: avatarHeadJoint, - })*/ - - overlayFrames[oID] = { position: getCamePos(), rotation: getCameOri() } - - // Overlays.editOverlay(oID, overlayFrames[oID]) - - props = Overlays.getProperties(oID, ["position", "rotation"]) - print("createOrb" + oID + JSON.stringify(props)) - - return oID; -} - -function createOrbs() { - print("createOrbs") - - createdOverlays.push(createOrb(0)); - createdOverlays.push(createOrb(1)); - createdOverlays.push(createSnap(2)); - -} - -var camSpace = {} - -function updateCamSpace() { - camSpace["pos"] = Camera.Position; - camSpace["ori"] = Camera.orientation; - camSpace["X"] = Vec3.multiply(Quat.getRight(Camera.orientation), Camera.frustum.aspectRatio); - camSpace["Y"] = Quat.getUp(Camera.orientation); - camSpace["Z"] = Vec3.multiply(Quat.getForward(), -1); -} - -function getCamePos(i) { - - return Vec3.sum(Camera.position, Vec3.multiplyQbyV(Camera.orientation, { x: -0.5 + 0.2 * i, y: -0.3, z: -1 })) - // return Vec3.add(Camera.position, {x: i * 0.3, y:0, z:1} -} -function getCameOri() { - return Camera.orientation -} -function updateFrames() { - for (var i = 0; i < createdOverlays.length; i++) { - overlayFrames[createdOverlays[i]] = { position: getCamePos(i), rotation: getCameOri() } - } - Overlays.editOverlays(overlayFrames) - -} - - -createOrbs() - -var accumulated = 0; -Script.update.connect(function(deltaTime) { - accumulated += deltaTime; - if (accumulated > 1) - updateFrames() -}); \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.js b/scripts/developer/utilities/render/engineInspector.js deleted file mode 100644 index 74e4231ff1..0000000000 --- a/scripts/developer/utilities/render/engineInspector.js +++ /dev/null @@ -1,71 +0,0 @@ - /*function openEngineTaskView() { - // Set up the qml ui - var qml = Script.resolvePath('engineInspector.qml'); - var window = new OverlayWindow({ - title: 'Render Engine', - source: qml, - width: 500, - height: 100 - }); - window.setPosition(200, 50); - window.closed.connect(function() { Script.stop(); }); - } - openEngineTaskView();*/ - - (function() { - var TABLET_BUTTON_NAME = "Inspector"; - var QMLAPP_URL = Script.resolvePath("./engineInspector.qml"); - var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg"); - var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg"); - - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - var button = tablet.addButton({ - text: TABLET_BUTTON_NAME, - icon: ICON_URL, - activeIcon: ACTIVE_ICON_URL - }); - - Script.scriptEnding.connect(function () { - killWindow() - button.clicked.disconnect(onClicked); - tablet.removeButton(button); - }); - - button.clicked.connect(onClicked); - - var onScreen = false; - var window; - - function onClicked() { - if (onScreen) { - killWindow() - } else { - createWindow() - } - } - - function createWindow() { - var qml = Script.resolvePath(QMLAPP_URL); - window = new OverlayWindow({ - title: 'Render Engine Inspector', - source: qml, - width: 250, - height: 500 - }); - window.setPosition(200, 50); - window.closed.connect(killWindow); - onScreen = true - button.editProperties({isActive: true}); - } - - function killWindow() { - if (window !== undefined) { - window.closed.disconnect(killWindow); - window.close() - window = undefined - } - onScreen = false - button.editProperties({isActive: false}) - } - }()); - \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml deleted file mode 100644 index 31283a4756..0000000000 --- a/scripts/developer/utilities/render/engineInspector.qml +++ /dev/null @@ -1,30 +0,0 @@ -// -// EngineInspector.qml -// -// Created by Sam Gateau on 06/07/2018 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html -// -import QtQuick 2.7 -import QtQuick.Controls 1.4 -import QtQuick.Layouts 1.3 - -import stylesUit 1.0 -import controlsUit 1.0 as HifiControls - -import "../lib/jet/qml" as Jet - -Item { - HifiConstants { id: hifi;} - id: root; - anchors.fill: parent - - property var rootConfig: Render.getConfig("") - - Jet.TaskListView { - rootConfig: root.rootConfig - anchors.fill: root - } -} \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineProfiler.js b/scripts/developer/utilities/render/engineProfiler.js deleted file mode 100644 index 418cab8622..0000000000 --- a/scripts/developer/utilities/render/engineProfiler.js +++ /dev/null @@ -1,59 +0,0 @@ - - - (function() { - var TABLET_BUTTON_NAME = "Profiler"; - var QMLAPP_URL = Script.resolvePath("./engineProfiler.qml"); - var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg"); - var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg"); - - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - var button = tablet.addButton({ - text: TABLET_BUTTON_NAME, - icon: ICON_URL, - activeIcon: ACTIVE_ICON_URL - }); - - Script.scriptEnding.connect(function () { - killWindow() - button.clicked.disconnect(onClicked); - tablet.removeButton(button); - }); - - button.clicked.connect(onClicked); - - var onScreen = false; - var window; - - function onClicked() { - if (onScreen) { - killWindow() - } else { - createWindow() - } - } - - function createWindow() { - var qml = Script.resolvePath(QMLAPP_URL); - window = Desktop.createWindow(Script.resolvePath(QMLAPP_URL), { - title: 'Render Engine Profiler', - flags: Desktop.ALWAYS_ON_TOP, - presentationMode: Desktop.PresentationMode.NATIVE, - size: {x: 500, y: 100} - }); - window.setPosition(200, 50); - window.closed.connect(killWindow); - onScreen = true - button.editProperties({isActive: true}); - } - - function killWindow() { - if (window !== undefined) { - window.closed.disconnect(killWindow); - window.close() - window = undefined - } - onScreen = false - button.editProperties({isActive: false}) - } - }()); - \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineProfiler.qml b/scripts/developer/utilities/render/engineProfiler.qml deleted file mode 100644 index bfa049d089..0000000000 --- a/scripts/developer/utilities/render/engineProfiler.qml +++ /dev/null @@ -1,31 +0,0 @@ -// -// EngineProfiler.qml -// -// Created by Sam Gateau on 06/07/2018 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html -// -import QtQuick 2.7 -import QtQuick.Controls 1.4 -import QtQuick.Layouts 1.3 - -import "qrc:///qml/styles-uit" -import "qrc:///qml/controls-uit" as HifiControls - -import "../lib/jet/qml" as Jet - -Item { - HifiConstants { id: hifi;} - id: root; - anchors.fill: parent - - property var rootConfig: Render.getConfig("") - - - Jet.TaskTimeFrameView { - rootConfig: root.rootConfig - anchors.fill: root - } -} \ No newline at end of file From f3bbd412d147719dc97f763657ab6e35f595680d Mon Sep 17 00:00:00 2001 From: sam gateau Date: Tue, 20 Nov 2018 17:40:59 -0800 Subject: [PATCH 047/117] Cleaning too many changes --- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 6 +++--- .../display-plugins/OpenGLDisplayPlugin.cpp | 11 +---------- libraries/gpu/src/gpu/Buffer.cpp | 18 ------------------ libraries/gpu/src/gpu/Buffer.h | 4 ++-- 4 files changed, 6 insertions(+), 33 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 7e95727fcc..d8b8cbd54a 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -165,11 +165,11 @@ static const uint32_t MIN_THROTTLE_CHECK_FRAMES = 60; bool Basic2DWindowOpenGLDisplayPlugin::isThrottled() const { static auto lastCheck = presentCount(); // Don't access the menu API every single frame - // if ((presentCount() - lastCheck) > MIN_THROTTLE_CHECK_FRAMES) { + if ((presentCount() - lastCheck) > MIN_THROTTLE_CHECK_FRAMES) { static const QString ThrottleFPSIfNotFocus = "Throttle FPS If Not Focus"; // FIXME - this value duplicated in Menu.h _isThrottled = (!_container->isForeground() && _container->isOptionChecked(ThrottleFPSIfNotFocus)); - // lastCheck = presentCount(); - // } + lastCheck = presentCount(); + } return _isThrottled; } diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 362952ddd7..190d4d4104 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -172,16 +172,7 @@ public: // If there's no active plugin, just sleep if (currentPlugin == nullptr) { // Minimum sleep ends up being about 2 ms anyway - QThread::msleep(16); - continue; - } - - static uint _vsyncLoopIndex = 0; - _vsyncLoopIndex++; - - if (currentPlugin->isThrottled() && (_vsyncLoopIndex % 8)) { - // Minimum sleep ends up being about 2 ms anyway - QThread::msleep(16); + QThread::msleep(1); continue; } diff --git a/libraries/gpu/src/gpu/Buffer.cpp b/libraries/gpu/src/gpu/Buffer.cpp index b3716c3490..ebb768e597 100644 --- a/libraries/gpu/src/gpu/Buffer.cpp +++ b/libraries/gpu/src/gpu/Buffer.cpp @@ -163,24 +163,6 @@ Buffer::Size Buffer::getSize() const { const Element BufferView::DEFAULT_ELEMENT = Element( gpu::SCALAR, gpu::UINT8, gpu::RAW ); -BufferView::BufferView(const BufferView& view) : - _buffer(view._buffer), - _offset(view._offset), - _size(view._size), - _element(view._element), - _stride(view._stride) -{} - -BufferView& BufferView::operator=(const BufferView& view) { - _buffer = (view._buffer); - _offset = (view._offset); - _size = (view._size); - _element = (view._element); - _stride = (view._stride); - - return (*this); -} - BufferView::BufferView() : BufferView(DEFAULT_ELEMENT) {} diff --git a/libraries/gpu/src/gpu/Buffer.h b/libraries/gpu/src/gpu/Buffer.h index e486e2392a..01cc652fd1 100644 --- a/libraries/gpu/src/gpu/Buffer.h +++ b/libraries/gpu/src/gpu/Buffer.h @@ -183,8 +183,8 @@ public: Element _element { DEFAULT_ELEMENT }; uint16 _stride { 0 }; - BufferView(const BufferView& view); - BufferView& operator=(const BufferView& view); + BufferView(const BufferView& view) = default; + BufferView& operator=(const BufferView& view) = default; BufferView(); BufferView(const Element& element); From c99a8101f7a6468dd7bfe4f094321495a5419411 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 20 Nov 2018 16:48:26 -0500 Subject: [PATCH 048/117] trying to fix build errors --- .../src/display-plugins/OpenGLDisplayPlugin.cpp | 4 ++-- .../src/display-plugins/hmd/HmdDisplayPlugin.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 9991130efc..2d19a745e1 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -538,11 +538,11 @@ std::function OpenGL auto hudMirrorPipeline = _mirrorHUDPipeline; auto hudStereo = isStereo(); auto hudCompositeFramebufferSize = _compositeFramebuffer->getSize(); - glm::ivec4 hudEyeViewports[2]; + std::array hudEyeViewports; for_each_eye([&](Eye eye) { hudEyeViewports[eye] = eyeViewport(eye); }); - return [hudPipeline, hudMirrorPipeline, hudStereo, hudEyeViewports, hudCompositeFramebufferSize](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { + return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { if (hudPipeline && hudTexture) { batch.enableStereo(false); batch.setPipeline(mirror ? hudMirrorPipeline : hudPipeline); diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index c0b1a7b753..321bcc3fd2 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -428,7 +428,7 @@ std::function HmdDis auto hudUniformBuffer = uniformsBuffer; auto hudUniforms = uniforms; auto hudIndexCount = indexCount; - return [hudPipeline, hudFormat, hudVertices, hudIndices, hudUniformBuffer, hudUniforms, hudIndexCount](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { + return [=](gpu::Batch& batch, const gpu::TexturePointer& hudTexture, bool mirror) { if (hudPipeline && hudTexture) { batch.setPipeline(hudPipeline); From 6b1c7bf96e3a67420c0c7929bf9d65691f5d696a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 20 Nov 2018 23:15:09 -0800 Subject: [PATCH 049/117] restoring the engine render views and cleaning up the task / config section of the pr --- libraries/render-utils/src/BloomEffect.cpp | 1 - libraries/task/src/task/Config.cpp | 3 - libraries/task/src/task/Config.h | 2 +- libraries/task/src/task/Task.h | 2 +- scripts/developer/utilities/lib/jet/jet.js | 5 +- .../utilities/render/engineInspector.js | 71 +++++++++++++++++++ .../utilities/render/engineInspector.qml | 30 ++++++++ .../utilities/render/engineProfiler.js | 59 +++++++++++++++ .../utilities/render/engineProfiler.qml | 31 ++++++++ 9 files changed, 196 insertions(+), 8 deletions(-) create mode 100644 scripts/developer/utilities/render/engineInspector.js create mode 100644 scripts/developer/utilities/render/engineInspector.qml create mode 100644 scripts/developer/utilities/render/engineProfiler.js create mode 100644 scripts/developer/utilities/render/engineProfiler.qml diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index e5b32bb1d4..414a1c3f91 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -283,7 +283,6 @@ void BloomEffect::configure(const Config& config) { blurName.back() = '0' + i; auto blurConfig = config.getConfig(blurName); blurConfig->filterScale = 1.0f; - //blurConfig->setProperty("filterScale", 1.0f); } } diff --git a/libraries/task/src/task/Config.cpp b/libraries/task/src/task/Config.cpp index c0e9c41468..5e8e4b246d 100644 --- a/libraries/task/src/task/Config.cpp +++ b/libraries/task/src/task/Config.cpp @@ -41,7 +41,6 @@ void JobConfig::setPresetList(const QJsonObject& object) { void TaskConfig::connectChildConfig(QConfigPointer childConfig, const std::string& name) { childConfig->setParent(this); childConfig->setObjectName(name.c_str()); - // childConfig->propagateParentEnabled((_isParentEnabled ? _isEnabled : false)); // Connect loaded->refresh QObject::connect(childConfig.get(), SIGNAL(loaded()), this, SLOT(refresh())); @@ -69,8 +68,6 @@ void TaskConfig::transferChildrenConfigs(QConfigPointer source) { QObject::connect(child, SIGNAL(dirtyEnabled()), this, SLOT(refresh())); } } - - // propagateParentEnabledToSubs(); } void TaskConfig::refresh() { diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index ab3303110b..da9b95a274 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -125,7 +125,7 @@ public: // Running Time measurement // The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated - void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration(runtime).count(); /* emit newStats();*/ } + void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration(runtime).count(); emit newStats(); } double getCPURunTime() const { return _msCPURunTime; } // Describe the node graph data connections of the associated Job/Task diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 0f4c67478e..fb7012b16c 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -164,7 +164,7 @@ public: void run(const ContextPointer& jobContext) override { jobContext->jobConfig = std::static_pointer_cast(Concept::_config); - if (/*jobContext->jobConfig->alwaysEnabled || */jobContext->jobConfig->isEnabled()) { + if (jobContext->jobConfig->isEnabled()) { jobRun(_data, jobContext, _input.get(), _output.edit()); } jobContext->jobConfig.reset(); diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js index cb78e2cc3f..71fb3e1f70 100644 --- a/scripts/developer/utilities/lib/jet/jet.js +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -172,7 +172,7 @@ function job_tree_model_functor(jobTreeModel, maxLevel, newNodeFunctor) { // Traverse the jobTreenode data structure created above function job_traverseTreeNode(root, functor, depth) { - // if (root.subNode.length) { + if (root.subNode.length) { depth++; for (var i = 0; i Date: Wed, 21 Nov 2018 13:31:54 -0800 Subject: [PATCH 050/117] Warnings from build --- interface/src/Application.cpp | 2 -- interface/src/Application.h | 1 - .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 2 +- 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dae9e3dad2..61365f3625 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -324,8 +324,6 @@ static const int THROTTLED_SIM_FRAME_PERIOD_MS = MSECS_PER_SECOND / THROTTLED_SI static const int ENTITY_SERVER_ADDED_TIMEOUT = 5000; static const int ENTITY_SERVER_CONNECTION_TIMEOUT = 5000; -static const uint32_t INVALID_FRAME = UINT32_MAX; - static const float INITIAL_QUERY_RADIUS = 10.0f; // priority radius for entities before physics enabled static const QString DESKTOP_LOCATION = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); diff --git a/interface/src/Application.h b/interface/src/Application.h index 2f23fc72d7..ead7231ffc 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -275,7 +275,6 @@ public: int getMaxOctreePacketsPerSecond() const; render::ScenePointer getMain3DScene() override { return _graphicsEngine.getRenderScene(); } - const render::ScenePointer& getMain3DScene() const { return _graphicsEngine.getRenderScene(); } render::EnginePointer getRenderEngine() override { return _graphicsEngine.getRenderEngine(); } gpu::ContextPointer getGPUContext() const { return _graphicsEngine.getGPUContext(); } diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index d8b8cbd54a..9d39a1968c 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -148,7 +148,7 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { batch.draw(gpu::TRIANGLE_STRIP, 4); batch.setResourceTexture(0, _virtualPadStickTexture); - batch.setModelTransform(stickTransform); + batch.setModelTransform(stickTransform);, batch.draw(gpu::TRIANGLE_STRIP, 4); batch.setResourceTexture(0, _virtualPadJumpBtnTexture); From 48f32dc36b9c737970eedece356629b274ecaec8 Mon Sep 17 00:00:00 2001 From: sam gateau Date: Wed, 21 Nov 2018 13:35:36 -0800 Subject: [PATCH 051/117] Remove stuppid error --- .../src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 9d39a1968c..d8b8cbd54a 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -148,7 +148,7 @@ void Basic2DWindowOpenGLDisplayPlugin::compositeExtra() { batch.draw(gpu::TRIANGLE_STRIP, 4); batch.setResourceTexture(0, _virtualPadStickTexture); - batch.setModelTransform(stickTransform);, + batch.setModelTransform(stickTransform); batch.draw(gpu::TRIANGLE_STRIP, 4); batch.setResourceTexture(0, _virtualPadJumpBtnTexture); From 5e51ba051ab5dbdc13b063eff0735a4c2a63772f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 22 Nov 2018 11:12:22 +1300 Subject: [PATCH 052/117] Improve code responsibilities --- .../controllers/controllerDispatcher.js | 24 +++---- .../controllerModules/inEditMode.js | 32 +++++++++ .../controllerModules/inVREditMode.js | 65 ++++++++++++------- .../nearParentGrabOverlay.js | 43 +++++------- .../controllerModules/nearTabletHighlight.js | 43 +++++------- .../libraries/controllerDispatcherUtils.js | 4 -- .../system/libraries/entitySelectionTool.js | 20 +++--- 7 files changed, 127 insertions(+), 104 deletions(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index a393205b5b..a880eb8b10 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -12,7 +12,7 @@ LEFT_HAND, RIGHT_HAND, NEAR_GRAB_PICK_RADIUS, DEFAULT_SEARCH_SPHERE_DISTANCE, DISPATCHER_PROPERTIES, getGrabPointSphereOffset, HMD, MyAvatar, Messages, findHandChildEntities, Picks, PickType, Pointers, PointerManager, getGrabPointSphereOffset, HMD, MyAvatar, Messages, findHandChildEntities, Picks, PickType, Pointers, - PointerManager, print, Selection, DISPATCHER_HOVERING_LIST, DISPATCHER_HOVERING_STYLE, HIFI_EDIT_MANIPULATION_CHANNEL + PointerManager, print, Selection, DISPATCHER_HOVERING_LIST, DISPATCHER_HOVERING_STYLE */ controllerDispatcherPlugins = {}; @@ -524,16 +524,17 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); _this.setBlacklist(); } } - } else if (channel === HIFI_EDIT_MANIPULATION_CHANNEL) { - message = JSON.parse(data); - var tabletIDs = message.action === "startEdit" ? - [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID, HMD.homeButtonHighlightID] : []; - if (message.hand === Controller.Standard.LeftHand) { - _this.leftBlacklistTabletIDs = tabletIDs; - _this.setLeftBlacklist(); - } else if (message.hand === Controller.Standard.RightHand) { - _this.rightBlacklistTabletIDs = tabletIDs; - _this.setRightBlacklist(); + + if (action === "tablet") { + var tabletIDs = message.blacklist + ? [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID, HMD.homeButtonHighlightID] : []; + if (message.hand === LEFT_HAND) { + _this.leftBlacklistTabletIDs = tabletIDs; + _this.setLeftBlacklist(); + } else { + _this.rightBlacklistTabletIDs = tabletIDs; + _this.setRightBlacklist(); + } } } } catch (e) { @@ -575,7 +576,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); var controllerDispatcher = new ControllerDispatcher(); Messages.subscribe('Hifi-Hand-RayPick-Blacklist'); - Messages.subscribe(HIFI_EDIT_MANIPULATION_CHANNEL); Messages.messageReceived.connect(controllerDispatcher.handleMessage); Script.scriptEnding.connect(controllerDispatcher.cleanup); diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index 3a1b835146..5709b19efe 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -20,6 +20,7 @@ Script.include("/~/system/libraries/utils.js"); var MARGIN = 25; function InEditMode(hand) { this.hand = hand; + this.isEditing = false; this.triggerClicked = false; this.selectedTarget = null; this.reticleMinX = MARGIN; @@ -212,6 +213,37 @@ Script.include("/~/system/libraries/utils.js"); enableDispatcherModule("LeftHandInEditMode", leftHandInEditMode); enableDispatcherModule("RightHandInEditMode", rightHandInEditMode); + var INEDIT_STATUS_CHANNEL = "Hifi-InEdit-Status"; + var HAND_RAYPICK_BLACKLIST_CHANNEL = "Hifi-Hand-RayPick-Blacklist"; + this.handleMessage = function (channel, data, sender) { + if (channel === INEDIT_STATUS_CHANNEL && sender === MyAvatar.sessionUUID) { + var message; + + try { + message = JSON.parse(data); + } catch (e) { + return; + } + + switch (message.method) { + case "editing": + if (message.hand === LEFT_HAND) { + leftHandInEditMode.isEditing = message.editing; + } else { + rightHandInEditMode.isEditing = message.editing; + } + Messages.sendLocalMessage(HAND_RAYPICK_BLACKLIST_CHANNEL, JSON.stringify({ + action: "tablet", + hand: message.hand, + blacklist: message.editing + })); + break; + } + } + }; + Messages.subscribe(INEDIT_STATUS_CHANNEL); + Messages.messageReceived.connect(this.handleMessage); + function cleanup() { disableDispatcherModule("LeftHandInEditMode"); disableDispatcherModule("RightHandInEditMode"); diff --git a/scripts/system/controllers/controllerModules/inVREditMode.js b/scripts/system/controllers/controllerModules/inVREditMode.js index 0c04918ab1..104e37d76c 100644 --- a/scripts/system/controllers/controllerModules/inVREditMode.js +++ b/scripts/system/controllers/controllerModules/inVREditMode.js @@ -18,7 +18,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); function InVREditMode(hand) { this.hand = hand; - this.disableModules = false; + this.isAppActive = false; + this.isEditing = false; this.running = false; var NO_HAND_LASER = -1; // Invalid hand parameter so that standard laser is not displayed. this.parameters = makeDispatcherModuleParameters( @@ -66,7 +67,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); }; this.isReady = function (controllerData) { - if (this.disableModules) { + if (this.isAppActive) { return makeRunningValues(true, [], []); } return makeRunningValues(false, [], []); @@ -74,14 +75,13 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.run = function (controllerData) { // Default behavior if disabling is not enabled. - if (!this.disableModules) { + if (!this.isAppActive) { return this.exitModule(); } // Tablet stylus. - var tabletStylusInput = getEnabledModuleByName(this.hand === RIGHT_HAND ? - "RightTabletStylusInput" : - "LeftTabletStylusInput"); + var tabletStylusInput = getEnabledModuleByName(this.hand === RIGHT_HAND + ? "RightTabletStylusInput" : "LeftTabletStylusInput"); if (tabletStylusInput) { var tabletReady = tabletStylusInput.isReady(controllerData); if (tabletReady.active) { @@ -90,9 +90,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); } // Tablet surface. - var overlayLaser = getEnabledModuleByName(this.hand === RIGHT_HAND ? - "RightWebSurfaceLaserInput" : - "LeftWebSurfaceLaserInput"); + var overlayLaser = getEnabledModuleByName(this.hand === RIGHT_HAND + ? "RightWebSurfaceLaserInput" : "LeftWebSurfaceLaserInput"); if (overlayLaser) { var overlayLaserReady = overlayLaser.isReady(controllerData); var target = controllerData.rayPicks[this.hand].objectID; @@ -114,8 +113,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); // HUD overlay. if (!controllerData.triggerClicks[this.hand]) { var hudLaser = getEnabledModuleByName(this.hand === RIGHT_HAND - ? "RightHudOverlayPointer" - : "LeftHudOverlayPointer"); + ? "RightHudOverlayPointer" : "LeftHudOverlayPointer"); if (hudLaser) { var hudLaserReady = hudLaser.isReady(controllerData); if (hudLaserReady.active) { @@ -125,9 +123,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); } // Teleport. - var teleporter = getEnabledModuleByName(this.hand === RIGHT_HAND ? - "RightTeleporter" : - "LeftTeleporter"); + var teleporter = getEnabledModuleByName(this.hand === RIGHT_HAND + ? "RightTeleporter" : "LeftTeleporter"); if (teleporter) { var teleporterReady = teleporter.isReady(controllerData); if (teleporterReady.active) { @@ -145,19 +142,39 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); enableDispatcherModule("LeftHandInVREditMode", leftHandInVREditMode); enableDispatcherModule("RightHandInVREditMode", rightHandInVREditMode); - var INVREDIT_DISABLER_MESSAGE_CHANNEL = "Hifi-InVREdit-Disabler"; - this.handleMessage = function (channel, message, sender) { - if (sender === MyAvatar.sessionUUID && channel === INVREDIT_DISABLER_MESSAGE_CHANNEL) { - if (message === "both") { - leftHandInVREditMode.disableModules = true; - rightHandInVREditMode.disableModules = true; - } else if (message === "none") { - leftHandInVREditMode.disableModules = false; - rightHandInVREditMode.disableModules = false; + var INVREDIT_STATUS_CHANNEL = "Hifi-InVREdit-Status"; + var HAND_RAYPICK_BLACKLIST_CHANNEL = "Hifi-Hand-RayPick-Blacklist"; + this.handleMessage = function (channel, data, sender) { + if (channel === INVREDIT_STATUS_CHANNEL && sender === MyAvatar.sessionUUID) { + var message; + + try { + message = JSON.parse(data); + } catch (e) { + return; + } + + switch (message.method) { + case "active": + leftHandInVREditMode.isAppActive = message.active; + rightHandInVREditMode.isAppActive = message.active; + break; + case "editing": + if (message.hand === LEFT_HAND) { + leftHandInVREditMode.isEditing = message.editing; + } else { + rightHandInVREditMode.isEditing = message.editing; + } + Messages.sendLocalMessage(HAND_RAYPICK_BLACKLIST_CHANNEL, JSON.stringify({ + action: "tablet", + hand: message.hand, + blacklist: message.editing + })); + break; } } }; - Messages.subscribe(INVREDIT_DISABLER_MESSAGE_CHANNEL); + Messages.subscribe(INVREDIT_STATUS_CHANNEL); Messages.messageReceived.connect(this.handleMessage); this.cleanup = function () { diff --git a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js index cbee8cabf7..e59b2e35ad 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabOverlay.js @@ -9,7 +9,7 @@ /* global Script, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, getControllerJointIndex, enableDispatcherModule, disableDispatcherModule, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, makeDispatcherModuleParameters, Overlays, makeRunningValues, Vec3, resizeTablet, getTabletWidthFromSettings, - NEAR_GRAB_RADIUS, HMD, Uuid, HIFI_EDIT_MANIPULATION_CHANNEL + NEAR_GRAB_RADIUS, HMD, Uuid, getEnabledModuleByName */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -176,14 +176,23 @@ Script.include("/~/system/libraries/utils.js"); return null; }; - this.isEditing = false; - this.setIsEditing = function (editing) { - this.isEditing = editing; + this.isEditing = function () { + var inEditModeModule = getEnabledModuleByName(this.hand === RIGHT_HAND + ? "RightHandInEditMode" : "LeftHandInEditMode"); + if (inEditModeModule && inEditModeModule.isEditing) { + return true; + } + var inVREditModeModule = getEnabledModuleByName(this.hand === RIGHT_HAND + ? "RightHandInVREditMode" : "LeftHandInVREditMode"); + if (inVREditModeModule && inVREditModeModule.isEditing) { + return true; + } + return false; }; this.isReady = function (controllerData) { if ((controllerData.triggerClicks[this.hand] === 0 && controllerData.secondaryValues[this.hand] === 0) - || this.isEditing) { + || this.isEditing()) { this.robbed = false; return makeRunningValues(false, [], []); } @@ -207,7 +216,7 @@ Script.include("/~/system/libraries/utils.js"); this.run = function (controllerData) { if ((controllerData.triggerClicks[this.hand] === 0 && controllerData.secondaryValues[this.hand] === 0) - || this.isEditing || !this.isGrabbedThingVisible()) { + || this.isEditing() || !this.isGrabbedThingVisible()) { this.endNearParentingGrabOverlay(); this.robbed = false; return makeRunningValues(false, [], []); @@ -235,28 +244,6 @@ Script.include("/~/system/libraries/utils.js"); enableDispatcherModule("LeftNearParentingGrabOverlay", leftNearParentingGrabOverlay); enableDispatcherModule("RightNearParentingGrabOverlay", rightNearParentingGrabOverlay); - function onMessageReceived(channel, data, senderID) { - var message; - - if (channel !== HIFI_EDIT_MANIPULATION_CHANNEL || senderID !== MyAvatar.sessionUUID) { - return; - } - - try { - message = JSON.parse(data); - } catch (e) { - return; - } - - if (message.hand === Controller.Standard.LeftHand) { - leftNearParentingGrabOverlay.setIsEditing(message.action === "startEdit"); - } else if (message.hand === Controller.Standard.RightHand) { - rightNearParentingGrabOverlay.setIsEditing(message.action === "startEdit"); - } - } - Messages.subscribe(HIFI_EDIT_MANIPULATION_CHANNEL); - Messages.messageReceived.connect(onMessageReceived); - function cleanup() { leftNearParentingGrabOverlay.cleanup(); rightNearParentingGrabOverlay.cleanup(); diff --git a/scripts/system/controllers/controllerModules/nearTabletHighlight.js b/scripts/system/controllers/controllerModules/nearTabletHighlight.js index 3ced0a9e87..2e046f5dc6 100644 --- a/scripts/system/controllers/controllerModules/nearTabletHighlight.js +++ b/scripts/system/controllers/controllerModules/nearTabletHighlight.js @@ -11,7 +11,7 @@ // /* global LEFT_HAND, RIGHT_HAND, makeDispatcherModuleParameters, makeRunningValues, enableDispatcherModule, - * disableDispatcherModule, HIFI_EDIT_MANIPULATION_CHANNEL */ + * disableDispatcherModule, getEnabledModuleByName */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -66,9 +66,18 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); 100 ); - this.isEditing = false; - this.setIsEditing = function (editing) { - this.isEditing = editing; + this.isEditing = function () { + var inEditModeModule = getEnabledModuleByName(this.hand === RIGHT_HAND + ? "RightHandInEditMode" : "LeftHandInEditMode"); + if (inEditModeModule && inEditModeModule.isEditing) { + return true; + } + var inVREditModeModule = getEnabledModuleByName(this.hand === RIGHT_HAND + ? "RightHandInVREditMode" : "LeftHandInVREditMode"); + if (inVREditModeModule && inVREditModeModule.isEditing) { + return true; + } + return false; }; this.isNearTablet = function (controllerData) { @@ -76,7 +85,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); }; this.isReady = function (controllerData) { - if (!this.isEditing && this.isNearTablet(controllerData)) { + if (!this.isEditing() && this.isNearTablet(controllerData)) { return makeRunningValues(true, [], []); } setTabletNearGrabbable(this.hand, false); @@ -84,7 +93,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); }; this.run = function (controllerData) { - if (this.isEditing || !this.isNearTablet(controllerData)) { + if (this.isEditing() || !this.isNearTablet(controllerData)) { setTabletNearGrabbable(this.hand, false); return makeRunningValues(false, [], []); } @@ -116,28 +125,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); HMD.mountedChanged.connect(onDisplayModeChanged); onDisplayModeChanged(); - function onMessageReceived(channel, data, senderID) { - var message; - - if (channel !== HIFI_EDIT_MANIPULATION_CHANNEL || senderID !== MyAvatar.sessionUUID) { - return; - } - - try { - message = JSON.parse(data); - } catch (e) { - return; - } - - if (message.hand === Controller.Standard.LeftHand) { - leftNearTabletHighlight.setIsEditing(message.action === "startEdit"); - } else if (message.hand === Controller.Standard.RightHand) { - rightNearTabletHighlight.setIsEditing(message.action === "startEdit"); - } - } - Messages.subscribe(HIFI_EDIT_MANIPULATION_CHANNEL); - Messages.messageReceived.connect(onMessageReceived); - function cleanUp() { disableDispatcherModule("LeftNearTabletHighlight"); disableDispatcherModule("RightNearTabletHighlight"); diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index f7b997a897..e9d5255d28 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -24,7 +24,6 @@ HAPTIC_PULSE_DURATION:true, DISPATCHER_HOVERING_LIST:true, DISPATCHER_HOVERING_STYLE:true, - HIFI_EDIT_MANIPULATION_CHANNEL:true, Entities, makeDispatcherModuleParameters:true, makeRunningValues:true, @@ -150,8 +149,6 @@ DISPATCHER_PROPERTIES = [ "userData" ]; -HIFI_EDIT_MANIPULATION_CHANNEL = "HiFi-Edit-Manipulation"; - // priority -- a lower priority means the module will be asked sooner than one with a higher priority in a given update step // activitySlots -- indicates which "slots" must not yet be in use for this module to start // requiredDataForReady -- which "situation" parts this module looks at to decide if it will start @@ -593,7 +590,6 @@ if (typeof module !== 'undefined') { TRIGGER_OFF_VALUE: TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE: TRIGGER_ON_VALUE, DISPATCHER_HOVERING_LIST: DISPATCHER_HOVERING_LIST, - HIFI_EDIT_MANIPULATION_CHANNEL: HIFI_EDIT_MANIPULATION_CHANNEL, worldPositionToRegistrationFrameMatrix: worldPositionToRegistrationFrameMatrix }; } diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 4552ed27fb..e1427b0a51 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -14,7 +14,7 @@ // /* global SelectionManager, SelectionDisplay, grid, rayPlaneIntersection, rayPlaneIntersection2, pushCommandForSelections, - getMainTabletIDs, getControllerWorldLocation, TRIGGER_ON_VALUE, HIFI_EDIT_MANIPULATION_CHANNEL */ + getMainTabletIDs, getControllerWorldLocation, TRIGGER_ON_VALUE */ const SPACE_LOCAL = "local"; const SPACE_WORLD = "world"; @@ -639,6 +639,8 @@ SelectionDisplay = (function() { ROLL: 2 }; + const INEDIT_STATUS_CHANNEL = "Hifi-InEdit-Status"; + /** * The current space mode, this could have been a forced space mode since we do not support multi selection while in * local space mode. @@ -1118,11 +1120,12 @@ SelectionDisplay = (function() { activeTool = hitTool; that.clearDebugPickPlane(); if (activeTool.onBegin) { - Messages.sendLocalMessage(HIFI_EDIT_MANIPULATION_CHANNEL, JSON.stringify({ - action: "startEdit", - hand: that.triggeredHand - })); that.editingHand = that.triggeredHand; + Messages.sendLocalMessage(INEDIT_STATUS_CHANNEL, JSON.stringify({ + method: "editing", + hand: that.editingHand === Controller.Standard.LeftHand ? LEFT_HAND : RIGHT_HAND, + editing: true + })); activeTool.onBegin(event, pickRay, results); } else { print("ERROR: entitySelectionTool.mousePressEvent - ActiveTool(" + activeTool.mode + ") missing onBegin"); @@ -1271,9 +1274,10 @@ SelectionDisplay = (function() { if (wantDebug) { print(" Triggering ActiveTool(" + activeTool.mode + ")'s onEnd"); } - Messages.sendLocalMessage(HIFI_EDIT_MANIPULATION_CHANNEL, JSON.stringify({ - action: "finishEdit", - hand: that.editingHand + Messages.sendLocalMessage(INEDIT_STATUS_CHANNEL, JSON.stringify({ + method: "editing", + hand: that.editingHand === Controller.Standard.LeftHand ? LEFT_HAND : RIGHT_HAND, + editing: false })); that.editingHand = NO_HAND; activeTool.onEnd(event); From 9ee35def3dc5aa5118d064919e3b8a1152e15e37 Mon Sep 17 00:00:00 2001 From: sam gateau Date: Wed, 21 Nov 2018 15:42:35 -0800 Subject: [PATCH 053/117] trying to fix the include issue --- interface/src/graphics/RenderEventHandler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/graphics/RenderEventHandler.h b/interface/src/graphics/RenderEventHandler.h index c566202b5b..93f8b548d0 100644 --- a/interface/src/graphics/RenderEventHandler.h +++ b/interface/src/graphics/RenderEventHandler.h @@ -10,9 +10,9 @@ #ifndef hifi_RenderEventHandler_h #define hifi_RenderEventHandler_h +#include +#include #include "gl/OffscreenGLCanvas.h" -#include -#include enum ApplicationEvent { // Execute a lambda function From 746c5ed621a0206fea789fc6d58242995ddf6b1c Mon Sep 17 00:00:00 2001 From: amantley Date: Wed, 21 Nov 2018 15:46:54 -0800 Subject: [PATCH 054/117] we can now handle missing joints and extra joints --- libraries/animation/src/AnimSkeleton.cpp | 3 ++- libraries/fbx/src/FBXReader.cpp | 22 +++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index e928658366..c5fb20d99b 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -27,6 +27,7 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { _fbxToHifiJointNameMapping = hfmModel.fbxToHifiJointNameMapping; buildSkeletonFromJoints(joints, hfmModel.jointRotationOffsets); + // we make a copy of the inverseBindMatrices in order to prevent mutating the model bind pose // when we are dealing with a joint offset in the model for (int i = 0; i < (int)hfmModel.meshes.size(); i++) { @@ -352,7 +353,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, } int mirrorJointIndex = -1; mirrorJointIndex = containsLeft(_joints[i].name); - if (mirrorJointIndex > -1) { + if (!(mirrorJointIndex > -1)) { mirrorJointIndex = containsRight(_joints[i].name); } if (mirrorJointIndex >= 0) { diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 3ddcd75255..abf84d96b1 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -480,14 +480,14 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& std::map lights; QVariantHash joints = mapping.value("joint").toHash(); - QString jointEyeLeftName = processID(getString(joints.value("jointEyeLeft", "jointEyeLeft"))); - QString jointEyeRightName = processID(getString(joints.value("jointEyeRight", "jointEyeRight"))); - QString jointNeckName = processID(getString(joints.value("jointNeck", "jointNeck"))); - QString jointRootName = processID(getString(joints.value("jointRoot", "jointRoot"))); + QString jointEyeLeftName = "EyeLeft"; //processID(getString(joints.value("jointEyeLeft", "jointEyeLeft"))); + QString jointEyeRightName = "EyeRight"; // processID(getString(joints.value("jointEyeRight", "jointEyeRight"))); + QString jointNeckName = "Neck"; //processID(getString(joints.value("jointNeck", "jointNeck"))); + QString jointRootName = "Hips"; //processID(getString(joints.value("jointRoot", "jointRoot"))); QString jointLeanName = processID(getString(joints.value("jointLean", "jointLean"))); QString jointHeadName = "Head";// processID(getString(joints.value("jointHead", "jointHead"))); - QString jointLeftHandName = processID(getString(joints.value("jointLeftHand", "jointLeftHand"))); - QString jointRightHandName = processID(getString(joints.value("jointRightHand", "jointRightHand"))); + QString jointLeftHandName = "LeftHand"; //processID(getString(joints.value("jointLeftHand", "jointLeftHand"))); + QString jointRightHandName = "RightHand"; // processID(getString(joints.value("jointRightHand", "jointRightHand"))); QString jointEyeLeftID; QString jointEyeRightID; QString jointNeckID; @@ -1845,7 +1845,15 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& jointIndex = hfmModel.getJointIndex(hfmModel.fbxToHifiJointNameMapping[jointName]); } if (jointIndex != -1) { - hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); + //if (jointIndex == 18) { + // glm::quat spine3LocalOffset(0.94232035f, 0.000000014995882f, 0.33471236f, 0.000000058068572f); + // glm::quat spine3AbsoluteOffset = spine3LocalOffset * hfmModel.jointRotationOffsets[16]; + // hfmModel.jointRotationOffsets.insert(jointIndex, spine3AbsoluteOffset); + // qCDebug(modelformat) << "Joint Rotation Offset added for spine3 : " << spine3AbsoluteOffset; + //} else { + hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); + //} + } qCDebug(modelformat) << "Joint Rotation Offset added to Rig._jointRotationOffsets : " << " jointName: " << jointName << " jointIndex: " << jointIndex << " rotation offset: " << rotationOffset; } From e282d51883aa891350de859f64553fdcfdc961bb Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 26 Nov 2018 01:15:07 -0500 Subject: [PATCH 055/117] CR --- interface/src/AvatarBookmarks.cpp | 2 +- .../scripting/WalletScriptingInterface.cpp | 2 +- .../ui/overlays/ContextOverlayInterface.cpp | 4 +- .../src/avatars-renderer/Avatar.cpp | 2 +- .../src/RenderableEntityItem.cpp | 10 +-- .../entities/src/EntityEditPacketSender.cpp | 4 +- libraries/entities/src/EntityItem.cpp | 10 +-- libraries/entities/src/EntityItem.h | 26 +++++--- .../entities/src/EntityItemProperties.cpp | 64 +++++++++---------- libraries/entities/src/EntityItemProperties.h | 4 +- .../entities/src/EntityPropertyFlags.cpp | 2 +- libraries/entities/src/EntityPropertyFlags.h | 2 +- .../entities/src/EntityScriptingInterface.cpp | 18 +++--- .../entities/src/EntityScriptingInterface.h | 10 +-- libraries/entities/src/EntityTree.cpp | 10 +-- .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 2 +- libraries/physics/src/EntityMotionState.cpp | 4 +- 18 files changed, 92 insertions(+), 86 deletions(-) diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index df7620013c..ae14fb5064 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -58,7 +58,7 @@ void addAvatarEntities(const QVariantList& avatarEntities) { EntityItemPropertiesFromScriptValueHonorReadOnly(scriptProperties, entityProperties); entityProperties.setParentID(myNodeID); - entityProperties.setEntityHost(EntityHost::AVATAR_ENTITY); + entityProperties.setEntityHostType(entity::HostType::AVATAR); entityProperties.setOwningAvatarID(myNodeID); entityProperties.setSimulationOwner(myNodeID, AVATAR_ENTITY_SIMULATION_PRIORITY); entityProperties.markAllChanged(); diff --git a/interface/src/scripting/WalletScriptingInterface.cpp b/interface/src/scripting/WalletScriptingInterface.cpp index 6ad81f0e2b..60f850adac 100644 --- a/interface/src/scripting/WalletScriptingInterface.cpp +++ b/interface/src/scripting/WalletScriptingInterface.cpp @@ -35,7 +35,7 @@ void WalletScriptingInterface::proveAvatarEntityOwnershipVerification(const QUui QSharedPointer contextOverlayInterface = DependencyManager::get(); EntityItemProperties entityProperties = DependencyManager::get()->getEntityProperties(entityID, contextOverlayInterface->getEntityPropertyFlags()); - if (entityProperties.getEntityHost() == EntityHost::AVATAR_ENTITY) { + if (entityProperties.getEntityHostType() == entity::HostType::AVATAR) { if (!entityID.isNull() && entityProperties.getCertificateID().length() > 0) { contextOverlayInterface->requestOwnershipVerification(entityID); } else { diff --git a/interface/src/ui/overlays/ContextOverlayInterface.cpp b/interface/src/ui/overlays/ContextOverlayInterface.cpp index f6c213163d..d077a2fe51 100644 --- a/interface/src/ui/overlays/ContextOverlayInterface.cpp +++ b/interface/src/ui/overlays/ContextOverlayInterface.cpp @@ -46,7 +46,7 @@ ContextOverlayInterface::ContextOverlayInterface() { _entityPropertyFlags += PROP_DIMENSIONS; _entityPropertyFlags += PROP_REGISTRATION_POINT; _entityPropertyFlags += PROP_CERTIFICATE_ID; - _entityPropertyFlags += PROP_ENTITY_HOST; + _entityPropertyFlags += PROP_ENTITY_HOST_TYPE; _entityPropertyFlags += PROP_OWNING_AVATAR_ID; auto entityScriptingInterface = DependencyManager::get().data(); @@ -296,7 +296,7 @@ void ContextOverlayInterface::requestOwnershipVerification(const QUuid& entityID auto nodeList = DependencyManager::get(); if (entityProperties.verifyStaticCertificateProperties()) { - if (entityProperties.getEntityHost() == EntityHost::AVATAR_ENTITY) { + if (entityProperties.getEntityHostType() == entity::HostType::AVATAR) { SharedNodePointer entityServer = nodeList->soloNodeOfType(NodeType::EntityServer); if (entityServer) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index fcac61a0bd..6398426690 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -389,7 +389,7 @@ void Avatar::updateAvatarEntities() { QScriptValue scriptProperties = variantMapToScriptValue(asMap, scriptEngine); EntityItemProperties properties; EntityItemPropertiesFromScriptValueHonorReadOnly(scriptProperties, properties); - properties.setEntityHost(EntityHost::AVATAR_ENTITY); + properties.setEntityHostType(entity::HostType::AVATAR); properties.setOwningAvatarID(getID()); // there's no entity-server to tell us we're the simulation owner, so always set the diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 9b9d0bb7a9..75d06191ea 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -39,7 +39,7 @@ enum class RenderItemStatusIcon { SIMULATION_OWNER = 3, HAS_ACTIONS = 4, OTHER_SIMULATION_OWNER = 5, - ENTITY_HOST = 6, + ENTITY_HOST_TYPE = 6, NONE = 255 }; @@ -118,17 +118,17 @@ void EntityRenderer::makeStatusGetters(const EntityItemPointer& entity, Item::St if (entity->isAvatarEntity()) { if (entity->getOwningAvatarID() == myNodeID) { return render::Item::Status::Value(1.0f, render::Item::Status::Value::GREEN, - (unsigned char)RenderItemStatusIcon::ENTITY_HOST); + (unsigned char)RenderItemStatusIcon::ENTITY_HOST_TYPE); } else { return render::Item::Status::Value(1.0f, render::Item::Status::Value::RED, - (unsigned char)RenderItemStatusIcon::ENTITY_HOST); + (unsigned char)RenderItemStatusIcon::ENTITY_HOST_TYPE); } } else if (entity->isLocalEntity()) { return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE, - (unsigned char)RenderItemStatusIcon::ENTITY_HOST); + (unsigned char)RenderItemStatusIcon::ENTITY_HOST_TYPE); } return render::Item::Status::Value(0.0f, render::Item::Status::Value::GREEN, - (unsigned char)RenderItemStatusIcon::ENTITY_HOST); + (unsigned char)RenderItemStatusIcon::ENTITY_HOST_TYPE); }); } diff --git a/libraries/entities/src/EntityEditPacketSender.cpp b/libraries/entities/src/EntityEditPacketSender.cpp index 0169bb6d9c..c414a7a4ac 100644 --- a/libraries/entities/src/EntityEditPacketSender.cpp +++ b/libraries/entities/src/EntityEditPacketSender.cpp @@ -84,7 +84,7 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, EntityTreePointer entityTree, EntityItemID entityItemID, const EntityItemProperties& properties) { - if (properties.getEntityHost() == EntityHost::AVATAR_ENTITY) { + if (properties.getEntityHostType() == entity::HostType::AVATAR) { if (!_myAvatar) { qCWarning(entities) << "Suppressing entity edit message: cannot send avatar entity edit with no myAvatar"; } else if (properties.getOwningAvatarID() == _myAvatar->getID()) { @@ -94,7 +94,7 @@ void EntityEditPacketSender::queueEditEntityMessage(PacketType type, qCWarning(entities) << "Suppressing entity edit message: cannot send avatar entity edit for another avatar"; } return; - } else if (properties.getEntityHost() == EntityHost::LOCAL_ENTITY) { + } else if (properties.getEntityHostType() == entity::HostType::LOCAL) { // Don't send edits for local entities return; } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 8ffde04b23..5855306994 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -119,7 +119,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_PARENT_JOINT_INDEX; requestedProperties += PROP_QUERY_AA_CUBE; - requestedProperties += PROP_ENTITY_HOST; + requestedProperties += PROP_ENTITY_HOST_TYPE; requestedProperties += PROP_OWNING_AVATAR_ID; requestedProperties += PROP_LAST_EDITED_BY; @@ -172,7 +172,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet EntityPropertyFlags propertyFlags(PROP_LAST_ITEM); EntityPropertyFlags requestedProperties = getEntityProperties(params); - requestedProperties -= PROP_ENTITY_HOST; + requestedProperties -= PROP_ENTITY_HOST_TYPE; requestedProperties -= PROP_OWNING_AVATAR_ID; // If we are being called for a subsequent pass at appendEntityData() that failed to completely encode this item, @@ -1334,7 +1334,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire COPY_ENTITY_PROPERTY_TO_PROPERTIES(localPosition, getLocalPosition); COPY_ENTITY_PROPERTY_TO_PROPERTIES(localRotation, getLocalOrientation); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(entityHost, getEntityHost); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(entityHostType, getEntityHostType); COPY_ENTITY_PROPERTY_TO_PROPERTIES(owningAvatarID, getOwningAvatarID); COPY_ENTITY_PROPERTY_TO_PROPERTIES(lastEditedBy, getLastEditedBy); @@ -1476,7 +1476,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex); SET_ENTITY_PROPERTY_FROM_PROPERTIES(queryAACube, setQueryAACube); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(entityHost, setEntityHost); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(entityHostType, setEntityHostType); SET_ENTITY_PROPERTY_FROM_PROPERTIES(owningAvatarID, setOwningAvatarID); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lastEditedBy, setLastEditedBy); @@ -3274,7 +3274,7 @@ void EntityItem::prepareForSimulationOwnershipBid(EntityItemProperties& properti properties.setSimulationOwner(Physics::getSessionUUID(), priority); setPendingOwnershipPriority(priority); - properties.setEntityHost(getEntityHost()); + properties.setEntityHostType(getEntityHostType()); properties.setOwningAvatarID(getOwningAvatarID()); setLastBroadcast(now); // for debug/physics status icons } \ No newline at end of file diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index e119595eb6..8c78dd1cd6 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -64,11 +64,17 @@ const uint64_t MAX_INCOMING_SIMULATION_UPDATE_PERIOD = MAX_OUTGOING_SIMULATION_U class MeshProxyList; -enum class EntityHost { - DOMAIN_ENTITY = 0, - AVATAR_ENTITY, - LOCAL_ENTITY +#ifdef DOMAIN +#undef DOMAIN +#endif + +namespace entity { +enum class HostType { + DOMAIN = 0, + AVATAR, + LOCAL }; +} /// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available /// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate @@ -484,11 +490,11 @@ public: void setScriptHasFinishedPreload(bool value); bool isScriptPreloadFinished(); - bool isDomainEntity() const { return _entityHost == EntityHost::DOMAIN_ENTITY; } - bool isAvatarEntity() const { return _entityHost == EntityHost::AVATAR_ENTITY; } - bool isLocalEntity() const { return _entityHost == EntityHost::LOCAL_ENTITY; } - EntityHost getEntityHost() const { return _entityHost; } - virtual void setEntityHost(EntityHost entityHost) { _entityHost = entityHost; } + bool isDomainEntity() const { return _hostType == entity::HostType::DOMAIN; } + bool isAvatarEntity() const { return _hostType == entity::HostType::AVATAR; } + bool isLocalEntity() const { return _hostType == entity::HostType::LOCAL; } + entity::HostType getEntityHostType() const { return _hostType; } + virtual void setEntityHostType(entity::HostType hostType) { _hostType = hostType; } // if this entity is an avatar entity, which avatar is it associated with? QUuid getOwningAvatarID() const { return _owningAvatarID; } @@ -683,7 +689,7 @@ protected: QUuid _sourceUUID; /// the server node UUID we came from - EntityHost _entityHost { EntityHost::DOMAIN_ENTITY }; + entity::HostType _hostType { entity::HostType::DOMAIN }; bool _transitingWithAvatar{ false }; QUuid _owningAvatarID; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index bcd53a2420..a477ee50b1 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -306,26 +306,26 @@ void EntityItemProperties::setMaterialMappingModeFromString(const QString& mater } } -QString EntityItemProperties::getEntityHostAsString() const { - switch (_entityHost) { - case EntityHost::DOMAIN_ENTITY: +QString EntityItemProperties::getEntityHostTypeAsString() const { + switch (_entityHostType) { + case entity::HostType::DOMAIN: return "domain"; - case EntityHost::AVATAR_ENTITY: + case entity::HostType::AVATAR: return "avatar"; - case EntityHost::LOCAL_ENTITY: + case entity::HostType::LOCAL: return "local"; default: return ""; } } -void EntityItemProperties::setEntityHostFromString(const QString& entityHost) { - if (entityHost == "domain") { - _entityHost = EntityHost::DOMAIN_ENTITY; - } else if (entityHost == "avatar") { - _entityHost = EntityHost::AVATAR_ENTITY; - } else if (entityHost == "local") { - _entityHost = EntityHost::LOCAL_ENTITY; +void EntityItemProperties::setEntityHostTypeFromString(const QString& entityHostType) { + if (entityHostType == "domain") { + _entityHostType = entity::HostType::DOMAIN; + } else if (entityHostType == "avatar") { + _entityHostType = entity::HostType::AVATAR; + } else if (entityHostType == "local") { + _entityHostType = entity::HostType::LOCAL; } } @@ -476,7 +476,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_GHOSTING_ALLOWED, ghostingAllowed); CHECK_PROPERTY_CHANGE(PROP_FILTER_URL, filterURL); - CHECK_PROPERTY_CHANGE(PROP_ENTITY_HOST, entityHost); + CHECK_PROPERTY_CHANGE(PROP_ENTITY_HOST_TYPE, entityHostType); CHECK_PROPERTY_CHANGE(PROP_OWNING_AVATAR_ID, owningAvatarID); CHECK_PROPERTY_CHANGE(PROP_SHAPE, shape); @@ -512,16 +512,16 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Entities.EntityType} type - The entity type. You cannot change the type of an entity after it's created. (Though * its value may switch among "Box", "Shape", and "Sphere" depending on changes to * the shape property set for entities of these types.) Read-only. - * @property {EntityHost} entityHost="domain" - How this entity will behave, including if and how it is sent to other people. - * The value can only be set at entity creation by using the entityHost parameter in + * @property {EntityHostType} entityHostType="domain" - How this entity will behave, including if and how it is sent to other people. + * The value can only be set at entity creation by using the entityHostType parameter in * {@link Entities.addEntity}. * @property {boolean} avatarEntity=false - If true then the entity is an avatar entity; An avatar entity follows you to each domain you visit, * rendering at the same world coordinates unless it's parented to your avatar. Value cannot be changed after the entity is created.
- * The value can only be set at entity creation by using the entityHost parameter in + * The value can only be set at entity creation by using the entityHostType parameter in * {@link Entities.addEntity}. clientOnly is an alias. * @property {boolean} localEntity=false - If true then the entity is a local entity; Local entities only render for you and are not sent over the wire. * Value cannot be changed after the entity is created.
- * The value can only be set at entity creation by using the entityHost parameter in + * The value can only be set at entity creation by using the entityHostType parameter in * {@link Entities.addEntity}. * @property {Uuid} owningAvatarID=Uuid.NULL - The session ID of the owning avatar if avatarEntity is * true, otherwise {@link Uuid|Uuid.NULL}. Read-only. @@ -768,7 +768,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * overlay's ID. * To apply a material to an avatar, set the material entity's parentID property to the avatar's session UUID. * To apply a material to your avatar such that it persists across domains and log-ins, create the material as an avatar entity - * by setting the entityHost parameter in {@link Entities.addEntity} to "avatar". + * by setting the entityHostType parameter in {@link Entities.addEntity} to "avatar". * Material entities render as non-scalable spheres if they don't have their parent set. * @typedef {object} Entities.EntityProperties-Material * @property {string} materialURL="" - URL to a {@link MaterialResource}. If you append ?name to the URL, the @@ -1556,8 +1556,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ANGULAR_VELOCITY, localAngularVelocity); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_DIMENSIONS, localDimensions); - COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ENTITY_HOST, entityHost, getEntityHostAsString()); // Gettable but not settable except at entity creation - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_OWNING_AVATAR_ID, owningAvatarID); // Gettable but not settable + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_ENTITY_HOST_TYPE, entityHostType, getEntityHostTypeAsString()); // Gettable but not settable except at entity creation + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_OWNING_AVATAR_ID, owningAvatarID); // Gettable but not settable COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONEABLE, cloneable); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLONE_LIFETIME, cloneLifetime); @@ -1597,13 +1597,13 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool } if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::ClientOnly)) { - properties.setProperty("clientOnly", convertScriptValue(engine, getEntityHost() == EntityHost::AVATAR_ENTITY)); + properties.setProperty("clientOnly", convertScriptValue(engine, getEntityHostType() == entity::HostType::AVATAR)); } if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::AvatarEntity)) { - properties.setProperty("avatarEntity", convertScriptValue(engine, getEntityHost() == EntityHost::AVATAR_ENTITY)); + properties.setProperty("avatarEntity", convertScriptValue(engine, getEntityHostType() == entity::HostType::AVATAR)); } if (!psuedoPropertyFlagsActive || psueudoPropertyFlags.test(EntityPsuedoPropertyFlag::LocalEntity)) { - properties.setProperty("localEntity", convertScriptValue(engine, getEntityHost() == EntityHost::LOCAL_ENTITY)); + properties.setProperty("localEntity", convertScriptValue(engine, getEntityHostType() == entity::HostType::LOCAL)); } // FIXME - I don't think these properties are supported any more @@ -1792,7 +1792,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(ghostingAllowed, bool, setGhostingAllowed); COPY_PROPERTY_FROM_QSCRIPTVALUE(filterURL, QString, setFilterURL); - COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(entityHost, EntityHost); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(entityHostType, EntityHostType); COPY_PROPERTY_FROM_QSCRIPTVALUE(owningAvatarID, QUuid, setOwningAvatarID); COPY_PROPERTY_FROM_QSCRIPTVALUE(dpi, uint16_t, setDPI); @@ -1958,7 +1958,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(ghostingAllowed); COPY_PROPERTY_IF_CHANGED(filterURL); - COPY_PROPERTY_IF_CHANGED(entityHost); + COPY_PROPERTY_IF_CHANGED(entityHostType); COPY_PROPERTY_IF_CHANGED(owningAvatarID); COPY_PROPERTY_IF_CHANGED(dpi); @@ -3244,7 +3244,7 @@ void EntityItemProperties::markAllChanged() { _ghostingAllowedChanged = true; _filterURLChanged = true; - _entityHostChanged = true; + _entityHostTypeChanged = true; _owningAvatarIDChanged = true; _dpiChanged = true; @@ -3743,8 +3743,8 @@ QList EntityItemProperties::listChangedProperties() { out += "queryAACube"; } - if (entityHostChanged()) { - out += "entityHost"; + if (entityHostTypeChanged()) { + out += "entityHostType"; } if (owningAvatarIDChanged()) { out += "owningAvatarID"; @@ -3819,7 +3819,7 @@ bool EntityItemProperties::getScalesWithParent() const { if (success && parent) { bool avatarAncestor = (parent->getNestableType() == NestableType::Avatar || parent->hasAncestorOfType(NestableType::Avatar)); - scalesWithParent = getEntityHost() == EntityHost::AVATAR_ENTITY && avatarAncestor; + scalesWithParent = getEntityHostType() == entity::HostType::AVATAR && avatarAncestor; } } return scalesWithParent; @@ -3977,11 +3977,11 @@ void EntityItemProperties::convertToCloneProperties(const EntityItemID& entityID setParentJointIndex(-1); setLifetime(getCloneLifetime()); setDynamic(getCloneDynamic()); - if (getEntityHost() != EntityHost::LOCAL_ENTITY) { - setEntityHost(getCloneAvatarEntity() ? EntityHost::AVATAR_ENTITY : EntityHost::DOMAIN_ENTITY); + if (getEntityHostType() != entity::HostType::LOCAL) { + setEntityHostType(getCloneAvatarEntity() ? entity::HostType::AVATAR : entity::HostType::DOMAIN); } else { // Local Entities clone as local entities - setEntityHost(EntityHost::LOCAL_ENTITY); + setEntityHostType(entity::HostType::LOCAL); setCollisionless(true); } setCreated(usecTimestampNow()); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 9e666bca1b..a82e194fef 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -279,7 +279,7 @@ public: DEFINE_PROPERTY(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool, ZoneEntityItem::DEFAULT_GHOSTING_ALLOWED); DEFINE_PROPERTY(PROP_FILTER_URL, FilterURL, filterURL, QString, ZoneEntityItem::DEFAULT_FILTER_URL); - DEFINE_PROPERTY_REF_ENUM(PROP_ENTITY_HOST, EntityHost, entityHost, EntityHost, EntityHost::DOMAIN_ENTITY); + DEFINE_PROPERTY_REF_ENUM(PROP_ENTITY_HOST_TYPE, EntityHostType, entityHostType, entity::HostType, entity::HostType::DOMAIN); DEFINE_PROPERTY_REF(PROP_OWNING_AVATAR_ID, OwningAvatarID, owningAvatarID, QUuid, UNKNOWN_ENTITY_ID); DEFINE_PROPERTY_REF(PROP_DPI, DPI, dpi, uint16_t, ENTITY_ITEM_DEFAULT_DPI); @@ -589,7 +589,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, GhostingAllowed, ghostingAllowed, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, FilterURL, filterURL, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, EntityHostAsString, entityHost, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, EntityHostTypeAsString, entityHostType, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, OwningAvatarID, owningAvatarID, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, LastEditedBy, lastEditedBy, ""); diff --git a/libraries/entities/src/EntityPropertyFlags.cpp b/libraries/entities/src/EntityPropertyFlags.cpp index ff95e40fde..4aff36eb71 100644 --- a/libraries/entities/src/EntityPropertyFlags.cpp +++ b/libraries/entities/src/EntityPropertyFlags.cpp @@ -121,7 +121,7 @@ QDebug& operator<<(QDebug& dbg, const EntityPropertyFlags& f) { result = f.getHasProperty(PROP_FALLOFF_RADIUS) ? result + "falloffRadius " : result; result = f.getHasProperty(PROP_FLYING_ALLOWED) ? result + "flyingAllowed " : result; result = f.getHasProperty(PROP_GHOSTING_ALLOWED) ? result + "ghostingAllowed " : result; - result = f.getHasProperty(PROP_ENTITY_HOST) ? result + "entityHost " : result; + result = f.getHasProperty(PROP_ENTITY_HOST_TYPE) ? result + "entityHostType " : result; result = f.getHasProperty(PROP_OWNING_AVATAR_ID) ? result + "owningAvatarID " : result; result = f.getHasProperty(PROP_SHAPE) ? result + "shape " : result; result = f.getHasProperty(PROP_DPI) ? result + "dpi " : result; diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 7f1d48acdf..e267a46810 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -176,7 +176,7 @@ enum EntityPropertyList { PROP_FLYING_ALLOWED, // can avatars in a zone fly? PROP_GHOSTING_ALLOWED, // can avatars in a zone turn off physics? - PROP_ENTITY_HOST, // doesn't go over wire + PROP_ENTITY_HOST_TYPE, // doesn't go over wire PROP_OWNING_AVATAR_ID, // doesn't go over wire PROP_SHAPE, diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index ffd7748c37..825c8350b7 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -470,7 +470,7 @@ void synchronizeEditedGrabProperties(EntityItemProperties& properties, const QSt } -QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties, const QString& entityHostString) { +QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties, const QString& entityHostTypeString) { PROFILE_RANGE(script_entities, __FUNCTION__); _activityTracking.addedEntityCount++; @@ -479,10 +479,10 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties const auto sessionID = nodeList->getSessionUUID(); EntityItemProperties propertiesWithSimID = properties; - propertiesWithSimID.setEntityHostFromString(entityHostString); - if (propertiesWithSimID.getEntityHost() == EntityHost::AVATAR_ENTITY) { + propertiesWithSimID.setEntityHostTypeFromString(entityHostTypeString); + if (propertiesWithSimID.getEntityHostType() == entity::HostType::AVATAR) { propertiesWithSimID.setOwningAvatarID(sessionID); - } else if (propertiesWithSimID.getEntityHost() == EntityHost::LOCAL_ENTITY) { + } else if (propertiesWithSimID.getEntityHostType() == entity::HostType::LOCAL) { // For now, local entities are always collisionless // TODO: create a separate, local physics simulation that just handles local entities (and MyAvatar?) propertiesWithSimID.setCollisionless(true); @@ -572,7 +572,7 @@ QUuid EntityScriptingInterface::cloneEntity(QUuid entityIDToClone) { bool cloneAvatarEntity = properties.getCloneAvatarEntity(); properties.convertToCloneProperties(entityIDToClone); - if (properties.getEntityHost() == EntityHost::LOCAL_ENTITY) { + if (properties.getEntityHostType() == entity::HostType::LOCAL) { // Local entities are only cloned locally return addEntity(properties, "local"); } else if (cloneAvatarEntity) { @@ -838,9 +838,9 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& } // set these to make EntityItemProperties::getScalesWithParent() work correctly - EntityHost entityHost = entity->getEntityHost(); - properties.setEntityHost(entityHost); - if (entityHost == EntityHost::LOCAL_ENTITY) { + entity::HostType entityHostType = entity->getEntityHostType(); + properties.setEntityHostType(entityHostType); + if (entityHostType == entity::HostType::LOCAL) { properties.setCollisionless(true); } properties.setOwningAvatarID(entity->getOwningAvatarID()); @@ -1660,7 +1660,7 @@ bool EntityScriptingInterface::actionWorker(const QUuid& entityID, doTransmit = actor(simulation, entity); _entityTree->entityChanged(entity); if (doTransmit) { - properties.setEntityHost(entity->getEntityHost()); + properties.setEntityHostType(entity->getEntityHostType()); properties.setOwningAvatarID(entity->getOwningAvatarID()); } }); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 78d71ac76b..ff1149fb06 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -245,14 +245,14 @@ public slots: * localLocal entities are not sent over the wire and will only render for you, locally * * - * @typedef {string} EntityHost + * @typedef {string} EntityHostType */ /**jsdoc * Add a new entity with specified properties. * @function Entities.addEntity * @param {Entities.EntityProperties} properties - The properties of the entity to create. - * @param {EntityHost} [entityHost="domain"] - If "avatar" the entity is created as an avatar entity. An avatar entity + * @param {EntityHostType} [entityHostType="domain"] - If "avatar" the entity is created as an avatar entity. An avatar entity * follows you to each domain you visit, rendering at the same world coordinates unless it's parented to your avatar. * If "local", the entity is created as a local entity, which will only render for you and isn't sent over the wire. * Otherwise it is created as a normal entity and sent over the entity server. @@ -266,7 +266,7 @@ public slots: * }); * print("Entity created: " + entityID); */ - Q_INVOKABLE QUuid addEntity(const EntityItemProperties& properties, const QString& entityHostString); + Q_INVOKABLE QUuid addEntity(const EntityItemProperties& properties, const QString& entityHostTypeString); /**jsdoc * Add a new entity with specified properties. @@ -276,8 +276,8 @@ public slots: * @returns {Uuid} The ID of the entity if successfully created, otherwise {@link Uuid|Uuid.NULL}. */ Q_INVOKABLE QUuid addEntity(const EntityItemProperties& properties, bool avatarEntity = false) { - QString entityHost = avatarEntity ? "avatar" : "domain"; - return addEntity(properties, entityHost); + QString entityHostType = avatarEntity ? "avatar" : "domain"; + return addEntity(properties, entityHostType); } /// temporary method until addEntity can be used from QJSEngine diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 1abdd15314..e1330ead12 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -541,7 +541,7 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti return nullptr; } - if (properties.getEntityHost() == EntityHost::DOMAIN_ENTITY && getIsClient() && + if (properties.getEntityHostType() == entity::HostType::DOMAIN && getIsClient() && !nodeList->getThisNodeCanRez() && !nodeList->getThisNodeCanRezTmp() && !nodeList->getThisNodeCanRezCertified() && !nodeList->getThisNodeCanRezTmpCertified() && !_serverlessDomain && !isClone) { return nullptr; @@ -2668,15 +2668,15 @@ bool EntityTree::readFromMap(QVariantMap& map) { entityItemID = EntityItemID(QUuid::createUuid()); } - // Convert old clientOnly bool to new entityHost enum + // Convert old clientOnly bool to new entityHostType enum // (must happen before setOwningAvatarID below) - if (contentVersion < (int)EntityVersion::EntityHosts) { + if (contentVersion < (int)EntityVersion::EntityHostTypes) { if (entityMap.contains("clientOnly")) { - properties.setEntityHost(entityMap["clientOnly"].toBool() ? EntityHost::AVATAR_ENTITY : EntityHost::DOMAIN_ENTITY); + properties.setEntityHostType(entityMap["clientOnly"].toBool() ? entity::HostType::AVATAR : entity::HostType::DOMAIN); } } - if (properties.getEntityHost() == EntityHost::AVATAR_ENTITY) { + if (properties.getEntityHostType() == entity::HostType::AVATAR) { auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); properties.setOwningAvatarID(myNodeID); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 62ff742793..1c58325280 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::EntityHosts); + return static_cast(EntityVersion::EntityHostTypes); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 284760ea38..83494249c1 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -246,7 +246,7 @@ enum class EntityVersion : PacketVersion { GrabProperties, ScriptGlmVectors, FixedLightSerialization, - EntityHosts + EntityHostTypes }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index aaae31abb1..4b635ef0be 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -595,7 +595,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ EntityTreeElementPointer element = _entity->getElement(); EntityTreePointer tree = element ? element->getTree() : nullptr; - properties.setEntityHost(_entity->getEntityHost()); + properties.setEntityHostType(_entity->getEntityHostType()); properties.setOwningAvatarID(_entity->getOwningAvatarID()); entityPacketSender->queueEditEntityMessage(PacketType::EntityPhysics, tree, id, properties); @@ -610,7 +610,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ EntityItemProperties newQueryCubeProperties; newQueryCubeProperties.setQueryAACube(descendant->getQueryAACube()); newQueryCubeProperties.setLastEdited(properties.getLastEdited()); - newQueryCubeProperties.setEntityHost(entityDescendant->getEntityHost()); + newQueryCubeProperties.setEntityHostType(entityDescendant->getEntityHostType()); newQueryCubeProperties.setOwningAvatarID(entityDescendant->getOwningAvatarID()); entityPacketSender->queueEditEntityMessage(PacketType::EntityPhysics, tree, From 26fc53ef7808c86db8b7aab6fa7970c241dad536 Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 26 Nov 2018 11:08:59 -0800 Subject: [PATCH 056/117] cleaned up whitespace and removed debug prints --- libraries/animation/src/AnimSkeleton.cpp | 40 +++++++++---------- libraries/animation/src/Rig.cpp | 1 - .../src/avatars-renderer/Avatar.cpp | 12 +----- .../src/avatars-renderer/SkeletonModel.cpp | 1 - libraries/fbx/src/FBXReader.cpp | 28 ++++--------- 5 files changed, 27 insertions(+), 55 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index c5fb20d99b..110dd5f92a 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -65,19 +65,14 @@ AnimSkeleton::AnimSkeleton(const std::vector& joints, const QMap AnimSkeleton::getChildrenOfJoint(int jointIndex) const { } const QString AnimSkeleton::getJointName(int jointIndex) const { - + QString jointName = _joints[jointIndex].name; QMapIterator i(_fbxToHifiJointNameMapping); while (i.hasNext()) { @@ -146,8 +141,7 @@ const QString AnimSkeleton::getJointName(int jointIndex) const { break; } } - //qCDebug(animation) << "reverse lookup: returning " << jointName << " for " << jointIndex; - return jointName; //;_joints[jointIndex].name; + return jointName; } AnimPose AnimSkeleton::getAbsolutePose(int jointIndex, const AnimPoseVec& relativePoses) const { @@ -222,7 +216,6 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const { bool AnimSkeleton::checkNonMirrored(QString jointName) const { - //bool isNonMirrored = false; QMapIterator i(_fbxToHifiJointNameMapping); while (i.hasNext()) { i.next(); @@ -264,14 +257,15 @@ int AnimSkeleton::containsLeft(QString jointName) const { if (i.key().startsWith("Left")) { QString mirrorJointName = QString(i.key()).replace(0, 4, "Right"); mirrorJointIndex = nameToJointIndex(mirrorJointName); - //return true } } } - if (jointName.startsWith("Left")) { - QString mirrorJointName = QString(jointName).replace(0, 4, "Right"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); - } + if (mirrorJointIndex < 0) { + if (jointName.startsWith("Left")) { + QString mirrorJointName = QString(jointName).replace(0, 4, "Right"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + } + } return mirrorJointIndex; } @@ -285,12 +279,14 @@ int AnimSkeleton::containsRight(QString jointName) const { if (i.key().startsWith("Right")) { QString mirrorJointName = QString(i.key()).replace(0, 5, "Left"); mirrorJointIndex = nameToJointIndex(mirrorJointName); - } + } } } - if (jointName.startsWith("Right")) { - QString mirrorJointName = QString(jointName).replace(0, 5, "Left"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); + if (mirrorJointIndex < 0) { + if (jointName.startsWith("Right")) { + QString mirrorJointName = QString(jointName).replace(0, 5, "Left"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + } } return mirrorJointIndex; } @@ -353,7 +349,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, } int mirrorJointIndex = -1; mirrorJointIndex = containsLeft(_joints[i].name); - if (!(mirrorJointIndex > -1)) { + if (mirrorJointIndex < 0) { mirrorJointIndex = containsRight(_joints[i].name); } if (mirrorJointIndex >= 0) { diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 1675ea8e90..5e2610e37e 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -423,7 +423,6 @@ int Rig::indexOfJoint(const QString& jointName) const { int result = _animSkeleton->nameToJointIndex(jointName); if (_animSkeleton->getFBXToHifiJointNameMapping().contains(jointName)) { - //qCDebug(animation) << "the alternate name for the joint " << jointName << " is " << _animSkeleton->getFBXToHifiJointNameMapping()[jointName] << " " << _animSkeleton->nameToJointIndex(_animSkeleton->getFBXToHifiJointNameMapping()[jointName]); result = _animSkeleton->nameToJointIndex(jointName); } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 14e97a5bf9..f3017049a7 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1437,21 +1437,11 @@ int Avatar::getJointIndex(const QString& name) const { withValidJointIndicesCache([&]() { if (_modelJointIndicesCache.contains(name)) { result = _modelJointIndicesCache[name] - 1; - if (_skeletonModel && _skeletonModel->isActive()) { - // qCDebug(avatars_renderer) << "the other head id is this" << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]; - // qCDebug(avatars_renderer) << "joint indices cache " << name << " " << _modelJointIndicesCache[name]; - if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"])) { - // qCDebug(avatars_renderer) << "joint alternate name " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"] << " " << _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping["Head"]]; - } - } } else { - // doesn't contain name. - //qCDebug(avatars_renderer) << "name is not here"; + // doesn't contain name. check the fbx-to-hifi joint name mapping if (_skeletonModel && _skeletonModel->isActive()) { - if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name])) { result = _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name]] - 1; - // qCDebug(avatars_renderer) << "joint " << name << " remapped to " << _skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name] << result; } } } diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index a97ba4bf4b..36e37dd3d4 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -317,7 +317,6 @@ bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& seco } glm::vec3 SkeletonModel::getDefaultEyeModelPosition() const { - //qCDebug(avatars_renderer) << "default eye model position " << _defaultEyeModelPosition; return _owningAvatar->getModelScale() * _defaultEyeModelPosition; } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index abf84d96b1..35aabca123 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -423,11 +423,9 @@ QMap getJointNameMapping(const QVariantHash& mapping) { if (!mapping.isEmpty() && mapping.contains(JOINT_NAME_MAPPING_FIELD) && mapping[JOINT_NAME_MAPPING_FIELD].type() == QVariant::Hash) { auto jointNames = mapping[JOINT_NAME_MAPPING_FIELD].toHash(); for (auto itr = jointNames.begin(); itr != jointNames.end(); itr++) { - qCDebug(modelformat) << "found a joint mapping field key " << itr.key() << " value " << itr.value().toString(); fbxToHifiJointNameMap.insert(itr.key(), itr.value().toString()); qCDebug(modelformat) << "the mapped key " << itr.key() << " has a value of " << fbxToHifiJointNameMap[itr.key()]; } - } return fbxToHifiJointNameMap; } @@ -480,14 +478,14 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& std::map lights; QVariantHash joints = mapping.value("joint").toHash(); - QString jointEyeLeftName = "EyeLeft"; //processID(getString(joints.value("jointEyeLeft", "jointEyeLeft"))); - QString jointEyeRightName = "EyeRight"; // processID(getString(joints.value("jointEyeRight", "jointEyeRight"))); - QString jointNeckName = "Neck"; //processID(getString(joints.value("jointNeck", "jointNeck"))); - QString jointRootName = "Hips"; //processID(getString(joints.value("jointRoot", "jointRoot"))); + QString jointEyeLeftName = "EyeLeft"; + QString jointEyeRightName = "EyeRight"; + QString jointNeckName = "Neck"; + QString jointRootName = "Hips"; QString jointLeanName = processID(getString(joints.value("jointLean", "jointLean"))); - QString jointHeadName = "Head";// processID(getString(joints.value("jointHead", "jointHead"))); - QString jointLeftHandName = "LeftHand"; //processID(getString(joints.value("jointLeftHand", "jointLeftHand"))); - QString jointRightHandName = "RightHand"; // processID(getString(joints.value("jointRightHand", "jointRightHand"))); + QString jointHeadName = "Head"; + QString jointLeftHandName = "LeftHand"; + QString jointRightHandName = "RightHand"; QString jointEyeLeftID; QString jointEyeRightID; QString jointNeckID; @@ -1845,21 +1843,11 @@ HFMModel* FBXReader::extractHFMModel(const QVariantHash& mapping, const QString& jointIndex = hfmModel.getJointIndex(hfmModel.fbxToHifiJointNameMapping[jointName]); } if (jointIndex != -1) { - //if (jointIndex == 18) { - // glm::quat spine3LocalOffset(0.94232035f, 0.000000014995882f, 0.33471236f, 0.000000058068572f); - // glm::quat spine3AbsoluteOffset = spine3LocalOffset * hfmModel.jointRotationOffsets[16]; - // hfmModel.jointRotationOffsets.insert(jointIndex, spine3AbsoluteOffset); - // qCDebug(modelformat) << "Joint Rotation Offset added for spine3 : " << spine3AbsoluteOffset; - //} else { - hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); - //} - + hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); } qCDebug(modelformat) << "Joint Rotation Offset added to Rig._jointRotationOffsets : " << " jointName: " << jointName << " jointIndex: " << jointIndex << " rotation offset: " << rotationOffset; } - - return hfmModelPtr; } From fb7b503ce94ce8da1aaea43dc21d7b5905662ae3 Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 26 Nov 2018 13:48:00 -0800 Subject: [PATCH 057/117] removed unnecessary iteration of the joint name mapping in AnimSkeleton.cpp --- libraries/animation/src/AnimSkeleton.cpp | 54 ++++-------------------- 1 file changed, 8 insertions(+), 46 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 110dd5f92a..c5e6241555 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -27,7 +27,6 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { _fbxToHifiJointNameMapping = hfmModel.fbxToHifiJointNameMapping; buildSkeletonFromJoints(joints, hfmModel.jointRotationOffsets); - // we make a copy of the inverseBindMatrices in order to prevent mutating the model bind pose // when we are dealing with a joint offset in the model for (int i = 0; i < (int)hfmModel.meshes.size(); i++) { @@ -133,13 +132,8 @@ std::vector AnimSkeleton::getChildrenOfJoint(int jointIndex) const { const QString AnimSkeleton::getJointName(int jointIndex) const { QString jointName = _joints[jointIndex].name; - QMapIterator i(_fbxToHifiJointNameMapping); - while (i.hasNext()) { - i.next(); - if (i.value() == _joints[jointIndex].name) { - jointName = i.key(); - break; - } + if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(_joints[jointIndex].name))) { + jointName = _fbxToHifiJointNameMapping.key(_joints[jointIndex].name); } return jointName; } @@ -216,22 +210,8 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const { bool AnimSkeleton::checkNonMirrored(QString jointName) const { - QMapIterator i(_fbxToHifiJointNameMapping); - while (i.hasNext()) { - i.next(); - if (i.value() == jointName) { - // check for left right in the key - if (i.key() != "Hips" && i.key() != "Spine" && - i.key() != "Spine1" && i.key() != "Spine2" && - i.key() != "Neck" && i.key() != "Head" && - !((i.key().startsWith("Left") || i.key().startsWith("Right")) && - i.key() != "LeftEye" && i.key() != "RightEye")) { - //return true - return true; - } else { - return false; - } - } + if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { + jointName = _fbxToHifiJointNameMapping.key(jointName); } // check the unmapped name if (jointName != "Hips" && jointName != "Spine" && @@ -239,26 +219,16 @@ bool AnimSkeleton::checkNonMirrored(QString jointName) const { jointName != "Neck" && jointName != "Head" && !((jointName.startsWith("Left") || jointName.startsWith("Right")) && jointName != "LeftEye" && jointName != "RightEye")) { - //return true return true; } else { return false; } - } int AnimSkeleton::containsLeft(QString jointName) const { - QMapIterator i(_fbxToHifiJointNameMapping); int mirrorJointIndex = -1; - while (i.hasNext()) { - i.next(); - if (i.value() == jointName) { - // check for left right in the key - if (i.key().startsWith("Left")) { - QString mirrorJointName = QString(i.key()).replace(0, 4, "Right"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); - } - } + if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { + jointName = _fbxToHifiJointNameMapping.key(jointName); } if (mirrorJointIndex < 0) { if (jointName.startsWith("Left")) { @@ -270,17 +240,9 @@ int AnimSkeleton::containsLeft(QString jointName) const { } int AnimSkeleton::containsRight(QString jointName) const { - QMapIterator i(_fbxToHifiJointNameMapping); int mirrorJointIndex = -1; - while (i.hasNext()) { - i.next(); - if (i.value() == jointName) { - // check for left right in the key - if (i.key().startsWith("Right")) { - QString mirrorJointName = QString(i.key()).replace(0, 5, "Left"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); - } - } + if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { + jointName = _fbxToHifiJointNameMapping.key(jointName); } if (mirrorJointIndex < 0) { if (jointName.startsWith("Right")) { From e10936ec3429bf9110c846b4f7d57dd08ea41a93 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 26 Nov 2018 18:26:25 -0800 Subject: [PATCH 058/117] Delete network query resources for failed queries --- libraries/avatars/src/AvatarData.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index d9d4b57c31..40555547e9 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2103,8 +2103,9 @@ void AvatarData::setJointMappingsFromNetworkReply() { // before we process this update, make sure that the skeleton model URL hasn't changed // since we made the FST request - if (networkReply->url() != _skeletonModelURL) { + if (networkReply->error() != QNetworkReply::NoError || networkReply->url() != _skeletonModelURL) { qCDebug(avatars) << "Refusing to set joint mappings for FST URL that does not match the current URL"; + networkReply->deleteLater(); return; } From 2bd66924efed418e8999965bb90dd6313aec3fa8 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 26 Nov 2018 18:27:13 -0800 Subject: [PATCH 059/117] Clear deleted avatar-entity list in mixer --- assignment-client/src/avatars/AvatarMixerClientData.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 76cdf13986..5e36d8beaf 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -152,6 +152,8 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message, if (packetTraitVersion > instanceVersionRef) { if (traitSize == AvatarTraits::DELETED_TRAIT_SIZE) { _avatar->processDeletedTraitInstance(traitType, instanceID); + // Mixer doesn't need deleted IDs. + _avatar->getAndClearRecentlyDetachedIDs(); // to track a deleted instance but keep version information // the avatar mixer uses the negative value of the sent version From e193dcbc602597f823006a3d2704ac6e838a8c4b Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 27 Nov 2018 18:59:58 +0100 Subject: [PATCH 060/117] - add missing start/middle/finish tooltips - style updates --- .../system/assets/data/createAppTooltips.json | 64 +++++++++++++++++-- scripts/system/html/css/edit-style.css | 5 +- scripts/system/html/js/entityProperties.js | 11 +++- 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/scripts/system/assets/data/createAppTooltips.json b/scripts/system/assets/data/createAppTooltips.json index 720d4537ee..b3df0fa13b 100644 --- a/scripts/system/assets/data/createAppTooltips.json +++ b/scripts/system/assets/data/createAppTooltips.json @@ -193,22 +193,52 @@ "emitterShouldTrail": { "tooltip": "If enabled, then particles are \"left behind\" as the emitter moves, otherwise they are not." }, + "particleRadiusTriple": { + "tooltip": "The size of each particle.", + "jsPropertyName": "particleRadius" + }, "particleRadius": { "tooltip": "The size of each particle." }, + "radiusStart": { + "tooltip": "The start size of each particle." + }, + "radiusFinish": { + "tooltip": "The finish size of each particle." + }, "radiusSpread": { "tooltip": "The spread in size that each particle is given, resulting in a variety of sizes." }, + "particleColorTriple": { + "tooltip": "The color of each particle.", + "jsPropertyName": "color" + }, "particleColor": { "tooltip": "The color of each particle.", "jsPropertyName": "color" }, + "colorStart": { + "tooltip": "The start color of each particle." + }, + "colorFinish": { + "tooltip": "The finish color of each particle." + }, "colorSpread": { "tooltip": "The spread in color that each particle is given, resulting in a variety of colors." }, + "particleAlphaTriple": { + "tooltip": "The alpha of each particle.", + "jsPropertyName": "alpha" + }, "alpha": { "tooltip": "The alpha of each particle." }, + "alphaStart": { + "tooltip": "The start alpha of each particle." + }, + "alphaFinish": { + "tooltip": "The finish alpha of each particle." + }, "alphaSpread": { "tooltip": "The spread in alpha that each particle is given, resulting in a variety of alphas." }, @@ -218,20 +248,44 @@ "accelerationSpread": { "tooltip": "The spread in accelerations that each particle is given, resulting in a variety of accelerations." }, + "particleSpinTriple": { + "tooltip": "The spin of each particle.", + "jsPropertyName": "particleSpin" + }, "particleSpin": { - "tooltip": "The spin of each particle in the system." + "tooltip": "The spin of each particle." + }, + "spinStart": { + "tooltip": "The start spin of each particle." + }, + "spinFinish": { + "tooltip": "The finish spin of each particle." }, "spinSpread": { "tooltip": "The spread in spin that each particle is given, resulting in a variety of spins." }, "rotateWithEntity": { - "tooltip": "If enabled, each particle will spin relative to the roation of the entity as a whole." + "tooltip": "If enabled, each particle will spin relative to the rotation of the entity as a whole." + }, + "particlePolarTriple": { + "tooltip": "The angle range in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis.", + "skipJSProperty": true }, "polarStart": { - "tooltip": "The angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." + "tooltip": "The start angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." + }, + "polarFinish": { + "tooltip": "The finish angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." + }, + "particleAzimuthTriple": { + "tooltip": "The angle range in deg at which particles are emitted. Starts in the entity's -x direction, and rotates around its z axis.", + "skipJSProperty": true }, "azimuthStart": { - "tooltip": "The angle in deg at which particles are emitted. Starts in the entity's -z direction, and rotates around its y axis." + "tooltip": "The start angle in deg at which particles are emitted. Starts in the entity's -x direction, and rotates around its z axis." + }, + "azimuthFinish": { + "tooltip": "The finish angle in deg at which particles are emitted. Starts in the entity's -x direction, and rotates around its z axis." }, "lightColor": { "tooltip": "The color of the light emitted.", @@ -352,7 +406,7 @@ "tooltip": "The URL of a sound to play when the entity collides with something else." }, "grab.grabbable": { - "tooltip": "If enabled, this entity will allow grabbing input and will be moveable." + "tooltip": "If enabled, this entity will allow grabbing input and will be movable." }, "grab.triggerable": { "tooltip": "If enabled, the collider on this entity is used for triggering events." diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 5b5c9e057c..8c21965152 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -599,6 +599,7 @@ div.section[collapsed="true"], div.section[collapsed="true"] > .section-header { .triple-label { text-transform: uppercase; padding: 6px 0; + cursor: default; } .triple-item { @@ -1507,6 +1508,7 @@ input.rename-entity { } .create-app-tooltip { + z-index: 100; position: absolute; background: #6a6a6a; border: 1px solid black; @@ -1644,6 +1646,7 @@ input.number-slider { font-family: Raleway-Light; font-size: 14px; margin: 6px 0; + cursor: default; } #property-name, #property-id { @@ -1656,7 +1659,7 @@ input.number-slider { } #placeholder-property-type { - min-width: 0px; + min-width: 0; } .collapse-icon { diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 78e3cd4dc8..60b9c04fbd 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -720,6 +720,7 @@ const GROUPS = [ { type: "triple", label: "Size", + propertyID: "particleRadiusTriple", properties: [ { label: "Start", @@ -771,6 +772,7 @@ const GROUPS = [ { type: "triple", label: "Color", + propertyID: "particleColorTriple", properties: [ { label: "Start", @@ -807,6 +809,7 @@ const GROUPS = [ { type: "triple", label: "Alpha", + propertyID: "particleAlphaTriple", properties: [ { label: "Start", @@ -883,6 +886,7 @@ const GROUPS = [ { type: "triple", label: "Alpha", + propertyID: "particleSpinTriple", properties: [ { label: "Start", @@ -947,6 +951,7 @@ const GROUPS = [ { type: "triple", label: "Horizontal Angle", + propertyID: "particlePolarTriple", properties: [ { label: "Start", @@ -975,6 +980,7 @@ const GROUPS = [ { type: "triple", label: "Vertical Angle", + propertyID: "particleAzimuthTriple", properties: [ { label: "Start", @@ -2886,7 +2892,10 @@ function loaded() { let propertyElementID = "property-" + propertyID; propertyElementID = propertyElementID.replace('.', '-'); - elWrapper.appendChild(createElementFromHTML(`
${innerPropertyData.label}
`)); + let elLabel = createElementFromHTML(`
${innerPropertyData.label}
`); + createAppTooltip.registerTooltipElement(elLabel, propertyID); + + elWrapper.appendChild(elLabel); elProperty.appendChild(elWrapper); let property = createProperty(innerPropertyData, propertyElementID, propertyName, propertyID, elWrapper.childNodes[0]); From ec19d2f119d49093d03a57d4c378d1c00ccb4eab Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 21 Nov 2018 15:31:47 -0800 Subject: [PATCH 061/117] Fix Create tooltips getting pushed down for tall rows --- scripts/system/html/js/entityProperties.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 60b9c04fbd..7f269aa7ed 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -2858,23 +2858,20 @@ function loaded() { elGroup.appendChild(elContainer); } - elLabel = document.createElement('label'); - elLabel.setAttribute("for", propertyElementID); + let labelText = propertyData.label !== undefined ? propertyData.label : ""; + let className = ''; if (propertyData.indentedLabel || propertyData.showPropertyRule !== undefined) { - let elSpan = document.createElement('span'); - elSpan.className = 'indented'; - elSpan.innerText = propertyData.label !== undefined ? propertyData.label : ""; - elLabel.appendChild(elSpan); - } else { - elLabel.innerText = propertyData.label !== undefined ? propertyData.label : ""; + className = 'indented'; } + elLabel = createElementFromHTML( + ``); elContainer.appendChild(elLabel); } else { elContainer = document.getElementById(propertyData.replaceID); } if (elLabel) { - createAppTooltip.registerTooltipElement(elLabel, propertyID); + createAppTooltip.registerTooltipElement(elLabel.childNodes[0], propertyID); } let elProperty = createElementFromHTML('
'); From 3a4ec2cc270659113f346dbdb090c88f5a064ad8 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Tue, 27 Nov 2018 10:53:25 -0800 Subject: [PATCH 062/117] Update glowLine.slv --- libraries/render-utils/src/glowLine.slv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/glowLine.slv b/libraries/render-utils/src/glowLine.slv index ecb1152d52..3471bc2f98 100644 --- a/libraries/render-utils/src/glowLine.slv +++ b/libraries/render-utils/src/glowLine.slv @@ -53,9 +53,9 @@ void main(void) { // Add or subtract the orthogonal vector based on a different vertex ID // calculation - distanceFromCenter = mix(1.0, -1.0, float(gl_VertexID < 2)); + distanceFromCenter = 1.0 - 2.0 * float(gl_VertexID < 2); eye.xyz += distanceFromCenter * orthogonal; // Finally, put the eyespace vertex into clip space <$transformEyeToClipPos(cam, eye, gl_Position)$> -} \ No newline at end of file +} From 5ee803bf1d0a99db94be178c190239a302f887c3 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Tue, 27 Nov 2018 10:54:56 -0800 Subject: [PATCH 063/117] Update parabola.slv --- libraries/render-utils/src/parabola.slv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/parabola.slv b/libraries/render-utils/src/parabola.slv index f220c656aa..6032452d1d 100644 --- a/libraries/render-utils/src/parabola.slv +++ b/libraries/render-utils/src/parabola.slv @@ -49,7 +49,7 @@ void main(void) { normal = vec4(normalize(cross(_parabolaData.velocity, _parabolaData.acceleration)), 0); } - pos += 0.5 * _parabolaData.width * normal * mix(-1.0, 1.0, float(gl_VertexID % 2 == 0)); + pos += 0.5 * _parabolaData.width * normal * (-1.0 + 2.0 * float(gl_VertexID % 2 == 0)); <$transformModelToClipPos(cam, obj, pos, gl_Position)$> -} \ No newline at end of file +} From f728a8ba5a0084426079a4466100a91c2b1eaddb Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Tue, 27 Nov 2018 10:57:57 -0800 Subject: [PATCH 064/117] Update drawCellBounds.slv --- libraries/render/src/render/drawCellBounds.slv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render/src/render/drawCellBounds.slv b/libraries/render/src/render/drawCellBounds.slv index 4b5356741b..216f1ea299 100644 --- a/libraries/render/src/render/drawCellBounds.slv +++ b/libraries/render/src/render/drawCellBounds.slv @@ -51,7 +51,7 @@ void main(void) { vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]]; int cellIsEmpty = sign(inCellLocation.w); - ivec4 cellLocation = ivec4(inCellLocation.xyz, cellIsEmpty * inCellLocation.w); + ivec4 cellLocation = ivec4(inCellLocation.xyz, abs(inCellLocation.w)); vec4 cellBound = evalBound(cellLocation); pos.xyz = cellBound.xyz + vec3(cellBound.w) * pos.xyz; @@ -62,4 +62,4 @@ void main(void) { <$transformModelToClipPos(cam, obj, pos, gl_Position)$> varColor = vec4(colorWheel(fract(float(inCellLocation.w) / 5.0)), 0.8 + 0.2 * float(cellIsEmpty)); -} \ No newline at end of file +} From 579e2dd2eeed15b0a7ae74cf7249a914c87bcf28 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 27 Nov 2018 14:10:20 -0800 Subject: [PATCH 065/117] removed unnecessary mirror joint code and cleaned up whitespace in rig.cpp --- libraries/animation/src/AnimSkeleton.cpp | 65 ++++++------------------ libraries/animation/src/AnimSkeleton.h | 4 -- libraries/animation/src/Rig.cpp | 5 +- 3 files changed, 16 insertions(+), 58 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index c5e6241555..b124f55641 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -54,7 +54,6 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { } _clusterBindMatrixOriginalValues.push_back(dummyClustersList); } - //dump(false); } AnimSkeleton::AnimSkeleton(const std::vector& joints, const QMap jointOffsets) { @@ -208,51 +207,6 @@ void AnimSkeleton::mirrorAbsolutePoses(AnimPoseVec& poses) const { } } -bool AnimSkeleton::checkNonMirrored(QString jointName) const { - - if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { - jointName = _fbxToHifiJointNameMapping.key(jointName); - } - // check the unmapped name - if (jointName != "Hips" && jointName != "Spine" && - jointName != "Spine1" && jointName != "Spine2" && - jointName != "Neck" && jointName != "Head" && - !((jointName.startsWith("Left") || jointName.startsWith("Right")) && - jointName != "LeftEye" && jointName != "RightEye")) { - return true; - } else { - return false; - } -} - -int AnimSkeleton::containsLeft(QString jointName) const { - int mirrorJointIndex = -1; - if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { - jointName = _fbxToHifiJointNameMapping.key(jointName); - } - if (mirrorJointIndex < 0) { - if (jointName.startsWith("Left")) { - QString mirrorJointName = QString(jointName).replace(0, 4, "Right"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); - } - } - return mirrorJointIndex; -} - -int AnimSkeleton::containsRight(QString jointName) const { - int mirrorJointIndex = -1; - if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { - jointName = _fbxToHifiJointNameMapping.key(jointName); - } - if (mirrorJointIndex < 0) { - if (jointName.startsWith("Right")) { - QString mirrorJointName = QString(jointName).replace(0, 5, "Left"); - mirrorJointIndex = nameToJointIndex(mirrorJointName); - } - } - return mirrorJointIndex; -} - void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, const QMap jointOffsets) { _joints = joints; @@ -304,15 +258,26 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, _nonMirroredIndices.clear(); _mirrorMap.reserve(_jointsSize); for (int i = 0; i < _jointsSize; i++) { - if (checkNonMirrored(_joints[i].name)) { + QString jointName = _joints[i].name; + if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { + jointName = _fbxToHifiJointNameMapping.key(jointName); + } + if (jointName != "Hips" && jointName != "Spine" && + jointName != "Spine1" && jointName != "Spine2" && + jointName != "Neck" && jointName != "Head" && + !((jointName.startsWith("Left") || jointName.startsWith("Right")) && + jointName != "LeftEye" && jointName != "RightEye")) { // HACK: we don't want to mirror some joints so we remember their indices // so we can restore them after a future mirror operation _nonMirroredIndices.push_back(i); } int mirrorJointIndex = -1; - mirrorJointIndex = containsLeft(_joints[i].name); - if (mirrorJointIndex < 0) { - mirrorJointIndex = containsRight(_joints[i].name); + if (jointName.startsWith("Left")) { + QString mirrorJointName = QString(jointName).replace(0, 4, "Right"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); + } else if (jointName.startsWith("Right")) { + QString mirrorJointName = QString(jointName).replace(0, 5, "Left"); + mirrorJointIndex = nameToJointIndex(mirrorJointName); } if (mirrorJointIndex >= 0) { _mirrorMap.push_back(mirrorJointIndex); diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index 5581976d74..50b5d25c63 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -56,9 +56,6 @@ public: void saveNonMirroredPoses(const AnimPoseVec& poses) const; void restoreNonMirroredPoses(AnimPoseVec& poses) const; - bool checkNonMirrored(QString jointName) const; - int containsLeft(QString jointName) const; - int containsRight(QString jointName) const; void mirrorRelativePoses(AnimPoseVec& poses) const; void mirrorAbsolutePoses(AnimPoseVec& poses) const; @@ -67,7 +64,6 @@ public: std::vector lookUpJointIndices(const std::vector& jointNames) const; const HFMCluster getClusterBindMatricesOriginalValues(const int meshIndex, const int clusterIndex) const { return _clusterBindMatrixOriginalValues[meshIndex][clusterIndex]; } - const QMap getFBXToHifiJointNameMapping() const { return _fbxToHifiJointNameMapping; } protected: void buildSkeletonFromJoints(const std::vector& joints, const QMap jointOffsets); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 5e2610e37e..128ac05b81 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -363,6 +363,7 @@ void Rig::reset(const HFMModel& hfmModel) { _animSkeleton = std::make_shared(hfmModel); + _internalPoseSet._relativePoses.clear(); _internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses(); @@ -420,11 +421,7 @@ static const uint32_t MAX_JOINT_NAME_WARNING_COUNT = 100; int Rig::indexOfJoint(const QString& jointName) const { if (_animSkeleton) { - int result = _animSkeleton->nameToJointIndex(jointName); - if (_animSkeleton->getFBXToHifiJointNameMapping().contains(jointName)) { - result = _animSkeleton->nameToJointIndex(jointName); - } // This is a content error, so we should issue a warning. if (result < 0 && _jointNameWarningCount < MAX_JOINT_NAME_WARNING_COUNT) { From 1f354f813c2553566913e1c514dafb749278a438 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 27 Nov 2018 14:38:02 -0800 Subject: [PATCH 066/117] rework shader pre-compilation --- interface/src/Application.cpp | 7 ++++ interface/src/Application.h | 2 ++ interface/src/Application_render.cpp | 2 +- .../display-plugins/OpenGLDisplayPlugin.cpp | 21 ++---------- .../src/display-plugins/OpenGLDisplayPlugin.h | 5 --- .../gpu-gl-common/src/gpu/gl/GLBackend.cpp | 11 +++---- .../gpu-gl-common/src/gpu/gl/GLBackend.h | 4 +-- libraries/gpu/src/gpu/Batch.cpp | 6 ---- libraries/gpu/src/gpu/Batch.h | 4 --- libraries/gpu/src/gpu/Context.cpp | 33 +++++++++++++++++++ libraries/gpu/src/gpu/Context.h | 21 ++++++++++++ libraries/gpu/src/gpu/null/NullBackend.h | 2 ++ libraries/plugins/src/plugins/DisplayPlugin.h | 2 -- 13 files changed, 75 insertions(+), 45 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6d13305af7..8e311e5487 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2862,6 +2862,13 @@ void Application::initializeGL() { _glWidget->makeCurrent(); _gpuContext = std::make_shared(); + static std::once_flag once; + std::call_once(once, [&] { + _gpuContext->pushProgramsToSync(shader::allPrograms(), [this] { + _programsCompiled.store(true); + }, 1); + }); + DependencyManager::get()->setGPUContext(_gpuContext); } diff --git a/interface/src/Application.h b/interface/src/Application.h index fb1c916c36..c234cd757c 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -795,5 +795,7 @@ private: bool _prevShowTrackedObjects { false }; std::shared_ptr _splashScreen { std::make_shared() }; + std::atomic _programsCompiled { false }; + }; #endif // hifi_Application_h diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index 8d9cdc980a..046cd3b617 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -115,7 +115,7 @@ void Application::paintGL() { finalFramebuffer = framebufferCache->getFramebuffer(); } - if (!displayPlugin->areAllProgramsLoaded()) { + if (!_programsCompiled.load()) { gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { batch.setFramebuffer(finalFramebuffer); batch.enableSkybox(true); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 45e0bbc2a6..aafc1a28a5 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -525,6 +525,9 @@ void OpenGLDisplayPlugin::updateFrameData() { if (_newFrameQueue.size() > 1) { _droppedFrameRate.increment(_newFrameQueue.size() - 1); } + + _gpuContext->processProgramsToSync(); + while (!_newFrameQueue.empty()) { _currentFrame = _newFrameQueue.front(); _newFrameQueue.pop(); @@ -633,29 +636,11 @@ void OpenGLDisplayPlugin::internalPresent() { _presentRate.increment(); } -std::atomic OpenGLDisplayPlugin::_allProgramsLoaded { false }; -unsigned int OpenGLDisplayPlugin::_currentLoadingProgramIndex { 0 }; - -bool OpenGLDisplayPlugin::areAllProgramsLoaded() const { - return OpenGLDisplayPlugin::_allProgramsLoaded.load(); -} - void OpenGLDisplayPlugin::present() { auto frameId = (uint64_t)presentCount(); PROFILE_RANGE_EX(render, __FUNCTION__, 0xffffff00, frameId) uint64_t startPresent = usecTimestampNow(); - if (!OpenGLDisplayPlugin::_allProgramsLoaded.load()) { - const auto& programIDs = shader::allPrograms(); - if (OpenGLDisplayPlugin::_currentLoadingProgramIndex < programIDs.size()) { - gpu::doInBatch("createAndSyncProgram", _gpuContext, [&programIDs](gpu::Batch& batch) { - batch.createAndSyncProgram(programIDs.at(OpenGLDisplayPlugin::_currentLoadingProgramIndex++)); - }); - } else { - OpenGLDisplayPlugin::_allProgramsLoaded.store(true); - } - } - { PROFILE_RANGE_EX(render, "updateFrameData", 0xff00ff00, frameId) updateFrameData(); diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index acb12aa69a..1cc060161b 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -83,8 +83,6 @@ public: void copyTextureToQuickFramebuffer(NetworkTexturePointer source, QOpenGLFramebufferObject* target, GLsync* fenceSync) override; - bool areAllProgramsLoaded() const override; - protected: friend class PresentThread; @@ -182,8 +180,5 @@ protected: // be serialized through this mutex mutable Mutex _presentMutex; float _hudAlpha{ 1.0f }; - - static std::atomic _allProgramsLoaded; - static unsigned int _currentLoadingProgramIndex; }; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp index 415c5135d9..295b9becb8 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.cpp @@ -102,8 +102,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::gl::GLBackend::do_pushProfileRange), (&::gpu::gl::GLBackend::do_popProfileRange), - - (&::gpu::gl::GLBackend::do_createAndSyncProgram), }; #define GL_GET_INTEGER(NAME) glGetIntegerv(GL_##NAME, &const_cast(NAME)); @@ -708,11 +706,6 @@ void GLBackend::do_glColor4f(const Batch& batch, size_t paramOffset) { (void)CHECK_GL_ERROR(); } -void GLBackend::do_createAndSyncProgram(const Batch& batch, size_t paramOffset) { - auto shader = gpu::Shader::createProgram(batch._params[paramOffset + 0]._uint); - gpu::gl::GLShader::sync(*this, *shader); -} - void GLBackend::releaseBuffer(GLuint id, Size size) const { Lock lock(_trashMutex); _currentFrameTrash.buffersTrash.push_back({ id, size }); @@ -866,3 +859,7 @@ void GLBackend::setCameraCorrection(const Mat4& correction, const Mat4& prevRend _pipeline._cameraCorrectionBuffer._buffer->setSubData(0, _transform._correction); _pipeline._cameraCorrectionBuffer._buffer->flush(); } + +void GLBackend::syncProgram(const gpu::ShaderPointer& program) { + gpu::gl::GLShader::sync(*this, *program); +} \ No newline at end of file diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 0a2c1b92ff..07f7df9277 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -249,6 +249,8 @@ public: // Let's try to avoid to do that as much as possible! void syncCache() final override; + void syncProgram(const gpu::ShaderPointer& program) override; + // This is the ugly "download the pixels to sysmem for taking a snapshot" // Just avoid using it, it's ugly and will break performances virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, @@ -380,8 +382,6 @@ public: virtual void do_setStateBlendFactor(const Batch& batch, size_t paramOffset) final; virtual void do_setStateScissorRect(const Batch& batch, size_t paramOffset) final; - virtual void do_createAndSyncProgram(const Batch& batch, size_t paramOffset) final; - virtual GLuint getFramebufferID(const FramebufferPointer& framebuffer) = 0; virtual GLuint getTextureID(const TexturePointer& texture) final; virtual GLuint getBufferID(const Buffer& buffer) = 0; diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 43c1c69287..a9b062a285 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -759,10 +759,4 @@ void Batch::flush() { } buffer->flush(); } -} - -void Batch::createAndSyncProgram(unsigned int programID) { - ADD_COMMAND(createAndSyncProgram); - - _params.emplace_back(programID); } \ No newline at end of file diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index aff6cf5ddd..96a45d3111 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -289,8 +289,6 @@ public: void _glColor4f(float red, float green, float blue, float alpha); - void createAndSyncProgram(unsigned int programID); - // Maybe useful but shoudln't be public. Please convince me otherwise // Well porting to gles i need it... void runLambda(std::function f); @@ -370,8 +368,6 @@ public: COMMAND_pushProfileRange, COMMAND_popProfileRange, - COMMAND_createAndSyncProgram, - NUM_COMMANDS, }; typedef std::vector Commands; diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index dd0d510509..be55e5ba87 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -335,6 +335,39 @@ Size Context::getTextureResourceIdealGPUMemSize() { return Backend::textureResourceIdealGPUMemSize.getValue(); } +void Context::pushProgramsToSync(const std::vector& programIDs, std::function callback, size_t rate) { + std::vector programs; + for (auto programID : programIDs) { + programs.push_back(gpu::Shader::createProgram(programID)); + } + pushProgramsToSync(programs, callback, rate); +} + +void Context::pushProgramsToSync(const std::vector& programs, std::function callback, size_t rate) { + Lock lock(_programsToSyncMutex); + _programsToSyncQueue.emplace(programs, callback, rate == 0 ? programs.size() : rate); +} + +void Context::processProgramsToSync() { + Lock lock(_programsToSyncMutex); + if (!_programsToSyncQueue.empty()) { + ProgramsToSync programsToSync = _programsToSyncQueue.front(); + int numSynced = 0; + while (_nextProgramToSyncIndex < programsToSync.programs.size() && numSynced < programsToSync.rate) { + auto nextProgram = programsToSync.programs.at(_nextProgramToSyncIndex); + _backend->syncProgram(nextProgram); + _syncedPrograms.push_back(nextProgram); + _nextProgramToSyncIndex++; + numSynced++; + } + + if (_nextProgramToSyncIndex == programsToSync.programs.size()) { + programsToSync.callback(); + _nextProgramToSyncIndex = 0; + _programsToSyncQueue.pop(); + } + } +} BatchPointer Context::acquireBatch(const char* name) { Batch* rawBatch = nullptr; diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 011f980957..3fb90fd2e9 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -13,6 +13,7 @@ #include #include +#include #include @@ -61,6 +62,7 @@ public: virtual void render(const Batch& batch) = 0; virtual void syncCache() = 0; + virtual void syncProgram(const gpu::ShaderPointer& program) = 0; virtual void recycle() const = 0; virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) = 0; @@ -245,6 +247,20 @@ public: static Size getTextureResourcePopulatedGPUMemSize(); static Size getTextureResourceIdealGPUMemSize(); + struct ProgramsToSync { + ProgramsToSync(const std::vector& programs, std::function callback, size_t rate) : + programs(programs), callback(callback), rate(rate) {} + + std::vector programs; + std::function callback; + size_t rate; + }; + + void pushProgramsToSync(const std::vector& programIDs, std::function callback, size_t rate = 0); + void pushProgramsToSync(const std::vector& programs, std::function callback, size_t rate = 0); + + void processProgramsToSync(); + protected: Context(const Context& context); @@ -256,6 +272,11 @@ protected: RangeTimerPointer _frameRangeTimer; StereoState _stereo; + std::mutex _programsToSyncMutex; + std::queue _programsToSyncQueue; + gpu::Shaders _syncedPrograms; + size_t _nextProgramToSyncIndex { 0 }; + // Sampled at the end of every frame, the stats of all the counters mutable ContextStats _frameStats; diff --git a/libraries/gpu/src/gpu/null/NullBackend.h b/libraries/gpu/src/gpu/null/NullBackend.h index e227b631c7..f934bcf619 100644 --- a/libraries/gpu/src/gpu/null/NullBackend.h +++ b/libraries/gpu/src/gpu/null/NullBackend.h @@ -43,6 +43,8 @@ public: // Let's try to avoid to do that as much as possible! void syncCache() final { } + void syncProgram(const gpu::ShaderPointer& program) final {} + // This is the ugly "download the pixels to sysmem for taking a snapshot" // Just avoid using it, it's ugly and will break performances virtual void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage) final { } diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index e9fbd71689..ad49ceafe6 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -217,8 +217,6 @@ public: static const QString& MENU_PATH(); - virtual bool areAllProgramsLoaded() const { return true; } - signals: void recommendedFramebufferSizeChanged(const QSize& size); void resetSensorsRequested(); From ad777201f60dbb66790ded7d792145bfe82a3e99 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 27 Nov 2018 15:08:50 -0800 Subject: [PATCH 067/117] changed comment and cleaned up variable name in getJointName --- libraries/animation/src/AnimSkeleton.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index b124f55641..36664a41fe 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -65,7 +65,7 @@ int AnimSkeleton::nameToJointIndex(const QString& jointName) const { auto itr = _jointIndicesByName.find(jointName); if (_fbxToHifiJointNameMapping.contains(jointName)) { // if the fbx joint name is different than the hifi standard then look up the - // index from that name. + // index from the fbx joint name. itr = _jointIndicesByName.find(_fbxToHifiJointNameMapping[jointName]); } if (itr != _jointIndicesByName.end()) { @@ -131,8 +131,8 @@ std::vector AnimSkeleton::getChildrenOfJoint(int jointIndex) const { const QString AnimSkeleton::getJointName(int jointIndex) const { QString jointName = _joints[jointIndex].name; - if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(_joints[jointIndex].name))) { - jointName = _fbxToHifiJointNameMapping.key(_joints[jointIndex].name); + if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { + jointName = _fbxToHifiJointNameMapping.key(jointName); } return jointName; } From ecd936705b5ad707abe46df91535a06c431e812b Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Wed, 28 Nov 2018 09:54:20 -0800 Subject: [PATCH 068/117] typo --- libraries/graphics/src/graphics/Material.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 196c0d595c..773ffbc954 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -337,8 +337,8 @@ public: glm::vec2 _lightmapParams { 0.0, 1.0 }; // x: material mode (0 for UV, 1 for PROJECTED) - // x: 1 for texture repeat, 0 for discard outside of 0 - 1 - glm::vec2 _materialParms { 0.0, 1.0 }; + // y: 1 for texture repeat, 0 for discard outside of 0 - 1 + glm::vec2 _materialParams { 0.0, 1.0 }; Schema() {} }; From 860d92036855bacd44e743eb6ca936d012657aef Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Wed, 28 Nov 2018 09:55:10 -0800 Subject: [PATCH 069/117] more typos --- libraries/graphics/src/graphics/Material.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index 5cf3ef9871..c493b3ef6f 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -138,7 +138,7 @@ void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textur _schemaBuffer.edit()._lightmapParams = (textureMap ? glm::vec2(textureMap->getLightmapOffsetScale()) : glm::vec2(0.0, 1.0)); } - _schemaBuffer.edit()._materialParms = (textureMap ? glm::vec2(textureMap->getMappingMode(), textureMap->getRepeat()) : glm::vec2(MaterialMappingMode::UV, 1.0)); + _schemaBuffer.edit()._materialParams = (textureMap ? glm::vec2(textureMap->getMappingMode(), textureMap->getRepeat()) : glm::vec2(MaterialMappingMode::UV, 1.0)); _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); @@ -229,5 +229,5 @@ void Material::setTextureTransforms(const Transform& transform, MaterialMappingM for (int i = 0; i < NUM_TEXCOORD_TRANSFORMS; i++) { _schemaBuffer.edit()._texcoordTransforms[i] = transform.getMatrix(); } - _schemaBuffer.edit()._materialParms = glm::vec2(mode, repeat); -} \ No newline at end of file + _schemaBuffer.edit()._materialParams = glm::vec2(mode, repeat); +} From 371c50b2ab90b51f479e3906656a6a8b4d52c31d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 28 Nov 2018 11:01:15 -0800 Subject: [PATCH 070/117] Start work on Pay Out UI --- .../commerce/common/sendAsset/SendAsset.qml | 146 +++++++++++++++++- 1 file changed, 139 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index 2d0bb2d87b..2a2369795e 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -269,7 +269,7 @@ Item { RalewaySemiBold { id: sendAssetText; - text: root.assetCertID === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"; + text: root.assetCertID === "" ? "Send Money To:" : "Send \"" + root.assetName + "\" To:"; // Anchors anchors.top: parent.top; anchors.topMargin: 26; @@ -370,6 +370,50 @@ Item { } } + Item { + id: authorizedScriptButton; + // Anchors + anchors.top: nearbyButton.bottom; + anchors.topMargin: 32; + anchors.horizontalCenter: parent.horizontalCenter; + height: connectionButton.height; + width: connectionButton.width; + + Image { + anchors.top: parent.top; + source: "./images/nearby.svg"; + height: 70; + width: parent.width; + fillMode: Image.PreserveAspectFit; + horizontalAlignment: Image.AlignHCenter; + verticalAlignment: Image.AlignTop; + mipmap: true; + } + + RalewaySemiBold { + text: "Authorized Script"; + // Anchors + anchors.bottom: parent.bottom; + height: 15; + width: parent.width; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + horizontalAlignment: Text.AlignHCenter; + } + + MouseArea { + anchors.fill: parent; + onClicked: { + sendAssetStep.referrer = "authorizedScript"; + sendAssetStep.selectedRecipientNodeID = ""; + + root.nextActiveView = "sendAssetStep"; + } + } + } + HifiControlsUit.Button { id: backButton_sendAssetHome; visible: parentAppNavBarHeight === 0; @@ -860,7 +904,7 @@ Item { id: sendAssetStep; z: 996; - property string referrer; // either "connections", "nearby", or "payIn" + property string referrer; // either "connections", "nearby", "payIn", or "authorizedScript" property string selectedRecipientNodeID; property string selectedRecipientDisplayName; property string selectedRecipientUserName; @@ -872,7 +916,8 @@ Item { RalewaySemiBold { id: sendAssetText_sendAssetStep; - text: sendAssetStep.referrer === "payIn" && root.assetCertID !== "" ? "Send \"" + root.assetName + "\":" : + text: ((sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "authorizedScript") && + root.assetCertID !== "") ? "Send \"" + root.assetName + "\":" : (root.assetCertID === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"); // Anchors anchors.top: parent.top; @@ -901,12 +946,13 @@ Item { RalewaySemiBold { id: sendToText_sendAssetStep; - text: (root.assetCertID === "" || sendAssetStep.referrer === "payIn") ? "Send to:" : "Gift to:"; + text: sendAssetStep.referrer === "authorizedScript" ? "Script Secret:" : + (root.assetCertID === "" || sendAssetStep.referrer === "payIn") ? "Send to:" : "Gift to:"; // Anchors anchors.top: parent.top; anchors.left: parent.left; anchors.bottom: parent.bottom; - width: 90; + width: paintedWidth; // Text size size: 18; // Style @@ -915,8 +961,10 @@ Item { } RecipientDisplay { + visible: sendAssetStep.referrer !== "authorizedScript"; anchors.top: parent.top; anchors.left: sendToText_sendAssetStep.right; + anchors.leftMargin: 16; anchors.right: changeButton.left; anchors.rightMargin: 12; height: parent.height; @@ -929,6 +977,71 @@ Item { multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn"; } + Item { + id: scriptSecretContainer; + visible: sendAssetStep.referrer === "authorizedScript"; + anchors.top: parent.top; + anchors.left: sendToText_sendAssetStep.right; + anchors.right: parent.right; + height: parent.height; + + RalewaySemiBold { + id: scriptSecretHelp; + text: "[?]"; + // Anchors + anchors.left: parent.left; + anchors.leftMargin: 8; + anchors.verticalCenter: parent.verticalCenter; + height: 30; + width: paintedWidth; + // Text size + size: 18; + // Style + color: hifi.colors.blueAccent; + MouseArea { + anchors.fill: parent; + hoverEnabled: true; + onEntered: { + parent.color = hifi.colors.blueHighlight; + } + onExited: { + parent.color = hifi.colors.blueAccent; + } + onClicked: { + lightboxPopup.titleText = "Script Secret"; + lightboxPopup.bodyText = "This alphanumeric text string will be used to ensure " + + "that only your scripts have access to the asset that you are sending. Keep it private!"; + lightboxPopup.button1text = "CLOSE"; + lightboxPopup.button1method = function() { + lightboxPopup.visible = false; + } + lightboxPopup.visible = true; + } + } + } + + HifiControlsUit.TextField { + id: scriptSecretTextField; + text: generateRandomSecret(); + colorScheme: root.assetCertID === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; + // Anchors + anchors.verticalCenter: parent.verticalCenter; + anchors.left: scriptSecretHelp.right; + anchors.leftMargin: 16; + anchors.right: parent.right; + height: 50; + // Style + activeFocusOnPress: true; + activeFocusOnTab: true; + + validator: RegExpValidator { regExp: /^[a-zA-Z0-9]+$/ } + + onAccepted: { + optionalMessage.focus = true; + } + } + } + // "CHANGE" button HifiControlsUit.Button { id: changeButton; @@ -939,7 +1052,7 @@ Item { height: 35; width: 100; text: "CHANGE"; - visible: sendAssetStep.referrer !== "payIn"; + visible: sendAssetStep.referrer !== "payIn" && sendAssetStep.referrer !== "authorizedScript"; onClicked: { if (sendAssetStep.referrer === "connections") { root.nextActiveView = "chooseRecipientConnection"; @@ -1263,6 +1376,8 @@ Item { root.assetCertID, parseInt(amountTextField.text), optionalMessage.text); + } else if (sendAssetStep.referrer === "authorizedScript") { + console.log("ZRF HERE: SENDING TO AUTHORIZED SCRIPT"); } } } @@ -1867,6 +1982,17 @@ Item { sendAssetStep.referrer = ""; } + function generateRandomSecret() { + var randomSecret = ""; + var possibleCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + for (var i = 0; i < 10; i++) { + randomSecret += possibleCharacters.charAt(Math.floor(Math.random() * possibleCharacters.length)); + } + + return randomSecret; + } + // // Function Name: fromScript() // @@ -1908,9 +2034,15 @@ Item { sendAssetStep.referrer = "payIn"; sendAssetStep.selectedRecipientNodeID = ""; sendAssetStep.selectedRecipientDisplayName = "Determined by script:"; - sendAssetStep.selectedRecipientUserName = message.username; + sendAssetStep.selectedRecipientUserName = message.username || ""; optionalMessage.text = message.message || "No Message Provided"; + if (sendAssetStep.selectedRecipientUserName === "") { + console.log("SendAsset: Script didn't specify a recipient username!"); + sendAssetHome.visible = false; + return; + } + root.nextActiveView = "sendAssetStep"; break; case 'inspectionCertificate_resetCert': From e5f4f67c1066368e5bdaf1323aff5627174a1922 Mon Sep 17 00:00:00 2001 From: David Back Date: Wed, 28 Nov 2018 17:30:18 -0800 Subject: [PATCH 071/117] RC76 draggable number fixes --- scripts/system/edit.js | 33 ++++---- scripts/system/html/js/draggableNumber.js | 87 +++++++++++++--------- scripts/system/html/js/entityProperties.js | 41 +++++----- 3 files changed, 92 insertions(+), 69 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 077d50ddde..039f4f1e22 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -554,8 +554,9 @@ var toolBar = (function () { } } - SelectionManager.saveProperties(); entityID = Entities.addEntity(properties); + SelectionManager.addEntity(entityID, false, this); + SelectionManager.saveProperties(); pushCommandForSelections([{ entityID: entityID, properties: properties @@ -1273,6 +1274,7 @@ function mouseClickEvent(event) { } else { selectionManager.addEntity(foundEntity, true, this); } + selectionManager.saveProperties(); if (wantDebug) { print("Model selected: " + foundEntity); @@ -2130,12 +2132,17 @@ function applyEntityProperties(data) { entityID = DELETED_ENTITY_MAP[entityID]; } Entities.deleteEntity(entityID); + var index = selectedEntityIDs.indexOf(entityID); + if (index >= 0) { + selectedEntityIDs.splice(index, 1); + } } // We might be getting an undo while edit.js is disabled. If that is the case, don't set // our selections, causing the edit widgets to display. if (isActive) { selectionManager.setSelections(selectedEntityIDs, this); + selectionManager.saveProperties(); } } @@ -2324,7 +2331,6 @@ var PropertiesTool = function (opts) { } var i, properties, dY, diff, newPosition; if (data.type === "update") { - selectionManager.saveProperties(); if (selectionManager.selections.length > 1) { for (i = 0; i < selectionManager.selections.length; i++) { Entities.editEntity(selectionManager.selections[i], data.properties); @@ -2360,8 +2366,12 @@ var PropertiesTool = function (opts) { entityListTool.sendUpdate(); } } - pushCommandForSelections(); - blockPropertyUpdates = data.blockUpdateCallback === true; + if (data.onlyUpdateEntities) { + blockPropertyUpdates = true; + } else { + pushCommandForSelections(); + SelectionManager.saveProperties(); + } selectionManager._update(false, this); blockPropertyUpdates = false; } else if (data.type === 'saveUserData' || data.type === 'saveMaterialData') { @@ -2473,8 +2483,6 @@ var PropertiesTool = function (opts) { tooltips: Script.require('./assets/data/createAppTooltips.json'), hmdActive: HMD.active, }); - } else if (data.type === "updateProperties") { - updateSelections(true); } }; @@ -2739,17 +2747,16 @@ keyUpEventFromUIWindow = function(keyUpEvent) { selectionManager.pasteEntities(); } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "D") { selectionManager.duplicateSelection(); - } else if (keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") { - undoHistory.undo(); + } else if (!isOnMacPlatform && keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") { + undoHistory.undo(); // undo is only handled via handleMenuItem on Mac } else if (keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "P") { parentSelectedEntities(); } else if (keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "P") { unparentSelectedEntities(); - } else if ( - (keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") || - (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "Y")) { - - undoHistory.redo(); + } else if (!isOnMacPlatform && + ((keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") || + (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "Y"))) { + undoHistory.redo(); // redo is only handled via handleMenuItem on Mac } else if (WANT_DEBUG_MISSING_SHORTCUTS) { console.warn("unhandled key event: " + JSON.stringify(keyUpEvent)) } diff --git a/scripts/system/html/js/draggableNumber.js b/scripts/system/html/js/draggableNumber.js index c08cac2ce4..104088ac48 100644 --- a/scripts/system/html/js/draggableNumber.js +++ b/scripts/system/html/js/draggableNumber.js @@ -7,6 +7,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html const DELTA_X_FOCUS_THRESHOLD = 1; +const ENTER_KEY = 13; function DraggableNumber(min, max, step, decimals, dragStart, dragEnd) { this.min = min; @@ -24,7 +25,7 @@ function DraggableNumber(min, max, step, decimals, dragStart, dragEnd) { DraggableNumber.prototype = { mouseDown: function(event) { - if (event.target === this.elText) { + if (event.target === this.elText && !this.isDisabled()) { this.initialMouseEvent = event; this.lastMouseEvent = event; document.addEventListener("mousemove", this.onDocumentMouseMove); @@ -33,7 +34,7 @@ DraggableNumber.prototype = { }, mouseUp: function(event) { - if (event.target === this.elText && this.initialMouseEvent) { + if (!this.dragging && event.target === this.elText && this.initialMouseEvent) { let dx = event.clientX - this.initialMouseEvent.clientX; if (Math.abs(dx) <= DELTA_X_FOCUS_THRESHOLD) { this.elInput.style.visibility = "visible"; @@ -44,32 +45,33 @@ DraggableNumber.prototype = { }, documentMouseMove: function(event) { - if (this.initialMouseEvent) { + if (!this.dragging && this.initialMouseEvent) { let dxFromInitial = event.clientX - this.initialMouseEvent.clientX; - if (Math.abs(dxFromInitial) > DELTA_X_FOCUS_THRESHOLD && this.lastMouseEvent) { - let initialValue = this.elInput.value; - let dx = event.clientX - this.lastMouseEvent.clientX; - let changeValue = dx !== 0; - if (changeValue) { - while (dx !== 0) { - if (dx > 0) { - this.elInput.stepUp(); - --dx; - } else { - this.elInput.stepDown(); - ++dx; - } - } - this.inputChange(); - if (this.valueChangeFunction) { - this.valueChangeFunction(); + if (Math.abs(dxFromInitial) > DELTA_X_FOCUS_THRESHOLD) { + if (this.dragStartFunction) { + this.dragStartFunction(); + } + this.dragging = true; + } + this.lastMouseEvent = event; + } + if (this.dragging && this.lastMouseEvent) { + let initialValue = this.elInput.value; + let dx = event.clientX - this.lastMouseEvent.clientX; + let changeValue = dx !== 0; + if (changeValue) { + while (dx !== 0) { + if (dx > 0) { + this.elInput.stepUp(); + --dx; + } else { + this.elInput.stepDown(); + ++dx; } } - if (!this.dragging) { - if (this.dragStartFunction) { - this.dragStartFunction(); - } - this.dragging = true; + this.inputChange(); + if (this.valueChangeFunction) { + this.valueChangeFunction(); } } this.lastMouseEvent = event; @@ -89,18 +91,22 @@ DraggableNumber.prototype = { }, stepUp: function() { - this.elInput.stepUp(); - this.inputChange(); - if (this.valueChangeFunction) { - this.valueChangeFunction(); + if (!this.isDisabled()) { + this.elInput.stepUp(); + this.inputChange(); + if (this.valueChangeFunction) { + this.valueChangeFunction(); + } } }, stepDown: function() { - this.elInput.stepDown(); - this.inputChange(); - if (this.valueChangeFunction) { - this.valueChangeFunction(); + if (!this.isDisabled()) { + this.elInput.stepDown(); + this.inputChange(); + if (this.valueChangeFunction) { + this.valueChangeFunction(); + } } }, @@ -114,9 +120,6 @@ DraggableNumber.prototype = { }, setValueChangeFunction: function(valueChangeFunction) { - if (this.valueChangeFunction) { - this.elInput.removeEventListener("change", this.valueChangeFunction); - } this.valueChangeFunction = valueChangeFunction.bind(this.elInput); this.elInput.addEventListener("change", this.valueChangeFunction); }, @@ -129,6 +132,16 @@ DraggableNumber.prototype = { this.elInput.style.visibility = "hidden"; this.elText.style.visibility = "visible"; }, + + keyPress: function(event) { + if (event.keyCode === ENTER_KEY) { + this.inputBlur(); + } + }, + + isDisabled: function() { + return this.elText.getAttribute("disabled") === "disabled"; + }, initialize: function() { this.onMouseDown = this.mouseDown.bind(this); @@ -139,6 +152,7 @@ DraggableNumber.prototype = { this.onStepDown = this.stepDown.bind(this); this.onInputChange = this.inputChange.bind(this); this.onInputBlur = this.inputBlur.bind(this); + this.onKeyPress = this.keyPress.bind(this); this.elDiv = document.createElement('div'); this.elDiv.className = "draggable-number"; @@ -174,6 +188,7 @@ DraggableNumber.prototype = { this.elInput.style.visibility = "hidden"; this.elInput.addEventListener("change", this.onInputChange); this.elInput.addEventListener("blur", this.onInputBlur); + this.elInput.addEventListener("keypress", this.onKeyPress); this.elText.appendChild(this.elLeftArrow); this.elText.appendChild(this.elInput); diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 78e3cd4dc8..0aabb300de 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -882,7 +882,7 @@ const GROUPS = [ properties: [ { type: "triple", - label: "Alpha", + label: "Spin", properties: [ { label: "Start", @@ -951,8 +951,8 @@ const GROUPS = [ { label: "Start", type: "number", - min: -180, - max: 0, + min: 0, + max: 180, step: 1, decimals: 0, multiplier: DEGREES_TO_RADIANS, @@ -979,7 +979,7 @@ const GROUPS = [ { label: "Start", type: "number", - min: 0, + min: -180, max: 180, step: 1, decimals: 0, @@ -990,7 +990,7 @@ const GROUPS = [ { label: "Finish", type: "number", - min: 0, + min: -180, max: 180, step: 1, decimals: 0, @@ -1182,7 +1182,7 @@ const GROUPS = [ }, { label: "Lifetime", - type: "number", + type: "string", unit: "s", propertyID: "lifetime", }, @@ -1370,6 +1370,7 @@ const GROUPS_PER_TYPE = { }; const EDITOR_TIMEOUT_DURATION = 1500; +const IMAGE_DEBOUNCE_TIMEOUT = 250; const DEBOUNCE_TIMEOUT = 125; const COLOR_MIN = 0; @@ -1641,7 +1642,7 @@ function updateVisibleSpaceModeProperties() { * PROPERTY UPDATE FUNCTIONS */ -function updateProperty(originalPropertyName, propertyValue, isParticleProperty, blockUpdateCallback) { +function updateProperty(originalPropertyName, propertyValue, isParticleProperty) { let propertyUpdate = {}; // if this is a compound property name (i.e. animation.running) then split it by . up to 3 times let splitPropertyName = originalPropertyName.split('.'); @@ -1667,7 +1668,8 @@ function updateProperty(originalPropertyName, propertyValue, isParticleProperty, }); particleSyncDebounce(); } else { - updateProperties(propertyUpdate, blockUpdateCallback); + let onlyUpdateEntity = properties[originalPropertyName].dragging === true; + updateProperties(propertyUpdate, onlyUpdateEntity); } } @@ -1676,15 +1678,15 @@ var particleSyncDebounce = _.debounce(function () { particlePropertyUpdates = {}; }, DEBOUNCE_TIMEOUT); -function updateProperties(propertiesToUpdate, blockUpdateCallback) { - if (blockUpdateCallback === undefined) { - blockUpdateCallback = false; +function updateProperties(propertiesToUpdate, onlyUpdateEntity) { + if (onlyUpdateEntity === undefined) { + onlyUpdateEntity = false; } EventBridge.emitWebEvent(JSON.stringify({ id: lastEntityID, type: "update", properties: propertiesToUpdate, - blockUpdateCallback: blockUpdateCallback + onlyUpdateEntities: onlyUpdateEntity })); } @@ -1709,9 +1711,8 @@ function createDragStartFunction(property) { function createDragEndFunction(property) { return function() { property.dragging = false; - EventBridge.emitWebEvent(JSON.stringify({ - type: "updateProperties" - })); + // send an additonal update post-dragging to consider whole property change from dragStart to dragEnd to be 1 action + this.valueChangeFunction(); }; } @@ -1722,7 +1723,7 @@ function createEmitNumberPropertyUpdateFunction(property) { multiplier = 1; } let value = parseFloat(this.value) * multiplier; - updateProperty(property.name, value, property.isParticleProperty, property.dragging); + updateProperty(property.name, value, property.isParticleProperty); }; } @@ -1736,7 +1737,7 @@ function createEmitVec2PropertyUpdateFunction(property) { x: property.elNumberX.elInput.value * multiplier, y: property.elNumberY.elInput.value * multiplier }; - updateProperty(property.name, newValue, property.isParticleProperty, property.dragging); + updateProperty(property.name, newValue, property.isParticleProperty); }; } @@ -1751,7 +1752,7 @@ function createEmitVec3PropertyUpdateFunction(property) { y: property.elNumberY.elInput.value * multiplier, z: property.elNumberZ.elInput.value * multiplier }; - updateProperty(property.name, newValue, property.isParticleProperty, property.dragging); + updateProperty(property.name, newValue, property.isParticleProperty); }; } @@ -1877,7 +1878,7 @@ function createNumberProperty(property, elProperty) { elProperty.appendChild(elDraggableNumber.elDiv); if (propertyData.buttons !== undefined) { - addButtons(elDraggableNumber.elText, elementID, propertyData.buttons, false); + addButtons(elDraggableNumber.elDiv, elementID, propertyData.buttons, false); } return elDraggableNumber; @@ -2100,7 +2101,7 @@ function createTextureProperty(property, elProperty) { elDiv.classList.remove("no-preview"); elDiv.classList.add("no-texture"); } - }, DEBOUNCE_TIMEOUT * 2); + }, IMAGE_DEBOUNCE_TIMEOUT); elInput.imageLoad = imageLoad; elInput.oninput = function (event) { // Add throttle From 181f2b4263272fa0c4f99b5b1da57d12195e9b7d Mon Sep 17 00:00:00 2001 From: Clement Date: Wed, 28 Nov 2018 17:27:59 -0800 Subject: [PATCH 072/117] Fix Agent crash on shutdown --- assignment-client/src/avatars/ScriptableAvatar.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 2 +- libraries/avatars/src/AvatarData.h | 2 +- libraries/avatars/src/ClientTraitsHandler.cpp | 2 +- libraries/shared/src/SharedUtil.h | 7 +++++++ 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 51038a782f..bf5d87a6bf 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -21,7 +21,7 @@ #include ScriptableAvatar::ScriptableAvatar() { - _clientTraitsHandler = std::unique_ptr(new ClientTraitsHandler(this)); + _clientTraitsHandler.reset(new ClientTraitsHandler(this)); } QByteArray ScriptableAvatar::toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index afebd0bb79..7196aa1a2c 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -139,7 +139,7 @@ MyAvatar::MyAvatar(QThread* thread) : _flyingHMDSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "flyingHMD", _flyingPrefHMD), _avatarEntityCountSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" << "size", 0) { - _clientTraitsHandler = std::unique_ptr(new ClientTraitsHandler(this)); + _clientTraitsHandler.reset(new ClientTraitsHandler(this)); // give the pointer to our head to inherited _headData variable from AvatarData _headData = new MyHead(this); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 36c6ed6c50..7d88cab209 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1490,7 +1490,7 @@ protected: bool _isClientAvatar { false }; // null unless MyAvatar or ScriptableAvatar sending traits data to mixer - std::unique_ptr _clientTraitsHandler; + std::unique_ptr _clientTraitsHandler; template T readLockWithNamedJointIndex(const QString& name, const T& defaultValue, F f) const { diff --git a/libraries/avatars/src/ClientTraitsHandler.cpp b/libraries/avatars/src/ClientTraitsHandler.cpp index f8247d9e52..a301341a8e 100644 --- a/libraries/avatars/src/ClientTraitsHandler.cpp +++ b/libraries/avatars/src/ClientTraitsHandler.cpp @@ -22,7 +22,7 @@ ClientTraitsHandler::ClientTraitsHandler(AvatarData* owningAvatar) : _owningAvatar(owningAvatar) { auto nodeList = DependencyManager::get(); - QObject::connect(nodeList.data(), &NodeList::nodeAdded, [this](SharedNodePointer addedNode){ + QObject::connect(nodeList.data(), &NodeList::nodeAdded, this, [this](SharedNodePointer addedNode) { if (addedNode->getType() == NodeType::AvatarMixer) { resetForNewMixer(); } diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index f36574bed6..709eeca9b2 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -113,6 +113,13 @@ void doEvery(quint64& lastReportUsecs, quint64 secs, F lamdba) { // Maximum accuracy in msecs float secTimestampNow(); +// Custom deleter for QObjects that calls deleteLater +struct LaterDeleter { + void operator()(QObject* ptr) { + ptr->deleteLater(); + } +}; + float randFloat(); int randIntInRange (int min, int max); float randFloatInRange (float min,float max); From aa749b0980e5649e974c499ea55de51a3b24ef6d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 28 Nov 2018 21:46:13 -0800 Subject: [PATCH 073/117] adressing review comments --- .../utilities/lib/jet/qml/TaskListView.qml | 24 +------------------ .../lib/jet/qml/TaskTimeFrameView.qml | 1 - .../utilities/render/engineInspector.js | 14 ----------- .../utilities/render/engineInspector.qml | 2 +- 4 files changed, 2 insertions(+), 39 deletions(-) diff --git a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml index bc14404ee2..e2576fe783 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskListView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskListView.qml @@ -26,30 +26,10 @@ Rectangle { Component.onCompleted: { - //var functor = Jet.job_tree_model_functor(jobsModel) var functor = Jet.job_tree_model_functor(jobsModel, 3, function(node) { node["cpuT"] = 0.0 }) Jet.task_traverseTree(rootConfig, functor); - - - - /* var tfunctor = Jet.job_tree_model_array_functor(jobsModel.engineJobItemModel, function(node) { - node["init"] = (node.level < 3) - node["fullpath"] = (node.path + "." + node.name) - node["cpuT"] = 0.0 - }) - - Jet.task_traverseTree(rootConfig, tfunctor); -*/ - // var currentParentStach = [] - // currentParentStach.push(jobsModel); - - - /* Jet.job_traverseTreeNodeRoot(jobsModel.engineJobItemModel[0], function(node, depth, index) { - print(node.name + depth + " - " + index) - return true - })*/ } @@ -95,15 +75,13 @@ Rectangle { HifiControls.Label { id: objLabel - // property var config: root.rootConfig.getConfig(model.path + "." + model.name); colorScheme: (root.rootConfig.getConfig(model.path + "." + model.name) ? hifi.colorSchemes.dark : hifi.colorSchemes.light) text: (objRecursiveColumn.children.length > 2 ? objRecursiveColumn.children[1].visible ? qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name - // + " ms=" + config.cpuRunTime.toFixed(3) + " id=" + model.id } - } + } } Repeater { diff --git a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml index e1d9bd7ce1..f3ca550e44 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskTimeFrameView.qml @@ -166,7 +166,6 @@ Rectangle { function drawJob(ctx, depth, index, duration, timeOffset) { //print(root.jobsArray[index].cpuT) - // ctx.fillStyle = Qt.rgba(255, 255, 0, root.backgroundOpacity); ctx.fillStyle = ( depth % 2 ? ( index % 2 ? "blue" : "yellow") : ( index % 2 ? "green" : "red")) ctx.fillRect(getXFromTime(timeOffset), lineHeight * 2 * depth,getWFromDuration(duration), lineHeight); diff --git a/scripts/developer/utilities/render/engineInspector.js b/scripts/developer/utilities/render/engineInspector.js index 74e4231ff1..cd2b74f907 100644 --- a/scripts/developer/utilities/render/engineInspector.js +++ b/scripts/developer/utilities/render/engineInspector.js @@ -1,17 +1,3 @@ - /*function openEngineTaskView() { - // Set up the qml ui - var qml = Script.resolvePath('engineInspector.qml'); - var window = new OverlayWindow({ - title: 'Render Engine', - source: qml, - width: 500, - height: 100 - }); - window.setPosition(200, 50); - window.closed.connect(function() { Script.stop(); }); - } - openEngineTaskView();*/ - (function() { var TABLET_BUTTON_NAME = "Inspector"; var QMLAPP_URL = Script.resolvePath("./engineInspector.qml"); diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml index 31283a4756..1e05605ac7 100644 --- a/scripts/developer/utilities/render/engineInspector.qml +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -26,5 +26,5 @@ Item { Jet.TaskListView { rootConfig: root.rootConfig anchors.fill: root - } + } } \ No newline at end of file From 54fa4365b84d3a8d6e5cf0185b4b73611c517fff Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 28 Nov 2018 22:21:58 -0800 Subject: [PATCH 074/117] FIxing build issue doh... --- interface/src/Application.cpp | 6 ------ interface/src/Application_render.cpp | 3 --- 2 files changed, 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2e46043dba..d92eae5221 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5088,13 +5088,7 @@ void Application::init() { // Make sure Login state is up to date #if !defined(DISABLE_QML) DependencyManager::get()->toggleLoginDialog(); -<<<<<<< HEAD -======= #endif - if (!DISABLE_DEFERRED) { - DependencyManager::get()->init(); - } ->>>>>>> f4535e6784be56de3e3b0a21517280c12a434425 DependencyManager::get()->init(); _timerStart.start(); diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp index 1e66953a49..5063f6118d 100644 --- a/interface/src/Application_render.cpp +++ b/interface/src/Application_render.cpp @@ -19,9 +19,6 @@ #include "Util.h" - - -<<<<<<< HEAD //void Application::paintGL() { // // Some plugins process message events, allowing paintGL to be called reentrantly. // From ec4726ad151bd78bf1d020a8b5409138e6b0d7ab Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 29 Nov 2018 10:37:56 -0800 Subject: [PATCH 075/117] fix subproperty updates --- scripts/system/html/js/entityProperties.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 0aabb300de..5ac077b67b 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1668,7 +1668,10 @@ function updateProperty(originalPropertyName, propertyValue, isParticleProperty) }); particleSyncDebounce(); } else { - let onlyUpdateEntity = properties[originalPropertyName].dragging === true; + // only update the entity property value itself if in the middle of dragging + // prevent undo command push, saving new property values, and property update + // callback until drag is complete (additional update sent via dragEnd callback) + let onlyUpdateEntity = properties[originalPropertyName] && properties[originalPropertyName].dragging === true; updateProperties(propertyUpdate, onlyUpdateEntity); } } From bc39dbba8b38b80f6023f5e47dd75d4248c6cce6 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 29 Nov 2018 12:44:30 -0800 Subject: [PATCH 076/117] Finish out the feature --- .../commerce/common/sendAsset/SendAsset.qml | 297 +++++++++++++++--- .../common/sendAsset/images/clipboard.svg | 1 + interface/src/commerce/Ledger.cpp | 16 + interface/src/commerce/Ledger.h | 4 + interface/src/commerce/QmlCommerce.cpp | 16 + interface/src/commerce/QmlCommerce.h | 2 + 6 files changed, 291 insertions(+), 45 deletions(-) create mode 100644 interface/resources/qml/hifi/commerce/common/sendAsset/images/clipboard.svg diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index 2a2369795e..36113077f5 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -36,6 +36,8 @@ Item { property bool isCurrentlySendingAsset: false; property string assetName: ""; property string assetCertID: ""; + property string secret: ""; + property string authorizationID: ""; property string sendingPubliclyEffectImage; property var http; property var listModelName; @@ -108,6 +110,27 @@ Item { } } + onAuthorizeAssetTransferResult: { + if (!root.visible) { + return; + } + + root.isCurrentlySendingAsset = false; + + if (result.status === 'success') { + root.authorizationID = result.data.authorization_id; + authorizationIDText.text = root.authorizationID; + root.secret = result.data.secret; + secretText.text = root.secret + if (scriptSecretTextField.text !== root.secret) { + console.log("SendAsset: Returned secret doesn't match client-generated secret!"); + } + root.nextActiveView = 'paymentSuccess'; + } else { + root.nextActiveView = 'paymentFailure'; + } + } + onCertificateInfoResult: { if (result.status !== 'success') { console.log("Failed to get certificate info", result.data.message); @@ -408,6 +431,7 @@ Item { onClicked: { sendAssetStep.referrer = "authorizedScript"; sendAssetStep.selectedRecipientNodeID = ""; + scriptSecretTextField.text = generateRandomSecret(); root.nextActiveView = "sendAssetStep"; } @@ -1022,7 +1046,6 @@ Item { HifiControlsUit.TextField { id: scriptSecretTextField; - text: generateRandomSecret(); colorScheme: root.assetCertID === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; // Anchors anchors.verticalCenter: parent.verticalCenter; @@ -1034,8 +1057,6 @@ Item { activeFocusOnPress: true; activeFocusOnTab: true; - validator: RegExpValidator { regExp: /^[a-zA-Z0-9]+$/ } - onAccepted: { optionalMessage.focus = true; } @@ -1377,7 +1398,10 @@ Item { parseInt(amountTextField.text), optionalMessage.text); } else if (sendAssetStep.referrer === "authorizedScript") { - console.log("ZRF HERE: SENDING TO AUTHORIZED SCRIPT"); + Commerce.authorizeAssetTransfer(scriptSecretTextField.text || "", + root.assetCertID, + parseInt(amountTextField.text) || 1, + optionalMessage.text) } } } @@ -1449,18 +1473,24 @@ Item { Rectangle { anchors.top: parent.top; - anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 125; + anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 125; anchors.left: parent.left; - anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; + anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 50; anchors.right: parent.right; - anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; + anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 50; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 125; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 125; color: "#FFFFFF"; RalewaySemiBold { id: paymentSentText; - text: root.assetCertID === "" ? "Payment Sent" : (sendAssetStep.referrer === "payIn" ? "Item Sent" : "Gift Sent"); + text: root.assetCertID === "" ? (sendAssetStep.referrer === "authorizedScript" ? "Payment Authorized" : "Payment Sent") : + (sendAssetStep.referrer === "authorizedScript" ? "Item Transfer Authorized" : + (sendAssetStep.referrer === "payIn" ? "Item Sent" : "Gift Sent")); // Anchors anchors.top: parent.top; anchors.topMargin: 26; @@ -1498,6 +1528,8 @@ Item { onClicked: { if (sendAssetStep.referrer === "payIn") { sendToScript({method: "closeSendAsset"}); + } else if (sendAssetStep.referrer === "authorizedScript") { + showDidYouCopyLightbox(); } else { root.nextActiveView = "sendAssetHome"; resetSendAssetData(); @@ -1517,38 +1549,176 @@ Item { anchors.leftMargin: 20; anchors.right: parent.right; anchors.rightMargin: 20; - height: 80; + height: childrenRect.height; - RalewaySemiBold { - id: sendToText_paymentSuccess; - text: "Sent To:"; - // Anchors + Item { + id: sendToScriptContainer_paymentSuccess; + visible: sendAssetStep.referrer === "authorizedScript"; anchors.top: parent.top; anchors.left: parent.left; - anchors.bottom: parent.bottom; - width: 90; - // Text size - size: 18; - // Style - color: hifi.colors.baseGray; - verticalAlignment: Text.AlignVCenter; - } - - RecipientDisplay { - anchors.top: parent.top; - anchors.left: sendToText_paymentSuccess.right; anchors.right: parent.right; - height: parent.height; - textColor: hifi.colors.blueAccent; + height: childrenRect.height; - displayName: sendAssetStep.selectedRecipientDisplayName; - userName: sendAssetStep.selectedRecipientUserName; - profilePic: sendAssetStep.selectedRecipientProfilePic !== "" ? ((0 === sendAssetStep.selectedRecipientProfilePic.indexOf("http")) ? - sendAssetStep.selectedRecipientProfilePic : (Account.metaverseServerURL + sendAssetStep.selectedRecipientProfilePic)) : ""; - multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn"; + RalewaySemiBold { + id: authorizationIDLabel; + text: "Authorization ID:"; + // Anchors + anchors.left: parent.left; + anchors.top: authorizationIDText.top; + width: paintedWidth; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + verticalAlignment: Text.AlignVCenter; + } + + RalewayRegular { + id: authorizationIDText; + text: root.authorizationID; + anchors.top: parent.top; + anchors.left: authorizationIDLabel.right; + anchors.leftMargin: 16; + anchors.right: authorizationIDClipboardButton.left; + anchors.rightMargin: 16; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + horizontalAlignment: Text.AlignHCenter; + verticalAlignment: Text.AlignVCenter; + wrapMode: Text.WrapAnywhere; + } + + Image { + id: authorizationIDClipboardButton; + source: "images/clipboard.svg"; // clipboard by Bieutuong Bon from the Noun Project + fillMode: Image.PreserveAspectFit; + // Anchors + anchors.right: parent.right; + anchors.top: authorizationIDText.top; + height: 40; + width: height; + + MouseArea { + anchors.fill: parent; + onClicked: { + Window.copyToClipboard(root.authorizationID); + authorizationIDText.text = "Copied to Clipboard!\n"; + authorizationIDClipboardTimer.start(); + } + } + } + + Timer { + id: authorizationIDClipboardTimer; + interval: 2000; + repeat: false; + onTriggered: { + authorizationIDText.text = root.authorizationID; + } + } + + RalewaySemiBold { + id: secretLabel; + text: "Secret:"; + // Anchors + anchors.left: parent.left; + anchors.top: secretText.top; + width: authorizationIDLabel.width; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + verticalAlignment: Text.AlignVCenter; + } + + RalewayRegular { + id: secretText; + text: root.secret; + anchors.top: authorizationIDText.bottom; + anchors.topMargin: 16; + anchors.left: secretLabel.right; + anchors.leftMargin: 16; + anchors.right: secretClipboardButton.left; + anchors.rightMargin: 16; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + horizontalAlignment: Text.AlignHCenter; + verticalAlignment: Text.AlignVCenter; + wrapMode: Text.WrapAnywhere; + } + + Image { + id: secretClipboardButton; + source: "images/clipboard.svg"; // clipboard by Bieutuong Bon from the Noun Project + fillMode: Image.PreserveAspectFit; + // Anchors + anchors.right: parent.right; + anchors.top: secretText.top; + height: 40; + width: height; + + MouseArea { + anchors.fill: parent; + onClicked: { + Window.copyToClipboard(root.secret); + secretText.text = "Copied to Clipboard!\n"; + secretClipboardTimer.start(); + } + } + } + + Timer { + id: secretClipboardTimer; + interval: 2000; + repeat: false; + onTriggered: { + secretText.text = root.secret; + } + } } - } - + + Item { + id: sendToRecipientContainer_paymentSuccess; + visible: !sendToScriptContainer_paymentSuccess.visible; + anchors.top: parent.top; + anchors.left: parent.left; + anchors.right: parent.right; + height: 80; + + RalewaySemiBold { + id: sendToText_paymentSuccess; + text: "Sent To:"; + // Anchors + anchors.top: parent.top; + anchors.left: parent.left; + anchors.bottom: parent.bottom; + width: 90; + // Text size + size: 18; + // Style + color: hifi.colors.baseGray; + verticalAlignment: Text.AlignVCenter; + } + + RecipientDisplay { + anchors.top: parent.top; + anchors.left: sendToText_paymentSuccess.right; + anchors.right: parent.right; + height: parent.height; + textColor: hifi.colors.blueAccent; + + displayName: sendAssetStep.selectedRecipientDisplayName; + userName: sendAssetStep.selectedRecipientUserName; + profilePic: sendAssetStep.selectedRecipientProfilePic !== "" ? ((0 === sendAssetStep.selectedRecipientProfilePic.indexOf("http")) ? + sendAssetStep.selectedRecipientProfilePic : (Account.metaverseServerURL + sendAssetStep.selectedRecipientProfilePic)) : ""; + multiLineDisplay: sendAssetStep.referrer === "nearby" || sendAssetStep.referrer === "payIn"; + } + } + } Item { id: giftContainer_paymentSuccess; @@ -1563,7 +1733,8 @@ Item { RalewaySemiBold { id: gift_paymentSuccess; - text: sendAssetStep.referrer === "payIn" ? "Item:" : "Gift:"; + text: sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "authorizedScript" ? + "Item:" : "Gift:"; // Anchors anchors.top: parent.top; anchors.left: parent.left; @@ -1681,6 +1852,8 @@ Item { onClicked: { if (sendAssetStep.referrer === "payIn") { sendToScript({method: "closeSendAsset"}); + } else if (sendAssetStep.referrer === "authorizedScript") { + showDidYouCopyLightbox(); } else { root.nextActiveView = "sendAssetHome"; resetSendAssetData(); @@ -1714,13 +1887,17 @@ Item { Rectangle { anchors.top: parent.top; - anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 150; + anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 150; anchors.left: parent.left; - anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; + anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 50; anchors.right: parent.right; - anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 50; + anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 50; anchors.bottom: parent.bottom; - anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" ? 15 : 300; + anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || + sendAssetStep.referrer === "authorizedScript" ? 15 : 300; color: "#FFFFFF"; RalewaySemiBold { @@ -1772,8 +1949,9 @@ Item { RalewaySemiBold { id: paymentFailureDetailText; - text: "The recipient you specified was unable to receive your " + - (root.assetCertID === "" ? "payment." : (sendAssetStep.referrer === "payIn" ? "item." : "gift.")); + text: sendAssetStep.referrer === "authorizedScript" ? "The server was unable to handle your request. Please try again later." : + ("The recipient you specified was unable to receive your " + + (root.assetCertID === "" ? "payment." : (sendAssetStep.referrer === "payIn" ? "item." : "gift."))); anchors.top: paymentFailureText.bottom; anchors.topMargin: 20; anchors.left: parent.left; @@ -1791,7 +1969,8 @@ Item { Item { id: sendToContainer_paymentFailure; - visible: root.assetCertID === "" || sendAssetStep.referrer === "payIn"; + visible: (root.assetCertID === "" || sendAssetStep.referrer === "payIn") && + sendAssetStep.referrer !== "authorizedScript"; anchors.top: paymentFailureDetailText.bottom; anchors.topMargin: 8; anchors.left: parent.left; @@ -1833,7 +2012,8 @@ Item { Item { id: amountContainer_paymentFailure; visible: root.assetCertID === ""; - anchors.top: sendToContainer_paymentFailure.bottom; + anchors.top: sendToContainer_paymentFailure.visible ? + sendToContainer_paymentFailure.bottom : paymentFailureDetailText.bottom; anchors.topMargin: 16; anchors.left: parent.left; anchors.leftMargin: 20; @@ -1954,6 +2134,11 @@ Item { root.assetCertID, parseInt(amountTextField.text), optionalMessage.text); + } else if (sendAssetStep.referrer === "authorizedScript") { + Commerce.authorizeAssetTransfer(scriptSecretTextField.text || "", + root.assetCertID, + parseInt(amountTextField.text) || 1, + optionalMessage.text) } } } @@ -1983,16 +2168,38 @@ Item { } function generateRandomSecret() { + var RANDOM_SECRET_LENGTH = 25; var randomSecret = ""; var possibleCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - for (var i = 0; i < 10; i++) { + for (var i = 0; i < RANDOM_SECRET_LENGTH; i++) { randomSecret += possibleCharacters.charAt(Math.floor(Math.random() * possibleCharacters.length)); } return randomSecret; } + function showDidYouCopyLightbox() { + lightboxPopup.titleText = "Close Confirmation"; + lightboxPopup.bodyText = "Did you copy your Authorization ID and your Script Secret?\n\n" + + "You won't be able to see your Authorization ID or your Script Secret once " + + "you close this window."; + lightboxPopup.button1text = "GO BACK"; + lightboxPopup.button1method = function() { + lightboxPopup.visible = false; + } + lightboxPopup.button2text = "I'M ALL SET"; + lightboxPopup.button2method = function() { + lightboxPopup.visible = false; + root.nextActiveView = "sendAssetHome"; + resetSendAssetData(); + if (root.assetName !== "") { + sendSignalToParent({method: "closeSendAsset"}); + } + } + lightboxPopup.visible = true; + } + // // Function Name: fromScript() // diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/images/clipboard.svg b/interface/resources/qml/hifi/commerce/common/sendAsset/images/clipboard.svg new file mode 100644 index 0000000000..798fdaaab1 --- /dev/null +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/images/clipboard.svg @@ -0,0 +1 @@ +Created by Bieutuong Bonfrom the Noun Project \ No newline at end of file diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index b10c9647a0..fb177ddc82 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -63,6 +63,7 @@ Handler(balance) Handler(inventory) Handler(transferAssetToNode) Handler(transferAssetToUsername) +Handler(authorizeAssetTransfer) Handler(alreadyOwned) Handler(availableUpdates) Handler(updateItem) @@ -428,6 +429,7 @@ void Ledger::transferAssetToUsername(const QString& hfc_key, const QString& user transaction["username"] = username; transaction["quantity"] = amount; transaction["message"] = optionalMessage; + transaction["place_name"] = DependencyManager::get()->getPlaceName(); if (!certificateID.isEmpty()) { transaction["certificate_id"] = certificateID; } @@ -440,6 +442,20 @@ void Ledger::transferAssetToUsername(const QString& hfc_key, const QString& user } } +void Ledger::authorizeAssetTransfer(const QString& hfc_key, const QString& secret, const QString& certificateID, const int& amount, const QString& optionalMessage) { + QJsonObject transaction; + transaction["public_key"] = hfc_key; + transaction["secret"] = secret; + transaction["quantity"] = amount; + transaction["message"] = optionalMessage; + if (!certificateID.isEmpty()) { + transaction["certificate_id"] = certificateID; + } + QJsonDocument transactionDoc{ transaction }; + auto transactionString = transactionDoc.toJson(QJsonDocument::Compact); + signedSend("transaction", transactionString, hfc_key, "authorize", "authorizeAssetTransferSuccess", "authorizeAssetTransferFailure"); +} + void Ledger::alreadyOwned(const QString& marketplaceId) { auto wallet = DependencyManager::get(); QString endpoint = "already_owned"; diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 715d6337ad..700cbe2c4b 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -36,6 +36,7 @@ public: void certificateInfo(const QString& certificateId); void transferAssetToNode(const QString& hfc_key, const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage); void transferAssetToUsername(const QString& hfc_key, const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage); + void authorizeAssetTransfer(const QString& hfc_key, const QString& secret, const QString& certificateID, const int& amount, const QString& optionalMessage); void alreadyOwned(const QString& marketplaceId); void getAvailableUpdates(const QString& itemId = "", const int& pageNumber = 1, const int& itemsPerPage = 10); void updateItem(const QString& hfc_key, const QString& certificate_id); @@ -59,6 +60,7 @@ signals: void certificateInfoResult(QJsonObject result); void transferAssetToNodeResult(QJsonObject result); void transferAssetToUsernameResult(QJsonObject result); + void authorizeAssetTransferResult(QJsonObject result); void alreadyOwnedResult(QJsonObject result); void availableUpdatesResult(QJsonObject result); void updateItemResult(QJsonObject result); @@ -86,6 +88,8 @@ public slots: void transferAssetToNodeFailure(QNetworkReply* reply); void transferAssetToUsernameSuccess(QNetworkReply* reply); void transferAssetToUsernameFailure(QNetworkReply* reply); + void authorizeAssetTransferSuccess(QNetworkReply* reply); + void authorizeAssetTransferFailure(QNetworkReply* reply); void alreadyOwnedSuccess(QNetworkReply* reply); void alreadyOwnedFailure(QNetworkReply* reply); void availableUpdatesSuccess(QNetworkReply* reply); diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index 566f7ba324..aab053484b 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -38,6 +38,7 @@ QmlCommerce::QmlCommerce() { connect(ledger.data(), &Ledger::updateCertificateStatus, this, &QmlCommerce::updateCertificateStatus); connect(ledger.data(), &Ledger::transferAssetToNodeResult, this, &QmlCommerce::transferAssetToNodeResult); connect(ledger.data(), &Ledger::transferAssetToUsernameResult, this, &QmlCommerce::transferAssetToUsernameResult); + connect(ledger.data(), &Ledger::authorizeAssetTransferResult, this, &QmlCommerce::authorizeAssetTransferResult); connect(ledger.data(), &Ledger::availableUpdatesResult, this, &QmlCommerce::availableUpdatesResult); connect(ledger.data(), &Ledger::updateItemResult, this, &QmlCommerce::updateItemResult); @@ -246,6 +247,21 @@ void QmlCommerce::transferAssetToUsername(const QString& username, ledger->transferAssetToUsername(key, username, certificateID, amount, optionalMessage); } +void QmlCommerce::authorizeAssetTransfer(const QString& secret, + const QString& certificateID, + const int& amount, + const QString& optionalMessage) { + auto ledger = DependencyManager::get(); + auto wallet = DependencyManager::get(); + QStringList keys = wallet->listPublicKeys(); + if (keys.count() == 0) { + QJsonObject result{ { "status", "fail" }, { "message", "Uninitialized Wallet." } }; + return emit authorizeAssetTransferResult(result); + } + QString key = keys[0]; + ledger->authorizeAssetTransfer(key, secret, certificateID, amount, optionalMessage); +} + void QmlCommerce::replaceContentSet(const QString& itemHref, const QString& certificateID) { if (!certificateID.isEmpty()) { auto ledger = DependencyManager::get(); diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index c5fbdaf4a4..e22b540624 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -51,6 +51,7 @@ signals: void transferAssetToNodeResult(QJsonObject result); void transferAssetToUsernameResult(QJsonObject result); + void authorizeAssetTransferResult(QJsonObject result); void contentSetChanged(const QString& contentSetHref); @@ -84,6 +85,7 @@ protected: Q_INVOKABLE void transferAssetToNode(const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage); Q_INVOKABLE void transferAssetToUsername(const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage); + Q_INVOKABLE void authorizeAssetTransfer(const QString& secret, const QString& certificateID, const int& amount, const QString& optionalMessage); Q_INVOKABLE void replaceContentSet(const QString& itemHref, const QString& certificateID); From c53c52c7a018de4e9f36d807e5fa359a848e5054 Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 29 Nov 2018 17:42:04 -0800 Subject: [PATCH 077/117] Fix various Agent bugs --- assignment-client/src/Agent.cpp | 22 +++++++++++++++---- assignment-client/src/AssignmentClient.cpp | 15 +++++-------- .../src/scripts/EntityScriptServer.cpp | 20 ++++++++++++++--- libraries/recording/src/recording/Deck.cpp | 4 +--- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 88897a0fed..bd368ef7c2 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -656,6 +656,8 @@ void Agent::queryAvatars() { ViewFrustum view; view.setPosition(scriptedAvatar->getWorldPosition()); view.setOrientation(scriptedAvatar->getHeadOrientation()); + view.setProjection(DEFAULT_FIELD_OF_VIEW_DEGREES, DEFAULT_ASPECT_RATIO, + DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP); view.calculate(); ConicalViewFrustum conicalView { view }; @@ -876,18 +878,30 @@ void Agent::aboutToFinish() { DependencyManager::destroy(); // destroy all other created dependencies - DependencyManager::destroy(); - DependencyManager::destroy(); DependencyManager::destroy(); - DependencyManager::destroy(); DependencyManager::destroy(); - DependencyManager::destroy(); + DependencyManager::destroy(); + DependencyManager::destroy(); + DependencyManager::destroy(); + DependencyManager::destroy(); + + DependencyManager::destroy(); + DependencyManager::destroy(); + DependencyManager::destroy(); + DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); + DependencyManager::destroy(); + DependencyManager::destroy(); + DependencyManager::destroy(); + DependencyManager::destroy(); + + DependencyManager::destroy(); + // drop our shared pointer to the script engine, then ask ScriptEngines to shutdown scripting // this ensures that the ScriptEngine goes down before ScriptEngines _scriptEngine.clear(); diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 76ff5ab2ed..c1943de2cc 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -129,17 +129,12 @@ void AssignmentClient::stopAssignmentClient() { QThread* currentAssignmentThread = _currentAssignment->thread(); // ask the current assignment to stop - BLOCKING_INVOKE_METHOD(_currentAssignment, "stop"); + QMetaObject::invokeMethod(_currentAssignment, "stop"); - // ask the current assignment to delete itself on its thread - _currentAssignment->deleteLater(); - - // when this thread is destroyed we don't need to run our assignment complete method - disconnect(currentAssignmentThread, &QThread::destroyed, this, &AssignmentClient::assignmentCompleted); - - // wait on the thread from that assignment - it will be gone once the current assignment deletes - currentAssignmentThread->quit(); - currentAssignmentThread->wait(); + auto PROCESS_EVENTS_INTERVAL_MS = 100; + while (!currentAssignmentThread->wait(PROCESS_EVENTS_INTERVAL_MS)) { + QCoreApplication::processEvents(); + } } } diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 272985093c..ef0c807bc4 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -583,15 +583,29 @@ void EntityScriptServer::handleOctreePacket(QSharedPointer mess void EntityScriptServer::aboutToFinish() { shutdownScriptEngine(); + DependencyManager::get()->setEntityTree(nullptr); + DependencyManager::get()->cleanup(); + + DependencyManager::destroy(); + DependencyManager::destroy(); + DependencyManager::destroy(); + DependencyManager::destroy(); + + DependencyManager::destroy(); + DependencyManager::destroy(); + + DependencyManager::destroy(); + DependencyManager::destroy(); + + DependencyManager::destroy(); + DependencyManager::destroy(); DependencyManager::destroy(); + DependencyManager::destroy(); - DependencyManager::get()->cleanup(); DependencyManager::destroy(); - DependencyManager::destroy(); - DependencyManager::destroy(); // cleanup the AudioInjectorManager (and any still running injectors) DependencyManager::destroy(); diff --git a/libraries/recording/src/recording/Deck.cpp b/libraries/recording/src/recording/Deck.cpp index 69a8587581..4d65f0eb1b 100644 --- a/libraries/recording/src/recording/Deck.cpp +++ b/libraries/recording/src/recording/Deck.cpp @@ -180,9 +180,7 @@ void Deck::processFrames() { #ifdef WANT_RECORDING_DEBUG qCDebug(recordingLog) << "Setting timer for next processing " << nextInterval; #endif - _timer.singleShot(nextInterval, [this] { - processFrames(); - }); + _timer.singleShot(nextInterval, this, &Deck::processFrames); } void Deck::removeClip(const ClipConstPointer& clip) { From 88a9a96346617a7bd5b532ab881768aa121e87ea Mon Sep 17 00:00:00 2001 From: amantley Date: Fri, 30 Nov 2018 10:08:05 -0800 Subject: [PATCH 078/117] removed the code that turns off inactive hands in MyAvatar.cpp --- interface/src/avatar/MyAvatar.cpp | 40 ------------------------------- 1 file changed, 40 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index afebd0bb79..020ab68f0b 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -807,46 +807,6 @@ void MyAvatar::simulate(float deltaTime) { // before we perform rig animations and IK. updateSensorToWorldMatrix(); - // if we detect the hand controller is at rest, i.e. lying on the table, or the hand is too far away from the hmd - // disable the associated hand controller input. - { - // NOTE: all poses are in sensor space. - auto leftHandIter = _controllerPoseMap.find(controller::Action::LEFT_HAND); - if (leftHandIter != _controllerPoseMap.end() && leftHandIter->second.isValid()) { - _leftHandAtRestDetector.update(leftHandIter->second.getTranslation(), leftHandIter->second.getRotation()); - if (_leftHandAtRestDetector.isAtRest()) { - leftHandIter->second.valid = false; - } - } else { - _leftHandAtRestDetector.invalidate(); - } - - auto rightHandIter = _controllerPoseMap.find(controller::Action::RIGHT_HAND); - if (rightHandIter != _controllerPoseMap.end() && rightHandIter->second.isValid()) { - _rightHandAtRestDetector.update(rightHandIter->second.getTranslation(), rightHandIter->second.getRotation()); - if (_rightHandAtRestDetector.isAtRest()) { - rightHandIter->second.valid = false; - } - } else { - _rightHandAtRestDetector.invalidate(); - } - - auto headIter = _controllerPoseMap.find(controller::Action::HEAD); - - // The 99th percentile man has a spine to fingertip to height ratio of 0.45. Lets increase that by about 10% to 0.5 - // then measure the distance the center of the eyes to the finger tips. To come up with this ratio. - // From "The Measure of Man and Woman: Human Factors in Design, Revised Edition" by Alvin R. Tilley, Henry Dreyfuss Associates - const float MAX_HEAD_TO_HAND_DISTANCE_RATIO = 0.52f; - - float maxHeadHandDistance = getUserHeight() * MAX_HEAD_TO_HAND_DISTANCE_RATIO; - if (glm::length(headIter->second.getTranslation() - leftHandIter->second.getTranslation()) > maxHeadHandDistance) { - leftHandIter->second.valid = false; - } - if (glm::length(headIter->second.getTranslation() - rightHandIter->second.getTranslation()) > maxHeadHandDistance) { - rightHandIter->second.valid = false; - } - } - { PerformanceTimer perfTimer("skeleton"); From 051b7cfbb8106007e81564a04545076f8214d8be Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 30 Nov 2018 16:12:21 -0800 Subject: [PATCH 079/117] Fix MS20117: Prevent HTML link from appearing in Wallet notification --- scripts/system/commerce/wallet.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index d5365133b6..3a8462c5cb 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -615,7 +615,9 @@ function notificationPollCallbackHistory(historyArray) { ui.notificationDisplayBanner(message); } else { for (var i = 0; i < notificationCount; i++) { - message = '"' + (historyArray[i].message) + '" ' + + var historyMessage = historyArray[i].message; + var sanitizedHistoryMessage = historyMessage.replace(/<\/?[^>]+(>|$)/g, ""); + message = '"' + sanitizedHistoryMessage + '" ' + "Open INVENTORY to see all activity."; ui.notificationDisplayBanner(message); } From c0bf832e393655d7e455c0c5789e7889673b5a65 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Sun, 2 Dec 2018 16:18:36 -0800 Subject: [PATCH 080/117] Head and Hand offsets for Vive Trackers now function as expected In the Settings > Controller... > Calibration menu, when using head or hand trackers The provided Y and Z offsets should function correctly now. This gives you the ability to adjust the offsets of the pucks to the hands/head. For example: this allows you to wear the hand pucks on your forearms rather then the backs of your palms. --- .../qml/hifi/tablet/OpenVrConfiguration.qml | 35 ++++++++++++------- plugins/openvr/src/ViveControllerManager.cpp | 32 +++++++---------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml index e18fdea444..46817e07cf 100644 --- a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml +++ b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml @@ -207,12 +207,12 @@ Flickable { width: 112 label: "Y Offset" suffix: " cm" - minimumValue: -10 + minimumValue: -50 + maximumValue: 50 realStepSize: 1 - realValue: -5 colorScheme: hifi.colorSchemes.dark - onEditingFinished: { + onRealValueChanged: { sendConfigurationSettings(); openVrConfiguration.forceActiveFocus(); } @@ -223,14 +223,14 @@ Flickable { id: headZOffset width: 112 label: "Z Offset" - minimumValue: -10 + minimumValue: -50 + maximumValue: 50 realStepSize: 1 decimals: 1 suffix: " cm" - realValue: -5 colorScheme: hifi.colorSchemes.dark - onEditingFinished: { + onRealValueChanged: { sendConfigurationSettings(); openVrConfiguration.forceActiveFocus(); } @@ -319,11 +319,12 @@ Flickable { width: 112 suffix: " cm" label: "Y Offset" - minimumValue: -10 + minimumValue: -30 + maximumValue: 30 realStepSize: 1 colorScheme: hifi.colorSchemes.dark - onEditingFinished: { + onRealValueChanged: { sendConfigurationSettings(); openVrConfiguration.forceActiveFocus(); } @@ -335,12 +336,13 @@ Flickable { width: 112 label: "Z Offset" suffix: " cm" - minimumValue: -10 + minimumValue: -30 + maximumValue: 30 realStepSize: 1 decimals: 1 colorScheme: hifi.colorSchemes.dark - onEditingFinished: { + onRealValueChanged: { sendConfigurationSettings(); openVrConfiguration.forceActiveFocus(); } @@ -574,7 +576,7 @@ Flickable { colorScheme: hifi.colorSchemes.dark realValue: 33.0 - onEditingFinished: { + onRealValueChanged: { sendConfigurationSettings(); openVrConfiguration.forceActiveFocus(); } @@ -592,7 +594,7 @@ Flickable { colorScheme: hifi.colorSchemes.dark realValue: 48 - onEditingFinished: { + onRealValueChanged: { sendConfigurationSettings(); openVrConfiguration.forceActiveFocus(); } @@ -771,7 +773,7 @@ Flickable { realStepSize: 1.0 colorScheme: hifi.colorSchemes.dark - onEditingFinished: { + onRealValueChanged: { calibrationTimer.interval = realValue * 1000; openVrConfiguration.countDown = realValue; numberAnimation.duration = calibrationTimer.interval; @@ -977,6 +979,13 @@ Flickable { var configurationType = settings["trackerConfiguration"]; displayTrackerConfiguration(configurationType); + // default offset for user wearing puck on the center of their forehead. + headYOffset.realValue = 4; // (cm), puck is above the head joint. + headZOffset.realValue = 8; // (cm), puck is in front of the head joint. + + // defaults for user wearing the pucks on the backs of their palms. + handYOffset.realValue = 8; // (cm), puck is past the the hand joint. (set this to zero if puck is on the wrist) + handZOffset.realValue = -4; // (cm), puck is on above hand joint. var HmdHead = settings["HMDHead"]; var viveController = settings["handController"]; diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index af4f4da18c..283556f86a 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -892,7 +892,7 @@ glm::mat4 ViveControllerManager::InputDevice::calculateDefaultToReferenceForHead glm::vec3 x = glm::normalize(glm::cross(Vectors::UNIT_Y, forward)); glm::vec3 z = glm::normalize(glm::cross(x, Vectors::UNIT_Y)); glm::mat3 centerEyeRotMat(x, Vectors::UNIT_Y, z); - glm::vec3 centerEyeTrans = headPuckPose.translation + centerEyeRotMat * glm::vec3(0.0f, _headPuckYOffset, _headPuckZOffset); + glm::vec3 centerEyeTrans = headPuckPose.translation + centerEyeRotMat * -glm::vec3(0.0f, _headPuckYOffset, _headPuckZOffset); glm::mat4 E_s(glm::vec4(centerEyeRotMat[0], 0.0f), glm::vec4(centerEyeRotMat[1], 0.0f), @@ -1056,7 +1056,7 @@ void ViveControllerManager::InputDevice::hapticsHelper(float deltaTime, bool lef float hapticTime = strength * MAX_HAPTIC_TIME; if (hapticTime < duration * 1000.0f) { _system->TriggerHapticPulse(deviceIndex, 0, hapticTime); - } + } float remainingHapticTime = duration - (hapticTime / 1000.0f + deltaTime * 1000.0f); // in milliseconds if (leftHand) { @@ -1077,23 +1077,20 @@ void ViveControllerManager::InputDevice::calibrateLeftHand(const glm::mat4& defa } // This allows the user to not have to match the t-pose exactly. We assume that the y facing of the hand lies in the plane of the puck. - // Where the plane of the puck is defined by the the local z-axis of the puck, which is facing out of the vive logo/power button. + // Where the plane of the puck is defined by the the local z-axis of the puck, which is pointing out of the camera mount on the bottom of the puck. glm::vec3 zPrime = handPoseZAxis; glm::vec3 xPrime = glm::normalize(glm::cross(referenceHandYAxis, handPoseZAxis)); glm::vec3 yPrime = glm::normalize(glm::cross(zPrime, xPrime)); glm::mat4 newHandMat = glm::mat4(glm::vec4(xPrime, 0.0f), glm::vec4(yPrime, 0.0f), glm::vec4(zPrime, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); - glm::vec3 translationOffset = glm::vec3(0.0f, _handPuckYOffset, _handPuckZOffset); - glm::quat initialRotation = handPose.getRotation(); - glm::quat finalRotation = glmExtractRotation(newHandMat); - - glm::quat rotationOffset = glm::inverse(initialRotation) * finalRotation; - - glm::mat4 offsetMat = createMatFromQuatAndPos(rotationOffset, translationOffset); + glm::quat initialRot = handPose.getRotation(); + glm::quat postOffsetRot = glm::inverse(initialRot) * glmExtractRotation(newHandMat); + glm::vec3 postOffsetTrans = postOffsetRot * -glm::vec3(0.0f, _handPuckYOffset, _handPuckZOffset); + glm::mat4 postOffsetMat = createMatFromQuatAndPos(postOffsetRot, postOffsetTrans); _jointToPuckMap[controller::LEFT_HAND] = handPair.first; - _pucksPostOffset[handPair.first] = offsetMat; + _pucksPostOffset[handPair.first] = postOffsetMat; } void ViveControllerManager::InputDevice::calibrateRightHand(const glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration, PuckPosePair& handPair) { @@ -1113,16 +1110,13 @@ void ViveControllerManager::InputDevice::calibrateRightHand(const glm::mat4& def glm::mat4 newHandMat = glm::mat4(glm::vec4(xPrime, 0.0f), glm::vec4(yPrime, 0.0f), glm::vec4(zPrime, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); - glm::vec3 translationOffset = glm::vec3(0.0f, _handPuckYOffset, _handPuckZOffset); - glm::quat initialRotation = handPose.getRotation(); - glm::quat finalRotation = glmExtractRotation(newHandMat); - - glm::quat rotationOffset = glm::inverse(initialRotation) * finalRotation; - - glm::mat4 offsetMat = createMatFromQuatAndPos(rotationOffset, translationOffset); + glm::quat initialRot = handPose.getRotation(); + glm::quat postOffsetRot = glm::inverse(initialRot) * glmExtractRotation(newHandMat); + glm::vec3 postOffsetTrans = postOffsetRot * -glm::vec3(0.0f, _handPuckYOffset, _handPuckZOffset); + glm::mat4 postOffsetMat = createMatFromQuatAndPos(postOffsetRot, postOffsetTrans); _jointToPuckMap[controller::RIGHT_HAND] = handPair.first; - _pucksPostOffset[handPair.first] = offsetMat; + _pucksPostOffset[handPair.first] = postOffsetMat; } From f38f39c84d44f014ac51a9cdab81f1bf05d84d79 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Mon, 3 Dec 2018 19:20:16 +0100 Subject: [PATCH 081/117] ignore shortcuts in TEXTAREA elements --- scripts/system/html/js/entityList.js | 3 ++- scripts/system/html/js/entityProperties.js | 3 ++- scripts/system/html/js/gridControls.js | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index 84ad59df36..15353db48e 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -1186,7 +1186,8 @@ function loaded() { }; document.addEventListener("keyup", function (keyUpEvent) { - if (keyUpEvent.target.nodeName === "INPUT") { + const FILTERED_NODE_NAMES = ["INPUT", "TEXTAREA"]; + if (FILTERED_NODE_NAMES.includes(keyUpEvent.target.nodeName)) { return; } diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 14ed2b77e3..8562159ecf 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -3451,7 +3451,8 @@ function loaded() { }; document.addEventListener("keyup", function (keyUpEvent) { - if (keyUpEvent.target.nodeName === "INPUT") { + const FILTERED_NODE_NAMES = ["INPUT", "TEXTAREA"]; + if (FILTERED_NODE_NAMES.includes(keyUpEvent.target.nodeName)) { return; } let {code, key, keyCode, altKey, ctrlKey, metaKey, shiftKey} = keyUpEvent; diff --git a/scripts/system/html/js/gridControls.js b/scripts/system/html/js/gridControls.js index b2d5988938..3e5bfa1e2f 100644 --- a/scripts/system/html/js/gridControls.js +++ b/scripts/system/html/js/gridControls.js @@ -118,7 +118,8 @@ function loaded() { }; document.addEventListener("keyup", function (keyUpEvent) { - if (keyUpEvent.target.nodeName === "INPUT") { + const FILTERED_NODE_NAMES = ["INPUT", "TEXTAREA"]; + if (FILTERED_NODE_NAMES.includes(keyUpEvent.target.nodeName)) { return; } let {code, key, keyCode, altKey, ctrlKey, metaKey, shiftKey} = keyUpEvent; From f7fcf503c21f587a2b0910e38f1aa953442da70a Mon Sep 17 00:00:00 2001 From: amantley Date: Mon, 3 Dec 2018 14:50:57 -0800 Subject: [PATCH 082/117] removed joint lean from fbxSerializer. it was unused --- libraries/fbx/src/FBXSerializer.cpp | 6 ------ libraries/fbx/src/GLTFSerializer.cpp | 1 - libraries/hfm/src/hfm/HFM.h | 1 - 3 files changed, 8 deletions(-) diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/fbx/src/FBXSerializer.cpp index c7785003f9..cfdf596b98 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -482,7 +482,6 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr QString jointEyeRightName = "EyeRight"; QString jointNeckName = "Neck"; QString jointRootName = "Hips"; - QString jointLeanName = processID(getString(joints.value("jointLean", "jointLean"))); QString jointHeadName = "Head"; QString jointLeftHandName = "LeftHand"; QString jointRightHandName = "RightHand"; @@ -490,7 +489,6 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr QString jointEyeRightID; QString jointNeckID; QString jointRootID; - QString jointLeanID; QString jointHeadID; QString jointLeftHandID; QString jointRightHandID; @@ -614,9 +612,6 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr } else if (name == jointRootName || (hfmModel.fbxToHifiJointNameMapping.contains(jointRootName) && (name == hfmModel.fbxToHifiJointNameMapping[jointRootName]))) { jointRootID = getID(object.properties); - } else if (name == jointLeanName) { - jointLeanID = getID(object.properties); - } else if ((name == jointHeadName) || (hfmModel.fbxToHifiJointNameMapping.contains(jointHeadName) && (name == hfmModel.fbxToHifiJointNameMapping[jointHeadName]))) { jointHeadID = getID(object.properties); @@ -1451,7 +1446,6 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr hfmModel.rightEyeJointIndex = modelIDs.indexOf(jointEyeRightID); hfmModel.neckJointIndex = modelIDs.indexOf(jointNeckID); hfmModel.rootJointIndex = modelIDs.indexOf(jointRootID); - hfmModel.leanJointIndex = modelIDs.indexOf(jointLeanID); hfmModel.headJointIndex = modelIDs.indexOf(jointHeadID); hfmModel.leftHandJointIndex = modelIDs.indexOf(jointLeftHandID); hfmModel.rightHandJointIndex = modelIDs.indexOf(jointRightHandID); diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 28d377c605..5485f46905 100644 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1186,7 +1186,6 @@ void GLTFSerializer::hfmDebugDump(const HFMModel& hfmModel) { qCDebug(modelformat) << " rightEyeJointIndex =" << hfmModel.rightEyeJointIndex; qCDebug(modelformat) << " neckJointIndex =" << hfmModel.neckJointIndex; qCDebug(modelformat) << " rootJointIndex =" << hfmModel.rootJointIndex; - qCDebug(modelformat) << " leanJointIndex =" << hfmModel.leanJointIndex; qCDebug(modelformat) << " headJointIndex =" << hfmModel.headJointIndex; qCDebug(modelformat) << " leftHandJointIndex" << hfmModel.leftHandJointIndex; qCDebug(modelformat) << " rightHandJointIndex" << hfmModel.rightHandJointIndex; diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index b33417666f..ff1b4fd01b 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -274,7 +274,6 @@ public: int rightEyeJointIndex = -1; int neckJointIndex = -1; int rootJointIndex = -1; - int leanJointIndex = -1; int headJointIndex = -1; int leftHandJointIndex = -1; int rightHandJointIndex = -1; From c959dd7024d0a7f4ef841b6884fd945ed3ccaaab Mon Sep 17 00:00:00 2001 From: birarda Date: Mon, 3 Dec 2018 14:56:46 -0800 Subject: [PATCH 083/117] release avatar entity and traits locks sooner to avoid deadlock --- libraries/avatars/src/AvatarData.cpp | 38 ++++++++++++------- libraries/avatars/src/ClientTraitsHandler.cpp | 17 ++++++--- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index d9d4b57c31..d4357fac49 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2832,35 +2832,47 @@ void AvatarData::setAvatarEntityData(const AvatarEntityMap& avatarEntityData) { qCDebug(avatars) << "discard suspect AvatarEntityData with size =" << avatarEntityData.size(); return; } + + std::vector deletedEntityIDs; + QList updatedEntityIDs; + _avatarEntitiesLock.withWriteLock([&] { if (_avatarEntityData != avatarEntityData) { + // keep track of entities that were attached to this avatar but no longer are AvatarEntityIDs previousAvatarEntityIDs = QSet::fromList(_avatarEntityData.keys()); _avatarEntityData = avatarEntityData; setAvatarEntityDataChanged(true); + deletedEntityIDs.reserve(previousAvatarEntityIDs.size()); + foreach (auto entityID, previousAvatarEntityIDs) { if (!_avatarEntityData.contains(entityID)) { _avatarEntityDetached.insert(entityID); - - if (_clientTraitsHandler) { - // we have a client traits handler, so we flag this removed entity as deleted - // so that changes are sent next frame - _clientTraitsHandler->markInstancedTraitDeleted(AvatarTraits::AvatarEntity, entityID); - } + deletedEntityIDs.push_back(entityID); } } - if (_clientTraitsHandler) { - // if we have a client traits handler, flag any updated or created entities - // so that we send changes for them next frame - foreach (auto entityID, _avatarEntityData.keys()) { - _clientTraitsHandler->markInstancedTraitUpdated(AvatarTraits::AvatarEntity, entityID); - } - } + updatedEntityIDs = _avatarEntityData.keys(); } }); + + if (_clientTraitsHandler) { + // we have a client traits handler + + // flag removed entities as deleted so that changes are sent next frame + for (auto& deletedEntityID : deletedEntityIDs) { + _clientTraitsHandler->markInstancedTraitDeleted(AvatarTraits::AvatarEntity, deletedEntityID); + } + + // flag any updated or created entities so that we send changes for them next frame + for (auto& entityID : updatedEntityIDs) { + _clientTraitsHandler->markInstancedTraitUpdated(AvatarTraits::AvatarEntity, entityID); + } + } + + } AvatarEntityIDs AvatarData::getAndClearRecentlyDetachedIDs() { diff --git a/libraries/avatars/src/ClientTraitsHandler.cpp b/libraries/avatars/src/ClientTraitsHandler.cpp index a301341a8e..cbc8e93745 100644 --- a/libraries/avatars/src/ClientTraitsHandler.cpp +++ b/libraries/avatars/src/ClientTraitsHandler.cpp @@ -66,7 +66,7 @@ void ClientTraitsHandler::resetForNewMixer() { } void ClientTraitsHandler::sendChangedTraitsToMixer() { - Lock lock(_traitLock); + std::unique_lock lock(_traitLock); if (hasChangedTraits() || _shouldPerformInitialSend) { // we have at least one changed trait to send @@ -90,6 +90,14 @@ void ClientTraitsHandler::sendChangedTraitsToMixer() { _traitStatuses.reset(); _hasChangedTraits = false; + // if this was an initial send of all traits, consider it completed + bool initialSend = _shouldPerformInitialSend; + _shouldPerformInitialSend = false; + + // we can release the lock here since we've taken a copy of statuses + // and will setup the packet using the information in the copy + lock.unlock(); + auto simpleIt = traitStatusesCopy.simpleCBegin(); while (simpleIt != traitStatusesCopy.simpleCEnd()) { // because the vector contains all trait types (for access using trait type as index) @@ -111,12 +119,12 @@ void ClientTraitsHandler::sendChangedTraitsToMixer() { auto instancedIt = traitStatusesCopy.instancedCBegin(); while (instancedIt != traitStatusesCopy.instancedCEnd()) { for (auto& instanceIDValuePair : instancedIt->instances) { - if ((_shouldPerformInitialSend && instanceIDValuePair.value != Deleted) + if ((initialSend && instanceIDValuePair.value != Deleted) || instanceIDValuePair.value == Updated) { // this is a changed trait we need to send or we haven't send out trait information yet // ask the owning avatar to pack it _owningAvatar->packTraitInstance(instancedIt->traitType, instanceIDValuePair.id, *traitsPacketList); - } else if (!_shouldPerformInitialSend && instanceIDValuePair.value == Deleted) { + } else if (!initialSend && instanceIDValuePair.value == Deleted) { // pack delete for this trait instance AvatarTraits::packInstancedTraitDelete(instancedIt->traitType, instanceIDValuePair.id, *traitsPacketList); @@ -127,9 +135,6 @@ void ClientTraitsHandler::sendChangedTraitsToMixer() { } nodeList->sendPacketList(std::move(traitsPacketList), *avatarMixer); - - // if this was an initial send of all traits, consider it completed - _shouldPerformInitialSend = false; } } From ab184c5c2b7adadeb42c4e8c390e8b6cc5e69797 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 3 Dec 2018 15:16:06 -0800 Subject: [PATCH 084/117] Authorized Script to Coupon --- .../commerce/common/sendAsset/SendAsset.qml | 126 +++++++++--------- .../common/sendAsset/images/coupon.svg | 10 ++ 2 files changed, 73 insertions(+), 63 deletions(-) create mode 100644 interface/resources/qml/hifi/commerce/common/sendAsset/images/coupon.svg diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index 36113077f5..7c2116f77b 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -36,7 +36,7 @@ Item { property bool isCurrentlySendingAsset: false; property string assetName: ""; property string assetCertID: ""; - property string secret: ""; + property string couponID: ""; property string authorizationID: ""; property string sendingPubliclyEffectImage; property var http; @@ -120,9 +120,9 @@ Item { if (result.status === 'success') { root.authorizationID = result.data.authorization_id; authorizationIDText.text = root.authorizationID; - root.secret = result.data.secret; - secretText.text = root.secret - if (scriptSecretTextField.text !== root.secret) { + root.couponID = result.data.secret; + couponIDText.text = root.couponID + if (couponIDTextField.text !== root.couponID) { console.log("SendAsset: Returned secret doesn't match client-generated secret!"); } root.nextActiveView = 'paymentSuccess'; @@ -394,7 +394,7 @@ Item { } Item { - id: authorizedScriptButton; + id: createCouponButton; // Anchors anchors.top: nearbyButton.bottom; anchors.topMargin: 32; @@ -404,7 +404,7 @@ Item { Image { anchors.top: parent.top; - source: "./images/nearby.svg"; + source: "./images/coupon.svg"; height: 70; width: parent.width; fillMode: Image.PreserveAspectFit; @@ -414,7 +414,7 @@ Item { } RalewaySemiBold { - text: "Authorized Script"; + text: "Create Coupon"; // Anchors anchors.bottom: parent.bottom; height: 15; @@ -429,9 +429,9 @@ Item { MouseArea { anchors.fill: parent; onClicked: { - sendAssetStep.referrer = "authorizedScript"; + sendAssetStep.referrer = "createCoupon"; sendAssetStep.selectedRecipientNodeID = ""; - scriptSecretTextField.text = generateRandomSecret(); + couponIDTextField.text = generateRandomCouponID(); root.nextActiveView = "sendAssetStep"; } @@ -928,7 +928,7 @@ Item { id: sendAssetStep; z: 996; - property string referrer; // either "connections", "nearby", "payIn", or "authorizedScript" + property string referrer; // either "connections", "nearby", "payIn", or "createCoupon" property string selectedRecipientNodeID; property string selectedRecipientDisplayName; property string selectedRecipientUserName; @@ -940,7 +940,7 @@ Item { RalewaySemiBold { id: sendAssetText_sendAssetStep; - text: ((sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "authorizedScript") && + text: ((sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "createCoupon") && root.assetCertID !== "") ? "Send \"" + root.assetName + "\":" : (root.assetCertID === "" ? "Send Money To:" : "Gift \"" + root.assetName + "\" To:"); // Anchors @@ -970,7 +970,7 @@ Item { RalewaySemiBold { id: sendToText_sendAssetStep; - text: sendAssetStep.referrer === "authorizedScript" ? "Script Secret:" : + text: sendAssetStep.referrer === "createCoupon" ? "Coupon ID:" : (root.assetCertID === "" || sendAssetStep.referrer === "payIn") ? "Send to:" : "Gift to:"; // Anchors anchors.top: parent.top; @@ -985,7 +985,7 @@ Item { } RecipientDisplay { - visible: sendAssetStep.referrer !== "authorizedScript"; + visible: sendAssetStep.referrer !== "createCoupon"; anchors.top: parent.top; anchors.left: sendToText_sendAssetStep.right; anchors.leftMargin: 16; @@ -1002,15 +1002,15 @@ Item { } Item { - id: scriptSecretContainer; - visible: sendAssetStep.referrer === "authorizedScript"; + id: couponIDContainer; + visible: sendAssetStep.referrer === "createCoupon"; anchors.top: parent.top; anchors.left: sendToText_sendAssetStep.right; anchors.right: parent.right; height: parent.height; RalewaySemiBold { - id: scriptSecretHelp; + id: couponIDHelp; text: "[?]"; // Anchors anchors.left: parent.left; @@ -1032,9 +1032,9 @@ Item { parent.color = hifi.colors.blueAccent; } onClicked: { - lightboxPopup.titleText = "Script Secret"; + lightboxPopup.titleText = "Coupon ID"; lightboxPopup.bodyText = "This alphanumeric text string will be used to ensure " + - "that only your scripts have access to the asset that you are sending. Keep it private!"; + "that only you can redeem the coupon for the asset that you are sending. Keep it private!"; lightboxPopup.button1text = "CLOSE"; lightboxPopup.button1method = function() { lightboxPopup.visible = false; @@ -1045,11 +1045,11 @@ Item { } HifiControlsUit.TextField { - id: scriptSecretTextField; + id: couponIDTextField; colorScheme: root.assetCertID === "" ? hifi.colorSchemes.dark : hifi.colorSchemes.light; // Anchors anchors.verticalCenter: parent.verticalCenter; - anchors.left: scriptSecretHelp.right; + anchors.left: couponIDHelp.right; anchors.leftMargin: 16; anchors.right: parent.right; height: 50; @@ -1073,7 +1073,7 @@ Item { height: 35; width: 100; text: "CHANGE"; - visible: sendAssetStep.referrer !== "payIn" && sendAssetStep.referrer !== "authorizedScript"; + visible: sendAssetStep.referrer !== "payIn" && sendAssetStep.referrer !== "createCoupon"; onClicked: { if (sendAssetStep.referrer === "connections") { root.nextActiveView = "chooseRecipientConnection"; @@ -1397,8 +1397,8 @@ Item { root.assetCertID, parseInt(amountTextField.text), optionalMessage.text); - } else if (sendAssetStep.referrer === "authorizedScript") { - Commerce.authorizeAssetTransfer(scriptSecretTextField.text || "", + } else if (sendAssetStep.referrer === "createCoupon") { + Commerce.authorizeAssetTransfer(couponIDTextField.text || "", root.assetCertID, parseInt(amountTextField.text) || 1, optionalMessage.text) @@ -1474,22 +1474,22 @@ Item { Rectangle { anchors.top: parent.top; anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 125; + sendAssetStep.referrer === "createCoupon" ? 15 : 125; anchors.left: parent.left; anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 50; + sendAssetStep.referrer === "createCoupon" ? 15 : 50; anchors.right: parent.right; anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 50; + sendAssetStep.referrer === "createCoupon" ? 15 : 50; anchors.bottom: parent.bottom; anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 125; + sendAssetStep.referrer === "createCoupon" ? 15 : 125; color: "#FFFFFF"; RalewaySemiBold { id: paymentSentText; - text: root.assetCertID === "" ? (sendAssetStep.referrer === "authorizedScript" ? "Payment Authorized" : "Payment Sent") : - (sendAssetStep.referrer === "authorizedScript" ? "Item Transfer Authorized" : + text: root.assetCertID === "" ? (sendAssetStep.referrer === "createCoupon" ? "Payment Authorized" : "Payment Sent") : + (sendAssetStep.referrer === "createCoupon" ? "Item Transfer Authorized" : (sendAssetStep.referrer === "payIn" ? "Item Sent" : "Gift Sent")); // Anchors anchors.top: parent.top; @@ -1528,7 +1528,7 @@ Item { onClicked: { if (sendAssetStep.referrer === "payIn") { sendToScript({method: "closeSendAsset"}); - } else if (sendAssetStep.referrer === "authorizedScript") { + } else if (sendAssetStep.referrer === "createCoupon") { showDidYouCopyLightbox(); } else { root.nextActiveView = "sendAssetHome"; @@ -1553,7 +1553,7 @@ Item { Item { id: sendToScriptContainer_paymentSuccess; - visible: sendAssetStep.referrer === "authorizedScript"; + visible: sendAssetStep.referrer === "createCoupon"; anchors.top: parent.top; anchors.left: parent.left; anchors.right: parent.right; @@ -1620,11 +1620,11 @@ Item { } RalewaySemiBold { - id: secretLabel; - text: "Secret:"; + id: couponIDLabel; + text: "Coupon ID:"; // Anchors anchors.left: parent.left; - anchors.top: secretText.top; + anchors.top: couponIDText.top; width: authorizationIDLabel.width; // Text size size: 18; @@ -1634,13 +1634,13 @@ Item { } RalewayRegular { - id: secretText; - text: root.secret; + id: couponIDText; + text: root.couponID; anchors.top: authorizationIDText.bottom; anchors.topMargin: 16; - anchors.left: secretLabel.right; + anchors.left: couponIDLabel.right; anchors.leftMargin: 16; - anchors.right: secretClipboardButton.left; + anchors.right: couponIDClipboardButton.left; anchors.rightMargin: 16; // Text size size: 18; @@ -1652,31 +1652,31 @@ Item { } Image { - id: secretClipboardButton; + id: couponIDClipboardButton; source: "images/clipboard.svg"; // clipboard by Bieutuong Bon from the Noun Project fillMode: Image.PreserveAspectFit; // Anchors anchors.right: parent.right; - anchors.top: secretText.top; + anchors.top: couponIDText.top; height: 40; width: height; MouseArea { anchors.fill: parent; onClicked: { - Window.copyToClipboard(root.secret); - secretText.text = "Copied to Clipboard!\n"; - secretClipboardTimer.start(); + Window.copyToClipboard(root.couponID); + couponIDText.text = "Copied to Clipboard!\n"; + couponIDClipboardTimer.start(); } } } Timer { - id: secretClipboardTimer; + id: couponIDClipboardTimer; interval: 2000; repeat: false; onTriggered: { - secretText.text = root.secret; + couponIDText.text = root.couponID; } } } @@ -1733,7 +1733,7 @@ Item { RalewaySemiBold { id: gift_paymentSuccess; - text: sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "authorizedScript" ? + text: sendAssetStep.referrer === "payIn" || sendAssetStep.referrer === "createCoupon" ? "Item:" : "Gift:"; // Anchors anchors.top: parent.top; @@ -1852,7 +1852,7 @@ Item { onClicked: { if (sendAssetStep.referrer === "payIn") { sendToScript({method: "closeSendAsset"}); - } else if (sendAssetStep.referrer === "authorizedScript") { + } else if (sendAssetStep.referrer === "createCoupon") { showDidYouCopyLightbox(); } else { root.nextActiveView = "sendAssetHome"; @@ -1888,16 +1888,16 @@ Item { Rectangle { anchors.top: parent.top; anchors.topMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 150; + sendAssetStep.referrer === "createCoupon" ? 15 : 150; anchors.left: parent.left; anchors.leftMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 50; + sendAssetStep.referrer === "createCoupon" ? 15 : 50; anchors.right: parent.right; anchors.rightMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 50; + sendAssetStep.referrer === "createCoupon" ? 15 : 50; anchors.bottom: parent.bottom; anchors.bottomMargin: root.assetCertID === "" || sendAssetStep.referrer === "payIn" || - sendAssetStep.referrer === "authorizedScript" ? 15 : 300; + sendAssetStep.referrer === "createCoupon" ? 15 : 300; color: "#FFFFFF"; RalewaySemiBold { @@ -1949,7 +1949,7 @@ Item { RalewaySemiBold { id: paymentFailureDetailText; - text: sendAssetStep.referrer === "authorizedScript" ? "The server was unable to handle your request. Please try again later." : + text: sendAssetStep.referrer === "createCoupon" ? "The server was unable to handle your request. Please try again later." : ("The recipient you specified was unable to receive your " + (root.assetCertID === "" ? "payment." : (sendAssetStep.referrer === "payIn" ? "item." : "gift."))); anchors.top: paymentFailureText.bottom; @@ -1970,7 +1970,7 @@ Item { Item { id: sendToContainer_paymentFailure; visible: (root.assetCertID === "" || sendAssetStep.referrer === "payIn") && - sendAssetStep.referrer !== "authorizedScript"; + sendAssetStep.referrer !== "createCoupon"; anchors.top: paymentFailureDetailText.bottom; anchors.topMargin: 8; anchors.left: parent.left; @@ -2134,8 +2134,8 @@ Item { root.assetCertID, parseInt(amountTextField.text), optionalMessage.text); - } else if (sendAssetStep.referrer === "authorizedScript") { - Commerce.authorizeAssetTransfer(scriptSecretTextField.text || "", + } else if (sendAssetStep.referrer === "createCoupon") { + Commerce.authorizeAssetTransfer(couponIDTextField.text || "", root.assetCertID, parseInt(amountTextField.text) || 1, optionalMessage.text) @@ -2167,22 +2167,22 @@ Item { sendAssetStep.referrer = ""; } - function generateRandomSecret() { - var RANDOM_SECRET_LENGTH = 25; - var randomSecret = ""; + function generateRandomCouponID() { + var RANDOM_COUPON_ID_LENGTH = 25; + var randomCouponID = ""; var possibleCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - for (var i = 0; i < RANDOM_SECRET_LENGTH; i++) { - randomSecret += possibleCharacters.charAt(Math.floor(Math.random() * possibleCharacters.length)); + for (var i = 0; i < RANDOM_COUPON_ID_LENGTH; i++) { + randomCouponID += possibleCharacters.charAt(Math.floor(Math.random() * possibleCharacters.length)); } - return randomSecret; + return randomCouponID; } function showDidYouCopyLightbox() { lightboxPopup.titleText = "Close Confirmation"; - lightboxPopup.bodyText = "Did you copy your Authorization ID and your Script Secret?\n\n" + - "You won't be able to see your Authorization ID or your Script Secret once " + + lightboxPopup.bodyText = "Did you copy your Authorization ID and your Coupon ID?\n\n" + + "You won't be able to see your Authorization ID or your Coupon ID once " + "you close this window."; lightboxPopup.button1text = "GO BACK"; lightboxPopup.button1method = function() { diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/images/coupon.svg b/interface/resources/qml/hifi/commerce/common/sendAsset/images/coupon.svg new file mode 100644 index 0000000000..2b7c052589 --- /dev/null +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/images/coupon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + From 9315c546d3ac9cfb611e56d12918290649fbb56c Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 3 Dec 2018 16:26:47 -0800 Subject: [PATCH 085/117] Initial version - move updateJoints() to derived class --- .../src/avatars-renderer/Avatar.cpp | 28 ++++++++++++++++++ .../src/avatars-renderer/Avatar.h | 3 ++ libraries/avatars/src/AvatarData.cpp | 29 ++----------------- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index fceb146470..99eb08949b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1894,6 +1894,34 @@ QList Avatar::getSkeleton() { return QList(); } +void Avatar::updateJointMappings() { + { + QWriteLocker writeLock(&_jointDataLock); + _fstJointIndices.clear(); + _fstJointNames.clear(); + _jointData.clear(); + } + + //if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) { + // //// + // // TODO: Should we rely upon HTTPResourceRequest for ResourceRequestObserver instead? + // // HTTPResourceRequest::doSend() covers all of the following and + // // then some. It doesn't cover the connect() call, so we may + // // want to add a HTTPResourceRequest::doSend() method that does + // // connects. + // QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + // QNetworkRequest networkRequest = QNetworkRequest(_skeletonModelURL); + // networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + // networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + // DependencyManager::get()->update( + // _skeletonModelURL, -1, "AvatarData::updateJointMappings"); + // QNetworkReply* networkReply = networkAccessManager.get(networkRequest); + // // + // //// + // connect(networkReply, &QNetworkReply::finished, this, &AvatarData::setJointMappingsFromNetworkReply); + //} +} + void Avatar::addToScene(AvatarSharedPointer myHandle, const render::ScenePointer& scene) { if (scene) { auto nodelist = DependencyManager::get(); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 8f70b12122..d577ab35bf 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -516,6 +516,9 @@ protected: mutable QReadWriteLock _modelJointIndicesCacheLock; mutable bool _modelJointsCached { false }; + /// Loads the joint indices, names from the FST file (if any) + virtual void updateJointMappings() override; + glm::vec3 _skeletonOffset; std::vector> _attachmentModels; std::vector _attachmentModelsTexturesLoaded; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index d9d4b57c31..a369ea9a24 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2209,33 +2209,8 @@ void AvatarData::sendIdentityPacket() { _identityDataChanged = false; } -void AvatarData::updateJointMappings() { - { - QWriteLocker writeLock(&_jointDataLock); - _fstJointIndices.clear(); - _fstJointNames.clear(); - _jointData.clear(); - } - - if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) { - //// - // TODO: Should we rely upon HTTPResourceRequest for ResourceRequestObserver instead? - // HTTPResourceRequest::doSend() covers all of the following and - // then some. It doesn't cover the connect() call, so we may - // want to add a HTTPResourceRequest::doSend() method that does - // connects. - QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - QNetworkRequest networkRequest = QNetworkRequest(_skeletonModelURL); - networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); - networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); - DependencyManager::get()->update( - _skeletonModelURL, -1, "AvatarData::updateJointMappings"); - QNetworkReply* networkReply = networkAccessManager.get(networkRequest); - // - //// - connect(networkReply, &QNetworkReply::finished, this, &AvatarData::setJointMappingsFromNetworkReply); - } -} +void AvatarData::updateJointMappings() +{ } static const QString JSON_ATTACHMENT_URL = QStringLiteral("modelUrl"); static const QString JSON_ATTACHMENT_JOINT_NAME = QStringLiteral("jointName"); From 541d0ab4d689b2cc50eecb00128210480576105b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 3 Dec 2018 17:33:04 -0800 Subject: [PATCH 086/117] work around menu-item name hash collision for Home --- interface/src/Menu.h | 2 +- libraries/ui/src/ui/Menu.h | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/interface/src/Menu.h b/interface/src/Menu.h index e0e48ff32c..7168b7294e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -117,7 +117,7 @@ namespace MenuOption { const QString FrameTimer = "Show Timer"; const QString FullscreenMirror = "Mirror"; const QString Help = "Help..."; - const QString HomeLocation = "Home"; + const QString HomeLocation = "Home "; const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IndependentMode = "Independent Mode"; const QString ActionMotorControl = "Enable Default Motor Control"; diff --git a/libraries/ui/src/ui/Menu.h b/libraries/ui/src/ui/Menu.h index 2977a5330a..ec286b29ad 100644 --- a/libraries/ui/src/ui/Menu.h +++ b/libraries/ui/src/ui/Menu.h @@ -146,6 +146,11 @@ protected: int findPositionOfMenuItem(MenuWrapper* menu, const QString& searchMenuItem); int positionBeforeSeparatorIfNeeded(MenuWrapper* menu, int requestedPosition); + // There is a design flaw here -- _actionHash is system-wide and hashes the names of menu-items to their + // QActions. The path (parent submenu name etc) isn't included in the hash key. This generally works, + // but we add "Home" twice -- once for "go home" and once for "set startup location to home". Anytime + // a user bookmarks a place and gives it a name like an existing menu-item, something will go wrong. + // TODO: change the js api to require the full path when referring to a specific menu item. QHash _actionHash; bool isValidGrouping(const QString& grouping) const { return grouping == "Advanced" || grouping == "Developer"; } From eb097af79617216c97806c59d3507e9ccd154d9d Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 3 Dec 2018 17:42:39 -0800 Subject: [PATCH 087/117] Remove all .fst downloads from AvatarData and its derived classes --- .../src/avatars/ScriptableAvatar.cpp | 4 -- .../src/avatars-renderer/Avatar.cpp | 28 ---------- .../src/avatars-renderer/Avatar.h | 3 - libraries/avatars/src/AvatarData.cpp | 56 ------------------- libraries/avatars/src/AvatarData.h | 9 --- 5 files changed, 100 deletions(-) diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 51038a782f..392e9960e0 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -77,10 +77,6 @@ static AnimPose composeAnimPose(const HFMJoint& joint, const glm::quat rotation, } void ScriptableAvatar::update(float deltatime) { - if (_bind.isNull() && !_skeletonFBXURL.isEmpty()) { // AvatarData will parse the .fst, but not get the .fbx skeleton. - _bind = DependencyManager::get()->getAnimation(_skeletonFBXURL); - } - // Run animation if (_animation && _animation->isLoaded() && _animation->getFrames().size() > 0 && !_bind.isNull() && _bind->isLoaded()) { if (!_animSkeleton) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 99eb08949b..fceb146470 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1894,34 +1894,6 @@ QList Avatar::getSkeleton() { return QList(); } -void Avatar::updateJointMappings() { - { - QWriteLocker writeLock(&_jointDataLock); - _fstJointIndices.clear(); - _fstJointNames.clear(); - _jointData.clear(); - } - - //if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) { - // //// - // // TODO: Should we rely upon HTTPResourceRequest for ResourceRequestObserver instead? - // // HTTPResourceRequest::doSend() covers all of the following and - // // then some. It doesn't cover the connect() call, so we may - // // want to add a HTTPResourceRequest::doSend() method that does - // // connects. - // QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - // QNetworkRequest networkRequest = QNetworkRequest(_skeletonModelURL); - // networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); - // networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); - // DependencyManager::get()->update( - // _skeletonModelURL, -1, "AvatarData::updateJointMappings"); - // QNetworkReply* networkReply = networkAccessManager.get(networkRequest); - // // - // //// - // connect(networkReply, &QNetworkReply::finished, this, &AvatarData::setJointMappingsFromNetworkReply); - //} -} - void Avatar::addToScene(AvatarSharedPointer myHandle, const render::ScenePointer& scene) { if (scene) { auto nodelist = DependencyManager::get(); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index d577ab35bf..8f70b12122 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -516,9 +516,6 @@ protected: mutable QReadWriteLock _modelJointIndicesCacheLock; mutable bool _modelJointsCached { false }; - /// Loads the joint indices, names from the FST file (if any) - virtual void updateJointMappings() override; - glm::vec3 _skeletonOffset; std::vector> _attachmentModels; std::vector _attachmentModelsTexturesLoaded; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index a369ea9a24..420fa125e7 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2000,8 +2000,6 @@ void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) { _skeletonModelURL = expanded; - updateJointMappings(); - if (_clientTraitsHandler) { _clientTraitsHandler->markTraitUpdated(AvatarTraits::SkeletonModelURL); } @@ -2097,57 +2095,6 @@ void AvatarData::detachAll(const QString& modelURL, const QString& jointName) { setAttachmentData(attachmentData); } -void AvatarData::setJointMappingsFromNetworkReply() { - - QNetworkReply* networkReply = static_cast(sender()); - - // before we process this update, make sure that the skeleton model URL hasn't changed - // since we made the FST request - if (networkReply->url() != _skeletonModelURL) { - qCDebug(avatars) << "Refusing to set joint mappings for FST URL that does not match the current URL"; - return; - } - - { - QWriteLocker writeLock(&_jointDataLock); - QByteArray line; - while (!(line = networkReply->readLine()).isEmpty()) { - line = line.trimmed(); - if (line.startsWith("filename")) { - int filenameIndex = line.indexOf('=') + 1; - if (filenameIndex > 0) { - _skeletonFBXURL = _skeletonModelURL.resolved(QString(line.mid(filenameIndex).trimmed())); - } - } - if (!line.startsWith("jointIndex")) { - continue; - } - int jointNameIndex = line.indexOf('=') + 1; - if (jointNameIndex == 0) { - continue; - } - int secondSeparatorIndex = line.indexOf('=', jointNameIndex); - if (secondSeparatorIndex == -1) { - continue; - } - QString jointName = line.mid(jointNameIndex, secondSeparatorIndex - jointNameIndex).trimmed(); - bool ok; - int jointIndex = line.mid(secondSeparatorIndex + 1).trimmed().toInt(&ok); - if (ok) { - while (_fstJointNames.size() < jointIndex + 1) { - _fstJointNames.append(QString()); - } - _fstJointNames[jointIndex] = jointName; - } - } - for (int i = 0; i < _fstJointNames.size(); i++) { - _fstJointIndices.insert(_fstJointNames.at(i), i + 1); - } - } - - networkReply->deleteLater(); -} - void AvatarData::sendAvatarDataPacket(bool sendAll) { auto nodeList = DependencyManager::get(); @@ -2209,9 +2156,6 @@ void AvatarData::sendIdentityPacket() { _identityDataChanged = false; } -void AvatarData::updateJointMappings() -{ } - static const QString JSON_ATTACHMENT_URL = QStringLiteral("modelUrl"); static const QString JSON_ATTACHMENT_JOINT_NAME = QStringLiteral("jointName"); static const QString JSON_ATTACHMENT_TRANSFORM = QStringLiteral("transform"); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 36c6ed6c50..c3819d0d28 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1269,11 +1269,6 @@ public slots: */ void sendIdentityPacket(); - /**jsdoc - * @function MyAvatar.setJointMappingsFromNetworkReply - */ - void setJointMappingsFromNetworkReply(); - /**jsdoc * @function MyAvatar.setSessionUUID * @param {Uuid} sessionUUID @@ -1376,7 +1371,6 @@ protected: mutable HeadData* _headData { nullptr }; QUrl _skeletonModelURL; - QUrl _skeletonFBXURL; QVector _attachmentData; QVector _oldAttachmentData; QString _displayName; @@ -1390,9 +1384,6 @@ protected: QWeakPointer _owningAvatarMixer; - /// Loads the joint indices, names from the FST file (if any) - virtual void updateJointMappings(); - glm::vec3 _targetVelocity; SimpleMovingAverage _averageBytesReceived; From 7f2e427584c469c47e071da5a7351210a3bca7fc Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Mon, 3 Dec 2018 18:56:45 -0800 Subject: [PATCH 088/117] Added DropAfterDelay strategy to Vive Tracker Calibration Dialog This is a hybrid of None and Drop strategies. Basically, if the puck is out of range for less then 1/2 a second we still use it, however any longer then that and we mark it as invalid. --- .../qml/hifi/tablet/OpenVrConfiguration.qml | 2 +- plugins/openvr/src/ViveControllerManager.cpp | 23 ++++++++++++++++++- plugins/openvr/src/ViveControllerManager.h | 5 +++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml index e18fdea444..4ce9fe7c84 100644 --- a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml +++ b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml @@ -871,7 +871,7 @@ Flickable { editable: true colorScheme: hifi.colorSchemes.dark - model: ["None", "Freeze", "Drop"] + model: ["None", "Freeze", "Drop", "DropAfterDelay"] label: "" onCurrentIndexChanged: { diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index af4f4da18c..ff1f10f8ed 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -138,6 +138,8 @@ static QString outOfRangeDataStrategyToString(ViveControllerManager::OutOfRangeD return "Freeze"; case ViveControllerManager::OutOfRangeDataStrategy::Drop: return "Drop"; + case ViveControllerManager::OutOfRangeDataStrategy::DropAfterDelay: + return "DropAfterDelay"; } } @@ -146,6 +148,8 @@ static ViveControllerManager::OutOfRangeDataStrategy stringToOutOfRangeDataStrat return ViveControllerManager::OutOfRangeDataStrategy::Drop; } else if (string == "Freeze") { return ViveControllerManager::OutOfRangeDataStrategy::Freeze; + } else if (string == "DropAfterDelay") { + return ViveControllerManager::OutOfRangeDataStrategy::DropAfterDelay; } else { return ViveControllerManager::OutOfRangeDataStrategy::None; } @@ -302,7 +306,7 @@ void ViveControllerManager::loadSettings() { if (_inputDevice) { const double DEFAULT_ARM_CIRCUMFERENCE = 0.33; const double DEFAULT_SHOULDER_WIDTH = 0.48; - const QString DEFAULT_OUT_OF_RANGE_STRATEGY = "Drop"; + const QString DEFAULT_OUT_OF_RANGE_STRATEGY = "DropAfterDelay"; _inputDevice->_armCircumference = settings.value("armCircumference", QVariant(DEFAULT_ARM_CIRCUMFERENCE)).toDouble(); _inputDevice->_shoulderWidth = settings.value("shoulderWidth", QVariant(DEFAULT_SHOULDER_WIDTH)).toDouble(); _inputDevice->_outOfRangeDataStrategy = stringToOutOfRangeDataStrategy(settings.value("outOfRangeDataStrategy", QVariant(DEFAULT_OUT_OF_RANGE_STRATEGY)).toString()); @@ -516,6 +520,7 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid && poseIndex <= controller::TRACKED_OBJECT_15) { + uint64_t now = usecTimestampNow(); controller::Pose pose; switch (_outOfRangeDataStrategy) { case OutOfRangeDataStrategy::Drop: @@ -544,6 +549,22 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde _nextSimPoseData.angularVelocities[deviceIndex] = _lastSimPoseData.angularVelocities[deviceIndex]; } break; + case OutOfRangeDataStrategy::DropAfterDelay: + const uint64_t DROP_DELAY_TIME = 500 * USECS_PER_MSEC; + + // All Running_OK results are valid. + if (_nextSimPoseData.vrPoses[deviceIndex].eTrackingResult == vr::TrackingResult_Running_OK) { + pose = buildPose(_nextSimPoseData.poses[deviceIndex], _nextSimPoseData.linearVelocities[deviceIndex], _nextSimPoseData.angularVelocities[deviceIndex]); + // update the timer + _simDataRunningOkTimestampMap[deviceIndex] = now; + } else if (now - _simDataRunningOkTimestampMap[deviceIndex] < DROP_DELAY_TIME) { + // report the pose, even though pose is out-of-range + pose = buildPose(_nextSimPoseData.poses[deviceIndex], _nextSimPoseData.linearVelocities[deviceIndex], _nextSimPoseData.angularVelocities[deviceIndex]); + } else { + // this pose has been out-of-range for too long. + pose.valid = false; + } + break; } if (pose.valid) { diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 647702ae77..dbd248dc53 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -63,7 +63,8 @@ public: enum class OutOfRangeDataStrategy { None, Freeze, - Drop + Drop, + DropAfterDelay }; private: @@ -205,6 +206,8 @@ private: bool _hmdTrackingEnabled { true }; + std::map _simDataRunningOkTimestampMap; + QString configToString(Config config); friend class ViveControllerManager; }; From f3236e0843299552dae90e535712088a36b81f3e Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 4 Dec 2018 10:45:32 -0800 Subject: [PATCH 089/117] Remove FST joint members from AvatarData --- libraries/avatars/src/AvatarData.cpp | 9 ++------- libraries/avatars/src/AvatarData.h | 11 +---------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 420fa125e7..8705c35630 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1776,16 +1776,11 @@ int AvatarData::getFauxJointIndex(const QString& name) const { int AvatarData::getJointIndex(const QString& name) const { int result = getFauxJointIndex(name); - if (result != -1) { - return result; - } - QReadLocker readLock(&_jointDataLock); - return _fstJointIndices.value(name) - 1; + return result; } QStringList AvatarData::getJointNames() const { - QReadLocker readLock(&_jointDataLock); - return _fstJointNames; + return QStringList(); } glm::quat AvatarData::getOrientationOutbound() const { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index c3819d0d28..49fd49df58 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1377,9 +1377,6 @@ protected: QString _sessionDisplayName { }; bool _lookAtSnappingEnabled { true }; - QHash _fstJointIndices; ///< 1-based, since zero is returned for missing keys - QStringList _fstJointNames; ///< in order of depth-first traversal - quint64 _errorLogExpiry; ///< time in future when to log an error QWeakPointer _owningAvatarMixer; @@ -1487,11 +1484,8 @@ protected: T readLockWithNamedJointIndex(const QString& name, const T& defaultValue, F f) const { int index = getFauxJointIndex(name); QReadLocker readLock(&_jointDataLock); - if (index == -1) { - index = _fstJointIndices.value(name) - 1; - } - // The first conditional is superfluous, but illsutrative + // The first conditional is superfluous, but illustrative if (index == -1 || index < _jointData.size()) { return defaultValue; } @@ -1508,9 +1502,6 @@ protected: void writeLockWithNamedJointIndex(const QString& name, F f) { int index = getFauxJointIndex(name); QWriteLocker writeLock(&_jointDataLock); - if (index == -1) { - index = _fstJointIndices.value(name) - 1; - } if (index == -1) { return; } From edab74caa46dd34d467bb3174f115f44705c1a61 Mon Sep 17 00:00:00 2001 From: amantley Date: Tue, 4 Dec 2018 16:20:46 -0800 Subject: [PATCH 090/117] mapped the model joint names to hifi compliant joint names in FBX serializer --- libraries/animation/src/AnimSkeleton.cpp | 41 ++++++------------- libraries/animation/src/AnimSkeleton.h | 3 +- .../src/avatars-renderer/Avatar.cpp | 7 ---- libraries/fbx/src/FBXSerializer.cpp | 37 +++++++++-------- libraries/hfm/src/hfm/HFM.h | 2 +- 5 files changed, 34 insertions(+), 56 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 36664a41fe..16c2c1cc7e 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -23,8 +23,6 @@ AnimSkeleton::AnimSkeleton(const HFMModel& hfmModel) { for (auto& joint : hfmModel.joints) { joints.push_back(joint); } - - _fbxToHifiJointNameMapping = hfmModel.fbxToHifiJointNameMapping; buildSkeletonFromJoints(joints, hfmModel.jointRotationOffsets); // we make a copy of the inverseBindMatrices in order to prevent mutating the model bind pose @@ -61,14 +59,8 @@ AnimSkeleton::AnimSkeleton(const std::vector& joints, const QMap AnimSkeleton::getChildrenOfJoint(int jointIndex) const { return result; } -const QString AnimSkeleton::getJointName(int jointIndex) const { - - QString jointName = _joints[jointIndex].name; - if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { - jointName = _fbxToHifiJointNameMapping.key(jointName); - } - return jointName; +const QString& AnimSkeleton::getJointName(int jointIndex) const { + return _joints[jointIndex].name; } AnimPose AnimSkeleton::getAbsolutePose(int jointIndex, const AnimPoseVec& relativePoses) const { @@ -258,25 +245,21 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints, _nonMirroredIndices.clear(); _mirrorMap.reserve(_jointsSize); for (int i = 0; i < _jointsSize; i++) { - QString jointName = _joints[i].name; - if (_fbxToHifiJointNameMapping.contains(_fbxToHifiJointNameMapping.key(jointName))) { - jointName = _fbxToHifiJointNameMapping.key(jointName); - } - if (jointName != "Hips" && jointName != "Spine" && - jointName != "Spine1" && jointName != "Spine2" && - jointName != "Neck" && jointName != "Head" && - !((jointName.startsWith("Left") || jointName.startsWith("Right")) && - jointName != "LeftEye" && jointName != "RightEye")) { + if (_joints[i].name != "Hips" && _joints[i].name != "Spine" && + _joints[i].name != "Spine1" && _joints[i].name != "Spine2" && + _joints[i].name != "Neck" && _joints[i].name != "Head" && + !((_joints[i].name.startsWith("Left") || _joints[i].name.startsWith("Right")) && + _joints[i].name != "LeftEye" && _joints[i].name != "RightEye")) { // HACK: we don't want to mirror some joints so we remember their indices // so we can restore them after a future mirror operation _nonMirroredIndices.push_back(i); } int mirrorJointIndex = -1; - if (jointName.startsWith("Left")) { - QString mirrorJointName = QString(jointName).replace(0, 4, "Right"); + if (_joints[i].name.startsWith("Left")) { + QString mirrorJointName = QString(_joints[i].name).replace(0, 4, "Right"); mirrorJointIndex = nameToJointIndex(mirrorJointName); - } else if (jointName.startsWith("Right")) { - QString mirrorJointName = QString(jointName).replace(0, 5, "Left"); + } else if (_joints[i].name.startsWith("Right")) { + QString mirrorJointName = QString(_joints[i].name).replace(0, 5, "Left"); mirrorJointIndex = nameToJointIndex(mirrorJointName); } if (mirrorJointIndex >= 0) { diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index 777cb61302..14f39eedbc 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -27,7 +27,7 @@ public: explicit AnimSkeleton(const std::vector& joints, const QMap jointOffsets); int nameToJointIndex(const QString& jointName) const; - const QString getJointName(int jointIndex) const; + const QString& getJointName(int jointIndex) const; int getNumJoints() const; int getChainDepth(int jointIndex) const; @@ -79,7 +79,6 @@ protected: std::vector _mirrorMap; QHash _jointIndicesByName; std::vector> _clusterBindMatrixOriginalValues; - QMap _fbxToHifiJointNameMapping; // no copies AnimSkeleton(const AnimSkeleton&) = delete; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index f3017049a7..fceb146470 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1437,13 +1437,6 @@ int Avatar::getJointIndex(const QString& name) const { withValidJointIndicesCache([&]() { if (_modelJointIndicesCache.contains(name)) { result = _modelJointIndicesCache[name] - 1; - } else { - // doesn't contain name. check the fbx-to-hifi joint name mapping - if (_skeletonModel && _skeletonModel->isActive()) { - if (_modelJointIndicesCache.contains(_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name])) { - result = _modelJointIndicesCache[_skeletonModel->getHFMModel().fbxToHifiJointNameMapping[name]] - 1; - } - } } }); return result; diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/fbx/src/FBXSerializer.cpp index cfdf596b98..1581204819 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -419,15 +419,15 @@ QByteArray fileOnUrl(const QByteArray& filepath, const QString& url) { QMap getJointNameMapping(const QVariantHash& mapping) { static const QString JOINT_NAME_MAPPING_FIELD = "jointMap"; - QMap fbxToHifiJointNameMap; + QMap hfmToHifiJointNameMap; if (!mapping.isEmpty() && mapping.contains(JOINT_NAME_MAPPING_FIELD) && mapping[JOINT_NAME_MAPPING_FIELD].type() == QVariant::Hash) { auto jointNames = mapping[JOINT_NAME_MAPPING_FIELD].toHash(); for (auto itr = jointNames.begin(); itr != jointNames.end(); itr++) { - fbxToHifiJointNameMap.insert(itr.key(), itr.value().toString()); - qCDebug(modelformat) << "the mapped key " << itr.key() << " has a value of " << fbxToHifiJointNameMap[itr.key()]; + hfmToHifiJointNameMap.insert(itr.key(), itr.value().toString()); + qCDebug(modelformat) << "the mapped key " << itr.key() << " has a value of " << hfmToHifiJointNameMap[itr.key()]; } } - return fbxToHifiJointNameMap; + return hfmToHifiJointNameMap; } QMap getJointRotationOffsets(const QVariantHash& mapping) { @@ -530,8 +530,8 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr HFMModel& hfmModel = *hfmModelPtr; hfmModel.originalURL = url; - hfmModel.fbxToHifiJointNameMapping.clear(); - hfmModel.fbxToHifiJointNameMapping = getJointNameMapping(mapping); + hfmModel.hfmToHifiJointNameMapping.clear(); + hfmModel.hfmToHifiJointNameMapping = getJointNameMapping(mapping); float unitScaleFactor = 1.0f; glm::vec3 ambientColor; @@ -600,31 +600,31 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr hifiGlobalNodeID = id; } - if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye" || (hfmModel.fbxToHifiJointNameMapping.contains(jointEyeLeftName) && (name == hfmModel.fbxToHifiJointNameMapping[jointEyeLeftName]))) { + if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye" || (hfmModel.hfmToHifiJointNameMapping.contains(jointEyeLeftName) && (name == hfmModel.hfmToHifiJointNameMapping[jointEyeLeftName]))) { jointEyeLeftID = getID(object.properties); - } else if (name == jointEyeRightName || name == "EyeR" || name == "joint_Reye" || (hfmModel.fbxToHifiJointNameMapping.contains(jointEyeRightName) && (name == hfmModel.fbxToHifiJointNameMapping[jointEyeRightName]))) { + } else if (name == jointEyeRightName || name == "EyeR" || name == "joint_Reye" || (hfmModel.hfmToHifiJointNameMapping.contains(jointEyeRightName) && (name == hfmModel.hfmToHifiJointNameMapping[jointEyeRightName]))) { jointEyeRightID = getID(object.properties); - } else if (name == jointNeckName || name == "NeckRot" || name == "joint_neck" || (hfmModel.fbxToHifiJointNameMapping.contains(jointNeckName) && (name == hfmModel.fbxToHifiJointNameMapping[jointNeckName]))) { + } else if (name == jointNeckName || name == "NeckRot" || name == "joint_neck" || (hfmModel.hfmToHifiJointNameMapping.contains(jointNeckName) && (name == hfmModel.hfmToHifiJointNameMapping[jointNeckName]))) { jointNeckID = getID(object.properties); - } else if (name == jointRootName || (hfmModel.fbxToHifiJointNameMapping.contains(jointRootName) && (name == hfmModel.fbxToHifiJointNameMapping[jointRootName]))) { + } else if (name == jointRootName || (hfmModel.hfmToHifiJointNameMapping.contains(jointRootName) && (name == hfmModel.hfmToHifiJointNameMapping[jointRootName]))) { jointRootID = getID(object.properties); - } else if ((name == jointHeadName) || (hfmModel.fbxToHifiJointNameMapping.contains(jointHeadName) && (name == hfmModel.fbxToHifiJointNameMapping[jointHeadName]))) { + } else if ((name == jointHeadName) || (hfmModel.hfmToHifiJointNameMapping.contains(jointHeadName) && (name == hfmModel.hfmToHifiJointNameMapping[jointHeadName]))) { jointHeadID = getID(object.properties); - } else if (name == jointLeftHandName || name == "LeftHand" || name == "joint_L_hand" || (hfmModel.fbxToHifiJointNameMapping.contains(jointLeftHandName) && (name == hfmModel.fbxToHifiJointNameMapping[jointLeftHandName]))) { + } else if (name == jointLeftHandName || name == "LeftHand" || name == "joint_L_hand" || (hfmModel.hfmToHifiJointNameMapping.contains(jointLeftHandName) && (name == hfmModel.hfmToHifiJointNameMapping[jointLeftHandName]))) { jointLeftHandID = getID(object.properties); - } else if (name == jointRightHandName || name == "RightHand" || name == "joint_R_hand" || (hfmModel.fbxToHifiJointNameMapping.contains(jointRightHandName) && (name == hfmModel.fbxToHifiJointNameMapping[jointRightHandName]))) { + } else if (name == jointRightHandName || name == "RightHand" || name == "joint_R_hand" || (hfmModel.hfmToHifiJointNameMapping.contains(jointRightHandName) && (name == hfmModel.hfmToHifiJointNameMapping[jointRightHandName]))) { jointRightHandID = getID(object.properties); - } else if (name == "LeftToe" || name == "joint_L_toe" || name == "LeftToe_End" || (hfmModel.fbxToHifiJointNameMapping.contains("LeftToe") && (name == hfmModel.fbxToHifiJointNameMapping["LeftToe"]))) { + } else if (name == "LeftToe" || name == "joint_L_toe" || name == "LeftToe_End" || (hfmModel.hfmToHifiJointNameMapping.contains("LeftToe") && (name == hfmModel.hfmToHifiJointNameMapping["LeftToe"]))) { jointLeftToeID = getID(object.properties); - } else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End" || (hfmModel.fbxToHifiJointNameMapping.contains("RightToe") && (name == hfmModel.fbxToHifiJointNameMapping["RightToe"]))) { + } else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End" || (hfmModel.hfmToHifiJointNameMapping.contains("RightToe") && (name == hfmModel.hfmToHifiJointNameMapping["RightToe"]))) { jointRightToeID = getID(object.properties); } @@ -1398,6 +1398,9 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr } joint.inverseBindRotation = joint.inverseDefaultRotation; joint.name = fbxModel.name; + if (hfmModel.hfmToHifiJointNameMapping.contains(hfmModel.hfmToHifiJointNameMapping.key(joint.name))) { + joint.name = hfmModel.hfmToHifiJointNameMapping.key(fbxModel.name); + } foreach (const QString& childID, _connectionChildMap.values(modelID)) { QString type = typeFlags.value(childID); @@ -1833,8 +1836,8 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr QString jointName = itr.key(); glm::quat rotationOffset = itr.value(); int jointIndex = hfmModel.getJointIndex(jointName); - if (hfmModel.fbxToHifiJointNameMapping.contains(jointName)) { - jointIndex = hfmModel.getJointIndex(hfmModel.fbxToHifiJointNameMapping[jointName]); + if (hfmModel.hfmToHifiJointNameMapping.contains(jointName)) { + jointIndex = hfmModel.getJointIndex(hfmModel.hfmToHifiJointNameMapping[jointName]); } if (jointIndex != -1) { hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index ff1b4fd01b..3cc12724d5 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -312,7 +312,7 @@ public: QList blendshapeChannelNames; QMap jointRotationOffsets; - QMap fbxToHifiJointNameMapping; + QMap hfmToHifiJointNameMapping; }; }; From 0c64d1227a5c7c57eca72dec9c027b039df0564c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 4 Dec 2018 16:41:03 -0800 Subject: [PATCH 091/117] fix vive crash --- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 99c861871d..62f1720814 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -485,6 +485,7 @@ bool OpenVrDisplayPlugin::internalActivate() { _submitCanvas->doneCurrent(); }); } + _submitCanvas->moveToThread(_submitThread.get()); } return Parent::internalActivate(); From 58396b845fc4a9733d9d0bb43d6bbb3d72a15336 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 4 Dec 2018 17:32:50 -0800 Subject: [PATCH 092/117] move back to plugin thread (cherry picked from commit 98d3f6a9d1191031cda1ff040e69093ef6824f1c) --- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 62f1720814..11ef222172 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -319,6 +319,7 @@ public: glBindVertexArray(0); glDeleteVertexArrays(1, &_vao); _canvas->doneCurrent(); + _canvas->moveToThread(_plugin.thread()); } void update(const CompositeInfo& newCompositeInfo) { _queue.push(newCompositeInfo); } From 3123bb37e42e72d3bf887cac613f1eba603fc5c1 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 5 Dec 2018 10:34:47 -0800 Subject: [PATCH 093/117] fix audio switching issue --- interface/src/Application.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cb41a8c240..9f77c1d7fb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6638,11 +6638,16 @@ void Application::resetSensors(bool andReload) { } void Application::hmdVisibleChanged(bool visible) { + // TODO + // calling start and stop will change audio input and ouput to default audio devices. + // we need to add a pause/unpause functionality to AudioClient for this to work properly +#if 0 if (visible) { QMetaObject::invokeMethod(DependencyManager::get().data(), "start", Qt::QueuedConnection); } else { QMetaObject::invokeMethod(DependencyManager::get().data(), "stop", Qt::QueuedConnection); } +#endif } void Application::updateWindowTitle() const { From 7723261cb9aea50c7f59b713b239d1bf857daf6e Mon Sep 17 00:00:00 2001 From: Clement Date: Mon, 3 Dec 2018 16:51:14 -0800 Subject: [PATCH 094/117] Remove deferred script loading logic --- libraries/script-engine/src/ScriptEngine.cpp | 115 ------------------- libraries/script-engine/src/ScriptEngine.h | 3 - 2 files changed, 118 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 455fd93f4b..6f98dd2864 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -2061,68 +2061,6 @@ bool ScriptEngine::hasEntityScriptDetails(const EntityItemID& entityID) const { return _entityScripts.contains(entityID); } -const static EntityItemID BAD_SCRIPT_UUID_PLACEHOLDER { "{20170224-dead-face-0000-cee000021114}" }; - -void ScriptEngine::processDeferredEntityLoads(const QString& entityScript, const EntityItemID& leaderID) { - QList retryLoads; - QMutableListIterator i(_deferredEntityLoads); - while (i.hasNext()) { - auto retry = i.next(); - if (retry.entityScript == entityScript) { - retryLoads << retry; - i.remove(); - } - } - foreach(DeferredLoadEntity retry, retryLoads) { - // check whether entity was since been deleted - - EntityScriptDetails details; - if (!getEntityScriptDetails(retry.entityID, details)) { - qCDebug(scriptengine) << "processDeferredEntityLoads -- entity details gone (entity deleted?)" - << retry.entityID; - continue; - } - - // check whether entity has since been unloaded or otherwise errored-out - if (details.status != EntityScriptStatus::PENDING) { - qCDebug(scriptengine) << "processDeferredEntityLoads -- entity status no longer PENDING; " - << retry.entityID << details.status; - continue; - } - - // propagate leader's failure reasons to the pending entity - EntityScriptDetails leaderDetails; - { - QWriteLocker locker { &_entityScriptsLock }; - leaderDetails = _entityScripts[leaderID]; - } - if (leaderDetails.status != EntityScriptStatus::RUNNING) { - qCDebug(scriptengine) << QString("... pending load of %1 cancelled (leader: %2 status: %3)") - .arg(retry.entityID.toString()).arg(leaderID.toString()).arg(leaderDetails.status); - - auto extraDetail = QString("\n(propagated from %1)").arg(leaderID.toString()); - if (leaderDetails.status == EntityScriptStatus::ERROR_LOADING_SCRIPT || - leaderDetails.status == EntityScriptStatus::ERROR_RUNNING_SCRIPT) { - // propagate same error so User doesn't have to hunt down stampede's leader - updateEntityScriptStatus(retry.entityID, leaderDetails.status, leaderDetails.errorInfo + extraDetail); - } else { - // the leader Entity somehow ended up in some other state (rapid-fire delete or unload could cause) - updateEntityScriptStatus(retry.entityID, EntityScriptStatus::ERROR_LOADING_SCRIPT, - "A previous Entity failed to load using this script URL; reload to try again." + extraDetail); - } - continue; - } - - if (_occupiedScriptURLs.contains(retry.entityScript)) { - qCWarning(scriptengine) << "--- SHOULD NOT HAPPEN -- recursive call into processDeferredEntityLoads" << retry.entityScript; - continue; - } - - // if we made it here then the leading entity was successful so proceed with normal load - loadEntityScript(retry.entityID, retry.entityScript, false); - } -} - void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& entityScript, bool forceRedownload) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "loadEntityScript", @@ -2147,40 +2085,6 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& updateEntityScriptStatus(entityID, EntityScriptStatus::PENDING, "...pending..."); } - // This "occupied" approach allows multiple Entities to boot from the same script URL while still taking - // full advantage of cacheable require modules. This only affects Entities literally coming in back-to-back - // before the first one has time to finish loading. - if (_occupiedScriptURLs.contains(entityScript)) { - auto currentEntityID = _occupiedScriptURLs[entityScript]; - if (currentEntityID == BAD_SCRIPT_UUID_PLACEHOLDER) { - if (forceRedownload) { - // script was previously marked unusable, but we're reloading so reset it - _occupiedScriptURLs.remove(entityScript); - } else { - // since not reloading, assume that the exact same input would produce the exact same output again - // note: this state gets reset with "reload all scripts," leaving/returning to a Domain, clear cache, etc. -#ifdef DEBUG_ENTITY_STATES - qCDebug(scriptengine) << QString("loadEntityScript.cancelled entity: %1 (previous script failure)") - .arg(entityID.toString()); -#endif - updateEntityScriptStatus(entityID, EntityScriptStatus::ERROR_LOADING_SCRIPT, - "A previous Entity failed to load using this script URL; reload to try again."); - return; - } - } else { - // another entity is busy loading from this script URL so wait for them to finish -#ifdef DEBUG_ENTITY_STATES - qCDebug(scriptengine) << QString("loadEntityScript.deferring[%0] entity: %1 (waiting on %2 )") - .arg(_deferredEntityLoads.size()).arg(entityID.toString()).arg(currentEntityID.toString()); -#endif - _deferredEntityLoads.push_back({ entityID, entityScript }); - return; - } - } - - // the scriptURL slot is available; flag as in-use - _occupiedScriptURLs[entityScript] = entityID; - #ifdef DEBUG_ENTITY_STATES { EntityScriptDetails details; @@ -2223,10 +2127,6 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& qCDebug(scriptengine) << "loadEntityScript.contentAvailable -- aborting"; #endif } - // recheck whether us since may have been set to BAD_SCRIPT_UUID_PLACEHOLDER in entityScriptContentAvailable - if (_occupiedScriptURLs.contains(entityScript) && _occupiedScriptURLs[entityScript] == entityID) { - _occupiedScriptURLs.remove(entityScript); - } }); }, forceRedownload); } @@ -2301,13 +2201,6 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co newDetails.errorInfo = errorInfo; newDetails.status = status; setEntityScriptDetails(entityID, newDetails); - -#ifdef DEBUG_ENTITY_STATES - qCDebug(scriptengine) << "entityScriptContentAvailable -- flagging as BAD_SCRIPT_UUID_PLACEHOLDER"; -#endif - // flag the original entityScript as unusuable - _occupiedScriptURLs[entityScript] = BAD_SCRIPT_UUID_PLACEHOLDER; - processDeferredEntityLoads(entityScript, entityID); }; // NETWORK / FILESYSTEM ERRORS @@ -2441,9 +2334,6 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co callEntityScriptMethod(entityID, "preload"); emit entityScriptPreloadFinished(entityID); - - _occupiedScriptURLs.remove(entityScript); - processDeferredEntityLoads(entityScript, entityID); } /**jsdoc @@ -2499,10 +2389,6 @@ void ScriptEngine::unloadEntityScript(const EntityItemID& entityID, bool shouldR } stopAllTimersForEntityScript(entityID); - { - // FIXME: shouldn't have to do this here, but currently something seems to be firing unloads moments after firing initial load requests - processDeferredEntityLoads(scriptText, entityID); - } } } @@ -2532,7 +2418,6 @@ void ScriptEngine::unloadAllEntityScripts() { _entityScripts.clear(); } emit entityScriptDetailsUpdated(); - _occupiedScriptURLs.clear(); #ifdef DEBUG_ENGINE_STATE _debugDump( diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index fe8396bc50..8fe50aee78 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -747,7 +747,6 @@ protected: void updateEntityScriptStatus(const EntityItemID& entityID, const EntityScriptStatus& status, const QString& errorInfo = QString()); void setEntityScriptDetails(const EntityItemID& entityID, const EntityScriptDetails& details); void setParentURL(const QString& parentURL) { _parentURL = parentURL; } - void processDeferredEntityLoads(const QString& entityScript, const EntityItemID& leaderID); QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot); void stopTimer(QTimer* timer); @@ -783,8 +782,6 @@ protected: QSet _includedURLs; mutable QReadWriteLock _entityScriptsLock { QReadWriteLock::Recursive }; QHash _entityScripts; - QHash _occupiedScriptURLs; - QList _deferredEntityLoads; EntityScriptContentAvailableMap _contentAvailableQueue; bool _isThreaded { false }; From 02307d2308f56f21754d7a121d635d4062d7b6cb Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 5 Dec 2018 16:34:53 -0800 Subject: [PATCH 095/117] Secret to Coupon ID --- .../qml/hifi/commerce/common/sendAsset/SendAsset.qml | 4 ++-- interface/src/commerce/Ledger.cpp | 4 ++-- interface/src/commerce/Ledger.h | 2 +- interface/src/commerce/QmlCommerce.cpp | 4 ++-- interface/src/commerce/QmlCommerce.h | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml index 7c2116f77b..3125ad1ee6 100644 --- a/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml +++ b/interface/resources/qml/hifi/commerce/common/sendAsset/SendAsset.qml @@ -120,10 +120,10 @@ Item { if (result.status === 'success') { root.authorizationID = result.data.authorization_id; authorizationIDText.text = root.authorizationID; - root.couponID = result.data.secret; + root.couponID = result.data.coupon_id; couponIDText.text = root.couponID if (couponIDTextField.text !== root.couponID) { - console.log("SendAsset: Returned secret doesn't match client-generated secret!"); + console.log("SendAsset: Returned coupon ID doesn't match client-generated coupon ID!"); } root.nextActiveView = 'paymentSuccess'; } else { diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index fb177ddc82..8bb01f6389 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -442,10 +442,10 @@ void Ledger::transferAssetToUsername(const QString& hfc_key, const QString& user } } -void Ledger::authorizeAssetTransfer(const QString& hfc_key, const QString& secret, const QString& certificateID, const int& amount, const QString& optionalMessage) { +void Ledger::authorizeAssetTransfer(const QString& hfc_key, const QString& couponID, const QString& certificateID, const int& amount, const QString& optionalMessage) { QJsonObject transaction; transaction["public_key"] = hfc_key; - transaction["secret"] = secret; + transaction["coupon_id"] = couponID; transaction["quantity"] = amount; transaction["message"] = optionalMessage; if (!certificateID.isEmpty()) { diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index 700cbe2c4b..2e18f34c8d 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -36,7 +36,7 @@ public: void certificateInfo(const QString& certificateId); void transferAssetToNode(const QString& hfc_key, const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage); void transferAssetToUsername(const QString& hfc_key, const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage); - void authorizeAssetTransfer(const QString& hfc_key, const QString& secret, const QString& certificateID, const int& amount, const QString& optionalMessage); + void authorizeAssetTransfer(const QString& hfc_key, const QString& couponID, const QString& certificateID, const int& amount, const QString& optionalMessage); void alreadyOwned(const QString& marketplaceId); void getAvailableUpdates(const QString& itemId = "", const int& pageNumber = 1, const int& itemsPerPage = 10); void updateItem(const QString& hfc_key, const QString& certificate_id); diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index aab053484b..00acd40e70 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -247,7 +247,7 @@ void QmlCommerce::transferAssetToUsername(const QString& username, ledger->transferAssetToUsername(key, username, certificateID, amount, optionalMessage); } -void QmlCommerce::authorizeAssetTransfer(const QString& secret, +void QmlCommerce::authorizeAssetTransfer(const QString& couponID, const QString& certificateID, const int& amount, const QString& optionalMessage) { @@ -259,7 +259,7 @@ void QmlCommerce::authorizeAssetTransfer(const QString& secret, return emit authorizeAssetTransferResult(result); } QString key = keys[0]; - ledger->authorizeAssetTransfer(key, secret, certificateID, amount, optionalMessage); + ledger->authorizeAssetTransfer(key, couponID, certificateID, amount, optionalMessage); } void QmlCommerce::replaceContentSet(const QString& itemHref, const QString& certificateID) { diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index e22b540624..ad21899ebf 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -85,7 +85,7 @@ protected: Q_INVOKABLE void transferAssetToNode(const QString& nodeID, const QString& certificateID, const int& amount, const QString& optionalMessage); Q_INVOKABLE void transferAssetToUsername(const QString& username, const QString& certificateID, const int& amount, const QString& optionalMessage); - Q_INVOKABLE void authorizeAssetTransfer(const QString& secret, const QString& certificateID, const int& amount, const QString& optionalMessage); + Q_INVOKABLE void authorizeAssetTransfer(const QString& couponID, const QString& certificateID, const int& amount, const QString& optionalMessage); Q_INVOKABLE void replaceContentSet(const QString& itemHref, const QString& certificateID); From 16144b663036cbce530f77091a4ab8217f22450f Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 5 Dec 2018 17:14:40 -0800 Subject: [PATCH 096/117] Move the previously deleted FST reader down to the ScriptableAvatar class --- .../src/avatars/ScriptableAvatar.cpp | 96 +++++++++++++++++++ .../src/avatars/ScriptableAvatar.h | 32 +++++++ 2 files changed, 128 insertions(+) diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index 392e9960e0..29a66b44fc 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -19,6 +19,9 @@ #include #include #include +#include +#include + ScriptableAvatar::ScriptableAvatar() { _clientTraitsHandler = std::unique_ptr(new ClientTraitsHandler(this)); @@ -62,11 +65,28 @@ AnimationDetails ScriptableAvatar::getAnimationDetails() { return _animationDetails; } +int ScriptableAvatar::getJointIndex(const QString& name) const { + // Faux joints: + int result = AvatarData::getJointIndex(name); + if (result != -1) { + return result; + } + QReadLocker readLock(&_jointDataLock); + return _fstJointIndices.value(name) - 1; +} + +QStringList ScriptableAvatar::getJointNames() const { + QReadLocker readLock(&_jointDataLock); + return _fstJointNames; + return QStringList(); +} + void ScriptableAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { _bind.reset(); _animSkeleton.reset(); AvatarData::setSkeletonModelURL(skeletonModelURL); + updateJointMappings(); } static AnimPose composeAnimPose(const HFMJoint& joint, const glm::quat rotation, const glm::vec3 translation) { @@ -142,6 +162,82 @@ void ScriptableAvatar::update(float deltatime) { _clientTraitsHandler->sendChangedTraitsToMixer(); } +void ScriptableAvatar::updateJointMappings() { + { + QWriteLocker writeLock(&_jointDataLock); + _fstJointIndices.clear(); + _fstJointNames.clear(); + _jointData.clear(); + } + + if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) { + //// + // TODO: Should we rely upon HTTPResourceRequest for ResourceRequestObserver instead? + // HTTPResourceRequest::doSend() covers all of the following and + // then some. It doesn't cover the connect() call, so we may + // want to add a HTTPResourceRequest::doSend() method that does + // connects. + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); + QNetworkRequest networkRequest = QNetworkRequest(_skeletonModelURL); + networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + networkRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT); + DependencyManager::get()->update( + _skeletonModelURL, -1, "AvatarData::updateJointMappings"); + QNetworkReply* networkReply = networkAccessManager.get(networkRequest); + // + //// + connect(networkReply, &QNetworkReply::finished, this, &ScriptableAvatar::setJointMappingsFromNetworkReply); + } +} + +void ScriptableAvatar::setJointMappingsFromNetworkReply() { + QNetworkReply* networkReply = static_cast(sender()); + // before we process this update, make sure that the skeleton model URL hasn't changed + // since we made the FST request + if (networkReply->url() != _skeletonModelURL) { + qCDebug(avatars) << "Refusing to set joint mappings for FST URL that does not match the current URL"; + networkReply->deleteLater(); + return; + } + { + QWriteLocker writeLock(&_jointDataLock); + QByteArray line; + while (!(line = networkReply->readLine()).isEmpty()) { + line = line.trimmed(); + if (line.startsWith("filename")) { + int filenameIndex = line.indexOf('=') + 1; + if (filenameIndex > 0) { + _skeletonFBXURL = _skeletonModelURL.resolved(QString(line.mid(filenameIndex).trimmed())); + } + } + if (!line.startsWith("jointIndex")) { + continue; + } + int jointNameIndex = line.indexOf('=') + 1; + if (jointNameIndex == 0) { + continue; + } + int secondSeparatorIndex = line.indexOf('=', jointNameIndex); + if (secondSeparatorIndex == -1) { + continue; + } + QString jointName = line.mid(jointNameIndex, secondSeparatorIndex - jointNameIndex).trimmed(); + bool ok; + int jointIndex = line.mid(secondSeparatorIndex + 1).trimmed().toInt(&ok); + if (ok) { + while (_fstJointNames.size() < jointIndex + 1) { + _fstJointNames.append(QString()); + } + _fstJointNames[jointIndex] = jointName; + } + } + for (int i = 0; i < _fstJointNames.size(); i++) { + _fstJointIndices.insert(_fstJointNames.at(i), i + 1); + } + } + networkReply->deleteLater(); +} + void ScriptableAvatar::setHasProceduralBlinkFaceMovement(bool hasProceduralBlinkFaceMovement) { _headData->setHasProceduralBlinkFaceMovement(hasProceduralBlinkFaceMovement); } diff --git a/assignment-client/src/avatars/ScriptableAvatar.h b/assignment-client/src/avatars/ScriptableAvatar.h index 578bd84a8f..66b0b5ae3f 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.h +++ b/assignment-client/src/avatars/ScriptableAvatar.h @@ -153,6 +153,27 @@ public: */ Q_INVOKABLE AnimationDetails getAnimationDetails(); + /**jsdoc + * Get the names of all the joints in the current avatar. + * @function MyAvatar.getJointNames + * @returns {string[]} The joint names. + * @example Report the names of all the joints in your current avatar. + * print(JSON.stringify(MyAvatar.getJointNames())); + */ + Q_INVOKABLE virtual QStringList getJointNames() const override; + + /**jsdoc + * Get the joint index for a named joint. The joint index value is the position of the joint in the array returned by + * {@link MyAvatar.getJointNames} or {@link Avatar.getJointNames}. + * @function MyAvatar.getJointIndex + * @param {string} name - The name of the joint. + * @returns {number} The index of the joint. + * @example Report the index of your avatar's left arm joint. + * print(JSON.stringify(MyAvatar.getJointIndex("LeftArm")); + */ + /// Returns the index of the joint with the specified name, or -1 if not found/unknown. + Q_INVOKABLE virtual int getJointIndex(const QString& name) const override; + virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; virtual QByteArray toByteArrayStateful(AvatarDataDetail dataDetail, bool dropFaceTracking = false) override; @@ -167,12 +188,23 @@ public: public slots: void update(float deltatime); + /**jsdoc + * @function MyAvatar.setJointMappingsFromNetworkReply + */ + void setJointMappingsFromNetworkReply(); + private: AnimationPointer _animation; AnimationDetails _animationDetails; QStringList _maskedJoints; AnimationPointer _bind; // a sleazy way to get the skeleton, given the various library/cmake dependencies std::shared_ptr _animSkeleton; + QHash _fstJointIndices; ///< 1-based, since zero is returned for missing keys + QStringList _fstJointNames; ///< in order of depth-first traversal + QUrl _skeletonFBXURL; + + /// Loads the joint indices, names from the FST file (if any) + void updateJointMappings(); }; #endif // hifi_ScriptableAvatar_h From aa952e91429af6ee05224aa5c9815c4e2f163be1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 6 Dec 2018 15:24:03 +1300 Subject: [PATCH 097/117] Fix mini tablet visibility angle calculations --- scripts/system/miniTablet.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/scripts/system/miniTablet.js b/scripts/system/miniTablet.js index a933116dc8..780dacf85e 100644 --- a/scripts/system/miniTablet.js +++ b/scripts/system/miniTablet.js @@ -567,9 +567,7 @@ SHOWING_DELAY = 1000, // ms lastInvisible = [0, 0], HIDING_DELAY = 1000, // ms - lastVisible = [0, 0], - - HALF_PI = Math.PI / 2; + lastVisible = [0, 0]; function enterMiniDisabled() { @@ -608,8 +606,12 @@ handOrientation, miniPosition, miniToCameraDirection, + normalHandVector, medialHandVector, lateralHandVector, + normalDot, + medialDot, + lateralDot, medialAngle, lateralAngle, cameraToMini, @@ -664,14 +666,18 @@ miniToCameraDirection = Vec3.normalize(Vec3.subtract(Camera.position, miniPosition)); // Mini tablet aimed toward camera? - medialHandVector = Vec3.multiplyQbyV(handOrientation, Vec3.UNIT_NEG_Y); + medialHandVector = Vec3.multiplyQbyV(handOrientation, Vec3.UNIT_Y); lateralHandVector = Vec3.multiplyQbyV(handOrientation, hand === LEFT_HAND ? Vec3.UNIT_X : Vec3.UNIT_NEG_X); - medialAngle = Math.acos(Vec3.dot(medialHandVector, miniToCameraDirection)) - HALF_PI; - lateralAngle = Math.acos(Vec3.dot(lateralHandVector, miniToCameraDirection)) - HALF_PI; + normalHandVector = Vec3.multiplyQbyV(handOrientation, Vec3.UNIT_Z); + medialDot = Vec3.dot(medialHandVector, miniToCameraDirection); + lateralDot = Vec3.dot(lateralHandVector, miniToCameraDirection); + normalDot = Vec3.dot(normalHandVector, miniToCameraDirection); + medialAngle = Math.atan2(medialDot, normalDot); + lateralAngle = Math.atan2(lateralDot, normalDot); show = -MAX_MEDIAL_WRIST_CAMERA_ANGLE_RAD <= medialAngle && medialAngle <= MAX_MEDIAL_FINGER_CAMERA_ANGLE_RAD - && -MAX_LATERAL_PINKY_CAMERA_ANGLE_RAD <= lateralAngle - && lateralAngle <= MAX_LATERAL_THUMB_CAMERA_ANGLE_RAD; + && -MAX_LATERAL_THUMB_CAMERA_ANGLE_RAD <= lateralAngle + && lateralAngle <= MAX_LATERAL_PINKY_CAMERA_ANGLE_RAD; // Camera looking at mini tablet? cameraToMini = -Vec3.dot(miniToCameraDirection, Quat.getForward(Camera.orientation)); From 3160339551dda631170d4fc7f1b82aa03b8e036d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 4 Dec 2018 10:50:50 -0800 Subject: [PATCH 098/117] Improve Create properties for particles + materials Sizing of input fields is now flexible. Material scale field labels are no longer obscured. Material tooltips are corrected. --- .../system/assets/data/createAppTooltips.json | 2 +- scripts/system/html/css/edit-style.css | 30 +++++++++------- scripts/system/html/js/draggableNumber.js | 12 +++---- scripts/system/html/js/entityProperties.js | 35 ++++++++++--------- 4 files changed, 44 insertions(+), 35 deletions(-) diff --git a/scripts/system/assets/data/createAppTooltips.json b/scripts/system/assets/data/createAppTooltips.json index 720d4537ee..3a25402588 100644 --- a/scripts/system/assets/data/createAppTooltips.json +++ b/scripts/system/assets/data/createAppTooltips.json @@ -267,7 +267,7 @@ "jsPropertyName": "parentMaterialName" }, "selectSubmesh": { - "tooltip": "If enabled, \"Select Submesh\" property will show up, otherwise \"Material Name to Replace\" will be shown.", + "tooltip": "If enabled, \"Submesh to Replace\" property will show up, otherwise \"Material to Replace\" will be shown.", "skipJSProperty": true }, "priority": { diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 415d8e567f..d7d88ce91e 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -598,6 +598,7 @@ div.section[collapsed="true"], div.section[collapsed="true"] > .section-header { .triple-label { text-transform: uppercase; + text-align: center; padding: 6px 0; } @@ -605,6 +606,10 @@ div.section[collapsed="true"], div.section[collapsed="true"] > .section-header { margin-right: 10px; } +.triple-item.rgb.fstuple { + display: block !important; +} + .section-header[collapsed="true"] { margin-bottom: -21px; } @@ -911,14 +916,17 @@ div.refresh input[type="button"] { clear: both; } +.draggable-number-container { + flex: 0 1 124px; +} .draggable-number { position: relative; -} -.draggable-number div { height: 28px; - width: 124px; + flex: 0 1 124px; } -.draggable-number.text { + +.draggable-number .text { + position: absolute; display: inline-block; color: #afafaf; background-color: #252525; @@ -930,11 +938,12 @@ div.refresh input[type="button"] { width: 100%; line-height: 2; box-sizing: border-box; + z-index: 1; } -.draggable-number.text:hover { +.draggable-number .text:hover { cursor: ew-resize; } -.draggable-number span { +.draggable-number .left-arrow, .draggable-number .right-arrow { position: absolute; display: inline-block; font-family: HiFi-Glyphs; @@ -944,12 +953,12 @@ div.refresh input[type="button"] { .draggable-number span:hover { cursor: default; } -.draggable-number.left-arrow { +.draggable-number .left-arrow { top: 3px; left: 0px; transform: rotate(180deg); } -.draggable-number.right-arrow { +.draggable-number .right-arrow { top: 3px; right: 0px; } @@ -1514,6 +1523,7 @@ input.rename-entity { width: 258px; min-height: 20px; padding: 5px; + z-index: 100; } .create-app-tooltip .create-app-tooltip-description { @@ -1629,10 +1639,6 @@ 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 951b123e67..3995b846be 100644 --- a/scripts/system/html/js/draggableNumber.js +++ b/scripts/system/html/js/draggableNumber.js @@ -156,8 +156,8 @@ DraggableNumber.prototype = { this.elDiv = document.createElement('div'); this.elDiv.className = "draggable-number"; - this.elText = document.createElement('label'); - this.elText.className = "draggable-number text"; + this.elText = document.createElement('span'); + this.elText.className = "text"; this.elText.innerText = " "; this.elText.style.visibility = "visible"; this.elText.addEventListener("mousedown", this.onMouseDown); @@ -165,15 +165,15 @@ DraggableNumber.prototype = { this.elLeftArrow = document.createElement('span'); this.elRightArrow = document.createElement('span'); - this.elLeftArrow.className = 'draggable-number left-arrow'; + this.elLeftArrow.className = 'left-arrow'; this.elLeftArrow.innerHTML = 'D'; this.elLeftArrow.addEventListener("click", this.onStepDown); - this.elRightArrow.className = 'draggable-number right-arrow'; + this.elRightArrow.className = '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.className = "input"; this.elInput.setAttribute("type", "number"); if (this.min !== undefined) { this.elInput.setAttribute("min", this.min); @@ -190,8 +190,8 @@ DraggableNumber.prototype = { this.elInput.addEventListener("focus", this.showInput.bind(this)); this.elDiv.appendChild(this.elLeftArrow); + this.elDiv.appendChild(this.elText); this.elDiv.appendChild(this.elInput); this.elDiv.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 14ed2b77e3..ff760e3a4a 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -556,22 +556,24 @@ const GROUPS = [ { id: "save", label: "Save Material Data", className: "black", onClick: saveMaterialData } ], propertyID: "materialData", }, + { + label: "Select Submesh", + type: "bool", + propertyID: "selectSubmesh", + }, { label: "Submesh to Replace", type: "number", min: 0, step: 1, propertyID: "submeshToReplace", + indentedLabel: true, }, { - label: "Material Name to Replace", + label: "Material to Replace", type: "string", propertyID: "materialNameToReplace", - }, - { - label: "Select Submesh", - type: "bool", - propertyID: "selectSubmesh", + indentedLabel: true, }, { label: "Priority", @@ -582,7 +584,7 @@ const GROUPS = [ { label: "Material Position", type: "vec2", - vec2Type: "xy", + vec2Type: "xyz", min: 0, max: 1, step: 0.1, @@ -593,11 +595,11 @@ const GROUPS = [ { label: "Material Scale", type: "vec2", - vec2Type: "wh", + vec2Type: "xyz", min: 0, step: 0.1, decimals: 4, - subLabels: [ "width", "height" ], + subLabels: [ "x", "y" ], propertyID: "materialMappingScale", }, { @@ -1858,7 +1860,7 @@ function createNumberProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; - elProperty.className = "draggable-number"; + elProperty.className += " draggable-number-container"; let dragStartFunction = createDragStartFunction(property); let dragEndFunction = createDragEndFunction(property); @@ -1937,7 +1939,7 @@ function createColorProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; - elProperty.className = "rgb fstuple"; + elProperty.className += " rgb fstuple"; let elColorPicker = document.createElement('div'); elColorPicker.className = "color-picker"; @@ -1978,6 +1980,7 @@ function createColorProperty(property, elProperty) { color: '000000', submit: false, // We don't want to have a submission button onShow: function(colpick) { + console.log("Showing"); $(colorPickerID).attr('active', 'true'); // The original color preview within the picker needs to be updated on show because // prior to the picker being shown we don't have access to the selections' starting color. @@ -2879,20 +2882,20 @@ function loaded() { for (let i = 0; i < propertyData.properties.length; ++i) { let innerPropertyData = propertyData.properties[i]; - let elWrapper = createElementFromHTML('
'); + let elWrapper = createElementFromHTML('
'); + elProperty.appendChild(elWrapper); let propertyID = innerPropertyData.propertyID; let propertyName = innerPropertyData.propertyName !== undefined ? innerPropertyData.propertyName : propertyID; let propertyElementID = "property-" + propertyID; propertyElementID = propertyElementID.replace('.', '-'); - elWrapper.appendChild(createElementFromHTML(`
${innerPropertyData.label}
`)); - elProperty.appendChild(elWrapper); - - let property = createProperty(innerPropertyData, propertyElementID, propertyName, propertyID, elWrapper.childNodes[0]); + let property = createProperty(innerPropertyData, propertyElementID, propertyName, propertyID, elWrapper); property.isParticleProperty = group.id.includes("particles"); property.elContainer = elContainer; property.spaceMode = propertySpaceMode; + + elWrapper.appendChild(createElementFromHTML(`
${innerPropertyData.label}
`)); if (property.type !== 'placeholder') { properties[propertyID] = property; From a2af50a9d0b7a82c7c993d1801b2c5ee0d797afe Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 6 Dec 2018 11:07:26 -0800 Subject: [PATCH 099/117] Show pre-auth'd transactions in Recent Activity before redemption --- .../qml/hifi/commerce/wallet/WalletHome.qml | 8 ++++++-- interface/src/commerce/Ledger.cpp | 17 +++++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index 4c8e1e6ca5..cf293a06df 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -270,9 +270,11 @@ Item { model: transactionHistoryModel; delegate: Item { width: parent.width; - height: (model.transaction_type === "pendingCount" && model.count !== 0) ? 40 : ((model.status === "confirmed" || model.status === "invalidated") ? transactionText.height + 30 : 0); + height: (model.transaction_type === "pendingCount" && model.count !== 0) ? 40 : + (transactionContainer.visible ? transactionText.height + 30 : 0); Item { + id: pendingCountContainer; visible: model.transaction_type === "pendingCount" && model.count !== 0; anchors.top: parent.top; anchors.left: parent.left; @@ -291,7 +293,9 @@ Item { } Item { - visible: model.transaction_type !== "pendingCount" && (model.status === "confirmed" || model.status === "invalidated"); + id: transactionContainer; + visible: model.transaction_type !== "pendingCount" && + (model.status === "confirmed" || model.status === "invalidated"); anchors.top: parent.top; anchors.left: parent.left; width: parent.width; diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 8bb01f6389..d72d896638 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -204,6 +204,7 @@ QString transactionString(const QJsonObject& valueObject) { int sentMoney = valueObject["sent_money"].toInt(); int receivedMoney = valueObject["received_money"].toInt(); int dateInteger = valueObject["created_at"].toInt(); + QString transactionType = valueObject["transaction_type"].toString(); QString message = valueObject["message"].toString(); QDateTime createdAt(QDateTime::fromSecsSinceEpoch(dateInteger, Qt::UTC)); QString result; @@ -211,8 +212,12 @@ QString transactionString(const QJsonObject& valueObject) { if (sentCerts <= 0 && receivedCerts <= 0 && !KNOWN_USERS.contains(valueObject["sender_name"].toString())) { // this is an hfc transfer. if (sentMoney > 0) { - QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString()); - result += QString("Money sent to %1").arg(recipient); + if (transactionType == "escrow") { + result += QString("Money transferred to coupon"); + } else { + QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString()); + result += QString("Money sent to %1").arg(recipient); + } } else { QString sender = userLink(valueObject["sender_name"].toString(), valueObject["place_name"].toString()); result += QString("Money from %1").arg(sender); @@ -227,8 +232,12 @@ QString transactionString(const QJsonObject& valueObject) { ) { // this is a non-HFC asset transfer. if (sentCerts > 0) { - QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString()); - result += QString("Gift sent to %1").arg(recipient); + if (transactionType == "escrow") { + result += QString("Item transferred to coupon"); + } else { + QString recipient = userLink(valueObject["recipient_name"].toString(), valueObject["place_name"].toString()); + result += QString("Gift sent to %1").arg(recipient); + } } else { QString sender = userLink(valueObject["sender_name"].toString(), valueObject["place_name"].toString()); result += QString("Gift from %1").arg(sender); From 8620a5a4c3649903a4f50c19684e95f6749f17bb Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 6 Dec 2018 13:07:59 -0800 Subject: [PATCH 100/117] CR changes --- scripts/system/html/js/listView.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/html/js/listView.js b/scripts/system/html/js/listView.js index b19ba7e0cb..eec3f833ad 100644 --- a/scripts/system/html/js/listView.js +++ b/scripts/system/html/js/listView.js @@ -242,7 +242,7 @@ ListView.prototype = { resize: function() { if (!this.elTableBody || !this.elTableScroll) { - debugPrint("ListView.resize - no valid table body or table scroll element"); + console.log("ListView.resize - no valid table body or table scroll element"); return; } this.preResizeFunction(); @@ -284,7 +284,7 @@ ListView.prototype = { initialize: function() { if (!this.elTableBody || !this.elTableScroll) { - debugPrint("ListView.initialize - no valid table body or table scroll element"); + console.log("ListView.initialize - no valid table body or table scroll element"); return; } From 6d40bc9c2f0fdccccf2b76c499469fda98916192 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 29 Nov 2018 19:41:56 +0100 Subject: [PATCH 101/117] userData error message continues popup fix --- scripts/system/html/css/edit-style.css | 24 +++++ scripts/system/html/js/entityProperties.js | 103 +++++++++++++-------- 2 files changed, 86 insertions(+), 41 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 415d8e567f..641b9bb5fe 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1663,3 +1663,27 @@ input.number-slider { .collapse-icon { cursor: pointer; } + +#property-userData-editor.error { + border: 2px solid red; +} + +#property-userData-editorStatus { + color: white; + background-color: red; + padding: 5px; + display: none; + cursor: pointer; +} + +#property-materialData-editor.error { + border: 2px solid red; +} + +#property-materialData-editorStatus { + color: white; + background-color: red; + padding: 5px; + display: none; + cursor: pointer; +} diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index dc304c6803..bc93a1a9b7 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1823,7 +1823,7 @@ function createStringProperty(property, elProperty) { type="text" ${propertyData.placeholder ? 'placeholder="' + propertyData.placeholder + '"' : ''} ${propertyData.readOnly ? 'readonly' : ''}> - `) + `); elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); @@ -2359,31 +2359,41 @@ function saveUserData() { saveJSONUserData(true); } +function setJSONError(property, isError) { + $("#property-"+ property + "-editor").toggleClass('error', isError); + var $propertyUserDataEditorStatus = $("#property-"+ property + "-editorStatus"); + $propertyUserDataEditorStatus.css('display', isError ? 'block' : 'none'); + $propertyUserDataEditorStatus.text(isError ? 'Invalid JSON code - look for red X in your code' : ''); +} + function setUserDataFromEditor(noUpdate) { let json = null; + let errorFound = false; try { json = editor.get(); } catch (e) { - alert('Invalid JSON code - look for red X in your code ', +e); + errorFound = true; } - if (json === null) { + + setJSONError('userData', errorFound); + + if (json !== null) { return; + } + + let text = editor.getText(); + if (noUpdate) { + EventBridge.emitWebEvent( + JSON.stringify({ + id: lastEntityID, + type: "saveUserData", + properties: { + userData: text + } + }) + ); } else { - let text = editor.getText(); - if (noUpdate === true) { - EventBridge.emitWebEvent( - JSON.stringify({ - id: lastEntityID, - type: "saveUserData", - properties: { - userData: text - } - }) - ); - return; - } else { - updateProperty('userData', text, false); - } + updateProperty('userData', text, false); } } @@ -2505,9 +2515,10 @@ function hideUserDataSaved() { function showStaticUserData() { if (editor !== null) { - $('#property-userData-static').show(); - $('#property-userData-static').css('height', $('#property-userData-editor').height()); - $('#property-userData-static').text(editor.getText()); + let $propertyUserDataStatic = $('#property-userData-static'); + $propertyUserDataStatic.show(); + $propertyUserDataStatic.css('height', $('#property-userData-editor').height()); + $propertyUserDataStatic.text(editor.getText()); } } @@ -2528,6 +2539,7 @@ function getEditorJSON() { function deleteJSONEditor() { if (editor !== null) { + setJSONError('userData', false); editor.destroy(); editor = null; } @@ -2578,29 +2590,31 @@ function saveMaterialData() { function setMaterialDataFromEditor(noUpdate) { let json = null; + let errorFound = false; try { json = materialEditor.get(); } catch (e) { - alert('Invalid JSON code - look for red X in your code ', +e); + errorFound = true; } + + setJSONError('materialData', errorFound); + if (json === null) { return; + } + let text = materialEditor.getText(); + if (noUpdate) { + EventBridge.emitWebEvent( + JSON.stringify({ + id: lastEntityID, + type: "saveMaterialData", + properties: { + materialData: text + } + }) + ); } else { - let text = materialEditor.getText(); - if (noUpdate === true) { - EventBridge.emitWebEvent( - JSON.stringify({ - id: lastEntityID, - type: "saveMaterialData", - properties: { - materialData: text - } - }) - ); - return; - } else { - updateProperty('materialData', text, false); - } + updateProperty('materialData', text, false); } } @@ -2667,9 +2681,10 @@ function hideMaterialDataSaved() { function showStaticMaterialData() { if (materialEditor !== null) { - $('#property-materialData-static').show(); - $('#property-materialData-static').css('height', $('#property-materialData-editor').height()); - $('#property-materialData-static').text(materialEditor.getText()); + let $propertyMaterialDataStatic = $('#property-materialData-static'); + $propertyMaterialDataStatic.show(); + $propertyMaterialDataStatic.css('height', $('#property-materialData-editor').height()); + $propertyMaterialDataStatic.text(materialEditor.getText()); } } @@ -2955,7 +2970,7 @@ function loaded() { let elServerScriptError = document.getElementById("property-serverScripts-error"); let elServerScriptStatus = document.getElementById("property-serverScripts-status"); elServerScriptError.value = data.errorInfo; - // If we just set elServerScriptError's diplay to block or none, we still end up with + // If we just set elServerScriptError's display to block or none, we still end up with // it's parent contributing 21px bottom padding even when elServerScriptError is display:none. // So set it's parent to block or none elServerScriptError.parentElement.style.display = data.errorInfo ? "block" : "none"; @@ -3314,12 +3329,15 @@ function loaded() { elStaticUserData.setAttribute("id", userDataElementID + "-static"); let elUserDataEditor = document.createElement('div'); elUserDataEditor.setAttribute("id", userDataElementID + "-editor"); + let elUserDataEditorStatus = document.createElement('div'); + elUserDataEditorStatus.setAttribute("id", userDataElementID + "-editorStatus"); let elUserDataSaved = document.createElement('span'); elUserDataSaved.setAttribute("id", userDataElementID + "-saved"); elUserDataSaved.innerText = "Saved!"; elDiv.childNodes[JSON_EDITOR_ROW_DIV_INDEX].appendChild(elUserDataSaved); elDiv.insertBefore(elStaticUserData, elUserData); elDiv.insertBefore(elUserDataEditor, elUserData); + elDiv.insertBefore(elUserDataEditorStatus, elUserData); // Material Data let materialDataProperty = properties["materialData"]; @@ -3330,12 +3348,15 @@ function loaded() { elStaticMaterialData.setAttribute("id", materialDataElementID + "-static"); let elMaterialDataEditor = document.createElement('div'); elMaterialDataEditor.setAttribute("id", materialDataElementID + "-editor"); + let elMaterialDataEditorStatus = document.createElement('div'); + elMaterialDataEditorStatus.setAttribute("id", materialDataElementID + "-editorStatus"); let elMaterialDataSaved = document.createElement('span'); elMaterialDataSaved.setAttribute("id", materialDataElementID + "-saved"); elMaterialDataSaved.innerText = "Saved!"; elDiv.childNodes[JSON_EDITOR_ROW_DIV_INDEX].appendChild(elMaterialDataSaved); elDiv.insertBefore(elStaticMaterialData, elMaterialData); elDiv.insertBefore(elMaterialDataEditor, elMaterialData); + elDiv.insertBefore(elMaterialDataEditorStatus, elMaterialData); // Special Property Callbacks let elParentMaterialNameString = getPropertyInputElement("materialNameToReplace"); From 2771e2862e15e54b6cfa7edf696ef0e18d2f58f7 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 29 Nov 2018 19:55:34 +0100 Subject: [PATCH 102/117] add missing material data json error clear on delete --- scripts/system/html/js/entityProperties.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index bc93a1a9b7..ed03d62e70 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -2705,6 +2705,7 @@ function getMaterialEditorJSON() { function deleteJSONMaterialEditor() { if (materialEditor !== null) { + setJSONError('materialData', false); materialEditor.destroy(); materialEditor = null; } From 4f2289b347db6342006d41f98fdc89604f7525e1 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 6 Dec 2018 23:42:12 +0100 Subject: [PATCH 103/117] CR fixes --- scripts/system/html/js/entityProperties.js | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index ed03d62e70..6f8f2ef4bc 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1429,13 +1429,13 @@ const TEXTURE_ELEMENTS = { const JSON_EDITOR_ROW_DIV_INDEX = 2; -var elGroups = {}; -var properties = {}; -var colorPickers = {}; -var particlePropertyUpdates = {}; -var selectedEntityProperties; -var lastEntityID = null; -var createAppTooltip = new CreateAppTooltip(); +let elGroups = {}; +let properties = {}; +let colorPickers = {}; +let particlePropertyUpdates = {}; +let selectedEntityProperties; +let lastEntityID = null; +let createAppTooltip = new CreateAppTooltip(); let currentSpaceMode = PROPERTY_SPACE_MODE.LOCAL; function createElementFromHTML(htmlString) { @@ -1689,7 +1689,7 @@ function updateProperty(originalPropertyName, propertyValue, isParticleProperty) } } -var particleSyncDebounce = _.debounce(function () { +let particleSyncDebounce = _.debounce(function () { updateProperties(particlePropertyUpdates); particlePropertyUpdates = {}; }, DEBOUNCE_TIMEOUT); @@ -2361,7 +2361,7 @@ function saveUserData() { function setJSONError(property, isError) { $("#property-"+ property + "-editor").toggleClass('error', isError); - var $propertyUserDataEditorStatus = $("#property-"+ property + "-editorStatus"); + let $propertyUserDataEditorStatus = $("#property-"+ property + "-editorStatus"); $propertyUserDataEditorStatus.css('display', isError ? 'block' : 'none'); $propertyUserDataEditorStatus.text(isError ? 'Invalid JSON code - look for red X in your code' : ''); } @@ -2377,7 +2377,7 @@ function setUserDataFromEditor(noUpdate) { setJSONError('userData', errorFound); - if (json !== null) { + if (errorFound) { return; } @@ -2452,7 +2452,7 @@ function multiDataUpdater(groupName, updateKeyPair, userDataElement, defaults, r updateProperties(propertyUpdate, false); } -var editor = null; +let editor = null; function createJSONEditor() { let container = document.getElementById("property-userData-editor"); @@ -2545,7 +2545,7 @@ function deleteJSONEditor() { } } -var savedJSONTimer = null; +let savedJSONTimer = null; function saveJSONUserData(noUpdate) { setUserDataFromEditor(noUpdate); @@ -2599,7 +2599,7 @@ function setMaterialDataFromEditor(noUpdate) { setJSONError('materialData', errorFound); - if (json === null) { + if (errorFound) { return; } let text = materialEditor.getText(); @@ -2618,7 +2618,7 @@ function setMaterialDataFromEditor(noUpdate) { } } -var materialEditor = null; +let materialEditor = null; function createJSONMaterialEditor() { let container = document.getElementById("property-materialData-editor"); @@ -2711,7 +2711,7 @@ function deleteJSONMaterialEditor() { } } -var savedMaterialJSONTimer = null; +let savedMaterialJSONTimer = null; function saveJSONMaterialData(noUpdate) { setMaterialDataFromEditor(noUpdate); From 62a06fe3834fe91248c0d970daf90c2a9b648916 Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 29 Nov 2018 11:10:57 -0800 Subject: [PATCH 104/117] Update build docs --- BUILD.md | 20 ++++++++++++++++---- BUILD_WIN.md | 23 +++++------------------ 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/BUILD.md b/BUILD.md index 00b17743e9..25bbc89951 100644 --- a/BUILD.md +++ b/BUILD.md @@ -13,7 +13,7 @@ ### CMake External Project Dependencies -These dependencies need not be installed manually. They are automatically downloaded on the platforms where they are required. +These dependencies need not be installed manually. They are automatically downloaded on the platforms where they are required. - [Bullet Physics Engine](https://github.com/bulletphysics/bullet3/releases): 2.83 - [glm](https://glm.g-truc.net/0.9.8/index.html): 0.9.8 - [Oculus SDK](https://developer.oculus.com/downloads/): 1.11 (Win32) / 0.5 (Mac) @@ -22,7 +22,7 @@ These dependencies need not be installed manually. They are automatically downlo - [QuaZip](https://sourceforge.net/projects/quazip/files/quazip/): 0.7.3 - [SDL2](https://www.libsdl.org/download-2.0.php): 2.0.3 - [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/): 4.3 -- [vcpkg](https://github.com/highfidelity/vcpkg): +- [vcpkg](https://github.com/highfidelity/vcpkg): - [VHACD](https://github.com/virneo/v-hacd) - [zlib](http://www.zlib.net/): 1.28 (Win32 only) - [nvtt](https://github.com/highfidelity/nvidia-texture-tools): 2.1.1 (customized) @@ -48,6 +48,18 @@ The path it needs to be set to will depend on where and how Qt5 was installed. e export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.10.1/lib/cmake export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake +#### Vcpkg + +Hifi uses vcpkg to download and build dependencies. +You do not need to install vcpkg. + +Building the dependencies can be lengthy and the resulting files will be stored in your OS temp directory. +However, those files can potentially get cleaned up by the OS, so in order to avoid this and having to redo the lengthy build step, you can set the following environment variable: + +export HIFI_VCPKG_BASE=/path/to/directory + +Where /path/to/directory is the path to a directory where you wish the build files to get stored. + #### Generating build files Create a build directory in the root of your checkout and then run the CMake build from there. This will keep the rest of the directory clean. @@ -80,7 +92,7 @@ In the examples below the variable $NAME would be replaced by the name of the de ### Optional Components -#### Build Options +#### Build Options The following build options can be used when running CMake @@ -89,7 +101,7 @@ The following build options can be used when running CMake * BUILD_TESTS * BUILD_TOOLS -#### Developer Build Options +#### Developer Build Options * USE_GLES * DISABLE_UI diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 073b048911..a81fca5900 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -19,7 +19,7 @@ If you do not wish to use the Python installation bundled with Visual Studio, yo ### Step 2. Installing CMake -Download and install the latest version of CMake 3.9. +Download and install the latest version of CMake 3.9. Download the file named win64-x64 Installer from the [CMake Website](https://cmake.org/download/). You can access the installer on this [3.9 Version page](https://cmake.org/files/v3.9/). During installation, make sure to check "Add CMake to system PATH for all users" when prompted. @@ -35,20 +35,7 @@ Go to `Control Panel > System > Advanced System Settings > Environment Variables * Set "Variable name": `QT_CMAKE_PREFIX_PATH` * Set "Variable value": `C:\Qt\5.10.1\msvc2017_64\lib\cmake` -### Step 5. Installing [vcpkg](https://github.com/Microsoft/vcpkg) - - * Clone the VCPKG [repository](https://github.com/Microsoft/vcpkg) - * Follow the instructions in the [readme](https://github.com/Microsoft/vcpkg/blob/master/README.md) to bootstrap vcpkg - * Note, you may need to do these in a _Developer Command Prompt_ - * Set an environment variable VCPKG_ROOT to the location of the cloned repository - * Close and re-open any command prompts after setting the environment variable so that they will pick up the change - -### Step 6. Installing OpenSSL via vcpkg - - * In the vcpkg directory, install the 64 bit OpenSSL package with the command `.\vcpkg install openssl:x64-windows` - * Once the build completes you should have a file `ssl.h` in `${VCPKG_ROOT}/installed/x64-windows/include/openssl` - -### Step 7. Running CMake to Generate Build Files +### Step 5. Running CMake to Generate Build Files Run Command Prompt from Start and run the following commands: ``` @@ -58,9 +45,9 @@ cd build cmake .. -G "Visual Studio 15 Win64" ``` -Where `%HIFI_DIR%` is the directory for the highfidelity repository. +Where `%HIFI_DIR%` is the directory for the highfidelity repository. -### Step 8. Making a Build +### Step 6. Making a Build Open `%HIFI_DIR%\build\hifi.sln` using Visual Studio. @@ -68,7 +55,7 @@ Change the Solution Configuration (menu ribbon under the menu bar, next to the g Run from the menu bar `Build > Build Solution`. -### Step 9. Testing Interface +### Step 7. Testing Interface Create another environment variable (see Step #4) * Set "Variable name": `_NO_DEBUG_HEAP` From 1a3708c49dca4479429f1ca98cca4f3ad4c601f9 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 6 Dec 2018 16:14:28 -0800 Subject: [PATCH 105/117] better drag drop fix --- scripts/system/html/js/utils.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/system/html/js/utils.js b/scripts/system/html/js/utils.js index fe96e8b79e..d61b4d1762 100644 --- a/scripts/system/html/js/utils.js +++ b/scripts/system/html/js/utils.js @@ -11,13 +11,17 @@ function disableDragDrop() { document.addEventListener("drop", function(event) { event.preventDefault(); - event.dataTransfer.effectAllowed = "none"; - event.dataTransfer.dropEffect = "none"; - }, false); + }); document.addEventListener("dragover", function(event) { - event.preventDefault(); event.dataTransfer.effectAllowed = "none"; event.dataTransfer.dropEffect = "none"; + event.preventDefault(); + }); + + document.addEventListener("dragenter", function(event) { + event.dataTransfer.effectAllowed = "none"; + event.dataTransfer.dropEffect = "none"; + event.preventDefault(); }, false); } From ca0133a2a64420731dba8972ced4c46e7668ac2b Mon Sep 17 00:00:00 2001 From: amantley Date: Thu, 6 Dec 2018 16:24:06 -0800 Subject: [PATCH 106/117] put the lean joint back in --- libraries/fbx/src/FBXSerializer.cpp | 6 ++++++ libraries/fbx/src/GLTFSerializer.cpp | 1 + libraries/hfm/src/hfm/HFM.h | 1 + 3 files changed, 8 insertions(+) diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/fbx/src/FBXSerializer.cpp index 1581204819..37108ba5d2 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -482,6 +482,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr QString jointEyeRightName = "EyeRight"; QString jointNeckName = "Neck"; QString jointRootName = "Hips"; + QString jointLeanName = "Spine"; QString jointHeadName = "Head"; QString jointLeftHandName = "LeftHand"; QString jointRightHandName = "RightHand"; @@ -489,6 +490,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr QString jointEyeRightID; QString jointNeckID; QString jointRootID; + QString jointLeanID; QString jointHeadID; QString jointLeftHandID; QString jointRightHandID; @@ -612,6 +614,9 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr } else if (name == jointRootName || (hfmModel.hfmToHifiJointNameMapping.contains(jointRootName) && (name == hfmModel.hfmToHifiJointNameMapping[jointRootName]))) { jointRootID = getID(object.properties); + } else if (name == jointLeanName || (hfmModel.hfmToHifiJointNameMapping.contains(jointLeanName) && (name == hfmModel.hfmToHifiJointNameMapping[jointLeanName]))) { + jointLeanID = getID(object.properties); + } else if ((name == jointHeadName) || (hfmModel.hfmToHifiJointNameMapping.contains(jointHeadName) && (name == hfmModel.hfmToHifiJointNameMapping[jointHeadName]))) { jointHeadID = getID(object.properties); @@ -1449,6 +1454,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr hfmModel.rightEyeJointIndex = modelIDs.indexOf(jointEyeRightID); hfmModel.neckJointIndex = modelIDs.indexOf(jointNeckID); hfmModel.rootJointIndex = modelIDs.indexOf(jointRootID); + hfmModel.leanJointIndex = modelIDs.indexOf(jointLeanID); hfmModel.headJointIndex = modelIDs.indexOf(jointHeadID); hfmModel.leftHandJointIndex = modelIDs.indexOf(jointLeftHandID); hfmModel.rightHandJointIndex = modelIDs.indexOf(jointRightHandID); diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index 5485f46905..28d377c605 100644 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1186,6 +1186,7 @@ void GLTFSerializer::hfmDebugDump(const HFMModel& hfmModel) { qCDebug(modelformat) << " rightEyeJointIndex =" << hfmModel.rightEyeJointIndex; qCDebug(modelformat) << " neckJointIndex =" << hfmModel.neckJointIndex; qCDebug(modelformat) << " rootJointIndex =" << hfmModel.rootJointIndex; + qCDebug(modelformat) << " leanJointIndex =" << hfmModel.leanJointIndex; qCDebug(modelformat) << " headJointIndex =" << hfmModel.headJointIndex; qCDebug(modelformat) << " leftHandJointIndex" << hfmModel.leftHandJointIndex; qCDebug(modelformat) << " rightHandJointIndex" << hfmModel.rightHandJointIndex; diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index 3cc12724d5..de58d864b3 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -274,6 +274,7 @@ public: int rightEyeJointIndex = -1; int neckJointIndex = -1; int rootJointIndex = -1; + int leanJointIndex = -1; int headJointIndex = -1; int leftHandJointIndex = -1; int rightHandJointIndex = -1; From f8ae0227c30f269a3fa0f5afcb603b8ecb6e761c Mon Sep 17 00:00:00 2001 From: amantley Date: Thu, 6 Dec 2018 20:16:03 -0800 Subject: [PATCH 107/117] added the lean joint back and fixed a name mapping reversal in fbxserializer.cpp --- libraries/fbx/src/FBXSerializer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/fbx/src/FBXSerializer.cpp index 37108ba5d2..67220342b8 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -1418,7 +1418,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr joint.bindTransformFoundInCluster = false; hfmModel.joints.append(joint); - hfmModel.jointIndices.insert(fbxModel.name, hfmModel.joints.size()); + hfmModel.jointIndices.insert(joint.name, hfmModel.joints.size()); QString rotationID = localRotations.value(modelID); AnimationCurve xRotCurve = animationCurves.value(xComponents.value(rotationID)); @@ -1843,7 +1843,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr glm::quat rotationOffset = itr.value(); int jointIndex = hfmModel.getJointIndex(jointName); if (hfmModel.hfmToHifiJointNameMapping.contains(jointName)) { - jointIndex = hfmModel.getJointIndex(hfmModel.hfmToHifiJointNameMapping[jointName]); + jointIndex = hfmModel.getJointIndex(jointName); } if (jointIndex != -1) { hfmModel.jointRotationOffsets.insert(jointIndex, rotationOffset); From 72a91668a5d43f3e6245e26e30645192d90e4de4 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Sat, 13 Oct 2018 00:14:33 +0300 Subject: [PATCH 108/117] FB19219 Make avatarapp to handle wearables update via drag&drop --- libraries/entities/src/EntityItem.cpp | 5 ++ libraries/entities/src/EntityItem.h | 2 +- .../entities/src/EntityScriptingInterface.cpp | 14 +++++ .../entities/src/EntityScriptingInterface.h | 27 ++++++++ libraries/entities/src/EntityTree.cpp | 1 + libraries/entities/src/EntityTree.h | 1 + libraries/entities/src/ModelEntityItem.cpp | 5 ++ libraries/entities/src/ModelEntityItem.h | 1 + scripts/system/avatarapp.js | 61 ++++++++++++++----- 9 files changed, 101 insertions(+), 16 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 5855306994..35c491a331 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -3277,4 +3277,9 @@ void EntityItem::prepareForSimulationOwnershipBid(EntityItemProperties& properti properties.setEntityHostType(getEntityHostType()); properties.setOwningAvatarID(getOwningAvatarID()); setLastBroadcast(now); // for debug/physics status icons +} + +bool EntityItem::isWearable() const { + return isVisible() && getParentJointIndex() != INVALID_JOINT_INDEX + && (getParentID() == DependencyManager::get()->getSessionUUID() || getParentID() == AVATAR_SELF_ID); } \ No newline at end of file diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 8c78dd1cd6..eb1cdf24e4 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -489,7 +489,7 @@ public: void scriptHasUnloaded(); void setScriptHasFinishedPreload(bool value); bool isScriptPreloadFinished(); - + virtual bool isWearable() const; bool isDomainEntity() const { return _hostType == entity::HostType::DOMAIN; } bool isAvatarEntity() const { return _hostType == entity::HostType::AVATAR; } bool isLocalEntity() const { return _hostType == entity::HostType::LOCAL; } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 4a634899c4..1b1853762b 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -114,6 +114,8 @@ bool EntityScriptingInterface::canReplaceContent() { void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) { if (_entityTree) { + disconnect(_entityTree.get(), &EntityTree::addingEntityPointer, this, &EntityScriptingInterface::onAddingEntity); + disconnect(_entityTree.get(), &EntityTree::deletingEntityPointer, this, &EntityScriptingInterface::onDeletingEntity); disconnect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); disconnect(_entityTree.get(), &EntityTree::deletingEntity, this, &EntityScriptingInterface::deletingEntity); disconnect(_entityTree.get(), &EntityTree::clearingEntities, this, &EntityScriptingInterface::clearingEntities); @@ -122,6 +124,8 @@ void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) { _entityTree = elementTree; if (_entityTree) { + connect(_entityTree.get(), &EntityTree::addingEntityPointer, this, &EntityScriptingInterface::onAddingEntity, Qt::DirectConnection); + connect(_entityTree.get(), &EntityTree::deletingEntityPointer, this, &EntityScriptingInterface::onDeletingEntity, Qt::DirectConnection); connect(_entityTree.get(), &EntityTree::addingEntity, this, &EntityScriptingInterface::addingEntity); connect(_entityTree.get(), &EntityTree::deletingEntity, this, &EntityScriptingInterface::deletingEntity); connect(_entityTree.get(), &EntityTree::clearingEntities, this, &EntityScriptingInterface::clearingEntities); @@ -1060,7 +1064,17 @@ void EntityScriptingInterface::handleEntityScriptCallMethodPacket(QSharedPointer } } +void EntityScriptingInterface::onAddingEntity(EntityItem* entity) { + if (entity->isWearable()) { + emit addingWearable(entity->getEntityItemID()); + } +} +void EntityScriptingInterface::onDeletingEntity(EntityItem* entity) { + if (entity->isWearable()) { + emit deletingWearable(entity->getEntityItemID()); + } +} QUuid EntityScriptingInterface::findClosestEntity(const glm::vec3& center, float radius) const { PROFILE_RANGE(script_entities, __FUNCTION__); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index ff1149fb06..0cea005ddd 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -1908,6 +1908,31 @@ signals: */ void addingEntity(const EntityItemID& entityID); + /**jsdoc + * Triggered when an 'wearable' entity is deleted. + * @function Entities.deletingWearable + * @param {Uuid} entityID - The ID of the 'wearable' entity deleted. + * @returns {Signal} + * @example Report when an 'wearable' entity is deleted. + * Entities.deletingWearable.connect(function (entityID) { + * print("Deleted wearable: " + entityID); + * }); + */ + void deletingWearable(const EntityItemID& entityID); + + /**jsdoc + * Triggered when an 'wearable' entity is added to Interface's local in-memory tree of entities it knows about. This may occur when + * 'wearable' entities are added to avatar + * @function Entities.addingWearable + * @param {Uuid} entityID - The ID of the 'wearable' entity added. + * @returns {Signal} + * @example Report when an 'wearable' entity is added. + * Entities.addingWearable.connect(function (entityID) { + * print("Added wearable: " + entityID); + * }); + */ + void addingWearable(const EntityItemID& entityID); + /**jsdoc * Triggered when you disconnect from a domain, at which time Interface's local in-memory tree of entities it knows about * is cleared. @@ -1938,6 +1963,8 @@ protected: private slots: void handleEntityScriptCallMethodPacket(QSharedPointer receivedMessage, SharedNodePointer senderNode); + void onAddingEntity(EntityItem* entity); + void onDeletingEntity(EntityItem* entity); private: bool actionWorker(const QUuid& entityID, std::function actor); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index b23be66ade..dd020da5a0 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -305,6 +305,7 @@ void EntityTree::postAddEntity(EntityItemPointer entity) { fixupNeedsParentFixups(); emit addingEntity(entity->getEntityItemID()); + emit addingEntityPointer(entity.get()); } bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode) { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index c6a590ec71..d7f93b1eb2 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -309,6 +309,7 @@ signals: void deletingEntity(const EntityItemID& entityID); void deletingEntityPointer(EntityItem* entityID); void addingEntity(const EntityItemID& entityID); + void addingEntityPointer(EntityItem* entityID); void editingEntityPointer(const EntityItemPointer& entityID); void entityScriptChanging(const EntityItemID& entityItemID, const bool reload); void entityServerScriptChanging(const EntityItemID& entityItemID, const bool reload); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index b4b00e57a7..caa67ade9a 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -519,6 +519,11 @@ QVector ModelEntityItem::getJointTranslationsSet() const { return result; } +bool ModelEntityItem::isWearable() const +{ + return isVisible() && (getParentJointIndex() != INVALID_JOINT_INDEX || getRelayParentJoints()) + && (getParentID() == DependencyManager::get()->getSessionUUID() || getParentID() == AVATAR_SELF_ID); +} bool ModelEntityItem::hasModel() const { return resultWithReadLock([&] { diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 5ca3e2caa1..3de1ebdbdc 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -123,6 +123,7 @@ public: QVector getJointTranslations() const; QVector getJointTranslationsSet() const; + virtual bool isWearable() const override; private: void setAnimationSettings(const QString& value); // only called for old bitstream format bool applyNewAnimationProperties(AnimationPropertyGroup newProperties); diff --git a/scripts/system/avatarapp.js b/scripts/system/avatarapp.js index 81a6447aae..65abf791a5 100644 --- a/scripts/system/avatarapp.js +++ b/scripts/system/avatarapp.js @@ -69,12 +69,12 @@ function getMyAvatarSettings() { } } -function updateAvatarWearables(avatar, bookmarkAvatarName, callback) { +function updateAvatarWearables(avatar, callback) { executeLater(function() { var wearables = getMyAvatarWearables(); avatar[ENTRY_AVATAR_ENTITIES] = wearables; - sendToQml({'method' : 'wearablesUpdated', 'wearables' : wearables, 'avatarName' : bookmarkAvatarName}) + sendToQml({'method' : 'wearablesUpdated', 'wearables' : wearables}) if(callback) callback(); @@ -188,7 +188,11 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See sendToQml(message) break; case 'selectAvatar': + Entities.addingWearable.disconnect(onAddingWearable); + Entities.deletingWearable.disconnect(onDeletingWearable); AvatarBookmarks.loadBookmark(message.name); + Entities.addingWearable.connect(onAddingWearable); + Entities.deletingWearable.connect(onDeletingWearable); break; case 'deleteAvatar': AvatarBookmarks.removeBookmark(message.name); @@ -223,7 +227,7 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See // revert changes using snapshot of wearables if(currentAvatarWearablesBackup !== null) { AvatarBookmarks.updateAvatarEntities(currentAvatarWearablesBackup); - updateAvatarWearables(currentAvatar, message.avatarName); + updateAvatarWearables(currentAvatar); } } else { sendToQml({'method' : 'updateAvatarInBookmarks'}); @@ -256,8 +260,11 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See parentJointIndex: hipsIndex }; + Entities.addingWearable.disconnect(onAddingWearable); var entityID = Entities.addEntity(properties, true); - updateAvatarWearables(currentAvatar, message.avatarName, function() { + Entities.addingWearable.connect(onAddingWearable); + + updateAvatarWearables(currentAvatar, function() { onSelectedEntity(entityID); }); break; @@ -265,8 +272,12 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See ensureWearableSelected(message.entityID); break; case 'deleteWearable': + + Entities.deletingWearable.disconnect(onDeletingWearable); Entities.deleteEntity(message.entityID); - updateAvatarWearables(currentAvatar, message.avatarName); + Entities.deletingWearable.connect(onDeletingWearable); + + updateAvatarWearables(currentAvatar); break; case 'changeDisplayName': if (MyAvatar.displayName !== message.displayName) { @@ -380,6 +391,18 @@ function onSelectedEntity(entityID, pointerEvent) { } } +function onAddingWearable(entityID) { + updateAvatarWearables(currentAvatar, function() { + sendToQml({'method' : 'updateAvatarInBookmarks'}); + }); +} + +function onDeletingWearable(entityID) { + updateAvatarWearables(currentAvatar, function() { + sendToQml({'method' : 'updateAvatarInBookmarks'}); + }); +} + function handleWearableMessages(channel, message, sender) { if (channel !== 'Hifi-Object-Manipulation') { return; @@ -485,6 +508,8 @@ function off() { AvatarBookmarks.bookmarkDeleted.disconnect(onBookmarkDeleted); AvatarBookmarks.bookmarkAdded.disconnect(onBookmarkAdded); + Entities.addingWearable.disconnect(onAddingWearable); + Entities.deletingWearable.disconnect(onDeletingWearable); MyAvatar.skeletonModelURLChanged.disconnect(onSkeletonModelURLChanged); MyAvatar.dominantHandChanged.disconnect(onDominantHandChanged); MyAvatar.collisionsEnabledChanged.disconnect(onCollisionsEnabledChanged); @@ -495,16 +520,23 @@ function off() { } function on() { - AvatarBookmarks.bookmarkLoaded.connect(onBookmarkLoaded); - AvatarBookmarks.bookmarkDeleted.connect(onBookmarkDeleted); - AvatarBookmarks.bookmarkAdded.connect(onBookmarkAdded); - MyAvatar.skeletonModelURLChanged.connect(onSkeletonModelURLChanged); - MyAvatar.dominantHandChanged.connect(onDominantHandChanged); - MyAvatar.collisionsEnabledChanged.connect(onCollisionsEnabledChanged); - MyAvatar.newCollisionSoundURL.connect(onNewCollisionSoundUrl); - MyAvatar.animGraphUrlChanged.connect(onAnimGraphUrlChanged); - MyAvatar.targetScaleChanged.connect(onTargetScaleChanged); + if (!isWired) { // It is not ok to connect these twice, hence guard. + isWired = true; + + AvatarBookmarks.bookmarkLoaded.connect(onBookmarkLoaded); + AvatarBookmarks.bookmarkDeleted.connect(onBookmarkDeleted); + AvatarBookmarks.bookmarkAdded.connect(onBookmarkAdded); + + Entities.addingWearable.connect(onAddingWearable); + Entities.deletingWearable.connect(onDeletingWearable); + MyAvatar.skeletonModelURLChanged.connect(onSkeletonModelURLChanged); + MyAvatar.dominantHandChanged.connect(onDominantHandChanged); + MyAvatar.collisionsEnabledChanged.connect(onCollisionsEnabledChanged); + MyAvatar.newCollisionSoundURL.connect(onNewCollisionSoundUrl); + MyAvatar.animGraphUrlChanged.connect(onAnimGraphUrlChanged); + MyAvatar.targetScaleChanged.connect(onTargetScaleChanged); + } } function onTabletButtonClicked() { @@ -514,7 +546,6 @@ function onTabletButtonClicked() { } else { ContextOverlay.enabled = false; tablet.loadQMLSource(AVATARAPP_QML_SOURCE); - isWired = true; } } var hasEventBridge = false; From 600d09e533e2c3c27ff9dbdf5c6ee44c31b36c1e Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Mon, 19 Nov 2018 00:53:51 +0530 Subject: [PATCH 109/117] relax 'isWearable()' condition to match latest changes in 'master' --- libraries/entities/src/EntityItem.cpp | 3 +-- libraries/entities/src/ModelEntityItem.cpp | 6 ------ libraries/entities/src/ModelEntityItem.h | 1 - 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 35c491a331..94d0024fd5 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -3280,6 +3280,5 @@ void EntityItem::prepareForSimulationOwnershipBid(EntityItemProperties& properti } bool EntityItem::isWearable() const { - return isVisible() && getParentJointIndex() != INVALID_JOINT_INDEX - && (getParentID() == DependencyManager::get()->getSessionUUID() || getParentID() == AVATAR_SELF_ID); + return isVisible() && (getParentID() == DependencyManager::get()->getSessionUUID() || getParentID() == AVATAR_SELF_ID); } \ No newline at end of file diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index caa67ade9a..e68e287ee2 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -519,12 +519,6 @@ QVector ModelEntityItem::getJointTranslationsSet() const { return result; } -bool ModelEntityItem::isWearable() const -{ - return isVisible() && (getParentJointIndex() != INVALID_JOINT_INDEX || getRelayParentJoints()) - && (getParentID() == DependencyManager::get()->getSessionUUID() || getParentID() == AVATAR_SELF_ID); -} - bool ModelEntityItem::hasModel() const { return resultWithReadLock([&] { return !_modelURL.isEmpty(); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 3de1ebdbdc..5ca3e2caa1 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -123,7 +123,6 @@ public: QVector getJointTranslations() const; QVector getJointTranslationsSet() const; - virtual bool isWearable() const override; private: void setAnimationSettings(const QString& value); // only called for old bitstream format bool applyNewAnimationProperties(AnimationPropertyGroup newProperties); From 92117d602c30146b88bcddc2b61a6ae17060c9ea Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 5 Dec 2018 11:20:18 -0800 Subject: [PATCH 110/117] remove cruft --- interface/src/Application_render.cpp | 240 ---------------------- interface/src/graphics/GraphicsEngine.cpp | 4 + 2 files changed, 4 insertions(+), 240 deletions(-) delete mode 100644 interface/src/Application_render.cpp diff --git a/interface/src/Application_render.cpp b/interface/src/Application_render.cpp deleted file mode 100644 index ea672e3510..0000000000 --- a/interface/src/Application_render.cpp +++ /dev/null @@ -1,240 +0,0 @@ -// -// Application_render.cpp -// interface/src -// -// Copyright 2013 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 -// - -#include "Application.h" -#include - -#include -#include -#include -#include -#include "ui/Stats.h" -#include "Util.h" - -//void Application::paintGL() { -// // Some plugins process message events, allowing paintGL to be called reentrantly. -// -// _renderFrameCount++; -// // SG: Moved into the RenderEventHandler -// //_lastTimeRendered.start(); -// -// auto lastPaintBegin = usecTimestampNow(); -// PROFILE_RANGE_EX(render, __FUNCTION__, 0xff0000ff, (uint64_t)_renderFrameCount); -// PerformanceTimer perfTimer("paintGL"); -// -// if (nullptr == _displayPlugin) { -// return; -// } -// -// DisplayPluginPointer displayPlugin; -// { -// PROFILE_RANGE(render, "/getActiveDisplayPlugin"); -// displayPlugin = getActiveDisplayPlugin(); -// } -// -// { -// PROFILE_RANGE(render, "/pluginBeginFrameRender"); -// // If a display plugin loses it's underlying support, it -// // needs to be able to signal us to not use it -// if (!displayPlugin->beginFrameRender(_renderFrameCount)) { -// QMetaObject::invokeMethod(this, "updateDisplayMode"); -// return; -// } -// } -// -// RenderArgs renderArgs; -// glm::mat4 HMDSensorPose; -// glm::mat4 eyeToWorld; -// glm::mat4 sensorToWorld; -// ViewFrustum viewFrustum; -// -// bool isStereo; -// glm::mat4 stereoEyeOffsets[2]; -// glm::mat4 stereoEyeProjections[2]; -// -// { -// QMutexLocker viewLocker(&_renderArgsMutex); -// renderArgs = _appRenderArgs._renderArgs; -// -// // don't render if there is no context. -// if (!_appRenderArgs._renderArgs._context) { -// return; -// } -// -// HMDSensorPose = _appRenderArgs._headPose; -// eyeToWorld = _appRenderArgs._eyeToWorld; -// sensorToWorld = _appRenderArgs._sensorToWorld; -// isStereo = _appRenderArgs._isStereo; -// for_each_eye([&](Eye eye) { -// stereoEyeOffsets[eye] = _appRenderArgs._eyeOffsets[eye]; -// stereoEyeProjections[eye] = _appRenderArgs._eyeProjections[eye]; -// }); -// viewFrustum = _appRenderArgs._renderArgs.getViewFrustum(); -// } -// -// { -// PROFILE_RANGE(render, "/gpuContextReset"); -// _graphicsEngine.getGPUContext()->beginFrame(_appRenderArgs._view, HMDSensorPose); -// // Reset the gpu::Context Stages -// // Back to the default framebuffer; -// gpu::doInBatch("Application_render::gpuContextReset", _graphicsEngine.getGPUContext(), [&](gpu::Batch& batch) { -// batch.resetStages(); -// }); -// -// if (isStereo) { -// renderArgs._context->enableStereo(true); -// renderArgs._context->setStereoProjections(stereoEyeProjections); -// renderArgs._context->setStereoViews(stereoEyeOffsets); -// } -// } -// -// gpu::FramebufferPointer finalFramebuffer; -// QSize finalFramebufferSize; -// { -// PROFILE_RANGE(render, "/getOutputFramebuffer"); -// // Primary rendering pass -// auto framebufferCache = DependencyManager::get(); -// finalFramebufferSize = framebufferCache->getFrameBufferSize(); -// // Final framebuffer that will be handed to the display-plugin -// finalFramebuffer = framebufferCache->getFramebuffer(); -// } -// -// if (!_programsCompiled.load()) { -// gpu::doInBatch("splashFrame", _gpuContext, [&](gpu::Batch& batch) { -// batch.setFramebuffer(finalFramebuffer); -// batch.enableSkybox(true); -// batch.enableStereo(isStereo); -// batch.setViewportTransform({ 0, 0, finalFramebuffer->getSize() }); -// _splashScreen->render(batch, viewFrustum); -// }); -// } else { -// { -// PROFILE_RANGE(render, "/renderOverlay"); -// PerformanceTimer perfTimer("renderOverlay"); -// // NOTE: There is no batch associated with this renderArgs -// // the ApplicationOverlay class assumes it's viewport is setup to be the device size -// renderArgs._viewport = glm::ivec4(0, 0, getDeviceSize()); -// _applicationOverlay.renderOverlay(&renderArgs); -// } -// -// { -// PROFILE_RANGE(render, "/updateCompositor"); -// getApplicationCompositor().setFrameInfo(_renderFrameCount, eyeToWorld, sensorToWorld); -// } -// -// { -// PROFILE_RANGE(render, "/runRenderFrame"); -// renderArgs._hudOperator = displayPlugin->getHUDOperator(); -// renderArgs._hudTexture = _applicationOverlay.getOverlayTexture(); -// renderArgs._blitFramebuffer = finalFramebuffer; -// runRenderFrame(&renderArgs); -// } -// } -// -// auto frame = _graphicsEngine.getGPUContext()->endFrame(); -// frame->frameIndex = _renderFrameCount; -// frame->framebuffer = finalFramebuffer; -// frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) { -// auto frameBufferCache = DependencyManager::get(); -// if (frameBufferCache) { -// frameBufferCache->releaseFramebuffer(framebuffer); -// } -// }; -// // deliver final scene rendering commands to the display plugin -// { -// PROFILE_RANGE(render, "/pluginOutput"); -// PerformanceTimer perfTimer("pluginOutput"); -// _renderLoopCounter.increment(); -// displayPlugin->submitFrame(frame); -// } -// -// // Reset the framebuffer and stereo state -// renderArgs._blitFramebuffer.reset(); -// renderArgs._context->enableStereo(false); -// -//#if !defined(DISABLE_QML) -// { -// auto stats = Stats::getInstance(); -// if (stats) { -// stats->setRenderDetails(renderArgs._details); -// } -// } -//#endif -// -// uint64_t lastPaintDuration = usecTimestampNow() - lastPaintBegin; -// _frameTimingsScriptingInterface.addValue(lastPaintDuration); -//} - -// WorldBox Render Data & rendering functions -// -//class WorldBoxRenderData { -//public: -// typedef render::Payload Payload; -// typedef Payload::DataPointer Pointer; -// -// int _val = 0; -// static render::ItemID _item; // unique WorldBoxRenderData -//}; -// -//render::ItemID WorldBoxRenderData::_item{ render::Item::INVALID_ITEM_ID }; -// -//namespace render { -// template <> const ItemKey payloadGetKey(const WorldBoxRenderData::Pointer& stuff) { return ItemKey::Builder::opaqueShape().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); } -// template <> const Item::Bound payloadGetBound(const WorldBoxRenderData::Pointer& stuff) { return Item::Bound(); } -// template <> void payloadRender(const WorldBoxRenderData::Pointer& stuff, RenderArgs* args) { -// if (Menu::getInstance()->isOptionChecked(MenuOption::WorldAxes)) { -// PerformanceTimer perfTimer("worldBox"); -// -// auto& batch = *args->_batch; -// DependencyManager::get()->bindSimpleProgram(batch); -// renderWorldBox(args, batch); -// } -// } -//} -// -//void Application::runRenderFrame(RenderArgs* renderArgs) { -// PROFILE_RANGE(render, __FUNCTION__); -// PerformanceTimer perfTimer("display"); -// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::runRenderFrame()"); -// -// // The pending changes collecting the changes here -// render::Transaction transaction; -// -// if (DependencyManager::get()->shouldRenderEntities()) { -// // render models... -// PerformanceTimer perfTimer("entities"); -// PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), -// "Application::runRenderFrame() ... entities..."); -// -// RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE; -// -// renderArgs->_debugFlags = renderDebugFlags; -// } -// -// // Make sure the WorldBox is in the scene -// // For the record, this one RenderItem is the first one we created and added to the scene. -// // We could move that code elsewhere but you know... -// if (!render::Item::isValidID(WorldBoxRenderData::_item)) { -// auto worldBoxRenderData = std::make_shared(); -// auto worldBoxRenderPayload = std::make_shared(worldBoxRenderData); -// -// WorldBoxRenderData::_item = _main3DScene->allocateID(); -// -// transaction.resetItem(WorldBoxRenderData::_item, worldBoxRenderPayload); -// _main3DScene->enqueueTransaction(transaction); -// } -// -// { -// PerformanceTimer perfTimer("EngineRun"); -// _renderEngine->getRenderContext()->args = renderArgs; -// _renderEngine->run(); -// } -//} - diff --git a/interface/src/graphics/GraphicsEngine.cpp b/interface/src/graphics/GraphicsEngine.cpp index b7a5e89d35..36bf3a1b97 100644 --- a/interface/src/graphics/GraphicsEngine.cpp +++ b/interface/src/graphics/GraphicsEngine.cpp @@ -56,6 +56,10 @@ void GraphicsEngine::initializeGPU(GLWidget* glwidget) { glwidget->makeCurrent(); _gpuContext = std::make_shared(); + _gpuContext->pushProgramsToSync(shader::allPrograms(), [this] { + _programsCompiled.store(true); + }, 1); + DependencyManager::get()->setGPUContext(_gpuContext); } From 8431b3b0c187db5f97566e98b960205c32316c9d Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 7 Dec 2018 10:39:10 -0800 Subject: [PATCH 111/117] correct order of mixes --- libraries/gpu/src/gpu/Color.slh | 4 ++-- libraries/render-utils/src/simple_textured.slf | 2 +- libraries/render-utils/src/simple_textured_fade.slf | 4 ++-- libraries/render-utils/src/simple_textured_unlit.slf | 4 ++-- libraries/render-utils/src/simple_textured_unlit_fade.slf | 4 ++-- libraries/render-utils/src/simple_transparent_textured.slf | 2 +- .../render-utils/src/simple_transparent_textured_fade.slf | 2 +- .../render-utils/src/simple_transparent_textured_unlit.slf | 2 +- .../src/simple_transparent_textured_unlit_fade.slf | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/libraries/gpu/src/gpu/Color.slh b/libraries/gpu/src/gpu/Color.slh index 16eb7487ed..65ddc0b01e 100644 --- a/libraries/gpu/src/gpu/Color.slh +++ b/libraries/gpu/src/gpu/Color.slh @@ -18,8 +18,8 @@ float color_scalar_sRGBToLinear(float value) { const float SRGB_ELBOW = 0.04045; - - return (value <= SRGB_ELBOW) ? value / 12.92 : pow((value + 0.055) / 1.055, 2.4); + + return mix(pow((value + 0.055) / 1.055, 2.4), value / 12.92, float(value <= SRGB_ELBOW)); } vec3 color_sRGBToLinear(vec3 srgb) { diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index 9494edb890..dbc49fcb5d 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -29,7 +29,7 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; packDeferredFragment( diff --git a/libraries/render-utils/src/simple_textured_fade.slf b/libraries/render-utils/src/simple_textured_fade.slf index 5ca21a71ac..5a9eb0688e 100644 --- a/libraries/render-utils/src/simple_textured_fade.slf +++ b/libraries/render-utils/src/simple_textured_fade.slf @@ -41,9 +41,9 @@ void main(void) { applyFade(fadeParams, _positionWS.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; - texel.a = abs(_color.a); + texel.a *= abs(_color.a); const float ALPHA_THRESHOLD = 0.999; if (texel.a < ALPHA_THRESHOLD) { diff --git a/libraries/render-utils/src/simple_textured_unlit.slf b/libraries/render-utils/src/simple_textured_unlit.slf index 2d8f228f1c..475428f0ae 100644 --- a/libraries/render-utils/src/simple_textured_unlit.slf +++ b/libraries/render-utils/src/simple_textured_unlit.slf @@ -29,9 +29,9 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; - texel.a = abs(_color.a); + texel.a *= abs(_color.a); const float ALPHA_THRESHOLD = 0.999; if (texel.a < ALPHA_THRESHOLD) { diff --git a/libraries/render-utils/src/simple_textured_unlit_fade.slf b/libraries/render-utils/src/simple_textured_unlit_fade.slf index 442be14a8e..d0ba4c13fe 100644 --- a/libraries/render-utils/src/simple_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_textured_unlit_fade.slf @@ -41,9 +41,9 @@ void main(void) { applyFade(fadeParams, _positionWS.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; - texel.a = abs(_color.a); + texel.a *= abs(_color.a); const float ALPHA_THRESHOLD = 0.999; if (texel.a < ALPHA_THRESHOLD) { diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf index 1a9d14e2fa..bd29ff2ec9 100644 --- a/libraries/render-utils/src/simple_transparent_textured.slf +++ b/libraries/render-utils/src/simple_transparent_textured.slf @@ -29,7 +29,7 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; texel.a *= abs(_color.a); diff --git a/libraries/render-utils/src/simple_transparent_textured_fade.slf b/libraries/render-utils/src/simple_transparent_textured_fade.slf index 75a88dc581..d401989f90 100644 --- a/libraries/render-utils/src/simple_transparent_textured_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_fade.slf @@ -47,7 +47,7 @@ void main(void) { applyFade(fadeParams, _positionWS.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; texel.a *= abs(_color.a); diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit.slf b/libraries/render-utils/src/simple_transparent_textured_unlit.slf index 3f4abfc730..42a8270274 100644 --- a/libraries/render-utils/src/simple_transparent_textured_unlit.slf +++ b/libraries/render-utils/src/simple_transparent_textured_unlit.slf @@ -28,7 +28,7 @@ layout(location=0) out vec4 _fragColor0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; texel.a *= abs(_color.a); diff --git a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf index e46426ec7a..afc0c94575 100644 --- a/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf +++ b/libraries/render-utils/src/simple_transparent_textured_unlit_fade.slf @@ -40,7 +40,7 @@ void main(void) { applyFade(fadeParams, _positionWS.xyz, fadeEmissive); vec4 texel = texture(originalTexture, _texCoord0); - texel = mix(color_sRGBAToLinear(texel), texel, float(_color.a <= 0.0)); + texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0)); texel.rgb *= _color.rgb; texel.a *= abs(_color.a); From 818339823c64a65fd21a120a9c7da38a4d4da7d5 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 6 Dec 2018 14:50:16 -0800 Subject: [PATCH 112/117] Add new number type in Create --- scripts/system/html/css/edit-style.css | 5 + scripts/system/html/js/entityProperties.js | 159 +++++++++++++-------- 2 files changed, 103 insertions(+), 61 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 13825119ce..5bfa5c0609 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1697,3 +1697,8 @@ input.number-slider { display: none; cursor: pointer; } + +input[type=number].hide-spinner::-webkit-inner-spin-button { + -webkit-appearance: none; + visibility: hidden; +} diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 84a1ab2a12..972c5f63be 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -75,7 +75,7 @@ const GROUPS = [ }, { label: "Parent Joint Index", - type: "number", + type: "number-draggable", propertyID: "parentJointIndex", }, { @@ -135,7 +135,7 @@ const GROUPS = [ }, { label: "Line Height", - type: "number", + type: "number-draggable", min: 0, step: 0.005, decimals: 4, @@ -183,7 +183,7 @@ const GROUPS = [ }, { label: "Light Intensity", - type: "number", + type: "number-draggable", min: 0, max: 10, step: 0.1, @@ -193,7 +193,7 @@ const GROUPS = [ }, { label: "Light Horizontal Angle", - type: "number", + type: "number-draggable", multiplier: DEGREES_TO_RADIANS, decimals: 2, unit: "deg", @@ -202,7 +202,7 @@ const GROUPS = [ }, { label: "Light Vertical Angle", - type: "number", + type: "number-draggable", multiplier: DEGREES_TO_RADIANS, decimals: 2, unit: "deg", @@ -241,7 +241,7 @@ const GROUPS = [ }, { label: "Ambient Intensity", - type: "number", + type: "number-draggable", min: 0, max: 10, step: 0.1, @@ -270,7 +270,7 @@ const GROUPS = [ }, { label: "Range", - type: "number", + type: "number-draggable", min: 5, max: 10000, step: 5, @@ -287,7 +287,7 @@ const GROUPS = [ }, { label: "Base", - type: "number", + type: "number-draggable", min: -1000, max: 1000, step: 10, @@ -298,7 +298,7 @@ const GROUPS = [ }, { label: "Ceiling", - type: "number", + type: "number-draggable", min: -1000, max: 5000, step: 10, @@ -315,7 +315,7 @@ const GROUPS = [ }, { label: "Background Blend", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -337,7 +337,7 @@ const GROUPS = [ }, { label: "Glare Angle", - type: "number", + type: "number-draggable", min: 0, max: 180, step: 1, @@ -353,7 +353,7 @@ const GROUPS = [ }, { label: "Bloom Intensity", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -363,7 +363,7 @@ const GROUPS = [ }, { label: "Bloom Threshold", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -373,7 +373,7 @@ const GROUPS = [ }, { label: "Bloom Size", - type: "number", + type: "number-draggable", min: 0, max: 2, step: 0.01, @@ -432,22 +432,22 @@ const GROUPS = [ }, { label: "Animation Frame", - type: "number", + type: "number-draggable", propertyID: "animation.currentFrame", }, { label: "First Frame", - type: "number", + type: "number-draggable", propertyID: "animation.firstFrame", }, { label: "Last Frame", - type: "number", + type: "number-draggable", propertyID: "animation.lastFrame", }, { label: "Animation FPS", - type: "number", + type: "number-draggable", propertyID: "animation.fps", }, { @@ -486,7 +486,7 @@ const GROUPS = [ }, { label: "Source Resolution", - type: "number", + type: "number-draggable", propertyID: "dpi", }, ] @@ -503,7 +503,7 @@ const GROUPS = [ }, { label: "Intensity", - type: "number", + type: "number-draggable", min: 0, step: 0.1, decimals: 1, @@ -511,7 +511,7 @@ const GROUPS = [ }, { label: "Fall-Off Radius", - type: "number", + type: "number-draggable", min: 0, step: 0.1, decimals: 1, @@ -525,14 +525,14 @@ const GROUPS = [ }, { label: "Spotlight Exponent", - type: "number", + type: "number-draggable", step: 0.01, decimals: 2, propertyID: "exponent", }, { label: "Spotlight Cut-Off", - type: "number", + type: "number-draggable", step: 0.01, decimals: 2, propertyID: "cutoff", @@ -563,7 +563,7 @@ const GROUPS = [ }, { label: "Submesh to Replace", - type: "number", + type: "number-draggable", min: 0, step: 1, propertyID: "submeshToReplace", @@ -577,7 +577,7 @@ const GROUPS = [ }, { label: "Priority", - type: "number", + type: "number-draggable", min: 0, propertyID: "priority", }, @@ -612,7 +612,7 @@ const GROUPS = [ }, { label: "Material Rotation", - type: "number", + type: "number-draggable", step: 0.1, decimals: 2, unit: "deg", @@ -636,7 +636,7 @@ const GROUPS = [ }, { label: "Lifespan", - type: "number", + type: "number-draggable", unit: "s", min: 0.01, max: 10, @@ -646,7 +646,7 @@ const GROUPS = [ }, { label: "Max Particles", - type: "number", + type: "number-draggable", min: 1, max: 10000, step: 1, @@ -667,7 +667,7 @@ const GROUPS = [ properties: [ { label: "Emit Rate", - type: "number", + type: "number-draggable", min: 1, max: 1000, step: 1, @@ -675,7 +675,7 @@ const GROUPS = [ }, { label: "Emit Speed", - type: "number", + type: "number-draggable", min: 0, max: 5, step: 0.01, @@ -684,7 +684,7 @@ const GROUPS = [ }, { label: "Speed Spread", - type: "number", + type: "number-draggable", min: 0, max: 5, step: 0.01, @@ -703,7 +703,7 @@ const GROUPS = [ }, { label: "Emit Radius Start", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -738,7 +738,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "number", + type: "number-draggable", min: 0, max: 4, step: 0.01, @@ -748,7 +748,7 @@ const GROUPS = [ }, { label: "Middle", - type: "number", + type: "number-draggable", min: 0, max: 4, step: 0.01, @@ -757,7 +757,7 @@ const GROUPS = [ }, { label: "Finish", - type: "number", + type: "number-draggable", min: 0, max: 4, step: 0.01, @@ -769,7 +769,7 @@ const GROUPS = [ }, { label: "Size Spread", - type: "number", + type: "number-draggable", min: 0, max: 4, step: 0.01, @@ -825,7 +825,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -835,7 +835,7 @@ const GROUPS = [ }, { label: "Middle", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -844,7 +844,7 @@ const GROUPS = [ }, { label: "Finish", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -856,7 +856,7 @@ const GROUPS = [ }, { label: "Alpha Spread", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -901,7 +901,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "number", + type: "number-draggable", min: -360, max: 360, step: 1, @@ -913,7 +913,7 @@ const GROUPS = [ }, { label: "Middle", - type: "number", + type: "number-draggable", min: -360, max: 360, step: 1, @@ -924,7 +924,7 @@ const GROUPS = [ }, { label: "Finish", - type: "number", + type: "number-draggable", min: -360, max: 360, step: 1, @@ -938,7 +938,7 @@ const GROUPS = [ }, { label: "Spin Spread", - type: "number", + type: "number-draggable", min: 0, max: 360, step: 1, @@ -965,7 +965,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "number", + type: "number-draggable", min: 0, max: 180, step: 1, @@ -976,7 +976,7 @@ const GROUPS = [ }, { label: "Finish", - type: "number", + type: "number-draggable", min: 0, max: 180, step: 1, @@ -993,7 +993,7 @@ const GROUPS = [ properties: [ { label: "Start", - type: "number", + type: "number-draggable", min: -180, max: 180, step: 1, @@ -1004,7 +1004,7 @@ const GROUPS = [ }, { label: "Finish", - type: "number", + type: "number-draggable", min: -180, max: 180, step: 1, @@ -1089,7 +1089,7 @@ const GROUPS = [ }, { label: "Scale", - type: "number", + type: "number-draggable", defaultValue: 100, unit: "%", buttons: [ { id: "rescale", label: "Rescale", className: "blue", onClick: rescaleDimensions }, @@ -1131,14 +1131,14 @@ const GROUPS = [ }, { label: "Clone Lifetime", - type: "number", + type: "number-draggable", unit: "s", propertyID: "cloneLifetime", showPropertyRule: { "cloneable": "true" }, }, { label: "Clone Limit", - type: "number", + type: "number-draggable", propertyID: "cloneLimit", showPropertyRule: { "cloneable": "true" }, }, @@ -1197,7 +1197,7 @@ const GROUPS = [ }, { label: "Lifetime", - type: "string", + type: "number", unit: "s", propertyID: "lifetime", }, @@ -1291,7 +1291,7 @@ const GROUPS = [ }, { label: "Linear Damping", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -1310,7 +1310,7 @@ const GROUPS = [ }, { label: "Angular Damping", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -1319,7 +1319,7 @@ const GROUPS = [ }, { label: "Bounciness", - type: "number", + type: "number-draggable", min: 0, max: 1, step: 0.01, @@ -1328,7 +1328,7 @@ const GROUPS = [ }, { label: "Friction", - type: "number", + type: "number-draggable", min: 0, max: 10, step: 0.1, @@ -1337,7 +1337,7 @@ const GROUPS = [ }, { label: "Density", - type: "number", + type: "number-draggable", min: 100, max: 10000, step: 1, @@ -1454,12 +1454,13 @@ function getPropertyInputElement(propertyID) { let property = properties[propertyID]; switch (property.data.type) { case 'string': + case 'number': case 'bool': case 'dropdown': case 'textarea': case 'texture': return property.elInput; - case 'number': + case 'number-draggable': return property.elNumber.elInput; case 'vec3': case 'vec2': @@ -1529,6 +1530,7 @@ function resetProperties() { let propertyData = property.data; switch (propertyData.type) { + case 'number': case 'string': { property.elInput.value = ""; break; @@ -1537,7 +1539,7 @@ function resetProperties() { property.elInput.checked = false; break; } - case 'number': { + case 'number-draggable': { if (propertyData.defaultValue !== undefined) { property.elNumber.setValue(propertyData.defaultValue); } else { @@ -1873,7 +1875,33 @@ function createBoolProperty(property, elProperty) { return elInput; } -function createNumberProperty(property, elProperty) { +function createNumberProperty(property, elProperty) { + let elementID = property.elementID; + let propertyData = property.data; + + elProperty.className = "text"; + + let elInput = createElementFromHTML(` + + `) + + + elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); + + elProperty.appendChild(elInput); + + if (propertyData.buttons !== undefined) { + addButtons(elProperty, elementID, propertyData.buttons, false); + } + + return elInput; +} + +function createNumberSpinnerProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; @@ -2217,7 +2245,11 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI break; } case 'number': { - property.elNumber = createNumberProperty(property, elProperty); + property.elInput = createNumberProperty(property, elProperty); + break; + } + case 'number-draggable': { + property.elNumber = createNumberSpinnerProperty(property, elProperty); break; } case 'vec3': { @@ -3098,6 +3130,7 @@ function loaded() { let isPropertyNotNumber = false; switch (propertyData.type) { case 'number': + case 'number-draggable': isPropertyNotNumber = isNaN(propertyValue) || propertyValue === null; break; case 'vec3': @@ -3130,6 +3163,10 @@ function loaded() { break; } case 'number': { + property.elInput.value = propertyValue; + break; + } + case 'number-draggable': { let multiplier = propertyData.multiplier !== undefined ? propertyData.multiplier : 1; let value = propertyValue / multiplier; if (propertyData.round !== undefined) { From c9ab5c23eab77cbb92fb717cab9671fa45cdd35d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 6 Dec 2018 15:30:11 -0800 Subject: [PATCH 113/117] Add support for min/max/step/defaultValue on number field --- scripts/system/html/js/entityProperties.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 972c5f63be..cfead83851 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1533,6 +1533,11 @@ function resetProperties() { case 'number': case 'string': { property.elInput.value = ""; + if (propertyData.defaultValue !== undefined) { + property.elInput.setValue(propertyData.defaultValue); + } else { + property.elInput.setValue(""); + } break; } case 'bool': { @@ -1889,6 +1894,18 @@ function createNumberProperty(property, elProperty) { ${propertyData.readOnly ? 'readonly' : ''}> `) + 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); + } + if (propertyData.defaultValue !== undefined) { + elInput.value = propertyData.defaultValue; + } elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); From f42c31ca36c311432cafaaa679e8dc3ae330a01f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 6 Dec 2018 15:35:25 -0800 Subject: [PATCH 114/117] Update number property to reuse numberdraggable emit function --- scripts/system/html/js/entityProperties.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index cfead83851..1717f31832 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1532,11 +1532,10 @@ function resetProperties() { switch (propertyData.type) { case 'number': case 'string': { - property.elInput.value = ""; if (propertyData.defaultValue !== undefined) { - property.elInput.setValue(propertyData.defaultValue); + property.elInput.value = propertyData.defaultValue; } else { - property.elInput.setValue(""); + property.elInput.value = ""; } break; } @@ -1907,7 +1906,7 @@ function createNumberProperty(property, elProperty) { elInput.value = propertyData.defaultValue; } - elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); + elInput.addEventListener('change', createEmitNumberPropertyUpdateFunction(property)); elProperty.appendChild(elInput); @@ -1918,7 +1917,7 @@ function createNumberProperty(property, elProperty) { return elInput; } -function createNumberSpinnerProperty(property, elProperty) { +function createNumberDraggableProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; @@ -2266,7 +2265,7 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI break; } case 'number-draggable': { - property.elNumber = createNumberSpinnerProperty(property, elProperty); + property.elNumber = createNumberDraggableProperty(property, elProperty); break; } case 'vec3': { From bf844e047240cde91502e1e0e135d2e4bd1c45a3 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 5 Dec 2018 16:07:45 -0800 Subject: [PATCH 115/117] Add hiding of certified properties in Create --- scripts/system/html/js/entityList.js | 8 ++++-- scripts/system/html/js/entityProperties.js | 33 ++++++++++++++++------ scripts/system/libraries/entityList.js | 3 +- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index 9e6eb3311a..89b56c7f7b 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -23,6 +23,7 @@ const SCROLLBAR_WIDTH = 20; const RESIZER_WIDTH = 10; const DELTA_X_MOVE_COLUMNS_THRESHOLD = 2; const DELTA_X_COLUMN_SWAP_POSITION = 5; +const CERTIFIED_PLACEHOLDER = "** Certified **"; const COLUMNS = { type: { @@ -635,10 +636,11 @@ function loaded() { id: entity.id, name: entity.name, type: type, - url: filename, - fullUrl: entity.url, + url: entity.certificateID === "" ? filename : "" + CERTIFIED_PLACEHOLDER + "", + fullUrl: entity.certificateID === "" ? filename : CERTIFIED_PLACEHOLDER, locked: entity.locked, visible: entity.visible, + certificateID: entity.certificateID, verticesCount: displayIfNonZero(entity.verticesCount), texturesCount: displayIfNonZero(entity.texturesCount), texturesSize: decimalMegabytes(entity.texturesSize), @@ -876,7 +878,7 @@ function loaded() { if (column.data.glyph) { elCell.innerHTML = itemData[column.data.propertyID] ? column.data.columnHeader : null; } else { - elCell.innerText = itemData[column.data.propertyID]; + elCell.innerHTML = itemData[column.data.propertyID]; } elCell.style = "min-width:" + column.widthPx + "px;" + "max-width:" + column.widthPx + "px;"; elCell.className = createColumnClassName(column.columnID); diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 84a1ab2a12..c39761e311 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -390,7 +390,9 @@ const GROUPS = [ { label: "Model", type: "string", + placeholder: "URL", propertyID: "modelURL", + hideIfCertified: true, }, { label: "Collision Shape", @@ -404,11 +406,13 @@ const GROUPS = [ label: "Compound Shape", type: "string", propertyID: "compoundShapeURL", + hideIfCertified: true, }, { label: "Animation", type: "string", propertyID: "animation.url", + hideIfCertified: true, }, { label: "Play Automatically", @@ -460,6 +464,7 @@ const GROUPS = [ type: "textarea", propertyID: "originalTextures", readOnly: true, + hideIfCertified: true, }, ] }, @@ -1181,6 +1186,7 @@ const GROUPS = [ buttons: [ { id: "reload", label: "F", className: "glyph", onClick: reloadScripts } ], propertyID: "script", placeholder: "URL", + hideIfCertified: true, }, { label: "Server Script", @@ -1267,6 +1273,7 @@ const GROUPS = [ placeholder: "URL", propertyID: "collisionSoundURL", showPropertyRule: { "collisionless": "false" }, + hideIfCertified: true, }, { label: "Dynamic", @@ -3084,6 +3091,15 @@ function loaded() { showGroupsForType(selectedEntityProperties.type); + if (selectedEntityProperties.locked) { + disableProperties(); + getPropertyInputElement("locked").removeAttribute('disabled'); + } else { + enableProperties(); + disableSaveUserDataButton(); + disableSaveMaterialDataButton() + } + for (let propertyID in properties) { let property = properties[propertyID]; let propertyData = property.data; @@ -3094,6 +3110,14 @@ function loaded() { if (propertyValue === undefined && !isSubProperty) { continue; } + + if (propertyData.hideIfCertified) { + let shouldHide = selectedEntityProperties.certificateID !== ""; + if (shouldHide) { + propertyValue = "** Certified **"; + } + property.elInput.disabled = shouldHide; + } let isPropertyNotNumber = false; switch (propertyData.type) { @@ -3272,15 +3296,6 @@ function loaded() { hideMaterialDataSaved(); } - if (selectedEntityProperties.locked) { - disableProperties(); - getPropertyInputElement("locked").removeAttribute('disabled'); - } else { - enableProperties(); - disableSaveUserDataButton(); - disableSaveMaterialDataButton() - } - let activeElement = document.activeElement; if (doSelectElement && typeof activeElement.select !== "undefined") { activeElement.select(); diff --git a/scripts/system/libraries/entityList.js b/scripts/system/libraries/entityList.js index eeb16fd60d..f27ab6caf2 100644 --- a/scripts/system/libraries/entityList.js +++ b/scripts/system/libraries/entityList.js @@ -164,7 +164,7 @@ EntityListTool = function(shouldUseEditTabletApp) { var cameraPosition = Camera.position; PROFILE("getMultipleProperties", function () { var multipleProperties = Entities.getMultipleEntityProperties(ids, ['name', 'type', 'locked', - 'visible', 'renderInfo', 'modelURL', 'materialURL', 'script']); + 'visible', 'renderInfo', 'modelURL', 'materialURL', 'script', 'certificateID']); for (var i = 0; i < multipleProperties.length; i++) { var properties = multipleProperties[i]; @@ -182,6 +182,7 @@ EntityListTool = function(shouldUseEditTabletApp) { url: url, locked: properties.locked, visible: properties.visible, + certificateID: properties.certificateID, verticesCount: (properties.renderInfo !== undefined ? valueIfDefined(properties.renderInfo.verticesCount) : ""), texturesCount: (properties.renderInfo !== undefined ? From 51fd742722e9919ae8b0f2d11b899577351557d5 Mon Sep 17 00:00:00 2001 From: birarda Date: Fri, 7 Dec 2018 11:17:44 -0800 Subject: [PATCH 116/117] fix for initial send of non-instanced trait --- libraries/avatars/src/ClientTraitsHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars/src/ClientTraitsHandler.cpp b/libraries/avatars/src/ClientTraitsHandler.cpp index cbc8e93745..3e24c1f9ad 100644 --- a/libraries/avatars/src/ClientTraitsHandler.cpp +++ b/libraries/avatars/src/ClientTraitsHandler.cpp @@ -104,7 +104,7 @@ void ClientTraitsHandler::sendChangedTraitsToMixer() { // we double check that it is a simple iterator here auto traitType = static_cast(std::distance(traitStatusesCopy.simpleCBegin(), simpleIt)); - if (_shouldPerformInitialSend || *simpleIt == Updated) { + if (initialSend || *simpleIt == Updated) { if (traitType == AvatarTraits::SkeletonModelURL) { _owningAvatar->packTrait(traitType, *traitsPacketList); From 177a94b9a990a79056d090c9aaa3ef7fd5cfc5c2 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Dec 2018 14:01:29 -0800 Subject: [PATCH 117/117] fix realod all scripts functionality --- libraries/script-engine/src/ScriptEngines.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 399ccf1919..e198502b3d 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -31,6 +31,8 @@ static const QUrl DEFAULT_SCRIPTS_LOCATION { "file:///~//defaultScripts.js" }; // Using a QVariantList so this is human-readable in the settings file static Setting::Handle runningScriptsHandle(SETTINGS_KEY, { QVariant(DEFAULT_SCRIPTS_LOCATION) }); +const int RELOAD_ALL_SCRIPTS_TIMEOUT = 1000; + ScriptsModel& getScriptsModel() { static ScriptsModel scriptsModel; @@ -386,15 +388,10 @@ void ScriptEngines::stopAllScripts(bool restart) { // queue user scripts if restarting if (restart && scriptEngine->isUserLoaded()) { _isReloading = true; - bool lastScript = (it == _scriptEnginesHash.constEnd() - 1); ScriptEngine::Type type = scriptEngine->getType(); - connect(scriptEngine.data(), &ScriptEngine::finished, this, [this, type, lastScript] (QString scriptName) { + connect(scriptEngine.data(), &ScriptEngine::finished, this, [this, type] (QString scriptName) { reloadScript(scriptName, true)->setType(type); - - if (lastScript) { - _isReloading = false; - } }); } @@ -404,6 +401,9 @@ void ScriptEngines::stopAllScripts(bool restart) { if (restart) { qCDebug(scriptengine) << "stopAllScripts -- emitting scriptsReloading"; + QTimer::singleShot(RELOAD_ALL_SCRIPTS_TIMEOUT, this, [&] { + _isReloading = false; + }); emit scriptsReloading(); } }