From a934b79321ba2bd5fc18938abbcce49cf4074f39 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 16 Aug 2019 17:34:16 -0700 Subject: [PATCH 01/46] Updating the bloom debug ui --- scripts/developer/utilities/render/bloom.qml | 83 ------------------- .../developer/utilities/render/debugBloom.js | 13 ++- scripts/developer/utilities/render/luci.qml | 6 ++ .../developer/utilities/render/luci/Bloom.qml | 42 ++++++++++ .../developer/utilities/render/luci/qmldir | 1 + 5 files changed, 54 insertions(+), 91 deletions(-) delete mode 100644 scripts/developer/utilities/render/bloom.qml create mode 100644 scripts/developer/utilities/render/luci/Bloom.qml diff --git a/scripts/developer/utilities/render/bloom.qml b/scripts/developer/utilities/render/bloom.qml deleted file mode 100644 index 705a9826d6..0000000000 --- a/scripts/developer/utilities/render/bloom.qml +++ /dev/null @@ -1,83 +0,0 @@ -// -// bloom.qml -// developer/utilities/render -// -// Olivier Prat, created on 09/25/2017. -// Copyright 2017 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.5 -import QtQuick.Controls 1.4 -import "configSlider" - -Item { - id: root - property var configDebug: Render.getConfig("RenderMainView.DebugBloom") - - Column { - spacing: 8 - - GroupBox { - title: "Debug" - Row { - ExclusiveGroup { id: debugGroup } - RadioButton { - text : "Off" - checked : !root.configDebug["enabled"] - onCheckedChanged: { - if (checked) { - root.configDebug["enabled"] = false - } - } - exclusiveGroup : debugGroup - } - RadioButton { - text : "Lvl 0" - checked :root.configDebug["enabled"] && root.configDebug["mode"]==0 - onCheckedChanged: { - if (checked) { - root.configDebug["enabled"] = true - root.configDebug["mode"] = 0 - } - } - exclusiveGroup : debugGroup - } - RadioButton { - text : "Lvl 1" - checked : root.configDebug["enabled"] && root.configDebug["mode"]==1 - onCheckedChanged: { - if (checked) { - root.configDebug["enabled"] = true - root.configDebug["mode"] = 1 - } - } - exclusiveGroup : debugGroup - } - RadioButton { - text : "Lvl 2" - checked : root.configDebug["enabled"] && root.configDebug["mode"]==2 - onCheckedChanged: { - if (checked) { - root.configDebug["enabled"] = true - root.configDebug["mode"] = 2 - } - } - exclusiveGroup : debugGroup - } - RadioButton { - text : "All" - checked : root.configDebug["enabled"] && root.configDebug["mode"]==3 - onCheckedChanged: { - if (checked) { - root.configDebug["enabled"] = true - root.configDebug["mode"] = 3 - } - } - exclusiveGroup : debugGroup - } - } - } - } -} diff --git a/scripts/developer/utilities/render/debugBloom.js b/scripts/developer/utilities/render/debugBloom.js index 39629ab0ce..3c5e722a18 100644 --- a/scripts/developer/utilities/render/debugBloom.js +++ b/scripts/developer/utilities/render/debugBloom.js @@ -10,11 +10,8 @@ // // Set up the qml ui -var qml = Script.resolvePath('bloom.qml'); -var window = new OverlayWindow({ - title: 'Bloom', - source: qml, - width: 285, - height: 40, -}); -window.closed.connect(function() { Script.stop(); }); \ No newline at end of file +var window = Desktop.createWindow(Script.resolvePath('./luci/Bloom.qml'), { + title: "Bloom", + presentationMode: Desktop.PresentationMode.NATIVE, + size: {x: 285, y: 40} +}); \ No newline at end of file diff --git a/scripts/developer/utilities/render/luci.qml b/scripts/developer/utilities/render/luci.qml index d768acb160..71962992b8 100644 --- a/scripts/developer/utilities/render/luci.qml +++ b/scripts/developer/utilities/render/luci.qml @@ -72,6 +72,12 @@ Rectangle { Antialiasing {} } } + Prop.PropFolderPanel { + label: "Bloom" + panelFrameData: Component { + Bloom {} + } + } Prop.PropFolderPanel { label: "Culling" panelFrameData: Component { diff --git a/scripts/developer/utilities/render/luci/Bloom.qml b/scripts/developer/utilities/render/luci/Bloom.qml new file mode 100644 index 0000000000..28d6fe7697 --- /dev/null +++ b/scripts/developer/utilities/render/luci/Bloom.qml @@ -0,0 +1,42 @@ +// +// bloom.qml +// +// Olivier Prat, created on 09/25/2017. +// Copyright 2017 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 "../../lib/prop" as Prop + +Column { + anchors.left: parent.left + anchors.right: parent.right + + id: bloom + + property var config: Render.getConfig("RenderMainView.DebugBloom") + + function setDebugMode(mode) { + bloom.config.enabled = (mode != 0); + bloom.config.mode = mode; + } + + Prop.PropEnum { + label: "Debug Bloom Buffer" + object: config + property: "mode" + // valueVar: 0 + enums: [ + "Off", + "Lvl 0", + "Lvl 1", + "Lvl 2", + "All", + ] + + valueVarSetter: function (mode) { bloom.setDebugMode(mode) } + } +} + diff --git a/scripts/developer/utilities/render/luci/qmldir b/scripts/developer/utilities/render/luci/qmldir index 3ebd9fcd8d..a4059ffcab 100644 --- a/scripts/developer/utilities/render/luci/qmldir +++ b/scripts/developer/utilities/render/luci/qmldir @@ -5,6 +5,7 @@ BoundingBoxes 1.0 BoundingBoxes.qml Framebuffer 1.0 Framebuffer.qml Antialiasing 1.0 Antialiasing.qml Culling 1.0 Culling.qml +Bloom 1.0 Bloom.qml Platform 1.0 Platform.qml RenderSettings 1.0 RenderSettings.qml From aeb407698d64718f83b4b9c65241d20888c97d61 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 18 Aug 2019 22:15:20 -0700 Subject: [PATCH 02/46] bloom ui --- libraries/render-utils/src/BloomEffect.cpp | 11 ++++++++++- libraries/render-utils/src/BloomEffect.h | 10 +++++++--- scripts/developer/utilities/render/luci/Bloom.qml | 6 +++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index e58d07ac33..f83c05cff8 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -187,12 +187,17 @@ void BloomDraw::run(const render::RenderContextPointer& renderContext, const Inp } } +void DebugBloomConfig::setMode(int mode) { + _mode = std::min((int)DebugBloomConfig::MODE_COUNT, std::max(0, mode)); + emit dirty(); +} + DebugBloom::DebugBloom() { _params = std::make_shared(sizeof(glm::vec4), nullptr); } void DebugBloom::configure(const Config& config) { - _mode = static_cast(config.mode); + _mode = (DebugBloomConfig::Mode) config.getMode(); assert(_mode < DebugBloomConfig::MODE_COUNT); } @@ -201,6 +206,10 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; + if (_mode == DebugBloomConfig::OFF) { + return; + } + const auto frameBuffer = inputs.get0(); const auto combinedBlurBuffer = inputs.get4(); const auto framebufferSize = frameBuffer->getSize(); diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h index 07ae2887c9..9c170e771a 100644 --- a/libraries/render-utils/src/BloomEffect.h +++ b/libraries/render-utils/src/BloomEffect.h @@ -87,12 +87,13 @@ private: class DebugBloomConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(int mode MEMBER mode NOTIFY dirty) + Q_PROPERTY(int mode READ getMode WRITE setMode NOTIFY dirty) public: enum Mode { - MODE_LEVEL0 = 0, + OFF = 0, + MODE_LEVEL0, MODE_LEVEL1, MODE_LEVEL2, MODE_ALL_LEVELS, @@ -102,7 +103,10 @@ public: DebugBloomConfig() : render::Job::Config(false) {} - int mode{ MODE_ALL_LEVELS }; + void setMode(int mode); + int getMode() const { return _mode; } + + int _mode{ MODE_ALL_LEVELS }; signals: void dirty(); diff --git a/scripts/developer/utilities/render/luci/Bloom.qml b/scripts/developer/utilities/render/luci/Bloom.qml index 28d6fe7697..67c931f66c 100644 --- a/scripts/developer/utilities/render/luci/Bloom.qml +++ b/scripts/developer/utilities/render/luci/Bloom.qml @@ -19,15 +19,15 @@ Column { property var config: Render.getConfig("RenderMainView.DebugBloom") function setDebugMode(mode) { + console.log("Bloom mode is " + mode) bloom.config.enabled = (mode != 0); bloom.config.mode = mode; } Prop.PropEnum { label: "Debug Bloom Buffer" - object: config - property: "mode" - // valueVar: 0 + // object: config + // property: "mode" enums: [ "Off", "Lvl 0", From c5bd9ecf4fd7ad8cc40de3d0a25f316f5a9beee5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 19 Aug 2019 18:14:29 -0700 Subject: [PATCH 03/46] REfreshing the antialiasing qml na dconfig of the Jitter Job --- .../render-utils/src/AntialiasingEffect.cpp | 36 +-- .../render-utils/src/AntialiasingEffect.h | 4 +- .../render-utils/src/RenderDeferredTask.cpp | 9 +- .../utilities/render/luci/Antialiasing.qml | 207 ++++++++---------- .../developer/utilities/render/luci/Bloom.qml | 6 + .../utilities/render/luci/ShadingModel.qml | 3 +- 6 files changed, 128 insertions(+), 137 deletions(-) diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index 180e914d60..0e70cb7f3c 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -298,29 +298,33 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const }); } - void JitterSampleConfig::setIndex(int current) { _index = (current) % JitterSample::SEQUENCE_LENGTH; emit dirty(); } -int JitterSampleConfig::cycleStopPauseRun() { - _state = (_state + 1) % 3; +void JitterSampleConfig::setState(int state) { + _state = (state) % 3; switch (_state) { - case 0: { - return none(); - break; - } - case 1: { - return pause(); - break; - } - case 2: - default: { - return play(); - break; - } + case 0: { + none(); + break; } + case 1: { + pause(); + break; + } + case 2: + default: { + play(); + break; + } + } + emit dirty(); +} + +int JitterSampleConfig::cycleStopPauseRun() { + setState((_state + 1) % 3); return _state; } diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index 7d8bbb44d9..415571d348 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -25,6 +25,7 @@ class JitterSampleConfig : public render::Job::Config { Q_PROPERTY(bool freeze MEMBER freeze NOTIFY dirty) Q_PROPERTY(bool stop MEMBER stop NOTIFY dirty) Q_PROPERTY(int index READ getIndex NOTIFY dirty) + Q_PROPERTY(int state READ getState WRITE setState NOTIFY dirty) public: JitterSampleConfig() : render::Job::Config(true) {} @@ -33,6 +34,7 @@ public: bool freeze{ false }; void setIndex(int current); + void setState(int state); public slots: int cycleStopPauseRun(); @@ -58,7 +60,7 @@ class JitterSample { public: enum { - SEQUENCE_LENGTH = 64 + SEQUENCE_LENGTH = 32 }; using Config = JitterSampleConfig; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 4561cf903d..cfcc6777d6 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -150,8 +150,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Prepare deferred, generate the shared Deferred Frame Transform. Only valid with the scaled frame buffer const auto deferredFrameTransform = task.addJob("DeferredFrameTransform", jitter); - const auto opaqueRangeTimer = task.addJob("BeginOpaqueRangeTimer", "DrawOpaques"); - const auto prepareDeferredInputs = PrepareDeferred::Inputs(scaledPrimaryFramebuffer, lightingModel).asVarying(); const auto prepareDeferredOutputs = task.addJob("PrepareDeferred", prepareDeferredInputs); const auto deferredFramebuffer = prepareDeferredOutputs.getN(0); @@ -164,8 +162,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto opaqueInputs = DrawStateSortDeferred::Inputs(opaques, lightingModel, jitter).asVarying(); task.addJob("DrawOpaqueDeferred", opaqueInputs, shapePlumber); - task.addJob("OpaqueRangeTimer", opaqueRangeTimer); - // Opaque all rendered // Linear Depth Pass @@ -216,13 +212,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto transparentsInputs = RenderTransparentDeferred::Inputs(transparents, hazeFrame, lightFrame, lightingModel, lightClusters, shadowFrame, jitter).asVarying(); task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); - const auto outlineRangeTimer = task.addJob("BeginHighlightRangeTimer", "Highlight"); - + // Highlight const auto outlineInputs = DrawHighlightTask::Inputs(items, deferredFramebuffer, lightingFramebuffer, deferredFrameTransform, jitter).asVarying(); task.addJob("DrawHighlight", outlineInputs); - task.addJob("HighlightRangeTimer", outlineRangeTimer); - // Layered Over (in front) const auto inFrontOpaquesInputs = DrawLayered3D::Inputs(inFrontOpaque, lightingModel, hazeFrame, jitter).asVarying(); const auto inFrontTransparentsInputs = DrawLayered3D::Inputs(inFrontTransparent, lightingModel, hazeFrame, jitter).asVarying(); diff --git a/scripts/developer/utilities/render/luci/Antialiasing.qml b/scripts/developer/utilities/render/luci/Antialiasing.qml index 6d1209157f..46d8a8fcdb 100644 --- a/scripts/developer/utilities/render/luci/Antialiasing.qml +++ b/scripts/developer/utilities/render/luci/Antialiasing.qml @@ -22,15 +22,12 @@ import "../../lib/prop" as Prop Column{ - HifiConstants { id: hifi; } + id: antialiasing - id: antialiasing - padding: 10 anchors.left: parent.left anchors.right: parent.right - spacing: 10 - Prop.PropScalar { + Prop.PropScalar { label: "MSAA" object: Render.getConfig("RenderMainView.PreparePrimaryBufferForward") property: "numSamples" @@ -38,49 +35,58 @@ Column{ max: 32 integral: true } - Row { - spacing: 10 - id: fxaaOnOff - property bool debugFXAA: false - HifiControls.Button { - function getTheText() { - if (Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff) { - return "FXAA" - } else { - return "TAA" - } - } - text: getTheText() - onClicked: { - var onOff = !Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff; - if (onOff) { - Render.getConfig("RenderMainView.JitterCam").none(); - Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff = true; - } else { - Render.getConfig("RenderMainView.JitterCam").play(); - Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff = false; - } - + + Prop.PropEnum { + label: "Deferred AA Method" + enums: [ + "Off", + "TAA", + "FXAA", + ] + + valueVarSetter: function (mode) { setAAMode(mode) } + valueVarGetter: function () { return Render.getConfig("RenderMainView.JitterCam").state + + Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff * 2 } + + function setAAMode(mode) { + console.log("Deferred AA mode is " + mode) + + if (mode == 0) { + Render.getConfig("RenderMainView.JitterCam").state = 0; + Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff = false; + } else if (mode == 1) { + Render.getConfig("RenderMainView.JitterCam").state = 1; + Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff = false; + } else { + Render.getConfig("RenderMainView.JitterCam").state = 0; + Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff = true; } } } Separator {} + Prop.PropEnum { + label: "Jitter" + object: Render.getConfig("RenderMainView.JitterCam") + property: "state" + + enums: [ + "Off", + "On", + "Paused", + ] + } + Prop.PropScalar { + label: "Sample Index" + object: Render.getConfig("RenderMainView.JitterCam") + property: "index" + // min: -1 + // max: 32 + readOnly: true + integral: true + } Row { spacing: 10 - - HifiControls.Button { - text: { - var state = 2 - (Render.getConfig("RenderMainView.JitterCam").freeze * 1 - Render.getConfig("RenderMainView.JitterCam").stop * 2); - if (state === 2) { - return "Jitter" - } else if (state === 1) { - return "Paused at " + Render.getConfig("RenderMainView.JitterCam").index + "" - } else { - return "No Jitter" - } - } - onClicked: { Render.getConfig("RenderMainView.JitterCam").cycleStopPauseRun(); } - } + HifiControls.Button { text: "<" onClicked: { Render.getConfig("RenderMainView.JitterCam").prev(); } @@ -90,96 +96,75 @@ Column{ onClicked: { Render.getConfig("RenderMainView.JitterCam").next(); } } } - Separator {} - HifiControls.CheckBox { - boxSize: 20 - text: "Constrain color" - checked: Render.getConfig("RenderMainView.Antialiasing")["constrainColor"] - onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["constrainColor"] = checked } - } - ConfigSlider { - label: qsTr("Covariance gamma") - integral: false - config: Render.getConfig("RenderMainView.Antialiasing") + Separator {} + Prop.PropBool { + label: "Constrain color" + object: Render.getConfig("RenderMainView.Antialiasing") + property: "constrainColor" + } + Prop.PropScalar { + label: "Covariance gamma" + object: Render.getConfig("RenderMainView.Antialiasing") property: "covarianceGamma" max: 1.5 min: 0.5 - height: 38 - } - Separator {} - HifiControls.CheckBox { - boxSize: 20 - text: "Feedback history color" - checked: Render.getConfig("RenderMainView.Antialiasing")["feedbackColor"] - onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["feedbackColor"] = checked } - } - - ConfigSlider { - label: qsTr("Source blend") - integral: false - config: Render.getConfig("RenderMainView.Antialiasing") + } + Separator {} + Prop.PropBool { + label: "Feedback history color" + object: Render.getConfig("RenderMainView.Antialiasing") + property: "feedbackColor" + } + Prop.PropScalar { + label: "Source blend" + object: Render.getConfig("RenderMainView.Antialiasing") property: "blend" max: 1.0 min: 0.0 - height: 38 } - - ConfigSlider { - label: qsTr("Post sharpen") - integral: false - config: Render.getConfig("RenderMainView.Antialiasing") + Prop.PropScalar { + label: "Post sharpen" + object: Render.getConfig("RenderMainView.Antialiasing") property: "sharpen" max: 1.0 min: 0.0 } - Separator {} - Row { - - spacing: 10 - HifiControls.CheckBox { - boxSize: 20 - text: "Debug" - checked: Render.getConfig("RenderMainView.Antialiasing")["debug"] - onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["debug"] = checked } - } - HifiControls.CheckBox { - boxSize: 20 - text: "Show Debug Cursor" - checked: Render.getConfig("RenderMainView.Antialiasing")["showCursorPixel"] - onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["showCursorPixel"] = checked } - } - } - ConfigSlider { - label: qsTr("Debug Region <") - integral: false - config: Render.getConfig("RenderMainView.Antialiasing") + Separator {} + Prop.PropBool { + label: "Debug" + object: Render.getConfig("RenderMainView.Antialiasing") + property: "debug" + } + Prop.PropBool { + label: "Show Debug Cursor" + object: Render.getConfig("RenderMainView.Antialiasing") + property: "showCursorPixel" + } + Prop.PropScalar { + label: "Debug Region <" + object: Render.getConfig("RenderMainView.Antialiasing") property: "debugX" max: 1.0 min: 0.0 } - HifiControls.CheckBox { - boxSize: 20 - text: "Closest Fragment" - checked: Render.getConfig("RenderMainView.Antialiasing")["showClosestFragment"] - onCheckedChanged: { Render.getConfig("RenderMainView.Antialiasing")["showClosestFragment"] = checked } - } - ConfigSlider { - label: qsTr("Debug Velocity Threshold [pix]") - integral: false - config: Render.getConfig("RenderMainView.Antialiasing") + Prop.PropBool { + label: "Closest Fragment" + object: Render.getConfig("RenderMainView.Antialiasing") + property: "showClosestFragment" + } + Prop.PropScalar { + label: "Debug Velocity Threshold [pix]" + object: Render.getConfig("RenderMainView.Antialiasing") property: "debugShowVelocityThreshold" max: 50 min: 0.0 - height: 38 } - ConfigSlider { - label: qsTr("Debug Orb Zoom") - integral: false - config: Render.getConfig("RenderMainView.Antialiasing") + Prop.PropScalar { + label: "Debug Orb Zoom" + object: Render.getConfig("RenderMainView.Antialiasing") property: "debugOrbZoom" max: 32.0 min: 1.0 - height: 38 - } + } } diff --git a/scripts/developer/utilities/render/luci/Bloom.qml b/scripts/developer/utilities/render/luci/Bloom.qml index 67c931f66c..0edaea702b 100644 --- a/scripts/developer/utilities/render/luci/Bloom.qml +++ b/scripts/developer/utilities/render/luci/Bloom.qml @@ -37,6 +37,12 @@ Column { ] valueVarSetter: function (mode) { bloom.setDebugMode(mode) } + } + + Prop.PropBool { + label: "Debug Bloom Buffer" + object: Render.getConfig("RenderMainView.Bloom") + property: "enabled" } } diff --git a/scripts/developer/utilities/render/luci/ShadingModel.qml b/scripts/developer/utilities/render/luci/ShadingModel.qml index 78ca7f1740..afeca5a204 100644 --- a/scripts/developer/utilities/render/luci/ShadingModel.qml +++ b/scripts/developer/utilities/render/luci/ShadingModel.qml @@ -35,7 +35,8 @@ Column { "Emissive:LightingModel:enableEmissive", "Lightmap:LightingModel:enableLightmap", "Background:LightingModel:enableBackground", - "Haze:LightingModel:enableHaze", + "Haze:LightingModel:enableHaze", + "Bloom:LightingModel:enableBloom", "AO:LightingModel:enableAmbientOcclusion", "Textures:LightingModel:enableMaterialTexturing" ] From e1e4d9ac6c8f55c881519c75f4ec854a17132421 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 20 Aug 2019 18:15:35 -0700 Subject: [PATCH 04/46] Exposing the AA mode of the AA job --- .../render-utils/src/AntialiasingEffect.cpp | 7 +++++ .../render-utils/src/AntialiasingEffect.h | 14 ++++++++++ .../utilities/render/luci/Antialiasing.qml | 28 +++++-------------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index 0e70cb7f3c..c9da8373db 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -139,6 +139,11 @@ void Antialiasing::run(const render::RenderContextPointer& renderContext, const } #else +void AntialiasingConfig::setAAMode(int mode) { + _mode = std::min((int)AntialiasingConfig::MODE_COUNT, std::max(0, mode)); + emit dirty(); +} + Antialiasing::Antialiasing(bool isSharpenEnabled) : _isSharpenEnabled{ isSharpenEnabled } { } @@ -189,6 +194,8 @@ const gpu::PipelinePointer& Antialiasing::getDebugBlendPipeline() { } void Antialiasing::configure(const Config& config) { + _mode = (AntialiasingConfig::Mode) config.getAAMode(); + _sharpen = config.sharpen * 0.25f; if (!_isSharpenEnabled) { _sharpen = 0.0f; diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index 415571d348..1a760a8b06 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -88,6 +88,7 @@ private: class AntialiasingConfig : public render::Job::Config { Q_OBJECT + Q_PROPERTY(int mode READ getAAMode WRITE setAAMode NOTIFY dirty) Q_PROPERTY(float blend MEMBER blend NOTIFY dirty) Q_PROPERTY(float sharpen MEMBER sharpen NOTIFY dirty) Q_PROPERTY(float covarianceGamma MEMBER covarianceGamma NOTIFY dirty) @@ -108,9 +109,21 @@ class AntialiasingConfig : public render::Job::Config { public: AntialiasingConfig() : render::Job::Config(true) {} + enum Mode { + OFF = 0, + TAA, + FXAA, + MODE_COUNT + }; + + void setAAMode(int mode); + int getAAMode() const { return _mode; } + void setDebugFXAA(bool debug) { debugFXAAX = (debug ? 0.0f : 1.0f); emit dirty();} bool debugFXAA() const { return (debugFXAAX == 0.0f ? true : false); } + int _mode{ TAA }; + float blend{ 0.25f }; float sharpen{ 0.05f }; @@ -197,6 +210,7 @@ private: gpu::PipelinePointer _debugBlendPipeline; TAAParamsBuffer _params; + AntialiasingConfig::Mode _mode{ AntialiasingConfig::TAA }; float _sharpen{ 0.15f }; bool _isSharpenEnabled{ true }; }; diff --git a/scripts/developer/utilities/render/luci/Antialiasing.qml b/scripts/developer/utilities/render/luci/Antialiasing.qml index 46d8a8fcdb..2a52dfed46 100644 --- a/scripts/developer/utilities/render/luci/Antialiasing.qml +++ b/scripts/developer/utilities/render/luci/Antialiasing.qml @@ -38,44 +38,29 @@ Column{ Prop.PropEnum { label: "Deferred AA Method" + object: Render.getConfig("RenderMainView.Antialiasing") + property: "mode" enums: [ "Off", "TAA", "FXAA", ] - - valueVarSetter: function (mode) { setAAMode(mode) } - valueVarGetter: function () { return Render.getConfig("RenderMainView.JitterCam").state + - Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff * 2 } - - function setAAMode(mode) { - console.log("Deferred AA mode is " + mode) - - if (mode == 0) { - Render.getConfig("RenderMainView.JitterCam").state = 0; - Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff = false; - } else if (mode == 1) { - Render.getConfig("RenderMainView.JitterCam").state = 1; - Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff = false; - } else { - Render.getConfig("RenderMainView.JitterCam").state = 0; - Render.getConfig("RenderMainView.Antialiasing").fxaaOnOff = true; - } - } } - Separator {} Prop.PropEnum { + id: jitter label: "Jitter" object: Render.getConfig("RenderMainView.JitterCam") property: "state" - enums: [ "Off", "On", "Paused", ] } + Separator {} + Prop.PropScalar { + visible: (Render.getConfig("RenderMainView.JitterCam").state == 2) label: "Sample Index" object: Render.getConfig("RenderMainView.JitterCam") property: "index" @@ -85,6 +70,7 @@ Column{ integral: true } Row { + visible: (Render.getConfig("RenderMainView.JitterCam").state == 2) spacing: 10 HifiControls.Button { From 001e4bc952553b61416e374a957543827768ae30 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Wed, 21 Aug 2019 16:11:10 -0700 Subject: [PATCH 05/46] AnimClip now supports relative animations. Relative animations are animations that are rotation deltas from some base reference pose. They are calculated by multiplying each frame of each joint the inverse of that joints in the base reference pose. It is intended for use with additive blending. Added the following fields to AnimClip node. * isRelative (boolean) * baseURL (string) * baseFrame (int) --- libraries/animation/src/AnimClip.cpp | 265 ++++++++++++--------- libraries/animation/src/AnimClip.h | 11 +- libraries/animation/src/AnimNodeLoader.cpp | 6 +- libraries/animation/src/Rig.cpp | 2 +- 4 files changed, 173 insertions(+), 111 deletions(-) diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index e5edb46f69..3d045341ff 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -16,100 +16,6 @@ #include "AnimationLogging.h" #include "AnimUtil.h" - -AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag) : - AnimNode(AnimNode::Type::Clip, id), - _startFrame(startFrame), - _endFrame(endFrame), - _timeScale(timeScale), - _loopFlag(loopFlag), - _mirrorFlag(mirrorFlag), - _frame(startFrame) -{ - loadURL(url); -} - -AnimClip::~AnimClip() { - -} - -const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) { - - // lookup parameters from animVars, using current instance variables as defaults. - _startFrame = animVars.lookup(_startFrameVar, _startFrame); - _endFrame = animVars.lookup(_endFrameVar, _endFrame); - _timeScale = animVars.lookup(_timeScaleVar, _timeScale); - _loopFlag = animVars.lookup(_loopFlagVar, _loopFlag); - _mirrorFlag = animVars.lookup(_mirrorFlagVar, _mirrorFlag); - float frame = animVars.lookup(_frameVar, _frame); - - _frame = ::accumulateTime(_startFrame, _endFrame, _timeScale, frame, dt, _loopFlag, _id, triggersOut); - - // poll network anim to see if it's finished loading yet. - if (_networkAnim && _networkAnim->isLoaded() && _skeleton) { - // loading is complete, copy animation frames from network animation, then throw it away. - copyFromNetworkAnim(); - _networkAnim.reset(); - } - - if (_anim.size()) { - - // lazy creation of mirrored animation frames. - if (_mirrorFlag && _anim.size() != _mirrorAnim.size()) { - buildMirrorAnim(); - } - - int prevIndex = (int)glm::floor(_frame); - int nextIndex; - if (_loopFlag && _frame >= _endFrame) { - nextIndex = (int)glm::ceil(_startFrame); - } else { - nextIndex = (int)glm::ceil(_frame); - } - - // It can be quite possible for the user to set _startFrame and _endFrame to - // values before or past valid ranges. We clamp the frames here. - int frameCount = (int)_anim.size(); - prevIndex = std::min(std::max(0, prevIndex), frameCount - 1); - nextIndex = std::min(std::max(0, nextIndex), frameCount - 1); - - const AnimPoseVec& prevFrame = _mirrorFlag ? _mirrorAnim[prevIndex] : _anim[prevIndex]; - const AnimPoseVec& nextFrame = _mirrorFlag ? _mirrorAnim[nextIndex] : _anim[nextIndex]; - float alpha = glm::fract(_frame); - - ::blend(_poses.size(), &prevFrame[0], &nextFrame[0], alpha, &_poses[0]); - } - - processOutputJoints(triggersOut); - - return _poses; -} - -void AnimClip::loadURL(const QString& url) { - auto animCache = DependencyManager::get(); - _networkAnim = animCache->getAnimation(url); - _url = url; -} - -void AnimClip::setCurrentFrameInternal(float frame) { - // because dt is 0, we should not encounter any triggers - const float dt = 0.0f; - AnimVariantMap triggers; - _frame = ::accumulateTime(_startFrame, _endFrame, _timeScale, frame + _startFrame, dt, _loopFlag, _id, triggers); -} - -static std::vector buildJointIndexMap(const AnimSkeleton& dstSkeleton, const AnimSkeleton& srcSkeleton) { - std::vector jointIndexMap; - int srcJointCount = srcSkeleton.getNumJoints(); - jointIndexMap.reserve(srcJointCount); - for (int srcJointIndex = 0; srcJointIndex < srcJointCount; srcJointIndex++) { - QString srcJointName = srcSkeleton.getJointName(srcJointIndex); - int dstJointIndex = dstSkeleton.nameToJointIndex(srcJointName); - jointIndexMap.push_back(dstJointIndex); - } - return jointIndexMap; -} - #ifdef USE_CUSTOM_ASSERT #undef ASSERT #define ASSERT(x) \ @@ -123,12 +29,44 @@ static std::vector buildJointIndexMap(const AnimSkeleton& dstSkeleton, cons #define ASSERT assert #endif -void AnimClip::copyFromNetworkAnim() { - assert(_networkAnim && _networkAnim->isLoaded() && _skeleton); - _anim.clear(); +static std::vector buildJointIndexMap(const AnimSkeleton& dstSkeleton, const AnimSkeleton& srcSkeleton) { + std::vector jointIndexMap; + int srcJointCount = srcSkeleton.getNumJoints(); + jointIndexMap.reserve(srcJointCount); + for (int srcJointIndex = 0; srcJointIndex < srcJointCount; srcJointIndex++) { + QString srcJointName = srcSkeleton.getJointName(srcJointIndex); + int dstJointIndex = dstSkeleton.nameToJointIndex(srcJointName); + jointIndexMap.push_back(dstJointIndex); + } + return jointIndexMap; +} - auto avatarSkeleton = getSkeleton(); - const HFMModel& animModel = _networkAnim->getHFMModel(); +static void bakeRelativeAnim(std::vector& anim, const AnimPoseVec& basePoses) { + + // invert all the basePoses + AnimPoseVec invBasePoses = basePoses; + for (auto&& invBasePose : invBasePoses) { + invBasePose = invBasePose.inverse(); + } + + // for each frame of the animation + for (auto&& animPoses : anim) { + ASSERT(animPoses.size() == basePoses.size()); + + // for each joint in animPoses + for (size_t i = 0; i < animPoses.size(); ++i) { + + // convert this AnimPose into a relative animation. + animPoses[i] = animPoses[i] * invBasePoses[i]; + } + } +} + +static std::vector copyAndRetargetFromNetworkAnim(AnimationPointer networkAnim, AnimSkeleton::ConstPointer avatarSkeleton) { + ASSERT(networkAnim && networkAnim->isLoaded() && avatarSkeleton); + std::vector anim; + + const HFMModel& animModel = networkAnim->getHFMModel(); AnimSkeleton animSkeleton(animModel); const int animJointCount = animSkeleton.getNumJoints(); const int avatarJointCount = avatarSkeleton->getNumJoints(); @@ -137,7 +75,7 @@ void AnimClip::copyFromNetworkAnim() { std::vector avatarToAnimJointIndexMap = buildJointIndexMap(animSkeleton, *avatarSkeleton); const int animFrameCount = animModel.animationFrames.size(); - _anim.resize(animFrameCount); + anim.resize(animFrameCount); // find the size scale factor for translation in the animation. float boneLengthScale = 1.0f; @@ -223,8 +161,8 @@ void AnimClip::copyFromNetworkAnim() { // convert avatar rotations into relative frame avatarSkeleton->convertAbsoluteRotationsToRelative(avatarRotations); - ASSERT(frame >= 0 && frame < (int)_anim.size()); - _anim[frame].reserve(avatarJointCount); + ASSERT(frame >= 0 && frame < (int)anim.size()); + anim[frame].reserve(avatarJointCount); for (int avatarJointIndex = 0; avatarJointIndex < avatarJointCount; avatarJointIndex++) { const AnimPose& avatarDefaultPose = avatarSkeleton->getRelativeDefaultPose(avatarJointIndex); @@ -251,14 +189,123 @@ void AnimClip::copyFromNetworkAnim() { // build the final pose ASSERT(avatarJointIndex >= 0 && avatarJointIndex < (int)avatarRotations.size()); - _anim[frame].push_back(AnimPose(relativeScale, avatarRotations[avatarJointIndex], relativeTranslation)); + anim[frame].push_back(AnimPose(relativeScale, avatarRotations[avatarJointIndex], relativeTranslation)); } } - // mirrorAnim will be re-built on demand, if needed. - _mirrorAnim.clear(); + return anim; +} - _poses.resize(avatarJointCount); +AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag, + bool isRelative, const QString& baseURL, float baseFrame) : + AnimNode(AnimNode::Type::Clip, id), + _startFrame(startFrame), + _endFrame(endFrame), + _timeScale(timeScale), + _loopFlag(loopFlag), + _mirrorFlag(mirrorFlag), + _frame(startFrame), + _isRelative(isRelative), + _baseFrame(baseFrame) +{ + loadURL(url); + + if (isRelative) { + auto animCache = DependencyManager::get(); + _baseNetworkAnim = animCache->getAnimation(baseURL); + _baseURL = baseURL; + } +} + +AnimClip::~AnimClip() { + +} + +const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) { + + // lookup parameters from animVars, using current instance variables as defaults. + _startFrame = animVars.lookup(_startFrameVar, _startFrame); + _endFrame = animVars.lookup(_endFrameVar, _endFrame); + _timeScale = animVars.lookup(_timeScaleVar, _timeScale); + _loopFlag = animVars.lookup(_loopFlagVar, _loopFlag); + _mirrorFlag = animVars.lookup(_mirrorFlagVar, _mirrorFlag); + float frame = animVars.lookup(_frameVar, _frame); + + _frame = ::accumulateTime(_startFrame, _endFrame, _timeScale, frame, dt, _loopFlag, _id, triggersOut); + + // poll network anim to see if it's finished loading yet. + if (_isRelative) { + if (_networkAnim && _networkAnim->isLoaded() && _skeleton) { + // loading is complete, copy & retarget animation. + _anim = copyAndRetargetFromNetworkAnim(_networkAnim, _skeleton); + + // we no longer need the actual animation resource anymore. + _networkAnim.reset(); + + // mirrorAnim will be re-built on demand, if needed. + _mirrorAnim.clear(); + + _poses.resize(_skeleton->getNumJoints()); + } + } else { + if (_networkAnim && _networkAnim->isLoaded() && _baseNetworkAnim && _baseNetworkAnim->isLoaded() && _skeleton) { + // loading is complete, copy & retarget animation. + _anim = copyAndRetargetFromNetworkAnim(_networkAnim, _skeleton); + + // we no longer need the actual animation resource anymore. + _networkAnim.reset(); + + // mirrorAnim will be re-built on demand, if needed. + _mirrorAnim.clear(); + + _poses.resize(_skeleton->getNumJoints()); + + // copy & retarget baseAnim! + auto baseAnim = copyAndRetargetFromNetworkAnim(_baseNetworkAnim, _skeleton); + + // make _anim relative to the baseAnim reference frame. + bakeRelativeAnim(_anim, baseAnim[(int)_baseFrame]); + } + } + + if (_anim.size()) { + + // lazy creation of mirrored animation frames. + if (_mirrorFlag && _anim.size() != _mirrorAnim.size()) { + buildMirrorAnim(); + } + + int prevIndex = (int)glm::floor(_frame); + int nextIndex; + if (_loopFlag && _frame >= _endFrame) { + nextIndex = (int)glm::ceil(_startFrame); + } else { + nextIndex = (int)glm::ceil(_frame); + } + + // It can be quite possible for the user to set _startFrame and _endFrame to + // values before or past valid ranges. We clamp the frames here. + int frameCount = (int)_anim.size(); + prevIndex = std::min(std::max(0, prevIndex), frameCount - 1); + nextIndex = std::min(std::max(0, nextIndex), frameCount - 1); + + const AnimPoseVec& prevFrame = _mirrorFlag ? _mirrorAnim[prevIndex] : _anim[prevIndex]; + const AnimPoseVec& nextFrame = _mirrorFlag ? _mirrorAnim[nextIndex] : _anim[nextIndex]; + float alpha = glm::fract(_frame); + + ::blend(_poses.size(), &prevFrame[0], &nextFrame[0], alpha, &_poses[0]); + } + + processOutputJoints(triggersOut); + + return _poses; +} + +void AnimClip::setCurrentFrameInternal(float frame) { + // because dt is 0, we should not encounter any triggers + const float dt = 0.0f; + AnimVariantMap triggers; + _frame = ::accumulateTime(_startFrame, _endFrame, _timeScale, frame + _startFrame, dt, _loopFlag, _id, triggers); } void AnimClip::buildMirrorAnim() { @@ -275,3 +322,9 @@ void AnimClip::buildMirrorAnim() { const AnimPoseVec& AnimClip::getPosesInternal() const { return _poses; } + +void AnimClip::loadURL(const QString& url) { + auto animCache = DependencyManager::get(); + _networkAnim = animCache->getAnimation(url); + _url = url; +} diff --git a/libraries/animation/src/AnimClip.h b/libraries/animation/src/AnimClip.h index 92f4c01dcc..04a402356c 100644 --- a/libraries/animation/src/AnimClip.h +++ b/libraries/animation/src/AnimClip.h @@ -25,7 +25,8 @@ class AnimClip : public AnimNode { public: friend class AnimTests; - AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag); + AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag, + bool isRelative, const QString& baseURL, float baseFrame); virtual ~AnimClip() override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override; @@ -52,19 +53,20 @@ public: void setMirrorFlag(bool mirrorFlag) { _mirrorFlag = mirrorFlag; } float getFrame() const { return _frame; } - void loadURL(const QString& url); + protected: virtual void setCurrentFrameInternal(float frame) override; - void copyFromNetworkAnim(); void buildMirrorAnim(); // for AnimDebugDraw rendering virtual const AnimPoseVec& getPosesInternal() const override; AnimationPointer _networkAnim; + AnimationPointer _baseNetworkAnim; + AnimPoseVec _poses; // _anim[frame][joint] @@ -78,6 +80,9 @@ protected: bool _loopFlag; bool _mirrorFlag; float _frame; + bool _isRelative; + QString _baseURL; + float _baseFrame; QString _startFrameVar; QString _endFrameVar; diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index d43351fff9..9f223e08d1 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -374,6 +374,9 @@ static AnimNode::Pointer loadClipNode(const QJsonObject& jsonObj, const QString& READ_FLOAT(timeScale, jsonObj, id, jsonUrl, nullptr); READ_BOOL(loopFlag, jsonObj, id, jsonUrl, nullptr); READ_OPTIONAL_BOOL(mirrorFlag, jsonObj, false); + READ_OPTIONAL_BOOL(isRelative, jsonObj, false); + READ_OPTIONAL_STRING(baseURL, jsonObj); + READ_OPTIONAL_FLOAT(baseFrame, jsonObj, 0.0f); READ_OPTIONAL_STRING(startFrameVar, jsonObj); READ_OPTIONAL_STRING(endFrameVar, jsonObj); @@ -381,11 +384,12 @@ static AnimNode::Pointer loadClipNode(const QJsonObject& jsonObj, const QString& READ_OPTIONAL_STRING(loopFlagVar, jsonObj); READ_OPTIONAL_STRING(mirrorFlagVar, jsonObj); + // animation urls can be relative to the containing url document. auto tempUrl = QUrl(url); tempUrl = jsonUrl.resolved(tempUrl); - auto node = std::make_shared(id, tempUrl.toString(), startFrame, endFrame, timeScale, loopFlag, mirrorFlag); + auto node = std::make_shared(id, tempUrl.toString(), startFrame, endFrame, timeScale, loopFlag, mirrorFlag, isRelative, baseURL, baseFrame); if (!startFrameVar.isEmpty()) { node->setStartFrameVar(startFrameVar); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 211c54def8..2974212bf1 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -564,7 +564,7 @@ void Rig::overrideRoleAnimation(const QString& role, const QString& url, float f _origRoleAnimations[role] = node; const float REFERENCE_FRAMES_PER_SECOND = 30.0f; float timeScale = fps / REFERENCE_FRAMES_PER_SECOND; - auto clipNode = std::make_shared(role, url, firstFrame, lastFrame, timeScale, loop, false); + auto clipNode = std::make_shared(role, url, firstFrame, lastFrame, timeScale, loop, false, false, "", 0.0f); _roleAnimStates[role] = { role, url, fps, loop, firstFrame, lastFrame }; AnimNode::Pointer parent = node->getParent(); parent->replaceChild(node, clipNode); From f1afc9e8731692b8a757b9cbd4709aa563f3b9a1 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 23 Aug 2019 08:46:14 -0700 Subject: [PATCH 06/46] Bug fix & rename isRelative to relativeFlag --- libraries/animation/src/AnimClip.cpp | 9 +++++---- libraries/animation/src/AnimClip.h | 4 ++-- libraries/animation/src/AnimNodeLoader.cpp | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 3d045341ff..d58c3511cd 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -197,7 +197,7 @@ static std::vector copyAndRetargetFromNetworkAnim(AnimationPointer } AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag, - bool isRelative, const QString& baseURL, float baseFrame) : + bool relativeFlag, const QString& baseURL, float baseFrame) : AnimNode(AnimNode::Type::Clip, id), _startFrame(startFrame), _endFrame(endFrame), @@ -205,12 +205,12 @@ AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, floa _loopFlag(loopFlag), _mirrorFlag(mirrorFlag), _frame(startFrame), - _isRelative(isRelative), + _relativeFlag(relativeFlag), _baseFrame(baseFrame) { loadURL(url); - if (isRelative) { + if (relativeFlag) { auto animCache = DependencyManager::get(); _baseNetworkAnim = animCache->getAnimation(baseURL); _baseURL = baseURL; @@ -234,7 +234,7 @@ const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, const Anim _frame = ::accumulateTime(_startFrame, _endFrame, _timeScale, frame, dt, _loopFlag, _id, triggersOut); // poll network anim to see if it's finished loading yet. - if (_isRelative) { + if (!_relativeFlag) { if (_networkAnim && _networkAnim->isLoaded() && _skeleton) { // loading is complete, copy & retarget animation. _anim = copyAndRetargetFromNetworkAnim(_networkAnim, _skeleton); @@ -256,6 +256,7 @@ const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, const Anim _networkAnim.reset(); // mirrorAnim will be re-built on demand, if needed. + // TODO: handle mirrored relative animations. _mirrorAnim.clear(); _poses.resize(_skeleton->getNumJoints()); diff --git a/libraries/animation/src/AnimClip.h b/libraries/animation/src/AnimClip.h index 04a402356c..2ecaffb8b1 100644 --- a/libraries/animation/src/AnimClip.h +++ b/libraries/animation/src/AnimClip.h @@ -26,7 +26,7 @@ public: friend class AnimTests; AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag, - bool isRelative, const QString& baseURL, float baseFrame); + bool relativeFlag, const QString& baseURL, float baseFrame); virtual ~AnimClip() override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override; @@ -80,7 +80,7 @@ protected: bool _loopFlag; bool _mirrorFlag; float _frame; - bool _isRelative; + bool _relativeFlag; QString _baseURL; float _baseFrame; diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index 9f223e08d1..ebd8a6de5b 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -374,7 +374,7 @@ static AnimNode::Pointer loadClipNode(const QJsonObject& jsonObj, const QString& READ_FLOAT(timeScale, jsonObj, id, jsonUrl, nullptr); READ_BOOL(loopFlag, jsonObj, id, jsonUrl, nullptr); READ_OPTIONAL_BOOL(mirrorFlag, jsonObj, false); - READ_OPTIONAL_BOOL(isRelative, jsonObj, false); + READ_OPTIONAL_BOOL(relativeFlag, jsonObj, false); READ_OPTIONAL_STRING(baseURL, jsonObj); READ_OPTIONAL_FLOAT(baseFrame, jsonObj, 0.0f); @@ -389,7 +389,7 @@ static AnimNode::Pointer loadClipNode(const QJsonObject& jsonObj, const QString& auto tempUrl = QUrl(url); tempUrl = jsonUrl.resolved(tempUrl); - auto node = std::make_shared(id, tempUrl.toString(), startFrame, endFrame, timeScale, loopFlag, mirrorFlag, isRelative, baseURL, baseFrame); + auto node = std::make_shared(id, tempUrl.toString(), startFrame, endFrame, timeScale, loopFlag, mirrorFlag, relativeFlag, baseURL, baseFrame); if (!startFrameVar.isEmpty()) { node->setStartFrameVar(startFrameVar); From ed3ba876a840f2e670e209e41798b5fdf9e1957e Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 26 Aug 2019 17:02:15 -0700 Subject: [PATCH 07/46] AddRelative blending support (Absolute is still not working) --- libraries/animation/src/AnimBlendLinear.cpp | 23 +++++++++++++++--- libraries/animation/src/AnimBlendLinear.h | 3 ++- libraries/animation/src/AnimContext.h | 7 ++++++ libraries/animation/src/AnimNodeLoader.cpp | 26 +++++++++++++++++++-- libraries/animation/src/AnimUtil.cpp | 21 ++++++++++++++++- libraries/animation/src/AnimUtil.h | 3 +++ 6 files changed, 76 insertions(+), 7 deletions(-) diff --git a/libraries/animation/src/AnimBlendLinear.cpp b/libraries/animation/src/AnimBlendLinear.cpp index 17ca88123f..c740de72cb 100644 --- a/libraries/animation/src/AnimBlendLinear.cpp +++ b/libraries/animation/src/AnimBlendLinear.cpp @@ -14,9 +14,10 @@ #include "AnimUtil.h" #include "AnimClip.h" -AnimBlendLinear::AnimBlendLinear(const QString& id, float alpha) : +AnimBlendLinear::AnimBlendLinear(const QString& id, float alpha, AnimBlendType blendType) : AnimNode(AnimNode::Type::BlendLinear, id), - _alpha(alpha) { + _alpha(alpha), + _blendType(blendType) { } @@ -79,7 +80,23 @@ void AnimBlendLinear::evaluateAndBlendChildren(const AnimVariantMap& animVars, c if (prevPoses.size() > 0 && prevPoses.size() == nextPoses.size()) { _poses.resize(prevPoses.size()); - ::blend(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]); + if (_blendType == AnimBlendType_Normal) { + ::blend(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]); + } else if (_blendType == AnimBlendType_AddRelative) { + ::blendAdd(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]); + } else if (_blendType == AnimBlendType_AddAbsolute) { + // onvert from relative to absolute + AnimPoseVec prev = prevPoses; + _skeleton->convertRelativePosesToAbsolute(prev); + AnimPoseVec next = nextPoses; + _skeleton->convertRelativePosesToAbsolute(next); + + // then blend + ::blendAdd(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]); + + // convert result back into relative + _skeleton->convertAbsolutePosesToRelative(_poses); + } } } } diff --git a/libraries/animation/src/AnimBlendLinear.h b/libraries/animation/src/AnimBlendLinear.h index d0fe2a8503..e6fb39438f 100644 --- a/libraries/animation/src/AnimBlendLinear.h +++ b/libraries/animation/src/AnimBlendLinear.h @@ -27,7 +27,7 @@ class AnimBlendLinear : public AnimNode { public: friend class AnimTests; - AnimBlendLinear(const QString& id, float alpha); + AnimBlendLinear(const QString& id, float alpha, AnimBlendType blendType); virtual ~AnimBlendLinear() override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override; @@ -43,6 +43,7 @@ protected: AnimPoseVec _poses; + AnimBlendType _blendType; float _alpha; QString _alphaVar; diff --git a/libraries/animation/src/AnimContext.h b/libraries/animation/src/AnimContext.h index 5f353fcae4..2ee8a30980 100644 --- a/libraries/animation/src/AnimContext.h +++ b/libraries/animation/src/AnimContext.h @@ -34,6 +34,13 @@ enum class AnimNodeType { NumTypes }; +enum AnimBlendType { + AnimBlendType_Normal, + AnimBlendType_AddRelative, + AnimBlendType_AddAbsolute, + AnimBlendType_NumTypes +}; + class AnimContext { public: AnimContext() {} diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index ebd8a6de5b..c00dabfb5d 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -161,6 +161,19 @@ static EasingType stringToEasingType(const QString& str) { } } +static AnimBlendType stringToAnimBlendType(const QString& str) { + if (str == "normal") { + return AnimBlendType_Normal; + } else if (str == "addRelative") { + return AnimBlendType_AddRelative; + } else if (str == "addAbsolute") { + return AnimBlendType_AddAbsolute; + } else { + return AnimBlendType_NumTypes; + } +} + + static const char* animManipulatorJointVarTypeToString(AnimManipulator::JointVar::Type type) { switch (type) { case AnimManipulator::JointVar::Type::Absolute: return "absolute"; @@ -413,10 +426,19 @@ static AnimNode::Pointer loadClipNode(const QJsonObject& jsonObj, const QString& static AnimNode::Pointer loadBlendLinearNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { READ_FLOAT(alpha, jsonObj, id, jsonUrl, nullptr); - + READ_OPTIONAL_STRING(blendType, jsonObj); READ_OPTIONAL_STRING(alphaVar, jsonObj); - auto node = std::make_shared(id, alpha); + AnimBlendType blendTypeEnum = AnimBlendType_Normal; // default value + if (!blendType.isEmpty()) { + blendTypeEnum = stringToAnimBlendType(blendType); + if (blendTypeEnum == AnimBlendType_NumTypes) { + qCCritical(animation) << "AnimNodeLoader, bad blendType on blendLinear, id = " << id; + return nullptr; + } + } + + auto node = std::make_shared(id, alpha, blendTypeEnum); if (!alphaVar.isEmpty()) { node->setAlphaVar(alphaVar); diff --git a/libraries/animation/src/AnimUtil.cpp b/libraries/animation/src/AnimUtil.cpp index f4f922d704..621e714f97 100644 --- a/libraries/animation/src/AnimUtil.cpp +++ b/libraries/animation/src/AnimUtil.cpp @@ -15,7 +15,6 @@ // TODO: use restrict keyword // TODO: excellent candidate for simd vectorization. - void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result) { for (size_t i = 0; i < numPoses; i++) { const AnimPose& aPose = a[i]; @@ -27,6 +26,26 @@ void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, A } } +// additive blend +void blendAdd(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result) { + for (size_t i = 0; i < numPoses; i++) { + const AnimPose& aPose = a[i]; + const AnimPose& bPose = b[i]; + + result[i].scale() = lerp(aPose.scale(), bPose.scale(), alpha); + + // adjust sign of bPose.rot() if necessary + glm::quat bTemp = bPose.rot(); + float dot = glm::dot(aPose.rot(), bTemp); + if (dot < 0.0f) { + bTemp = -bTemp; + } + result[i].rot() = glm::normalize((alpha * bTemp) * aPose.rot()); + + result[i].trans() = aPose.trans() + (alpha * bPose.trans()); + } +} + glm::quat averageQuats(size_t numQuats, const glm::quat* quats) { if (numQuats == 0) { return glm::quat(); diff --git a/libraries/animation/src/AnimUtil.h b/libraries/animation/src/AnimUtil.h index 26dc19da06..5d67b27abb 100644 --- a/libraries/animation/src/AnimUtil.h +++ b/libraries/animation/src/AnimUtil.h @@ -16,6 +16,9 @@ // this is where the magic happens void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result); +// additive blending +void blendAdd(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result); + glm::quat averageQuats(size_t numQuats, const glm::quat* quats); float accumulateTime(float startFrame, float endFrame, float timeScale, float currentFrame, float dt, bool loopFlag, From 1979e1dbc7aecca330bd504dc55dfcf032dd48d0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 27 Aug 2019 16:37:37 -0700 Subject: [PATCH 08/46] apply fake eye saccades if eye joints aren't overridden (rather than if HasProceduralEyeFaceMovement is true) --- interface/src/avatar/MySkeletonModel.cpp | 5 +---- libraries/animation/src/Rig.cpp | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/MySkeletonModel.cpp b/interface/src/avatar/MySkeletonModel.cpp index 6080911dd9..9d5693da33 100755 --- a/interface/src/avatar/MySkeletonModel.cpp +++ b/interface/src/avatar/MySkeletonModel.cpp @@ -337,10 +337,7 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) { eyeParams.modelTranslation = getTranslation(); eyeParams.leftEyeJointIndex = _rig.indexOfJoint("LeftEye"); eyeParams.rightEyeJointIndex = _rig.indexOfJoint("RightEye"); - - if (_owningAvatar->getHasProceduralEyeFaceMovement()) { - _rig.updateFromEyeParameters(eyeParams); - } + _rig.updateFromEyeParameters(eyeParams); updateFingers(); } diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 211c54def8..bd099af7c0 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1973,7 +1973,7 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm // TODO: does not properly handle avatar scale. - if (isIndexValid(index)) { + if (isIndexValid(index) && !_internalPoseSet._overrideFlags[i]) { const glm::mat4 rigToWorld = createMatFromQuatAndPos(modelRotation, modelTranslation); const glm::mat4 worldToRig = glm::inverse(rigToWorld); const glm::vec3 lookAtVector = glm::normalize(transformPoint(worldToRig, lookAtSpot) - _internalPoseSet._absolutePoses[index].trans()); From f331b76c5161850399a4b074ce3e2782f796eaf0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 27 Aug 2019 16:58:37 -0700 Subject: [PATCH 09/46] apply fake eye saccades if eye joints aren't overridden (rather than if HasProceduralEyeFaceMovement is true) --- libraries/animation/src/Rig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index bd099af7c0..153637f176 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1973,7 +1973,7 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm // TODO: does not properly handle avatar scale. - if (isIndexValid(index) && !_internalPoseSet._overrideFlags[i]) { + if (isIndexValid(index) && !_internalPoseSet._overrideFlags[index]) { const glm::mat4 rigToWorld = createMatFromQuatAndPos(modelRotation, modelTranslation); const glm::mat4 worldToRig = glm::inverse(rigToWorld); const glm::vec3 lookAtVector = glm::normalize(transformPoint(worldToRig, lookAtSpot) - _internalPoseSet._absolutePoses[index].trans()); From adda7774d377ef3e635b81b55394e489efcabdf9 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 28 Aug 2019 14:08:21 -0700 Subject: [PATCH 10/46] WIP checkpoint addAbsolute still broken --- libraries/animation/src/AnimBlendLinear.cpp | 32 ++++++++++----- libraries/animation/src/AnimClip.cpp | 44 ++++++++++++++++++--- 2 files changed, 62 insertions(+), 14 deletions(-) diff --git a/libraries/animation/src/AnimBlendLinear.cpp b/libraries/animation/src/AnimBlendLinear.cpp index c740de72cb..65329dd167 100644 --- a/libraries/animation/src/AnimBlendLinear.cpp +++ b/libraries/animation/src/AnimBlendLinear.cpp @@ -85,17 +85,31 @@ void AnimBlendLinear::evaluateAndBlendChildren(const AnimVariantMap& animVars, c } else if (_blendType == AnimBlendType_AddRelative) { ::blendAdd(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]); } else if (_blendType == AnimBlendType_AddAbsolute) { - // onvert from relative to absolute - AnimPoseVec prev = prevPoses; - _skeleton->convertRelativePosesToAbsolute(prev); - AnimPoseVec next = nextPoses; - _skeleton->convertRelativePosesToAbsolute(next); + // convert prev from relative to absolute + AnimPoseVec absPrev = prevPoses; + _skeleton->convertRelativePosesToAbsolute(absPrev); + + // rotate the offset rotations from next into the parent relative frame of each joint. + AnimPoseVec relOffsetPoses; + relOffsetPoses.reserve(nextPoses.size()); + for (size_t i = 0; i < nextPoses.size(); ++i) { + // copy translation and scale from nextPoses + AnimPose pose = nextPoses[i]; + + // AJT: HACK nuke trans + pose.trans() = glm::vec3(0.0f); + + int parentIndex = _skeleton->getParentIndex(i); + if (parentIndex >= 0) { + // but transform nextPoses rot into absPrev parent frame. + pose.rot() = glm::inverse(absPrev[parentIndex].rot()) * nextPoses[i].rot(); + } + + relOffsetPoses.push_back(pose); + } // then blend - ::blendAdd(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]); - - // convert result back into relative - _skeleton->convertAbsolutePosesToRelative(_poses); + ::blendAdd(_poses.size(), &prevPoses[0], &relOffsetPoses[0], alpha, &_poses[0]); } } } diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index d58c3511cd..3f386f2804 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -41,7 +41,7 @@ static std::vector buildJointIndexMap(const AnimSkeleton& dstSkeleton, cons return jointIndexMap; } -static void bakeRelativeAnim(std::vector& anim, const AnimPoseVec& basePoses) { +static void bakeRelativeDeltaAnim(std::vector& anim, const AnimPoseVec& basePoses) { // invert all the basePoses AnimPoseVec invBasePoses = basePoses; @@ -55,13 +55,42 @@ static void bakeRelativeAnim(std::vector& anim, const AnimPoseVec& // for each joint in animPoses for (size_t i = 0; i < animPoses.size(); ++i) { - - // convert this AnimPose into a relative animation. + // convert this relative AnimPose into a delta animation. animPoses[i] = animPoses[i] * invBasePoses[i]; } } } +void bakeAbsoluteDeltaAnim(std::vector& anim, const AnimPoseVec& basePoses, AnimSkeleton::ConstPointer skeleton) { + + // invert all the basePoses + AnimPoseVec invBasePoses = basePoses; + for (auto&& invBasePose : invBasePoses) { + invBasePose = invBasePose.inverse(); + } + + AnimPoseVec absBasePoses = basePoses; + skeleton->convertRelativePosesToAbsolute(absBasePoses); + + // for each frame of the animation + for (auto&& animPoses : anim) { + ASSERT(animPoses.size() == basePoses.size()); + + // for each joint in animPoses + for (size_t i = 0; i < animPoses.size(); ++i) { + + // scale and translation are relative frame + animPoses[i] = animPoses[i] * invBasePoses[i]; + + // but transform the rotation delta into the absolute frame. + int parentIndex = skeleton->getParentIndex(i); + if (parentIndex >= 0) { + animPoses[i].rot() = absBasePoses[parentIndex].rot() * animPoses[i].rot(); + } + } + } +} + static std::vector copyAndRetargetFromNetworkAnim(AnimationPointer networkAnim, AnimSkeleton::ConstPointer avatarSkeleton) { ASSERT(networkAnim && networkAnim->isLoaded() && avatarSkeleton); std::vector anim; @@ -264,8 +293,13 @@ const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, const Anim // copy & retarget baseAnim! auto baseAnim = copyAndRetargetFromNetworkAnim(_baseNetworkAnim, _skeleton); - // make _anim relative to the baseAnim reference frame. - bakeRelativeAnim(_anim, baseAnim[(int)_baseFrame]); +//#define BLEND_ADD_ABSOLUTE + +#ifdef BLEND_ADD_ABSOLUTE + bakeAbsoluteDeltaAnim(_anim, baseAnim[(int)_baseFrame], _skeleton); +#else + bakeRelativeDeltaAnim(_anim, baseAnim[(int)_baseFrame]); +#endif } } From 16a20a5ead5ce52e77a4b1c0816dfe4209e93764 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 28 Aug 2019 18:19:35 -0700 Subject: [PATCH 11/46] AddAbsolute now works! added blendType to AnimClip --- libraries/animation/src/AnimBlendLinear.cpp | 8 +++---- libraries/animation/src/AnimClip.cpp | 26 ++++++++++----------- libraries/animation/src/AnimClip.h | 4 ++-- libraries/animation/src/AnimNodeLoader.cpp | 14 +++++++++-- libraries/animation/src/Rig.cpp | 2 +- 5 files changed, 31 insertions(+), 23 deletions(-) diff --git a/libraries/animation/src/AnimBlendLinear.cpp b/libraries/animation/src/AnimBlendLinear.cpp index 65329dd167..4e8c42dad3 100644 --- a/libraries/animation/src/AnimBlendLinear.cpp +++ b/libraries/animation/src/AnimBlendLinear.cpp @@ -93,16 +93,14 @@ void AnimBlendLinear::evaluateAndBlendChildren(const AnimVariantMap& animVars, c AnimPoseVec relOffsetPoses; relOffsetPoses.reserve(nextPoses.size()); for (size_t i = 0; i < nextPoses.size(); ++i) { + // copy translation and scale from nextPoses AnimPose pose = nextPoses[i]; - // AJT: HACK nuke trans - pose.trans() = glm::vec3(0.0f); - - int parentIndex = _skeleton->getParentIndex(i); + int parentIndex = _skeleton->getParentIndex((int)i); if (parentIndex >= 0) { // but transform nextPoses rot into absPrev parent frame. - pose.rot() = glm::inverse(absPrev[parentIndex].rot()) * nextPoses[i].rot(); + pose.rot() = glm::inverse(absPrev[parentIndex].rot()) * pose.rot() * absPrev[parentIndex].rot(); } relOffsetPoses.push_back(pose); diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 3f386f2804..96bc87d738 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -83,9 +83,9 @@ void bakeAbsoluteDeltaAnim(std::vector& anim, const AnimPoseVec& ba animPoses[i] = animPoses[i] * invBasePoses[i]; // but transform the rotation delta into the absolute frame. - int parentIndex = skeleton->getParentIndex(i); + int parentIndex = skeleton->getParentIndex((int)i); if (parentIndex >= 0) { - animPoses[i].rot() = absBasePoses[parentIndex].rot() * animPoses[i].rot(); + animPoses[i].rot() = absBasePoses[parentIndex].rot() * animPoses[i].rot() * glm::inverse(absBasePoses[parentIndex].rot()); } } } @@ -226,7 +226,7 @@ static std::vector copyAndRetargetFromNetworkAnim(AnimationPointer } AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag, - bool relativeFlag, const QString& baseURL, float baseFrame) : + AnimBlendType blendType, const QString& baseURL, float baseFrame) : AnimNode(AnimNode::Type::Clip, id), _startFrame(startFrame), _endFrame(endFrame), @@ -234,12 +234,12 @@ AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, floa _loopFlag(loopFlag), _mirrorFlag(mirrorFlag), _frame(startFrame), - _relativeFlag(relativeFlag), + _blendType(blendType), _baseFrame(baseFrame) { loadURL(url); - if (relativeFlag) { + if (blendType != AnimBlendType_Normal) { auto animCache = DependencyManager::get(); _baseNetworkAnim = animCache->getAnimation(baseURL); _baseURL = baseURL; @@ -263,7 +263,7 @@ const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, const Anim _frame = ::accumulateTime(_startFrame, _endFrame, _timeScale, frame, dt, _loopFlag, _id, triggersOut); // poll network anim to see if it's finished loading yet. - if (!_relativeFlag) { + if (_blendType == AnimBlendType_Normal) { if (_networkAnim && _networkAnim->isLoaded() && _skeleton) { // loading is complete, copy & retarget animation. _anim = copyAndRetargetFromNetworkAnim(_networkAnim, _skeleton); @@ -277,6 +277,7 @@ const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, const Anim _poses.resize(_skeleton->getNumJoints()); } } else { + // an additive blend type if (_networkAnim && _networkAnim->isLoaded() && _baseNetworkAnim && _baseNetworkAnim->isLoaded() && _skeleton) { // loading is complete, copy & retarget animation. _anim = copyAndRetargetFromNetworkAnim(_networkAnim, _skeleton); @@ -293,13 +294,12 @@ const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, const Anim // copy & retarget baseAnim! auto baseAnim = copyAndRetargetFromNetworkAnim(_baseNetworkAnim, _skeleton); -//#define BLEND_ADD_ABSOLUTE - -#ifdef BLEND_ADD_ABSOLUTE - bakeAbsoluteDeltaAnim(_anim, baseAnim[(int)_baseFrame], _skeleton); -#else - bakeRelativeDeltaAnim(_anim, baseAnim[(int)_baseFrame]); -#endif + if (_blendType == AnimBlendType_AddAbsolute) { + bakeAbsoluteDeltaAnim(_anim, baseAnim[(int)_baseFrame], _skeleton); + } else { + // AnimBlendType_AddRelative + bakeRelativeDeltaAnim(_anim, baseAnim[(int)_baseFrame]); + } } } diff --git a/libraries/animation/src/AnimClip.h b/libraries/animation/src/AnimClip.h index 2ecaffb8b1..24acdcf20a 100644 --- a/libraries/animation/src/AnimClip.h +++ b/libraries/animation/src/AnimClip.h @@ -26,7 +26,7 @@ public: friend class AnimTests; AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag, bool mirrorFlag, - bool relativeFlag, const QString& baseURL, float baseFrame); + AnimBlendType blendType, const QString& baseURL, float baseFrame); virtual ~AnimClip() override; virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override; @@ -80,7 +80,7 @@ protected: bool _loopFlag; bool _mirrorFlag; float _frame; - bool _relativeFlag; + AnimBlendType _blendType; QString _baseURL; float _baseFrame; diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index c00dabfb5d..100269c55c 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -387,7 +387,7 @@ static AnimNode::Pointer loadClipNode(const QJsonObject& jsonObj, const QString& READ_FLOAT(timeScale, jsonObj, id, jsonUrl, nullptr); READ_BOOL(loopFlag, jsonObj, id, jsonUrl, nullptr); READ_OPTIONAL_BOOL(mirrorFlag, jsonObj, false); - READ_OPTIONAL_BOOL(relativeFlag, jsonObj, false); + READ_OPTIONAL_STRING(blendType, jsonObj); READ_OPTIONAL_STRING(baseURL, jsonObj); READ_OPTIONAL_FLOAT(baseFrame, jsonObj, 0.0f); @@ -402,7 +402,17 @@ static AnimNode::Pointer loadClipNode(const QJsonObject& jsonObj, const QString& auto tempUrl = QUrl(url); tempUrl = jsonUrl.resolved(tempUrl); - auto node = std::make_shared(id, tempUrl.toString(), startFrame, endFrame, timeScale, loopFlag, mirrorFlag, relativeFlag, baseURL, baseFrame); + // AJT: + AnimBlendType blendTypeEnum = AnimBlendType_Normal; // default value + if (!blendType.isEmpty()) { + blendTypeEnum = stringToAnimBlendType(blendType); + if (blendTypeEnum == AnimBlendType_NumTypes) { + qCCritical(animation) << "AnimNodeLoader, bad blendType on clip, id = " << id; + return nullptr; + } + } + + auto node = std::make_shared(id, tempUrl.toString(), startFrame, endFrame, timeScale, loopFlag, mirrorFlag, blendTypeEnum, baseURL, baseFrame); if (!startFrameVar.isEmpty()) { node->setStartFrameVar(startFrameVar); diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 2974212bf1..d5594fca6c 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -564,7 +564,7 @@ void Rig::overrideRoleAnimation(const QString& role, const QString& url, float f _origRoleAnimations[role] = node; const float REFERENCE_FRAMES_PER_SECOND = 30.0f; float timeScale = fps / REFERENCE_FRAMES_PER_SECOND; - auto clipNode = std::make_shared(role, url, firstFrame, lastFrame, timeScale, loop, false, false, "", 0.0f); + auto clipNode = std::make_shared(role, url, firstFrame, lastFrame, timeScale, loop, false, AnimBlendType_Normal, "", 0.0f); _roleAnimStates[role] = { role, url, fps, loop, firstFrame, lastFrame }; AnimNode::Pointer parent = node->getParent(); parent->replaceChild(node, clipNode); From 52ed0bcb71469ed960af59ff29d862fa67ab54a0 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 29 Aug 2019 10:17:51 -0700 Subject: [PATCH 12/46] additive blending work --- libraries/animation/src/AnimBlendLinear.cpp | 13 +++++++++++++ libraries/animation/src/AnimUtil.cpp | 15 +++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/libraries/animation/src/AnimBlendLinear.cpp b/libraries/animation/src/AnimBlendLinear.cpp index 4e8c42dad3..c066dc92eb 100644 --- a/libraries/animation/src/AnimBlendLinear.cpp +++ b/libraries/animation/src/AnimBlendLinear.cpp @@ -37,6 +37,19 @@ const AnimPoseVec& AnimBlendLinear::evaluate(const AnimVariantMap& animVars, con } else if (_children.size() == 1) { _poses = _children[0]->evaluate(animVars, context, dt, triggersOut); context.setDebugAlpha(_children[0]->getID(), parentDebugAlpha, _children[0]->getType()); + } else if (_children.size() == 2 && _blendType != AnimBlendType_Normal) { + // special case for additive blending + float alpha = glm::clamp(_alpha, 0.0f, 1.0f); + const size_t prevPoseIndex = 0; + const size_t nextPoseIndex = 1; + evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, dt); + + // for animation stack debugging + float weight2 = alpha; + float weight1 = 1.0f - weight2; + context.setDebugAlpha(_children[prevPoseIndex]->getID(), weight1 * parentDebugAlpha, _children[prevPoseIndex]->getType()); + context.setDebugAlpha(_children[nextPoseIndex]->getID(), weight2 * parentDebugAlpha, _children[nextPoseIndex]->getType()); + } else { float clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1)); size_t prevPoseIndex = glm::floor(clampedAlpha); diff --git a/libraries/animation/src/AnimUtil.cpp b/libraries/animation/src/AnimUtil.cpp index 621e714f97..e5f7cf4182 100644 --- a/libraries/animation/src/AnimUtil.cpp +++ b/libraries/animation/src/AnimUtil.cpp @@ -28,19 +28,22 @@ void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, A // additive blend void blendAdd(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result) { + + const glm::quat identity = glm::quat(); for (size_t i = 0; i < numPoses; i++) { const AnimPose& aPose = a[i]; const AnimPose& bPose = b[i]; result[i].scale() = lerp(aPose.scale(), bPose.scale(), alpha); - // adjust sign of bPose.rot() if necessary - glm::quat bTemp = bPose.rot(); - float dot = glm::dot(aPose.rot(), bTemp); - if (dot < 0.0f) { - bTemp = -bTemp; + // ensure that delta has the same "polarity" as the identity quat. + // we don't need to do a full dot product, just sign of w is sufficient. + glm::quat delta = bPose.rot(); + if (delta.w < 0.0f) { + delta = -delta; } - result[i].rot() = glm::normalize((alpha * bTemp) * aPose.rot()); + delta = glm::lerp(identity, delta, alpha); + result[i].rot() = glm::normalize(delta * aPose.rot()); result[i].trans() = aPose.trans() + (alpha * bPose.trans()); } From c814176d6a55f4875429cfe7f10c000ba9a90e61 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 29 Aug 2019 16:16:19 -0700 Subject: [PATCH 13/46] Fix initialization order of members warning --- libraries/animation/src/AnimBlendLinear.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/animation/src/AnimBlendLinear.h b/libraries/animation/src/AnimBlendLinear.h index e6fb39438f..40a20adb2c 100644 --- a/libraries/animation/src/AnimBlendLinear.h +++ b/libraries/animation/src/AnimBlendLinear.h @@ -43,8 +43,8 @@ protected: AnimPoseVec _poses; - AnimBlendType _blendType; float _alpha; + AnimBlendType _blendType; QString _alphaVar; From f91ec8fbf5a7d1dae570571c1768ab33042a714f Mon Sep 17 00:00:00 2001 From: Matt Hardcastle Date: Fri, 30 Aug 2019 08:18:00 -0700 Subject: [PATCH 14/46] Call Interface "High Fidelity" on macOS --- interface/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index c08cf47030..4bcd7aaf0f 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -117,6 +117,7 @@ if (APPLE) # configure CMake to use a custom Info.plist set_target_properties(${this_target} PROPERTIES MACOSX_BUNDLE_INFO_PLIST MacOSXBundleInfo.plist.in) + set(MACOSX_BUNDLE_BUNDLE_NAME "High Fidelity") if (PRODUCTION_BUILD) set(MACOSX_BUNDLE_GUI_IDENTIFIER com.highfidelity.interface) else () From a33bc3722d35fad462b3e105d5454fffd4d3e224 Mon Sep 17 00:00:00 2001 From: RebeccaStankus Date: Fri, 30 Aug 2019 11:10:27 -0700 Subject: [PATCH 15/46] Add feetPosition to avatar properties --- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 7 +++++++ libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 1 + libraries/avatars/src/AvatarData.h | 3 +++ libraries/avatars/src/ScriptAvatarData.cpp | 7 +++++++ libraries/avatars/src/ScriptAvatarData.h | 3 +++ 5 files changed, 21 insertions(+) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 7f363dd36f..c222853088 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1848,6 +1848,13 @@ void Avatar::setPositionViaScript(const glm::vec3& position) { updateAttitude(getWorldOrientation()); } +void Avatar::setFeetPositionViaScript(const glm::vec3& position) { + auto feetAjustment = getWorldPosition() - getWorldFeetPosition(); + auto _goToPosition = position + feetAjustment; + setWorldPosition(_goToPosition); + updateAttitude(getWorldOrientation()); +} + void Avatar::setOrientationViaScript(const glm::quat& orientation) { setWorldOrientation(orientation); updateAttitude(orientation); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 7bb15ecbf7..891f125b28 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -437,6 +437,7 @@ public: Q_INVOKABLE glm::vec3 getWorldFeetPosition(); void setPositionViaScript(const glm::vec3& position) override; + void setFeetPositionViaScript(const glm::vec3& position) override; void setOrientationViaScript(const glm::quat& orientation) override; /**jsdoc diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 59a2e2a53e..5857a7dcaa 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -488,6 +488,7 @@ class AvatarData : public QObject, public SpatiallyNestable { // IMPORTANT: The JSDoc for the following properties should be copied to MyAvatar.h and ScriptableAvatar.h. /* * @property {Vec3} position - The position of the avatar. + * @property {Vec3} feetPosition - The feet position of the avatar. * @property {number} scale=1.0 - The scale of the avatar. The value can be set to anything between 0.005 and * 1000.0. When the scale value is fetched, it may temporarily be further limited by the domain's settings. * @property {number} density - The density of the avatar in kg/m3. The density is used to work out its mass in @@ -536,6 +537,7 @@ class AvatarData : public QObject, public SpatiallyNestable { * Read-only. */ Q_PROPERTY(glm::vec3 position READ getWorldPosition WRITE setPositionViaScript) + Q_PROPERTY(glm::vec3 feetPosition READ getWorldFeetPosition WRITE setFeetPositionViaScript) Q_PROPERTY(float scale READ getDomainLimitedScale WRITE setTargetScale) Q_PROPERTY(float density READ getDensity) Q_PROPERTY(glm::vec3 handPosition READ getHandPosition WRITE setHandPosition) @@ -629,6 +631,7 @@ public: void setBodyRoll(float bodyRoll); virtual void setPositionViaScript(const glm::vec3& position); + virtual void setFeetPositionViaScript(const glm::vec3& position); virtual void setOrientationViaScript(const glm::quat& orientation); virtual void updateAttitude(const glm::quat& orientation) {} diff --git a/libraries/avatars/src/ScriptAvatarData.cpp b/libraries/avatars/src/ScriptAvatarData.cpp index 18717c8ca3..3228445f81 100644 --- a/libraries/avatars/src/ScriptAvatarData.cpp +++ b/libraries/avatars/src/ScriptAvatarData.cpp @@ -31,6 +31,13 @@ glm::vec3 ScriptAvatarData::getPosition() const { return glm::vec3(); } } +glm::vec3 ScriptAvatarData::getFeetPosition() const { + if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { + return sharedAvatarData->getWorldFeetPosition(); + } else { + return glm::vec3(); + } +} float ScriptAvatarData::getTargetScale() const { if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { return sharedAvatarData->getTargetScale(); diff --git a/libraries/avatars/src/ScriptAvatarData.h b/libraries/avatars/src/ScriptAvatarData.h index 9c5c2c6918..5b962d23df 100644 --- a/libraries/avatars/src/ScriptAvatarData.h +++ b/libraries/avatars/src/ScriptAvatarData.h @@ -20,6 +20,7 @@ * Information about an avatar. * @typedef {object} AvatarData * @property {Vec3} position - The avatar's position. + * @property {Vec3} feetPosition - The avatar's feet position. * @property {number} scale - The target scale of the avatar without any restrictions on permissible values imposed by the * domain. * @property {Vec3} handPosition - A user-defined hand position, in world coordinates. The position moves with the avatar but @@ -70,6 +71,7 @@ class ScriptAvatarData : public QObject { // PHYSICAL PROPERTIES: POSITION AND ORIENTATION // Q_PROPERTY(glm::vec3 position READ getPosition) + Q_PROPERTY(glm::vec3 feetPosition READ getFeetPosition) Q_PROPERTY(float scale READ getTargetScale) Q_PROPERTY(glm::vec3 handPosition READ getHandPosition) Q_PROPERTY(float bodyPitch READ getBodyPitch) @@ -124,6 +126,7 @@ public: // PHYSICAL PROPERTIES: POSITION AND ORIENTATION // glm::vec3 getPosition() const; + glm::vec3 getFeetPosition() const; float getTargetScale() const; glm::vec3 getHandPosition() const; float getBodyPitch() const; From 5fadfa52757f261eb2f36e4115724e3ea29e4b6a Mon Sep 17 00:00:00 2001 From: RebeccaStankus Date: Fri, 30 Aug 2019 13:41:46 -0700 Subject: [PATCH 16/46] Updated property in MyAvatar.h --- interface/src/avatar/MyAvatar.h | 2 ++ libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 7 ------- libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 1 - libraries/avatars/src/AvatarData.h | 3 --- libraries/avatars/src/ScriptAvatarData.cpp | 7 ------- libraries/avatars/src/ScriptAvatarData.h | 3 --- 6 files changed, 2 insertions(+), 21 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index bb6f036533..ef7af9abae 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -154,6 +154,7 @@ class MyAvatar : public Avatar { * * @property {Vec3} qmlPosition - A synonym for position for use by QML. * + * @property {Vec3} feetPosition - The position of the avatar's feet. * @property {boolean} shouldRenderLocally=true - If true then your avatar is rendered for you in Interface, * otherwise it is not rendered for you (but it is still rendered for other users). * @property {Vec3} motorVelocity=Vec3.ZERO - The target velocity of your avatar to be achieved by a scripted motor. @@ -340,6 +341,7 @@ class MyAvatar : public Avatar { Q_PROPERTY(QVector3D qmlPosition READ getQmlPosition) QVector3D getQmlPosition() { auto p = getWorldPosition(); return QVector3D(p.x, p.y, p.z); } + Q_PROPERTY(glm::vec3 feetPosition READ getWorldFeetPosition WRITE goToFeetLocation) Q_PROPERTY(bool shouldRenderLocally READ getShouldRenderLocally WRITE setShouldRenderLocally) Q_PROPERTY(glm::vec3 motorVelocity READ getScriptedMotorVelocity WRITE setScriptedMotorVelocity) Q_PROPERTY(float motorTimescale READ getScriptedMotorTimescale WRITE setScriptedMotorTimescale) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index c222853088..7f363dd36f 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1848,13 +1848,6 @@ void Avatar::setPositionViaScript(const glm::vec3& position) { updateAttitude(getWorldOrientation()); } -void Avatar::setFeetPositionViaScript(const glm::vec3& position) { - auto feetAjustment = getWorldPosition() - getWorldFeetPosition(); - auto _goToPosition = position + feetAjustment; - setWorldPosition(_goToPosition); - updateAttitude(getWorldOrientation()); -} - void Avatar::setOrientationViaScript(const glm::quat& orientation) { setWorldOrientation(orientation); updateAttitude(orientation); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 891f125b28..7bb15ecbf7 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -437,7 +437,6 @@ public: Q_INVOKABLE glm::vec3 getWorldFeetPosition(); void setPositionViaScript(const glm::vec3& position) override; - void setFeetPositionViaScript(const glm::vec3& position) override; void setOrientationViaScript(const glm::quat& orientation) override; /**jsdoc diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 5857a7dcaa..59a2e2a53e 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -488,7 +488,6 @@ class AvatarData : public QObject, public SpatiallyNestable { // IMPORTANT: The JSDoc for the following properties should be copied to MyAvatar.h and ScriptableAvatar.h. /* * @property {Vec3} position - The position of the avatar. - * @property {Vec3} feetPosition - The feet position of the avatar. * @property {number} scale=1.0 - The scale of the avatar. The value can be set to anything between 0.005 and * 1000.0. When the scale value is fetched, it may temporarily be further limited by the domain's settings. * @property {number} density - The density of the avatar in kg/m3. The density is used to work out its mass in @@ -537,7 +536,6 @@ class AvatarData : public QObject, public SpatiallyNestable { * Read-only. */ Q_PROPERTY(glm::vec3 position READ getWorldPosition WRITE setPositionViaScript) - Q_PROPERTY(glm::vec3 feetPosition READ getWorldFeetPosition WRITE setFeetPositionViaScript) Q_PROPERTY(float scale READ getDomainLimitedScale WRITE setTargetScale) Q_PROPERTY(float density READ getDensity) Q_PROPERTY(glm::vec3 handPosition READ getHandPosition WRITE setHandPosition) @@ -631,7 +629,6 @@ public: void setBodyRoll(float bodyRoll); virtual void setPositionViaScript(const glm::vec3& position); - virtual void setFeetPositionViaScript(const glm::vec3& position); virtual void setOrientationViaScript(const glm::quat& orientation); virtual void updateAttitude(const glm::quat& orientation) {} diff --git a/libraries/avatars/src/ScriptAvatarData.cpp b/libraries/avatars/src/ScriptAvatarData.cpp index 3228445f81..18717c8ca3 100644 --- a/libraries/avatars/src/ScriptAvatarData.cpp +++ b/libraries/avatars/src/ScriptAvatarData.cpp @@ -31,13 +31,6 @@ glm::vec3 ScriptAvatarData::getPosition() const { return glm::vec3(); } } -glm::vec3 ScriptAvatarData::getFeetPosition() const { - if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { - return sharedAvatarData->getWorldFeetPosition(); - } else { - return glm::vec3(); - } -} float ScriptAvatarData::getTargetScale() const { if (AvatarSharedPointer sharedAvatarData = _avatarData.lock()) { return sharedAvatarData->getTargetScale(); diff --git a/libraries/avatars/src/ScriptAvatarData.h b/libraries/avatars/src/ScriptAvatarData.h index 5b962d23df..9c5c2c6918 100644 --- a/libraries/avatars/src/ScriptAvatarData.h +++ b/libraries/avatars/src/ScriptAvatarData.h @@ -20,7 +20,6 @@ * Information about an avatar. * @typedef {object} AvatarData * @property {Vec3} position - The avatar's position. - * @property {Vec3} feetPosition - The avatar's feet position. * @property {number} scale - The target scale of the avatar without any restrictions on permissible values imposed by the * domain. * @property {Vec3} handPosition - A user-defined hand position, in world coordinates. The position moves with the avatar but @@ -71,7 +70,6 @@ class ScriptAvatarData : public QObject { // PHYSICAL PROPERTIES: POSITION AND ORIENTATION // Q_PROPERTY(glm::vec3 position READ getPosition) - Q_PROPERTY(glm::vec3 feetPosition READ getFeetPosition) Q_PROPERTY(float scale READ getTargetScale) Q_PROPERTY(glm::vec3 handPosition READ getHandPosition) Q_PROPERTY(float bodyPitch READ getBodyPitch) @@ -126,7 +124,6 @@ public: // PHYSICAL PROPERTIES: POSITION AND ORIENTATION // glm::vec3 getPosition() const; - glm::vec3 getFeetPosition() const; float getTargetScale() const; glm::vec3 getHandPosition() const; float getBodyPitch() const; From a5923ac9aa3bd77ba2717d10fc8c552d584fb81f Mon Sep 17 00:00:00 2001 From: amerhifi Date: Fri, 30 Aug 2019 14:15:03 -0700 Subject: [PATCH 17/46] adding unpinnable options to any dlg process and main app so that user cannot accidentaly pin the launcher --- launchers/win32/LauncherDlg.cpp | 18 +++++++++++++++++- launchers/win32/LauncherDlg.h | 1 + launchers/win32/LauncherUtils.cpp | 3 ++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/launchers/win32/LauncherDlg.cpp b/launchers/win32/LauncherDlg.cpp index 9cf21e9c8c..5d8db860e5 100644 --- a/launchers/win32/LauncherDlg.cpp +++ b/launchers/win32/LauncherDlg.cpp @@ -13,7 +13,10 @@ #include "LauncherApp.h" #include "LauncherDlg.h" +#include +#include #include + #pragma comment(lib, "d2d1") #ifdef _DEBUG @@ -84,7 +87,7 @@ END_MESSAGE_MAP() BOOL CLauncherDlg::OnInitDialog() { CDialog::OnInitDialog(); - + MarkWindowAsUnpinnable(); SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon @@ -129,6 +132,19 @@ BOOL CLauncherDlg::OnInitDialog() { return TRUE; } +void CLauncherDlg::MarkWindowAsUnpinnable() { + HWND hwnd = AfxGetMainWnd()->m_hWnd; + IPropertyStore* pps; + HRESULT hr = SHGetPropertyStoreForWindow(hwnd, IID_PPV_ARGS(&pps)); + if (SUCCEEDED(hr)) { + PROPVARIANT var; + var.vt = VT_BOOL; + var.boolVal = VARIANT_TRUE; + hr = pps->SetValue(PKEY_AppUserModel_PreventPinning, var); + pps->Release(); + } +} + POINT CLauncherDlg::getMouseCoords(MSG* pMsg) { POINT pos; pos.x = (int)(short)LOWORD(pMsg->lParam); diff --git a/launchers/win32/LauncherDlg.h b/launchers/win32/LauncherDlg.h index d25618c554..b0ccbfa04f 100644 --- a/launchers/win32/LauncherDlg.h +++ b/launchers/win32/LauncherDlg.h @@ -59,6 +59,7 @@ protected: BOOL getTextFormat(int ResID, TextFormat& formatOut); void showWindows(std::vector windows, bool show); POINT getMouseCoords(MSG* pMsg); + void MarkWindowAsUnpinnable(); bool _isConsoleRunning { false }; diff --git a/launchers/win32/LauncherUtils.cpp b/launchers/win32/LauncherUtils.cpp index ef23073ca5..cd0c15ccc3 100644 --- a/launchers/win32/LauncherUtils.cpp +++ b/launchers/win32/LauncherUtils.cpp @@ -150,7 +150,8 @@ BOOL LauncherUtils::launchApplication(LPCWSTR lpApplicationName, LPTSTR cmdArgs) ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); - + + si.dwFlags = STARTF_TITLEISAPPID | STARTF_PREVENTPINNING; // start the program up BOOL success = CreateProcess( lpApplicationName, // the path From 08ca702c829babcd194d3220216cd7b6249b473c Mon Sep 17 00:00:00 2001 From: amerhifi Date: Fri, 30 Aug 2019 14:16:11 -0700 Subject: [PATCH 18/46] remove space --- launchers/win32/LauncherDlg.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/launchers/win32/LauncherDlg.cpp b/launchers/win32/LauncherDlg.cpp index 5d8db860e5..386d2747d6 100644 --- a/launchers/win32/LauncherDlg.cpp +++ b/launchers/win32/LauncherDlg.cpp @@ -16,7 +16,6 @@ #include #include #include - #pragma comment(lib, "d2d1") #ifdef _DEBUG From cba258b8c4d2219590a3e9f3f2d61b3135bf9777 Mon Sep 17 00:00:00 2001 From: Matt Hardcastle Date: Fri, 30 Aug 2019 11:53:59 -0700 Subject: [PATCH 19/46] Error handling for Launcher's update Before this change the update helper app in the Mac version of HQ Launcher silently ignored errors. This change adds error handling to aid troubleshooting. --- launchers/darwin/src/updater/main.m | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/launchers/darwin/src/updater/main.m b/launchers/darwin/src/updater/main.m index 7c7ace6f70..f8fe5a598c 100644 --- a/launchers/darwin/src/updater/main.m +++ b/launchers/darwin/src/updater/main.m @@ -21,15 +21,39 @@ int main(int argc, char const* argv[]) { for (int index = 0; index < argc; index++) { NSLog(@"argv at index %d = %s", index, argv[index]); } + + NSError *error = nil; + NSString* oldLauncher = [NSString stringWithUTF8String:argv[1]]; NSString* newLauncher = [NSString stringWithUTF8String:argv[2]]; NSURL* destinationUrl = [UpdaterHelper NSStringToNSURL:newLauncher]; NSFileManager* fileManager = [NSFileManager defaultManager]; - [fileManager replaceItemAtURL:[UpdaterHelper NSStringToNSURL:oldLauncher] withItemAtURL:[UpdaterHelper NSStringToNSURL:newLauncher] backupItemName:nil options:NSFileManagerItemReplacementUsingNewMetadataOnly resultingItemURL:&destinationUrl error:nil]; + [fileManager replaceItemAtURL:[UpdaterHelper NSStringToNSURL:oldLauncher] + withItemAtURL:[UpdaterHelper NSStringToNSURL:newLauncher] + backupItemName:nil + options:NSFileManagerItemReplacementUsingNewMetadataOnly + resultingItemURL:&destinationUrl + error:&error]; + if (error != nil) { + NSLog(@"couldn't update launcher: %@", error); + return 1; + } + NSWorkspace* workspace = [NSWorkspace sharedWorkspace]; NSURL* applicationURL = [UpdaterHelper NSStringToNSURL: [oldLauncher stringByAppendingString: @"/Contents/MacOS/HQ Launcher"]]; NSArray* arguments =@[]; NSLog(@"Launcher agruments: %@", arguments); - [workspace launchApplicationAtURL:applicationURL options:NSWorkspaceLaunchNewInstance configuration:[NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments] error:nil]; + + NSDictionary *configuration = [NSDictionary dictionaryWithObject:arguments + forKey:NSWorkspaceLaunchConfigurationArguments]; + [workspace launchApplicationAtURL:applicationURL + options:NSWorkspaceLaunchNewInstance + configuration:configuration + error:&error]; + if (error != nil) { + NSLog(@"couldn't start launcher: %@", error); + return 1; + } + return 0; } From a34a533c07dcaa99c2dabd88dad4376263c31113 Mon Sep 17 00:00:00 2001 From: RebeccaStankus Date: Tue, 3 Sep 2019 10:04:11 -0700 Subject: [PATCH 20/46] Added defaults for some params --- interface/src/avatar/MyAvatar.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index ef7af9abae..0108fb5eda 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1940,9 +1940,8 @@ public slots: * @param {boolean} [shouldFaceLocation=false] - Set to true to position the avatar a short distance away from * the new position and orientate the avatar to face the position. */ - void goToFeetLocation(const glm::vec3& newPosition, - bool hasOrientation, const glm::quat& newOrientation, - bool shouldFaceLocation); + void goToFeetLocation(const glm::vec3& newPosition, bool hasOrientation = false, + const glm::quat& newOrientation = glm::quat(), bool shouldFaceLocation = false); /**jsdoc * Moves the avatar to a new position and/or orientation in the domain. From 86b635d80a464a08f422d31c8e9718a59b66df92 Mon Sep 17 00:00:00 2001 From: Clement Date: Tue, 3 Sep 2019 13:40:02 -0700 Subject: [PATCH 21/46] Add context object to timer connection --- assignment-client/src/avatars/MixerAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/MixerAvatar.cpp b/assignment-client/src/avatars/MixerAvatar.cpp index 29f7e9ebd2..9be93dad40 100644 --- a/assignment-client/src/avatars/MixerAvatar.cpp +++ b/assignment-client/src/avatars/MixerAvatar.cpp @@ -33,7 +33,7 @@ MixerAvatar::MixerAvatar() { _challengeTimer.setSingleShot(true); _challengeTimer.setInterval(CHALLENGE_TIMEOUT_MS); - _challengeTimer.callOnTimeout([this]() { + _challengeTimer.callOnTimeout(this, [this]() { if (_verifyState == challengeClient) { _pendingEvent = false; _verifyState = verificationFailed; From 03c5dfad3dc7809d77a9391288ed1dad2be3fa38 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 3 Sep 2019 16:28:32 -0700 Subject: [PATCH 22/46] propagating the Bloom on off correctly and fixing the problem where Luci prevents from seeing the zone and finally, update the luci.js with the newer version --- libraries/render-utils/src/BloomEffect.cpp | 3 +- libraries/render-utils/src/BloomEffect.h | 13 +- .../render-utils/src/RenderDeferredTask.cpp | 2 +- .../utilities/render/deferredLighting.qml | 103 -------------- scripts/developer/utilities/render/luci.js | 128 +++++++++--------- .../developer/utilities/render/luci/Bloom.qml | 12 +- .../utilities/render/luci/BoundingBoxes.qml | 2 +- scripts/developer/utilities/render/luci2.js | 84 ------------ 8 files changed, 83 insertions(+), 264 deletions(-) delete mode 100644 scripts/developer/utilities/render/deferredLighting.qml delete mode 100644 scripts/developer/utilities/render/luci2.js diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index f83c05cff8..0c499a9d34 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -35,12 +35,13 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons const auto frameTransform = inputs.get0(); const auto inputFrameBuffer = inputs.get1(); const auto bloomFrame = inputs.get2(); + const auto lightingModel = inputs.get3(); const auto& bloomStage = renderContext->_scene->getStage(); graphics::BloomPointer bloom; if (bloomStage && bloomFrame->_blooms.size()) { bloom = bloomStage->getBloom(bloomFrame->_blooms.front()); } - if (!bloom) { + if (!bloom || (lightingModel && !lightingModel->isBloomEnabled())) { renderContext->taskFlow.abortTask(); return; } diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h index 9c170e771a..47558affd9 100644 --- a/libraries/render-utils/src/BloomEffect.h +++ b/libraries/render-utils/src/BloomEffect.h @@ -17,6 +17,7 @@ #include "BloomStage.h" #include "DeferredFrameTransform.h" +#include "LightingModel.h" class BloomConfig : public render::Task::Config { Q_OBJECT @@ -28,7 +29,7 @@ class BloomThresholdConfig : public render::Job::Config { class BloomThreshold { public: - using Inputs = render::VaryingSet3; + using Inputs = render::VaryingSet4; using Outputs = render::VaryingSet3; using Config = BloomThresholdConfig; using JobModel = render::Job::ModelIO; @@ -131,14 +132,14 @@ private: class BloomEffect { public: - using Inputs = render::VaryingSet3; + using Inputs = render::VaryingSet4; using Config = BloomConfig; - using JobModel = render::Task::ModelI; + using JobModel = render::Task::ModelI; - BloomEffect(); + BloomEffect(); - void configure(const Config& config); - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); + void configure(const Config& config); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); }; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index cfcc6777d6..c506f22bc7 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -227,7 +227,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("Antialiasing", antialiasingInputs); // Add bloom - const auto bloomInputs = BloomEffect::Inputs(deferredFrameTransform, lightingFramebuffer, bloomFrame).asVarying(); + const auto bloomInputs = BloomEffect::Inputs(deferredFrameTransform, lightingFramebuffer, bloomFrame, lightingModel).asVarying(); task.addJob("Bloom", bloomInputs); const auto destFramebuffer = static_cast(nullptr); diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml deleted file mode 100644 index f2891ddc55..0000000000 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ /dev/null @@ -1,103 +0,0 @@ -// -// deferredLighting.qml -// -// Created by Sam Gateau on 6/6/2016 -// 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 "configSlider" -import "luci" - -Rectangle { - HifiConstants { id: hifi;} - id: render; - anchors.margins: hifi.dimensions.contentMargin.x - - color: hifi.colors.baseGray; - property var mainViewTask: Render.getConfig("RenderMainView") - - Column { - spacing: 5 - anchors.left: parent.left - anchors.right: parent.right - anchors.margins: hifi.dimensions.contentMargin.x - - - HifiControls.Label { - text: "Shading" - } - ShadingModel {} - - Separator {} - ToneMapping {} - - Separator {} - Column { - anchors.left: parent.left - anchors.right: parent.right - spacing: 5 - Repeater { - model: [ "MSAA:PreparePrimaryBufferForward:numSamples:4:1" - ] - ConfigSlider { - label: qsTr(modelData.split(":")[0]) - integral: true - config: render.mainViewTask.getConfig(modelData.split(":")[1]) - property: modelData.split(":")[2] - max: modelData.split(":")[3] - min: modelData.split(":")[4] - - anchors.left: parent.left - anchors.right: parent.right - } - } - } - Separator {} - Framebuffer {} - - Separator {} - BoundingBoxes { - - } - Separator {} - Row { - HifiControls.Button { - text: "Engine" - // activeFocusOnPress: false - onClicked: { - sendToScript({method: "openEngineView"}); - } - } - HifiControls.Button { - text: "LOD" - // activeFocusOnPress: false - onClicked: { - sendToScript({method: "openEngineLODView"}); - } - } - HifiControls.Button { - text: "Cull" - // activeFocusOnPress: false - onClicked: { - sendToScript({method: "openCullInspectorView"}); - } - } - } - Row { - HifiControls.Button { - text: "Material" - onClicked: { - sendToScript({method: "openMaterialInspectorView"}); - } - } - } - } -} diff --git a/scripts/developer/utilities/render/luci.js b/scripts/developer/utilities/render/luci.js index fd84f55e65..e2e5523ccd 100644 --- a/scripts/developer/utilities/render/luci.js +++ b/scripts/developer/utilities/render/luci.js @@ -1,80 +1,84 @@ -"use strict"; - -// -// Luci.js -// tablet-engine app -// -// 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 -// +var MaterialInspector = Script.require('./materialInspector.js'); +var Page = Script.require('./luci/Page.js'); -(function() { - var AppUi = Script.require('appUi'); - - var MaterialInspector = Script.require('./materialInspector.js'); - var Page = Script.require('./luci/Page.js'); - var moveDebugCursor = false; - var onMousePressEvent = function (e) { - if (e.isMiddleButton) { - moveDebugCursor = true; - setDebugCursor(e.x, e.y); - } - }; - Controller.mousePressEvent.connect(onMousePressEvent); - - var onMouseReleaseEvent = function () { - moveDebugCursor = false; - }; - Controller.mouseReleaseEvent.connect(onMouseReleaseEvent); - - var onMouseMoveEvent = function (e) { - if (moveDebugCursor) { - setDebugCursor(e.x, e.y); - } - }; - Controller.mouseMoveEvent.connect(onMouseMoveEvent); - - function setDebugCursor(x, y) { - var nx = 2.0 * (x / Window.innerWidth) - 1.0; - var ny = 1.0 - 2.0 * ((y) / (Window.innerHeight)); - - Render.getConfig("RenderMainView").getConfig("DebugDeferredBuffer").size = { x: nx, y: ny, z: 1.0, w: 1.0 }; - } +function openView() { + //window.closed.connect(function() { Script.stop(); }); var pages = new Pages(); - - pages.addPage('openEngineLODView', 'Render LOD', '../lod.qml', 300, 400); - pages.addPage('openCullInspectorView', 'Cull Inspector', '../luci/Culling.qml', 300, 400); - pages.addPage('openMaterialInspectorView', 'Material Inspector', '../materialInspector.qml', 300, 400, MaterialInspector.setWindow); - function fromQml(message) { if (pages.open(message.method)) { return; } } - var ui; - function startup() { - ui = new AppUi({ - buttonName: "LUCI", - home: Script.resolvePath("deferredLighting.qml"), - additionalAppScreens : Script.resolvePath("engineInspector.qml"), - onMessage: fromQml, - normalButton: Script.resolvePath("../../../system/assets/images/luci-i.svg"), - activeButton: Script.resolvePath("../../../system/assets/images/luci-a.svg") - }); + var luciWindow + function openLuciWindow(window) { + if (luciWindow !== undefined) { + activeWindow.fromQml.disconnect(fromQml); + } + if (window !== undefined) { + window.fromQml.connect(fromQml); + } + luciWindow = window; + + + var moveDebugCursor = false; + var onMousePressEvent = function (e) { + if (e.isMiddleButton) { + moveDebugCursor = true; + setDebugCursor(e.x, e.y); + } + }; + Controller.mousePressEvent.connect(onMousePressEvent); + + var onMouseReleaseEvent = function () { + moveDebugCursor = false; + }; + Controller.mouseReleaseEvent.connect(onMouseReleaseEvent); + + var onMouseMoveEvent = function (e) { + if (moveDebugCursor) { + setDebugCursor(e.x, e.y); + } + }; + Controller.mouseMoveEvent.connect(onMouseMoveEvent); + + function setDebugCursor(x, y) { + var nx = 2.0 * (x / Window.innerWidth) - 1.0; + var ny = 1.0 - 2.0 * ((y) / (Window.innerHeight)); + + Render.getConfig("RenderMainView").getConfig("DebugDeferredBuffer").size = { x: nx, y: ny, z: 1.0, w: 1.0 }; + } + } - startup(); - Script.scriptEnding.connect(function () { + + function closeLuciWindow() { + if (luciWindow !== undefined) { + activeWindow.fromQml.disconnect(fromQml); + } + luciWindow = {}; + Controller.mousePressEvent.disconnect(onMousePressEvent); Controller.mouseReleaseEvent.disconnect(onMouseReleaseEvent); Controller.mouseMoveEvent.disconnect(onMouseMoveEvent); pages.clear(); - }); -}()); + } + + pages.addPage('Luci', 'Luci', '../luci.qml', 300, 420, openLuciWindow, closeLuciWindow); + pages.addPage('openEngineInspectorView', 'Render Engine Inspector', '../engineInspector.qml', 300, 400); + pages.addPage('openEngineLODView', 'Render LOD', '../lod.qml', 300, 400); + pages.addPage('openMaterialInspectorView', 'Material Inspector', '../materialInspector.qml', 300, 400, MaterialInspector.setWindow, MaterialInspector.setWindow); + + pages.open('Luci'); + + + return pages; +} + + +openView(); + diff --git a/scripts/developer/utilities/render/luci/Bloom.qml b/scripts/developer/utilities/render/luci/Bloom.qml index 0edaea702b..7db75d94ef 100644 --- a/scripts/developer/utilities/render/luci/Bloom.qml +++ b/scripts/developer/utilities/render/luci/Bloom.qml @@ -18,6 +18,12 @@ Column { property var config: Render.getConfig("RenderMainView.DebugBloom") + Prop.PropBool { + label: "Apply Bloom" + object: Render.getConfig("RenderMainView.LightingModel") + property: "enableBloom" + } + function setDebugMode(mode) { console.log("Bloom mode is " + mode) bloom.config.enabled = (mode != 0); @@ -38,11 +44,5 @@ Column { valueVarSetter: function (mode) { bloom.setDebugMode(mode) } } - - Prop.PropBool { - label: "Debug Bloom Buffer" - object: Render.getConfig("RenderMainView.Bloom") - property: "enabled" - } } diff --git a/scripts/developer/utilities/render/luci/BoundingBoxes.qml b/scripts/developer/utilities/render/luci/BoundingBoxes.qml index 636267729c..6b34e41b4c 100644 --- a/scripts/developer/utilities/render/luci/BoundingBoxes.qml +++ b/scripts/developer/utilities/render/luci/BoundingBoxes.qml @@ -54,7 +54,7 @@ Column { Prop.PropCheckBox { text: "Zones" checked: root.mainViewTask.getConfig("DrawZones")["enabled"] - onCheckedChanged: { root.mainViewTask.getConfig("ZoneRenderer")["enabled"] = checked; root.mainViewTask.getConfig("DrawZones")["enabled"] = checked; } + onCheckedChanged: { root.mainViewTask.getConfig("DrawZones")["enabled"] = checked; } } } Column { diff --git a/scripts/developer/utilities/render/luci2.js b/scripts/developer/utilities/render/luci2.js deleted file mode 100644 index e2e5523ccd..0000000000 --- a/scripts/developer/utilities/render/luci2.js +++ /dev/null @@ -1,84 +0,0 @@ - - -var MaterialInspector = Script.require('./materialInspector.js'); -var Page = Script.require('./luci/Page.js'); - - -function openView() { - //window.closed.connect(function() { Script.stop(); }); - - - var pages = new Pages(); - function fromQml(message) { - if (pages.open(message.method)) { - return; - } - } - - var luciWindow - function openLuciWindow(window) { - if (luciWindow !== undefined) { - activeWindow.fromQml.disconnect(fromQml); - } - if (window !== undefined) { - window.fromQml.connect(fromQml); - } - luciWindow = window; - - - var moveDebugCursor = false; - var onMousePressEvent = function (e) { - if (e.isMiddleButton) { - moveDebugCursor = true; - setDebugCursor(e.x, e.y); - } - }; - Controller.mousePressEvent.connect(onMousePressEvent); - - var onMouseReleaseEvent = function () { - moveDebugCursor = false; - }; - Controller.mouseReleaseEvent.connect(onMouseReleaseEvent); - - var onMouseMoveEvent = function (e) { - if (moveDebugCursor) { - setDebugCursor(e.x, e.y); - } - }; - Controller.mouseMoveEvent.connect(onMouseMoveEvent); - - function setDebugCursor(x, y) { - var nx = 2.0 * (x / Window.innerWidth) - 1.0; - var ny = 1.0 - 2.0 * ((y) / (Window.innerHeight)); - - Render.getConfig("RenderMainView").getConfig("DebugDeferredBuffer").size = { x: nx, y: ny, z: 1.0, w: 1.0 }; - } - - } - - function closeLuciWindow() { - if (luciWindow !== undefined) { - activeWindow.fromQml.disconnect(fromQml); - } - luciWindow = {}; - - Controller.mousePressEvent.disconnect(onMousePressEvent); - Controller.mouseReleaseEvent.disconnect(onMouseReleaseEvent); - Controller.mouseMoveEvent.disconnect(onMouseMoveEvent); - pages.clear(); - } - - pages.addPage('Luci', 'Luci', '../luci.qml', 300, 420, openLuciWindow, closeLuciWindow); - pages.addPage('openEngineInspectorView', 'Render Engine Inspector', '../engineInspector.qml', 300, 400); - pages.addPage('openEngineLODView', 'Render LOD', '../lod.qml', 300, 400); - pages.addPage('openMaterialInspectorView', 'Material Inspector', '../materialInspector.qml', 300, 400, MaterialInspector.setWindow, MaterialInspector.setWindow); - - pages.open('Luci'); - - - return pages; -} - - -openView(); - From df0eb901a22df788dd7c27d00747d42fdf8792e5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 3 Sep 2019 17:01:03 -0700 Subject: [PATCH 23/46] REverting the change in the jittering sequence length --- libraries/render-utils/src/AntialiasingEffect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index 1a760a8b06..fc25343751 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -60,7 +60,7 @@ class JitterSample { public: enum { - SEQUENCE_LENGTH = 32 + SEQUENCE_LENGTH = 64 }; using Config = JitterSampleConfig; From 44e518f5a14c319e4aa2c57ca030bdaa2880088e Mon Sep 17 00:00:00 2001 From: milad Date: Tue, 3 Sep 2019 18:06:25 -0700 Subject: [PATCH 24/46] working fix --- .../settingsApp/general/General.qml | 9 ++-- .../simplifiedEmote/simplifiedEmote.js | 25 +++++------ .../ui/qml/SimplifiedEmoteIndicator.qml | 43 ++++++++++++++----- 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml index 9e58a0aa98..2260bc312a 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml @@ -136,17 +136,18 @@ Flickable { Layout.preferredHeight: 18 Layout.preferredWidth: parent.width labelTextOn: "Show Emote UI" - checked: Settings.getValue("simplifiedUI/emoteIndicatorVisible", true) + checked: Settings.getValue("simplifiedUI/showEmoteUI", true) onClicked: { - var currentSetting = Settings.getValue("simplifiedUI/emoteIndicatorVisible", true); - Settings.setValue("simplifiedUI/emoteIndicatorVisible", !currentSetting); + console.log("CLICKED GENERAL SETTING") + var currentSetting = Settings.getValue("simplifiedUI/showEmoteUI", true); + Settings.setValue("simplifiedUI/showEmoteUI", !currentSetting); } Connections { target: Settings onValueChanged: { - if (setting === "simplifiedUI/emoteIndicatorVisible") { + if (setting === "simplifiedUI/showEmoteUI") { emoteSwitch.checked = value; } } diff --git a/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js b/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js index cd6c80dd64..6697807b67 100644 --- a/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js +++ b/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js @@ -425,7 +425,7 @@ function onGeometryChanged(rect) { function onWindowMinimizedChanged(isMinimized) { if (isMinimized) { handleEmoteIndicatorVisibleChanged(false); - } else if (!HMD.active && Settings.getValue("simplifiedUI/emoteIndicatorVisible", true)) { + } else if (!HMD.active) { handleEmoteIndicatorVisibleChanged(true); } } @@ -520,8 +520,8 @@ function showEmoteAppBar() { } -function handleEmoteIndicatorVisibleChanged(newValue) { - if (newValue && !emoteAppBarWindow) { +function handleEmoteIndicatorVisibleChanged(shouldBeVisible) { + if (shouldBeVisible && !emoteAppBarWindow) { showEmoteAppBar(); } else if (emoteAppBarWindow) { emoteAppBarWindow.fromQml.disconnect(onMessageFromEmoteAppBar); @@ -530,11 +530,14 @@ function handleEmoteIndicatorVisibleChanged(newValue) { } } - -function onSettingsValueChanged(settingName, newValue) { - if (settingName === "simplifiedUI/emoteIndicatorVisible") { - handleEmoteIndicatorVisibleChanged(newValue); - } +function handleEmoteIndictaorTrayDisabledChanged(shouldBeDisabled) { + emoteAppBarWindow.sendToQml({ + "source": "simplifiedEmote.js", + "method": "updateTrayDisabled", + "data": { + "shouldBeDisabled": shouldBeDisabled + } + }); } @@ -545,7 +548,7 @@ function onDisplayModeChanged(isHMDMode) { if (isHMDMode) { handleEmoteIndicatorVisibleChanged(false); - } else if (Settings.getValue("simplifiedUI/emoteIndicatorVisible", true)) { + } else { handleEmoteIndicatorVisibleChanged(true); } } @@ -584,12 +587,11 @@ function init() { Window.minimizedChanged.connect(onWindowMinimizedChanged); Window.geometryChanged.connect(onGeometryChanged); - Settings.valueChanged.connect(onSettingsValueChanged); HMD.displayModeChanged.connect(onDisplayModeChanged); emojiAPI.startup(); getSounds(); - handleEmoteIndicatorVisibleChanged(Settings.getValue("simplifiedUI/emoteIndicatorVisible", true)); + handleEmoteIndicatorVisibleChanged(true); Controller.keyPressEvent.connect(keyPressHandler); Controller.keyReleaseEvent.connect(keyReleaseHandler); @@ -621,7 +623,6 @@ function shutdown() { Window.minimizedChanged.disconnect(onWindowMinimizedChanged); Window.geometryChanged.disconnect(onGeometryChanged); - Settings.valueChanged.disconnect(onSettingsValueChanged); HMD.displayModeChanged.disconnect(onDisplayModeChanged); if (keyPressSignalsConnected) { diff --git a/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml b/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml index a401feec12..b178b9eef5 100644 --- a/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml +++ b/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml @@ -21,22 +21,33 @@ Rectangle { id: root color: simplifiedUI.colors.white anchors.fill: parent - + Component.onCompleted: { + console.log("\n\n\n\n\n\n\n COMPLETED @@2 \n\n\n\n\n\n\n\n"); + } property int originalWidth: 48 property int expandedWidth: mainEmojiContainer.width + drawerContainer.width // For the below to work, the Repeater's Item's second child must be the individual button's `MouseArea` - property int requestedWidth: (drawerContainer.keepDrawerExpanded || - emoteIndicatorMouseArea.containsMouse || - emoteButtonsRepeater.itemAt(0).hovered || - emoteButtonsRepeater.itemAt(1).hovered || - emoteButtonsRepeater.itemAt(2).hovered || - emoteButtonsRepeater.itemAt(3).hovered || - emoteButtonsRepeater.itemAt(4).hovered || - emoteButtonsRepeater.itemAt(5).hovered) ? expandedWidth : originalWidth; + // Here + property int requestedWidth: ( + root.showEmoteUI && ( + drawerContainer.keepDrawerExpanded || + emoteIndicatorMouseArea.containsMouse || + emoteButtonsRepeater.itemAt(0).hovered || + emoteButtonsRepeater.itemAt(1).hovered || + emoteButtonsRepeater.itemAt(2).hovered || + emoteButtonsRepeater.itemAt(3).hovered || + emoteButtonsRepeater.itemAt(4).hovered || + emoteButtonsRepeater.itemAt(5).hovered) + ) ? expandedWidth : originalWidth; readonly property int totalEmojiDurationMS: 7000 // Must match `TOTAL_EMOJI_DURATION_MS` in `simplifiedEmoji.js` readonly property string emoteIconSource: "images/emote_Icon.svg" + // property bool trayDisabled: Settings.getValue("simplifiedUI/showEmoteUI", false) + property bool showEmoteUI: Settings.getValue("simplifiedUI/showEmoteUI", false) + onRequestedWidthChanged: { + console.log("root.tryDisabled on requested widthChanged", root.showEmoteUI); + console.log(root.requestedWidth); root.requestNewWidth(root.requestedWidth); } @@ -45,6 +56,18 @@ Rectangle { SmoothedAnimation { duration: 220 } } + Connections { + target: Settings + + onValueChanged: { + console.log("in on value changed", setting, value) + if (setting === "simplifiedUI/showEmoteUI") { + console.log("on root tray disabled"); + root.showEmoteUI = value; + } + } + } + SimplifiedConstants.SimplifiedConstants { id: simplifiedUI } @@ -158,7 +181,7 @@ Rectangle { anchors.fill: lockIcon source: lockIcon color: "#ffffff" - visible: drawerContainer.keepDrawerExpanded + visible: root.showEmoteUI && drawerContainer.keepDrawerExpanded } MouseArea { From 669fef763a91177508835ce1347122fa157a9604 Mon Sep 17 00:00:00 2001 From: milad Date: Tue, 3 Sep 2019 18:11:56 -0700 Subject: [PATCH 25/46] removed logs --- .../hifi/simplifiedUI/settingsApp/general/General.qml | 1 - .../simplifiedUI/simplifiedEmote/simplifiedEmote.js | 10 ---------- .../ui/qml/SimplifiedEmoteIndicator.qml | 8 -------- 3 files changed, 19 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml index 2260bc312a..c74a01f31d 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml @@ -138,7 +138,6 @@ Flickable { labelTextOn: "Show Emote UI" checked: Settings.getValue("simplifiedUI/showEmoteUI", true) onClicked: { - console.log("CLICKED GENERAL SETTING") var currentSetting = Settings.getValue("simplifiedUI/showEmoteUI", true); Settings.setValue("simplifiedUI/showEmoteUI", !currentSetting); } diff --git a/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js b/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js index 6697807b67..ab2cef7cb2 100644 --- a/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js +++ b/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js @@ -530,16 +530,6 @@ function handleEmoteIndicatorVisibleChanged(shouldBeVisible) { } } -function handleEmoteIndictaorTrayDisabledChanged(shouldBeDisabled) { - emoteAppBarWindow.sendToQml({ - "source": "simplifiedEmote.js", - "method": "updateTrayDisabled", - "data": { - "shouldBeDisabled": shouldBeDisabled - } - }); -} - function onDisplayModeChanged(isHMDMode) { reactionsBegun.forEach(function(react) { diff --git a/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml b/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml index b178b9eef5..b8b983c19c 100644 --- a/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml +++ b/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml @@ -21,13 +21,9 @@ Rectangle { id: root color: simplifiedUI.colors.white anchors.fill: parent - Component.onCompleted: { - console.log("\n\n\n\n\n\n\n COMPLETED @@2 \n\n\n\n\n\n\n\n"); - } property int originalWidth: 48 property int expandedWidth: mainEmojiContainer.width + drawerContainer.width // For the below to work, the Repeater's Item's second child must be the individual button's `MouseArea` - // Here property int requestedWidth: ( root.showEmoteUI && ( drawerContainer.keepDrawerExpanded || @@ -46,8 +42,6 @@ Rectangle { onRequestedWidthChanged: { - console.log("root.tryDisabled on requested widthChanged", root.showEmoteUI); - console.log(root.requestedWidth); root.requestNewWidth(root.requestedWidth); } @@ -60,9 +54,7 @@ Rectangle { target: Settings onValueChanged: { - console.log("in on value changed", setting, value) if (setting === "simplifiedUI/showEmoteUI") { - console.log("on root tray disabled"); root.showEmoteUI = value; } } From 6c9c22a5fbe9d48360cd526385e3ce568e59fa83 Mon Sep 17 00:00:00 2001 From: milad Date: Tue, 3 Sep 2019 18:14:15 -0700 Subject: [PATCH 26/46] removed old code --- .../simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml b/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml index b8b983c19c..8032edce84 100644 --- a/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml +++ b/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml @@ -37,7 +37,6 @@ Rectangle { ) ? expandedWidth : originalWidth; readonly property int totalEmojiDurationMS: 7000 // Must match `TOTAL_EMOJI_DURATION_MS` in `simplifiedEmoji.js` readonly property string emoteIconSource: "images/emote_Icon.svg" - // property bool trayDisabled: Settings.getValue("simplifiedUI/showEmoteUI", false) property bool showEmoteUI: Settings.getValue("simplifiedUI/showEmoteUI", false) From cf01d9f1af21d4be2bd7612dabbe134a82a432e2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 4 Sep 2019 21:04:03 +1200 Subject: [PATCH 27/46] Script.require() JSDoc fixes --- libraries/script-engine/src/ScriptEngine.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 7300f52f9b..06085f30fd 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -416,8 +416,10 @@ public: * Provides access to methods or objects provided in an external JavaScript or JSON file. * See {@link https://docs.highfidelity.com/script/js-tips.html} for further details. * @function Script.require - * @param {string} module - The module to use. May be a JavaScript file or the name of a system module such as - * "sppUi". + * @param {string} module - The module to use. May be a JavaScript file, a JSON file, or the name of a system module such + * as "appUi" (i.e., the "appUi.js" system module JavaScript file). + * @returns {object|array} The value assigned to module.exports in the JavaScript file, or the value defined + * in the JSON file. */ Q_INVOKABLE QScriptValue require(const QString& moduleId); From 5624ba6e1458e7d396522f913cfa7b8811fe9592 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 4 Sep 2019 21:05:06 +1200 Subject: [PATCH 28/46] Fix JSDoc for some Controller.Hardware.Vive property names --- plugins/openvr/src/ViveControllerManager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index c21a9ae4df..8aa7311de4 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -1319,13 +1319,13 @@ void ViveControllerManager::InputDevice::setConfigFromString(const QString& valu * RXnumbernumberRight stick x-axis scale. * RYnumbernumberRight stick y-axis scale. * LSnumbernumberLeft touch pad pressed. - * LS_CENTERnumbernumberLeft touch pad center pressed. - * LS_XnumbernumberLeft touch pad pressed x-coordinate. - * LS_YnumbernumberLeft touch pad pressed y-coordinate. + * LSCenternumbernumberLeft touch pad center pressed. + * LSXnumbernumberLeft touch pad pressed x-coordinate. + * LSYnumbernumberLeft touch pad pressed y-coordinate. * RSnumbernumberRight touch pad pressed. - * RS_CENTERnumbernumberRight touch pad center pressed. - * RS_XnumbernumberRight touch pad pressed x-coordinate. - * RS_YnumbernumberRight touch pad pressed y-coordinate. + * RSCenternumbernumberRight touch pad center pressed. + * RSXnumbernumberRight touch pad pressed x-coordinate. + * RSYnumbernumberRight touch pad pressed y-coordinate. * LSTouchnumbernumberLeft touch pad is touched. * RSTouchnumbernumberRight touch pad is touched. * Triggers From 4e274347b4d95d209266f2a771a829786600e57f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 4 Sep 2019 21:05:36 +1200 Subject: [PATCH 29/46] Fix typo in Entities.getAbsoluteJointRotationInObjectFrame() JSDoc --- libraries/entities/src/EntityScriptingInterface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index ca9108852f..52470e56c4 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -1294,7 +1294,7 @@ public slots: Q_INVOKABLE int getJointParent(const QUuid& entityID, int index); /**jsdoc - * Gets the translation of a joint in a {@link Entities.EntityProperties-Model|Model} entity relative to the entity's + * Gets the rotation of a joint in a {@link Entities.EntityProperties-Model|Model} entity relative to the entity's * position and orientation. * @function Entities.getAbsoluteJointRotationInObjectFrame * @param {Uuid} entityID - The ID of the entity. From 6474705ca2423e0eda6b2231ca704ad8be31b9f1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 4 Sep 2019 21:06:30 +1200 Subject: [PATCH 30/46] Reformat "supported script types" in Entities and Scripts signals --- libraries/script-engine/src/ScriptEngine.cpp | 4 ++-- libraries/script-engine/src/ScriptEngine.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index e679e9f6c5..57e9b06f9d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -2210,7 +2210,7 @@ void ScriptEngine::loadEntityScript(const EntityItemID& entityID, const QString& /**jsdoc * Triggered when the script starts for a user. See also, {@link Script.entityScriptPreloadFinished}. *

