From 11a240e2db79671bbd1a41b4a3909034afc1d83f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 18 Jun 2018 12:47:13 -0700 Subject: [PATCH 001/100] 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/100] 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/100] 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/100] 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/100] 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/100] 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/100] 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/100] 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/100] 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/100] 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/100] 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 ebfae17a40eb297d63d344b431954a882f53611c Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Fri, 2 Nov 2018 13:28:33 -0700 Subject: [PATCH 012/100] "Works" on Mac --- interface/src/Application.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 30b5e3ed5f..438d200de2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3636,12 +3636,6 @@ void Application::onPresent(quint32 frameCount) { if (_renderEventHandler && !isAboutToQuit() && _pendingRenderEvent.compare_exchange_strong(expected, true)) { postEvent(_renderEventHandler, new QEvent((QEvent::Type)ApplicationEvent::Render)); } - - // This is done here so it won't be during a resize/move event - if (_setGeometryRequested) { - _setGeometryRequested = false; - _window->setGeometry(requestedGeometry); - } } static inline bool isKeyEvent(QEvent::Type type) { @@ -4809,6 +4803,12 @@ void Application::idle() { _idleLoopStdev.reset(); } } + + // This is done here so it won't be during a resize/move event + if (_setGeometryRequested) { + _setGeometryRequested = false; + _window->setGeometry(requestedGeometry); + } _overlayConductor.update(secondsSinceLastUpdate); From 53b7cc13761c073e88dbf976ee201f402ed49117 Mon Sep 17 00:00:00 2001 From: vladest Date: Sat, 17 Nov 2018 15:06:25 +0100 Subject: [PATCH 013/100] Fix QML achoring warnings on Layouts --- interface/resources/qml/hifi/tablet/TabletHome.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletHome.qml b/interface/resources/qml/hifi/tablet/TabletHome.qml index f1f54e8419..1b0165ea94 100644 --- a/interface/resources/qml/hifi/tablet/TabletHome.qml +++ b/interface/resources/qml/hifi/tablet/TabletHome.qml @@ -61,7 +61,7 @@ Item { RalewaySemiBold { text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in") horizontalAlignment: Text.AlignRight - anchors.right: parent.right + Layout.alignment: Qt.AlignRight font.pixelSize: 20 color: "#afafaf" } @@ -71,7 +71,7 @@ Item { height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0 text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : "" horizontalAlignment: Text.AlignRight - anchors.right: parent.right + Layout.alignment: Qt.AlignRight font.pixelSize: 20 color: "#afafaf" } From 932d1dbcd735d4b5e6a69afd07903a8cc3ce5999 Mon Sep 17 00:00:00 2001 From: vladest Date: Sat, 17 Nov 2018 17:20:02 +0100 Subject: [PATCH 014/100] Fixed width binding loop warning --- interface/resources/qml/LoginDialog/LinkAccountBody.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 103761236d..3e4614c342 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -23,6 +23,8 @@ Item { width: root.pane.width property bool failAfterSignUp: false + onWidthChanged: d.resize(); + function login() { flavorText.visible = false mainTextContainer.visible = false @@ -127,7 +129,7 @@ Item { Column { id: form width: parent.width - onHeightChanged: d.resize(); onWidthChanged: d.resize(); + onHeightChanged: d.resize(); anchors { top: mainTextContainer.bottom From 837b321004e0901330c5f131753911f67b734495 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sat, 17 Nov 2018 10:35:05 -0800 Subject: [PATCH 015/100] 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: Mon, 19 Nov 2018 10:31:06 -0800 Subject: [PATCH 016/100] WIP - Readme to install on Mac. --- tools/nitpick/README.md | 162 +++++++++++++++++++++------------------- 1 file changed, 85 insertions(+), 77 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index e8129ae29e..aeafdc3384 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -12,70 +12,78 @@ Nitpick has 5 functions, separated into 4 tabs: 1. Evaluating the results of running tests 1. Web interface -## Installation -### Executable -1. On Windows: download the installer by browsing to [here](). -2. Double click on the installer and install to a convenient location +## Build +Nitpick is built as part of the High Fidelity build. +### Creating installers +#### Windows +1. Verify that 7Zip is installed. +1. cd to the `build\tools\nitpick\Release` directory +1. Delete any existing installers (named nitpick-installer-###.exe) +1. Select all, right-click and select 7-Zip->Add to archive... +1. Set Archive format to 7z +1. Check "Create SFX archive +1. Enter installer name (i.e. `nitpick-installer-v1.0.exe`) +1. Click "OK" +1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.0.exe: aws s3 cp nitpick-installer-v1.0.exe s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.exe +#### Mac +1. (First time) install create-dmg: + `brew install create-dmg` +1. cd to the `build/tools/nitpick/Release` folder +1. Delete any existing installer: `rm nitpick.dmg` +1. Create installer: `create-dmg --volname nitpick-installer-v1.0 nitpick-installer-v1.0.dmg "source_folder/" +1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Mac/nitpick-installer-v1.0.dmg: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.0.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.dmg` +### Installation +#### Windows +1. Download the installer by browsing to [here](). +1. (First time) download and install vc_redist.x64.exe (available at https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.0.exe) +1. (First time) download and install Python 3 from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/python-3.7.0-amd64.exe (also located at https://www.python.org/downloads/) + 1. After installation - create an environment variable called PYTHON_PATH and set it to the folder containing the Python executable. +1. (First time) download and install AWS CLI from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/AWSCLI64PY3.msi (also available at https://aws.amazon.com/cli/ + 1. Open a new command prompt and run `aws configure` + 1. Enter the AWS account number + 1. Enter the secret key + 1. Leave region name and ouput format as default [None] + 1. Install the latest release of Boto3 via pip: `pip install boto3` + +1. Double click on the installer and install to a convenient location ![](./setup_7z.PNG) -3. To run nitpick, double click **nitpick.exe**. -### Python -The TestRail interface requires Python 3 to be installed. Nitpick has been tested with Python 3.7.0 but should work with newer versions. - -Python 3 can be downloaded from: -1. Windows installer -2. Linux (source) (**Gzipped source tarball**) -3. Mac (**macOS 64-bit/32-bit installer** or **macOS 64-bit/32-bit installer**) - -#### Windows -After installation - create an environment variable called PYTHON_PATH and set it to the folder containing the Python executable. - -#### Mac -After installation - run `open "/Applications/Python 3.6/Install Certificates.command"`. This is needed because the Mac Python supplied no longer links with the deprecated Apple-supplied system OpenSSL libraries but rather supplies a private copy of OpenSSL 1.0.2 which does not automatically access the system default root certificates. -Verify that `/usr/local/bin/python3` exists. - -### AWS interface -#### Windows -1. Download the AWS CLI from `https://aws.amazon.com/cli/` -1. Install (installer is named `AWSCLI64PY3.msi`) -1. Open a new command prompt and run `aws configure` -1. Enter the AWS account number -1. Enter the secret key -1. Leave region name and ouput format as default [None] -1. Install the latest release of Boto3 via pip: -pip install boto3 -#### Mac -1. Install pip with the script provided by the Python Packaging Authority: +1. To run nitpick, double click **nitpick.exe** +####Mac +1. DOWNLOAD INSTALLER +1. Install Python from https://www.python.org/downloads/release/python-370/ (**macOS 64-bit installer** or **macOS 64-bit/32-bit installer**) + 1. After installation - run `open "/Applications/Python 3.6/Install Certificates.command"`. This is needed because the Mac Python supplied no longer links with the deprecated Apple-supplied system OpenSSL libraries but rather supplies a private copy of OpenSSL 1.0.2 which does not automatically access the system default root certificates. + 1. Verify that `/usr/local/bin/python3` exists. +1. (First time - AWS interface) Install pip with the script provided by the Python Packaging Authority: $ curl -O https://bootstrap.pypa.io/get-pip.py $ python3 get-pip.py --user + 1. Use pip to install the AWS CLI. + $ pip3 install awscli --upgrade --user + This will install aws in your user. For user XXX, aws will be located in ~/Library/Python/3.7/bin + 1. Open a new command prompt and run `aws configure` + 1. Enter the AWS account number + 1. Enter the secret key + 1. Leave region name and ouput format as default [None] + 1. Install the latest release of Boto3 via pip: pip3 install boto3 -1. Use pip to install the AWS CLI. -$ pip3 install awscli --upgrade --user -This will install aws in your user. For user XXX, aws will be located in /Users/XXX/Library/Python/3.7/bin -1. Open a new command prompt and run `aws configure` -1. Enter the AWS account number -1. Enter the secret key -1. Leave region name and ouput format as default [None] -1. Install the latest release of Boto3 via pip: -pip3 install boto3 - -# Create +#Use +## Create ![](./Create.PNG) The Create tab provides functions to create tests from snapshots, MD files, a test outline and recursive scripts. -## Create Tests -### Usage +### Create Tests +#### Usage This function is used to create/update Expected Images after a successful run of a test, or multiple tests. The user will be asked for the snapshot folder and then the tests root folder. All snapshots located in the snapshot folder will be used to create or update the expected images in the relevant tests. -### Details +#### Details As an example - if the snapshots folder contains an image named `tests.content.entity.zone.zoneOrientation.00003.png`, then this file will be copied to `tests/contente/enity/zone/zoneOrientation/ExpectedImage0003.png`. -## Create Tests Outline -### Usage +### Create Tests Outline +#### Usage This function creates an MD file in the (user-selected) tests root folder. The file provides links to both the tests and the MD files. -## Create MD file -### Usage +### Create MD file +#### Usage This function creates a file named `test.md` from a `test.js` script. The user will be asked for the folder containing the test script: -### Details +#### Details The process to produce the MD file is a simplistic parse of the test script. - The string in the `nitpick.perform(...)` function call will be the title of the file @@ -86,25 +94,25 @@ The process to produce the MD file is a simplistic parse of the test script. - The step description is the string in the addStep/addStepStepSnapshot commands - Image links are provided where applicable to the local Expected Images files -## Create all MD files -### Usage +### Create all MD files +#### Usage This function creates all MD files recursively from the user-selected root folder. This can be any folder in the tests hierarchy (e.g. all engine\material tests). The file provides a hierarchal list of all the tests -## Create testAuto script -### Usage +### Create testAuto script +#### Usage This function creates a script named `testAuto.js` in a user-selected test folder. -### Details +#### Details The script created runs the `test.js` script in the folder in automatic mode. The script is the same for all tests. -## Create all testAuto scripts -### Usage +### Create all testAuto scripts +#### Usage This function creates all testAuto scripts recursively from the user-selected root folder. This can be any folder in the tests hierarchy (e.g. all engine\material tests). The file provides a hierarchical list of all the tests -## Create Recursive Script -### Usage +### Create Recursive Script +#### Usage After the user selects a folder within the tests hierarchy, a script is created, named `testRecursive.js`. This script calls all `test.js` scripts in the sub-folders. -### Details +#### Details The various scripts are called in alphabetical order. An example of a recursive script is as follows: @@ -130,18 +138,18 @@ Script.include(testsRootPath + "content/overlay/layer/drawHUDLayer/test.js"); nitpick.runRecursive(); ``` -## Create all Recursive Scripts -### Usage +### Create all Recursive Scripts +#### Usage In this case all recursive scripts, from the selected folder down, are created. Running this function in the tests root folder will create (or update) all the recursive scripts. -# Windows +## Windows ![](./Windows.PNG) This tab is Windows-specific. It provides buttons to hide and show the task bar. The task bar should be hidden for all tests that use the primary camera. This is required to ensure that the snapshots are the right size. -# Run +## Run ![](./Run.PNG) The run tab is used to run tests in automatic mode. The tests require the location of a folder to store files in; this folder can safely be re-used for any number of runs (the "Working Folder"). The test script that is run is `https://github.com/highfidelity/hifi_tests/blob/master/tests/testRecursive.js`. The user can use a different branch' or even repository, if required. @@ -163,7 +171,7 @@ The working folder will ultimately contain the following: 1. The `dev-builds.xml` file, if it was downloaded. 1. The HighFidelity installer. Note that this is always named `HighFidelity-Beta-latest-dev` so as not to store too many installers over time. 1. A log file describing the runs. This file is appended to after each run. -# Evaluate +## Evaluate ![](./Evaluate.PNG) The Evaluate tab provides a single function - evaluating the results of a test run. @@ -171,11 +179,11 @@ The Evaluate tab provides a single function - evaluating the results of a test r A checkbox (defaulting to checked) runs the evaluation in interactive mode. In this mode - every failure is shown to the user, who can then decide whether to pass the test, fail it or abort the whole evaluation. If any tests have failed, then a zipped folder will be created in the snapshots folder, with a description of each failed step in each test. -### Usage +#### Usage Before starting the evaluation, make sure the GitHub user and branch are set correctly. The user should not normally be changed, but the branch may need to be set to the appropriate RC. After setting the check-box as required and pressing Evaluate - the user will be asked for the snapshots folder. -### Details +#### Details Evaluation proceeds in a number of steps: 1. A folder is created to store any failures @@ -191,7 +199,7 @@ Evaluation proceeds in a number of steps: 1. At the end of the test, the folder is zipped and the original folder is deleted. If there are no errors then the zipped folder will be empty. -# Web Interface +## Web Interface ![](./WebInterface.PNG) This tab has two functions: updating the TestRail cases, runs and results, and creating web page reports that are stored on AWS. @@ -206,8 +214,8 @@ Any access to TestRail will require the TestRail account (default is High Fideli - The Project ID defaults to 14 - Interface. - The Suite ID defaults to 1147 - Rendering. - The TestRail page provides 3 functions for writing to TestRail. -## Create Test Cases -### Usage +### Create Test Cases +#### Usage This function can either create an XML file that can then be imported into TestRail through TestRail itself, or automatically create the appropriate TestRail Sections. The user will be first asked for the tests root folder and a folder to store temporary files (this is the output folder). @@ -219,7 +227,7 @@ If Python is selected, the user will then be prompted for TestRail data. After After selecting the appropriate Release, press OK. The Python script will be created in the output folder, and the user will be prompted to run it. A busy window will appear until the process is complete. -### Details +#### Details A number of Python scripts are created: - `testrail.py` is the TestRail interface code. - `stack.py` is a simple stack class @@ -227,7 +235,7 @@ A number of Python scripts are created: - `addTestCases` is the script that writes to TestRail. In addition - a file containing all the releases will be created - `releases.txt` -## Create Run +### Create Run A Run is created from previously created Test Cases. The user will first be prompted for a temporary folder (for the Python scripts). @@ -237,7 +245,7 @@ After entering TestRail data and pressing `Accept` - the Sections combo will be After selecting the appropriate Section, press OK. The Python script will be created in the output folder, and the user will be prompted to run it. A busy window will appear until the process is complete. -### Details +#### Details A number of Python scripts are created: - `testrail.py` is the TestRail interface code. - `stack.py` is a simple stack class @@ -245,7 +253,7 @@ A number of Python scripts are created: - `addRun` is the script that writes to TestRail. In addition - a file containing all the releases will be created - `sections.txt` -## Update Run Results +### Update Run Results This function updates a Run with the results of an automated test. The user will first be prompted to enter the zipped results folder and a folder to store temporary files (this is the output folder). @@ -255,13 +263,13 @@ After entering TestRail data and pressing `Accept` - the Run combo will be popul After selecting the appropriate Run, press OK. The Python script will be created in the output folder, and the user will be prompted to run it. A busy window will appear until the process is complete. -### Details +#### Details A number of Python scripts are created: - `testrail.py` is the TestRail interface code. - `getRuns.py` reads the release names from TestRail - `addRun` is the script that writes to TestRail. In addition - a file containing all the releases will be created - `runs.txt`. -## Create Web Page +### Create Web Page This function requests a zipped results folder and converts it to a web page. The page is created in a user-selecetd working folder. If the `Update AWS` checkbox is checked then the page will also be copied to AWS, and the appropriate URL will be displayed in the window below the button. From eea89655f69e0eb0f1dbe874a041b9cb4fd179a4 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 19 Nov 2018 10:33:04 -0800 Subject: [PATCH 017/100] WIP - Readme to install on Mac. --- tools/nitpick/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index aeafdc3384..8b16319b1a 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -34,7 +34,7 @@ Nitpick is built as part of the High Fidelity build. 1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Mac/nitpick-installer-v1.0.dmg: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.0.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.dmg` ### Installation #### Windows -1. Download the installer by browsing to [here](). +1. Download the installer by browsing to [here]() 1. (First time) download and install vc_redist.x64.exe (available at https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.0.exe) 1. (First time) download and install Python 3 from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/python-3.7.0-amd64.exe (also located at https://www.python.org/downloads/) 1. After installation - create an environment variable called PYTHON_PATH and set it to the folder containing the Python executable. @@ -49,7 +49,7 @@ Nitpick is built as part of the High Fidelity build. ![](./setup_7z.PNG) 1. To run nitpick, double click **nitpick.exe** ####Mac -1. DOWNLOAD INSTALLER +1. Download the installer by browsing to [here](). 1. Install Python from https://www.python.org/downloads/release/python-370/ (**macOS 64-bit installer** or **macOS 64-bit/32-bit installer**) 1. After installation - run `open "/Applications/Python 3.6/Install Certificates.command"`. This is needed because the Mac Python supplied no longer links with the deprecated Apple-supplied system OpenSSL libraries but rather supplies a private copy of OpenSSL 1.0.2 which does not automatically access the system default root certificates. 1. Verify that `/usr/local/bin/python3` exists. From d6fbcb1668b9134b2013f72e44f801150d4cedc6 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 19 Nov 2018 11:04:09 -0800 Subject: [PATCH 018/100] remove entity highlighting --- .../controllers/controllerDispatcher.js | 4 - .../controllerModules/equipEntity.js | 6 - .../controllerModules/farActionGrabEntity.js | 84 +++------- .../highlightNearbyEntities.js | 155 ------------------ .../mouseHighlightEntities.js | 104 ------------ .../controllerModules/nearActionGrabEntity.js | 7 - .../controllerModules/nearParentGrabEntity.js | 25 +-- .../controllerModules/nearTrigger.js | 3 +- .../system/controllers/controllerScripts.js | 2 - 9 files changed, 31 insertions(+), 359 deletions(-) delete mode 100644 scripts/system/controllers/controllerModules/highlightNearbyEntities.js delete mode 100644 scripts/system/controllers/controllerModules/mouseHighlightEntities.js diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index b657faefba..2658f11989 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -129,9 +129,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); return getControllerWorldLocation(Controller.Standard.RightHand, true); }; - Selection.enableListHighlight(DISPATCHER_HOVERING_LIST, DISPATCHER_HOVERING_STYLE); - Selection.enableListToScene(DISPATCHER_HOVERING_LIST); - this.updateTimings = function () { _this.intervalCount++; var thisInterval = Date.now(); @@ -525,7 +522,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Controller.disableMapping(MAPPING_NAME); _this.pointerManager.removePointers(); Pointers.removePointer(this.mouseRayPick); - Selection.disableListHighlight(DISPATCHER_HOVERING_LIST); }; } diff --git a/scripts/system/controllers/controllerModules/equipEntity.js b/scripts/system/controllers/controllerModules/equipEntity.js index 12a69d7b27..c61e46c8eb 100644 --- a/scripts/system/controllers/controllerModules/equipEntity.js +++ b/scripts/system/controllers/controllerModules/equipEntity.js @@ -459,13 +459,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa this.dropGestureReset(); this.clearEquipHaptics(); Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - unhighlightTargetEntity(this.targetEntityID); - var message = { - hand: this.hand, - entityID: this.targetEntityID - }; - Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message)); var grabbedProperties = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES); var grabData = getGrabbableData(grabbedProperties); diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index 91119a4292..1eaed44ce2 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -84,7 +84,6 @@ Script.include("/~/system/libraries/controllers.js"); this.entityWithContextOverlay = false; this.contextOverlayTimer = false; this.locked = false; - this.highlightedEntity = null; this.reticleMinX = MARGIN; this.reticleMaxX = null; this.reticleMinY = MARGIN; @@ -410,9 +409,6 @@ Script.include("/~/system/libraries/controllers.js"); if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || (this.notPointingAtEntity(controllerData) && Window.isPhysicsEnabled()) || this.targetIsNull()) { this.endFarGrabAction(); - Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", - this.highlightedEntity); - this.highlightedEntity = null; this.restoreIgnoredEntities(); return makeRunningValues(false, [], []); } @@ -466,9 +462,6 @@ Script.include("/~/system/libraries/controllers.js"); if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) { if (controllerData.triggerClicks[this.hand]) { var entityID = rayPickInfo.objectID; - Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", - this.highlightedEntity); - this.highlightedEntity = null; var targetProps = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); if (targetProps.href !== "") { AddressManager.handleLookupString(targetProps.href); @@ -513,66 +506,43 @@ Script.include("/~/system/libraries/controllers.js"); this.startFarGrabAction(controllerData, targetProps); } } - } else { - var targetEntityID = rayPickInfo.objectID; - if (this.highlightedEntity !== targetEntityID) { - Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", - this.highlightedEntity); - var selectionTargetProps = Entities.getEntityProperties(targetEntityID, DISPATCHER_PROPERTIES); + } else if (!this.entityWithContextOverlay) { + var _this = this; - var selectionTargetObject = new TargetObject(targetEntityID, selectionTargetProps); - selectionTargetObject.parentProps = getEntityParents(selectionTargetProps); - var selectionTargetEntity = selectionTargetObject.getTargetEntity(); - - if (entityIsGrabbable(selectionTargetEntity.props) || - entityIsGrabbable(selectionTargetObject.entityProps)) { - - Selection.addToSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", rayPickInfo.objectID); + if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) { + if (_this.contextOverlayTimer) { + Script.clearTimeout(_this.contextOverlayTimer); } - this.highlightedEntity = rayPickInfo.objectID; + _this.contextOverlayTimer = false; + _this.potentialEntityWithContextOverlay = rayPickInfo.objectID; } - if (!this.entityWithContextOverlay) { - var _this = this; - - if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) { - if (_this.contextOverlayTimer) { - Script.clearTimeout(_this.contextOverlayTimer); + if (!_this.contextOverlayTimer) { + _this.contextOverlayTimer = Script.setTimeout(function () { + if (!_this.entityWithContextOverlay && + _this.contextOverlayTimer && + _this.potentialEntityWithContextOverlay === rayPickInfo.objectID) { + var props = Entities.getEntityProperties(rayPickInfo.objectID, DISPATCHER_PROPERTIES); + var pointerEvent = { + type: "Move", + id: _this.hand + 1, // 0 is reserved for hardware mouse + pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID, + rayPickInfo.intersection, props), + pos3D: rayPickInfo.intersection, + normal: rayPickInfo.surfaceNormal, + direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal), + button: "Secondary" + }; + if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) { + _this.entityWithContextOverlay = rayPickInfo.objectID; + } } _this.contextOverlayTimer = false; - _this.potentialEntityWithContextOverlay = rayPickInfo.objectID; - } - - if (!_this.contextOverlayTimer) { - _this.contextOverlayTimer = Script.setTimeout(function () { - if (!_this.entityWithContextOverlay && - _this.contextOverlayTimer && - _this.potentialEntityWithContextOverlay === rayPickInfo.objectID) { - var props = Entities.getEntityProperties(rayPickInfo.objectID, DISPATCHER_PROPERTIES); - var pointerEvent = { - type: "Move", - id: _this.hand + 1, // 0 is reserved for hardware mouse - pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID, - rayPickInfo.intersection, props), - pos3D: rayPickInfo.intersection, - normal: rayPickInfo.surfaceNormal, - direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal), - button: "Secondary" - }; - if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) { - _this.entityWithContextOverlay = rayPickInfo.objectID; - } - } - _this.contextOverlayTimer = false; - }, 500); - } + }, 500); } } } else if (this.distanceRotating) { this.distanceRotate(otherFarGrabModule); - } else if (this.highlightedEntity) { - Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", this.highlightedEntity); - this.highlightedEntity = null; } } return this.exitIfDisabled(controllerData); diff --git a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js b/scripts/system/controllers/controllerModules/highlightNearbyEntities.js deleted file mode 100644 index 403b5d5149..0000000000 --- a/scripts/system/controllers/controllerModules/highlightNearbyEntities.js +++ /dev/null @@ -1,155 +0,0 @@ -// -// highlightNearbyEntities.js -// -// Created by Dante Ruiz 2018-4-10 -// Copyright 2017 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 - - -/* global Script, MyAvatar, entityIsCloneable, Messages, print */ - -"use strict"; - -(function () { - Script.include("/~/system/libraries/controllerDispatcherUtils.js"); - Script.include("/~/system/libraries/controllers.js"); - Script.include("/~/system/libraries/cloneEntityUtils.js"); - var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); - - function differenceInArrays(firstArray, secondArray) { - var differenceArray = firstArray.filter(function(element) { - return secondArray.indexOf(element) < 0; - }); - - return differenceArray; - } - - function HighlightNearbyEntities(hand) { - this.hand = hand; - this.otherHand = hand === dispatcherUtils.RIGHT_HAND ? dispatcherUtils.LEFT_HAND : - dispatcherUtils.RIGHT_HAND; - this.highlightedEntities = []; - - this.parameters = dispatcherUtils.makeDispatcherModuleParameters( - 480, - this.hand === dispatcherUtils.RIGHT_HAND ? ["rightHand"] : ["leftHand"], - [], - 100); - - - this.isGrabable = function(controllerData, props) { - var canGrabEntity = false; - if (dispatcherUtils.entityIsGrabbable(props) || entityIsCloneable(props)) { - // if we've attempted to grab a child, roll up to the root of the tree - var groupRootProps = dispatcherUtils.findGroupParent(controllerData, props); - canGrabEntity = true; - if (!dispatcherUtils.entityIsGrabbable(groupRootProps)) { - canGrabEntity = false; - } - } - return canGrabEntity; - }; - - this.clearAll = function() { - this.highlightedEntities.forEach(function(entity) { - dispatcherUtils.unhighlightTargetEntity(entity); - }); - }; - - this.hasHyperLink = function(props) { - return (props.href !== "" && props.href !== undefined); - }; - - this.removeEntityFromHighlightList = function(entityID) { - var index = this.highlightedEntities.indexOf(entityID); - if (index > -1) { - this.highlightedEntities.splice(index, 1); - } - }; - - this.getOtherModule = function() { - var otherModule = this.hand === dispatcherUtils.RIGHT_HAND ? leftHighlightNearbyEntities : - rightHighlightNearbyEntities; - return otherModule; - }; - - this.getOtherHandHighlightedEntities = function() { - return this.getOtherModule().highlightedEntities; - }; - - this.highlightEntities = function(controllerData) { - var nearbyEntitiesProperties = controllerData.nearbyEntityProperties[this.hand]; - var otherHandHighlightedEntities = this.getOtherHandHighlightedEntities(); - var newHighlightedEntities = []; - var sensorScaleFactor = MyAvatar.sensorToWorldScale; - for (var i = 0; i < nearbyEntitiesProperties.length; i++) { - var props = nearbyEntitiesProperties[i]; - if (props.distance > dispatcherUtils.NEAR_GRAB_RADIUS * sensorScaleFactor) { - continue; - } - if (this.isGrabable(controllerData, props) || this.hasHyperLink(props)) { - dispatcherUtils.highlightTargetEntity(props.id); - if (newHighlightedEntities.indexOf(props.id) < 0) { - newHighlightedEntities.push(props.id); - } - } - } - - var unhighlightEntities = differenceInArrays(this.highlightedEntities, newHighlightedEntities); - - unhighlightEntities.forEach(function(entityID) { - if (otherHandHighlightedEntities.indexOf(entityID) < 0 ) { - dispatcherUtils.unhighlightTargetEntity(entityID); - } - }); - this.highlightedEntities = newHighlightedEntities; - }; - - this.isReady = function(controllerData) { - this.highlightEntities(controllerData); - return dispatcherUtils.makeRunningValues(false, [], []); - }; - - this.run = function(controllerData) { - return this.isReady(controllerData); - }; - } - - var handleMessage = function(channel, message, sender) { - var data; - if (sender === MyAvatar.sessionUUID) { - if (channel === 'Hifi-unhighlight-entity') { - try { - data = JSON.parse(message); - var hand = data.hand; - if (hand === dispatcherUtils.LEFT_HAND) { - leftHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID); - } else if (hand === dispatcherUtils.RIGHT_HAND) { - rightHighlightNearbyEntities.removeEntityFromHighlightList(data.entityID); - } - } catch (e) { - print("highlightNearbyEntities -- Failed to parse message: " + JSON.stringify(message)); - } - } else if (channel === 'Hifi-unhighlight-all') { - leftHighlightNearbyEntities.clearAll(); - rightHighlightNearbyEntities.clearAll(); - } - } - }; - var leftHighlightNearbyEntities = new HighlightNearbyEntities(dispatcherUtils.LEFT_HAND); - var rightHighlightNearbyEntities = new HighlightNearbyEntities(dispatcherUtils.RIGHT_HAND); - - dispatcherUtils.enableDispatcherModule("LeftHighlightNearbyEntities", leftHighlightNearbyEntities); - dispatcherUtils.enableDispatcherModule("RightHighlightNearbyEntities", rightHighlightNearbyEntities); - - function cleanup() { - dispatcherUtils.disableDispatcherModule("LeftHighlightNearbyEntities"); - dispatcherUtils.disableDispatcherModule("RightHighlightNearbyEntities"); - } - Messages.subscribe('Hifi-unhighlight-entity'); - Messages.subscribe('Hifi-unhighlight-all'); - Messages.messageReceived.connect(handleMessage); - Script.scriptEnding.connect(cleanup); -}()); diff --git a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js b/scripts/system/controllers/controllerModules/mouseHighlightEntities.js deleted file mode 100644 index 59a68d98a4..0000000000 --- a/scripts/system/controllers/controllerModules/mouseHighlightEntities.js +++ /dev/null @@ -1,104 +0,0 @@ -// -// mouseHighlightEntities.js -// -// scripts/system/controllers/controllerModules/ -// -// Created by Dante Ruiz 2018-4-11 -// Copyright 2017 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 -// - -/* jslint bitwise: true */ - -/* global Script, print, Entities, Messages, Picks, HMD, MyAvatar, isInEditMode, DISPATCHER_PROPERTIES */ - - -(function() { - Script.include("/~/system/libraries/utils.js"); - var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); - - function MouseHighlightEntities() { - this.highlightedEntity = null; - this.grabbedEntity = null; - - this.parameters = dispatcherUtils.makeDispatcherModuleParameters( - 5, - ["mouse"], - [], - 100); - - this.setGrabbedEntity = function(entity) { - this.grabbedEntity = entity; - this.highlightedEntity = null; - }; - - this.isReady = function(controllerData) { - if (HMD.active) { - if (this.highlightedEntity) { - dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); - this.highlightedEntity = null; - } - } else if (!this.grabbedEntity && !isInEditMode()) { - var pickResult = controllerData.mouseRayPick; - if (pickResult.type === Picks.INTERSECTED_ENTITY) { - var targetEntityID = pickResult.objectID; - - if (this.highlightedEntity !== targetEntityID) { - var targetProps = Entities.getEntityProperties(targetEntityID, DISPATCHER_PROPERTIES); - - if (this.highlightedEntity) { - dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); - this.highlightedEntity = null; - } - - if (dispatcherUtils.entityIsGrabbable(targetProps)) { - // highlight entity - dispatcherUtils.highlightTargetEntity(targetEntityID); - this.highlightedEntity = targetEntityID; - } - } - } else if (this.highlightedEntity) { - dispatcherUtils.unhighlightTargetEntity(this.highlightedEntity); - this.highlightedEntity = null; - } - } - - return dispatcherUtils.makeRunningValues(false, [], []); - }; - - this.run = function(controllerData) { - return this.isReady(controllerData); - }; - } - - var mouseHighlightEntities = new MouseHighlightEntities(); - dispatcherUtils.enableDispatcherModule("MouseHighlightEntities", mouseHighlightEntities); - - var handleMessage = function(channel, message, sender) { - var data; - if (sender === MyAvatar.sessionUUID) { - if (channel === 'Hifi-Object-Manipulation') { - try { - data = JSON.parse(message); - if (data.action === 'grab') { - var grabbedEntity = data.grabbedEntity; - mouseHighlightEntities.setGrabbedEntity(grabbedEntity); - } else if (data.action === 'release') { - mouseHighlightEntities.setGrabbedEntity(null); - } - } catch (e) { - print("Warning: mouseHighlightEntities -- error parsing Hifi-Object-Manipulation: " + message); - } - } - } - }; - - function cleanup() { - dispatcherUtils.disableDispatcherModule("MouseHighlightEntities"); - } - Messages.subscribe('Hifi-Object-Manipulation'); - Messages.messageReceived.connect(handleMessage); - Script.scriptEnding.connect(cleanup); -})(); diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js index 5ced6080a2..dac98a7e0a 100644 --- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js @@ -115,13 +115,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "startNearGrab", args); - unhighlightTargetEntity(this.targetEntityID); - var message = { - hand: this.hand, - entityID: this.targetEntityID - }; - - Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message)); }; // this is for when the action is going to time-out diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index f354067a77..b327b88e1b 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -11,7 +11,7 @@ TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, findHandChildEntities, TEAR_AWAY_DISTANCE, MSECS_PER_SEC, TEAR_AWAY_CHECK_TIME, - TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, highlightTargetEntity, unhighlightTargetEntity, + TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, distanceBetweenEntityLocalPositionAndBoundingBox, getGrabbableData, getGrabPointSphereOffset, DISPATCHER_PROPERTIES */ @@ -45,7 +45,6 @@ Script.include("/~/system/libraries/controllers.js"); this.autoUnequipCounter = 0; this.lastUnexpectedChildrenCheckTime = 0; this.robbed = false; - this.highlightedEntity = null; this.cloneAllowed = true; this.parameters = makeDispatcherModuleParameters( @@ -95,14 +94,7 @@ Script.include("/~/system/libraries/controllers.js"); this.startNearParentingGrabEntity = function (controllerData, targetProps) { var grabData = getGrabbableData(targetProps); Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - unhighlightTargetEntity(this.targetEntityID); - this.highlightedEntity = null; - var message = { - hand: this.hand, - entityID: this.targetEntityID - }; - Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message)); var handJointIndex; if (grabData.grabFollowsController) { handJointIndex = getControllerJointIndex(this.hand); @@ -164,8 +156,7 @@ Script.include("/~/system/libraries/controllers.js"); grabbedEntity: this.targetEntityID, joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand" })); - unhighlightTargetEntity(this.targetEntityID); - this.highlightedEntity = null; + this.grabbing = false; this.targetEntityID = null; this.robbed = false; @@ -290,15 +281,9 @@ Script.include("/~/system/libraries/controllers.js"); return makeRunningValues(false, [], []); // let nearActionGrabEntity handle it } else { this.targetEntityID = targetProps.id; - this.highlightedEntity = this.targetEntityID; - highlightTargetEntity(this.targetEntityID); return makeRunningValues(true, [this.targetEntityID], []); } } else { - if (this.highlightedEntity) { - unhighlightTargetEntity(this.highlightedEntity); - this.highlightedEntity = null; - } this.hapticTargetID = null; this.robbed = false; return makeRunningValues(false, [], []); @@ -316,8 +301,6 @@ Script.include("/~/system/libraries/controllers.js"); var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; if (!props) { // entity was deleted - unhighlightTargetEntity(this.targetEntityID); - this.highlightedEntity = null; this.grabbing = false; this.targetEntityID = null; this.hapticTargetID = null; @@ -335,12 +318,10 @@ Script.include("/~/system/libraries/controllers.js"); var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "continueNearGrab", args); } else { - // still searching / highlighting + // still searching var readiness = this.isReady(controllerData); if (!readiness.active) { this.robbed = false; - unhighlightTargetEntity(this.highlightedEntity); - this.highlightedEntity = null; return readiness; } if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) { diff --git a/scripts/system/controllers/controllerModules/nearTrigger.js b/scripts/system/controllers/controllerModules/nearTrigger.js index f4e39cfbb9..4bff4ea3f0 100644 --- a/scripts/system/controllers/controllerModules/nearTrigger.js +++ b/scripts/system/controllers/controllerModules/nearTrigger.js @@ -7,7 +7,7 @@ /* global Script, Entities, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, getGrabbableData, - Vec3, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS, unhighlightTargetEntity + Vec3, TRIGGER_OFF_VALUE, makeDispatcherModuleParameters, makeRunningValues, NEAR_GRAB_RADIUS */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -55,7 +55,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.startNearTrigger = function (controllerData) { var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "startNearTrigger", args); - unhighlightTargetEntity(this.targetEntityID); }; this.continueNearTrigger = function (controllerData) { diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index 999e448171..83fa455519 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -35,9 +35,7 @@ var CONTOLLER_SCRIPTS = [ "controllerModules/hudOverlayPointer.js", "controllerModules/mouseHMD.js", "controllerModules/scaleEntity.js", - "controllerModules/highlightNearbyEntities.js", "controllerModules/nearGrabHyperLinkEntity.js", - "controllerModules/mouseHighlightEntities.js", "controllerModules/nearTabletHighlight.js" ]; From d30334fc3a236882bbb2e5ce8c05be158542ec4f Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 19 Nov 2018 11:47:00 -0800 Subject: [PATCH 019/100] Updating on Mac --- tools/nitpick/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index 8b16319b1a..e112497aba 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -28,10 +28,14 @@ Nitpick is built as part of the High Fidelity build. #### Mac 1. (First time) install create-dmg: `brew install create-dmg` +1. Copy the quazip dynamic library: + `cp ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib ~/hifi/build/tools/nitpick/Release` +1. Change the loader instruction to find the dynamic library locally + `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib ./libquazip5.1.0.0.dylib ~/hifi/build/tools/nitpick/Release/nitpick` 1. cd to the `build/tools/nitpick/Release` folder -1. Delete any existing installer: `rm nitpick.dmg` -1. Create installer: `create-dmg --volname nitpick-installer-v1.0 nitpick-installer-v1.0.dmg "source_folder/" -1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Mac/nitpick-installer-v1.0.dmg: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.0.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.dmg` +1. Delete any existing installer: rm nitpick.dmg` +1. Create installer: `create-dmg --volname nitpick-installer-v1.0 nitpick-installer-v1.0.dmg "source_folder/"` +1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.0.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.dmg` ### Installation #### Windows 1. Download the installer by browsing to [here]() From 7ffa70d0ac3558c31811877dc6af0b66b66dbea2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 20 Nov 2018 09:36:58 +1300 Subject: [PATCH 020/100] Fix memory accumulating while Interface is minimized --- interface/src/Application.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7a30b566e9..929a27c88b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6222,6 +6222,11 @@ void Application::update(float deltaTime) { PerformanceTimer perfTimer("enqueueFrame"); getMain3DScene()->enqueueFrame(); } + + // If the display plugin is inactive then the frames won't be processed so process them here. + if (!getActiveDisplayPlugin()->isActive()) { + getMain3DScene()->processTransactionQueue(); + } } void Application::updateRenderArgs(float deltaTime) { From d4281212d6ba479644e49c2cc2b83dac814ef4dd Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 19 Nov 2018 14:32:47 -0800 Subject: [PATCH 021/100] First running version. --- tools/nitpick/README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index e112497aba..a0006cabe0 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -26,15 +26,16 @@ Nitpick is built as part of the High Fidelity build. 1. Click "OK" 1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.0.exe: aws s3 cp nitpick-installer-v1.0.exe s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.exe #### Mac +These steps assume the hifi repository has been cloned to `~/hifi`. 1. (First time) install create-dmg: `brew install create-dmg` -1. Copy the quazip dynamic library: - `cp ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib ~/hifi/build/tools/nitpick/Release` +1. Copy the quazip dynamic library to the Release: + `cp ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib ~/hifi/build/tools/nitpick/Release/` 1. Change the loader instruction to find the dynamic library locally - `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib ./libquazip5.1.0.0.dylib ~/hifi/build/tools/nitpick/Release/nitpick` + `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib ~/hifi/build/tools/nitpick/Release/libquazip5.1.dylib ~/hifi/build/tools/nitpick/Release/nitpick` 1. cd to the `build/tools/nitpick/Release` folder -1. Delete any existing installer: rm nitpick.dmg` -1. Create installer: `create-dmg --volname nitpick-installer-v1.0 nitpick-installer-v1.0.dmg "source_folder/"` +1. Delete any existing installer: `rm nitpick.dmg` +1. Create installer (note final period!): `create-dmg --volname nitpick-installer-v1.0 nitpick-installer-v1.0.dmg .` 1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.0.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.dmg` ### Installation #### Windows From a448efb45279acbae68578545f694ea42470290b Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 19 Nov 2018 16:01:53 -0800 Subject: [PATCH 022/100] WIP - Readme to install on Mac. --- tools/nitpick/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index a0006cabe0..c891ee1844 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -53,7 +53,7 @@ These steps assume the hifi repository has been cloned to `~/hifi`. 1. Double click on the installer and install to a convenient location ![](./setup_7z.PNG) 1. To run nitpick, double click **nitpick.exe** -####Mac +#### Mac 1. Download the installer by browsing to [here](). 1. Install Python from https://www.python.org/downloads/release/python-370/ (**macOS 64-bit installer** or **macOS 64-bit/32-bit installer**) 1. After installation - run `open "/Applications/Python 3.6/Install Certificates.command"`. This is needed because the Mac Python supplied no longer links with the deprecated Apple-supplied system OpenSSL libraries but rather supplies a private copy of OpenSSL 1.0.2 which does not automatically access the system default root certificates. From da60aaa5af4454861b8263fb12220789cbd54b53 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 19 Nov 2018 17:52:21 -0800 Subject: [PATCH 023/100] WIP - Readme to install on Mac. --- tools/nitpick/README.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index c891ee1844..3bbc4fbac1 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -29,17 +29,16 @@ Nitpick is built as part of the High Fidelity build. These steps assume the hifi repository has been cloned to `~/hifi`. 1. (First time) install create-dmg: `brew install create-dmg` -1. Copy the quazip dynamic library to the Release: - `cp ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib ~/hifi/build/tools/nitpick/Release/` -1. Change the loader instruction to find the dynamic library locally - `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib ~/hifi/build/tools/nitpick/Release/libquazip5.1.dylib ~/hifi/build/tools/nitpick/Release/nitpick` 1. cd to the `build/tools/nitpick/Release` folder +1. Copy the quazip dynamic library (note final period): + `cp ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib .` +1. Change the loader instruction to find the dynamic library locally + `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib libquazip5.1.dylib nitpick` 1. Delete any existing installer: `rm nitpick.dmg` -1. Create installer (note final period!): `create-dmg --volname nitpick-installer-v1.0 nitpick-installer-v1.0.dmg .` +1. Create installer (note final period): `create-dmg --volname nitpick-installer-v1.0 nitpick-installer-v1.0.dmg .` 1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.0.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.dmg` ### Installation #### Windows -1. Download the installer by browsing to [here]() 1. (First time) download and install vc_redist.x64.exe (available at https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.0.exe) 1. (First time) download and install Python 3 from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/python-3.7.0-amd64.exe (also located at https://www.python.org/downloads/) 1. After installation - create an environment variable called PYTHON_PATH and set it to the folder containing the Python executable. @@ -50,12 +49,13 @@ These steps assume the hifi repository has been cloned to `~/hifi`. 1. Leave region name and ouput format as default [None] 1. Install the latest release of Boto3 via pip: `pip install boto3` +1. Download the installer by browsing to [here]() 1. Double click on the installer and install to a convenient location ![](./setup_7z.PNG) -1. To run nitpick, double click **nitpick.exe** + +1. __To run nitpick, double click **nitpick.exe**__ #### Mac -1. Download the installer by browsing to [here](). -1. Install Python from https://www.python.org/downloads/release/python-370/ (**macOS 64-bit installer** or **macOS 64-bit/32-bit installer**) +1. (Firat time) install Python from https://www.python.org/downloads/release/python-370/ (**macOS 64-bit installer** or **macOS 64-bit/32-bit installer**) 1. After installation - run `open "/Applications/Python 3.6/Install Certificates.command"`. This is needed because the Mac Python supplied no longer links with the deprecated Apple-supplied system OpenSSL libraries but rather supplies a private copy of OpenSSL 1.0.2 which does not automatically access the system default root certificates. 1. Verify that `/usr/local/bin/python3` exists. 1. (First time - AWS interface) Install pip with the script provided by the Python Packaging Authority: @@ -69,7 +69,13 @@ $ python3 get-pip.py --user 1. Enter the secret key 1. Leave region name and ouput format as default [None] 1. Install the latest release of Boto3 via pip: pip3 install boto3 +1. Download the installer by browsing to [here](). +1. Double-click on the downloaded image to mount it +1. Create a folder for the nitpick files (e.g. ~/nitpick) +1. Copy the downloaded files to the folder + `cp -r /Volumes/nitpick-installer-v1.0/* .` +1. __To run nitpick, cd to the folder that you copied to and run `./nitpick`__ #Use ## Create ![](./Create.PNG) From e24eee897ee504a974fcf4955f979c3e0e015efb Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 19 Nov 2018 17:59:02 -0800 Subject: [PATCH 024/100] Typo. --- interface/src/Application.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 603a02ffae..fb6e8ec566 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4899,12 +4899,6 @@ void Application::idle() { _idleLoopStdev.reset(); } } - - // This is done here so it won't be during a resize/move event - if (_setGeometryRequested) { - _setGeometryRequested = false; - _window->setGeometry(requestedGeometry); - } _overlayConductor.update(secondsSinceLastUpdate); From 58408497d1177006b462625175dfb0fa6715ef98 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 19 Nov 2018 21:27:23 -0500 Subject: [PATCH 025/100] 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 026/100] 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 a2bcc9e899118fe47c0260e66f26539b3f5e4740 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 20 Nov 2018 15:19:54 -0800 Subject: [PATCH 027/100] teeny weeny typo... --- tools/nitpick/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index 3bbc4fbac1..dce3880123 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -55,7 +55,7 @@ These steps assume the hifi repository has been cloned to `~/hifi`. 1. __To run nitpick, double click **nitpick.exe**__ #### Mac -1. (Firat time) install Python from https://www.python.org/downloads/release/python-370/ (**macOS 64-bit installer** or **macOS 64-bit/32-bit installer**) +1. (First time) install Python from https://www.python.org/downloads/release/python-370/ (**macOS 64-bit installer** or **macOS 64-bit/32-bit installer**) 1. After installation - run `open "/Applications/Python 3.6/Install Certificates.command"`. This is needed because the Mac Python supplied no longer links with the deprecated Apple-supplied system OpenSSL libraries but rather supplies a private copy of OpenSSL 1.0.2 which does not automatically access the system default root certificates. 1. Verify that `/usr/local/bin/python3` exists. 1. (First time - AWS interface) Install pip with the script provided by the Python Packaging Authority: From f6ffb16103b3788078ca2cd90cf65c7562c263d4 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 20 Nov 2018 15:21:39 -0800 Subject: [PATCH 028/100] Version 1.1 --- tools/nitpick/src/ui/Nitpick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/src/ui/Nitpick.cpp b/tools/nitpick/src/ui/Nitpick.cpp index a4aef8fad5..201d6e562d 100644 --- a/tools/nitpick/src/ui/Nitpick.cpp +++ b/tools/nitpick/src/ui/Nitpick.cpp @@ -36,7 +36,7 @@ Nitpick::Nitpick(QWidget* parent) : QMainWindow(parent) { _ui.statusLabel->setText(""); _ui.plainTextEdit->setReadOnly(true); - setWindowTitle("Nitpick - v1.0"); + setWindowTitle("Nitpick - v1.1"); // Coming soon to a nitpick near you... //// _helpWindow.textBrowser->setText() From c3c41700f6a9ea8fd00782e631a9ce38c4fdbd57 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 20 Nov 2018 17:01:58 -0800 Subject: [PATCH 029/100] Can delete temporarY AppData folder and rename High Fidelity folder as a temporary folder --- tools/nitpick/src/TestRunner.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tools/nitpick/src/TestRunner.cpp b/tools/nitpick/src/TestRunner.cpp index c7823ba751..30aad70f5f 100644 --- a/tools/nitpick/src/TestRunner.cpp +++ b/tools/nitpick/src/TestRunner.cpp @@ -336,16 +336,18 @@ void TestRunner::saveExistingHighFidelityAppDataFolder() { QString dataDirectory{ "NOT FOUND" }; dataDirectory = qgetenv("USERPROFILE") + "\\AppData\\Roaming"; - +#elif defined Q_OS_MAC + QString dataDirectory{ QDir::homePath() + "/Library/Application Support" }; +#endif if (_runLatest->isChecked()) { - _appDataFolder = dataDirectory + "\\High Fidelity"; + _appDataFolder = dataDirectory + "/High Fidelity"; } else { // We are running a PR build - _appDataFolder = dataDirectory + "\\High Fidelity - " + getPRNumberFromURL(_url->text()); + _appDataFolder = dataDirectory + "/High Fidelity - " + getPRNumberFromURL(_url->text()); } _savedAppDataFolder = dataDirectory + "/" + UNIQUE_FOLDER_NAME; - if (_savedAppDataFolder.exists()) { + if (QDir(_savedAppDataFolder).exists()) { _savedAppDataFolder.removeRecursively(); } @@ -356,9 +358,6 @@ void TestRunner::saveExistingHighFidelityAppDataFolder() { // Copy an "empty" AppData folder (i.e. no entities) copyFolder(QDir::currentPath() + "/AppDataHighFidelity", _appDataFolder.path()); -#elif defined Q_OS_MAC - // TODO: find Mac equivalent of AppData -#endif } void TestRunner::createSnapshotFolder() { From 44b9b92450f9f2c884a9cad8194dcc8225c6719a Mon Sep 17 00:00:00 2001 From: sam gateau Date: Tue, 20 Nov 2018 17:32:04 -0800 Subject: [PATCH 030/100] 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 031/100] 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 4ef54cd4f277e43bcbc355a87f8019da617266e9 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 20 Nov 2018 17:45:37 -0800 Subject: [PATCH 032/100] Tests run without Interface crashing. --- tools/nitpick/src/TestRunner.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/nitpick/src/TestRunner.cpp b/tools/nitpick/src/TestRunner.cpp index 30aad70f5f..0a5002d02d 100644 --- a/tools/nitpick/src/TestRunner.cpp +++ b/tools/nitpick/src/TestRunner.cpp @@ -350,7 +350,6 @@ void TestRunner::saveExistingHighFidelityAppDataFolder() { if (QDir(_savedAppDataFolder).exists()) { _savedAppDataFolder.removeRecursively(); } - if (_appDataFolder.exists()) { // The original folder is saved in a unique name _appDataFolder.rename(_appDataFolder.path(), _savedAppDataFolder.path()); From 4c0f8b176b72ba0e66c0f50510d4fba0b4a67388 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 20 Nov 2018 19:59:43 -0800 Subject: [PATCH 033/100] No need for this after implementation of AppData on Mac. --- tools/nitpick/src/TestRunner.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/nitpick/src/TestRunner.cpp b/tools/nitpick/src/TestRunner.cpp index 0a5002d02d..9549dedb91 100644 --- a/tools/nitpick/src/TestRunner.cpp +++ b/tools/nitpick/src/TestRunner.cpp @@ -467,12 +467,7 @@ void TestRunner::runInterfaceWithTestScript() { // Move to an empty area url = "file:///~serverless/tutorial.json"; } else { -#ifdef Q_OS_WIN url = "hifi://localhost"; -#elif defined Q_OS_MAC - // TODO: Find out Mac equivalent of AppData, then this won't be needed - url = "hifi://localhost/9999,9999,9999"; -#endif } QString testScript = From eb2533d22418f0fc24b3f37f685d7235b2ae26fc Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 20 Nov 2018 20:51:20 -0800 Subject: [PATCH 034/100] Updated CMake file to include the AppData folder --- tools/nitpick/CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/nitpick/CMakeLists.txt b/tools/nitpick/CMakeLists.txt index 543b9c9b47..efb5125f69 100644 --- a/tools/nitpick/CMakeLists.txt +++ b/tools/nitpick/CMakeLists.txt @@ -50,10 +50,12 @@ if (WIN32) ) # add a custom command to copy the empty Apps/Data High Fidelity folder (i.e. - a valid folder with no entities) + # this also copied to the containing folder, to facilitate running from Visual Studio add_custom_command( TARGET ${TARGET_NAME} POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/AppDataHighFidelity" "$/AppDataHighFidelity" + COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/AppDataHighFidelity" "AppDataHighFidelity" ) # add a custom command to copy the SSL DLLs @@ -62,5 +64,12 @@ if (WIN32) POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_directory "$ENV{VCPKG_ROOT}/installed/x64-windows/bin" "$" ) +elseif (APPLE) + # add a custom command to copy the empty Apps/Data High Fidelity folder (i.e. - a valid folder with no entities) + add_custom_command( + TARGET ${TARGET_NAME} + POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/AppDataHighFidelity" "$/AppDataHighFidelity" + ) +endif () -endif () \ No newline at end of file From 2b71a82e4e59b853800a705f623744372d275d2a Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 20 Nov 2018 20:52:13 -0800 Subject: [PATCH 035/100] Updated to v1.1 --- tools/nitpick/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index dce3880123..e325be1f40 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -35,8 +35,8 @@ These steps assume the hifi repository has been cloned to `~/hifi`. 1. Change the loader instruction to find the dynamic library locally `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib libquazip5.1.dylib nitpick` 1. Delete any existing installer: `rm nitpick.dmg` -1. Create installer (note final period): `create-dmg --volname nitpick-installer-v1.0 nitpick-installer-v1.0.dmg .` -1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.0.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.dmg` +1. Create installer (note final period): `create-dmg --volname nitpick-installer-v1.1 nitpick-installer-v1.1.dmg .` +1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.1.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.1.dmg` ### Installation #### Windows 1. (First time) download and install vc_redist.x64.exe (available at https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.0.exe) From c99a8101f7a6468dd7bfe4f094321495a5419411 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 20 Nov 2018 16:48:26 -0500 Subject: [PATCH 036/100] 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 037/100] 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 038/100] 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 039/100] 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 9ee35def3dc5aa5118d064919e3b8a1152e15e37 Mon Sep 17 00:00:00 2001 From: sam gateau Date: Wed, 21 Nov 2018 15:42:35 -0800 Subject: [PATCH 040/100] 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 1e746e1b1c85233dcdf450250385e065ca76b799 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 21 Nov 2018 16:43:13 -0800 Subject: [PATCH 041/100] Swap key light directions in Create --- scripts/system/html/js/entityProperties.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 78e3cd4dc8..ce6fabd0c5 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -197,7 +197,7 @@ const GROUPS = [ multiplier: DEGREES_TO_RADIANS, decimals: 2, unit: "deg", - propertyID: "keyLight.direction.x", + propertyID: "keyLight.direction.y", showPropertyRule: { "keyLightMode": "enabled" }, }, { @@ -206,7 +206,7 @@ const GROUPS = [ multiplier: DEGREES_TO_RADIANS, decimals: 2, unit: "deg", - propertyID: "keyLight.direction.y", + propertyID: "keyLight.direction.x", showPropertyRule: { "keyLightMode": "enabled" }, }, { From 1362e7f3613949ea967b87306ed231bd5c0076b3 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Nov 2018 08:26:54 +1300 Subject: [PATCH 042/100] Fix near parent grab entity tear away distance calc --- .../controllerModules/nearParentGrabEntity.js | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index f354067a77..e5d3b055bc 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -24,15 +24,6 @@ Script.include("/~/system/libraries/controllers.js"); // XXX this.ignoreIK = (grabbableData.ignoreIK !== undefined) ? grabbableData.ignoreIK : true; // XXX this.kinematicGrab = (grabbableData.kinematic !== undefined) ? grabbableData.kinematic : NEAR_GRABBING_KINEMATIC; - // this offset needs to match the one in libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp:378 - var GRAB_POINT_SPHERE_OFFSET = { x: 0.04, y: 0.13, z: 0.039 }; // x = upward, y = forward, z = lateral - - function getGrabOffset(handController) { - var offset = getGrabPointSphereOffset(handController, true); - offset.y = -offset.y; - return Vec3.multiply(MyAvatar.sensorToWorldScale, offset); - } - function NearParentingGrabEntity(hand) { this.hand = hand; this.targetEntityID = null; @@ -178,8 +169,10 @@ Script.include("/~/system/libraries/controllers.js"); this.lastUnequipCheckTime = now; if (props.parentID === MyAvatar.SELF_ID) { var tearAwayDistance = TEAR_AWAY_DISTANCE * MyAvatar.sensorToWorldScale; - var controllerIndex = (this.hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand); - var controllerGrabOffset = getGrabOffset(controllerIndex); + var controllerIndex = + this.hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand; + var controllerGrabOffset = getGrabPointSphereOffset(controllerIndex, true); + controllerGrabOffset = Vec3.multiply(-1, controllerGrabOffset); var distance = distanceBetweenEntityLocalPositionAndBoundingBox(props, controllerGrabOffset); if (distance > tearAwayDistance) { this.autoUnequipCounter++; @@ -242,13 +235,15 @@ Script.include("/~/system/libraries/controllers.js"); // nearbyEntityProperties is already sorted by length from controller var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; var sensorScaleFactor = MyAvatar.sensorToWorldScale; + var tearAwayDistance = TEAR_AWAY_DISTANCE * sensorScaleFactor; + var nearGrabRadius = NEAR_GRAB_RADIUS * sensorScaleFactor; for (var i = 0; i < nearbyEntityProperties.length; i++) { var props = nearbyEntityProperties[i]; - var handPosition = controllerData.controllerLocations[this.hand].position; - var dist = distanceBetweenPointAndEntityBoundingBox(handPosition, props); - var distance = Vec3.distance(handPosition, props.position); - if ((dist > TEAR_AWAY_DISTANCE) || - (distance > NEAR_GRAB_RADIUS * sensorScaleFactor)) { + var grabPosition = controllerData.controllerLocations[this.hand].position; // Is offset from hand position. + var dist = distanceBetweenPointAndEntityBoundingBox(grabPosition, props); + var distance = Vec3.distance(grabPosition, props.position); + if ((dist > tearAwayDistance) || + (distance > nearGrabRadius)) { // Only smallish entities can be near grabbed. continue; } if (entityIsGrabbable(props) || entityIsCloneable(props)) { From f1dad3c465b3bcc07605470db8a6a75fca168733 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Nov 2018 08:35:02 +1300 Subject: [PATCH 043/100] Add hystersis between near parent grabbing and tearing away --- .../controllers/controllerModules/nearParentGrabEntity.js | 7 ++++--- scripts/system/libraries/controllerDispatcherUtils.js | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index e5d3b055bc..db10fff69a 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -12,7 +12,8 @@ findGroupParent, Vec3, cloneEntity, entityIsCloneable, propsAreCloneDynamic, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, findHandChildEntities, TEAR_AWAY_DISTANCE, MSECS_PER_SEC, TEAR_AWAY_CHECK_TIME, TEAR_AWAY_COUNT, distanceBetweenPointAndEntityBoundingBox, print, Uuid, highlightTargetEntity, unhighlightTargetEntity, - distanceBetweenEntityLocalPositionAndBoundingBox, getGrabbableData, getGrabPointSphereOffset, DISPATCHER_PROPERTIES + distanceBetweenEntityLocalPositionAndBoundingBox, getGrabbableData, getGrabPointSphereOffset, DISPATCHER_PROPERTIES, + NEAR_GRAB_DISTANCE */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); @@ -235,14 +236,14 @@ Script.include("/~/system/libraries/controllers.js"); // nearbyEntityProperties is already sorted by length from controller var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand]; var sensorScaleFactor = MyAvatar.sensorToWorldScale; - var tearAwayDistance = TEAR_AWAY_DISTANCE * sensorScaleFactor; + var nearGrabDistance = NEAR_GRAB_DISTANCE * sensorScaleFactor; var nearGrabRadius = NEAR_GRAB_RADIUS * sensorScaleFactor; for (var i = 0; i < nearbyEntityProperties.length; i++) { var props = nearbyEntityProperties[i]; var grabPosition = controllerData.controllerLocations[this.hand].position; // Is offset from hand position. var dist = distanceBetweenPointAndEntityBoundingBox(grabPosition, props); var distance = Vec3.distance(grabPosition, props.position); - if ((dist > tearAwayDistance) || + if ((dist > nearGrabDistance) || (distance > nearGrabRadius)) { // Only smallish entities can be near grabbed. continue; } diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index e9d5255d28..ab2801087e 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -53,6 +53,7 @@ TEAR_AWAY_DISTANCE:true, TEAR_AWAY_COUNT:true, TEAR_AWAY_CHECK_TIME:true, + NEAR_GRAB_DISTANCE: true, distanceBetweenPointAndEntityBoundingBox:true, entityIsEquipped:true, entityIsFarGrabbedByOther:true, @@ -99,6 +100,10 @@ NEAR_GRAB_RADIUS = 1.0; TEAR_AWAY_DISTANCE = 0.15; // ungrab an entity if its bounding-box moves this far from the hand TEAR_AWAY_COUNT = 2; // multiply by TEAR_AWAY_CHECK_TIME to know how long the item must be away TEAR_AWAY_CHECK_TIME = 0.15; // seconds, duration between checks + +NEAR_GRAB_DISTANCE = 0.14; // Grab an entity if its bounding box is within this distance. +// Smaller than TEAR_AWAY_DISTANCE for hysteresis. + DISPATCHER_HOVERING_LIST = "dispactherHoveringList"; DISPATCHER_HOVERING_STYLE = { isOutlineSmooth: true, From 29c268df5ae0e4c9bf03543d9b96047da74f8490 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Nov 2018 11:38:54 +1300 Subject: [PATCH 044/100] Remove extraneous grab entity haptic pulses --- .../controllers/controllerModules/farParentGrabEntity.js | 6 ------ .../controllerModules/nearActionGrabEntity.js | 7 ------- .../controllerModules/nearParentGrabEntity.js | 9 --------- 3 files changed, 22 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farParentGrabEntity.js b/scripts/system/controllers/controllerModules/farParentGrabEntity.js index f85869aa7f..4b85c6d046 100644 --- a/scripts/system/controllers/controllerModules/farParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farParentGrabEntity.js @@ -256,7 +256,6 @@ Script.include("/~/system/libraries/controllers.js"); }; this.endFarParentGrab = function (controllerData) { - this.hapticTargetID = null; // var endProps = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; var endProps = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES); if (this.thisFarGrabJointIsParent(endProps)) { @@ -410,11 +409,6 @@ Script.include("/~/system/libraries/controllers.js"); if (targetEntity) { var gtProps = Entities.getEntityProperties(targetEntity, DISPATCHER_PROPERTIES); if (entityIsGrabbable(gtProps)) { - // give haptic feedback - if (gtProps.id !== this.hapticTargetID) { - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - this.hapticTargetID = gtProps.id; - } // if we've attempted to grab a child, roll up to the root of the tree var groupRootProps = findGroupParent(controllerData, gtProps); if (entityIsGrabbable(groupRootProps)) { diff --git a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js index 5ced6080a2..1d1f89e2c7 100644 --- a/scripts/system/controllers/controllerModules/nearActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearActionGrabEntity.js @@ -24,7 +24,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); this.hand = hand; this.targetEntityID = null; this.actionID = null; // action this script created... - this.hapticTargetID = null; this.parameters = makeDispatcherModuleParameters( 500, @@ -171,10 +170,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); break; } if (entityIsGrabbable(props) || entityIsCloneable(props)) { - if (props.id !== this.hapticTargetID) { - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - this.hapticTargetID = props.id; - } if (!entityIsCloneable(props)) { // if we've attempted to grab a non-cloneable child, roll up to the root of the tree var groupRootProps = findGroupParent(controllerData, props); @@ -206,7 +201,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); return makeRunningValues(true, [this.targetEntityID], []); } } else { - this.hapticTargetID = null; return makeRunningValues(false, [], []); } }; @@ -216,7 +210,6 @@ Script.include("/~/system/libraries/cloneEntityUtils.js"); if (controllerData.triggerClicks[this.hand] < TRIGGER_OFF_VALUE && controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) { this.endNearGrabAction(); - this.hapticTargetID = null; return makeRunningValues(false, [], []); } diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index db10fff69a..3be6f602c2 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -32,7 +32,6 @@ Script.include("/~/system/libraries/controllers.js"); this.previousParentID = {}; this.previousParentJointIndex = {}; this.previouslyUnhooked = {}; - this.hapticTargetID = null; this.lastUnequipCheckTime = 0; this.autoUnequipCounter = 0; this.lastUnexpectedChildrenCheckTime = 0; @@ -138,7 +137,6 @@ Script.include("/~/system/libraries/controllers.js"); }; this.endNearParentingGrabEntity = function (controllerData) { - this.hapticTargetID = null; var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; if (this.thisHandIsParent(props) && !this.robbed) { Entities.editEntity(this.targetEntityID, { @@ -248,11 +246,6 @@ Script.include("/~/system/libraries/controllers.js"); continue; } if (entityIsGrabbable(props) || entityIsCloneable(props)) { - // give haptic feedback - if (props.id !== this.hapticTargetID) { - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); - this.hapticTargetID = props.id; - } if (!entityIsCloneable(props)) { // if we've attempted to grab a non-cloneable child, roll up to the root of the tree var groupRootProps = findGroupParent(controllerData, props); @@ -295,7 +288,6 @@ Script.include("/~/system/libraries/controllers.js"); unhighlightTargetEntity(this.highlightedEntity); this.highlightedEntity = null; } - this.hapticTargetID = null; this.robbed = false; return makeRunningValues(false, [], []); } @@ -316,7 +308,6 @@ Script.include("/~/system/libraries/controllers.js"); this.highlightedEntity = null; this.grabbing = false; this.targetEntityID = null; - this.hapticTargetID = null; this.robbed = false; return makeRunningValues(false, [], []); } From f2abf8e398a733fbe804c1168b6011cf5095abbc Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Nov 2018 11:43:05 +1300 Subject: [PATCH 045/100] Debounce haptic pulses at start of near parent grab --- .../controllerModules/farParentGrabEntity.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/farParentGrabEntity.js b/scripts/system/controllers/controllerModules/farParentGrabEntity.js index 4b85c6d046..230c4f06db 100644 --- a/scripts/system/controllers/controllerModules/farParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farParentGrabEntity.js @@ -61,6 +61,8 @@ Script.include("/~/system/libraries/controllers.js"); this.reticleMinY = MARGIN; this.reticleMaxY = 0; this.lastUnexpectedChildrenCheckTime = 0; + this.endedGrab = 0; + this.MIN_HAPTIC_PULSE_INTERVAL = 500; // ms var FAR_GRAB_JOINTS = [65527, 65528]; // FARGRAB_LEFTHAND_INDEX, FARGRAB_RIGHTHAND_INDEX @@ -144,7 +146,12 @@ Script.include("/~/system/libraries/controllers.js"); // compute the mass for the purpose of energy and how quickly to move object this.mass = this.getMass(grabbedProperties.dimensions, grabbedProperties.density); - Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); + // Debounce haptic pules. Can occur as near grab controller module vacillates between being ready or not due to + // changing positions and floating point rounding. + if (Date.now() - this.endedGrab > this.MIN_HAPTIC_PULSE_INTERVAL) { + Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand); + } + unhighlightTargetEntity(this.targetEntityID); var message = { hand: this.hand, @@ -256,6 +263,7 @@ Script.include("/~/system/libraries/controllers.js"); }; this.endFarParentGrab = function (controllerData) { + this.endedGrab = Date.now(); // var endProps = controllerData.nearbyEntityPropertiesByID[this.targetEntityID]; var endProps = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES); if (this.thisFarGrabJointIsParent(endProps)) { From c96cd422e186180dde2b2ce95e4e2059ad38ad66 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 24 Nov 2018 11:58:40 +1300 Subject: [PATCH 046/100] Fix near parent grab tear away calc for avatar scale --- .../controllers/controllerModules/nearParentGrabEntity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js index 3be6f602c2..433ad9ef53 100644 --- a/scripts/system/controllers/controllerModules/nearParentGrabEntity.js +++ b/scripts/system/controllers/controllerModules/nearParentGrabEntity.js @@ -171,7 +171,7 @@ Script.include("/~/system/libraries/controllers.js"); var controllerIndex = this.hand === LEFT_HAND ? Controller.Standard.LeftHand : Controller.Standard.RightHand; var controllerGrabOffset = getGrabPointSphereOffset(controllerIndex, true); - controllerGrabOffset = Vec3.multiply(-1, controllerGrabOffset); + controllerGrabOffset = Vec3.multiply(-MyAvatar.sensorToWorldScale, controllerGrabOffset); var distance = distanceBetweenEntityLocalPositionAndBoundingBox(props, controllerGrabOffset); if (distance > tearAwayDistance) { this.autoUnequipCounter++; From b3f646e9dc1fe3833e99325545ad1cb710498b80 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sat, 24 Nov 2018 09:44:46 -0800 Subject: [PATCH 047/100] Updated to v1.1 --- tools/nitpick/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index e325be1f40..ce65fec64f 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -24,7 +24,7 @@ Nitpick is built as part of the High Fidelity build. 1. Check "Create SFX archive 1. Enter installer name (i.e. `nitpick-installer-v1.0.exe`) 1. Click "OK" -1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.0.exe: aws s3 cp nitpick-installer-v1.0.exe s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.exe +1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.1.exe: aws s3 cp nitpick-installer-v1.0.exe s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.exe #### Mac These steps assume the hifi repository has been cloned to `~/hifi`. 1. (First time) install create-dmg: @@ -49,7 +49,7 @@ These steps assume the hifi repository has been cloned to `~/hifi`. 1. Leave region name and ouput format as default [None] 1. Install the latest release of Boto3 via pip: `pip install boto3` -1. Download the installer by browsing to [here]() +1. Download the installer by browsing to [here]() 1. Double click on the installer and install to a convenient location ![](./setup_7z.PNG) @@ -69,7 +69,7 @@ $ python3 get-pip.py --user 1. Enter the secret key 1. Leave region name and ouput format as default [None] 1. Install the latest release of Boto3 via pip: pip3 install boto3 -1. Download the installer by browsing to [here](). +1. Download the installer by browsing to [here](). 1. Double-click on the downloaded image to mount it 1. Create a folder for the nitpick files (e.g. ~/nitpick) 1. Copy the downloaded files to the folder From f62fd97f09a7be1fa52984da8bb01f7865039ee9 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sat, 24 Nov 2018 09:49:13 -0800 Subject: [PATCH 048/100] Updated to v1.1 --- tools/nitpick/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index ce65fec64f..78b4866880 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -22,9 +22,9 @@ Nitpick is built as part of the High Fidelity build. 1. Select all, right-click and select 7-Zip->Add to archive... 1. Set Archive format to 7z 1. Check "Create SFX archive -1. Enter installer name (i.e. `nitpick-installer-v1.0.exe`) +1. Enter installer name (i.e. `nitpick-installer-v1.1.exe`) 1. Click "OK" -1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.1.exe: aws s3 cp nitpick-installer-v1.0.exe s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.exe +1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.1.exe: aws s3 cp nitpick-installer-v1.1.exe s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.1.exe #### Mac These steps assume the hifi repository has been cloned to `~/hifi`. 1. (First time) install create-dmg: @@ -39,7 +39,7 @@ These steps assume the hifi repository has been cloned to `~/hifi`. 1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.1.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.1.dmg` ### Installation #### Windows -1. (First time) download and install vc_redist.x64.exe (available at https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.0.exe) +1. (First time) download and install vc_redist.x64.exe (available at https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.1.exe) 1. (First time) download and install Python 3 from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/python-3.7.0-amd64.exe (also located at https://www.python.org/downloads/) 1. After installation - create an environment variable called PYTHON_PATH and set it to the folder containing the Python executable. 1. (First time) download and install AWS CLI from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/AWSCLI64PY3.msi (also available at https://aws.amazon.com/cli/ @@ -72,8 +72,9 @@ $ python3 get-pip.py --user 1. Download the installer by browsing to [here](). 1. Double-click on the downloaded image to mount it 1. Create a folder for the nitpick files (e.g. ~/nitpick) + If this folder exists then delete all it's contents. 1. Copy the downloaded files to the folder - `cp -r /Volumes/nitpick-installer-v1.0/* .` + `cp -r /Volumes/nitpick-installer-v1.1/* .` 1. __To run nitpick, cd to the folder that you copied to and run `./nitpick`__ #Use From bbbc358ccbfa31668ad2249f299f4e4326a4e850 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sat, 24 Nov 2018 20:31:19 -0800 Subject: [PATCH 049/100] Restore AppData folder on Mac --- tools/nitpick/src/TestRunner.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/nitpick/src/TestRunner.cpp b/tools/nitpick/src/TestRunner.cpp index 9549dedb91..30740bd28a 100644 --- a/tools/nitpick/src/TestRunner.cpp +++ b/tools/nitpick/src/TestRunner.cpp @@ -582,15 +582,11 @@ void TestRunner::addBuildNumberToResults(QString zippedFolderName) { } void TestRunner::restoreHighFidelityAppDataFolder() { -#ifdef Q_OS_WIN _appDataFolder.removeRecursively(); if (_savedAppDataFolder != QDir()) { _appDataFolder.rename(_savedAppDataFolder.path(), _appDataFolder.path()); } -#elif defined Q_OS_MAC - // TODO: find Mac equivalent of AppData -#endif } // Copies a folder recursively From 26319e6d6fbd04e4e3ec5f3163b574601ded6556 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sat, 24 Nov 2018 20:37:21 -0800 Subject: [PATCH 050/100] Remove all disk images --- tools/nitpick/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index 78b4866880..bdea4eb059 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -34,7 +34,7 @@ These steps assume the hifi repository has been cloned to `~/hifi`. `cp ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib .` 1. Change the loader instruction to find the dynamic library locally `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib libquazip5.1.dylib nitpick` -1. Delete any existing installer: `rm nitpick.dmg` +1. Delete any existing disk images: `rm *.dmg` 1. Create installer (note final period): `create-dmg --volname nitpick-installer-v1.1 nitpick-installer-v1.1.dmg .` 1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.1.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.1.dmg` ### Installation From e173b2968739e50e5ae7569b2a04ee283d6deebc Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sat, 24 Nov 2018 20:43:13 -0800 Subject: [PATCH 051/100] Added warning --- tools/nitpick/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index bdea4eb059..ae8821c6be 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -36,6 +36,7 @@ These steps assume the hifi repository has been cloned to `~/hifi`. `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib libquazip5.1.dylib nitpick` 1. Delete any existing disk images: `rm *.dmg` 1. Create installer (note final period): `create-dmg --volname nitpick-installer-v1.1 nitpick-installer-v1.1.dmg .` + Make sure to wait for completion. 1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.1.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.1.dmg` ### Installation #### Windows From 6313ab8ed7d610dd269a45cd03589f1eb0d13f19 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Sun, 25 Nov 2018 20:10:01 -0800 Subject: [PATCH 052/100] Working on possible crash on Mac. --- tools/nitpick/src/Downloader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/nitpick/src/Downloader.cpp b/tools/nitpick/src/Downloader.cpp index de768398b0..3256e79601 100644 --- a/tools/nitpick/src/Downloader.cpp +++ b/tools/nitpick/src/Downloader.cpp @@ -12,12 +12,12 @@ #include Downloader::Downloader(QUrl fileURL, QObject *parent) : QObject(parent) { + _networkAccessManager.get(QNetworkRequest(fileURL)); + connect( &_networkAccessManager, SIGNAL (finished(QNetworkReply*)), this, SLOT (fileDownloaded(QNetworkReply*)) ); - - _networkAccessManager.get(QNetworkRequest(fileURL)); } void Downloader::fileDownloaded(QNetworkReply* reply) { From 2913d4f9841fd6ebd5f32767598b41d9b1700952 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 26 Nov 2018 08:25:07 -0800 Subject: [PATCH 053/100] Removed baaaaaad file. --- .../domain-server/AccountInfo.bin | Bin 1450 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tools/nitpick/AppDataHighFidelity/domain-server/AccountInfo.bin diff --git a/tools/nitpick/AppDataHighFidelity/domain-server/AccountInfo.bin b/tools/nitpick/AppDataHighFidelity/domain-server/AccountInfo.bin deleted file mode 100644 index 645e34895e5c2ae38571d19a60c21df84c880b12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1450 zcmaiuX*d)J9EbliWDyXqirx)88es;s{=7|CAKh> zBjk=;YebG7Q;j3-rehG<dt}>pTS1HE7EiYrSuWTvl;>I*HM&!jW zQF^;JC>UK&QL*QLl`~)>=6uz{euwwhQzNZxEK;lngD; zU}IlZ50Qdg_G#^+%-96}TyTChjkG3Sd77^{k@e0kQ(4Vxx>j52LE7599bdxF^k7DC zL5aEuJBJc_m)W{@eN^tj=SuDz_M?2p)e*;LO>w4!y3seywe_dxv279TT=%hO`%1;5 z{QQ#%I0aWS>(pnJ*3z}%xqBAZ`3?8BF4)LzUfSWZr(J$tuRjrbnu*w0=UIH%uL%u8 zTJ24?;^qZs|KOw=lD|QUx^(Nu{G?E%1OgDq1O$*eFUT-cx9jFeelbfGK9Q;n+!Q=1 zyksC@q2k6^sd9bIQJz);%J95I*2a;-KKXRp)YhJIGT%UBQQ?v73k+sD(dFr<+YJ@Z z&X)hCsJeToSbv17bEHO*+b`&D>^0#vN69K{$S^HZTcC%xXyLLJD_qe%QMX8>S#Qp@FLf+ z$qKKOuD6C(v}Rq&Rm@Sn!?W#d@h}#UksJ=pkd9>2H6{`|JOjp1VFxw23<)Qv80!#H zT$J0or(#;Cv?!D>lvA(kyVx@Mruf$Eg+ZJpt+<7UkaYKOU#9BuN_Q!9G3Ub5K6E51 zi;hcwDzrX!;MeCSEstp$sWH}SdYO%&{m!qp61Q6a@E-F?-n#0rp1_BnuOjUkXRG?H zVaRw(ToHHKP~`iFnm8+U$bl_TX)M)$sK(Oic=w@YHtc>V-$HVdOl%jOAOv=MemJ~_ z=>3~m7c6#ey&p#ky^*0^_2Mep!pfJYULMd?LW@nD&CpK#g3eDS$YX~@<3DCxdY?pP z2k$-^cLa5?GpQ8fpx%qFpMh~w+*RRSqWwZc3)4Ri4vk#5HwOsYT!ua+Uk<=oRf zEt__XDpen1TCzwTnbhn}QWBU!IY~P)v9tu|wbgL*(zdz`rnV<)KIack!@U0#8OdQI z343_VBs0Ct9k!8@?=|YZ<>E7v&$s(eZa@W7-WM1pUd6BR2auc!{$8zgVqK7hZ}ZdE zuZx=Fbq@A_!LW%^>de**+TrNI7M$x)$MczObLpX%@9R1n7Rn~8KYDx3`1%FPVWC3u zK@D`WW0gM3-rR1q2-`a3fa{$Yi?2J5&3FNvYH}2YGpJ< z?$-5)<(3e)O-1K7CaKDx5MG}rYGh10w3pSnr*!4hzQ2PzQ20s_DSC}0U@fCoAR00n*mQ!oQ_pa32$ Qfed)SeP24@fdT>l0D=~Uga7~l From 48fabf51f2847359320b4e9d2ba4ac6f58ccd4ac Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 26 Nov 2018 08:54:09 -0800 Subject: [PATCH 054/100] Corrected Linux compilation error. --- tools/nitpick/src/TestRunner.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/nitpick/src/TestRunner.cpp b/tools/nitpick/src/TestRunner.cpp index 30740bd28a..65358a0c3d 100644 --- a/tools/nitpick/src/TestRunner.cpp +++ b/tools/nitpick/src/TestRunner.cpp @@ -332,12 +332,11 @@ void TestRunner::verifyInstallationSucceeded() { } void TestRunner::saveExistingHighFidelityAppDataFolder() { -#ifdef Q_OS_WIN QString dataDirectory{ "NOT FOUND" }; - +#ifdef Q_OS_WIN dataDirectory = qgetenv("USERPROFILE") + "\\AppData\\Roaming"; #elif defined Q_OS_MAC - QString dataDirectory{ QDir::homePath() + "/Library/Application Support" }; + dataDirectory{ QDir::homePath() + "/Library/Application Support" }; #endif if (_runLatest->isChecked()) { _appDataFolder = dataDirectory + "/High Fidelity"; From a6e203e3e5a58f31e12a57827dd0575dfe8ba0ee Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 Nov 2018 10:55:42 -0800 Subject: [PATCH 055/100] Fix draggable inputs not being tabbable --- scripts/system/html/css/edit-style.css | 11 ++++---- scripts/system/html/js/draggableNumber.js | 32 ++++++++++++++++------ scripts/system/html/js/entityProperties.js | 2 +- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 5b5c9e057c..415d8e567f 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -916,7 +916,7 @@ div.refresh input[type="button"] { } .draggable-number div { height: 28px; - width: 92px; + width: 124px; } .draggable-number.text { display: inline-block; @@ -929,6 +929,7 @@ div.refresh input[type="button"] { height: 28px; width: 100%; line-height: 2; + box-sizing: border-box; } .draggable-number.text:hover { cursor: ew-resize; @@ -944,12 +945,12 @@ div.refresh input[type="button"] { cursor: default; } .draggable-number.left-arrow { - top: -5px; + top: 3px; left: 0px; transform: rotate(180deg); } .draggable-number.right-arrow { - top: -5px; + top: 3px; right: 0px; } .draggable-number input[type=number] { @@ -971,14 +972,14 @@ div.refresh input[type="button"] { left: 12px; } .draggable-number.fstuple + .draggable-number.fstuple { - padding-left: 28px; + margin-left: 28px; } .draggable-number.fstuple input { right: -10px; } .draggable-number.fstuple .sublabel { position: absolute; - top: 0; + top: 6px; left: -16px; font-family: FiraSans-SemiBold; font-size: 15px; diff --git a/scripts/system/html/js/draggableNumber.js b/scripts/system/html/js/draggableNumber.js index c08cac2ce4..951b123e67 100644 --- a/scripts/system/html/js/draggableNumber.js +++ b/scripts/system/html/js/draggableNumber.js @@ -23,6 +23,20 @@ function DraggableNumber(min, max, step, decimals, dragStart, dragEnd) { } DraggableNumber.prototype = { + showInput: function() { + this.elText.style.visibility = "hidden"; + this.elLeftArrow.style.visibility = "hidden"; + this.elRightArrow.style.visibility = "hidden"; + this.elInput.style.opacity = 1; + }, + + hideInput: function() { + this.elText.style.visibility = "visible"; + this.elLeftArrow.style.visibility = "visible"; + this.elRightArrow.style.visibility = "visible"; + this.elInput.style.opacity = 0; + }, + mouseDown: function(event) { if (event.target === this.elText) { this.initialMouseEvent = event; @@ -36,8 +50,8 @@ DraggableNumber.prototype = { if (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"; - this.elText.style.visibility = "hidden"; + this.showInput(); + this.elInput.focus(); } this.initialMouseEvent = null; } @@ -125,9 +139,8 @@ DraggableNumber.prototype = { this.setValue(this.elInput.value); }, - inputBlur: function() { - this.elInput.style.visibility = "hidden"; - this.elText.style.visibility = "visible"; + inputBlur: function(ev) { + this.hideInput(); }, initialize: function() { @@ -171,13 +184,14 @@ DraggableNumber.prototype = { if (this.step !== undefined) { this.elInput.setAttribute("step", this.step); } - this.elInput.style.visibility = "hidden"; + this.elInput.style.opacity = 0; this.elInput.addEventListener("change", this.onInputChange); this.elInput.addEventListener("blur", this.onInputBlur); + this.elInput.addEventListener("focus", this.showInput.bind(this)); - this.elText.appendChild(this.elLeftArrow); - this.elText.appendChild(this.elInput); - this.elText.appendChild(this.elRightArrow); + this.elDiv.appendChild(this.elLeftArrow); + 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 78e3cd4dc8..786df503df 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -2149,7 +2149,7 @@ function createTupleNumberInput(property, subLabel) { propertyData.decimals, dragStartFunction, dragEndFunction); elDraggableNumber.elInput.setAttribute("id", elementID); elDraggableNumber.elDiv.className += " fstuple"; - elDraggableNumber.elText.insertBefore(elLabel, elDraggableNumber.elLeftArrow); + elDraggableNumber.elDiv.insertBefore(elLabel, elDraggableNumber.elLeftArrow); return elDraggableNumber; } From e943504f608f5cb2d9129d3156be6c8441e65b5d Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 26 Nov 2018 15:59:08 -0800 Subject: [PATCH 056/100] Updated README.md --- tools/nitpick/README.md | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index ae8821c6be..fe027be227 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -12,7 +12,7 @@ Nitpick has 5 functions, separated into 4 tabs: 1. Evaluating the results of running tests 1. Web interface -## Build +## Build (for developers) Nitpick is built as part of the High Fidelity build. ### Creating installers #### Windows @@ -27,15 +27,17 @@ Nitpick is built as part of the High Fidelity build. 1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.1.exe: aws s3 cp nitpick-installer-v1.1.exe s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.1.exe #### Mac These steps assume the hifi repository has been cloned to `~/hifi`. +1. (first time) Install brew + In a terminal: `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)` 1. (First time) install create-dmg: - `brew install create-dmg` -1. cd to the `build/tools/nitpick/Release` folder + In a terminal: `brew install create-dmg` +1. In a terminal: cd to the `build/tools/nitpick/Release` folder 1. Copy the quazip dynamic library (note final period): - `cp ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib .` + In a terminal: `cp ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib .` 1. Change the loader instruction to find the dynamic library locally - `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib libquazip5.1.dylib nitpick` -1. Delete any existing disk images: `rm *.dmg` -1. Create installer (note final period): `create-dmg --volname nitpick-installer-v1.1 nitpick-installer-v1.1.dmg .` + In a terminal: `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib libquazip5.1.dylib nitpick` +1. Delete any existing disk images. In a terminal: `rm *.dmg` +1. Create installer (note final period).In a terminal: `create-dmg --volname nitpick-installer-v1.1 nitpick-installer-v1.1.dmg .` Make sure to wait for completion. 1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.1.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.1.dmg` ### Installation @@ -56,16 +58,20 @@ These steps assume the hifi repository has been cloned to `~/hifi`. 1. __To run nitpick, double click **nitpick.exe**__ #### Mac +1. (first time) Install brew + In a terminal: `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)` +1. (First time) install Qt: + In a terminal: `brew install qt` 1. (First time) install Python from https://www.python.org/downloads/release/python-370/ (**macOS 64-bit installer** or **macOS 64-bit/32-bit installer**) - 1. After installation - run `open "/Applications/Python 3.6/Install Certificates.command"`. This is needed because the Mac Python supplied no longer links with the deprecated Apple-supplied system OpenSSL libraries but rather supplies a private copy of OpenSSL 1.0.2 which does not automatically access the system default root certificates. + 1. After installation - In a terminal: run `open "/Applications/Python 3.6/Install Certificates.command"`. This is needed because the Mac Python supplied no longer links with the deprecated Apple-supplied system OpenSSL libraries but rather supplies a private copy of OpenSSL 1.0.2 which does not automatically access the system default root certificates. 1. Verify that `/usr/local/bin/python3` exists. 1. (First time - AWS interface) Install pip with the script provided by the Python Packaging Authority: -$ curl -O https://bootstrap.pypa.io/get-pip.py -$ python3 get-pip.py --user +In a terminal: `curl -O https://bootstrap.pypa.io/get-pip.py` +In a terminal: `python3 get-pip.py --user` 1. Use pip to install the AWS CLI. - $ pip3 install awscli --upgrade --user + `pip3 install awscli --upgrade --user` This will install aws in your user. For user XXX, aws will be located in ~/Library/Python/3.7/bin - 1. Open a new command prompt and run `aws configure` + 1. Open a new command prompt and run `~/Library/Python/3.7/bin/aws configure` 1. Enter the AWS account number 1. Enter the secret key 1. Leave region name and ouput format as default [None] @@ -75,9 +81,11 @@ $ python3 get-pip.py --user 1. Create a folder for the nitpick files (e.g. ~/nitpick) If this folder exists then delete all it's contents. 1. Copy the downloaded files to the folder - `cp -r /Volumes/nitpick-installer-v1.1/* .` + In a terminal: + `cd ~/nitpick` + `cp -r /Volumes/nitpick-installer-v1.1/* .` -1. __To run nitpick, cd to the folder that you copied to and run `./nitpick`__ +1. __To run nitpick, cd to the folder that you copied to and run `./nitpick`__ #Use ## Create ![](./Create.PNG) From 2ade0078f45187f191fe4d94f14cf5cf852c0187 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 26 Nov 2018 16:02:22 -0800 Subject: [PATCH 057/100] Updated README.md --- tools/nitpick/README.md | 52 ++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index 3bbc4fbac1..fe027be227 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -12,7 +12,7 @@ Nitpick has 5 functions, separated into 4 tabs: 1. Evaluating the results of running tests 1. Web interface -## Build +## Build (for developers) Nitpick is built as part of the High Fidelity build. ### Creating installers #### Windows @@ -22,24 +22,27 @@ Nitpick is built as part of the High Fidelity build. 1. Select all, right-click and select 7-Zip->Add to archive... 1. Set Archive format to 7z 1. Check "Create SFX archive -1. Enter installer name (i.e. `nitpick-installer-v1.0.exe`) +1. Enter installer name (i.e. `nitpick-installer-v1.1.exe`) 1. Click "OK" -1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.0.exe: aws s3 cp nitpick-installer-v1.0.exe s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.exe +1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.1.exe: aws s3 cp nitpick-installer-v1.1.exe s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.1.exe #### Mac These steps assume the hifi repository has been cloned to `~/hifi`. +1. (first time) Install brew + In a terminal: `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)` 1. (First time) install create-dmg: - `brew install create-dmg` -1. cd to the `build/tools/nitpick/Release` folder + In a terminal: `brew install create-dmg` +1. In a terminal: cd to the `build/tools/nitpick/Release` folder 1. Copy the quazip dynamic library (note final period): - `cp ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib .` + In a terminal: `cp ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib .` 1. Change the loader instruction to find the dynamic library locally - `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib libquazip5.1.dylib nitpick` -1. Delete any existing installer: `rm nitpick.dmg` -1. Create installer (note final period): `create-dmg --volname nitpick-installer-v1.0 nitpick-installer-v1.0.dmg .` -1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.0.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.dmg` + In a terminal: `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib libquazip5.1.dylib nitpick` +1. Delete any existing disk images. In a terminal: `rm *.dmg` +1. Create installer (note final period).In a terminal: `create-dmg --volname nitpick-installer-v1.1 nitpick-installer-v1.1.dmg .` + Make sure to wait for completion. +1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.1.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.1.dmg` ### Installation #### Windows -1. (First time) download and install vc_redist.x64.exe (available at https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.0.exe) +1. (First time) download and install vc_redist.x64.exe (available at https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.1.exe) 1. (First time) download and install Python 3 from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/python-3.7.0-amd64.exe (also located at https://www.python.org/downloads/) 1. After installation - create an environment variable called PYTHON_PATH and set it to the folder containing the Python executable. 1. (First time) download and install AWS CLI from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/AWSCLI64PY3.msi (also available at https://aws.amazon.com/cli/ @@ -49,33 +52,40 @@ These steps assume the hifi repository has been cloned to `~/hifi`. 1. Leave region name and ouput format as default [None] 1. Install the latest release of Boto3 via pip: `pip install boto3` -1. Download the installer by browsing to [here]() +1. Download the installer by browsing to [here]() 1. Double click on the installer and install to a convenient location ![](./setup_7z.PNG) 1. __To run nitpick, double click **nitpick.exe**__ #### Mac -1. (Firat time) install Python from https://www.python.org/downloads/release/python-370/ (**macOS 64-bit installer** or **macOS 64-bit/32-bit installer**) - 1. After installation - run `open "/Applications/Python 3.6/Install Certificates.command"`. This is needed because the Mac Python supplied no longer links with the deprecated Apple-supplied system OpenSSL libraries but rather supplies a private copy of OpenSSL 1.0.2 which does not automatically access the system default root certificates. +1. (first time) Install brew + In a terminal: `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)` +1. (First time) install Qt: + In a terminal: `brew install qt` +1. (First time) install Python from https://www.python.org/downloads/release/python-370/ (**macOS 64-bit installer** or **macOS 64-bit/32-bit installer**) + 1. After installation - In a terminal: run `open "/Applications/Python 3.6/Install Certificates.command"`. This is needed because the Mac Python supplied no longer links with the deprecated Apple-supplied system OpenSSL libraries but rather supplies a private copy of OpenSSL 1.0.2 which does not automatically access the system default root certificates. 1. Verify that `/usr/local/bin/python3` exists. 1. (First time - AWS interface) Install pip with the script provided by the Python Packaging Authority: -$ curl -O https://bootstrap.pypa.io/get-pip.py -$ python3 get-pip.py --user +In a terminal: `curl -O https://bootstrap.pypa.io/get-pip.py` +In a terminal: `python3 get-pip.py --user` 1. Use pip to install the AWS CLI. - $ pip3 install awscli --upgrade --user + `pip3 install awscli --upgrade --user` This will install aws in your user. For user XXX, aws will be located in ~/Library/Python/3.7/bin - 1. Open a new command prompt and run `aws configure` + 1. Open a new command prompt and run `~/Library/Python/3.7/bin/aws configure` 1. Enter the AWS account number 1. Enter the secret key 1. Leave region name and ouput format as default [None] 1. Install the latest release of Boto3 via pip: pip3 install boto3 -1. Download the installer by browsing to [here](). +1. Download the installer by browsing to [here](). 1. Double-click on the downloaded image to mount it 1. Create a folder for the nitpick files (e.g. ~/nitpick) + If this folder exists then delete all it's contents. 1. Copy the downloaded files to the folder - `cp -r /Volumes/nitpick-installer-v1.0/* .` + In a terminal: + `cd ~/nitpick` + `cp -r /Volumes/nitpick-installer-v1.1/* .` -1. __To run nitpick, cd to the folder that you copied to and run `./nitpick`__ +1. __To run nitpick, cd to the folder that you copied to and run `./nitpick`__ #Use ## Create ![](./Create.PNG) From ebc7875f5ea7b58edadbf676dd1e390b9674a11b Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 26 Nov 2018 16:03:40 -0800 Subject: [PATCH 058/100] Updated README.md --- tools/nitpick/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index fe027be227..319d374a5d 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -86,7 +86,7 @@ In a terminal: `python3 get-pip.py --user` `cp -r /Volumes/nitpick-installer-v1.1/* .` 1. __To run nitpick, cd to the folder that you copied to and run `./nitpick`__ -#Use +# Usage ## Create ![](./Create.PNG) From c211dc363b4d41fbef1d729ff04441fbef295a9b Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 26 Nov 2018 16:05:49 -0800 Subject: [PATCH 059/100] Updated README.md --- tools/nitpick/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index fe027be227..319d374a5d 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -86,7 +86,7 @@ In a terminal: `python3 get-pip.py --user` `cp -r /Volumes/nitpick-installer-v1.1/* .` 1. __To run nitpick, cd to the folder that you copied to and run `./nitpick`__ -#Use +# Usage ## Create ![](./Create.PNG) From e587820de317fa337088fc686e0e02373a2f46bd Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 26 Nov 2018 16:18:43 -0800 Subject: [PATCH 060/100] Should be v1.0 --- tools/nitpick/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index 319d374a5d..ce43332c1b 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -22,9 +22,9 @@ Nitpick is built as part of the High Fidelity build. 1. Select all, right-click and select 7-Zip->Add to archive... 1. Set Archive format to 7z 1. Check "Create SFX archive -1. Enter installer name (i.e. `nitpick-installer-v1.1.exe`) +1. Enter installer name (i.e. `nitpick-installer-v1.0.exe`) 1. Click "OK" -1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.1.exe: aws s3 cp nitpick-installer-v1.1.exe s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.1.exe +1. Copy created installer to https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.0.exe: aws s3 cp nitpick-installer-v1.0.exe s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.exe #### Mac These steps assume the hifi repository has been cloned to `~/hifi`. 1. (first time) Install brew @@ -37,12 +37,12 @@ These steps assume the hifi repository has been cloned to `~/hifi`. 1. Change the loader instruction to find the dynamic library locally In a terminal: `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib libquazip5.1.dylib nitpick` 1. Delete any existing disk images. In a terminal: `rm *.dmg` -1. Create installer (note final period).In a terminal: `create-dmg --volname nitpick-installer-v1.1 nitpick-installer-v1.1.dmg .` +1. Create installer (note final period).In a terminal: `create-dmg --volname nitpick-installer-v1.0 nitpick-installer-v1.0.dmg .` Make sure to wait for completion. -1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.1.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.1.dmg` +1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.0.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.0.dmg` ### Installation #### Windows -1. (First time) download and install vc_redist.x64.exe (available at https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.1.exe) +1. (First time) download and install vc_redist.x64.exe (available at https://hifi-qa.s3.amazonaws.com/nitpick/Windows/nitpick-installer-v1.0.exe) 1. (First time) download and install Python 3 from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/python-3.7.0-amd64.exe (also located at https://www.python.org/downloads/) 1. After installation - create an environment variable called PYTHON_PATH and set it to the folder containing the Python executable. 1. (First time) download and install AWS CLI from https://hifi-qa.s3.amazonaws.com/nitpick/Windows/AWSCLI64PY3.msi (also available at https://aws.amazon.com/cli/ @@ -52,7 +52,7 @@ These steps assume the hifi repository has been cloned to `~/hifi`. 1. Leave region name and ouput format as default [None] 1. Install the latest release of Boto3 via pip: `pip install boto3` -1. Download the installer by browsing to [here]() +1. Download the installer by browsing to [here]() 1. Double click on the installer and install to a convenient location ![](./setup_7z.PNG) @@ -76,14 +76,14 @@ In a terminal: `python3 get-pip.py --user` 1. Enter the secret key 1. Leave region name and ouput format as default [None] 1. Install the latest release of Boto3 via pip: pip3 install boto3 -1. Download the installer by browsing to [here](). +1. Download the installer by browsing to [here](). 1. Double-click on the downloaded image to mount it 1. Create a folder for the nitpick files (e.g. ~/nitpick) If this folder exists then delete all it's contents. 1. Copy the downloaded files to the folder In a terminal: `cd ~/nitpick` - `cp -r /Volumes/nitpick-installer-v1.1/* .` + `cp -r /Volumes/nitpick-installer-v1.0/* .` 1. __To run nitpick, cd to the folder that you copied to and run `./nitpick`__ # Usage From e7ab7094cd1acf473969e89283c87c567b4683e9 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 26 Nov 2018 16:42:48 -0800 Subject: [PATCH 061/100] Kill Hifi processes after evaluation. --- tools/nitpick/src/TestRunner.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/nitpick/src/TestRunner.cpp b/tools/nitpick/src/TestRunner.cpp index 30740bd28a..e3b8adca28 100644 --- a/tools/nitpick/src/TestRunner.cpp +++ b/tools/nitpick/src/TestRunner.cpp @@ -528,8 +528,6 @@ void TestRunner::runInterfaceWithTestScript() { } void TestRunner::interfaceExecutionComplete() { - killProcesses(); - QFileInfo testCompleted(QDir::toNativeSeparators(_snapshotFolder) +"/tests_completed.txt"); if (!testCompleted.exists()) { QMessageBox::critical(0, "Tests not completed", "Interface seems to have crashed before completion of the test scripts\nExisting images will be evaluated"); @@ -537,6 +535,8 @@ void TestRunner::interfaceExecutionComplete() { evaluateResults(); + killProcesses(); + // The High Fidelity AppData folder will be restored after evaluation has completed } From 5da6ecad121ee1111115e5109b9c3b1db1c199ea Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 26 Nov 2018 18:10:14 -0800 Subject: [PATCH 062/100] Compilation error. --- tools/nitpick/src/TestRunner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/src/TestRunner.cpp b/tools/nitpick/src/TestRunner.cpp index 7c2dfda1cd..12bdf87495 100644 --- a/tools/nitpick/src/TestRunner.cpp +++ b/tools/nitpick/src/TestRunner.cpp @@ -336,7 +336,7 @@ void TestRunner::saveExistingHighFidelityAppDataFolder() { #ifdef Q_OS_WIN dataDirectory = qgetenv("USERPROFILE") + "\\AppData\\Roaming"; #elif defined Q_OS_MAC - dataDirectory{ QDir::homePath() + "/Library/Application Support" }; + dataDirectory = QDir::homePath() + "/Library/Application Support"; #endif if (_runLatest->isChecked()) { _appDataFolder = dataDirectory + "/High Fidelity"; From aed947cb0a65ff3006054485503fe616fc45d4b1 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Mon, 26 Nov 2018 18:10:41 -0800 Subject: [PATCH 063/100] Minor cleanup. --- tools/nitpick/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index 319d374a5d..a02980ddfe 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -37,7 +37,7 @@ These steps assume the hifi repository has been cloned to `~/hifi`. 1. Change the loader instruction to find the dynamic library locally In a terminal: `install_name_tool -change ~/hifi/build/ext/Xcode/quazip/project/lib/libquazip5.1.dylib libquazip5.1.dylib nitpick` 1. Delete any existing disk images. In a terminal: `rm *.dmg` -1. Create installer (note final period).In a terminal: `create-dmg --volname nitpick-installer-v1.1 nitpick-installer-v1.1.dmg .` +1. Create installer (note final period).In a terminal: `create-dmg --volname nitpick-installer-v1.1 nitpick-installer-v1.1.dmg .` Make sure to wait for completion. 1. Copy created installer to AWS: `~/Library/Python/3.7/bin/aws s3 cp nitpick-installer-v1.1.dmg s3://hifi-qa/nitpick/Mac/nitpick-installer-v1.1.dmg` ### Installation From 9cc896c4a884c6feaa7584560b30ee7f7bd92c6f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 20 Nov 2018 09:13:07 -0800 Subject: [PATCH 064/100] fixing keyboard mallets dimensions --- interface/src/ui/Keyboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index 6852691634..46a25a24a7 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -60,7 +60,7 @@ static const float MALLET_TOUCH_Y_OFFSET = 0.050f; static const float MALLET_Y_OFFSET = 0.160f; static const glm::quat MALLET_ROTATION_OFFSET{0.70710678f, 0.0f, -0.70710678f, 0.0f}; -static const glm::vec3 MALLET_MODEL_DIMENSIONS{0.03f, MALLET_LENGTH, 0.03f}; +static const glm::vec3 MALLET_MODEL_DIMENSIONS{0.01f, MALLET_LENGTH, 0.01f}; static const glm::vec3 MALLET_POSITION_OFFSET{0.0f, -MALLET_Y_OFFSET / 2.0f, 0.0f}; static const glm::vec3 MALLET_TIP_OFFSET{0.0f, MALLET_LENGTH - MALLET_TOUCH_Y_OFFSET, 0.0f}; From 29028386c8a60abebac6248ba6b1911a87f35d65 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 27 Nov 2018 11:56:07 -0800 Subject: [PATCH 065/100] Keyboard menu option in general settings --- interface/resources/qml/controlsUit/Keyboard.qml | 4 ++-- interface/src/Menu.cpp | 2 -- interface/src/Menu.h | 1 - .../src/scripting/KeyboardScriptingInterface.cpp | 4 ++++ interface/src/scripting/KeyboardScriptingInterface.h | 3 +++ interface/src/ui/Keyboard.cpp | 11 +++++++++++ interface/src/ui/Keyboard.h | 7 +++++++ interface/src/ui/PreferencesDialog.cpp | 7 +++++++ 8 files changed, 34 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/controlsUit/Keyboard.qml b/interface/resources/qml/controlsUit/Keyboard.qml index c38631ff79..a55523f34a 100644 --- a/interface/resources/qml/controlsUit/Keyboard.qml +++ b/interface/resources/qml/controlsUit/Keyboard.qml @@ -44,14 +44,14 @@ Rectangle { onPasswordChanged: { - var use3DKeyboard = (typeof MenuInterface === "undefined") ? false : MenuInterface.isOptionChecked("Use 3D Keyboard"); + var use3DKeyboard = (typeof KeyboardScriptingInterface === "undefined") ? false : KeyboardScriptingInterface.use3DKeyboard; if (use3DKeyboard) { KeyboardScriptingInterface.password = password; } } onRaisedChanged: { - var use3DKeyboard = (typeof MenuInterface === "undefined") ? false : MenuInterface.isOptionChecked("Use 3D Keyboard"); + var use3DKeyboard = (typeof KeyboardScriptingInterface === "undefined") ? false : KeyboardScriptingInterface.use3DKeyboard; if (!use3DKeyboard) { keyboardBase.height = raised ? raisedHeight : 0; keyboardBase.visible = raised; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 13c622627d..e9a44b1e87 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -364,8 +364,6 @@ Menu::Menu() { qApp->setHmdTabletBecomesToolbarSetting(action->isChecked()); }); - addCheckableActionToQMenuAndActionHash(uiOptionsMenu, MenuOption::Use3DKeyboard, 0, true); - // Developer > Render >>> MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index d3d9e5e674..e0e48ff32c 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -213,7 +213,6 @@ namespace MenuOption { const QString TurnWithHead = "Turn using Head"; const QString UseAudioForMouth = "Use Audio for Mouth"; const QString UseCamera = "Use Camera"; - const QString Use3DKeyboard = "Use 3D Keyboard"; const QString VelocityFilter = "Velocity Filter"; const QString VisibleToEveryone = "Everyone"; const QString VisibleToFriends = "Friends"; diff --git a/interface/src/scripting/KeyboardScriptingInterface.cpp b/interface/src/scripting/KeyboardScriptingInterface.cpp index b26e1ec378..d86bb56e64 100644 --- a/interface/src/scripting/KeyboardScriptingInterface.cpp +++ b/interface/src/scripting/KeyboardScriptingInterface.cpp @@ -32,3 +32,7 @@ void KeyboardScriptingInterface::setPassword(bool password) { void KeyboardScriptingInterface::loadKeyboardFile(const QString& keyboardFile) { DependencyManager::get()->loadKeyboardFile(keyboardFile); } + +bool KeyboardScriptingInterface::getUse3DKeyboard() { + return DependencyManager::get()->getUse3DKeyboard(); +} diff --git a/interface/src/scripting/KeyboardScriptingInterface.h b/interface/src/scripting/KeyboardScriptingInterface.h index 1ab91ea7c3..709dfe01de 100644 --- a/interface/src/scripting/KeyboardScriptingInterface.h +++ b/interface/src/scripting/KeyboardScriptingInterface.h @@ -30,6 +30,7 @@ class KeyboardScriptingInterface : public QObject, public Dependency { Q_OBJECT Q_PROPERTY(bool raised READ isRaised WRITE setRaised) Q_PROPERTY(bool password READ isPassword WRITE setPassword) + Q_PROPERTY(bool use3DKeyboard READ getUse3DKeyboard); public: Q_INVOKABLE void loadKeyboardFile(const QString& string); @@ -39,5 +40,7 @@ private: bool isPassword(); void setPassword(bool password); + + bool getUse3DKeyboard(); }; #endif diff --git a/interface/src/ui/Keyboard.cpp b/interface/src/ui/Keyboard.cpp index 6852691634..74fd869b87 100644 --- a/interface/src/ui/Keyboard.cpp +++ b/interface/src/ui/Keyboard.cpp @@ -241,6 +241,17 @@ void Keyboard::registerKeyboardHighlighting() { selection->enableListToScene(KEY_PRESSED_HIGHLIGHT); } +bool Keyboard::getUse3DKeyboard() const { + return _use3DKeyboardLock.resultWithReadLock([&] { + return _use3DKeyboard.get(); + }); +} + +void Keyboard::setUse3DKeyboard(bool use) { + _use3DKeyboardLock.withWriteLock([&] { + _use3DKeyboard.set(use); + }); +} void Keyboard::createKeyboard() { auto pointerManager = DependencyManager::get(); diff --git a/interface/src/ui/Keyboard.h b/interface/src/ui/Keyboard.h index 18db38b2ae..9c0c8c40f2 100644 --- a/interface/src/ui/Keyboard.h +++ b/interface/src/ui/Keyboard.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "ui/overlays/Overlay.h" @@ -97,6 +98,9 @@ public: bool isPassword() const; void setPassword(bool password); + bool getUse3DKeyboard() const; + void setUse3DKeyboard(bool use); + void loadKeyboardFile(const QString& keyboardFile); QVector getKeysID(); @@ -143,6 +147,9 @@ private: SharedSoundPointer _keySound { nullptr }; std::shared_ptr _layerSwitchTimer { std::make_shared() }; + mutable ReadWriteLockable _use3DKeyboardLock; + Setting::Handle _use3DKeyboard { "use3DKeyboard", true }; + QString _typedCharacters; TextDisplay _textDisplay; Anchor _anchor; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 5f8b191a4f..d1fbe02759 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -24,6 +24,7 @@ #include "Snapshot.h" #include "SnapshotAnimated.h" #include "UserActivityLogger.h" +#include "ui/Keyboard.h" void setupPreferences() { auto preferences = DependencyManager::get(); @@ -119,6 +120,12 @@ void setupPreferences() { preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use reticle cursor instead of arrow", getter, setter)); } + { + auto getter = []()->bool { return DependencyManager::get()->getUse3DKeyboard(); }; + auto setter = [](bool value) { DependencyManager::get()->setUse3DKeyboard(value); }; + preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use Virtual Keyboard", getter, setter)); + } + { auto getter = []()->bool { return qApp->getMiniTabletEnabled(); }; auto setter = [](bool value) { qApp->setMiniTabletEnabled(value); }; From fac27553d740edacc270122e43200209a6196183 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 23 Nov 2018 19:56:35 -0800 Subject: [PATCH 066/100] suppress 'No instance available' messages during shutdown. try a different way of shutting down AudioClient. --- interface/src/Application.cpp | 5 ++++- libraries/audio-client/src/AudioClient.cpp | 1 - libraries/shared/src/DependencyManager.h | 13 +++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 21af28ffcb..ed834a2cc5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2572,6 +2572,8 @@ void Application::cleanupBeforeQuit() { QString webengineRemoteDebugging = QProcessEnvironment::systemEnvironment().value("QTWEBENGINE_REMOTE_DEBUGGING", "false"); qCDebug(interfaceapp) << "QTWEBENGINE_REMOTE_DEBUGGING =" << webengineRemoteDebugging; + DependencyManager::prepareToExit(); + if (tracing::enabled()) { auto tracer = DependencyManager::get(); tracer->stopTracing(); @@ -2684,6 +2686,7 @@ void Application::cleanupBeforeQuit() { // destroy Audio so it and its threads have a chance to go down safely // this must happen after QML, as there are unexplained audio crashes originating in qtwebengine + QMetaObject::invokeMethod(DependencyManager::get().data(), "stop"); DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); @@ -2775,7 +2778,7 @@ Application::~Application() { // quit the thread used by the closure event sender closeEventSender->thread()->quit(); - // Can't log to file passed this point, FileLogger about to be deleted + // Can't log to file past this point, FileLogger about to be deleted qInstallMessageHandler(LogHandler::verboseMessageHandler); _renderEventHandler->deleteLater(); diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 92f7a27853..9bad7e2f45 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -302,7 +302,6 @@ void AudioClient::customDeleter() { #if defined(Q_OS_ANDROID) _shouldRestartInputSetup = false; #endif - stop(); deleteLater(); } diff --git a/libraries/shared/src/DependencyManager.h b/libraries/shared/src/DependencyManager.h index 978732fd50..bda1077990 100644 --- a/libraries/shared/src/DependencyManager.h +++ b/libraries/shared/src/DependencyManager.h @@ -74,6 +74,9 @@ public: #endif return hashCode; } + + static void prepareToExit() { manager()._exiting = true; } + private: static DependencyManager& manager(); @@ -84,6 +87,8 @@ private: QHash> _instanceHash; QHash _inheritanceHash; + + bool _exiting { false }; }; template @@ -95,9 +100,17 @@ QSharedPointer DependencyManager::get() { instance = qSharedPointerCast(manager().safeGet(hashCode)); #ifndef QT_NO_DEBUG + // debug builds... if (instance.isNull()) { qWarning() << "DependencyManager::get(): No instance available for" << typeid(T).name(); } +#else + // for non-debug builds, don't print "No instance available" during shutdown, because + // the act of printing this often causes crashes (because the LogHandler has-been/is-being + // deleted). + if (!manager()._exiting && instance.isNull()) { + qWarning() << "DependencyManager::get(): No instance available for" << typeid(T).name(); + } #endif } From 4effd365ed096e94d0c71077e4a1289129e1bdf5 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 27 Nov 2018 17:34:17 -0800 Subject: [PATCH 067/100] Change "Autotester" to "nitpick". --- tools/nitpick/src/Test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/nitpick/src/Test.cpp b/tools/nitpick/src/Test.cpp index 47458d00ee..2b862783a7 100644 --- a/tools/nitpick/src/Test.cpp +++ b/tools/nitpick/src/Test.cpp @@ -677,7 +677,7 @@ bool Test::createTestAutoScript(const QString& directory) { stream << "if (typeof PATH_TO_THE_REPO_PATH_UTILS_FILE === 'undefined') PATH_TO_THE_REPO_PATH_UTILS_FILE = 'https://raw.githubusercontent.com/highfidelity/hifi_tests/master/tests/utils/branchUtils.js';\n"; stream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);\n"; - stream << "var nitpick = createAutoTester(Script.resolvePath('.'));\n\n"; + stream << "var nitpick = createNitpick(Script.resolvePath('.'));\n\n"; stream << "nitpick.enableAuto();\n\n"; stream << "Script.include('./test.js?raw=true');\n"; @@ -758,7 +758,7 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact "/tests/utils/branchUtils.js\";" << endl; textStream << "Script.include(PATH_TO_THE_REPO_PATH_UTILS_FILE);" << endl; - textStream << "var nitpick = createAutoTester(Script.resolvePath(\".\"));" << endl << endl; + textStream << "var nitpick = createNitpick(Script.resolvePath(\".\"));" << endl << endl; textStream << "var testsRootPath = nitpick.getTestsRootPath();" << endl << endl; From 59a030a16f3c2b89d47b1007e959dcf052ad546d Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Tue, 27 Nov 2018 17:41:00 -0800 Subject: [PATCH 068/100] Correct message to user. --- tools/nitpick/src/Test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/nitpick/src/Test.cpp b/tools/nitpick/src/Test.cpp index 2b862783a7..e17978d9d0 100644 --- a/tools/nitpick/src/Test.cpp +++ b/tools/nitpick/src/Test.cpp @@ -620,7 +620,7 @@ void Test::createTestAutoScript() { } if (createTestAutoScript(_testDirectory)) { - QMessageBox::information(0, "Success", "'nitpick.js` script has been created"); + QMessageBox::information(0, "Success", "'testAuto.js` script has been created"); } } @@ -748,9 +748,9 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact QTextStream textStream(&allTestsFilename); - textStream << "// This is an automatically generated file, created by auto-tester" << endl; + textStream << "// This is an automatically generated file, created by nitpick" << endl; - // Include 'autoTest.js' + // Include 'nitpick.js' QString branch = nitpick->getSelectedBranch(); QString user = nitpick->getSelectedUser(); From 8be775c2b70239e0c5d046082b84b02eac3875d9 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 28 Nov 2018 10:54:39 -0800 Subject: [PATCH 069/100] don't save joint information for avatar entities --- interface/src/AvatarBookmarks.cpp | 40 +++++++++++++++++++------------ 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/interface/src/AvatarBookmarks.cpp b/interface/src/AvatarBookmarks.cpp index 534fb15d93..099171a427 100644 --- a/interface/src/AvatarBookmarks.cpp +++ b/interface/src/AvatarBookmarks.cpp @@ -247,25 +247,35 @@ QVariantMap AvatarBookmarks::getAvatarDataToBookmark() { bookmark.insert(ENTRY_AVATAR_URL, avatarUrl); bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale); - QScriptEngine scriptEngine; QVariantList wearableEntities; auto treeRenderer = DependencyManager::get(); EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr; - auto avatarEntities = myAvatar->getAvatarEntityData(); - for (auto entityID : avatarEntities.keys()) { - auto entity = entityTree->findEntityByID(entityID); - if (!entity || !isWearableEntity(entity)) { - continue; + + if (entityTree) { + QScriptEngine scriptEngine; + auto avatarEntities = myAvatar->getAvatarEntityData(); + for (auto entityID : avatarEntities.keys()) { + auto entity = entityTree->findEntityByID(entityID); + if (!entity || !isWearableEntity(entity)) { + continue; + } + + QVariantMap avatarEntityData; + + EncodeBitstreamParams params; + auto desiredProperties = entity->getEntityProperties(params); + desiredProperties += PROP_LOCAL_POSITION; + desiredProperties += PROP_LOCAL_ROTATION; + desiredProperties -= PROP_JOINT_ROTATIONS_SET; + desiredProperties -= PROP_JOINT_ROTATIONS; + desiredProperties -= PROP_JOINT_TRANSLATIONS_SET; + desiredProperties -= PROP_JOINT_TRANSLATIONS; + + EntityItemProperties entityProperties = entity->getProperties(desiredProperties); + QScriptValue scriptProperties = EntityItemPropertiesToScriptValue(&scriptEngine, entityProperties); + avatarEntityData["properties"] = scriptProperties.toVariant(); + wearableEntities.append(QVariant(avatarEntityData)); } - QVariantMap avatarEntityData; - EncodeBitstreamParams params; - auto desiredProperties = entity->getEntityProperties(params); - desiredProperties += PROP_LOCAL_POSITION; - desiredProperties += PROP_LOCAL_ROTATION; - EntityItemProperties entityProperties = entity->getProperties(desiredProperties); - QScriptValue scriptProperties = EntityItemPropertiesToScriptValue(&scriptEngine, entityProperties); - avatarEntityData["properties"] = scriptProperties.toVariant(); - wearableEntities.append(QVariant(avatarEntityData)); } bookmark.insert(ENTRY_AVATAR_ENTITIES, wearableEntities); return bookmark; From 1683179fe5fb75cd6d89bedb90614b283e971d45 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 29 Nov 2018 09:14:10 +1300 Subject: [PATCH 070/100] Remove unused constant --- interface/src/ModelSelector.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ModelSelector.cpp b/interface/src/ModelSelector.cpp index 7e428a294d..3223e3ab9c 100644 --- a/interface/src/ModelSelector.cpp +++ b/interface/src/ModelSelector.cpp @@ -19,7 +19,6 @@ #include static const QString AVATAR_HEAD_AND_BODY_STRING = "Avatar Body with Head"; -static const QString AVATAR_ATTACHEMENT_STRING = "Avatar Attachment"; static const QString ENTITY_MODEL_STRING = "Entity Model"; ModelSelector::ModelSelector() { From c29f6346d8ad9a237d06a3cab2fb43add240ecc8 Mon Sep 17 00:00:00 2001 From: Clement Date: Wed, 28 Nov 2018 14:04:14 -0800 Subject: [PATCH 071/100] Clear mixing structures when we stop mixing for node --- assignment-client/src/audio/AudioMixerClientData.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 9a78ba31a2..90698bfac8 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -337,6 +337,13 @@ void AudioMixerClientData::removeAgentAvatarAudioStream() { if (it != _audioStreams.end()) { _audioStreams.erase(it); + + // Clear mixing structures so that they get recreated with up to date + // data if the stream comes back + setHasReceivedFirstMix(false); + _streams.skipped.clear(); + _streams.inactive.clear(); + _streams.active.clear(); } } From 11252a8f56d052b922004e5801cb7e54b5ce9771 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 28 Nov 2018 16:48:34 -0800 Subject: [PATCH 072/100] Fix UBSAN warning (left-shift of negative integer) when peak limiter is called with implausibly large (or NaN) audio values --- libraries/audio/src/AudioDynamics.h | 32 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/libraries/audio/src/AudioDynamics.h b/libraries/audio/src/AudioDynamics.h index 8dbc7a75cc..6bfd249bc9 100644 --- a/libraries/audio/src/AudioDynamics.h +++ b/libraries/audio/src/AudioDynamics.h @@ -51,7 +51,7 @@ #include // convert float to int using round-to-nearest FORCEINLINE static int32_t floatToInt(float x) { - return _mm_cvt_ss2si(_mm_load_ss(&x)); + return _mm_cvt_ss2si(_mm_set_ss(x)); } #else @@ -150,7 +150,7 @@ static const int IEEE754_EXPN_BIAS = 127; // // Peak detection and -log2(x) for float input (mono) // x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff -// x > 2^LOG2_HEADROOM undefined +// x > 2^LOG2_HEADROOM returns 0 // FORCEINLINE static int32_t peaklog2(float* input) { @@ -161,12 +161,12 @@ FORCEINLINE static int32_t peaklog2(float* input) { uint32_t peak = u & IEEE754_FABS_MASK; // split into e and x - 1.0 - int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; + int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff; - // saturate - if (e > 31) { - return 0x7fffffff; + // saturate when e > 31 or e < 0 + if ((uint32_t)e > 31) { + return 0x7fffffff & ~(e >> 31); } int k = x >> (31 - LOG2_TABBITS); @@ -186,7 +186,7 @@ FORCEINLINE static int32_t peaklog2(float* input) { // // Peak detection and -log2(x) for float input (stereo) // x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff -// x > 2^LOG2_HEADROOM undefined +// x > 2^LOG2_HEADROOM returns 0 // FORCEINLINE static int32_t peaklog2(float* input0, float* input1) { @@ -200,12 +200,12 @@ FORCEINLINE static int32_t peaklog2(float* input0, float* input1) { uint32_t peak = MAX(u0, u1); // split into e and x - 1.0 - int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; + int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff; - // saturate - if (e > 31) { - return 0x7fffffff; + // saturate when e > 31 or e < 0 + if ((uint32_t)e > 31) { + return 0x7fffffff & ~(e >> 31); } int k = x >> (31 - LOG2_TABBITS); @@ -225,7 +225,7 @@ FORCEINLINE static int32_t peaklog2(float* input0, float* input1) { // // Peak detection and -log2(x) for float input (quad) // x < 2^(31-LOG2_HEADROOM) returns 0x7fffffff -// x > 2^LOG2_HEADROOM undefined +// x > 2^LOG2_HEADROOM returns 0 // FORCEINLINE static int32_t peaklog2(float* input0, float* input1, float* input2, float* input3) { @@ -243,12 +243,12 @@ FORCEINLINE static int32_t peaklog2(float* input0, float* input1, float* input2, uint32_t peak = MAX(MAX(u0, u1), MAX(u2, u3)); // split into e and x - 1.0 - int e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; + int32_t e = IEEE754_EXPN_BIAS - (peak >> IEEE754_MANT_BITS) + LOG2_HEADROOM; int32_t x = (peak << IEEE754_EXPN_BITS) & 0x7fffffff; - // saturate - if (e > 31) { - return 0x7fffffff; + // saturate when e > 31 or e < 0 + if ((uint32_t)e > 31) { + return 0x7fffffff & ~(e >> 31); } int k = x >> (31 - LOG2_TABBITS); From 181f2b4263272fa0c4f99b5b1da57d12195e9b7d Mon Sep 17 00:00:00 2001 From: Clement Date: Wed, 28 Nov 2018 17:27:59 -0800 Subject: [PATCH 073/100] 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 074/100] 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 075/100] 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 88d935a28e755341de9ef34edb38602713d15539 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Thu, 29 Nov 2018 08:12:14 -0800 Subject: [PATCH 076/100] Fix the audio injector "pitch" property --- libraries/audio/src/AudioInjector.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 4af6e79caf..1581990e0c 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -447,9 +447,9 @@ AudioInjectorPointer AudioInjector::playSound(SharedSoundPointer sound, const A using AudioConstants::AudioSample; using AudioConstants::SAMPLE_RATE; const int standardRate = SAMPLE_RATE; - // limit to 4 octaves - const int pitch = glm::clamp(options.pitch, 1 / 16.0f, 16.0f); - const int resampledRate = SAMPLE_RATE / pitch; + // limit pitch to 4 octaves + const float pitch = glm::clamp(options.pitch, 1 / 16.0f, 16.0f); + const int resampledRate = glm::round(SAMPLE_RATE / pitch); auto audioData = sound->getAudioData(); auto numChannels = audioData->getNumChannels(); @@ -499,9 +499,9 @@ AudioInjectorPointer AudioInjector::playSound(AudioDataPointer audioData, const using AudioConstants::AudioSample; using AudioConstants::SAMPLE_RATE; const int standardRate = SAMPLE_RATE; - // limit to 4 octaves - const int pitch = glm::clamp(options.pitch, 1 / 16.0f, 16.0f); - const int resampledRate = SAMPLE_RATE / pitch; + // limit pitch to 4 octaves + const float pitch = glm::clamp(options.pitch, 1 / 16.0f, 16.0f); + const int resampledRate = glm::round(SAMPLE_RATE / pitch); auto numChannels = audioData->getNumChannels(); auto numFrames = audioData->getNumFrames(); From 59b7cdf318336ded6c26ea1b039cf7fa648c189d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 29 Nov 2018 13:10:15 -0800 Subject: [PATCH 077/100] Fix empty rgb field in Create going black --- scripts/system/html/js/colpick.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/system/html/js/colpick.js b/scripts/system/html/js/colpick.js index 505dd294d6..e4ad65dfb6 100644 --- a/scripts/system/html/js/colpick.js +++ b/scripts/system/html/js/colpick.js @@ -309,6 +309,9 @@ For usage and examples: colpick.com/plugin }, // Fix the values if the user enters a negative or high value fixHSB = function (hsb) { + hsb.h = isNaN(hsb.h) ? 0 : hsb.h; + hsb.s = isNaN(hsb.s) ? 0 : hsb.s; + hsb.b = isNaN(hsb.b) ? 0 : hsb.b; return { h: Math.min(360, Math.max(0, hsb.h)), s: Math.min(100, Math.max(0, hsb.s)), @@ -316,6 +319,9 @@ For usage and examples: colpick.com/plugin }; }, fixRGB = function (rgb) { + rgb.r = isNaN(rgb.r) ? 0 : rgb.r; + rgb.g = isNaN(rgb.g) ? 0 : rgb.g; + rgb.b = isNaN(rgb.b) ? 0 : rgb.b; return { r: Math.min(255, Math.max(0, rgb.r)), g: Math.min(255, Math.max(0, rgb.g)), From c53c52c7a018de4e9f36d807e5fa359a848e5054 Mon Sep 17 00:00:00 2001 From: Clement Date: Thu, 29 Nov 2018 17:42:04 -0800 Subject: [PATCH 078/100] 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 87c863584d4bc04af3a38b7d515ffb1ea5b3df25 Mon Sep 17 00:00:00 2001 From: NissimHadar Date: Thu, 29 Nov 2018 17:43:19 -0800 Subject: [PATCH 079/100] Just to remove conflict. --- tools/nitpick/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/nitpick/README.md b/tools/nitpick/README.md index a02980ddfe..7d75d660d7 100644 --- a/tools/nitpick/README.md +++ b/tools/nitpick/README.md @@ -1,6 +1,6 @@ # nitpick -Nitpick is a stand alone application that provides a mechanism for regression testing. The general idea is simple: +Nitpick is a stand alone application that provides a mechanism for regression testing. The general idea is simple: * Each test folder has a script that produces a set of snapshots. * The snapshots are compared to a 'canonical' set of images that have been produced beforehand. * The result, if any test failed, is a zipped folder describing the failure. From 051b7cfbb8106007e81564a04545076f8214d8be Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 30 Nov 2018 16:12:21 -0800 Subject: [PATCH 080/100] 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 43b5a141806202774b7b7e79fe171871c8917ac3 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Fri, 30 Nov 2018 20:25:35 -0800 Subject: [PATCH 081/100] fixing missing header function --- interface/src/ui/Keyboard.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/Keyboard.h b/interface/src/ui/Keyboard.h index 416bfacd3f..a66ae74ced 100644 --- a/interface/src/ui/Keyboard.h +++ b/interface/src/ui/Keyboard.h @@ -94,7 +94,7 @@ public: void registerKeyboardHighlighting(); bool isRaised() const; void setRaised(bool raised); - + void setResetKeyboardPositionOnRaise(bool reset); bool isPassword() const; void setPassword(bool password); From c0bf832e393655d7e455c0c5789e7889673b5a65 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Sun, 2 Dec 2018 16:18:36 -0800 Subject: [PATCH 082/100] 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 5beb81060420fa4286d08ca64ae7981524d12b2c Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Mon, 3 Dec 2018 16:09:10 -0800 Subject: [PATCH 083/100] adding more steam login flow --- interface/resources/qml/LoginDialog.qml | 2 +- .../qml/LoginDialog/CantAccessBody.qml | 2 +- .../qml/LoginDialog/CompleteProfileBody.qml | 76 ++++++++-------- .../qml/LoginDialog/LinkAccountBody.qml | 85 +++++++++++++----- .../qml/LoginDialog/LoggingInBody.qml | 12 +-- .../resources/qml/LoginDialog/SignUpBody.qml | 19 ++-- .../qml/LoginDialog/UsernameCollisionBody.qml | 86 ++++++------------- .../resources/qml/OverlayLoginDialog.qml | 2 +- .../resources/qml/controlsUit/TextField.qml | 6 +- .../qml/dialogs/TabletLoginDialog.qml | 2 +- 10 files changed, 149 insertions(+), 143 deletions(-) diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index ce6fdc095a..2a67c568d5 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -92,6 +92,6 @@ FocusScope { } Component.onCompleted: { - bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader }); + bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false }); } } diff --git a/interface/resources/qml/LoginDialog/CantAccessBody.qml b/interface/resources/qml/LoginDialog/CantAccessBody.qml index 4eeb048318..5d91d9c9ee 100644 --- a/interface/resources/qml/LoginDialog/CantAccessBody.qml +++ b/interface/resources/qml/LoginDialog/CantAccessBody.qml @@ -131,7 +131,7 @@ Item { horizontalAlignment: Text.AlignHCenter Component.onCompleted: { bodyText.text = root.isTablet ? qsTr("Please navigate to your default browser\nto recover your account.\nIf you are in a VR headset, please take it off.") : - qsTr("Please navigate to your default browser to recover your account.\nIf you are in a VR headset, please take it off."); + qsTr("Please navigate to your default browser to recover your account.\nIf you are in a VR headset,\nplease take it off."); bodyTextMetrics.text = bodyText.text; bodyText bodyText.anchors.leftMargin = (parent.width - bodyTextMetrics.width) / 2; diff --git a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml index 89ed567752..873b53f351 100644 --- a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml +++ b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml @@ -26,14 +26,14 @@ Item { readonly property int fontSize: 15 readonly property bool fontBold: true + readonly property bool withSteam: withSteam + QtObject { id: d readonly property int minWidth: 480 - // readonly property int minWidthButton: !root.isTablet ? 256 : 174 - readonly property int minWidthButton: 36 + readonly property int minWidthButton: !root.isTablet ? 256 : 174 property int maxWidth: root.isTablet ? 1280 : root.width readonly property int minHeight: 120 - // readonly property int minHeightButton: !root.isTablet ? 56 : 42 readonly property int minHeightButton: 36 property int maxHeight: root.isTablet ? 720 : root.height @@ -70,7 +70,7 @@ Item { height: banner.height anchors { top: parent.top - topMargin: 85 + topMargin: 0.18 * parent.height } Image { id: banner @@ -121,7 +121,7 @@ Item { } Item { id: buttons - width: Math.max(banner.width, cancelContainer.width + profileButton.width) + width: banner.width height: d.minHeightButton anchors { top: parent.top @@ -129,43 +129,24 @@ Item { left: parent.left leftMargin: (parent.width - banner.width) / 2 } - Item { - id: cancelContainer - width: cancelText.width - height: d.minHeightButton + HifiControlsUit.Button { + id: cancelButton anchors { top: parent.top left: parent.left } - Text { - id: cancelText - text: qsTr("Cancel"); + width: (parent.width - hifi.dimensions.contentSpacing.x) / 2 + height: d.minHeightButton - lineHeight: 1 - color: "white" - font.family: completeProfileBody.fontFamily - font.pixelSize: completeProfileBody.fontSize - font.capitalization: Font.AllUppercase; - font.bold: completeProfileBody.fontBold - lineHeightMode: Text.ProportionalHeight - anchors.centerIn: parent + text: qsTr("CANCEL") + color: hifi.buttons.noneBorderlessWhite + + fontFamily: completeProfileBody.fontFamily + fontSize: completeProfileBody.fontSize + fontBold: completeProfileBody.fontBold + onClicked: { + bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader }); } - MouseArea { - id: cancelArea - anchors.fill: parent - hoverEnabled: true - onEntered: { - Tablet.playSound(TabletEnums.ButtonHover); - } - onClicked: { - Tablet.playSound(TabletEnums.ButtonClick); - bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader }); - } - } - TextMetrics { - id: profileButtonTextMetrics - font: cancelText.font - text: qsTr("CREATE YOUR PROFILE") } HifiControlsUit.Button { id: profileButton @@ -173,7 +154,7 @@ Item { top: parent.top right: parent.right } - width: Math.max(profileButtonTextMetrics.width + 2 * hifi.dimensions.contentSpacing.x, d.minWidthButton) + width: (parent.width - hifi.dimensions.contentSpacing.x) / 2 height: d.minHeightButton text: qsTr("Create your profile") @@ -185,8 +166,6 @@ Item { onClicked: { loginErrorMessage.visible = false; loginDialog.createAccountFromSteam(); - bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, - "withSteam": true, "fromBody": "CompleteProfileBody" }) } } } @@ -212,7 +191,7 @@ Item { onLinkActivated: { loginDialog.isLogIn = true; - bodyLoader.setSource("SignInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": "" }); + bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": "", "linkSteam": true }); } } @@ -246,11 +225,26 @@ Item { lineHeight: 1 lineHeightMode: Text.ProportionalHeight - onLinkActivated: loginDialog.openUrl(link) + onLinkActivated: loginDialog.openUrl(link); } } } + Connections { + target: loginDialog + onHandleCreateCompleted: { + console.log("Create Succeeded") + + loginDialog.loginThroughSteam(); + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true }); + } + onHandleCreateFailed: { + console.log("Create Failed: " + error); + + bodyLoader.setSource("UsernameCollisionBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader }); + } + } + Component.onCompleted: { //but rise Tablet's one instead for Tablet interface if (root.isTablet || root.isOverlay) { diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 1c01f675e3..1f93904774 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -35,6 +35,7 @@ Item { property bool punctuationMode: false property bool withSteam: false + property bool linkSteam: linkSteam property bool withOculus: false property string errorString: errorString @@ -44,7 +45,6 @@ Item { readonly property int minWidthButton: !root.isTablet ? 256 : 174 property int maxWidth: root.isTablet ? 1280 : root.width readonly property int minHeight: 120 - // readonly property int minHeightButton: !root.isTablet ? 56 : 42 readonly property int minHeightButton: 36 property int maxHeight: root.isTablet ? 720 : root.height @@ -73,11 +73,19 @@ Item { loginDialog.isLogIn = true; loginErrorMessage.text = linkAccountBody.errorString; loginErrorMessage.visible = (linkAccountBody.errorString !== ""); - loginButton.text = "Log In"; + loginButton.text = !linkAccountBody.linkSteam ? "Log In" : "Link Account"; loginButton.color = hifi.buttons.blue; emailField.placeholderText = "Username or Email"; var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", ""); emailField.text = keepMeLoggedInCheckbox.checked ? savedUsername === "Unknown user" ? "" : savedUsername : ""; + if (linkAccountBody.linkSteam) { + steamInfoText.anchors.top = passwordField.bottom; + keepMeLoggedInCheckbox.anchors.top = steamInfoText.bottom; + loginButton.width = (passwordField.width - hifi.dimensions.contentSpacing.x) / 2; + loginButton.anchors.right = emailField.right; + } else { + loginButton.anchors.left = emailField.left; + } loginContainer.visible = true; } @@ -102,7 +110,7 @@ Item { height: banner.height anchors { bottom: loginContainer.top - bottomMargin: 0.125 * parent.height + bottomMargin: 0.07 * parent.height } Image { id: banner @@ -152,6 +160,7 @@ Item { width: banner.width height: linkAccountBody.textFieldHeight font.pixelSize: linkAccountBody.textFieldFontSize + styleRenderType: Text.QtRendering anchors { top: parent.top topMargin: loginErrorMessage.height @@ -189,6 +198,7 @@ Item { width: banner.width height: linkAccountBody.textFieldHeight font.pixelSize: linkAccountBody.textFieldFontSize + styleRenderType: Text.QtRendering placeholderText: "Password" activeFocusOnPress: true echoMode: passwordFieldMouseArea.showPassword ? TextInput.Normal : TextInput.Password @@ -269,16 +279,30 @@ Item { } onCheckedChanged: { Settings.setValue("keepMeLoggedIn", checked); - if (checked) { - Settings.setValue("keepMeLoggedIn/savedUsername", Account.username); - var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", ""); - emailField.text = savedUsername === "Unknown user" ? "" : savedUsername; - } else { - Settings.setValue("keepMeLoggedIn/savedUsername", ""); - } } Component.onDestruction: { Settings.setValue("keepMeLoggedIn", checked); + if (checked) { + Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text); + } + } + } + HifiControlsUit.Button { + id: cancelButton + width: (passwordField.width - hifi.dimensions.contentSpacing.x) / 2; + height: d.minHeightButton + text: qsTr("Cancel") + fontFamily: linkAccountBody.fontFamily + fontSize: linkAccountBody.fontSize + fontBold: linkAccountBody.fontBold + color: hifi.buttons.noneBorderlessWhite; + visible: linkAccountBody.linkSteam + anchors { + top: keepMeLoggedInCheckbox.bottom + topMargin: hifi.dimensions.contentSpacing.y + } + onClicked: { + bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": linkAccountBody.withSteam, "errorString": errorString }); } } HifiControlsUit.Button { @@ -292,22 +316,38 @@ Item { anchors { top: keepMeLoggedInCheckbox.bottom topMargin: hifi.dimensions.contentSpacing.y - left: emailField.left } onClicked: { linkAccountBody.login() } } + Text { + id: steamInfoText + visible: linkAccountBody.linkSteam + anchors { + top: loginButton.bottom + topMargin: hifi.dimensions.contentSpacing.y + left: emailField.left + } + + font.family: linkAccountBody.fontFamily + font.pixelSize: linkAccountBody.textFieldFontSize + color: "white" + text: qsTr("Your Steam account information will not be exposed to others."); + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } HifiStylesUit.ShortcutText { id: cantAccessText z: 10 + visible: !linkAccountBody.linkSteam anchors { top: loginButton.bottom topMargin: hifi.dimensions.contentSpacing.y left: emailField.left } font.family: linkAccountBody.fontFamily - font.pixelSize: 18 + font.pixelSize: linkAccountBody.textFieldFontSize text: " Can't access your account?" @@ -349,6 +389,10 @@ Item { "withSteam": linkAccountBody.withSteam, "withOculus": linkAccountBody.withOculus, "fromBody": "LinkAccountBody" }); } Component.onCompleted: { + if (linkAccountBody.linkSteam) { + continueButton.visible = false; + return; + } if (loginDialog.isOculusStoreRunning()) { continueButton.text = qsTr("CONTINUE WITH OCULUS"); continueButton.buttonGlyph = hifi.glyphs.oculus; @@ -366,10 +410,11 @@ Item { id: signUpContainer width: loginContainer.width height: signUpTextMetrics.height + visible: !linkAccountBody.linkSteam anchors { left: loginContainer.left top: loginContainer.bottom - // topMargin: 0.25 * parent.height + topMargin: 0.05 * parent.height } TextMetrics { id: signUpTextMetrics @@ -406,7 +451,7 @@ Item { onLinkActivated: { Tablet.playSound(TabletEnums.ButtonClick); bodyLoader.setSource("SignUpBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, - "errorString": "" }); + "errorString": "", "linkSteam": linkAccountBody.linkSteam }); } } } @@ -430,7 +475,7 @@ Item { fontFamily: linkAccountBody.fontFamily fontSize: linkAccountBody.fontSize fontBold: linkAccountBody.fontBold - visible: loginDialog.getLoginDialogPoppedUp() + visible: loginDialog.getLoginDialogPoppedUp() && !linkAccountBody.linkSteam; onClicked: { if (loginDialog.getLoginDialogPoppedUp()) { console.log("[ENCOURAGELOGINDIALOG]: user dismissed login screen") @@ -464,11 +509,11 @@ Item { case Qt.Key_Return: event.accepted = true; Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text); - linkAccountBody.login(); - break; - case Qt.Key_Escape: - event.accepted = true; - root.tryDestroy(); + if (linkAccountBody.linkSteam) { + linkAccountBody.linkSteam(); + } else { + linkAccountBody.login(); + } break; } } diff --git a/interface/resources/qml/LoginDialog/LoggingInBody.qml b/interface/resources/qml/LoginDialog/LoggingInBody.qml index a594e7ed17..92d5113251 100644 --- a/interface/resources/qml/LoginDialog/LoggingInBody.qml +++ b/interface/resources/qml/LoginDialog/LoggingInBody.qml @@ -130,7 +130,7 @@ Item { height: banner.height anchors { top: parent.top - topMargin: 85 + topMargin: 0.18 * parent.height } Image { id: banner @@ -260,8 +260,8 @@ Item { var errorString = ""; if (loggingInBody.withSteam) { loggingInGlyph.visible = false; - errorString = "Your Steam authentication has failed. Please make sure you are logged into Steam and try again." - bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": errorString }); + errorString = "Your Steam authentication has failed. Please make sure you are logged into Steam and try again."; + bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": loggingInBody.withSteam, "errorString": errorString }); } else if (loggingInBody.withOculus) { loggingInGlyph.visible = false; errorString = "Your Oculus authentication has failed. Please make sure you are logged into Oculus and try again." @@ -269,11 +269,7 @@ Item { } else { errorString = "Username or password is incorrect."; - if (loginDialog.isLogIn && loggingInBody.withSteam) { - bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader }); - } else { - bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": errorString }); - } + bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": errorString }); } } } diff --git a/interface/resources/qml/LoginDialog/SignUpBody.qml b/interface/resources/qml/LoginDialog/SignUpBody.qml index bd50714843..81e35256d8 100644 --- a/interface/resources/qml/LoginDialog/SignUpBody.qml +++ b/interface/resources/qml/LoginDialog/SignUpBody.qml @@ -37,6 +37,7 @@ Item { onKeyboardRaisedChanged: d.resize(); property string errorString: errorString + property bool linkSteam: linkSteam QtObject { id: d @@ -44,7 +45,6 @@ Item { readonly property int minWidthButton: !root.isTablet ? 256 : 174 property int maxWidth: root.isTablet ? 1280 : root.width readonly property int minHeight: 120 - // readonly property int minHeightButton: !root.isTablet ? 56 : 42 readonly property int minHeightButton: 36 property int maxHeight: root.isTablet ? 720 : root.height @@ -110,7 +110,7 @@ Item { height: banner.height anchors { bottom: loginContainer.top - bottomMargin: 0.125 * parent.height + bottomMargin: 0.07 * parent.height } Image { id: banner @@ -163,6 +163,7 @@ Item { height: signUpBody.textFieldHeight placeholderText: "Username" font.pixelSize: signUpBody.textFieldFontSize + styleRenderType: Text.QtRendering anchors { top: parent.top topMargin: loginErrorMessage.height @@ -210,6 +211,7 @@ Item { } placeholderText: "Username or Email" font.pixelSize: signUpBody.textFieldFontSize + styleRenderType: Text.QtRendering activeFocusOnPress: true Keys.onPressed: { switch (event.key) { @@ -248,6 +250,7 @@ Item { height: signUpBody.textFieldHeight placeholderText: "Password" font.pixelSize: signUpBody.textFieldFontSize + styleRenderType: Text.QtRendering activeFocusOnPress: true echoMode: passwordFieldMouseArea.showPassword ? TextInput.Normal : TextInput.Password anchors { @@ -336,16 +339,12 @@ Item { } onCheckedChanged: { Settings.setValue("keepMeLoggedIn", checked); - if (checked) { - Settings.setValue("keepMeLoggedIn/savedUsername", Account.username); - var savedUsername = Settings.getValue("keepMeLoggedIn/savedUsername", ""); - usernameField.text = savedUsername === "Unknown user" ? "" : savedUsername; - } else { - Settings.setValue("keepMeLoggedIn/savedUsername", ""); - } } Component.onDestruction: { Settings.setValue("keepMeLoggedIn", checked); + if (checked) { + Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text); + } } } @@ -370,7 +369,7 @@ Item { fontSize: signUpBody.fontSize fontBold: signUpBody.fontBold onClicked: { - bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader }); + bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": signUpBody.linkSteam }); } } HifiControlsUit.Button { diff --git a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml index 2771deaf05..8e9e04c9d0 100644 --- a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml +++ b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml @@ -29,8 +29,7 @@ Item { function create() { mainTextContainer.visible = false - loginDialog.createAccountFromSteam(textField.text) - bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true, "fromBody": "UsernameCollisionBody" }); + loginDialog.createAccountFromSteam(textField.text); } property bool keyboardEnabled: false @@ -45,7 +44,6 @@ Item { readonly property int minWidthButton: !root.isTablet ? 256 : 174 property int maxWidth: root.isTablet ? 1280 : root.width readonly property int minHeight: 120 - // readonly property int minHeightButton: !root.isTablet ? 56 : 42 readonly property int minHeightButton: 36 property int maxHeight: root.isTablet ? 720 : root.height @@ -84,7 +82,7 @@ Item { height: banner.height anchors { top: parent.top - topMargin: 85 + topMargin: 0.18 * parent.height } Image { id: banner @@ -110,7 +108,7 @@ Item { } font.family: usernameCollisionBody.fontFamily - font.pixelSize: usernameCollisionBody.fontSize - 10 + font.pixelSize: usernameCollisionBody.fontSize font.bold: usernameCollisionBody.fontBold text: qsTr("Your Steam username is not available.") wrapMode: Text.WordWrap @@ -130,7 +128,8 @@ Item { topMargin: hifi.dimensions.contentSpacing.y } font.family: "Fira Sans" - font.pixelSize: usernameCollisionBody.fontSize - 10 + font.pixelSize: usernameCollisionBody.fontSize + styleRenderType: Text.QtRendering font.bold: usernameCollisionBody.fontBold width: banner.width @@ -170,7 +169,7 @@ Item { Item { id: buttons - width: Math.max(banner.width, cancelContainer.width + profileButton.width) + width: banner.width height: d.minHeightButton anchors { top: textField.bottom @@ -179,45 +178,24 @@ Item { leftMargin: (parent.width - banner.width) / 2 } - Item { - id: cancelContainer - width: cancelText.width - height: d.minHeightButton + HifiControlsUit.Button { + id: cancelButton anchors { top: parent.top left: parent.left } - Text { - id: cancelText - text: qsTr("Cancel"); + width: (parent.width - hifi.dimensions.contentSpacing.x) / 2 + height: d.minHeightButton - lineHeight: 1 - color: "white" - font.family: usernameCollisionBody.fontFamily - font.pixelSize: usernameCollisionBody.fontSize - font.capitalization: Font.AllUppercase; - font.bold: usernameCollisionBody.fontBold - lineHeightMode: Text.ProportionalHeight - anchors.centerIn: parent + text: qsTr("CANCEL") + color: hifi.buttons.noneBorderlessWhite + + fontFamily: usernameCollisionBody.fontFamily + fontSize: usernameCollisionBody.fontSize + fontBold: usernameCollisionBody.fontBold + onClicked: { + bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader }); } - MouseArea { - id: cancelArea - anchors.fill: parent - acceptedButtons: Qt.LeftButton - hoverEnabled: true - onEntered: { - Tablet.playSound(TabletEnums.ButtonHover); - } - onClicked: { - Tablet.playSound(TabletEnums.ButtonClick); - bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader }); - } - } - } - TextMetrics { - id: profileButtonTextMetrics - font: cancelText.font - text: qsTr("CREATE YOUR PROFILE") } HifiControlsUit.Button { id: profileButton @@ -225,7 +203,7 @@ Item { top: parent.top right: parent.right } - width: Math.max(profileButtonTextMetrics.width + 2 * hifi.dimensions.contentSpacing.x, d.minWidthButton) + width: (parent.width - hifi.dimensions.contentSpacing.x) / 2 height: d.minHeightButton text: qsTr("Create your profile") @@ -241,23 +219,15 @@ Item { } } - Component.onCompleted: { - //dont rise local keyboard - keyboardEnabled = !root.isTablet && HMD.active; - //but rise Tablet's one instead for Tablet interface - if (root.isTablet || root.isOverlay) { - root.keyboardEnabled = HMD.active; - root.keyboardRaised = Qt.binding( function() { return keyboardRaised; }) - } - - root.text = ""; - d.resize(); - textField.focus = true; - if (usernameCollisionBody.errorString !== "") { - mainTextContainer.visible = true; - mainTextContainer.text = usernameCollisionBody.errorString; - } - } + // Component.onCompleted: { + // root.text = ""; + // d.resize(); + // textField.focus = true; + // if (usernameCollisionBody.errorString !== "") { + // mainTextContainer.visible = true; + // mainTextContainer.text = usernameCollisionBody.errorString; + // } + // } Connections { target: loginDialog diff --git a/interface/resources/qml/OverlayLoginDialog.qml b/interface/resources/qml/OverlayLoginDialog.qml index 566360972f..0bf01ba7e1 100644 --- a/interface/resources/qml/OverlayLoginDialog.qml +++ b/interface/resources/qml/OverlayLoginDialog.qml @@ -121,6 +121,6 @@ FocusScope { Component.onCompleted: { keyboardTimer.start(); - bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": ""}); + bodyLoader.setSource("LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false }); } } diff --git a/interface/resources/qml/controlsUit/TextField.qml b/interface/resources/qml/controlsUit/TextField.qml index d78f3a1340..1d47126cd1 100644 --- a/interface/resources/qml/controlsUit/TextField.qml +++ b/interface/resources/qml/controlsUit/TextField.qml @@ -31,6 +31,7 @@ TextField { property bool hasClearButton: false; property string leftPermanentGlyph: ""; property string centerPlaceholderGlyph: ""; + property int styleRenderType: Text.NativeRendering placeholderText: textField.placeholderText @@ -44,8 +45,8 @@ TextField { // workaround for https://bugreports.qt.io/browse/QTBUG-49297 Keys.onPressed: { switch (event.key) { - case Qt.Key_Return: - case Qt.Key_Enter: + case Qt.Key_Return: + case Qt.Key_Enter: event.accepted = true; // emit accepted signal manually @@ -156,6 +157,7 @@ TextField { selectionColor: hifi.colors.primaryHighlight padding.left: hasRoundedBorder ? textField.height / 2 : ((isSearchField || textField.leftPermanentGlyph !== "") ? textField.height - 2 : 0) + hifi.dimensions.textPadding padding.right: (hasClearButton ? textField.height - 2 : 0) + hifi.dimensions.textPadding + renderType: textField.styleRenderType } HifiControls.Label { diff --git a/interface/resources/qml/dialogs/TabletLoginDialog.qml b/interface/resources/qml/dialogs/TabletLoginDialog.qml index 23ed4886b3..8ce5fd5a2a 100644 --- a/interface/resources/qml/dialogs/TabletLoginDialog.qml +++ b/interface/resources/qml/dialogs/TabletLoginDialog.qml @@ -143,7 +143,7 @@ FocusScope { } Component.onCompleted: { - bodyLoader.setSource("../LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader }); keyboardTimer.start(); + bodyLoader.setSource("../LoginDialog/LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": false }); } } From 22bf4fc5c4498fd2f4e2147aaa3036c2775aeffb Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Mon, 3 Dec 2018 16:11:13 -0800 Subject: [PATCH 084/100] removing `fromBody` --- interface/resources/qml/LoginDialog/UsernameCollisionBody.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml index 8e9e04c9d0..382502886f 100644 --- a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml +++ b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml @@ -234,7 +234,7 @@ Item { onHandleCreateCompleted: { console.log("Create Succeeded") loginDialog.loginThroughSteam(); - bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true, "fromBody": "UsernameCollisionBody" }) + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true }) } onHandleCreateFailed: { console.log("Create Failed: " + error) From dc3381d4a951f0cbeee41172e830f899756fa30b Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Mon, 3 Dec 2018 17:28:10 -0800 Subject: [PATCH 085/100] updating artwork --- interface/resources/qml/LoginDialog.qml | 2 +- .../qml/LoginDialog/LinkAccountBody.qml | 9 ++++++--- .../qml/LoginDialog/LoggingInBody.qml | 1 - .../resources/qml/LoginDialog/SignUpBody.qml | 4 ++-- .../resources/qml/LoginDialog/background.jpg | Bin 0 -> 322933 bytes .../resources/qml/LoginDialog/background.png | Bin 22511 -> 0 bytes .../resources/qml/OverlayLoginDialog.qml | 2 +- .../qml/dialogs/TabletLoginDialog.qml | 2 +- interface/src/Application.cpp | 8 +++++--- interface/src/ui/LoginDialog.cpp | 19 ++++++++++++++++++ interface/src/ui/LoginDialog.h | 2 ++ interface/src/ui/overlays/Web3DOverlay.cpp | 8 ++++++++ interface/src/ui/overlays/Web3DOverlay.h | 1 + 13 files changed, 46 insertions(+), 12 deletions(-) create mode 100644 interface/resources/qml/LoginDialog/background.jpg delete mode 100644 interface/resources/qml/LoginDialog/background.png diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index 2a67c568d5..b0f3b0f1f1 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -52,7 +52,7 @@ FocusScope { Image { id: loginDialogBackground - source: "LoginDialog/background.png" + source: "LoginDialog/background.jpg" anchors.fill: parent z: -2 } diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 1f93904774..ed6affb4b7 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -65,7 +65,7 @@ Item { function login() { loginDialog.login(emailField.text, passwordField.text); - bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "withOculus": false, "fromBody": "" }); + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "withOculus": false }); } function init() { @@ -386,7 +386,7 @@ Item { } bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, - "withSteam": linkAccountBody.withSteam, "withOculus": linkAccountBody.withOculus, "fromBody": "LinkAccountBody" }); + "withSteam": linkAccountBody.withSteam, "withOculus": linkAccountBody.withOculus }); } Component.onCompleted: { if (linkAccountBody.linkSteam) { @@ -402,7 +402,6 @@ Item { } else { continueButton.visible = false; } - } } } @@ -490,6 +489,10 @@ Item { } } + onFocusChanged: { + emailField.focus = focus; + } + Component.onCompleted: { //but rise Tablet's one instead for Tablet interface root.keyboardEnabled = HMD.active; diff --git a/interface/resources/qml/LoginDialog/LoggingInBody.qml b/interface/resources/qml/LoginDialog/LoggingInBody.qml index 92d5113251..b48c2a595f 100644 --- a/interface/resources/qml/LoginDialog/LoggingInBody.qml +++ b/interface/resources/qml/LoginDialog/LoggingInBody.qml @@ -26,7 +26,6 @@ Item { property bool fontBold: true property bool withSteam: withSteam property bool withOculus: withOculus - property string fromBody: fromBody QtObject { id: d diff --git a/interface/resources/qml/LoginDialog/SignUpBody.qml b/interface/resources/qml/LoginDialog/SignUpBody.qml index 81e35256d8..19627c985f 100644 --- a/interface/resources/qml/LoginDialog/SignUpBody.qml +++ b/interface/resources/qml/LoginDialog/SignUpBody.qml @@ -67,7 +67,7 @@ Item { function login() { loginDialog.signup(emailField.text, usernameField.text, passwordField.text); return; - bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "withOculus": false, "fromBody": "" }); + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "withOculus": false }); } function init() { @@ -433,7 +433,7 @@ Item { console.log("Sign Up Completed"); loginDialog.login(usernameField.text, passwordField.text); - bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "fromBody": "" }); + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false }); } onHandleSignupFailed: { console.log("Sign Up Failed") diff --git a/interface/resources/qml/LoginDialog/background.jpg b/interface/resources/qml/LoginDialog/background.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6cf6c47b4759ac700b99c41dada9addf90b1dbda GIT binary patch literal 322933 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

50WcK*0P+`O{{Xl6rTQy!{{Y-?G>7($<0E^Z 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 z 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

iAu#G=nnbs}>)`v3}k(85xTq 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, properties); keyboard->setResetKeyboardPositionOnRaise(false); } + auto loginDialogOverlay = std::dynamic_pointer_cast(getOverlays().getOverlay(_loginDialogOverlayID)); + loginDialogOverlay->setActiveFocus(true); getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(false); getApplicationCompositor().getReticleInterface()->setVisible(false); if (!_loginStateManager.isSetUp()) { diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 54a4680fcd..d6a67207be 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -121,6 +121,25 @@ void LoginDialog::login(const QString& username, const QString& password) const DependencyManager::get()->requestAccessToken(username, password); } +void LoginDialog::loginThroughOculus() { + qDebug() << "Attempting to login through Oculus"; + if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { + steamClient->requestTicket([this](Ticket ticket) { + if (ticket.isNull()) { + emit handleLoginFailed(); + return; + } + + DependencyManager::get()->requestAccessTokenWithSteam(ticket); + }); + } +} + +void LoginDialog::linkOculus() { + qDebug() << "Attempting to link Oculus account"; + +} + void LoginDialog::loginThroughSteam() { qDebug() << "Attempting to login through Steam"; if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index 1c5ecc3f5f..230e18881a 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -65,6 +65,8 @@ protected slots: Q_INVOKABLE bool isOculusStoreRunning() const; Q_INVOKABLE void login(const QString& username, const QString& password) const; + Q_INVOKABLE void loginThroughOculus(); + Q_INVOKABLE void linkOculus(); Q_INVOKABLE void loginThroughSteam(); Q_INVOKABLE void linkSteam(); Q_INVOKABLE void createAccountFromSteam(QString username = QString()); diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 3f06b43a9e..bd1d884ee9 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -473,6 +473,14 @@ void Web3DOverlay::handlePointerEventAsMouse(const PointerEvent& event) { QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent); } +void Web3DOverlay::setActiveFocus(bool focus) { + if (_webSurface && focus) { + if (focus) { + _webSurface->getRootItem()->forceActiveFocus(); + } + } +} + void Web3DOverlay::setProperties(const QVariantMap& properties) { Billboard3DOverlay::setProperties(properties); diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h index 4137ed8680..f52075df5b 100644 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ b/interface/src/ui/overlays/Web3DOverlay.h @@ -44,6 +44,7 @@ public: Q_INVOKABLE void handlePointerEvent(const PointerEvent& event); void handlePointerEventAsTouch(const PointerEvent& event); void handlePointerEventAsMouse(const PointerEvent& event); + void setActiveFocus(bool focus); // setters void setURL(const QString& url); From 541d0ab4d689b2cc50eecb00128210480576105b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 3 Dec 2018 17:33:04 -0800 Subject: [PATCH 086/100] 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 e7e42e34308e42af5d0a53fb88cce310fafff77c Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Tue, 4 Dec 2018 10:03:40 -0800 Subject: [PATCH 087/100] adding steam linking --- .../qml/LoginDialog/CompleteProfileBody.qml | 28 ++++--------------- .../qml/LoginDialog/LinkAccountBody.qml | 12 +++----- .../qml/LoginDialog/LoggingInBody.qml | 17 ++++++++++- .../resources/qml/LoginDialog/SignUpBody.qml | 4 +-- .../qml/LoginDialog/UsernameCollisionBody.qml | 22 ++++----------- 5 files changed, 33 insertions(+), 50 deletions(-) diff --git a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml index 873b53f351..8f7401b975 100644 --- a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml +++ b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml @@ -27,6 +27,7 @@ Item { readonly property bool fontBold: true readonly property bool withSteam: withSteam + property string errorString: errorString QtObject { id: d @@ -94,31 +95,14 @@ Item { // above buttons. anchors.topMargin: (parent.height - additionalTextContainer.height) / 2 - hifi.dimensions.contentSpacing.y - profileButton.height anchors.left: parent.left; + anchors.leftMargin: (parent.width - loginErrorMessageTextMetrics.width) / 2; color: "red"; - font.family: "Cairo" - font.pixelSize: 12 - text: "" + font.family: completeProfileBody.fontFamily + font.pixelSize: completeProfileBody.fontSize + text: completeProfileBody.errorString visible: true } - HifiStylesUit.HiFiGlyphs { - id: loggedInGlyph; - text: hifi.glyphs.steamSquare; - // color - color: "white" - // Size - size: 78; - // Anchors - anchors.left: parent.left; - anchors.leftMargin: (parent.width - loggedInGlyph.size) / 2; - anchors.top: loginErrorMessage.bottom - anchors.topMargin: 2 * hifi.dimensions.contentSpacing.y - // Alignment - horizontalAlignment: Text.AlignHCenter; - verticalAlignment: Text.AlignVCenter; - visible: false; - - } Item { id: buttons width: banner.width @@ -236,7 +220,7 @@ Item { console.log("Create Succeeded") loginDialog.loginThroughSteam(); - bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true }); + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true, "linkSteam": false }); } onHandleCreateFailed: { console.log("Create Failed: " + error); diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index ed6affb4b7..1da2924b33 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -65,7 +65,7 @@ Item { function login() { loginDialog.login(emailField.text, passwordField.text); - bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "withOculus": false }); + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "withOculus": false, "linkSteam": linkAccountBody.linkSteam }); } function init() { @@ -302,7 +302,7 @@ Item { topMargin: hifi.dimensions.contentSpacing.y } onClicked: { - bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": linkAccountBody.withSteam, "errorString": errorString }); + bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": linkAccountBody.withSteam, "errorString": "" }); } } HifiControlsUit.Button { @@ -386,7 +386,7 @@ Item { } bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, - "withSteam": linkAccountBody.withSteam, "withOculus": linkAccountBody.withOculus }); + "withSteam": linkAccountBody.withSteam, "withOculus": linkAccountBody.withOculus, "linkSteam": linkAccountBody.linkSteam }); } Component.onCompleted: { if (linkAccountBody.linkSteam) { @@ -512,11 +512,7 @@ Item { case Qt.Key_Return: event.accepted = true; Settings.setValue("keepMeLoggedIn/savedUsername", emailField.text); - if (linkAccountBody.linkSteam) { - linkAccountBody.linkSteam(); - } else { - linkAccountBody.login(); - } + linkAccountBody.login(); break; } } diff --git a/interface/resources/qml/LoginDialog/LoggingInBody.qml b/interface/resources/qml/LoginDialog/LoggingInBody.qml index b48c2a595f..bfb01bae05 100644 --- a/interface/resources/qml/LoginDialog/LoggingInBody.qml +++ b/interface/resources/qml/LoginDialog/LoggingInBody.qml @@ -26,6 +26,7 @@ Item { property bool fontBold: true property bool withSteam: withSteam property bool withOculus: withOculus + property bool linkSteam: linkSteam QtObject { id: d @@ -88,6 +89,11 @@ Item { } function loadingSuccess() { loggingInSpinner.visible = false; + if (loggingInBody.linkSteam) { + loggingInText.text = "Linking to Steam"; + loginDialog.linkSteam(); + return; + } if (loggingInBody.withSteam) { // reset the flag. loggingInGlyph.visible = false; @@ -247,9 +253,18 @@ Item { Connections { target: loginDialog + onHandleLinkCompleted: { + console.log("Link Succeeded"); + loggingInBody.linkSteam = false; + loadingSuccess(); + } + onHandleLinkFailed: { + console.log("Link Failed: " + error); + bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "linkSteam": true, "errorString": error }); + } onHandleLoginCompleted: { - console.log("Login Succeeded") + console.log("Login Succeeded"); loadingSuccess(); } diff --git a/interface/resources/qml/LoginDialog/SignUpBody.qml b/interface/resources/qml/LoginDialog/SignUpBody.qml index 19627c985f..fc5d30224d 100644 --- a/interface/resources/qml/LoginDialog/SignUpBody.qml +++ b/interface/resources/qml/LoginDialog/SignUpBody.qml @@ -67,7 +67,7 @@ Item { function login() { loginDialog.signup(emailField.text, usernameField.text, passwordField.text); return; - bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "withOculus": false }); + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "withOculus": false, "linkSteam": false }); } function init() { @@ -433,7 +433,7 @@ Item { console.log("Sign Up Completed"); loginDialog.login(usernameField.text, passwordField.text); - bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false }); + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "linkSteam": false }); } onHandleSignupFailed: { console.log("Sign Up Failed") diff --git a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml index 382502886f..a2670cbf62 100644 --- a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml +++ b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml @@ -25,8 +25,6 @@ Item { readonly property int fontSize: 15 readonly property bool fontBold: true - readonly property string errorString: errorString - function create() { mainTextContainer.visible = false loginDialog.createAccountFromSteam(textField.text); @@ -110,7 +108,7 @@ Item { font.family: usernameCollisionBody.fontFamily font.pixelSize: usernameCollisionBody.fontSize font.bold: usernameCollisionBody.fontBold - text: qsTr("Your Steam username is not available.") + text: qsTr("Your Steam username is not available."); wrapMode: Text.WordWrap color: hifi.colors.redAccent lineHeight: 1 @@ -194,7 +192,7 @@ Item { fontSize: usernameCollisionBody.fontSize fontBold: usernameCollisionBody.fontBold onClicked: { - bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader }); + bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "errorString": "" }); } } HifiControlsUit.Button { @@ -219,28 +217,18 @@ Item { } } - // Component.onCompleted: { - // root.text = ""; - // d.resize(); - // textField.focus = true; - // if (usernameCollisionBody.errorString !== "") { - // mainTextContainer.visible = true; - // mainTextContainer.text = usernameCollisionBody.errorString; - // } - // } - Connections { target: loginDialog onHandleCreateCompleted: { - console.log("Create Succeeded") + console.log("Create Succeeded"); loginDialog.loginThroughSteam(); - bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true }) + bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": true, "linkSteam": false }) } onHandleCreateFailed: { console.log("Create Failed: " + error) mainTextContainer.visible = true - mainTextContainer.text = "\"" + textField.text + qsTr("\" is invalid or already taken.") + mainTextContainer.text = "\"" + textField.text + qsTr("\" is invalid or already taken."); } onHandleLoginCompleted: { console.log("Login Succeeded"); From a24cd41367b5a055abd992e52dcc6ac0e9ee43eb Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Tue, 4 Dec 2018 14:19:09 -0800 Subject: [PATCH 088/100] getting textfield into focus --- .../resources/qml/LoginDialog/LinkAccountBody.qml | 10 +++++++--- interface/src/Application.cpp | 12 +++++++----- interface/src/Application.h | 2 ++ interface/src/ui/LoginDialog.cpp | 8 +++++++- interface/src/ui/LoginDialog.h | 4 ++++ interface/src/ui/overlays/Web3DOverlay.cpp | 8 -------- interface/src/ui/overlays/Web3DOverlay.h | 1 - 7 files changed, 27 insertions(+), 18 deletions(-) diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 1da2924b33..89cf8594eb 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -166,7 +166,6 @@ Item { topMargin: loginErrorMessage.height } placeholderText: "Username or Email" - focus: true activeFocusOnPress: true Keys.onPressed: { switch (event.key) { @@ -489,8 +488,13 @@ Item { } } - onFocusChanged: { - emailField.focus = focus; + Connections { + target: loginDialog + onFocusEnabled: { + Qt.callLater(function() { + emailField.forceActiveFocus(); + }) + } } Component.onCompleted: { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 776abf3f2a..cdf44100a0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5849,6 +5849,9 @@ void Application::setKeyboardFocusOverlay(const OverlayID& overlayID) { _keyboardFocusHighlight->setVisible(false); } } + if (overlayID == _loginDialogOverlayID) { + emit loginDialogFocusEnabled(); + } } } @@ -8178,9 +8181,9 @@ void Application::loadDomainConnectionDialog() { } void Application::toggleLogDialog() { - //if (getLoginDialogPoppedUp()) { - // return; - //} + if (getLoginDialogPoppedUp()) { + return; + } if (! _logDialog) { _logDialog = new LogDialog(nullptr, getLogger()); } @@ -8749,8 +8752,7 @@ void Application::createLoginDialogOverlay() { overlays.editOverlay(keyboard->getAnchorID(), properties); keyboard->setResetKeyboardPositionOnRaise(false); } - auto loginDialogOverlay = std::dynamic_pointer_cast(getOverlays().getOverlay(_loginDialogOverlayID)); - loginDialogOverlay->setActiveFocus(true); + setKeyboardFocusOverlay(_loginDialogOverlayID); getApplicationCompositor().getReticleInterface()->setAllowMouseCapture(false); getApplicationCompositor().getReticleInterface()->setVisible(false); if (!_loginStateManager.isSetUp()) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 573919cd26..64bb96a57b 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -344,6 +344,8 @@ signals: void interstitialModeChanged(bool isInInterstitialMode); + void loginDialogFocusEnabled(); + void miniTabletEnabledChanged(bool enabled); public slots: diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index d6a67207be..e17abc4d3e 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -42,8 +42,9 @@ LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) { this, &LoginDialog::handleLoginCompleted); connect(accountManager.data(), &AccountManager::loginFailed, this, &LoginDialog::handleLoginFailed); -#endif + connect(qApp, SIGNAL(loginDialogFocusEnabled()), this, SLOT(onFocusEnabled())); connect(this, SIGNAL(dismissedLoginDialog()), qApp, SLOT(onDismissedLoginDialog())); +#endif } LoginDialog::~LoginDialog() { @@ -307,3 +308,8 @@ void LoginDialog::signupFailed(QNetworkReply* reply) { emit handleSignupFailed(DEFAULT_SIGN_UP_FAILURE_MESSAGE); } } + +void LoginDialog::onFocusEnabled() { + forceActiveFocus(); + emit focusEnabled(); +} diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h index 230e18881a..b5f45de48a 100644 --- a/interface/src/ui/LoginDialog.h +++ b/interface/src/ui/LoginDialog.h @@ -48,6 +48,8 @@ signals: // occurs upon dismissing the encouraging log in. void dismissedLoginDialog(); + void focusEnabled(); + public slots: void linkCompleted(QNetworkReply* reply); void linkFailed(QNetworkReply* reply); @@ -58,6 +60,8 @@ public slots: void signupCompleted(QNetworkReply* reply); void signupFailed(QNetworkReply* reply); + void onFocusEnabled(); + protected slots: Q_INVOKABLE void dismissLoginDialog(); diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index bd1d884ee9..3f06b43a9e 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -473,14 +473,6 @@ void Web3DOverlay::handlePointerEventAsMouse(const PointerEvent& event) { QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent); } -void Web3DOverlay::setActiveFocus(bool focus) { - if (_webSurface && focus) { - if (focus) { - _webSurface->getRootItem()->forceActiveFocus(); - } - } -} - void Web3DOverlay::setProperties(const QVariantMap& properties) { Billboard3DOverlay::setProperties(properties); diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h index f52075df5b..4137ed8680 100644 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ b/interface/src/ui/overlays/Web3DOverlay.h @@ -44,7 +44,6 @@ public: Q_INVOKABLE void handlePointerEvent(const PointerEvent& event); void handlePointerEventAsTouch(const PointerEvent& event); void handlePointerEventAsMouse(const PointerEvent& event); - void setActiveFocus(bool focus); // setters void setURL(const QString& url); From 3951203b559c992bb89ab21cc2758387de2ac4ea Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Tue, 4 Dec 2018 16:50:01 -0800 Subject: [PATCH 089/100] adding tablet bg/no movement in login state --- .../controllers/standard_nomovement.json | 78 ++++++++++++++++++ .../qml/LoginDialog/background_tablet.jpg | Bin 0 -> 278939 bytes .../qml/dialogs/TabletLoginDialog.qml | 2 +- interface/src/Application.cpp | 20 ++++- 4 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 interface/resources/controllers/standard_nomovement.json create mode 100644 interface/resources/qml/LoginDialog/background_tablet.jpg diff --git a/interface/resources/controllers/standard_nomovement.json b/interface/resources/controllers/standard_nomovement.json new file mode 100644 index 0000000000..015bc33056 --- /dev/null +++ b/interface/resources/controllers/standard_nomovement.json @@ -0,0 +1,78 @@ +{ + "name": "Standard to Action (No Movement)", + "channels": [ + { "from": "Standard.LT", "to": "Actions.LeftHandClick" }, + { "from": "Standard.RT", "to": "Actions.RightHandClick" }, + + { "from": "Standard.LeftHand", "to": "Actions.LeftHand" }, + { "from": "Standard.LeftHandThumb1", "to": "Actions.LeftHandThumb1"}, + { "from": "Standard.LeftHandThumb2", "to": "Actions.LeftHandThumb2"}, + { "from": "Standard.LeftHandThumb3", "to": "Actions.LeftHandThumb3"}, + { "from": "Standard.LeftHandThumb4", "to": "Actions.LeftHandThumb4"}, + { "from": "Standard.LeftHandIndex1", "to": "Actions.LeftHandIndex1"}, + { "from": "Standard.LeftHandIndex2", "to": "Actions.LeftHandIndex2"}, + { "from": "Standard.LeftHandIndex3", "to": "Actions.LeftHandIndex3"}, + { "from": "Standard.LeftHandIndex4", "to": "Actions.LeftHandIndex4"}, + { "from": "Standard.LeftHandMiddle1", "to": "Actions.LeftHandMiddle1"}, + { "from": "Standard.LeftHandMiddle2", "to": "Actions.LeftHandMiddle2"}, + { "from": "Standard.LeftHandMiddle3", "to": "Actions.LeftHandMiddle3"}, + { "from": "Standard.LeftHandMiddle4", "to": "Actions.LeftHandMiddle4"}, + { "from": "Standard.LeftHandRing1", "to": "Actions.LeftHandRing1"}, + { "from": "Standard.LeftHandRing2", "to": "Actions.LeftHandRing2"}, + { "from": "Standard.LeftHandRing3", "to": "Actions.LeftHandRing3"}, + { "from": "Standard.LeftHandRing4", "to": "Actions.LeftHandRing4"}, + { "from": "Standard.LeftHandPinky1", "to": "Actions.LeftHandPinky1"}, + { "from": "Standard.LeftHandPinky2", "to": "Actions.LeftHandPinky2"}, + { "from": "Standard.LeftHandPinky3", "to": "Actions.LeftHandPinky3"}, + { "from": "Standard.LeftHandPinky4", "to": "Actions.LeftHandPinky4"}, + + { "from": "Standard.RightHand", "to": "Actions.RightHand" }, + { "from": "Standard.RightHandThumb1", "to": "Actions.RightHandThumb1"}, + { "from": "Standard.RightHandThumb2", "to": "Actions.RightHandThumb2"}, + { "from": "Standard.RightHandThumb3", "to": "Actions.RightHandThumb3"}, + { "from": "Standard.RightHandThumb4", "to": "Actions.RightHandThumb4"}, + { "from": "Standard.RightHandIndex1", "to": "Actions.RightHandIndex1"}, + { "from": "Standard.RightHandIndex2", "to": "Actions.RightHandIndex2"}, + { "from": "Standard.RightHandIndex3", "to": "Actions.RightHandIndex3"}, + { "from": "Standard.RightHandIndex4", "to": "Actions.RightHandIndex4"}, + { "from": "Standard.RightHandMiddle1", "to": "Actions.RightHandMiddle1"}, + { "from": "Standard.RightHandMiddle2", "to": "Actions.RightHandMiddle2"}, + { "from": "Standard.RightHandMiddle3", "to": "Actions.RightHandMiddle3"}, + { "from": "Standard.RightHandMiddle4", "to": "Actions.RightHandMiddle4"}, + { "from": "Standard.RightHandRing1", "to": "Actions.RightHandRing1"}, + { "from": "Standard.RightHandRing2", "to": "Actions.RightHandRing2"}, + { "from": "Standard.RightHandRing3", "to": "Actions.RightHandRing3"}, + { "from": "Standard.RightHandRing4", "to": "Actions.RightHandRing4"}, + { "from": "Standard.RightHandPinky1", "to": "Actions.RightHandPinky1"}, + { "from": "Standard.RightHandPinky2", "to": "Actions.RightHandPinky2"}, + { "from": "Standard.RightHandPinky3", "to": "Actions.RightHandPinky3"}, + { "from": "Standard.RightHandPinky4", "to": "Actions.RightHandPinky4"}, + + { "from": "Standard.LeftFoot", "to": "Actions.LeftFoot" }, + { "from": "Standard.RightFoot", "to": "Actions.RightFoot" }, + + { "from": "Standard.Hips", "to": "Actions.Hips" }, + { "from": "Standard.Spine2", "to": "Actions.Spine2" }, + + { "from": "Standard.Head", "to": "Actions.Head" }, + { "from": "Standard.LeftArm", "to": "Actions.LeftArm" }, + { "from": "Standard.RightArm", "to": "Actions.RightArm" }, + + { "from": "Standard.TrackedObject00", "to" : "Actions.TrackedObject00" }, + { "from": "Standard.TrackedObject01", "to" : "Actions.TrackedObject01" }, + { "from": "Standard.TrackedObject02", "to" : "Actions.TrackedObject02" }, + { "from": "Standard.TrackedObject03", "to" : "Actions.TrackedObject03" }, + { "from": "Standard.TrackedObject04", "to" : "Actions.TrackedObject04" }, + { "from": "Standard.TrackedObject05", "to" : "Actions.TrackedObject05" }, + { "from": "Standard.TrackedObject06", "to" : "Actions.TrackedObject06" }, + { "from": "Standard.TrackedObject07", "to" : "Actions.TrackedObject07" }, + { "from": "Standard.TrackedObject08", "to" : "Actions.TrackedObject08" }, + { "from": "Standard.TrackedObject09", "to" : "Actions.TrackedObject09" }, + { "from": "Standard.TrackedObject10", "to" : "Actions.TrackedObject10" }, + { "from": "Standard.TrackedObject11", "to" : "Actions.TrackedObject11" }, + { "from": "Standard.TrackedObject12", "to" : "Actions.TrackedObject12" }, + { "from": "Standard.TrackedObject13", "to" : "Actions.TrackedObject13" }, + { "from": "Standard.TrackedObject14", "to" : "Actions.TrackedObject14" }, + { "from": "Standard.TrackedObject15", "to" : "Actions.TrackedObject15" } + ] +} diff --git a/interface/resources/qml/LoginDialog/background_tablet.jpg b/interface/resources/qml/LoginDialog/background_tablet.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a46c052c0476e03e37e8b49b56793c06fbf31f4c GIT binary patch literal 278939 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

#mj^jI2&sMYP$BpG<`QNSP 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%0DoO6KEv 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

+0*yn{Jj|UTPqtSxNCL1ZgU*JmYg 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
1+h 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 L=+plI4nP0dtp!CP literal 0 HcmV?d00001 diff --git a/interface/resources/qml/dialogs/TabletLoginDialog.qml b/interface/resources/qml/dialogs/TabletLoginDialog.qml index 5c8bcdd63a..0012d88f55 100644 --- a/interface/resources/qml/dialogs/TabletLoginDialog.qml +++ b/interface/resources/qml/dialogs/TabletLoginDialog.qml @@ -91,7 +91,7 @@ FocusScope { Image { id: loginDialogBackground - source: "../LoginDialog/background.jpg" + source: "../LoginDialog/background_tablet.jpg" anchors.fill: parent z: -2 } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 217ac5591a..359910e957 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -333,6 +333,10 @@ Setting::Handle maxOctreePacketsPerSecond{"maxOctreePPS", DEFAULT_MAX_OCTRE Setting::Handle loginDialogPoppedUp{"loginDialogPoppedUp", false}; static const QUrl OVERLAY_LOGIN_DIALOG_URL(PathUtils::qmlUrl("OverlayLoginDialog.qml")); +static const QString STANDARD_TO_ACTION_MAPPING_NAME = "Standard to Action"; +static const QString NO_MOVEMENT_MAPPING_NAME = "Standard to Action (No Movement)"; +static const QString NO_MOVEMENT_MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/standard_nomovement.json"; + static const QString MARKETPLACE_CDN_HOSTNAME = "mpassets.highfidelity.com"; static const int INTERVAL_TO_CHECK_HMD_WORN_STATUS = 500; // milliseconds static const QString DESKTOP_DISPLAY_PLUGIN_NAME = "Desktop"; @@ -5209,7 +5213,14 @@ void Application::pauseUntilLoginDetermined() { } getMyAvatar()->setEnableMeshVisible(false); - _controllerScriptingInterface->disableMapping("Standard to Action"); + _controllerScriptingInterface->disableMapping(STANDARD_TO_ACTION_MAPPING_NAME); + + { + auto userInputMapper = DependencyManager::get(); + if (userInputMapper->loadMapping(NO_MOVEMENT_MAPPING_JSON)) { + _controllerScriptingInterface->enableMapping(NO_MOVEMENT_MAPPING_NAME); + } + } const auto& nodeList = DependencyManager::get(); // save interstitial mode setting until resuming. @@ -5250,8 +5261,13 @@ void Application::resumeAfterLoginDialogActionTaken() { updateSystemTabletMode(); + { + auto userInputMapper = DependencyManager::get(); + userInputMapper->unloadMapping(NO_MOVEMENT_MAPPING_JSON); + _controllerScriptingInterface->disableMapping(NO_MOVEMENT_MAPPING_NAME); + } getMyAvatar()->setEnableMeshVisible(true); - _controllerScriptingInterface->enableMapping("Standard to Action"); + _controllerScriptingInterface->enableMapping(STANDARD_TO_ACTION_MAPPING_NAME); const auto& nodeList = DependencyManager::get(); nodeList->getDomainHandler().setInterstitialModeEnabled(_interstitialModeEnabled); From 2a77a29f8ab2e285764fdf1c0639b47607ad8b37 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Tue, 4 Dec 2018 17:07:03 -0800 Subject: [PATCH 090/100] Delete LoginScreenDialog.qml --- .../qml/hifi/dialogs/LoginScreenDialog.qml | 84 ------------------- 1 file changed, 84 deletions(-) delete mode 100644 interface/resources/qml/hifi/dialogs/LoginScreenDialog.qml diff --git a/interface/resources/qml/hifi/dialogs/LoginScreenDialog.qml b/interface/resources/qml/hifi/dialogs/LoginScreenDialog.qml deleted file mode 100644 index eb4558190b..0000000000 --- a/interface/resources/qml/hifi/dialogs/LoginScreenDialog.qml +++ /dev/null @@ -1,84 +0,0 @@ -// -// LoginScreenDialog.qml -// -// Created by Wayne Chen on 2018/10/9 -// 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 Hifi 1.0 -import QtQuick 2.7 -import QtQuick.Controls 1.4 -import QtQuick.Controls.Styles 1.4 as OriginalStyles -import "qrc:///controls-uit" as HifiControlsUit -import "qrc:///styles-uit" as HifiStylesUit - - -LoginDialog { - id: loginDialog - - Loader { - id: bodyLoader - Item { - - function login() { - flavorText.visible = false - mainTextContainer.visible = false - toggleLoading(true) - loginDialog.login(usernameField.text, passwordField.text) - } - - Connections { - target: loginScreenDialog - onHandleLoginCompleted: { - console.log("Login Succeeded, linking steam account") - var poppedUp = Settings.getValue("loginDialogPoppedUp", false); - if (poppedUp) { - console.log("[ENCOURAGELOGINDIALOG]: logging in") - var data = { - "action": "user logged in" - }; - UserActivityLogger.logAction("encourageLoginDialog", data); - Settings.setValue("loginDialogPoppedUp", false); - } - if (loginDialog.isSteamRunning()) { - loginDialog.linkSteam() - } else { - bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true }) - bodyLoader.item.width = root.pane.width - bodyLoader.item.height = root.pane.height - } - } - onHandleLoginFailed: { - console.log("Login Failed") - var poppedUp = Settings.getValue("loginDialogPoppedUp", false); - if (poppedUp) { - console.log("[ENCOURAGELOGINDIALOG]: failed logging in") - var data = { - "action": "user failed logging in" - }; - UserActivityLogger.logAction("encourageLoginDialog", data); - Settings.setValue("loginDialogPoppedUp", false); - } - flavorText.visible = true - mainTextContainer.visible = true - toggleLoading(false) - } - onHandleLinkCompleted: { - console.log("Link Succeeded") - - bodyLoader.setSource("WelcomeBody.qml", { "welcomeBack" : true }) - bodyLoader.item.width = root.pane.width - bodyLoader.item.height = root.pane.height - } - onHandleLinkFailed: { - console.log("Link Failed") - toggleLoading(false) - } - } - - } - } -} From 4daa9435109ae00ab39f17ed345c1a73179e8a5c Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Tue, 4 Dec 2018 17:17:58 -0800 Subject: [PATCH 091/100] fixing scripts param/reverting some qml --- interface/resources/qml/LoginDialog.qml | 5 ++--- interface/resources/qml/LoginDialog/SignUpBody.qml | 2 +- interface/resources/qml/controlsUit/Keyboard.qml | 1 - interface/src/Application.cpp | 3 +++ interface/src/Application.h | 2 ++ interface/src/main.cpp | 11 +++++++++++ 6 files changed, 19 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index b0f3b0f1f1..70815192cc 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -1,9 +1,8 @@ // // LoginDialog.qml // -// Created by Wayne Chen -// Copyright 2018 High Fidelity, Inc. -// +// Created by David Rowe on 3 Jun 2015 +// Copyright 2015 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 // diff --git a/interface/resources/qml/LoginDialog/SignUpBody.qml b/interface/resources/qml/LoginDialog/SignUpBody.qml index fc5d30224d..e4e0f5a88c 100644 --- a/interface/resources/qml/LoginDialog/SignUpBody.qml +++ b/interface/resources/qml/LoginDialog/SignUpBody.qml @@ -1,5 +1,5 @@ // -// signUpBody.qml +// SignUpBody.qml // // Created by Stephen Birarda on 7 Dec 2016 // Copyright 2016 High Fidelity, Inc. diff --git a/interface/resources/qml/controlsUit/Keyboard.qml b/interface/resources/qml/controlsUit/Keyboard.qml index c39f7a219c..a55523f34a 100644 --- a/interface/resources/qml/controlsUit/Keyboard.qml +++ b/interface/resources/qml/controlsUit/Keyboard.qml @@ -56,7 +56,6 @@ Rectangle { keyboardBase.height = raised ? raisedHeight : 0; keyboardBase.visible = raised; } else { - console.log("raising 3d keyboard to " + raised); KeyboardScriptingInterface.raised = raised; KeyboardScriptingInterface.password = raised ? password : false; } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 359910e957..790a93ad5a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1765,6 +1765,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo userInputMapper->registerDevice(_touchscreenVirtualPadDevice->getInputDevice()); } + QString scriptsSwitch = QString("--").append(SCRIPTS_SWITCH); + _defaultScriptsLocation = getCmdOption(argc, constArgv, scriptsSwitch.toStdString().c_str()); + // Make sure we don't time out during slow operations at startup updateHeartbeat(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 4b55d90222..8196915248 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -98,6 +98,7 @@ static const UINT UWM_SHOW_APPLICATION = #endif static const QString RUNNING_MARKER_FILENAME = "Interface.running"; +static const QString SCRIPTS_SWITCH = "scripts"; class Application; #if defined(qApp) @@ -664,6 +665,7 @@ private: ControllerScriptingInterface* _controllerScriptingInterface{ nullptr }; QPointer _logDialog; QPointer _entityScriptServerLogDialog; + QDir _defaultScriptsLocation; FileLogger* _logger; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 0b02649c6e..5af0a9371d 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -72,6 +72,7 @@ int main(int argc, const char* argv[]) { QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath"); QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run"); QCommandLineOption overrideAppLocalDataPathOption("cache", "set test cache

", "dir"); + QCommandLineOption overrideScriptsPathOption(SCRIPTS_SWITCH, "set scripts ", "path"); parser.addOption(urlOption); parser.addOption(noUpdaterOption); @@ -79,6 +80,7 @@ int main(int argc, const char* argv[]) { parser.addOption(runServerOption); parser.addOption(serverContentPathOption); parser.addOption(overrideAppLocalDataPathOption); + parser.addOption(overrideScriptsPathOption); parser.addOption(allowMultipleInstancesOption); if (!parser.parse(arguments)) { @@ -165,6 +167,15 @@ int main(int argc, const char* argv[]) { if (allowMultipleInstances) { instanceMightBeRunning = false; } + // this needs to be done here in main, as the mechanism for setting the + // scripts directory appears not to work. See the bug report + // https://highfidelity.fogbugz.com/f/cases/5759/Issues-changing-scripts-directory-in-ScriptsEngine + if (parser.isSet(overrideScriptsPathOption)) { + QDir scriptsPath(parser.value(overrideScriptsPathOption)); + if (scriptsPath.exists()) { + PathUtils::defaultScriptsLocation(scriptsPath.path()); + } + } if (instanceMightBeRunning) { // Try to connect and send message to existing interface instance From 07599c02c83a735d66179de37bba6d6bcbc0fc45 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Wed, 5 Dec 2018 08:16:54 -0800 Subject: [PATCH 092/100] true reversion of scrips param --- interface/src/Application.cpp | 7 ++++++- libraries/script-engine/src/ScriptEngines.cpp | 5 +---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 790a93ad5a..455a31cf40 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5279,7 +5279,12 @@ void Application::resumeAfterLoginDialogActionTaken() { // this will force the model the look at the correct directory (weird order of operations issue) scriptEngines->reloadLocalFiles(); - scriptEngines->loadScripts(); + if (!_defaultScriptsLocation.exists()) { + scriptEngines->loadDefaultScripts(); + scriptEngines->defaultScriptsLocationOverridden(true); + } else { + scriptEngines->loadScripts(); + } } if (_firstRun.get()) { diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 2b3a5e5e53..4592088aee 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -319,13 +319,10 @@ void ScriptEngines::loadScripts() { // loads all saved scripts auto runningScripts = runningScriptsHandle.get(); - if (runningScripts.empty()) { - loadDefaultScripts(); - return; - } for (auto script : runningScripts) { auto string = script.toString(); + qDebug() << string; if (!string.isEmpty()) { loadScript(string); } From a2a4d2ff894ebfae7bb777ac64efc88f3b9f93db Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Wed, 5 Dec 2018 08:21:11 -0800 Subject: [PATCH 093/100] removing trailing debug --- libraries/script-engine/src/ScriptEngines.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 4592088aee..acc49ce2a2 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -322,7 +322,6 @@ void ScriptEngines::loadScripts() { for (auto script : runningScripts) { auto string = script.toString(); - qDebug() << string; if (!string.isEmpty()) { loadScript(string); } From 3d99ffc4596e57d57aa27b1d136461dcac4ede17 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Wed, 5 Dec 2018 08:25:01 -0800 Subject: [PATCH 094/100] outing oculus login --- .../qml/LoginDialog/LinkAccountBody.qml | 18 ++++++++++-------- .../qml/LoginDialog/LoggingInBody.qml | 2 -- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 89cf8594eb..1e06ead6d2 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -376,10 +376,11 @@ Item { buttonGlyph: hifi.glyphs.steamSquare buttonGlyphRightMargin: 10 onClicked: { - if (loginDialog.isOculusStoreRunning()) { - linkAccountBody.withOculus = true; - loginDialog.loginThroughSteam(); - } else if (loginDialog.isSteamRunning()) { + // if (loginDialog.isOculusStoreRunning()) { + // linkAccountBody.withOculus = true; + // loginDialog.loginThroughSteam(); + // } else + if (loginDialog.isSteamRunning()) { linkAccountBody.withSteam = true; loginDialog.loginThroughSteam(); } @@ -392,10 +393,11 @@ Item { continueButton.visible = false; return; } - if (loginDialog.isOculusStoreRunning()) { - continueButton.text = qsTr("CONTINUE WITH OCULUS"); - continueButton.buttonGlyph = hifi.glyphs.oculus; - } else if (loginDialog.isSteamRunning()) { + // if (loginDialog.isOculusStoreRunning()) { + // continueButton.text = qsTr("CONTINUE WITH OCULUS"); + // continueButton.buttonGlyph = hifi.glyphs.oculus; + // } else + if (loginDialog.isSteamRunning()) { continueButton.text = qsTr("CONTINUE WITH STEAM"); continueButton.buttonGlyph = hifi.glyphs.steamSquare; } else { diff --git a/interface/resources/qml/LoginDialog/LoggingInBody.qml b/interface/resources/qml/LoginDialog/LoggingInBody.qml index bfb01bae05..775f51c1fa 100644 --- a/interface/resources/qml/LoginDialog/LoggingInBody.qml +++ b/interface/resources/qml/LoginDialog/LoggingInBody.qml @@ -68,8 +68,6 @@ Item { function init() { // For the process of logging in. loggingInText.wrapMode = Text.NoWrap; - print("withSteam " + loggingInBody.withSteam); - print("withOculus " + loggingInBody.withOculus); if (loggingInBody.withSteam) { loggingInGlyph.visible = true; loggingInText.text = "Logging in to Steam"; From 328e1ebc27b7ea3197252af8845c4faa7d42675b Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Wed, 5 Dec 2018 08:51:13 -0800 Subject: [PATCH 095/100] autotester param fully functional --- interface/src/Application.cpp | 23 +++++++++++++---------- interface/src/Application.h | 1 + 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 455a31cf40..14cf67e693 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1789,6 +1789,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(offscreenUi.data(), &OffscreenUi::keyboardFocusActive, [this]() { #if !defined(Q_OS_ANDROID) + // Do not show login dialog if requested not to on the command line + QString hifiNoLoginCommandLineKey = QString("--").append(HIFI_NO_LOGIN_COMMAND_LINE_KEY); + int index = arguments().indexOf(hifiNoLoginCommandLineKey); + if (index != -1) { + resumeAfterLoginDialogActionTaken(); + return; + } + // only for non-android. QML is ready to be shown at this time. showLoginScreen(); #endif @@ -2324,17 +2332,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(&AndroidHelper::instance(), &AndroidHelper::enterBackground, this, &Application::enterBackground); connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground); AndroidHelper::instance().notifyLoadComplete(); -#else -#if !defined(DISABLE_QML) - // Do not show login dialog if requested not to on the command line - const QString HIFI_NO_LOGIN_COMMAND_LINE_KEY = "--no-login-suggestion"; - int index = arguments().indexOf(HIFI_NO_LOGIN_COMMAND_LINE_KEY); - if (index == -1) { - // request not found - pauseUntilLoginDetermined(); - } -#endif #endif + pauseUntilLoginDetermined(); } void Application::updateVerboseLogging() { @@ -2890,6 +2889,7 @@ static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, in #endif void Application::showLoginScreen() { +#if !defined(DISABLE_QML) auto accountManager = DependencyManager::get(); auto dialogsManager = DependencyManager::get(); if (!accountManager->isLoggedIn()) { @@ -2908,6 +2908,9 @@ void Application::showLoginScreen() { } _loginDialogPoppedUp = !accountManager->isLoggedIn(); loginDialogPoppedUp.set(_loginDialogPoppedUp); +#else + resumeAfterLoginDialogActionTaken(); +#endif } void Application::initializeUi() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 8196915248..13a96a9d11 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -99,6 +99,7 @@ static const UINT UWM_SHOW_APPLICATION = static const QString RUNNING_MARKER_FILENAME = "Interface.running"; static const QString SCRIPTS_SWITCH = "scripts"; +static const QString HIFI_NO_LOGIN_COMMAND_LINE_KEY = "no-login-suggestion"; class Application; #if defined(qApp) From 40053ef13a766ba0fae1386b68ee8ff72975666c Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Wed, 5 Dec 2018 09:10:17 -0800 Subject: [PATCH 096/100] make sure android still functions as expected --- interface/src/Application.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 14cf67e693..d82e394896 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1799,6 +1799,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // only for non-android. QML is ready to be shown at this time. showLoginScreen(); +#else + resumeAfterLoginDialogActionTaken(); #endif }); From 37beab3ab3328a1a0ef871799b05fd1a7e4b40b7 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Wed, 5 Dec 2018 09:36:56 -0800 Subject: [PATCH 097/100] fixing the desktop tablet problem again --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d82e394896..c4d9da1512 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5259,7 +5259,7 @@ void Application::resumeAfterLoginDialogActionTaken() { return; } - if (!isHMDMode()) { + if (!isHMDMode() && getDesktopTabletBecomesToolbarSetting()) { auto toolbar = DependencyManager::get()->getToolbar("com.highfidelity.interface.toolbar.system"); toolbar->writeProperty("visible", true); } else { From eb51a5b7b60390d192be6e7ce1d440b9938a90a8 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Wed, 5 Dec 2018 10:16:48 -0800 Subject: [PATCH 098/100] changing opacity to 0.5 --- interface/resources/qml/LoginDialog.qml | 30 ++++++++++++++++++- .../qml/LoginDialog/CantAccessBody.qml | 23 -------------- .../qml/LoginDialog/CompleteProfileBody.qml | 27 ++--------------- .../qml/LoginDialog/LinkAccountBody.qml | 29 ++---------------- .../qml/LoginDialog/LoggingInBody.qml | 4 +-- .../resources/qml/LoginDialog/SignUpBody.qml | 10 +++---- .../qml/LoginDialog/UsernameCollisionBody.qml | 30 ++----------------- .../resources/qml/OverlayLoginDialog.qml | 30 ++++++++++++++++++- .../qml/dialogs/TabletLoginDialog.qml | 30 ++++++++++++++++++- 9 files changed, 102 insertions(+), 111 deletions(-) diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml index 70815192cc..33e43fdf78 100644 --- a/interface/resources/qml/LoginDialog.qml +++ b/interface/resources/qml/LoginDialog.qml @@ -36,6 +36,8 @@ FocusScope { property string title: "" property string text: "" property int titleWidth: 0 + property alias bannerWidth: banner.width + property alias bannerHeight: banner.height function tryDestroy() { root.destroy() @@ -50,10 +52,36 @@ FocusScope { } Image { + z: -10 id: loginDialogBackground source: "LoginDialog/background.jpg" anchors.fill: parent - z: -2 + } + + Rectangle { + z: -6 + id: opaqueRect + height: parent.height + width: parent.width + opacity: 0.5 + color: "black" + } + + Item { + z: -5 + id: bannerContainer + width: parent.width + height: banner.height + anchors { + top: parent.top + topMargin: 0.18 * parent.height + } + Image { + id: banner + anchors.centerIn: parent + source: "../images/high-fidelity-banner.svg" + horizontalAlignment: Image.AlignHCenter + } } Keys.onPressed: { diff --git a/interface/resources/qml/LoginDialog/CantAccessBody.qml b/interface/resources/qml/LoginDialog/CantAccessBody.qml index 5d91d9c9ee..7a46f197b6 100644 --- a/interface/resources/qml/LoginDialog/CantAccessBody.qml +++ b/interface/resources/qml/LoginDialog/CantAccessBody.qml @@ -56,29 +56,6 @@ Item { anchors.fill: parent onHeightChanged: d.resize(); onWidthChanged: d.resize(); - Rectangle { - id: opaqueRect - height: parent.height - width: parent.width - opacity: 0.9 - color: "black" - } - Item { - id: bannerContainer - width: parent.width - height: banner.height - anchors { - bottom: textContainer.top - bottomMargin: 0.125 * parent.height - } - Image { - id: banner - anchors.centerIn: parent - source: "../../images/high-fidelity-banner.svg" - horizontalAlignment: Image.AlignHCenter - } - } - Item { id: textContainer width: parent.width diff --git a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml index 8f7401b975..ab81515226 100644 --- a/interface/resources/qml/LoginDialog/CompleteProfileBody.qml +++ b/interface/resources/qml/LoginDialog/CompleteProfileBody.qml @@ -57,29 +57,6 @@ Item { height: root.height onHeightChanged: d.resize(); onWidthChanged: d.resize(); - Rectangle { - id: opaqueRect - height: parent.height - width: parent.width - opacity: 0.9 - color: "black" - } - - Item { - id: bannerContainer - width: parent.width - height: banner.height - anchors { - top: parent.top - topMargin: 0.18 * parent.height - } - Image { - id: banner - anchors.centerIn: parent - source: "../../images/high-fidelity-banner.svg" - horizontalAlignment: Image.AlignHCenter - } - } Item { id: contentItem anchors.fill: parent @@ -105,13 +82,13 @@ Item { Item { id: buttons - width: banner.width + width: root.bannerWidth height: d.minHeightButton anchors { top: parent.top topMargin: (parent.height - additionalTextContainer.height) / 2 - hifi.dimensions.contentSpacing.y left: parent.left - leftMargin: (parent.width - banner.width) / 2 + leftMargin: (parent.width - root.bannerWidth) / 2 } HifiControlsUit.Button { id: cancelButton diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 1e06ead6d2..fe6853b1c4 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -96,36 +96,13 @@ Item { height: root.height onHeightChanged: d.resize(); onWidthChanged: d.resize(); - Rectangle { - id: opaqueRect - height: parent.height - width: parent.width - opacity: 0.9 - color: "black" - } - - Item { - id: bannerContainer - width: parent.width - height: banner.height - anchors { - bottom: loginContainer.top - bottomMargin: 0.07 * parent.height - } - Image { - id: banner - anchors.centerIn: parent - source: "../../images/high-fidelity-banner.svg" - horizontalAlignment: Image.AlignHCenter - } - } Item { id: loginContainer width: emailField.width height: 0.45 * parent.height anchors { top: parent.top - topMargin: bannerContainer.height + 0.25 * parent.height + topMargin: root.bannerHeight + 0.25 * parent.height left: parent.left leftMargin: (parent.width - emailField.width) / 2 } @@ -157,7 +134,7 @@ Item { HifiControlsUit.TextField { id: emailField - width: banner.width + width: root.bannerWidth height: linkAccountBody.textFieldHeight font.pixelSize: linkAccountBody.textFieldFontSize styleRenderType: Text.QtRendering @@ -194,7 +171,7 @@ Item { } HifiControlsUit.TextField { id: passwordField - width: banner.width + width: root.bannerWidth height: linkAccountBody.textFieldHeight font.pixelSize: linkAccountBody.textFieldFontSize styleRenderType: Text.QtRendering diff --git a/interface/resources/qml/LoginDialog/LoggingInBody.qml b/interface/resources/qml/LoginDialog/LoggingInBody.qml index 775f51c1fa..eca58c6441 100644 --- a/interface/resources/qml/LoginDialog/LoggingInBody.qml +++ b/interface/resources/qml/LoginDialog/LoggingInBody.qml @@ -102,7 +102,7 @@ Item { } else if (loggingInBody.withOculus) { // reset the flag. loggingInGlyph.visible = false; - loggingInText.text = "You are now logged into Oculus!" + loggingInText.text = "You are now logged into Oculus!" loggingInText.anchors.centerIn = loggingInHeader; loggingInText.anchors.bottom = loggingInHeader.bottom; loggedInGlyph.text = hifi.glyphs.oculus; @@ -123,7 +123,7 @@ Item { id: opaqueRect height: parent.height width: parent.width - opacity: 0.9 + opacity: 0.7 color: "black" } diff --git a/interface/resources/qml/LoginDialog/SignUpBody.qml b/interface/resources/qml/LoginDialog/SignUpBody.qml index e4e0f5a88c..9ac4075e23 100644 --- a/interface/resources/qml/LoginDialog/SignUpBody.qml +++ b/interface/resources/qml/LoginDialog/SignUpBody.qml @@ -122,10 +122,10 @@ Item { Item { id: loginContainer width: usernameField.width - height: parent.height - bannerContainer.height + height: parent.height anchors { top: parent.top - topMargin: bannerContainer.height + 0.25 * parent.height + topMargin: root.bannerHeight + 0.25 * parent.height left: parent.left leftMargin: (parent.width - usernameField.width) / 2 } @@ -159,7 +159,7 @@ Item { HifiControlsUit.TextField { id: usernameField - width: banner.width + width: root.bannerWidth height: signUpBody.textFieldHeight placeholderText: "Username" font.pixelSize: signUpBody.textFieldFontSize @@ -204,7 +204,7 @@ Item { HifiControlsUit.TextField { id: emailField - width: banner.width + width: root.bannerWidth height: signUpBody.textFieldHeight anchors { top: parent.top @@ -246,7 +246,7 @@ Item { } HifiControlsUit.TextField { id: passwordField - width: banner.width + width: root.bannerWidth height: signUpBody.textFieldHeight placeholderText: "Password" font.pixelSize: signUpBody.textFieldFontSize diff --git a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml index a2670cbf62..24c1afc6af 100644 --- a/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml +++ b/interface/resources/qml/LoginDialog/UsernameCollisionBody.qml @@ -66,30 +66,6 @@ Item { onHeightChanged: d.resize(); onWidthChanged: d.resize(); anchors.fill: parent - Rectangle { - id: opaqueRect - height: parent.height - width: parent.width - opacity: 0.9 - color: "black" - } - - Item { - id: bannerContainer - width: parent.width - height: banner.height - anchors { - top: parent.top - topMargin: 0.18 * parent.height - } - Image { - id: banner - anchors.centerIn: parent - source: "../../images/high-fidelity-banner.svg" - horizontalAlignment: Image.AlignHCenter - } - } - TextMetrics { id: mainTextContainerTextMetrics font: mainTextContainer.font @@ -129,7 +105,7 @@ Item { font.pixelSize: usernameCollisionBody.fontSize styleRenderType: Text.QtRendering font.bold: usernameCollisionBody.fontBold - width: banner.width + width: root.bannerWidth placeholderText: "Choose your own" @@ -167,13 +143,13 @@ Item { Item { id: buttons - width: banner.width + width: root.bannerWidth height: d.minHeightButton anchors { top: textField.bottom topMargin: hifi.dimensions.contentSpacing.y left: parent.left - leftMargin: (parent.width - banner.width) / 2 + leftMargin: (parent.width - root.bannerWidth) / 2 } HifiControlsUit.Button { diff --git a/interface/resources/qml/OverlayLoginDialog.qml b/interface/resources/qml/OverlayLoginDialog.qml index b9ae869b1e..76f0cfa8de 100644 --- a/interface/resources/qml/OverlayLoginDialog.qml +++ b/interface/resources/qml/OverlayLoginDialog.qml @@ -36,6 +36,8 @@ FocusScope { property string title: "" property int titleWidth: 0 property alias text: loginKeyboard.mirroredText + property alias bannerWidth: banner.width + property alias bannerHeight: banner.height function tryDestroy() { root.destroy() @@ -51,10 +53,36 @@ FocusScope { } Image { + z: -10 id: loginDialogBackground source: "LoginDialog/background.jpg" anchors.fill: parent - z: -2 + } + + Rectangle { + z: -6 + id: opaqueRect + height: parent.height + width: parent.width + opacity: 0.5 + color: "black" + } + + Item { + z: -5 + id: bannerContainer + width: parent.width + height: banner.height + anchors { + top: parent.top + topMargin: 0.18 * parent.height + } + Image { + id: banner + anchors.centerIn: parent + source: "../images/high-fidelity-banner.svg" + horizontalAlignment: Image.AlignHCenter + } } Timer { diff --git a/interface/resources/qml/dialogs/TabletLoginDialog.qml b/interface/resources/qml/dialogs/TabletLoginDialog.qml index 0012d88f55..c1d7a07ba1 100644 --- a/interface/resources/qml/dialogs/TabletLoginDialog.qml +++ b/interface/resources/qml/dialogs/TabletLoginDialog.qml @@ -39,6 +39,8 @@ FocusScope { property alias text: loginKeyboard.mirroredText property int titleWidth: 0 + property alias bannerWidth: banner.width + property alias bannerHeight: banner.height property string iconText: hifi.glyphs.avatar property int iconSize: 35 @@ -90,10 +92,36 @@ FocusScope { } Image { + z: -10 id: loginDialogBackground source: "../LoginDialog/background_tablet.jpg" anchors.fill: parent - z: -2 + } + + Item { + z: -5 + id: bannerContainer + width: parent.width + height: banner.height + anchors { + top: parent.top + topMargin: 0.18 * parent.height + } + Image { + id: banner + anchors.centerIn: parent + source: "../../images/high-fidelity-banner.svg" + horizontalAlignment: Image.AlignHCenter + } + } + + Rectangle { + z: -6 + id: opaqueRect + height: parent.height + width: parent.width + opacity: 0.5 + color: "black" } HifiControlsUit.Keyboard { From 27e4e1c245458a86d97d119228933a650d7818fc Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Wed, 5 Dec 2018 11:24:06 -0800 Subject: [PATCH 099/100] pitch updates login pos/fix signup errors --- .../qml/LoginDialog/LinkAccountBody.qml | 2 +- .../qml/LoginDialog/LoggingInBody.qml | 2 +- .../resources/qml/LoginDialog/SignUpBody.qml | 28 +++++++++---------- interface/src/Application.cpp | 13 ++++++--- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index fe6853b1c4..07b0e910f5 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -140,7 +140,7 @@ Item { styleRenderType: Text.QtRendering anchors { top: parent.top - topMargin: loginErrorMessage.height + topMargin: errorContainer.height } placeholderText: "Username or Email" activeFocusOnPress: true diff --git a/interface/resources/qml/LoginDialog/LoggingInBody.qml b/interface/resources/qml/LoginDialog/LoggingInBody.qml index eca58c6441..32b9ec431c 100644 --- a/interface/resources/qml/LoginDialog/LoggingInBody.qml +++ b/interface/resources/qml/LoginDialog/LoggingInBody.qml @@ -102,7 +102,7 @@ Item { } else if (loggingInBody.withOculus) { // reset the flag. loggingInGlyph.visible = false; - loggingInText.text = "You are now logged into Oculus!" + loggingInText.text = "You are now logged into Oculus!" loggingInText.anchors.centerIn = loggingInHeader; loggingInText.anchors.bottom = loggingInHeader.bottom; loggedInGlyph.text = hifi.glyphs.oculus; diff --git a/interface/resources/qml/LoginDialog/SignUpBody.qml b/interface/resources/qml/LoginDialog/SignUpBody.qml index 9ac4075e23..df50bb97f1 100644 --- a/interface/resources/qml/LoginDialog/SignUpBody.qml +++ b/interface/resources/qml/LoginDialog/SignUpBody.qml @@ -64,22 +64,14 @@ Item { } } - function login() { + function signup() { loginDialog.signup(emailField.text, usernameField.text, passwordField.text); return; - bodyLoader.setSource("LoggingInBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "withOculus": false, "linkSteam": false }); } function init() { // going to/from sign in/up dialog. loginDialog.isLogIn = false; - loginErrorMessage.visible = (signUpBody.errorString !== ""); - if (signUpBody.errorString !== "") { - loginErrorMessage.text = signUpBody.errorString; - errorContainer.anchors.bottom = usernameField.top; - errorContainer.anchors.bottomMargin = hifi.dimensions.contentSpacing.y; - errorContainer.anchors.left = usernameField.left; - } emailField.placeholderText = "Email"; emailField.text = ""; emailField.anchors.top = usernameField.bottom; @@ -133,7 +125,7 @@ Item { Item { id: errorContainer - width: loginErrorMessageTextMetrics.width + width: parent.width height: loginErrorMessageTextMetrics.height anchors { bottom: usernameField.top; @@ -147,6 +139,7 @@ Item { } Text { id: loginErrorMessage; + width: root.bannerWidth color: "red"; font.family: signUpBody.fontFamily font.pixelSize: 18 @@ -192,7 +185,7 @@ Item { if (keepMeLoggedInCheckbox.checked) { Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text); } - signUpBody.login(); + signUpBody.signup(); break; } } @@ -235,7 +228,7 @@ Item { if (keepMeLoggedInCheckbox.checked) { Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text); } - signUpBody.login(); + signUpBody.signup(); break; } } @@ -319,7 +312,7 @@ Item { if (keepMeLoggedInCheckbox.checked) { Settings.setValue("keepMeLoggedIn/savedUsername", usernameField.text); } - signUpBody.login(); + signUpBody.signup(); break; } } @@ -387,7 +380,7 @@ Item { } onClicked: { - signUpBody.login() + signUpBody.signup(); } } } @@ -442,6 +435,13 @@ Item { loginErrorMessage.visible = (errorStringEdited !== ""); if (errorStringEdited !== "") { loginErrorMessage.text = errorStringEdited; + loginErrorMessageTextMetrics.text = errorStringEdited; + if (loginErrorMessageTextMetrics.width > 350 && root.isTablet) { + loginErrorMessage.wrapMode = Text.WordWrap; + loginErrorMessage.verticalAlignment = Text.AlignLeft; + loginErrorMessage.horizontalAlignment = Text.AlignLeft; + errorContainer.height = 2 * loginErrorMessageTextMetrics.height; + } errorContainer.anchors.bottom = usernameField.top; errorContainer.anchors.left = usernameField.left; } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c4d9da1512..bdffcec2a8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -8656,11 +8656,13 @@ void Application::createLoginDialogOverlay() { } void Application::updateLoginDialogOverlayPosition() { - auto overlayPosition = getOverlays().getProperty(_loginDialogOverlayID, "position"); + const float LOOK_AWAY_THRESHOLD_ANGLE = 40.0f; + auto& overlays = getOverlays(); + auto overlayPosition = overlays.getProperty(_loginDialogOverlayID, "position"); auto overlayPositionVec = vec3FromVariant(overlayPosition.value); auto cameraPositionVec = _myCamera.getPosition(); auto cameraOrientation = _myCamera.getOrientation(); - cameraOrientation = cancelOutRollAndPitch(cameraOrientation); + cameraOrientation = cancelOutRoll(cameraOrientation); auto headLookVec = (cameraOrientation * Vectors::FRONT); auto overlayToHeadVec = overlayPositionVec - cameraPositionVec; auto pointAngle = (glm::acos(glm::dot(glm::normalize(overlayToHeadVec), glm::normalize(headLookVec))) * 180.0f / PI); @@ -8669,12 +8671,15 @@ void Application::updateLoginDialogOverlayPosition() { auto newOverlayPositionVec = (cameraPositionVec + offset) + (upVec * -0.1f); auto newOverlayOrientation = glm::inverse(glm::quat_cast(glm::lookAt(newOverlayPositionVec, cameraPositionVec, upVec))) * Quaternions::Y_180; - if (pointAngle > 40.0f) { + //auto isOverlayTooFar = (glm::distance(overlayPositionVec, getMyAvatar()->getWorldPosition()) > 1.0f); + + //if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE || isOverlayTooFar) { + if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE) { QVariantMap properties { {"position", vec3toVariant(newOverlayPositionVec)}, {"orientation", quatToVariant(newOverlayOrientation)} }; - getOverlays().editOverlay(_loginDialogOverlayID, properties); + overlays.editOverlay(_loginDialogOverlayID, properties); } } From 11c40666e41bec35c8ec615f2a7fa0b27b1f4d86 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Wed, 5 Dec 2018 11:29:58 -0800 Subject: [PATCH 100/100] removing trailing tests --- interface/src/Application.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bdffcec2a8..bdec22c0f3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -8671,9 +8671,6 @@ void Application::updateLoginDialogOverlayPosition() { auto newOverlayPositionVec = (cameraPositionVec + offset) + (upVec * -0.1f); auto newOverlayOrientation = glm::inverse(glm::quat_cast(glm::lookAt(newOverlayPositionVec, cameraPositionVec, upVec))) * Quaternions::Y_180; - //auto isOverlayTooFar = (glm::distance(overlayPositionVec, getMyAvatar()->getWorldPosition()) > 1.0f); - - //if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE || isOverlayTooFar) { if (pointAngle > LOOK_AWAY_THRESHOLD_ANGLE) { QVariantMap properties { {"position", vec3toVariant(newOverlayPositionVec)},