Note: Can only be connected to via this.preload = function (...) { ... } in the entity script.

- *
Available in:Client Entity ScriptsServer Entity Scripts
+ *

Supported Script Types: Client Entity Scripts • Server Entity Scripts

* @function Entities.preload * @param {Uuid} entityID - The ID of the entity that the script is running in. * @returns {Signal} @@ -2416,7 +2416,7 @@ void ScriptEngine::entityScriptContentAvailable(const EntityItemID& entityID, co /**jsdoc * Triggered when the script terminates for a user. *

Note: Can only be connected to via this.unoad = function () { ... } in the entity script.

- *
Available in:Client Entity ScriptsServer Entity Scripts
+ *

Supported Script Types: Client Entity Scripts • Server Entity Scripts

* @function Entities.unload * @param {Uuid} entityID - The ID of the entity that the script is running in. * @returns {Signal} diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 06085f30fd..3ffef16844 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -844,7 +844,7 @@ signals: /**jsdoc * Triggered when the script starts for the user. See also, {@link Entities.preload}. - *
Available in:Client Entity ScriptsServer Entity Scripts
+ *

Supported Script Types: Client Entity Scripts • Server Entity Scripts

* @function Script.entityScriptPreloadFinished * @param {Uuid} entityID - The ID of the entity that the script is running in. * @returns {Signal} From 672e61c49d5c4267a29c833d712a36fa21d29c1c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 4 Sep 2019 21:06:49 +1200 Subject: [PATCH 31/46] Fix typo in Entities.EntityProperties-Material example --- libraries/entities/src/EntityItemProperties.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index c16839dc1a..5437ceaab8 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -965,7 +965,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * // Value overrides entity's "color" property. * albedo: [1.0, 1.0, 0] // Yellow * } - * }), + * }) * }); */ From 5fdcf0ecaf8152441015014dc70de2ff92987973 Mon Sep 17 00:00:00 2001 From: milad Date: Wed, 4 Sep 2019 12:59:17 -0700 Subject: [PATCH 32/46] updated setting name and changed default value to true for show tray --- .../hifi/simplifiedUI/settingsApp/general/General.qml | 8 ++++---- .../ui/qml/SimplifiedEmoteIndicator.qml | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml b/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml index c74a01f31d..24fff2dae4 100644 --- a/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml +++ b/interface/resources/qml/hifi/simplifiedUI/settingsApp/general/General.qml @@ -136,17 +136,17 @@ Flickable { Layout.preferredHeight: 18 Layout.preferredWidth: parent.width labelTextOn: "Show Emote UI" - checked: Settings.getValue("simplifiedUI/showEmoteUI", true) + checked: Settings.getValue("simplifiedUI/allowEmoteDrawerExpansion", true) onClicked: { - var currentSetting = Settings.getValue("simplifiedUI/showEmoteUI", true); - Settings.setValue("simplifiedUI/showEmoteUI", !currentSetting); + var currentSetting = Settings.getValue("simplifiedUI/allowEmoteDrawerExpansion", true); + Settings.setValue("simplifiedUI/allowEmoteDrawerExpansion", !currentSetting); } Connections { target: Settings onValueChanged: { - if (setting === "simplifiedUI/showEmoteUI") { + if (setting === "simplifiedUI/allowEmoteDrawerExpansion") { emoteSwitch.checked = value; } } diff --git a/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml b/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml index 8032edce84..787ccadd62 100644 --- a/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml +++ b/scripts/simplifiedUI/simplifiedEmote/ui/qml/SimplifiedEmoteIndicator.qml @@ -25,7 +25,7 @@ Rectangle { property int expandedWidth: mainEmojiContainer.width + drawerContainer.width // For the below to work, the Repeater's Item's second child must be the individual button's `MouseArea` property int requestedWidth: ( - root.showEmoteUI && ( + root.allowEmoteDrawerExpansion && ( drawerContainer.keepDrawerExpanded || emoteIndicatorMouseArea.containsMouse || emoteButtonsRepeater.itemAt(0).hovered || @@ -37,7 +37,7 @@ Rectangle { ) ? expandedWidth : originalWidth; readonly property int totalEmojiDurationMS: 7000 // Must match `TOTAL_EMOJI_DURATION_MS` in `simplifiedEmoji.js` readonly property string emoteIconSource: "images/emote_Icon.svg" - property bool showEmoteUI: Settings.getValue("simplifiedUI/showEmoteUI", false) + property bool allowEmoteDrawerExpansion: Settings.getValue("simplifiedUI/allowEmoteDrawerExpansion", true) onRequestedWidthChanged: { @@ -53,8 +53,8 @@ Rectangle { target: Settings onValueChanged: { - if (setting === "simplifiedUI/showEmoteUI") { - root.showEmoteUI = value; + if (setting === "simplifiedUI/allowEmoteDrawerExpansion") { + root.allowEmoteDrawerExpansion = value; } } } @@ -172,7 +172,7 @@ Rectangle { anchors.fill: lockIcon source: lockIcon color: "#ffffff" - visible: root.showEmoteUI && drawerContainer.keepDrawerExpanded + visible: root.allowEmoteDrawerExpansion && drawerContainer.keepDrawerExpanded } MouseArea { From d316f014eb9f048d7af0ea68741cf1af18614461 Mon Sep 17 00:00:00 2001 From: milad Date: Wed, 4 Sep 2019 15:51:07 -0700 Subject: [PATCH 33/46] fixed double scriptEnding being called --- .../emojiApp/simplifiedEmoji.js | 20 ++++++------------- .../simplifiedEmote/simplifiedEmote.js | 1 - 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js index d3ec9da32d..709f0c9aeb 100644 --- a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js +++ b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js @@ -416,7 +416,6 @@ function init() { Window.domainChanged.connect(onDomainChanged); MyAvatar.scaleChanged.connect(onScaleChanged); - Script.scriptEnding.connect(scriptEnding); signalsConnected = true; } @@ -431,18 +430,6 @@ function init() { // ************************************* // #region cleanup - -function scriptEnding() { - resetEmojis(); - if (signalsConnected) { - Script.scriptEnding.disconnect(scriptEnding); - Window.domainChanged.disconnect(onDomainChanged); - MyAvatar.scaleChanged.disconnect(onScaleChanged); - signalsConnected = false; - } -} - - // #endregion // ************************************* // END cleanup @@ -476,7 +463,12 @@ function addEmojiFromQML(code) { } function unload() { - scriptEnding(); + resetEmojis(); + if (signalsConnected) { + Window.domainChanged.disconnect(onDomainChanged); + MyAvatar.scaleChanged.disconnect(onScaleChanged); + signalsConnected = false; + } } function startup() { diff --git a/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js b/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js index ab2cef7cb2..2fcb3dbb15 100644 --- a/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js +++ b/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js @@ -587,7 +587,6 @@ function init() { Controller.keyReleaseEvent.connect(keyReleaseHandler); keyPressSignalsConnected = true; - Script.scriptEnding.connect(shutdown); } From 79b72717297c5b7442d2a34c9f5f5213e259f472 Mon Sep 17 00:00:00 2001 From: milad Date: Wed, 4 Sep 2019 16:48:24 -0700 Subject: [PATCH 34/46] removed startup/unload apis from the 3 main modules --- .../emojiApp/simplifiedEmoji.js | 35 +++++++-------- .../simplifiedEmote/simplifiedEmote.js | 44 ++----------------- .../ui/simplifiedNametag/simplifiedNametag.js | 20 +++++---- .../simplifiedStatusIndicator.js | 29 +++++++----- scripts/simplifiedUI/ui/simplifiedUI.js | 25 +++-------- 5 files changed, 56 insertions(+), 97 deletions(-) diff --git a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js index 709f0c9aeb..cd443a79ba 100644 --- a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js +++ b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js @@ -388,11 +388,13 @@ function playPopAnimation() { var emojiCodeMap; var customEmojiCodeMap; var signalsConnected = false; -function init() { +var _this; +function startup() { // make a map of just the utf codes to help with accesing emojiCodeMap = emojiList.reduce(function (codeMap, currentEmojiInList, index) { if ( currentEmojiInList && + currentEmojiInList.code && currentEmojiInList.code.length > 0 && currentEmojiInList.code[UTF_CODE]) { @@ -414,9 +416,22 @@ function init() { pruneOldAvimojis(); + Script.scriptEnding.connect(unload); Window.domainChanged.connect(onDomainChanged); MyAvatar.scaleChanged.connect(onScaleChanged); signalsConnected = true; + + function AviMoji() { + _this = this; + this._avimojiQMLWindow; + } + + AviMoji.prototype = { + addEmoji: addEmojiFromQML, + registerAvimojiQMLWindow: registerAvimojiQMLWindow + }; + + return new AviMoji(); } @@ -440,12 +455,6 @@ function init() { // ************************************* // #region API -var _this; -function AviMoji() { - _this = this; - this._avimojiQMLWindow; -} - function registerAvimojiQMLWindow(avimojiQMLWindow) { this._avimojiQMLWindow = avimojiQMLWindow; } @@ -471,17 +480,7 @@ function unload() { } } -function startup() { - init(); -} - -AviMoji.prototype = { - startup: startup, - addEmoji: addEmojiFromQML, - unload: unload, - registerAvimojiQMLWindow: registerAvimojiQMLWindow -}; - +var AviMoji = startup(); module.exports = AviMoji; diff --git a/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js b/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js index 2fcb3dbb15..d1396c8ccf 100644 --- a/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js +++ b/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js @@ -544,8 +544,7 @@ function onDisplayModeChanged(isHMDMode) { } -var EmojiAPI = Script.require("./emojiApp/simplifiedEmoji.js"); -var emojiAPI = new EmojiAPI(); +var emojiAPI = Script.require("./emojiApp/simplifiedEmoji.js"); var keyPressSignalsConnected = false; var emojiCodeMap; var customEmojiCodeMap; @@ -578,7 +577,6 @@ function init() { Window.minimizedChanged.connect(onWindowMinimizedChanged); Window.geometryChanged.connect(onGeometryChanged); HMD.displayModeChanged.connect(onDisplayModeChanged); - emojiAPI.startup(); getSounds(); handleEmoteIndicatorVisibleChanged(true); @@ -586,11 +584,11 @@ function init() { Controller.keyPressEvent.connect(keyPressHandler); Controller.keyReleaseEvent.connect(keyReleaseHandler); keyPressSignalsConnected = true; - + Script.scriptEnding.connect(unload); } -function shutdown() { +function unload() { if (emoteAppBarWindow) { emoteAppBarWindow.fromQml.disconnect(onMessageFromEmoteAppBar); emoteAppBarWindow.close(); @@ -605,7 +603,6 @@ function shutdown() { endReactionWrapper(react); }); - emojiAPI.unload(); maybeClearClapSoundInterval(); maybeClearReticleUpdateLimiterTimeout(); maybeDeleteRemoteIndicatorTimeout(); @@ -758,37 +755,4 @@ function toggleEmojiApp() { // END EMOJI // ************************************* -// ************************************* -// START API -// ************************************* -// #region API - - -function startup() { - init(); -} - - -function unload() { - shutdown(); -} - -var _this; -function EmoteBar() { - _this = this; -} - - -EmoteBar.prototype = { - startup: startup, - unload: unload -}; - -module.exports = EmoteBar; - - -// #endregion -// ************************************* -// END API -// ************************************* - +init(); \ No newline at end of file diff --git a/scripts/simplifiedUI/ui/simplifiedNametag/simplifiedNametag.js b/scripts/simplifiedUI/ui/simplifiedNametag/simplifiedNametag.js index beea979170..daca429a09 100644 --- a/scripts/simplifiedUI/ui/simplifiedNametag/simplifiedNametag.js +++ b/scripts/simplifiedUI/ui/simplifiedNametag/simplifiedNametag.js @@ -47,15 +47,24 @@ function onAvatarAdded(uuid) { } -// Called on init +// Create a new nametag list manager, connect signals, and return back a new Nametag object. var avatarNametagMode; function startup() { nameTagListManager.create(); handleAvatarNametagMode(Settings.getValue("simplifiedNametag/avatarNametagMode", "on")); + Script.scriptEnding.connect(unload); Window.domainChanged.connect(onDomainChange); AvatarManager.avatarRemovedEvent.connect(onAvatarRemoved); AvatarManager.avatarAddedEvent.connect(onAvatarAdded); + + function NameTag() {} + + NameTag.prototype = { + handleAvatarNametagMode: handleAvatarNametagMode + }; + + return new NameTag(); } @@ -82,15 +91,10 @@ function handleAvatarNametagMode(newAvatarNameTagMode) { // ************************************* // #region api -function NameTag() {} -NameTag.prototype = { - startup: startup, - unload: unload, - handleAvatarNametagMode: handleAvatarNametagMode -}; +var nameTag = startup(); -module.exports = NameTag; +module.exports = nameTag; // #endregion diff --git a/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js b/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js index 2b401c5bc5..ad41a836f0 100644 --- a/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js +++ b/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js @@ -8,7 +8,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -function simplifiedStatusIndicator(properties) { +function SimplifiedStatusIndicator() { var that = this; var DEBUG = false; @@ -125,6 +125,16 @@ function simplifiedStatusIndicator(properties) { // #region SIGNALS + function updateProperties(properties) { + // Overwrite with the given properties + var overwriteableKeys = ["statusChanged"]; + Object.keys(properties).forEach(function (key) { + if (overwriteableKeys.indexOf(key) > -1) { + that[key] = properties[key]; + } + }); + } + var currentStatus = "available"; // Default is available function toggleStatus() { if (currentStatus === "busy") { @@ -207,6 +217,8 @@ function simplifiedStatusIndicator(properties) { Window.domainChanged.connect(onDomainChanged); getStatus(setStatus); + + Script.scriptEnding.connect(unload); } @@ -224,20 +236,13 @@ function simplifiedStatusIndicator(properties) { // #endregion APP LIFETIME - that.startup = startup; - that.unload = unload; that.toggleStatus = toggleStatus; that.setStatus = setStatus; that.getLocalStatus = getLocalStatus; that.statusChanged = statusChanged; - - // Overwrite with the given properties - var overwriteableKeys = ["statusChanged"]; - Object.keys(properties).forEach(function (key) { - if (overwriteableKeys.indexOf(key) > -1) { - that[key] = properties[key]; - } - }); + that.updateProperties = updateProperties; + + startup(); } -module.exports = simplifiedStatusIndicator; \ No newline at end of file +module.exports = new SimplifiedStatusIndicator(); \ No newline at end of file diff --git a/scripts/simplifiedUI/ui/simplifiedUI.js b/scripts/simplifiedUI/ui/simplifiedUI.js index 803c6627c0..7ec42ee72b 100644 --- a/scripts/simplifiedUI/ui/simplifiedUI.js +++ b/scripts/simplifiedUI/ui/simplifiedUI.js @@ -583,12 +583,11 @@ function restoreLODSettings() { } -var SimplifiedNametag = Script.require("./simplifiedNametag/simplifiedNametag.js?" + Date.now()); -var SimplifiedStatusIndicator = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js?" + Date.now()); -var SimplifiedEmote = Script.require("../simplifiedEmote/simplifiedEmote.js?" + Date.now()); -var si; -var nametag; -var emote; +var nametag = Script.require("./simplifiedNametag/simplifiedNametag.js?" + Date.now()); +var si = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js?" + Date.now()) +var emote = Script.require("../simplifiedEmote/simplifiedEmote.js?" + Date.now()); +// var nametag; +// var emote; var oldShowAudioTools; var oldShowBubbleTools; var keepExistingUIAndScriptsSetting = Settings.getValue("simplifiedUI/keepExistingUIAndScripts", false); @@ -607,16 +606,8 @@ function startup() { loadSimplifiedTopBar(); - si = new SimplifiedStatusIndicator({ - statusChanged: onStatusChanged - }); - si.startup(); - nametag = new SimplifiedNametag(); - nametag.startup(); - - emote = new SimplifiedEmote(); - emote.startup(); + si.updateProperties({ statusChanged: onStatusChanged }); updateInputDeviceMutedOverlay(Audio.muted); updateOutputDeviceMutedOverlay(isOutputMuted()); @@ -665,10 +656,6 @@ function shutdown() { maybeDeleteInputDeviceMutedOverlay(); maybeDeleteOutputDeviceMutedOverlay(); - nametag.unload(); - si.unload(); - emote.unload(); - Audio.mutedDesktopChanged.disconnect(onDesktopInputDeviceMutedChanged); Audio.mutedHMDChanged.disconnect(onHMDInputDeviceMutedChanged); Window.geometryChanged.disconnect(onGeometryChanged); From 252e8a2ed6c24cf3d6bb3e1ea72a118e85a5bb18 Mon Sep 17 00:00:00 2001 From: milad Date: Wed, 4 Sep 2019 16:49:46 -0700 Subject: [PATCH 35/46] removed commented out code --- scripts/simplifiedUI/ui/simplifiedUI.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/simplifiedUI/ui/simplifiedUI.js b/scripts/simplifiedUI/ui/simplifiedUI.js index 7ec42ee72b..c388c594c9 100644 --- a/scripts/simplifiedUI/ui/simplifiedUI.js +++ b/scripts/simplifiedUI/ui/simplifiedUI.js @@ -586,8 +586,6 @@ function restoreLODSettings() { var nametag = Script.require("./simplifiedNametag/simplifiedNametag.js?" + Date.now()); var si = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js?" + Date.now()) var emote = Script.require("../simplifiedEmote/simplifiedEmote.js?" + Date.now()); -// var nametag; -// var emote; var oldShowAudioTools; var oldShowBubbleTools; var keepExistingUIAndScriptsSetting = Settings.getValue("simplifiedUI/keepExistingUIAndScripts", false); From 3f2d2996a079582a52a3d86055a9c1ba122ef6c1 Mon Sep 17 00:00:00 2001 From: milad Date: Wed, 4 Sep 2019 16:59:14 -0700 Subject: [PATCH 36/46] removed comment region sections --- .../simplifiedEmote/emojiApp/simplifiedEmoji.js | 10 ---------- .../ui/simplifiedNametag/simplifiedNametag.js | 11 ----------- 2 files changed, 21 deletions(-) diff --git a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js index cd443a79ba..517a4ffe79 100644 --- a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js +++ b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js @@ -440,16 +440,6 @@ function startup() { // END main // ************************************* -// ************************************* -// START cleanup -// ************************************* -// #region cleanup - -// #endregion -// ************************************* -// END cleanup -// ************************************* - // ************************************* // START API // ************************************* diff --git a/scripts/simplifiedUI/ui/simplifiedNametag/simplifiedNametag.js b/scripts/simplifiedUI/ui/simplifiedNametag/simplifiedNametag.js index daca429a09..15ce8a83f6 100644 --- a/scripts/simplifiedUI/ui/simplifiedNametag/simplifiedNametag.js +++ b/scripts/simplifiedUI/ui/simplifiedNametag/simplifiedNametag.js @@ -86,18 +86,7 @@ function handleAvatarNametagMode(newAvatarNameTagMode) { } -// ************************************* -// START api -// ************************************* -// #region api - - var nameTag = startup(); module.exports = nameTag; - -// #endregion -// ************************************* -// END api -// ************************************* \ No newline at end of file From c73ea11b37b4d35eb7ca9409308b1f9bd2a2d67c Mon Sep 17 00:00:00 2001 From: milad Date: Wed, 4 Sep 2019 17:00:30 -0700 Subject: [PATCH 37/46] lowecase object --- .../simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js index 517a4ffe79..6d9c452162 100644 --- a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js +++ b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js @@ -470,9 +470,9 @@ function unload() { } } -var AviMoji = startup(); +var aviMoji = startup(); -module.exports = AviMoji; +module.exports = aviMoji; // #endregion // ************************************* From 408656f6ec1a830b5d2e6d470adaa76df2cfa957 Mon Sep 17 00:00:00 2001 From: milad Date: Wed, 4 Sep 2019 17:06:00 -0700 Subject: [PATCH 38/46] added line break --- .../ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js b/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js index ad41a836f0..d9331c62a3 100644 --- a/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js +++ b/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js @@ -86,6 +86,7 @@ function SimplifiedStatusIndicator() { }); } + // Get status from database function getStatus(callback) { var queryParamString = "type=getStatus"; @@ -135,6 +136,7 @@ function SimplifiedStatusIndicator() { }); } + var currentStatus = "available"; // Default is available function toggleStatus() { if (currentStatus === "busy") { From d86944baf477b8fde581abad788d43619b644eb0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 23 Sep 2018 15:09:28 -0700 Subject: [PATCH 39/46] rework polyvox state-machine --- .../src/RenderablePolyVoxEntityItem.cpp | 645 ++++++++++++------ .../src/RenderablePolyVoxEntityItem.h | 60 +- 2 files changed, 476 insertions(+), 229 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 3574544bba..7e555e665b 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -72,7 +72,6 @@ #include "EntityTreeRenderer.h" #include "RenderablePolyVoxEntityItem.h" -#include "EntityEditPacketSender.h" #include "PhysicalEntitySimulation.h" const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5; @@ -83,30 +82,60 @@ const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5; _voxelData -- compressed QByteArray representation of which voxels have which values _volData -- datastructure from the PolyVox library which holds which voxels have which values _mesh -- renderable representation of the voxels - _shape -- used for bullet collisions + _shape -- used for bullet (physics) collisions Each one depends on the one before it, except that _voxelData is set from _volData if a script edits the voxels. There are booleans to indicate that something has been updated and the dependents now need to be updated. + _meshReady -- do we have something to give scripts that ask for the mesh? + _voxelDataDirty -- do we need to uncompress data and expand it into _volData? + _volDataDirty -- does recomputeMesh need to be called? + _shapeReady -- are we ready to tell bullet our shape? - _voxelDataDirty - _volDataDirty - _meshDirty - In RenderablePolyVoxEntityItem::render, these flags are checked and changes are propagated along the chain. - decompressVolumeData() is called to decompress _voxelData into _volData. recomputeMesh() is called to invoke the - polyVox surface extractor to create _mesh (as well as set Simulation _flags). Because Simulation::DIRTY_SHAPE - is set, isReadyToComputeShape() gets called and _shape is created either from _volData or _shape, depending on - the surface style. + Here is a simplified diagram of the state machine implemented in RenderablePolyVoxEntityItem::update - When a script changes _volData, compressVolumeDataAndSendEditPacket is called to update _voxelData and to - send a packet to the entity-server. + +-------------------+ + | | + | | + | volDataDirty | voxelDataDirty + | +--v--+ + | +------+Ready+--------+ + | | +-----+ | + | | | + | +-----v----+ +------v------+ + | |BakingMesh| |Uncompressing| + | +-----+----+ +------+------+ + | | | + | | | + | +---v-------+ +-------v------------+ + | |Compressing| |BakingMeshNoCompress| + | +---------+-+ ++-------------------+ + | | | + | | | + | +-v--------v+ + | |BakingShape| + | +-----+-----+ + | | + +-------------------+ - decompressVolumeData, recomputeMesh, computeShapeInfoWorker, and compressVolumeDataAndSendEditPacket are too expensive - to run on a thread that has other things to do. These use QtConcurrent::run to spawn a thread. As each thread - finishes, it adjusts the dirty flags so that the next call to render() will kick off the next step. - polyvoxes are designed to seemlessly fit up against neighbors. If voxels go right up to the edge of polyvox, + The work for each step is done on temporary worker threads. The PolyVox entity will update _updateNeeded and + enable or disable update calls on the entity, depending on if there is more work to do. + + From the 'Ready' state, if we receive an update from the network, _voxelDataDirty will be set true. We + uncompress the received data, bake the mesh (for the render-engine's benefit), and then compute the shape + (for the physics-engine's benefit). This is the right-hand side of the diagram. + + From the 'Ready' state, if a script changes a voxel, _volDataDirty will be set true. We bake the mesh, + compress the voxels into a new _voxelData, and transmit the new _voxelData to the entity-server. We then + bake the shape. This is the left-hand side of the diagram. + + The actual state machine is more complicated than the diagram, because it's possible for _volDataDirty or + _voxelDataDirty to be set true while worker threads are attempting to bake meshes or shapes. If this happens, + we jump back to a higher point in the diagram to avoid wasting effort. + + PolyVoxes are designed to seemlessly fit up against neighbors. If voxels go right up to the edge of polyvox, the resulting mesh wont be closed -- the library assumes you'll have another polyvox next to it to continue the mesh. @@ -114,8 +143,8 @@ const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5; previously mentioned gaps along the edges. Non-edged polyvox entities can be told about their neighbors in all 6 cardinal directions. On the positive - edges of the polyvox, the values are set from the (negative edge of) relevant neighbor so that their meshes - knit together. This is handled by bonkNeighbors and copyUpperEdgesFromNeighbors. In these functions, variable + edges of the polyvox, the values are set from the (negative edge of the) relevant neighbor so that their meshes + knit together. This is handled by tellNeighborsToRecopyEdges and copyUpperEdgesFromNeighbors. In these functions, variable names have XP for x-positive, XN x-negative, etc. */ @@ -140,7 +169,8 @@ EntityItemPointer RenderablePolyVoxEntityItem::factory(const EntityItemID& entit return entity; } -RenderablePolyVoxEntityItem::RenderablePolyVoxEntityItem(const EntityItemID& entityItemID) : PolyVoxEntityItem(entityItemID) { } +RenderablePolyVoxEntityItem::RenderablePolyVoxEntityItem(const EntityItemID& entityItemID) : PolyVoxEntityItem(entityItemID) { +} RenderablePolyVoxEntityItem::~RenderablePolyVoxEntityItem() { withWriteLock([&] { @@ -165,11 +195,12 @@ bool isEdged(PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle) { } void RenderablePolyVoxEntityItem::setVoxelData(const QByteArray& voxelData) { - // compressed voxel information from the entity-server + // accept compressed voxel information from the entity-server withWriteLock([&] { if (_voxelData != voxelData) { _voxelData = voxelData; _voxelDataDirty = true; + startUpdates(); } }); } @@ -189,21 +220,22 @@ void RenderablePolyVoxEntityItem::setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxel bool willBeEdged = isEdged(voxelSurfaceStyle); if (wasEdged != willBeEdged) { - _volDataDirty = true; _volData.reset(); - _voxelSurfaceStyle = voxelSurfaceStyle; _voxelDataDirty = true; volSizeChanged = true; - } else { - _volDataDirty = true; - _voxelSurfaceStyle = voxelSurfaceStyle; } + _voxelSurfaceStyle = voxelSurfaceStyle; + startUpdates(); }); if (volSizeChanged) { // setVoxelVolumeSize will re-alloc _volData with the right size setVoxelVolumeSize(_voxelVolumeSize); } + + _updateFromNeighborXEdge = _updateFromNeighborYEdge = _updateFromNeighborZEdge = true; + tellNeighborsToRecopyEdges(true); + startUpdates(); } glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const { @@ -262,9 +294,6 @@ bool RenderablePolyVoxEntityItem::setVoxel(const ivec3& v, uint8_t toValue) { withWriteLock([&] { result = setVoxelInternal(v, toValue); }); - if (result) { - compressVolumeDataAndSendEditPacket(); - } return result; } @@ -311,9 +340,6 @@ bool RenderablePolyVoxEntityItem::setAll(uint8_t toValue) { result |= setVoxelInternal(v, toValue); }); }); - if (result) { - compressVolumeDataAndSendEditPacket(); - } return result; } @@ -336,9 +362,6 @@ bool RenderablePolyVoxEntityItem::setCuboid(const glm::vec3& lowPosition, const result |= setVoxelInternal(v, toValue); }); }); - if (result) { - compressVolumeDataAndSendEditPacket(); - } return result; } @@ -374,9 +397,6 @@ bool RenderablePolyVoxEntityItem::setSphereInVolume(const vec3& center, float ra }); }); - if (result) { - compressVolumeDataAndSendEditPacket(); - } return result; } @@ -434,9 +454,6 @@ bool RenderablePolyVoxEntityItem::setSphere(const vec3& centerWorldCoords, float }); }); - if (result) { - compressVolumeDataAndSendEditPacket(); - } return result; } @@ -482,9 +499,6 @@ bool RenderablePolyVoxEntityItem::setCapsule(const vec3& startWorldCoords, const }); }); - if (result) { - compressVolumeDataAndSendEditPacket(); - } return result; } @@ -710,8 +724,9 @@ ShapeType RenderablePolyVoxEntityItem::getShapeType() const { void RenderablePolyVoxEntityItem::setRegistrationPoint(const glm::vec3& value) { if (value != _registrationPoint) { - _meshDirty = true; + _shapeReady = false; EntityItem::setRegistrationPoint(value); + startUpdates(); } } @@ -721,15 +736,11 @@ bool RenderablePolyVoxEntityItem::isReadyToComputeShape() const { return true; } - // we determine if we are ready to compute the physics shape by actually doing so. - // if _voxelDataDirty or _volDataDirty is set, don't do this yet -- wait for their - // threads to finish before creating the collision shape. - if (_meshDirty && !_voxelDataDirty && !_volDataDirty) { - const_cast(this)->_meshDirty = false; - const_cast(this)->computeShapeInfoWorker(); - return false; - } - return true; + bool result; + withReadLock([&] { + result = _shapeReady; + }); + return result; } void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { @@ -739,33 +750,155 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { return; } - // the shape was actually computed in isReadyToComputeShape. Just hand it off, here. - withWriteLock([&] { + withReadLock([&] { info = _shapeInfo; }); } -bool RenderablePolyVoxEntityItem::updateDependents() { - bool voxelDataDirty; - bool volDataDirty; +void RenderablePolyVoxEntityItem::changeUpdates(bool value) { + if (_updateNeeded != value) { + EntityTreePointer entityTree = getTree(); + if (entityTree) { + EntitySimulationPointer simulation = entityTree->getSimulation(); + if (simulation) { + _updateNeeded = value; + _flags |= Simulation::DIRTY_UPDATEABLE; + simulation->changeEntity(getThisPointer()); + } + } + } +} + +void RenderablePolyVoxEntityItem::startUpdates() { + changeUpdates(true); +} + +void RenderablePolyVoxEntityItem::stopUpdates() { + changeUpdates(false); +} + +void RenderablePolyVoxEntityItem::update(const quint64& now) { + bool doRecomputeMesh { false }; + bool doUncompress { false }; + bool doCompress { false }; + bool doRecomputeShape { false }; + withWriteLock([&] { - voxelDataDirty = _voxelDataDirty; - volDataDirty = _volDataDirty; - if (_voxelDataDirty) { - _voxelDataDirty = false; - } else if (_volDataDirty) { - _volDataDirty = false; - } else { - _meshReady = true; + tellNeighborsToRecopyEdges(false); + + switch (_state) { + + case PolyVoxState::Ready: { + if (_volDataDirty) { + _volDataDirty = _voxelDataDirty = false; + _state = PolyVoxState::BakingMesh; + doRecomputeMesh = true; + } else if (_voxelDataDirty) { + _voxelDataDirty = false; + _state = PolyVoxState::Uncompressing; + doUncompress = true; + } else { + copyUpperEdgesFromNeighbors(); + if (!_volDataDirty && !_voxelDataDirty) { + // nothing to do + stopUpdates(); + } + } + break; + } + + case PolyVoxState::Uncompressing: { + break; // wait + } + case PolyVoxState::UncompressingFinished: { + if (_volDataDirty) { + _volDataDirty = _voxelDataDirty = false; + _state = PolyVoxState::BakingMeshNoCompress; + doRecomputeMesh = true; + } else if (_voxelDataDirty) { + _voxelDataDirty = false; + // _voxelData changed while we were uncompressing the previous version, uncompress again + _state = PolyVoxState::Uncompressing; + doUncompress = true; + } else { + _state = PolyVoxState::Ready; + } + break; + } + + case PolyVoxState::BakingMesh: { + break; // wait + } + case PolyVoxState::BakingMeshFinished: { + if (_volDataDirty) { + _volDataDirty = _voxelDataDirty = false; + _state = PolyVoxState::BakingMesh; + // a local edit happened while we were baking the mesh. rebake mesh... + doRecomputeMesh = true; + } else if (_voxelDataDirty) { + _voxelDataDirty = false; + // we received a change from the wire while baking the mesh. + _state = PolyVoxState::Uncompressing; + doUncompress = true; + } else { + _state = PolyVoxState::Compressing; + doCompress = true; + } + break; + } + + case PolyVoxState::BakingMeshNoCompress: { + break; // wait + } + case PolyVoxState::BakingMeshNoCompressFinished: { + if (_volDataDirty) { + _volDataDirty = _voxelDataDirty = false; + _state = PolyVoxState::BakingMesh; + // a local edit happened while we were baking the mesh. rebake mesh... + doRecomputeMesh = true; + } else if (_voxelDataDirty) { + _voxelDataDirty = false; + // we received a change from the wire while baking the mesh. + _state = PolyVoxState::Uncompressing; + doUncompress = true; + } else { + _state = PolyVoxState::BakingShape; + doRecomputeShape = true; + } + break; + } + + case PolyVoxState::Compressing: { + break; // wait + } + case PolyVoxState::CompressingFinished: { + _state = PolyVoxState::BakingShape; + doRecomputeShape = true; + break; + } + + case PolyVoxState::BakingShape: { + break; // wait + } + case PolyVoxState::BakingShapeFinished: { + _state = PolyVoxState::Ready; + break; + } } }); - if (voxelDataDirty) { - decompressVolumeData(); - } else if (volDataDirty) { + + if (doRecomputeMesh) { recomputeMesh(); } - - return !volDataDirty; + if (doUncompress) { + uncompressVolumeData(); + } + if (doCompress) { + compressVolumeDataAndSendEditPacket(); + } + if (doRecomputeShape) { + computeShapeInfoWorker(); + } } void RenderablePolyVoxEntityItem::setVoxelVolumeSize(const glm::vec3& voxelVolumeSize) { @@ -782,6 +915,9 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(const glm::vec3& voxelVolum _voxelVolumeSize = voxelVolumeSize; _volData.reset(); _onCount = 0; + _updateFromNeighborXEdge = _updateFromNeighborYEdge = _updateFromNeighborZEdge = true; + tellNeighborsToRecopyEdges(true); + startUpdates(); static const PolyVox::Vector3DInt32 lowCorner(0, 0, 0); PolyVox::Vector3DInt32 highCorner; @@ -806,6 +942,8 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(const glm::vec3& voxelVolum // having the "outside of voxel-space" value be 255 has helped me notice some problems. _volData->setBorderValue(255); }); + + tellNeighborsToRecopyEdges(true); } bool inUserBounds(const std::shared_ptr> vol, @@ -853,32 +991,38 @@ uint8_t RenderablePolyVoxEntityItem::getVoxelInternal(const ivec3& v) const { } +void RenderablePolyVoxEntityItem::setVoxelMarkNeighbors(int x, int y, int z, uint8_t toValue) { + _volData->setVoxelAt(x, y, z, toValue); + if (x == 0) { + _neighborXNeedsUpdate = true; + startUpdates(); + } + if (y == 0) { + _neighborYNeedsUpdate = true; + startUpdates(); + } + if (z == 0) { + _neighborZNeedsUpdate = true; + startUpdates(); + } +} + bool RenderablePolyVoxEntityItem::setVoxelInternal(const ivec3& v, uint8_t toValue) { - // set a voxel without recompressing the voxel data. This assumes that the caller has - // write-locked the entity. - bool result = false; - if (!inUserBounds(_volData, _voxelSurfaceStyle, v)) { - return result; + // set a voxel without recompressing the voxel data. This assumes that the caller has write-locked the entity. + bool result = updateOnCount(v, toValue); + if (result) { + if (isEdged()) { + setVoxelMarkNeighbors(v.x + 1, v.y + 1, v.z + 1, toValue); + } else { + setVoxelMarkNeighbors(v.x, v.y, v.z, toValue); + } + _volDataDirty = true; + startUpdates(); } - result = updateOnCount(v, toValue); - - if (isEdged()) { - _volData->setVoxelAt(v.x + 1, v.y + 1, v.z + 1, toValue); - } else { - _volData->setVoxelAt(v.x, v.y, v.z, toValue); - } - - if (glm::any(glm::equal(ivec3(0), v))) { - _neighborsNeedUpdate = true; - } - - _volDataDirty |= result; - return result; } - bool RenderablePolyVoxEntityItem::updateOnCount(const ivec3& v, uint8_t toValue) { // keep _onCount up to date if (!inUserBounds(_volData, _voxelSurfaceStyle, v)) { @@ -902,7 +1046,7 @@ bool RenderablePolyVoxEntityItem::updateOnCount(const ivec3& v, uint8_t toValue) return false; } -void RenderablePolyVoxEntityItem::decompressVolumeData() { +void RenderablePolyVoxEntityItem::uncompressVolumeData() { // take compressed data and expand it into _volData. QByteArray voxelData; auto entity = std::static_pointer_cast(getThisPointer()); @@ -921,9 +1065,9 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() { if (voxelXSize == 0 || voxelXSize > PolyVoxEntityItem::MAX_VOXEL_DIMENSION || voxelYSize == 0 || voxelYSize > PolyVoxEntityItem::MAX_VOXEL_DIMENSION || voxelZSize == 0 || voxelZSize > PolyVoxEntityItem::MAX_VOXEL_DIMENSION) { - qCDebug(entitiesrenderer) << "voxelSize is not reasonable, skipping decompressions." - << voxelXSize << voxelYSize << voxelZSize << getName() << getID(); - entity->setVoxelDataDirty(false); + qCDebug(entitiesrenderer) << "voxelSize is not reasonable, skipping uncompressions." + << voxelXSize << voxelYSize << voxelZSize << getName() << getID(); + entity->setVoxelsFromData(QByteArray(1, 0), 1, 1, 1); return; } int rawSize = voxelXSize * voxelYSize * voxelZSize; @@ -934,10 +1078,10 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() { QByteArray uncompressedData = qUncompress(compressedData); if (uncompressedData.size() != rawSize) { - qCDebug(entitiesrenderer) << "PolyVox decompress -- size is (" << voxelXSize << voxelYSize << voxelZSize << ")" + qCDebug(entitiesrenderer) << "PolyVox uncompress -- size is (" << voxelXSize << voxelYSize << voxelZSize << ")" << "so expected uncompressed length of" << rawSize << "but length is" << uncompressedData.size() - << getName() << getID(); - entity->setVoxelDataDirty(false); + << getName() << getID(); + entity->setVoxelsFromData(QByteArray(1, 0), 1, 1, 1); return; } @@ -947,13 +1091,14 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() { void RenderablePolyVoxEntityItem::setVoxelsFromData(QByteArray uncompressedData, quint16 voxelXSize, quint16 voxelYSize, quint16 voxelZSize) { - // this accepts the payload from decompressVolumeData + // this accepts the payload from uncompressVolumeData withWriteLock([&] { loop3(ivec3(0), ivec3(voxelXSize, voxelYSize, voxelZSize), [&](const ivec3& v) { int uncompressedIndex = (v.z * voxelYSize * voxelXSize) + (v.y * voxelZSize) + v.x; setVoxelInternal(v, uncompressedData[uncompressedIndex]); }); - _volDataDirty = true; + + _state = PolyVoxState::UncompressingFinished; }); } @@ -972,10 +1117,7 @@ void RenderablePolyVoxEntityItem::compressVolumeDataAndSendEditPacket() { voxelZSize = _voxelVolumeSize.z; }); - EntityTreeElementPointer element = getElement(); - EntityTreePointer tree = element ? element->getTree() : nullptr; - - QtConcurrent::run([voxelXSize, voxelYSize, voxelZSize, entity, tree] { + QtConcurrent::run([voxelXSize, voxelYSize, voxelZSize, entity] { auto polyVoxEntity = std::static_pointer_cast(entity); QByteArray uncompressedData = polyVoxEntity->volDataToArray(voxelXSize, voxelYSize, voxelZSize); @@ -992,17 +1134,37 @@ void RenderablePolyVoxEntityItem::compressVolumeDataAndSendEditPacket() { // HACK -- until we have a way to allow for properties larger than MTU, don't update. // revert the active voxel-space to the last version that fit. qCDebug(entitiesrenderer) << "compressed voxel data is too large" << entity->getName() << entity->getID(); + + const auto polyVoxEntity = std::static_pointer_cast(entity); + polyVoxEntity->compressVolumeDataFinished(QByteArray()); return; } - auto now = usecTimestampNow(); - entity->setLastEdited(now); - entity->setLastBroadcast(now); + std::static_pointer_cast(entity)->compressVolumeDataFinished(newVoxelData); + }); +} - std::static_pointer_cast(entity)->setVoxelData(newVoxelData); +void RenderablePolyVoxEntityItem::compressVolumeDataFinished(const QByteArray& voxelData) { + // compressed voxel information from the entity-server + withWriteLock([&] { + if (voxelData.size() > 0 && _voxelData != voxelData) { + _voxelData = voxelData; + } + _state = PolyVoxState::CompressingFinished; + }); + auto now = usecTimestampNow(); + setLastEdited(now); + setLastBroadcast(now); + + EntityTreeElementPointer element = getElement(); + EntityTreePointer tree = element ? element->getTree() : nullptr; + + if (tree) { tree->withReadLock([&] { - EntityItemProperties properties = entity->getProperties(); + EntityPropertyFlags desiredProperties; + desiredProperties.setHasProperty(PROP_VOXEL_DATA); + EntityItemProperties properties = getProperties(desiredProperties, false); properties.setVoxelDataDirty(); properties.setLastEdited(now); @@ -1010,12 +1172,13 @@ void RenderablePolyVoxEntityItem::compressVolumeDataAndSendEditPacket() { PhysicalEntitySimulationPointer peSimulation = std::static_pointer_cast(simulation); EntityEditPacketSender* packetSender = peSimulation ? peSimulation->getPacketSender() : nullptr; if (packetSender) { - packetSender->queueEditEntityMessage(PacketType::EntityEdit, tree, entity->getID(), properties); + packetSender->queueEditEntityMessage(PacketType::EntityEdit, tree, getID(), properties); } }); - }); + } } + EntityItemPointer lookUpNeighbor(EntityTreePointer tree, EntityItemID neighborID, EntityItemWeakPointer& currentWP) { EntityItemPointer current = currentWP.lock(); @@ -1064,56 +1227,103 @@ void RenderablePolyVoxEntityItem::copyUpperEdgesFromNeighbors() { return; } - auto currentXPNeighbor = getXPNeighbor(); - auto currentYPNeighbor = getYPNeighbor(); - auto currentZPNeighbor = getZPNeighbor(); - - if (currentXPNeighbor && currentXPNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { - withWriteLock([&] { - for (int y = 0; y < _volData->getHeight(); y++) { - for (int z = 0; z < _volData->getDepth(); z++) { - uint8_t neighborValue = currentXPNeighbor->getVoxel({ 0, y, z }); - if ((y == 0 || z == 0) && _volData->getVoxelAt(_volData->getWidth() - 1, y, z) != neighborValue) { - bonkNeighbors(); - } - _volData->setVoxelAt(_volData->getWidth() - 1, y, z, neighborValue); - } - } - }); + if (!_updateFromNeighborXEdge && !_updateFromNeighborYEdge && !_updateFromNeighborZEdge) { + return; } + cacheNeighbors(); - if (currentYPNeighbor && currentYPNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { - withWriteLock([&] { - for (int x = 0; x < _volData->getWidth(); x++) { - for (int z = 0; z < _volData->getDepth(); z++) { - uint8_t neighborValue = currentYPNeighbor->getVoxel({ x, 0, z }); - if ((x == 0 || z == 0) && _volData->getVoxelAt(x, _volData->getHeight() - 1, z) != neighborValue) { - bonkNeighbors(); - } - _volData->setVoxelAt(x, _volData->getHeight() - 1, z, neighborValue); - } - } - }); - } - - - if (currentZPNeighbor && currentZPNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { - withWriteLock([&] { - for (int x = 0; x < _volData->getWidth(); x++) { + if (_updateFromNeighborXEdge) { + _updateFromNeighborXEdge = false; + auto currentXPNeighbor = getXPNeighbor(); + if (currentXPNeighbor && currentXPNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { + withWriteLock([&] { + int x = _volData->getWidth() - 1; for (int y = 0; y < _volData->getHeight(); y++) { - uint8_t neighborValue = currentZPNeighbor->getVoxel({ x, y, 0 }); - _volData->setVoxelAt(x, y, _volData->getDepth() - 1, neighborValue); - if ((x == 0 || y == 0) && _volData->getVoxelAt(x, y, _volData->getDepth() - 1) != neighborValue) { - bonkNeighbors(); + for (int z = 0; z < _volData->getDepth(); z++) { + uint8_t neighborValue = currentXPNeighbor->getVoxel({ 0, y, z }); + uint8_t prevValue = _volData->getVoxelAt(x, y, z); + if (prevValue != neighborValue) { + _volData->setVoxelAt(x, y, z, neighborValue); + _volDataDirty = true; + } } - _volData->setVoxelAt(x, y, _volData->getDepth() - 1, neighborValue); } - } - }); + }); + } + } + + if (_updateFromNeighborYEdge) { + _updateFromNeighborYEdge = false; + auto currentYPNeighbor = getYPNeighbor(); + if (currentYPNeighbor && currentYPNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { + withWriteLock([&] { + int y = _volData->getHeight() - 1; + for (int x = 0; x < _volData->getWidth(); x++) { + for (int z = 0; z < _volData->getDepth(); z++) { + uint8_t neighborValue = currentYPNeighbor->getVoxel({ x, 0, z }); + uint8_t prevValue = _volData->getVoxelAt(x, y, z); + if (prevValue != neighborValue) { + _volData->setVoxelAt(x, y, z, neighborValue); + _volDataDirty = true; + } + } + } + }); + } + } + + if (_updateFromNeighborZEdge) { + _updateFromNeighborZEdge = false; + auto currentZPNeighbor = getZPNeighbor(); + if (currentZPNeighbor && currentZPNeighbor->getVoxelVolumeSize() == _voxelVolumeSize) { + withWriteLock([&] { + int z = _volData->getDepth() - 1; + for (int x = 0; x < _volData->getWidth(); x++) { + for (int y = 0; y < _volData->getHeight(); y++) { + uint8_t neighborValue = currentZPNeighbor->getVoxel({ x, y, 0 }); + uint8_t prevValue = _volData->getVoxelAt(x, y, z); + if (prevValue != neighborValue) { + _volData->setVoxelAt(x, y, z, neighborValue); + _volDataDirty = true; + } + } + } + }); + } } } +void RenderablePolyVoxEntityItem::tellNeighborsToRecopyEdges(bool force) { + // if this polyvox has changed any of its voxels with a zero coord (in x, y, or z) notify neighbors, if there are any + if (force || _neighborXNeedsUpdate || _neighborYNeedsUpdate || _neighborZNeedsUpdate) { + cacheNeighbors(); + + if (force || _neighborXNeedsUpdate) { + _neighborXNeedsUpdate = false; + auto currentXNNeighbor = getXNNeighbor(); + if (currentXNNeighbor) { + currentXNNeighbor->neighborXEdgeChanged(); + } + } + if (force || _neighborYNeedsUpdate) { + _neighborYNeedsUpdate = false; + auto currentYNNeighbor = getYNNeighbor(); + if (currentYNNeighbor) { + currentYNNeighbor->neighborYEdgeChanged(); + } + } + if (force || _neighborZNeedsUpdate) { + _neighborZNeedsUpdate = false; + auto currentZNNeighbor = getZNNeighbor(); + if (currentZNNeighbor) { + currentZNNeighbor->neighborZEdgeChanged(); + } + } + } +} + + void RenderablePolyVoxEntityItem::recomputeMesh() { // use _volData to make a renderable mesh PolyVoxSurfaceStyle voxelSurfaceStyle; @@ -1121,9 +1331,6 @@ void RenderablePolyVoxEntityItem::recomputeMesh() { voxelSurfaceStyle = _voxelSurfaceStyle; }); - cacheNeighbors(); - copyUpperEdgesFromNeighbors(); - auto entity = std::static_pointer_cast(getThisPointer()); QtConcurrent::run([entity, voxelSurfaceStyle] { @@ -1135,24 +1342,14 @@ void RenderablePolyVoxEntityItem::recomputeMesh() { entity->withReadLock([&] { PolyVox::SimpleVolume* volData = entity->getVolData(); switch (voxelSurfaceStyle) { - case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: { - PolyVox::MarchingCubesSurfaceExtractor> surfaceExtractor - (volData, volData->getEnclosingRegion(), &polyVoxMesh); - surfaceExtractor.execute(); - break; - } + case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: { PolyVox::MarchingCubesSurfaceExtractor> surfaceExtractor (volData, volData->getEnclosingRegion(), &polyVoxMesh); surfaceExtractor.execute(); break; } - case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: { - PolyVox::CubicSurfaceExtractorWithNormals> surfaceExtractor - (volData, volData->getEnclosingRegion(), &polyVoxMesh); - surfaceExtractor.execute(); - break; - } + case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: case PolyVoxEntityItem::SURFACE_CUBIC: { PolyVox::CubicSurfaceExtractorWithNormals> surfaceExtractor (volData, volData->getEnclosingRegion(), &polyVoxMesh); @@ -1180,7 +1377,6 @@ void RenderablePolyVoxEntityItem::recomputeMesh() { gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); mesh->setVertexBuffer(vertexBufferView); - // TODO -- use 3-byte normals rather than 3-float normals mesh->addAttribute(gpu::Stream::NORMAL, gpu::BufferView(vertexBufferPtr, @@ -1194,28 +1390,24 @@ void RenderablePolyVoxEntityItem::recomputeMesh() { (graphics::Index)vecIndices.size(), // numIndices (graphics::Index)0, // baseVertex graphics::Mesh::TRIANGLES)); // topology - mesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(graphics::Mesh::Part), - (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); + mesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(parts.size() * sizeof(graphics::Mesh::Part), (gpu::Byte*) parts.data()), + gpu::Element::PART_DRAWCALL)); entity->setMesh(mesh); }); } void RenderablePolyVoxEntityItem::setMesh(graphics::MeshPointer mesh) { // this catches the payload from recomputeMesh - bool neighborsNeedUpdate; withWriteLock([&] { if (!_collisionless) { _flags |= Simulation::DIRTY_SHAPE | Simulation::DIRTY_MASS; } + _shapeReady = false; _mesh = mesh; - _meshDirty = true; + _state = PolyVoxState::BakingMeshFinished; _meshReady = true; - neighborsNeedUpdate = _neighborsNeedUpdate; - _neighborsNeedUpdate = false; + startUpdates(); }); - if (neighborsNeedUpdate) { - bonkNeighbors(); - } somethingChangedNotification(); } @@ -1223,9 +1415,6 @@ void RenderablePolyVoxEntityItem::setMesh(graphics::MeshPointer mesh) { void RenderablePolyVoxEntityItem::computeShapeInfoWorker() { // this creates a collision-shape for the physics engine. The shape comes from // _volData for cubic extractors and from _mesh for marching-cube extractors - if (!_meshReady) { - return; - } EntityItemPointer entity = getThisPointer(); @@ -1295,8 +1484,8 @@ void RenderablePolyVoxEntityItem::computeShapeInfoWorker() { const auto& x = v.x; const auto& y = v.y; const auto& z = v.z; - if (glm::all(glm::greaterThan(v, ivec3(0))) && - glm::all(glm::lessThan(v, ivec3(voxelVolumeSize) - 1)) && + if (glm::all(glm::greaterThan(v, ivec3(0))) && + glm::all(glm::lessThan(v, ivec3(voxelVolumeSize) - 1)) && (polyVoxEntity->getVoxelInternal({ x - 1, y, z }) > 0) && (polyVoxEntity->getVoxelInternal({ x, y - 1, z }) > 0) && (polyVoxEntity->getVoxelInternal({ x, y, z - 1 }) > 0) && @@ -1360,6 +1549,10 @@ void RenderablePolyVoxEntityItem::setCollisionPoints(ShapeInfo::PointCollection // this catches the payload from computeShapeInfoWorker if (pointCollection.isEmpty()) { EntityItem::computeShapeInfo(_shapeInfo); + withWriteLock([&] { + _shapeReady = true; + _state = PolyVoxState::BakingShapeFinished; + }); return; } @@ -1373,7 +1566,8 @@ void RenderablePolyVoxEntityItem::setCollisionPoints(ShapeInfo::PointCollection QString::number(_registrationPoint.z); _shapeInfo.setParams(SHAPE_TYPE_COMPOUND, collisionModelDimensions, shapeKey); _shapeInfo.setPointCollection(pointCollection); - _meshDirty = false; + _shapeReady = true; + _state = PolyVoxState::BakingShapeFinished; }); } @@ -1384,7 +1578,8 @@ void RenderablePolyVoxEntityItem::setXNNeighborID(const EntityItemID& xNNeighbor if (xNNeighborID != _xNNeighborID) { PolyVoxEntityItem::setXNNeighborID(xNNeighborID); - cacheNeighbors(); + _neighborXNeedsUpdate = true; + startUpdates(); } } @@ -1395,7 +1590,8 @@ void RenderablePolyVoxEntityItem::setYNNeighborID(const EntityItemID& yNNeighbor if (yNNeighborID != _yNNeighborID) { PolyVoxEntityItem::setYNNeighborID(yNNeighborID); - cacheNeighbors(); + _neighborYNeedsUpdate = true; + startUpdates(); } } @@ -1406,7 +1602,8 @@ void RenderablePolyVoxEntityItem::setZNNeighborID(const EntityItemID& zNNeighbor if (zNNeighborID != _zNNeighborID) { PolyVoxEntityItem::setZNNeighborID(zNNeighborID); - cacheNeighbors(); + _neighborZNeedsUpdate = true; + startUpdates(); } } @@ -1416,7 +1613,8 @@ void RenderablePolyVoxEntityItem::setXPNeighborID(const EntityItemID& xPNeighbor } if (xPNeighborID != _xPNeighborID) { PolyVoxEntityItem::setXPNeighborID(xPNeighborID); - _volDataDirty = true; + _updateFromNeighborXEdge = true; + startUpdates(); } } @@ -1426,7 +1624,8 @@ void RenderablePolyVoxEntityItem::setYPNeighborID(const EntityItemID& yPNeighbor } if (yPNeighborID != _yPNeighborID) { PolyVoxEntityItem::setYPNeighborID(yPNeighborID); - _volDataDirty = true; + _updateFromNeighborYEdge = true; + startUpdates(); } } @@ -1436,7 +1635,8 @@ void RenderablePolyVoxEntityItem::setZPNeighborID(const EntityItemID& zPNeighbor } if (zPNeighborID != _zPNeighborID) { PolyVoxEntityItem::setZPNeighborID(zPNeighborID); - _volDataDirty = true; + _updateFromNeighborZEdge = true; + startUpdates(); } } @@ -1464,31 +1664,8 @@ std::shared_ptr RenderablePolyVoxEntityItem::getZPN return std::dynamic_pointer_cast(_zPNeighbor.lock()); } -void RenderablePolyVoxEntityItem::bonkNeighbors() { - // flag neighbors to the negative of this entity as needing to rebake their meshes. - cacheNeighbors(); - - auto currentXNNeighbor = getXNNeighbor(); - auto currentYNNeighbor = getYNNeighbor(); - auto currentZNNeighbor = getZNNeighbor(); - - if (currentXNNeighbor) { - currentXNNeighbor->setVolDataDirty(); - } - if (currentYNNeighbor) { - currentYNNeighbor->setVolDataDirty(); - } - if (currentZNNeighbor) { - currentZNNeighbor->setVolDataDirty(); - } -} - // deprecated bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) { - if (!updateDependents()) { - return false; - } - bool success = false; if (_mesh) { MeshProxy* meshProxy = nullptr; @@ -1517,7 +1694,7 @@ bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) { } scriptable::ScriptableModelBase RenderablePolyVoxEntityItem::getScriptableModel() { - if (!updateDependents() || !_mesh) { + if (!_mesh) { return scriptable::ScriptableModelBase(); } @@ -1628,9 +1805,6 @@ bool PolyVoxEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPo } void PolyVoxEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { - if (entity->_voxelDataDirty || entity->_volDataDirty) { - entity->updateDependents(); - } #ifdef POLYVOX_ENTITY_USE_FADE_EFFECT if (!_hasTransitioned) { @@ -1662,7 +1836,6 @@ void PolyVoxEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoi graphics::MeshPointer newMesh; entity->withReadLock([&] { newMesh = entity->_mesh; - }); if (newMesh && newMesh->getIndexBuffer()._buffer) { @@ -1705,3 +1878,41 @@ void PolyVoxEntityRenderer::doRender(RenderArgs* args) { batch.drawIndexed(gpu::TRIANGLES, (gpu::uint32)_mesh->getNumIndices(), 0); } +QDebug operator<<(QDebug debug, PolyVoxState state) { + switch (state) { + case PolyVoxState::Ready: + debug << "Ready"; + break; + case PolyVoxState::Uncompressing: + debug << "Uncompressing"; + break; + case PolyVoxState::UncompressingFinished: + debug << "UncompressingFinished"; + break; + case PolyVoxState::BakingMesh: + debug << "BakingMesh"; + break; + case PolyVoxState::BakingMeshFinished: + debug << "BakingMeshFinished"; + break; + case PolyVoxState::BakingMeshNoCompress: + debug << "BakingMeshNoCompress"; + break; + case PolyVoxState::BakingMeshNoCompressFinished: + debug << "BakingMeshNoCompressFinished"; + break; + case PolyVoxState::Compressing: + debug << "Compressing"; + break; + case PolyVoxState::CompressingFinished: + debug << "CompressingFinished"; + break; + case PolyVoxState::BakingShape: + debug << "BakingShape"; + break; + case PolyVoxState::BakingShapeFinished: + debug << "BakingShapeFinished"; + break; + } + return debug; +} diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index cca34767a4..c322959f86 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -30,7 +30,25 @@ namespace render { namespace entities { class PolyVoxEntityRenderer; -} } +} } + + +enum class PolyVoxState { + Ready, + Uncompressing, + UncompressingFinished, + BakingMesh, + BakingMeshFinished, + BakingMeshNoCompress, + BakingMeshNoCompressFinished, + Compressing, + CompressingFinished, + BakingShape, + BakingShapeFinished +}; + +QDebug operator<<(QDebug debug, PolyVoxState state); + class RenderablePolyVoxEntityItem : public PolyVoxEntityItem, public scriptable::ModelProvider { friend class render::entities::PolyVoxEntityRenderer; @@ -113,41 +131,61 @@ public: uint8_t getVoxelInternal(const ivec3& v) const; bool setVoxelInternal(const ivec3& v, uint8_t toValue); + void setVoxelMarkNeighbors(int x, int y, int z, uint8_t toValue); - void setVolDataDirty() { withWriteLock([&] { _volDataDirty = true; _meshReady = false; }); } + void compressVolumeDataFinished(const QByteArray& voxelData); + void neighborXEdgeChanged() { withWriteLock([&] { _updateFromNeighborXEdge = true; }); startUpdates(); } + void neighborYEdgeChanged() { withWriteLock([&] { _updateFromNeighborYEdge = true; }); startUpdates(); } + void neighborZEdgeChanged() { withWriteLock([&] { _updateFromNeighborZEdge = true; }); startUpdates(); } bool getMeshes(MeshProxyList& result) override; // deprecated virtual scriptable::ScriptableModelBase getScriptableModel() override; + virtual void update(const quint64& now) override; + bool needsToCallUpdate() const override { return _updateNeeded; } + private: bool updateOnCount(const ivec3& v, uint8_t toValue); PolyVox::RaycastResult doRayCast(glm::vec4 originInVoxel, glm::vec4 farInVoxel, glm::vec4& result) const; + void changeUpdates(bool value); + void startUpdates(); + void stopUpdates(); + void recomputeMesh(); void cacheNeighbors(); void copyUpperEdgesFromNeighbors(); - void bonkNeighbors(); + void tellNeighborsToRecopyEdges(bool force); bool updateDependents(); // these are run off the main thread - void decompressVolumeData(); + void uncompressVolumeData(); void compressVolumeDataAndSendEditPacket(); void computeShapeInfoWorker(); // The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions // may not match _voxelVolumeSize. - bool _meshDirty { true }; // does collision-shape need to be recomputed? - bool _meshReady{ false }; + bool _meshReady { false }; // do we have something to give scripts that ask for the mesh? + bool _voxelDataDirty { false }; // do we need to uncompress data and expand it into _volData? + bool _volDataDirty { false }; // does recomputeMesh need to be called? + bool _shapeReady { false }; // are we ready to tell bullet our shape? + PolyVoxState _state { PolyVoxState::Ready }; + bool _updateNeeded { true }; + graphics::MeshPointer _mesh; ShapeInfo _shapeInfo; std::shared_ptr> _volData; - bool _voxelDataDirty{ true }; - bool _volDataDirty { false }; // does recomputeMesh need to be called? int _onCount; // how many non-zero voxels are in _volData - bool _neighborsNeedUpdate { false }; + bool _neighborXNeedsUpdate { false }; + bool _neighborYNeedsUpdate { false }; + bool _neighborZNeedsUpdate { false }; + + bool _updateFromNeighborXEdge { false }; + bool _updateFromNeighborYEdge { false }; + bool _updateFromNeighborZEdge { false }; // these are cached lookups of _xNNeighborID, _yNNeighborID, _zNNeighborID, _xPNeighborID, _yPNeighborID, _zPNeighborID EntityItemWeakPointer _xNNeighbor; // neighbor found by going along negative X axis @@ -156,7 +194,6 @@ private: EntityItemWeakPointer _xPNeighbor; // neighbor found by going along positive X axis EntityItemWeakPointer _yPNeighbor; EntityItemWeakPointer _zPNeighbor; - }; namespace render { namespace entities { @@ -170,7 +207,7 @@ public: virtual scriptable::ScriptableModelBase getScriptableModel() override { return asTypedEntity()->getScriptableModel(); } - + protected: virtual ItemKey getKey() override { return ItemKey::Builder::opaqueShape().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()); } virtual ShapeKey getShapeKey() override; @@ -192,7 +229,6 @@ private: glm::mat4 _lastVoxelToWorldMatrix; PolyVoxEntityItem::PolyVoxSurfaceStyle _lastSurfaceStyle { PolyVoxEntityItem::SURFACE_MARCHING_CUBES }; std::array _xyzTextureUrls; - bool _neighborsNeedUpdate{ false }; }; } } From 57a309db537a47f973d47e3f1ee1d9dd82d9e0be Mon Sep 17 00:00:00 2001 From: milad Date: Wed, 4 Sep 2019 20:58:20 -0700 Subject: [PATCH 40/46] small formatting changes --- .../emojiApp/simplifiedEmoji.js | 23 ++++--------------- .../simplifiedEmote/simplifiedEmote.js | 5 ++-- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js index 6d9c452162..a0fe6cf811 100644 --- a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js +++ b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js @@ -394,7 +394,6 @@ function startup() { emojiCodeMap = emojiList.reduce(function (codeMap, currentEmojiInList, index) { if ( currentEmojiInList && - currentEmojiInList.code && currentEmojiInList.code.length > 0 && currentEmojiInList.code[UTF_CODE]) { @@ -423,7 +422,7 @@ function startup() { function AviMoji() { _this = this; - this._avimojiQMLWindow; + this._avimojiQMLWindow = null; } AviMoji.prototype = { @@ -435,20 +434,11 @@ function startup() { } -// #endregion -// ************************************* -// END main -// ************************************* - -// ************************************* -// START API -// ************************************* -// #region API - function registerAvimojiQMLWindow(avimojiQMLWindow) { this._avimojiQMLWindow = avimojiQMLWindow; } + function addEmojiFromQML(code) { var emojiObject = emojiList[emojiCodeMap[code]]; var emojiFilename; @@ -461,6 +451,7 @@ function addEmojiFromQML(code) { handleSelectedEmoji(emojiFilename); } + function unload() { resetEmojis(); if (signalsConnected) { @@ -470,11 +461,7 @@ function unload() { } } + var aviMoji = startup(); -module.exports = aviMoji; - -// #endregion -// ************************************* -// END API -// ************************************* \ No newline at end of file +module.exports = aviMoji; \ No newline at end of file diff --git a/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js b/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js index d1396c8ccf..abf0dd73e8 100644 --- a/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js +++ b/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js @@ -38,7 +38,6 @@ var customEmojiList = Script.require("./emojiApp/resources/modules/customEmojiLi // #region EMOTE_UTILITY - function updateEmoteAppBarPosition() { if (!emoteAppBarWindow) { return; @@ -548,7 +547,7 @@ var emojiAPI = Script.require("./emojiApp/simplifiedEmoji.js"); var keyPressSignalsConnected = false; var emojiCodeMap; var customEmojiCodeMap; -function init() { +function setup() { deleteOldReticles(); // make a map of just the utf codes to help with accesing @@ -755,4 +754,4 @@ function toggleEmojiApp() { // END EMOJI // ************************************* -init(); \ No newline at end of file +setup(); \ No newline at end of file From 404b42c41e6c34ae73df44ebc126129a01caa770 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 5 Sep 2019 08:04:09 -0700 Subject: [PATCH 41/46] remove unneeded call to tellNeighborsToRecopyEdges --- libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 7e555e665b..853e36b45b 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -916,7 +916,6 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(const glm::vec3& voxelVolum _volData.reset(); _onCount = 0; _updateFromNeighborXEdge = _updateFromNeighborYEdge = _updateFromNeighborZEdge = true; - tellNeighborsToRecopyEdges(true); startUpdates(); static const PolyVox::Vector3DInt32 lowCorner(0, 0, 0); From 531dceae4d13f221b99ee02f3fb12f504d112305 Mon Sep 17 00:00:00 2001 From: milad Date: Thu, 5 Sep 2019 10:29:25 -0700 Subject: [PATCH 42/46] changed status indicator to be similar to nametag and emoji --- .../ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js b/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js index d9331c62a3..4d06ecc99b 100644 --- a/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js +++ b/scripts/simplifiedUI/ui/simplifiedStatusIndicator/simplifiedStatusIndicator.js @@ -247,4 +247,6 @@ function SimplifiedStatusIndicator() { startup(); } -module.exports = new SimplifiedStatusIndicator(); \ No newline at end of file +var simplifiedStatusIndicator = new SimplifiedStatusIndicator(); + +module.exports = simplifiedStatusIndicator; \ No newline at end of file From 43237e14094908f4d117bd9e6f915e942093727d Mon Sep 17 00:00:00 2001 From: Matt Hardcastle Date: Thu, 5 Sep 2019 09:49:38 -0700 Subject: [PATCH 43/46] Check macOS Launcher's zip size before unzipping The Launcher can download an error page rather than the full Launcher. When this happens, the error page file is passed directly to unzip, which promptly fails with the following message: End-of-central-directory signature not found. Either this file is not a zipfile, or it constitutes one disk of a multi-part archive. In the latter case the central directory and zipfile comment will be found on the last disk(s) of this archive. unzip: cannot find zipfile directory in one of NewHQLauncher.zip or NewHQLauncher.zip.zip, and cannot find NewHQLauncher.zip.ZIP, period. This change improves the error message by checking the size of the Launcher download and failing if the Launcher is smaller than the smallest Launcher we've released. The smallest Launcher we've had is 308KB, so I picked 250KB as the limit because it's a nice rounder number below that. --- launchers/darwin/src/DownloadLauncher.m | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/launchers/darwin/src/DownloadLauncher.m b/launchers/darwin/src/DownloadLauncher.m index 7c32cf7d90..c54227ba83 100644 --- a/launchers/darwin/src/DownloadLauncher.m +++ b/launchers/darwin/src/DownloadLauncher.m @@ -1,6 +1,10 @@ #import "DownloadLauncher.h" #import "Launcher.h" +#include + +static const __int32_t kMinLauncherSize = 250000; // 308kb is our smallest launcher +static const NSString *kIOError = @"IOError"; @implementation DownloadLauncher @@ -22,8 +26,38 @@ } +-(void)validateHQLauncherZipAt:(NSURL *)location { + // Does the file look like a valid HQLauncher ZIP? + struct stat lStat; + const char *cStrLocation = location.fileSystemRepresentation; + if (stat(cStrLocation, &lStat) != 0) { + NSLog(@"couldn't stat download file: %s", cStrLocation); + @throw [NSException exceptionWithName:(NSString *)kIOError + reason:@"couldn't stat download file" + userInfo:nil]; + } + if (lStat.st_size <= kMinLauncherSize) { + NSLog(@"download is too small: %s is %lld bytes, should be at least %d bytes", + cStrLocation, lStat.st_size, kMinLauncherSize); + @throw [NSException exceptionWithName:(NSString *)kIOError + reason:@"download is too small" + userInfo:nil]; + } +} + -(void)URLSession:(NSURLSession*)session downloadTask:(NSURLSessionDownloadTask*)downloadTask didFinishDownloadingToURL:(NSURL*)location { NSLog(@"Did finish downloading to url"); + @try { + [self validateHQLauncherZipAt:location]; + } + @catch (NSException *exc) { + if ([exc.name isEqualToString:(NSString *)kIOError]) { + [[Launcher sharedLauncher] displayErrorPage]; + return; + } + @throw; + } + NSError* error = nil; NSFileManager* fileManager = [NSFileManager defaultManager]; NSString* destinationFileName = downloadTask.originalRequest.URL.lastPathComponent; From 2a3b99daa63ad1d42bc553f194161108187c521a Mon Sep 17 00:00:00 2001 From: amerhifi Date: Thu, 5 Sep 2019 13:40:29 -0700 Subject: [PATCH 44/46] removing flags --- launchers/win32/LauncherUtils.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/launchers/win32/LauncherUtils.cpp b/launchers/win32/LauncherUtils.cpp index cd0c15ccc3..88cb84eb6e 100644 --- a/launchers/win32/LauncherUtils.cpp +++ b/launchers/win32/LauncherUtils.cpp @@ -150,8 +150,6 @@ BOOL LauncherUtils::launchApplication(LPCWSTR lpApplicationName, LPTSTR cmdArgs) ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); - - si.dwFlags = STARTF_TITLEISAPPID | STARTF_PREVENTPINNING; // start the program up BOOL success = CreateProcess( lpApplicationName, // the path From 9e69b79e2add9acc599178d9231107dab2b60908 Mon Sep 17 00:00:00 2001 From: amerhifi Date: Thu, 5 Sep 2019 13:41:51 -0700 Subject: [PATCH 45/46] adding the space back --- launchers/win32/LauncherUtils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/launchers/win32/LauncherUtils.cpp b/launchers/win32/LauncherUtils.cpp index 88cb84eb6e..4f8e7f9a74 100644 --- a/launchers/win32/LauncherUtils.cpp +++ b/launchers/win32/LauncherUtils.cpp @@ -150,6 +150,7 @@ BOOL LauncherUtils::launchApplication(LPCWSTR lpApplicationName, LPTSTR cmdArgs) ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); + // start the program up BOOL success = CreateProcess( lpApplicationName, // the path From 7c84d897ba56590b0ff355d993a01917f5d63f86 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 5 Sep 2019 14:16:36 -0700 Subject: [PATCH 46/46] Fix webrtc link errors in debug builds --- cmake/macros/TargetWebRTC.cmake | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/macros/TargetWebRTC.cmake b/cmake/macros/TargetWebRTC.cmake index d2821528df..d215b0698e 100644 --- a/cmake/macros/TargetWebRTC.cmake +++ b/cmake/macros/TargetWebRTC.cmake @@ -15,9 +15,11 @@ macro(TARGET_WEBRTC) # select_library_configurations(WEBRTC) else() set(WEBRTC_INCLUDE_DIRS "${VCPKG_INSTALL_ROOT}/include/webrtc") - find_library(WEBRTC_LIBRARY NAMES webrtc PATHS ${VCPKG_INSTALL_ROOT}/lib/ NO_DEFAULT_PATH) target_include_directories(${TARGET_NAME} SYSTEM PUBLIC ${WEBRTC_INCLUDE_DIRS}) - target_link_libraries(${TARGET_NAME} ${WEBRTC_LIBRARY}) + find_library(WEBRTC_LIBRARY_RELEASE webrtc PATHS ${VCPKG_INSTALL_ROOT}/lib NO_DEFAULT_PATH) + find_library(WEBRTC_LIBRARY_DEBUG webrtc PATHS ${VCPKG_INSTALL_ROOT}/debug/lib NO_DEFAULT_PATH) + select_library_configurations(WEBRTC) + target_link_libraries(${TARGET_NAME} ${WEBRTC_LIBRARIES}) endif()