From 321d281919eaacec5b9f608bbe73098ab6b3ca15 Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Fri, 21 Apr 2017 01:46:44 -0700 Subject: [PATCH 01/31] Separating job/task classes from the render specific --- libraries/render/src/render/Context.h | 20 ++++++- libraries/render/src/render/Task.h | 84 +++++++++++++++++---------- 2 files changed, 71 insertions(+), 33 deletions(-) diff --git a/libraries/render/src/render/Context.h b/libraries/render/src/render/Context.h index cb0fc65d40..c493bda4b2 100644 --- a/libraries/render/src/render/Context.h +++ b/libraries/render/src/render/Context.h @@ -14,14 +14,28 @@ #include "Scene.h" + +namespace task { + +class JobConfig; + +class JobContext { +public: + virtual ~JobContext() {} + + std::shared_ptr jobConfig{ nullptr }; +}; +using JobContextPointer = std::shared_ptr; +} + namespace render { - class JobConfig; -class RenderContext { +class RenderContext : public task::JobContext { public: + virtual ~RenderContext() {} + RenderArgs* args; - std::shared_ptr jobConfig{ nullptr }; ScenePointer _scene; }; using RenderContextPointer = std::shared_ptr; diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 1035b74340..a4d60b25cc 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -28,13 +28,9 @@ #include "gpu/Batch.h" #include -namespace render { - -class Varying; - +namespace task { // A varying piece of data, to be used as Job/Task I/O -// TODO: Task IO class Varying { public: Varying() {} @@ -300,9 +296,9 @@ public: } }; -class Job; class JobConcept; -class Task; +template class JobT; +template class TaskT; class JobNoIO {}; template class PersistentConfig : public C { @@ -433,13 +429,11 @@ public: void connectChildConfig(QConfigPointer childConfig, const std::string& name); void transferChildrenConfigs(QConfigPointer source); + + JobConcept* _task; public slots: void refresh(); - -private: - friend Task; - JobConcept* _task; }; template void jobConfigure(T& data, const C& configuration) { @@ -451,16 +445,17 @@ template void jobConfigure(T&, const JobConfig&) { template void jobConfigure(T&, const TaskConfig&) { // nop, as the default TaskConfig was used, so the data does not need a configure method } -template void jobRun(T& data, const RenderContextPointer& renderContext, const JobNoIO& input, JobNoIO& output) { + +template void jobRun(T& data, const RC& renderContext, const JobNoIO& input, JobNoIO& output) { data.run(renderContext); } -template void jobRun(T& data, const RenderContextPointer& renderContext, const I& input, JobNoIO& output) { +template void jobRun(T& data, const RC& renderContext, const I& input, JobNoIO& output) { data.run(renderContext, input); } -template void jobRun(T& data, const RenderContextPointer& renderContext, const JobNoIO& input, O& output) { +template void jobRun(T& data, const RC& renderContext, const JobNoIO& input, O& output) { data.run(renderContext, output); } -template void jobRun(T& data, const RenderContextPointer& renderContext, const I& input, O& output) { +template void jobRun(T& data, const RC& renderContext, const I& input, O& output) { data.run(renderContext, input, output); } @@ -479,22 +474,29 @@ public: virtual QConfigPointer& getConfiguration() { return _config; } virtual void applyConfiguration() = 0; - virtual void run(const RenderContextPointer& renderContext) = 0; - -protected: void setCPURunTime(double mstime) { std::static_pointer_cast(_config)->setCPURunTime(mstime); } QConfigPointer _config; - - friend class Job; +protected: }; +template class Job { public: - using Concept = JobConcept; + using Context = RC; + using ContextPointer = std::shared_ptr; using Config = JobConfig; using QConfigPointer = std::shared_ptr; using None = JobNoIO; + + //template + class Concept : public JobConcept { + public: + Concept(QConfigPointer config) : JobConcept(config) {} + virtual ~Concept() = default; + + virtual void run(const ContextPointer& renderContext) = 0; + }; using ConceptPointer = std::shared_ptr; template class Model : public Concept { @@ -529,7 +531,7 @@ public: jobConfigure(_data, *std::static_pointer_cast(_config)); } - void run(const RenderContextPointer& renderContext) override { + void run(const ContextPointer& renderContext) override { renderContext->jobConfig = std::static_pointer_cast(_config); if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->isEnabled()) { jobRun(_data, renderContext, _input.get(), _output.edit()); @@ -554,7 +556,7 @@ public: return concept->_data; } - void run(const RenderContextPointer& renderContext) { + virtual void run(const ContextPointer& renderContext) { PerformanceTimer perfTimer(_name.c_str()); PROFILE_RANGE(render, _name.c_str()); auto start = usecTimestampNow(); @@ -576,13 +578,17 @@ protected: // The build method is where child Jobs can be added internally to the task // where the input of the task can be setup to feed the child jobs // and where the output of the task is defined -class Task : public Job { +template +class Task : public Job { public: + using Context = RC; + using ContextPointer = std::shared_ptr; using Config = TaskConfig; - using QConfigPointer = Job::QConfigPointer; - using None = Job::None; - using Concept = Job::Concept; - using Jobs = std::vector; + using _Job = Job; + using QConfigPointer = _Job::QConfigPointer; + using None = _Job::None; + using Concept = _Job::Concept; + using Jobs = std::vector<_Job>; Task(std::string name, ConceptPointer concept) : Job(name, concept) {} @@ -627,7 +633,6 @@ public: template static std::shared_ptr create(const Varying& input, A&&... args) { auto model = std::make_shared(input, std::make_shared()); - // std::static_pointer_cast(model->_config)->_task = model.get(); model->_data.build(*(model), model->_input, model->_output, std::forward(args)...); @@ -669,7 +674,7 @@ public: } } - void run(const RenderContextPointer& renderContext) override { + void run(const ContextPointer& renderContext) override { auto config = std::static_pointer_cast(_config); if (config->alwaysEnabled || config->enabled) { for (auto job : _jobs) { @@ -698,6 +703,25 @@ public: protected: }; +} + +namespace render { +using JobConfig =task::JobConfig; +using TaskConfig =task::TaskConfig; + +template using PersistentConfig = task::PersistentConfig; + +using Job = task::Job; +using Task = task::Task; + +using Varying = task::Varying; +template < typename T0, typename T1 > using VaryingSet2 = task::VaryingSet2; +template < typename T0, typename T1, typename T2 > using VaryingSet3 = task::VaryingSet3; +template < typename T0, typename T1, typename T2, typename T3 > using VaryingSet4 = task::VaryingSet4; +template < typename T0, typename T1, typename T2, typename T3, typename T4 > using VaryingSet5 = task::VaryingSet5; +template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5 > using VaryingSet6 = task::VaryingSet6; +template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > using VaryingSet7 = task::VaryingSet7; +template < class T, int NUM > using VaryingArray = task::VaryingArray; // Versions of the COnfig integrating a gpu & batch timer class GPUJobConfig : public JobConfig { From 8e73fa3eb4a3855a3fe13319c5ba14ca46d0d299 Mon Sep 17 00:00:00 2001 From: samcake Date: Fri, 21 Apr 2017 18:16:07 -0700 Subject: [PATCH 02/31] Separating the task classes in their own folder, and easing the declaration --- .../render-utils/src/DeferredLightingEffect.h | 1 - .../render-utils/src/RenderShadowTask.cpp | 1 - libraries/render/src/render/Context.h | 46 -- libraries/render/src/render/Engine.h | 61 +- .../src/render/RenderFetchCullSortTask.h | 2 - libraries/render/src/render/Task.h | 769 ------------------ .../src/{render/Task.cpp => task/Config.cpp} | 10 +- libraries/render/src/task/Config.h | 169 ++++ libraries/render/src/task/Task.h | 326 ++++++++ libraries/render/src/task/Varying.h | 287 +++++++ tests/gpu-test/src/TestWindow.h | 2 +- 11 files changed, 847 insertions(+), 827 deletions(-) delete mode 100644 libraries/render/src/render/Context.h delete mode 100644 libraries/render/src/render/Task.h rename libraries/render/src/{render/Task.cpp => task/Config.cpp} (95%) create mode 100644 libraries/render/src/task/Config.h create mode 100644 libraries/render/src/task/Task.h create mode 100644 libraries/render/src/task/Varying.h diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index c5e694cb18..dcf0c84622 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -20,7 +20,6 @@ #include "model/Light.h" #include "model/Geometry.h" -#include "render/Context.h" #include #include "DeferredFrameTransform.h" diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 0a4371cccd..d7ec087174 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -15,7 +15,6 @@ #include -#include #include #include #include diff --git a/libraries/render/src/render/Context.h b/libraries/render/src/render/Context.h deleted file mode 100644 index c493bda4b2..0000000000 --- a/libraries/render/src/render/Context.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// Context.h -// render/src/render -// -// Created by Zach Pomerantz on 1/6/2015. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_render_Context_h -#define hifi_render_Context_h - -#include "Scene.h" - - -namespace task { - -class JobConfig; - -class JobContext { -public: - virtual ~JobContext() {} - - std::shared_ptr jobConfig{ nullptr }; -}; -using JobContextPointer = std::shared_ptr; -} - -namespace render { - - -class RenderContext : public task::JobContext { -public: - virtual ~RenderContext() {} - - RenderArgs* args; - ScenePointer _scene; -}; -using RenderContextPointer = std::shared_ptr; - -} - -#endif // hifi_render_Context_h - diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 68d86e6c16..d4dba0e340 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -14,10 +14,67 @@ #include -#include "Context.h" -#include "Task.h" +#include "Scene.h" +#include "../task/Task.h" +#include "gpu/Batch.h" + namespace render { + + + class RenderContext : public task::JobContext { + public: + virtual ~RenderContext() {} + + RenderArgs* args; + ScenePointer _scene; + }; + using RenderContextPointer = std::shared_ptr; + + Task_DeclareTypeAliases(RenderContext) + + // Versions of the COnfig integrating a gpu & batch timer + class GPUJobConfig : public JobConfig { + Q_OBJECT + Q_PROPERTY(double gpuRunTime READ getGPURunTime) + Q_PROPERTY(double batchRunTime READ getBatchRunTime) + + double _msGPURunTime { 0.0 }; + double _msBatchRunTime { 0.0 }; + public: + using Persistent = PersistentConfig; + + GPUJobConfig() = default; + GPUJobConfig(bool enabled) : JobConfig(enabled) {} + + // Running Time measurement on GPU and for Batch execution + void setGPUBatchRunTime(double msGpuTime, double msBatchTime) { _msGPURunTime = msGpuTime; _msBatchRunTime = msBatchTime; } + double getGPURunTime() const { return _msGPURunTime; } + double getBatchRunTime() const { return _msBatchRunTime; } + }; + + class GPUTaskConfig : public TaskConfig { + Q_OBJECT + Q_PROPERTY(double gpuRunTime READ getGPURunTime) + Q_PROPERTY(double batchRunTime READ getBatchRunTime) + + double _msGPURunTime { 0.0 }; + double _msBatchRunTime { 0.0 }; + public: + + using Persistent = PersistentConfig; + + + GPUTaskConfig() = default; + GPUTaskConfig(bool enabled) : TaskConfig(enabled) {} + + // Running Time measurement on GPU and for Batch execution + void setGPUBatchRunTime(double msGpuTime, double msBatchTime) { _msGPURunTime = msGpuTime; _msBatchRunTime = msBatchTime; } + double getGPURunTime() const { return _msGPURunTime; } + double getBatchRunTime() const { return _msBatchRunTime; } + }; + + // The render engine holds all render tasks, and is itself a render task. // State flows through tasks to jobs via the render and scene contexts - // the engine should not be known from its jobs. diff --git a/libraries/render/src/render/RenderFetchCullSortTask.h b/libraries/render/src/render/RenderFetchCullSortTask.h index 12bcb9786d..f32293f001 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.h +++ b/libraries/render/src/render/RenderFetchCullSortTask.h @@ -13,8 +13,6 @@ #define hifi_RenderFetchCullSortTask_h #include - -#include "Task.h" #include "CullTask.h" class RenderFetchCullSortTask { diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h deleted file mode 100644 index a4d60b25cc..0000000000 --- a/libraries/render/src/render/Task.h +++ /dev/null @@ -1,769 +0,0 @@ -// -// Task.h -// render/src/render -// -// Created by Zach Pomerantz on 1/6/2016. -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_render_Task_h -#define hifi_render_Task_h -#include - -#include - -#include -#include -#include -#include - -#include "SettingHandle.h" - -#include "Context.h" -#include "Logging.h" - -#include "gpu/Batch.h" -#include - -namespace task { - -// A varying piece of data, to be used as Job/Task I/O -class Varying { -public: - Varying() {} - Varying(const Varying& var) : _concept(var._concept) {} - Varying& operator=(const Varying& var) { - _concept = var._concept; - return (*this); - } - template Varying(const T& data) : _concept(std::make_shared>(data)) {} - - template bool canCast() const { return !!std::dynamic_pointer_cast>(_concept); } - template const T& get() const { return std::static_pointer_cast>(_concept)->_data; } - template T& edit() { return std::static_pointer_cast>(_concept)->_data; } - - - // access potential sub varyings contained in this one. - Varying operator[] (uint8_t index) const { return (*_concept)[index]; } - uint8_t length() const { return (*_concept).length(); } - - template Varying getN (uint8_t index) const { return get()[index]; } - template Varying editN (uint8_t index) { return edit()[index]; } - -protected: - class Concept { - public: - virtual ~Concept() = default; - - virtual Varying operator[] (uint8_t index) const = 0; - virtual uint8_t length() const = 0; - }; - template class Model : public Concept { - public: - using Data = T; - - Model(const Data& data) : _data(data) {} - virtual ~Model() = default; - - virtual Varying operator[] (uint8_t index) const override { - Varying var; - return var; - } - virtual uint8_t length() const override { return 0; } - - Data _data; - }; - - std::shared_ptr _concept; -}; - -using VaryingPairBase = std::pair; -template < typename T0, typename T1 > -class VaryingSet2 : public VaryingPairBase { -public: - using Parent = VaryingPairBase; - typedef void is_proxy_tag; - - VaryingSet2() : Parent(Varying(T0()), Varying(T1())) {} - VaryingSet2(const VaryingSet2& pair) : Parent(pair.first, pair.second) {} - VaryingSet2(const Varying& first, const Varying& second) : Parent(first, second) {} - - const T0& get0() const { return first.get(); } - T0& edit0() { return first.edit(); } - - const T1& get1() const { return second.get(); } - T1& edit1() { return second.edit(); } - - virtual Varying operator[] (uint8_t index) const { - if (index == 1) { - return std::get<1>((*this)); - } else { - return std::get<0>((*this)); - } - } - virtual uint8_t length() const { return 2; } - - Varying hasVarying() const { return Varying((*this)); } -}; - - -template -class VaryingSet3 : public std::tuple{ -public: - using Parent = std::tuple; - - VaryingSet3() : Parent(Varying(T0()), Varying(T1()), Varying(T2())) {} - VaryingSet3(const VaryingSet3& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src)) {} - VaryingSet3(const Varying& first, const Varying& second, const Varying& third) : Parent(first, second, third) {} - - const T0& get0() const { return std::get<0>((*this)).template get(); } - T0& edit0() { return std::get<0>((*this)).template edit(); } - - const T1& get1() const { return std::get<1>((*this)).template get(); } - T1& edit1() { return std::get<1>((*this)).template edit(); } - - const T2& get2() const { return std::get<2>((*this)).template get(); } - T2& edit2() { return std::get<2>((*this)).template edit(); } - - virtual Varying operator[] (uint8_t index) const { - if (index == 2) { - return std::get<2>((*this)); - } else if (index == 1) { - return std::get<1>((*this)); - } else { - return std::get<0>((*this)); - } - } - virtual uint8_t length() const { return 3; } - - Varying hasVarying() const { return Varying((*this)); } -}; - -template -class VaryingSet4 : public std::tuple{ -public: - using Parent = std::tuple; - - VaryingSet4() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3())) {} - VaryingSet4(const VaryingSet4& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src)) {} - VaryingSet4(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth) : Parent(first, second, third, fourth) {} - - const T0& get0() const { return std::get<0>((*this)).template get(); } - T0& edit0() { return std::get<0>((*this)).template edit(); } - - const T1& get1() const { return std::get<1>((*this)).template get(); } - T1& edit1() { return std::get<1>((*this)).template edit(); } - - const T2& get2() const { return std::get<2>((*this)).template get(); } - T2& edit2() { return std::get<2>((*this)).template edit(); } - - const T3& get3() const { return std::get<3>((*this)).template get(); } - T3& edit3() { return std::get<3>((*this)).template edit(); } - - virtual Varying operator[] (uint8_t index) const { - if (index == 3) { - return std::get<3>((*this)); - } else if (index == 2) { - return std::get<2>((*this)); - } else if (index == 1) { - return std::get<1>((*this)); - } else { - return std::get<0>((*this)); - } - } - virtual uint8_t length() const { return 4; } - - Varying hasVarying() const { return Varying((*this)); } -}; - - -template -class VaryingSet5 : public std::tuple{ -public: - using Parent = std::tuple; - - VaryingSet5() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3()), Varying(T4())) {} - VaryingSet5(const VaryingSet5& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src), std::get<4>(src)) {} - VaryingSet5(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth, const Varying& fifth) : Parent(first, second, third, fourth, fifth) {} - - const T0& get0() const { return std::get<0>((*this)).template get(); } - T0& edit0() { return std::get<0>((*this)).template edit(); } - - const T1& get1() const { return std::get<1>((*this)).template get(); } - T1& edit1() { return std::get<1>((*this)).template edit(); } - - const T2& get2() const { return std::get<2>((*this)).template get(); } - T2& edit2() { return std::get<2>((*this)).template edit(); } - - const T3& get3() const { return std::get<3>((*this)).template get(); } - T3& edit3() { return std::get<3>((*this)).template edit(); } - - const T4& get4() const { return std::get<4>((*this)).template get(); } - T4& edit4() { return std::get<4>((*this)).template edit(); } - - virtual Varying operator[] (uint8_t index) const { - if (index == 4) { - return std::get<4>((*this)); - } else if (index == 3) { - return std::get<3>((*this)); - } else if (index == 2) { - return std::get<2>((*this)); - } else if (index == 1) { - return std::get<1>((*this)); - } else { - return std::get<0>((*this)); - } - } - virtual uint8_t length() const { return 5; } - - Varying hasVarying() const { return Varying((*this)); } -}; - -template -class VaryingSet6 : public std::tuple{ -public: - using Parent = std::tuple; - - VaryingSet6() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3()), Varying(T4()), Varying(T5())) {} - VaryingSet6(const VaryingSet6& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src), std::get<4>(src), std::get<5>(src)) {} - VaryingSet6(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth, const Varying& fifth, const Varying& sixth) : Parent(first, second, third, fourth, fifth, sixth) {} - - const T0& get0() const { return std::get<0>((*this)).template get(); } - T0& edit0() { return std::get<0>((*this)).template edit(); } - - const T1& get1() const { return std::get<1>((*this)).template get(); } - T1& edit1() { return std::get<1>((*this)).template edit(); } - - const T2& get2() const { return std::get<2>((*this)).template get(); } - T2& edit2() { return std::get<2>((*this)).template edit(); } - - const T3& get3() const { return std::get<3>((*this)).template get(); } - T3& edit3() { return std::get<3>((*this)).template edit(); } - - const T4& get4() const { return std::get<4>((*this)).template get(); } - T4& edit4() { return std::get<4>((*this)).template edit(); } - - const T5& get5() const { return std::get<5>((*this)).template get(); } - T5& edit5() { return std::get<5>((*this)).template edit(); } - - Varying hasVarying() const { return Varying((*this)); } -}; - -template -class VaryingSet7 : public std::tuple{ -public: - using Parent = std::tuple; - - VaryingSet7() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3()), Varying(T4()), Varying(T5()), Varying(T6())) {} - VaryingSet7(const VaryingSet7& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src), std::get<4>(src), std::get<5>(src), std::get<6>(src)) {} - VaryingSet7(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth, const Varying& fifth, const Varying& sixth, const Varying& seventh) : Parent(first, second, third, fourth, fifth, sixth, seventh) {} - - const T0& get0() const { return std::get<0>((*this)).template get(); } - T0& edit0() { return std::get<0>((*this)).template edit(); } - - const T1& get1() const { return std::get<1>((*this)).template get(); } - T1& edit1() { return std::get<1>((*this)).template edit(); } - - const T2& get2() const { return std::get<2>((*this)).template get(); } - T2& edit2() { return std::get<2>((*this)).template edit(); } - - const T3& get3() const { return std::get<3>((*this)).template get(); } - T3& edit3() { return std::get<3>((*this)).template edit(); } - - const T4& get4() const { return std::get<4>((*this)).template get(); } - T4& edit4() { return std::get<4>((*this)).template edit(); } - - const T5& get5() const { return std::get<5>((*this)).template get(); } - T5& edit5() { return std::get<5>((*this)).template edit(); } - - const T6& get6() const { return std::get<6>((*this)).template get(); } - T6& edit6() { return std::get<6>((*this)).template edit(); } - - Varying hasVarying() const { return Varying((*this)); } -}; - - -template < class T, int NUM > -class VaryingArray : public std::array { -public: - VaryingArray() { - for (size_t i = 0; i < NUM; i++) { - (*this)[i] = Varying(T()); - } - } -}; - -class JobConcept; -template class JobT; -template class TaskT; -class JobNoIO {}; - -template class PersistentConfig : public C { -public: - const QString DEFAULT = "Default"; - const QString NONE = "None"; - - PersistentConfig() = delete; - PersistentConfig(const QString& path) : - _preset(QStringList() << "Render" << "Engine" << path, DEFAULT) { } - PersistentConfig(const QStringList& path) : - _preset(QStringList() << "Render" << "Engine" << path, DEFAULT) { } - PersistentConfig(const QString& path, bool enabled) : C(enabled), - _preset(QStringList() << "Render" << "Engine" << path, enabled ? DEFAULT : NONE) { } - PersistentConfig(const QStringList& path, bool enabled) : C(enabled), - _preset(QStringList() << "Render" << "Engine" << path, enabled ? DEFAULT : NONE) { } - - QStringList getPresetList() { - if (_presets.empty()) { - setPresetList(QJsonObject()); - } - return _presets.keys(); - } - - virtual void setPresetList(const QJsonObject& list) override { - assert(_presets.empty()); - - _default = toJsonValue(*this).toObject().toVariantMap(); - - _presets.unite(list.toVariantMap()); - if (C::alwaysEnabled || C::enabled) { - _presets.insert(DEFAULT, _default); - } - if (!C::alwaysEnabled) { - _presets.insert(NONE, QVariantMap{{ "enabled", false }}); - } - - auto preset = _preset.get(); - if (preset != _preset.getDefault() && _presets.contains(preset)) { - // Load the persisted configuration - C::load(_presets[preset].toMap()); - } - } - - QString getPreset() { return _preset.get(); } - - void setPreset(const QString& preset) { - _preset.set(preset); - if (_presets.contains(preset)) { - // Always start back at default to remain deterministic - QVariantMap config = _default; - QVariantMap presetConfig = _presets[preset].toMap(); - for (auto it = presetConfig.cbegin(); it != presetConfig.cend(); it++) { - config.insert(it.key(), it.value()); - } - C::load(config); - } - } - -protected: - QVariantMap _default; - QVariantMap _presets; - Setting::Handle _preset; -}; - -// A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled) -class JobConfig : public QObject { - Q_OBJECT - Q_PROPERTY(double cpuRunTime READ getCPURunTime NOTIFY newStats()) //ms - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) - - double _msCPURunTime{ 0.0 }; -public: - using Persistent = PersistentConfig; - - JobConfig() = default; - JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} - - bool isEnabled() { return alwaysEnabled || enabled; } - void setEnabled(bool enable) { enabled = alwaysEnabled || enable; } - - bool alwaysEnabled{ true }; - bool enabled{ true }; - - virtual void setPresetList(const QJsonObject& object) { - for (auto it = object.begin(); it != object.end(); it++) { - JobConfig* child = findChild(it.key(), Qt::FindDirectChildrenOnly); - if (child) { - child->setPresetList(it.value().toObject()); - } - } - } - - // This must be named toJSON to integrate with the global scripting JSON object - Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); } - Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); emit loaded(); } - - // Running Time measurement - // The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated - void setCPURunTime(double mstime) { _msCPURunTime = mstime; emit newStats(); } - double getCPURunTime() const { return _msCPURunTime; } - -public slots: - void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); emit loaded(); } - -signals: - void loaded(); - void newStats(); -}; - -class TaskConfig : public JobConfig { - Q_OBJECT -public: - using QConfigPointer = std::shared_ptr; - - using Persistent = PersistentConfig; - - TaskConfig() = default ; - TaskConfig(bool enabled) : JobConfig(enabled) {} - - // getter for qml integration, prefer the templated getter - Q_INVOKABLE QObject* getConfig(const QString& name) { return QObject::findChild(name); } - // getter for cpp (strictly typed), prefer this getter - template typename T::Config* getConfig(std::string job = "") const { - QString name = job.empty() ? QString() : QString(job.c_str()); // an empty string is not a null string - return findChild(name); - } - - void connectChildConfig(QConfigPointer childConfig, const std::string& name); - void transferChildrenConfigs(QConfigPointer source); - - JobConcept* _task; - -public slots: - void refresh(); -}; - -template void jobConfigure(T& data, const C& configuration) { - data.configure(configuration); -} -template void jobConfigure(T&, const JobConfig&) { - // nop, as the default JobConfig was used, so the data does not need a configure method -} -template void jobConfigure(T&, const TaskConfig&) { - // nop, as the default TaskConfig was used, so the data does not need a configure method -} - -template void jobRun(T& data, const RC& renderContext, const JobNoIO& input, JobNoIO& output) { - data.run(renderContext); -} -template void jobRun(T& data, const RC& renderContext, const I& input, JobNoIO& output) { - data.run(renderContext, input); -} -template void jobRun(T& data, const RC& renderContext, const JobNoIO& input, O& output) { - data.run(renderContext, output); -} -template void jobRun(T& data, const RC& renderContext, const I& input, O& output) { - data.run(renderContext, input, output); -} - -// The guts of a job -class JobConcept { -public: - using Config = JobConfig; - using QConfigPointer = std::shared_ptr; - - JobConcept(QConfigPointer config) : _config(config) {} - virtual ~JobConcept() = default; - - virtual const Varying getInput() const { return Varying(); } - virtual const Varying getOutput() const { return Varying(); } - - virtual QConfigPointer& getConfiguration() { return _config; } - virtual void applyConfiguration() = 0; - - void setCPURunTime(double mstime) { std::static_pointer_cast(_config)->setCPURunTime(mstime); } - - QConfigPointer _config; -protected: -}; - -template -class Job { -public: - using Context = RC; - using ContextPointer = std::shared_ptr; - using Config = JobConfig; - using QConfigPointer = std::shared_ptr; - using None = JobNoIO; - - //template - class Concept : public JobConcept { - public: - Concept(QConfigPointer config) : JobConcept(config) {} - virtual ~Concept() = default; - - virtual void run(const ContextPointer& renderContext) = 0; - }; - using ConceptPointer = std::shared_ptr; - - template class Model : public Concept { - public: - using Data = T; - using Input = I; - using Output = O; - - Data _data; - Varying _input; - Varying _output; - - const Varying getInput() const override { return _input; } - const Varying getOutput() const override { return _output; } - - template - Model(const Varying& input, QConfigPointer config, A&&... args) : - Concept(config), - _data(Data(std::forward(args)...)), - _input(input), - _output(Output()) { - applyConfiguration(); - } - - template - static std::shared_ptr create(const Varying& input, A&&... args) { - return std::make_shared(input, std::make_shared(), std::forward(args)...); - } - - - void applyConfiguration() override { - jobConfigure(_data, *std::static_pointer_cast(_config)); - } - - void run(const ContextPointer& renderContext) override { - renderContext->jobConfig = std::static_pointer_cast(_config); - if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->isEnabled()) { - jobRun(_data, renderContext, _input.get(), _output.edit()); - } - renderContext->jobConfig.reset(); - } - }; - template using ModelI = Model; - template using ModelO = Model; - template using ModelIO = Model; - - Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} - - const Varying getInput() const { return _concept->getInput(); } - const Varying getOutput() const { return _concept->getOutput(); } - QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); } - void applyConfiguration() { return _concept->applyConfiguration(); } - - template T& edit() { - auto concept = std::static_pointer_cast(_concept); - assert(concept); - return concept->_data; - } - - virtual void run(const ContextPointer& renderContext) { - PerformanceTimer perfTimer(_name.c_str()); - PROFILE_RANGE(render, _name.c_str()); - auto start = usecTimestampNow(); - - _concept->run(renderContext); - - _concept->setCPURunTime((double)(usecTimestampNow() - start) / 1000.0); - } - -protected: - ConceptPointer _concept; - std::string _name = ""; -}; - -// A task is a specialized job to run a collection of other jobs -// It can be created on any type T by aliasing the type JobModel in the class T -// using JobModel = Task::Model -// The class T is expected to have a "build" method acting as a constructor. -// The build method is where child Jobs can be added internally to the task -// where the input of the task can be setup to feed the child jobs -// and where the output of the task is defined -template -class Task : public Job { -public: - using Context = RC; - using ContextPointer = std::shared_ptr; - using Config = TaskConfig; - using _Job = Job; - using QConfigPointer = _Job::QConfigPointer; - using None = _Job::None; - using Concept = _Job::Concept; - using Jobs = std::vector<_Job>; - - Task(std::string name, ConceptPointer concept) : Job(name, concept) {} - - class TaskConcept : public Concept { - public: - Varying _input; - Varying _output; - Jobs _jobs; - - const Varying getInput() const override { return _input; } - const Varying getOutput() const override { return _output; } - - TaskConcept(const Varying& input, QConfigPointer config) : Concept(config), _input(input) {} - - // Create a new job in the container's queue; returns the job's output - template const Varying addJob(std::string name, const Varying& input, NA&&... args) { - _jobs.emplace_back(name, (NT::JobModel::create(input, std::forward(args)...))); - - // Conect the child config to this task's config - std::static_pointer_cast(getConfiguration())->connectChildConfig(_jobs.back().getConfiguration(), name); - - return _jobs.back().getOutput(); - } - template const Varying addJob(std::string name, NA&&... args) { - const auto input = Varying(typename NT::JobModel::Input()); - return addJob(name, input, std::forward(args)...); - } - }; - - template class TaskModel : public TaskConcept { - public: - using Data = T; - using Input = I; - using Output = O; - - Data _data; - - TaskModel(const Varying& input, QConfigPointer config) : - TaskConcept(input, config), - _data(Data()) {} - - template - static std::shared_ptr create(const Varying& input, A&&... args) { - auto model = std::make_shared(input, std::make_shared()); - - model->_data.build(*(model), model->_input, model->_output, std::forward(args)...); - - // Recreate the Config to use the templated type - model->createConfiguration(); - model->applyConfiguration(); - - return model; - } - - template - static std::shared_ptr create(A&&... args) { - const auto input = Varying(Input()); - return create(input, std::forward(args)...); - } - - void createConfiguration() { - // A brand new config - auto config = std::make_shared(); - // Make sure we transfer the former children configs to the new config - config->transferChildrenConfigs(_config); - // swap - _config = config; - // Capture this - std::static_pointer_cast(_config)->_task = this; - } - - QConfigPointer& getConfiguration() override { - if (!_config) { - createConfiguration(); - } - return _config; - } - - void applyConfiguration() override { - jobConfigure(_data, *std::static_pointer_cast(_config)); - for (auto& job : _jobs) { - job.applyConfiguration(); - } - } - - void run(const ContextPointer& renderContext) override { - auto config = std::static_pointer_cast(_config); - if (config->alwaysEnabled || config->enabled) { - for (auto job : _jobs) { - job.run(renderContext); - } - } - } - }; - template using Model = TaskModel; - template using ModelI = TaskModel; - template using ModelO = TaskModel; - template using ModelIO = TaskModel; - - // Create a new job in the Task's queue; returns the job's output - template const Varying addJob(std::string name, const Varying& input, A&&... args) { - return std::static_pointer_cast( _concept)->addJob(name, input, std::forward(args)...); - } - template const Varying addJob(std::string name, A&&... args) { - const auto input = Varying(typename T::JobModel::Input()); - return std::static_pointer_cast( _concept)->addJob(name, input, std::forward(args)...); - } - - std::shared_ptr getConfiguration() { - return std::static_pointer_cast(_concept->getConfiguration()); - } - -protected: -}; -} - -namespace render { -using JobConfig =task::JobConfig; -using TaskConfig =task::TaskConfig; - -template using PersistentConfig = task::PersistentConfig; - -using Job = task::Job; -using Task = task::Task; - -using Varying = task::Varying; -template < typename T0, typename T1 > using VaryingSet2 = task::VaryingSet2; -template < typename T0, typename T1, typename T2 > using VaryingSet3 = task::VaryingSet3; -template < typename T0, typename T1, typename T2, typename T3 > using VaryingSet4 = task::VaryingSet4; -template < typename T0, typename T1, typename T2, typename T3, typename T4 > using VaryingSet5 = task::VaryingSet5; -template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5 > using VaryingSet6 = task::VaryingSet6; -template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > using VaryingSet7 = task::VaryingSet7; -template < class T, int NUM > using VaryingArray = task::VaryingArray; - -// Versions of the COnfig integrating a gpu & batch timer -class GPUJobConfig : public JobConfig { - Q_OBJECT - Q_PROPERTY(double gpuRunTime READ getGPURunTime) - Q_PROPERTY(double batchRunTime READ getBatchRunTime) - - double _msGPURunTime { 0.0 }; - double _msBatchRunTime { 0.0 }; -public: - using Persistent = PersistentConfig; - - GPUJobConfig() = default; - GPUJobConfig(bool enabled) : JobConfig(enabled) {} - - // Running Time measurement on GPU and for Batch execution - void setGPUBatchRunTime(double msGpuTime, double msBatchTime) { _msGPURunTime = msGpuTime; _msBatchRunTime = msBatchTime; } - double getGPURunTime() const { return _msGPURunTime; } - double getBatchRunTime() const { return _msBatchRunTime; } -}; - -class GPUTaskConfig : public TaskConfig { - Q_OBJECT - Q_PROPERTY(double gpuRunTime READ getGPURunTime) - Q_PROPERTY(double batchRunTime READ getBatchRunTime) - - double _msGPURunTime { 0.0 }; - double _msBatchRunTime { 0.0 }; -public: - - using Persistent = PersistentConfig; - - - GPUTaskConfig() = default; - GPUTaskConfig(bool enabled) : TaskConfig(enabled) {} - - // Running Time measurement on GPU and for Batch execution - void setGPUBatchRunTime(double msGpuTime, double msBatchTime) { _msGPURunTime = msGpuTime; _msBatchRunTime = msBatchTime; } - double getGPURunTime() const { return _msGPURunTime; } - double getBatchRunTime() const { return _msBatchRunTime; } -}; - -} - -#endif // hifi_render_Task_h diff --git a/libraries/render/src/render/Task.cpp b/libraries/render/src/task/Config.cpp similarity index 95% rename from libraries/render/src/render/Task.cpp rename to libraries/render/src/task/Config.cpp index 13476f102e..587c4319af 100644 --- a/libraries/render/src/render/Task.cpp +++ b/libraries/render/src/task/Config.cpp @@ -1,6 +1,6 @@ // -// Task.cpp -// render/src/render +// Config.cpp +// render/src/task // // Created by Zach Pomerantz on 1/21/2016. // Copyright 2016 High Fidelity, Inc. @@ -8,12 +8,12 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - -#include +#include "Config.h" #include "Task.h" +#include -using namespace render; +using namespace task; void TaskConfig::connectChildConfig(QConfigPointer childConfig, const std::string& name) { childConfig->setParent(this); diff --git a/libraries/render/src/task/Config.h b/libraries/render/src/task/Config.h new file mode 100644 index 0000000000..9e6f060d9d --- /dev/null +++ b/libraries/render/src/task/Config.h @@ -0,0 +1,169 @@ +// +// Config.h +// render/src/render +// +// Created by Zach Pomerantz on 1/6/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_task_Config_h +#define hifi_task_Config_h + +#include +#include +#include +#include +#include + +#include "SettingHandle.h" + +#include "Logging.h" + +#include +#include + +namespace task { + +class JobConcept; + +template class PersistentConfig : public C { +public: + const QString DEFAULT = "Default"; + const QString NONE = "None"; + + PersistentConfig() = delete; + PersistentConfig(const QString& path) : + _preset(QStringList() << "Render" << "Engine" << path, DEFAULT) { } + PersistentConfig(const QStringList& path) : + _preset(QStringList() << "Render" << "Engine" << path, DEFAULT) { } + PersistentConfig(const QString& path, bool enabled) : C(enabled), + _preset(QStringList() << "Render" << "Engine" << path, enabled ? DEFAULT : NONE) { } + PersistentConfig(const QStringList& path, bool enabled) : C(enabled), + _preset(QStringList() << "Render" << "Engine" << path, enabled ? DEFAULT : NONE) { } + + QStringList getPresetList() { + if (_presets.empty()) { + setPresetList(QJsonObject()); + } + return _presets.keys(); + } + + virtual void setPresetList(const QJsonObject& list) override { + assert(_presets.empty()); + + _default = toJsonValue(*this).toObject().toVariantMap(); + + _presets.unite(list.toVariantMap()); + if (C::alwaysEnabled || C::enabled) { + _presets.insert(DEFAULT, _default); + } + if (!C::alwaysEnabled) { + _presets.insert(NONE, QVariantMap{{ "enabled", false }}); + } + + auto preset = _preset.get(); + if (preset != _preset.getDefault() && _presets.contains(preset)) { + // Load the persisted configuration + C::load(_presets[preset].toMap()); + } + } + + QString getPreset() { return _preset.get(); } + + void setPreset(const QString& preset) { + _preset.set(preset); + if (_presets.contains(preset)) { + // Always start back at default to remain deterministic + QVariantMap config = _default; + QVariantMap presetConfig = _presets[preset].toMap(); + for (auto it = presetConfig.cbegin(); it != presetConfig.cend(); it++) { + config.insert(it.key(), it.value()); + } + C::load(config); + } + } + +protected: + QVariantMap _default; + QVariantMap _presets; + Setting::Handle _preset; +}; + +// A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled) +class JobConfig : public QObject { + Q_OBJECT + Q_PROPERTY(double cpuRunTime READ getCPURunTime NOTIFY newStats()) //ms + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) + + double _msCPURunTime{ 0.0 }; +public: + using Persistent = PersistentConfig; + + JobConfig() = default; + JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} + + bool isEnabled() { return alwaysEnabled || enabled; } + void setEnabled(bool enable) { enabled = alwaysEnabled || enable; } + + bool alwaysEnabled{ true }; + bool enabled{ true }; + + virtual void setPresetList(const QJsonObject& object) { + for (auto it = object.begin(); it != object.end(); it++) { + JobConfig* child = findChild(it.key(), Qt::FindDirectChildrenOnly); + if (child) { + child->setPresetList(it.value().toObject()); + } + } + } + + // This must be named toJSON to integrate with the global scripting JSON object + Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); } + Q_INVOKABLE void load(const QVariantMap& map) { qObjectFromJsonValue(QJsonObject::fromVariantMap(map), *this); emit loaded(); } + + // Running Time measurement + // The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated + void setCPURunTime(double mstime) { _msCPURunTime = mstime; emit newStats(); } + double getCPURunTime() const { return _msCPURunTime; } + +public slots: + void load(const QJsonObject& val) { qObjectFromJsonValue(val, *this); emit loaded(); } + +signals: + void loaded(); + void newStats(); +}; + +class TaskConfig : public JobConfig { + Q_OBJECT +public: + using QConfigPointer = std::shared_ptr; + + using Persistent = PersistentConfig; + + TaskConfig() = default ; + TaskConfig(bool enabled) : JobConfig(enabled) {} + + // getter for qml integration, prefer the templated getter + Q_INVOKABLE QObject* getConfig(const QString& name) { return QObject::findChild(name); } + // getter for cpp (strictly typed), prefer this getter + template typename T::Config* getConfig(std::string job = "") const { + QString name = job.empty() ? QString() : QString(job.c_str()); // an empty string is not a null string + return findChild(name); + } + + void connectChildConfig(QConfigPointer childConfig, const std::string& name); + void transferChildrenConfigs(QConfigPointer source); + + JobConcept* _task; + +public slots: + void refresh(); +}; + +} + +#endif // hifi_task_Config_h diff --git a/libraries/render/src/task/Task.h b/libraries/render/src/task/Task.h new file mode 100644 index 0000000000..3fcea66786 --- /dev/null +++ b/libraries/render/src/task/Task.h @@ -0,0 +1,326 @@ +// +// Task.h +// render/src/task +// +// Created by Zach Pomerantz on 1/6/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_task_Task_h +#define hifi_task_Task_h + +#include "Config.h" +#include "Varying.h" + +#include "SettingHandle.h" + +#include "Logging.h" + +#include +#include + +namespace task { + +class JobConcept; +template class JobT; +template class TaskT; +class JobNoIO {}; + +class JobContext { +public: + virtual ~JobContext() {} + + std::shared_ptr jobConfig { nullptr }; +}; +using JobContextPointer = std::shared_ptr; + +// The guts of a job +class JobConcept { +public: + using Config = JobConfig; + using QConfigPointer = std::shared_ptr; + + JobConcept(QConfigPointer config) : _config(config) {} + virtual ~JobConcept() = default; + + virtual const Varying getInput() const { return Varying(); } + virtual const Varying getOutput() const { return Varying(); } + + virtual QConfigPointer& getConfiguration() { return _config; } + virtual void applyConfiguration() = 0; + + void setCPURunTime(double mstime) { std::static_pointer_cast(_config)->setCPURunTime(mstime); } + + QConfigPointer _config; +protected: +}; + + +template void jobConfigure(T& data, const C& configuration) { + data.configure(configuration); +} +template void jobConfigure(T&, const JobConfig&) { + // nop, as the default JobConfig was used, so the data does not need a configure method +} +template void jobConfigure(T&, const TaskConfig&) { + // nop, as the default TaskConfig was used, so the data does not need a configure method +} + +template void jobRun(T& data, const RC& renderContext, const JobNoIO& input, JobNoIO& output) { + data.run(renderContext); +} +template void jobRun(T& data, const RC& renderContext, const I& input, JobNoIO& output) { + data.run(renderContext, input); +} +template void jobRun(T& data, const RC& renderContext, const JobNoIO& input, O& output) { + data.run(renderContext, output); +} +template void jobRun(T& data, const RC& renderContext, const I& input, O& output) { + data.run(renderContext, input, output); +} + +template +class Job { +public: + using Context = RC; + using ContextPointer = std::shared_ptr; + using Config = JobConfig; + using QConfigPointer = std::shared_ptr; + using None = JobNoIO; + + //template + class Concept : public JobConcept { + public: + Concept(QConfigPointer config) : JobConcept(config) {} + virtual ~Concept() = default; + + virtual void run(const ContextPointer& renderContext) = 0; + }; + using ConceptPointer = std::shared_ptr; + + template class Model : public Concept { + public: + using Data = T; + using Input = I; + using Output = O; + + Data _data; + Varying _input; + Varying _output; + + const Varying getInput() const override { return _input; } + const Varying getOutput() const override { return _output; } + + template + Model(const Varying& input, QConfigPointer config, A&&... args) : + Concept(config), + _data(Data(std::forward(args)...)), + _input(input), + _output(Output()) { + applyConfiguration(); + } + + template + static std::shared_ptr create(const Varying& input, A&&... args) { + return std::make_shared(input, std::make_shared(), std::forward(args)...); + } + + + void applyConfiguration() override { + jobConfigure(_data, *std::static_pointer_cast(_config)); + } + + void run(const ContextPointer& renderContext) override { + renderContext->jobConfig = std::static_pointer_cast(_config); + if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->isEnabled()) { + jobRun(_data, renderContext, _input.get(), _output.edit()); + } + renderContext->jobConfig.reset(); + } + }; + template using ModelI = Model; + template using ModelO = Model; + template using ModelIO = Model; + + Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} + + const Varying getInput() const { return _concept->getInput(); } + const Varying getOutput() const { return _concept->getOutput(); } + QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); } + void applyConfiguration() { return _concept->applyConfiguration(); } + + template T& edit() { + auto concept = std::static_pointer_cast(_concept); + assert(concept); + return concept->_data; + } + + virtual void run(const ContextPointer& renderContext) { + PerformanceTimer perfTimer(_name.c_str()); + PROFILE_RANGE(render, _name.c_str()); + auto start = usecTimestampNow(); + + _concept->run(renderContext); + + _concept->setCPURunTime((double)(usecTimestampNow() - start) / 1000.0); + } + +protected: + ConceptPointer _concept; + std::string _name = ""; +}; + +// A task is a specialized job to run a collection of other jobs +// It can be created on any type T by aliasing the type JobModel in the class T +// using JobModel = Task::Model +// The class T is expected to have a "build" method acting as a constructor. +// The build method is where child Jobs can be added internally to the task +// where the input of the task can be setup to feed the child jobs +// and where the output of the task is defined +template +class Task : public Job { +public: + using Context = RC; + using ContextPointer = std::shared_ptr; + using Config = TaskConfig; + using _Job = Job; + using QConfigPointer = _Job::QConfigPointer; + using None = _Job::None; + using Concept = _Job::Concept; + using Jobs = std::vector<_Job>; + + Task(std::string name, ConceptPointer concept) : Job(name, concept) {} + + class TaskConcept : public Concept { + public: + Varying _input; + Varying _output; + Jobs _jobs; + + const Varying getInput() const override { return _input; } + const Varying getOutput() const override { return _output; } + + TaskConcept(const Varying& input, QConfigPointer config) : Concept(config), _input(input) {} + + // Create a new job in the container's queue; returns the job's output + template const Varying addJob(std::string name, const Varying& input, NA&&... args) { + _jobs.emplace_back(name, (NT::JobModel::create(input, std::forward(args)...))); + + // Conect the child config to this task's config + std::static_pointer_cast(getConfiguration())->connectChildConfig(_jobs.back().getConfiguration(), name); + + return _jobs.back().getOutput(); + } + template const Varying addJob(std::string name, NA&&... args) { + const auto input = Varying(typename NT::JobModel::Input()); + return addJob(name, input, std::forward(args)...); + } + }; + + template class TaskModel : public TaskConcept { + public: + using Data = T; + using Input = I; + using Output = O; + + Data _data; + + TaskModel(const Varying& input, QConfigPointer config) : + TaskConcept(input, config), + _data(Data()) {} + + template + static std::shared_ptr create(const Varying& input, A&&... args) { + auto model = std::make_shared(input, std::make_shared()); + + model->_data.build(*(model), model->_input, model->_output, std::forward(args)...); + + // Recreate the Config to use the templated type + model->createConfiguration(); + model->applyConfiguration(); + + return model; + } + + template + static std::shared_ptr create(A&&... args) { + const auto input = Varying(Input()); + return create(input, std::forward(args)...); + } + + void createConfiguration() { + // A brand new config + auto config = std::make_shared(); + // Make sure we transfer the former children configs to the new config + config->transferChildrenConfigs(_config); + // swap + _config = config; + // Capture this + std::static_pointer_cast(_config)->_task = this; + } + + QConfigPointer& getConfiguration() override { + if (!_config) { + createConfiguration(); + } + return _config; + } + + void applyConfiguration() override { + jobConfigure(_data, *std::static_pointer_cast(_config)); + for (auto& job : _jobs) { + job.applyConfiguration(); + } + } + + void run(const ContextPointer& renderContext) override { + auto config = std::static_pointer_cast(_config); + if (config->alwaysEnabled || config->enabled) { + for (auto job : _jobs) { + job.run(renderContext); + } + } + } + }; + template using Model = TaskModel; + template using ModelI = TaskModel; + template using ModelO = TaskModel; + template using ModelIO = TaskModel; + + // Create a new job in the Task's queue; returns the job's output + template const Varying addJob(std::string name, const Varying& input, A&&... args) { + return std::static_pointer_cast( _concept)->addJob(name, input, std::forward(args)...); + } + template const Varying addJob(std::string name, A&&... args) { + const auto input = Varying(typename T::JobModel::Input()); + return std::static_pointer_cast( _concept)->addJob(name, input, std::forward(args)...); + } + + std::shared_ptr getConfiguration() { + return std::static_pointer_cast(_concept->getConfiguration()); + } + +protected: +}; +} + + +#define Task_DeclareTypeAliases(ContextName) \ + using JobConfig = task::JobConfig; \ + using TaskConfig = task::TaskConfig; \ + template using PersistentConfig = task::PersistentConfig; \ + using Job = task::Job<##ContextName>; \ + using Task = task::Task<##ContextName>; \ + using Varying = task::Varying; \ + template < typename T0, typename T1 > using VaryingSet2 = task::VaryingSet2; \ + template < typename T0, typename T1, typename T2 > using VaryingSet3 = task::VaryingSet3; \ + template < typename T0, typename T1, typename T2, typename T3 > using VaryingSet4 = task::VaryingSet4; \ + template < typename T0, typename T1, typename T2, typename T3, typename T4 > using VaryingSet5 = task::VaryingSet5; \ + template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5 > using VaryingSet6 = task::VaryingSet6; \ + template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > using VaryingSet7 = task::VaryingSet7; \ + template < class T, int NUM > using VaryingArray = task::VaryingArray; + +#endif // hifi_task_Task_h diff --git a/libraries/render/src/task/Varying.h b/libraries/render/src/task/Varying.h new file mode 100644 index 0000000000..50f4acd414 --- /dev/null +++ b/libraries/render/src/task/Varying.h @@ -0,0 +1,287 @@ +// +// Varying.h +// render/src/task +// +// Created by Zach Pomerantz on 1/6/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_task_Varying_h +#define hifi_task_Varying_h + +#include +#include + +namespace task { + +// A varying piece of data, to be used as Job/Task I/O +class Varying { +public: + Varying() {} + Varying(const Varying& var) : _concept(var._concept) {} + Varying& operator=(const Varying& var) { + _concept = var._concept; + return (*this); + } + template Varying(const T& data) : _concept(std::make_shared>(data)) {} + + template bool canCast() const { return !!std::dynamic_pointer_cast>(_concept); } + template const T& get() const { return std::static_pointer_cast>(_concept)->_data; } + template T& edit() { return std::static_pointer_cast>(_concept)->_data; } + + + // access potential sub varyings contained in this one. + Varying operator[] (uint8_t index) const { return (*_concept)[index]; } + uint8_t length() const { return (*_concept).length(); } + + template Varying getN (uint8_t index) const { return get()[index]; } + template Varying editN (uint8_t index) { return edit()[index]; } + +protected: + class Concept { + public: + virtual ~Concept() = default; + + virtual Varying operator[] (uint8_t index) const = 0; + virtual uint8_t length() const = 0; + }; + template class Model : public Concept { + public: + using Data = T; + + Model(const Data& data) : _data(data) {} + virtual ~Model() = default; + + virtual Varying operator[] (uint8_t index) const override { + Varying var; + return var; + } + virtual uint8_t length() const override { return 0; } + + Data _data; + }; + + std::shared_ptr _concept; +}; + +using VaryingPairBase = std::pair; +template < typename T0, typename T1 > +class VaryingSet2 : public VaryingPairBase { +public: + using Parent = VaryingPairBase; + typedef void is_proxy_tag; + + VaryingSet2() : Parent(Varying(T0()), Varying(T1())) {} + VaryingSet2(const VaryingSet2& pair) : Parent(pair.first, pair.second) {} + VaryingSet2(const Varying& first, const Varying& second) : Parent(first, second) {} + + const T0& get0() const { return first.get(); } + T0& edit0() { return first.edit(); } + + const T1& get1() const { return second.get(); } + T1& edit1() { return second.edit(); } + + virtual Varying operator[] (uint8_t index) const { + if (index == 1) { + return std::get<1>((*this)); + } else { + return std::get<0>((*this)); + } + } + virtual uint8_t length() const { return 2; } + + Varying hasVarying() const { return Varying((*this)); } +}; + + +template +class VaryingSet3 : public std::tuple{ +public: + using Parent = std::tuple; + + VaryingSet3() : Parent(Varying(T0()), Varying(T1()), Varying(T2())) {} + VaryingSet3(const VaryingSet3& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src)) {} + VaryingSet3(const Varying& first, const Varying& second, const Varying& third) : Parent(first, second, third) {} + + const T0& get0() const { return std::get<0>((*this)).template get(); } + T0& edit0() { return std::get<0>((*this)).template edit(); } + + const T1& get1() const { return std::get<1>((*this)).template get(); } + T1& edit1() { return std::get<1>((*this)).template edit(); } + + const T2& get2() const { return std::get<2>((*this)).template get(); } + T2& edit2() { return std::get<2>((*this)).template edit(); } + + virtual Varying operator[] (uint8_t index) const { + if (index == 2) { + return std::get<2>((*this)); + } else if (index == 1) { + return std::get<1>((*this)); + } else { + return std::get<0>((*this)); + } + } + virtual uint8_t length() const { return 3; } + + Varying hasVarying() const { return Varying((*this)); } +}; + +template +class VaryingSet4 : public std::tuple{ +public: + using Parent = std::tuple; + + VaryingSet4() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3())) {} + VaryingSet4(const VaryingSet4& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src)) {} + VaryingSet4(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth) : Parent(first, second, third, fourth) {} + + const T0& get0() const { return std::get<0>((*this)).template get(); } + T0& edit0() { return std::get<0>((*this)).template edit(); } + + const T1& get1() const { return std::get<1>((*this)).template get(); } + T1& edit1() { return std::get<1>((*this)).template edit(); } + + const T2& get2() const { return std::get<2>((*this)).template get(); } + T2& edit2() { return std::get<2>((*this)).template edit(); } + + const T3& get3() const { return std::get<3>((*this)).template get(); } + T3& edit3() { return std::get<3>((*this)).template edit(); } + + virtual Varying operator[] (uint8_t index) const { + if (index == 3) { + return std::get<3>((*this)); + } else if (index == 2) { + return std::get<2>((*this)); + } else if (index == 1) { + return std::get<1>((*this)); + } else { + return std::get<0>((*this)); + } + } + virtual uint8_t length() const { return 4; } + + Varying hasVarying() const { return Varying((*this)); } +}; + + +template +class VaryingSet5 : public std::tuple{ +public: + using Parent = std::tuple; + + VaryingSet5() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3()), Varying(T4())) {} + VaryingSet5(const VaryingSet5& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src), std::get<4>(src)) {} + VaryingSet5(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth, const Varying& fifth) : Parent(first, second, third, fourth, fifth) {} + + const T0& get0() const { return std::get<0>((*this)).template get(); } + T0& edit0() { return std::get<0>((*this)).template edit(); } + + const T1& get1() const { return std::get<1>((*this)).template get(); } + T1& edit1() { return std::get<1>((*this)).template edit(); } + + const T2& get2() const { return std::get<2>((*this)).template get(); } + T2& edit2() { return std::get<2>((*this)).template edit(); } + + const T3& get3() const { return std::get<3>((*this)).template get(); } + T3& edit3() { return std::get<3>((*this)).template edit(); } + + const T4& get4() const { return std::get<4>((*this)).template get(); } + T4& edit4() { return std::get<4>((*this)).template edit(); } + + virtual Varying operator[] (uint8_t index) const { + if (index == 4) { + return std::get<4>((*this)); + } else if (index == 3) { + return std::get<3>((*this)); + } else if (index == 2) { + return std::get<2>((*this)); + } else if (index == 1) { + return std::get<1>((*this)); + } else { + return std::get<0>((*this)); + } + } + virtual uint8_t length() const { return 5; } + + Varying hasVarying() const { return Varying((*this)); } +}; + +template +class VaryingSet6 : public std::tuple{ +public: + using Parent = std::tuple; + + VaryingSet6() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3()), Varying(T4()), Varying(T5())) {} + VaryingSet6(const VaryingSet6& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src), std::get<4>(src), std::get<5>(src)) {} + VaryingSet6(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth, const Varying& fifth, const Varying& sixth) : Parent(first, second, third, fourth, fifth, sixth) {} + + const T0& get0() const { return std::get<0>((*this)).template get(); } + T0& edit0() { return std::get<0>((*this)).template edit(); } + + const T1& get1() const { return std::get<1>((*this)).template get(); } + T1& edit1() { return std::get<1>((*this)).template edit(); } + + const T2& get2() const { return std::get<2>((*this)).template get(); } + T2& edit2() { return std::get<2>((*this)).template edit(); } + + const T3& get3() const { return std::get<3>((*this)).template get(); } + T3& edit3() { return std::get<3>((*this)).template edit(); } + + const T4& get4() const { return std::get<4>((*this)).template get(); } + T4& edit4() { return std::get<4>((*this)).template edit(); } + + const T5& get5() const { return std::get<5>((*this)).template get(); } + T5& edit5() { return std::get<5>((*this)).template edit(); } + + Varying hasVarying() const { return Varying((*this)); } +}; + +template +class VaryingSet7 : public std::tuple{ +public: + using Parent = std::tuple; + + VaryingSet7() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3()), Varying(T4()), Varying(T5()), Varying(T6())) {} + VaryingSet7(const VaryingSet7& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src), std::get<4>(src), std::get<5>(src), std::get<6>(src)) {} + VaryingSet7(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth, const Varying& fifth, const Varying& sixth, const Varying& seventh) : Parent(first, second, third, fourth, fifth, sixth, seventh) {} + + const T0& get0() const { return std::get<0>((*this)).template get(); } + T0& edit0() { return std::get<0>((*this)).template edit(); } + + const T1& get1() const { return std::get<1>((*this)).template get(); } + T1& edit1() { return std::get<1>((*this)).template edit(); } + + const T2& get2() const { return std::get<2>((*this)).template get(); } + T2& edit2() { return std::get<2>((*this)).template edit(); } + + const T3& get3() const { return std::get<3>((*this)).template get(); } + T3& edit3() { return std::get<3>((*this)).template edit(); } + + const T4& get4() const { return std::get<4>((*this)).template get(); } + T4& edit4() { return std::get<4>((*this)).template edit(); } + + const T5& get5() const { return std::get<5>((*this)).template get(); } + T5& edit5() { return std::get<5>((*this)).template edit(); } + + const T6& get6() const { return std::get<6>((*this)).template get(); } + T6& edit6() { return std::get<6>((*this)).template edit(); } + + Varying hasVarying() const { return Varying((*this)); } +}; + + +template < class T, int NUM > +class VaryingArray : public std::array { +public: + VaryingArray() { + for (size_t i = 0; i < NUM; i++) { + (*this)[i] = Varying(T()); + } + } +}; +} + +#endif // hifi_task_Varying_h diff --git a/tests/gpu-test/src/TestWindow.h b/tests/gpu-test/src/TestWindow.h index fd059f3e32..bceb29305e 100644 --- a/tests/gpu-test/src/TestWindow.h +++ b/tests/gpu-test/src/TestWindow.h @@ -17,7 +17,7 @@ #include #include -#include +#include #define DEFERRED_LIGHTING From 3691be4a2f498a6322b021634c24d2c89c38e380 Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Sat, 22 Apr 2017 08:53:13 -0700 Subject: [PATCH 03/31] PUshing function to cpp --- libraries/render/src/task/Config.cpp | 9 +++++++++ libraries/render/src/task/Config.h | 12 +----------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/libraries/render/src/task/Config.cpp b/libraries/render/src/task/Config.cpp index 587c4319af..cb2c4f1e3c 100644 --- a/libraries/render/src/task/Config.cpp +++ b/libraries/render/src/task/Config.cpp @@ -15,6 +15,15 @@ using namespace task; +void JobConfig::setPresetList(const QJsonObject& object) { + for (auto it = object.begin(); it != object.end(); it++) { + JobConfig* child = findChild(it.key(), Qt::FindDirectChildrenOnly); + if (child) { + child->setPresetList(it.value().toObject()); + } + } +} + void TaskConfig::connectChildConfig(QConfigPointer childConfig, const std::string& name) { childConfig->setParent(this); childConfig->setObjectName(name.c_str()); diff --git a/libraries/render/src/task/Config.h b/libraries/render/src/task/Config.h index 9e6f060d9d..203a0e4688 100644 --- a/libraries/render/src/task/Config.h +++ b/libraries/render/src/task/Config.h @@ -22,9 +22,6 @@ #include "Logging.h" -#include -#include - namespace task { class JobConcept; @@ -111,14 +108,7 @@ public: bool alwaysEnabled{ true }; bool enabled{ true }; - virtual void setPresetList(const QJsonObject& object) { - for (auto it = object.begin(); it != object.end(); it++) { - JobConfig* child = findChild(it.key(), Qt::FindDirectChildrenOnly); - if (child) { - child->setPresetList(it.value().toObject()); - } - } - } + virtual void setPresetList(const QJsonObject& object); // This must be named toJSON to integrate with the global scripting JSON object Q_INVOKABLE QString toJSON() { return QJsonDocument(toJsonValue(*this).toObject()).toJson(QJsonDocument::Compact); } From 33d770c24e27fb3fb4eafe2627e134bf08095482 Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Mon, 24 Apr 2017 00:52:09 -0700 Subject: [PATCH 04/31] removing the explicit SettingHandle path to REnder?engine --- libraries/render-utils/src/AmbientOcclusionEffect.h | 2 +- libraries/render-utils/src/RenderShadowTask.h | 2 +- libraries/render/src/task/Config.h | 8 ++------ 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 92d0f1d375..3643e608ed 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -71,7 +71,7 @@ class AmbientOcclusionEffectConfig : public render::GPUJobConfig::Persistent { Q_PROPERTY(int blurRadius MEMBER blurRadius WRITE setBlurRadius) public: - AmbientOcclusionEffectConfig() : render::GPUJobConfig::Persistent("Ambient Occlusion", false) {} + AmbientOcclusionEffectConfig() : render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion", false) {} const int MAX_RESOLUTION_LEVEL = 4; const int MAX_BLUR_RADIUS = 6; diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index a044028e4d..031f44a42d 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -35,7 +35,7 @@ class RenderShadowTaskConfig : public render::Task::Config::Persistent { Q_OBJECT Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty) public: - RenderShadowTaskConfig() : render::Task::Config::Persistent("Shadows", false) {} + RenderShadowTaskConfig() : render::Task::Config::Persistent(QStringList() << "Render" << "Engine" << "Shadows", false) {} signals: void dirty(); diff --git a/libraries/render/src/task/Config.h b/libraries/render/src/task/Config.h index 203a0e4688..2825a06c15 100644 --- a/libraries/render/src/task/Config.h +++ b/libraries/render/src/task/Config.h @@ -32,14 +32,10 @@ public: const QString NONE = "None"; PersistentConfig() = delete; - PersistentConfig(const QString& path) : - _preset(QStringList() << "Render" << "Engine" << path, DEFAULT) { } PersistentConfig(const QStringList& path) : - _preset(QStringList() << "Render" << "Engine" << path, DEFAULT) { } - PersistentConfig(const QString& path, bool enabled) : C(enabled), - _preset(QStringList() << "Render" << "Engine" << path, enabled ? DEFAULT : NONE) { } + _preset(path, DEFAULT) { } PersistentConfig(const QStringList& path, bool enabled) : C(enabled), - _preset(QStringList() << "Render" << "Engine" << path, enabled ? DEFAULT : NONE) { } + _preset(path, enabled ? DEFAULT : NONE) { } QStringList getPresetList() { if (_presets.empty()) { From c36f8da4c00afbdf0c3af5ca4365cf021a168758 Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 24 Apr 2017 10:46:29 -0700 Subject: [PATCH 05/31] Fixing build on mac --- interface/src/avatar/CauterizedModel.cpp | 3 +- libraries/render-utils/src/Model.cpp | 2 +- libraries/render/src/render/Engine.h | 2 + libraries/render/src/task/Config.h | 2 + libraries/render/src/task/Task.h | 51 +++++++++++------------- 5 files changed, 31 insertions(+), 29 deletions(-) diff --git a/interface/src/avatar/CauterizedModel.cpp b/interface/src/avatar/CauterizedModel.cpp index c7d25d3151..d7b7e0fedf 100644 --- a/interface/src/avatar/CauterizedModel.cpp +++ b/interface/src/avatar/CauterizedModel.cpp @@ -16,6 +16,7 @@ #include #include "CauterizedMeshPartPayload.h" +#include "RenderUtilsLogging.h" CauterizedModel::CauterizedModel(RigPointer rig, QObject* parent) : @@ -51,7 +52,7 @@ void CauterizedModel::createVisibleRenderItemSet() { // all of our mesh vectors must match in size if ((int)meshes.size() != _meshStates.size()) { - qCDebug(renderlogging) << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; + qCDebug(renderutils) << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; return; } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 309182b25e..eddda41d5e 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1194,7 +1194,7 @@ void Model::createVisibleRenderItemSet() { // all of our mesh vectors must match in size if ((int)meshes.size() != _meshStates.size()) { - qCDebug(renderlogging) << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; + qCDebug(renderutils) << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; return; } diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index d4dba0e340..240693b422 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -100,6 +100,8 @@ namespace render { protected: RenderContextPointer _renderContext; + + void run(const RenderContextPointer& context) override { assert(_renderContext); Task::run(_renderContext); } }; using EnginePointer = std::shared_ptr; diff --git a/libraries/render/src/task/Config.h b/libraries/render/src/task/Config.h index 2825a06c15..c78a3f3bfe 100644 --- a/libraries/render/src/task/Config.h +++ b/libraries/render/src/task/Config.h @@ -150,6 +150,8 @@ public slots: void refresh(); }; +using QConfigPointer = std::shared_ptr; + } #endif // hifi_task_Config_h diff --git a/libraries/render/src/task/Task.h b/libraries/render/src/task/Task.h index 3fcea66786..ed335150a7 100644 --- a/libraries/render/src/task/Task.h +++ b/libraries/render/src/task/Task.h @@ -41,7 +41,6 @@ using JobContextPointer = std::shared_ptr; class JobConcept { public: using Config = JobConfig; - using QConfigPointer = std::shared_ptr; JobConcept(QConfigPointer config) : _config(config) {} virtual ~JobConcept() = default; @@ -88,10 +87,8 @@ public: using Context = RC; using ContextPointer = std::shared_ptr; using Config = JobConfig; - using QConfigPointer = std::shared_ptr; using None = JobNoIO; - //template class Concept : public JobConcept { public: Concept(QConfigPointer config) : JobConcept(config) {} @@ -130,11 +127,11 @@ public: void applyConfiguration() override { - jobConfigure(_data, *std::static_pointer_cast(_config)); + jobConfigure(_data, *std::static_pointer_cast(Concept::_config)); } void run(const ContextPointer& renderContext) override { - renderContext->jobConfig = std::static_pointer_cast(_config); + renderContext->jobConfig = std::static_pointer_cast(Concept::_config); if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->isEnabled()) { jobRun(_data, renderContext, _input.get(), _output.edit()); } @@ -186,13 +183,13 @@ public: using Context = RC; using ContextPointer = std::shared_ptr; using Config = TaskConfig; - using _Job = Job; - using QConfigPointer = _Job::QConfigPointer; - using None = _Job::None; - using Concept = _Job::Concept; - using Jobs = std::vector<_Job>; + using JobType = Job; + using None = typename JobType::None; + using Concept = typename JobType::Concept; + using ConceptPointer = typename JobType::ConceptPointer; + using Jobs = std::vector; - Task(std::string name, ConceptPointer concept) : Job(name, concept) {} + Task(std::string name, ConceptPointer concept) : JobType(name, concept) {} class TaskConcept : public Concept { public: @@ -210,7 +207,7 @@ public: _jobs.emplace_back(name, (NT::JobModel::create(input, std::forward(args)...))); // Conect the child config to this task's config - std::static_pointer_cast(getConfiguration())->connectChildConfig(_jobs.back().getConfiguration(), name); + std::static_pointer_cast(Concept::getConfiguration())->connectChildConfig(_jobs.back().getConfiguration(), name); return _jobs.back().getOutput(); } @@ -255,31 +252,31 @@ public: // A brand new config auto config = std::make_shared(); // Make sure we transfer the former children configs to the new config - config->transferChildrenConfigs(_config); + config->transferChildrenConfigs(Concept::_config); // swap - _config = config; + Concept::_config = config; // Capture this - std::static_pointer_cast(_config)->_task = this; + std::static_pointer_cast(Concept::_config)->_task = this; } QConfigPointer& getConfiguration() override { - if (!_config) { + if (!Concept::_config) { createConfiguration(); } - return _config; + return Concept::_config; } void applyConfiguration() override { - jobConfigure(_data, *std::static_pointer_cast(_config)); - for (auto& job : _jobs) { + jobConfigure(_data, *std::static_pointer_cast(Concept::_config)); + for (auto& job : TaskConcept::_jobs) { job.applyConfiguration(); } } void run(const ContextPointer& renderContext) override { - auto config = std::static_pointer_cast(_config); + auto config = std::static_pointer_cast(Concept::_config); if (config->alwaysEnabled || config->enabled) { - for (auto job : _jobs) { + for (auto job : TaskConcept::_jobs) { job.run(renderContext); } } @@ -292,15 +289,15 @@ public: // Create a new job in the Task's queue; returns the job's output template const Varying addJob(std::string name, const Varying& input, A&&... args) { - return std::static_pointer_cast( _concept)->addJob(name, input, std::forward(args)...); + return std::static_pointer_cast(JobType::_concept)->template addJob(name, input, std::forward(args)...); } template const Varying addJob(std::string name, A&&... args) { const auto input = Varying(typename T::JobModel::Input()); - return std::static_pointer_cast( _concept)->addJob(name, input, std::forward(args)...); + return std::static_pointer_cast(JobType::_concept)->template addJob(name, input, std::forward(args)...); } std::shared_ptr getConfiguration() { - return std::static_pointer_cast(_concept->getConfiguration()); + return std::static_pointer_cast(JobType::_concept->getConfiguration()); } protected: @@ -308,12 +305,12 @@ protected: } -#define Task_DeclareTypeAliases(ContextName) \ +#define Task_DeclareTypeAliases(ContextType) \ using JobConfig = task::JobConfig; \ using TaskConfig = task::TaskConfig; \ template using PersistentConfig = task::PersistentConfig; \ - using Job = task::Job<##ContextName>; \ - using Task = task::Task<##ContextName>; \ + using Job = task::Job; \ + using Task = task::Task; \ using Varying = task::Varying; \ template < typename T0, typename T1 > using VaryingSet2 = task::VaryingSet2; \ template < typename T0, typename T1, typename T2 > using VaryingSet3 = task::VaryingSet3; \ From 4c212fb1e56450c57f4f70792fd3c3041fd77da4 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 10 Apr 2017 17:28:21 -0700 Subject: [PATCH 06/31] pull qApp spaghetti out of Avatar class some ends of spaghetti get pushed into AvatarManger class split Camera class into Camera base and FancyCamera derivation Application::getCamera() returns Camera by refence instead of pointer --- interface/src/FancyCamera.h | 3 --- interface/src/avatar/Avatar.cpp | 1 - 2 files changed, 4 deletions(-) diff --git a/interface/src/FancyCamera.h b/interface/src/FancyCamera.h index cd231cd929..9ffa6cafd8 100644 --- a/interface/src/FancyCamera.h +++ b/interface/src/FancyCamera.h @@ -13,9 +13,6 @@ #include "Camera.h" -#include - -// TODO: come up with a better name than "FancyCamera" class FancyCamera : public Camera { Q_OBJECT diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ce8ec44f6c..9360421417 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -59,7 +59,6 @@ namespace render { auto avatarPtr = static_pointer_cast(avatar); if (avatarPtr->isInitialized() && args) { PROFILE_RANGE_BATCH(*args->_batch, "renderAvatarPayload"); - // TODO AVATARS_RENDERER: remove need for qApp avatarPtr->render(args); } } From 65682a914da69a55ed7c75e1fd3a1165e345f291 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 14 Apr 2017 10:22:32 -0700 Subject: [PATCH 07/31] remove cufty AvatarManager LocalLights feature --- interface/src/Application.cpp | 6 ----- interface/src/avatar/Avatar.cpp | 31 +++++------------------ interface/src/avatar/AvatarManager.cpp | 35 -------------------------- interface/src/avatar/AvatarManager.h | 15 ----------- 4 files changed, 6 insertions(+), 81 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 39a4b8ee7c..8801989e44 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5451,12 +5451,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri entityScriptingInterface->setPacketSender(&_entityEditSender); entityScriptingInterface->setEntityTree(getEntities()->getTree()); - // AvatarManager has some custom types - AvatarManager::registerMetaTypes(scriptEngine); - - // give the script engine to the RecordingScriptingInterface for its callbacks - DependencyManager::get()->setScriptEngine(scriptEngine); - if (property(hifi::properties::TEST).isValid()) { scriptEngine->registerGlobalObject("Test", TestScriptingInterface::getInstance()); } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 9360421417..a639b6880b 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -638,36 +638,17 @@ void Avatar::render(RenderArgs* renderArgs) { glm::vec3 toTarget = frustum.getPosition() - getPosition(); float distanceToTarget = glm::length(toTarget); - { - fixupModelsInScene(renderArgs->_scene); + fixupModelsInScene(renderArgs->_scene); - if (renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE) { - // add local lights - const float BASE_LIGHT_DISTANCE = 2.0f; - const float LIGHT_FALLOFF_RADIUS = 0.01f; - const float LIGHT_EXPONENT = 1.0f; - const float LIGHT_CUTOFF = glm::radians(80.0f); - float distance = BASE_LIGHT_DISTANCE * getUniformScale(); - glm::vec3 position = _skeletonModel->getTranslation(); - glm::quat orientation = getOrientation(); - foreach (const AvatarManager::LocalLight& light, DependencyManager::get()->getLocalLights()) { - glm::vec3 direction = orientation * light.direction; - DependencyManager::get()->addSpotLight(position - direction * distance, - distance * 2.0f, light.color, 0.5f, LIGHT_FALLOFF_RADIUS, orientation, LIGHT_EXPONENT, LIGHT_CUTOFF); - } - } - - bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes); - if (renderBounding && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) { - PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); - const float BOUNDING_SHAPE_ALPHA = 0.7f; - _skeletonModel->renderBoundingCollisionShapes(*renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA); - } + bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes); + if (renderBounding && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) { + PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); + const float BOUNDING_SHAPE_ALPHA = 0.7f; + _skeletonModel->renderBoundingCollisionShapes(*renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA); } const float DISPLAYNAME_DISTANCE = 20.0f; setShowDisplayName(distanceToTarget < DISPLAYNAME_DISTANCE); - if (!isMyAvatar() || renderArgs->_cameraMode != (int8_t)CAMERA_MODE_FIRST_PERSON) { auto& frustum = renderArgs->getViewFrustum(); auto textPosition = getDisplayNamePosition(); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index c4bcb67a16..ef57211d5c 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -50,23 +50,6 @@ static const quint64 MIN_TIME_BETWEEN_MY_AVATAR_DATA_SENDS = USECS_PER_SECOND / // We add _myAvatar into the hash with all the other AvatarData, and we use the default NULL QUid as the key. const QUuid MY_AVATAR_KEY; // NULL key -static QScriptValue localLightToScriptValue(QScriptEngine* engine, const AvatarManager::LocalLight& light) { - QScriptValue object = engine->newObject(); - object.setProperty("direction", vec3toScriptValue(engine, light.direction)); - object.setProperty("color", vec3toScriptValue(engine, light.color)); - return object; -} - -static void localLightFromScriptValue(const QScriptValue& value, AvatarManager::LocalLight& light) { - vec3FromScriptValue(value.property("direction"), light.direction); - vec3FromScriptValue(value.property("color"), light.color); -} - -void AvatarManager::registerMetaTypes(QScriptEngine* engine) { - qScriptRegisterMetaType(engine, localLightToScriptValue, localLightFromScriptValue); - qScriptRegisterSequenceMetaType >(engine); -} - AvatarManager::AvatarManager(QObject* parent) : _avatarsToFade(), _myAvatar(std::make_shared(qApp->thread(), std::make_shared())) @@ -387,24 +370,6 @@ void AvatarManager::deleteAllAvatars() { } } -void AvatarManager::setLocalLights(const QVector& localLights) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setLocalLights", Q_ARG(const QVector&, localLights)); - return; - } - _localLights = localLights; -} - -QVector AvatarManager::getLocalLights() const { - if (QThread::currentThread() != thread()) { - QVector result; - QMetaObject::invokeMethod(const_cast(this), "getLocalLights", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(QVector, result)); - return result; - } - return _localLights; -} - void AvatarManager::getObjectsToRemoveFromPhysics(VectorOfMotionStates& result) { result.clear(); result.swap(_motionStatesToRemoveFromPhysics); diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 45f1a597eb..074e0f4fba 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -64,16 +64,6 @@ public: bool shouldShowReceiveStats() const { return _shouldShowReceiveStats; } - class LocalLight { - public: - glm::vec3 color; - glm::vec3 direction; - }; - - Q_INVOKABLE void setLocalLights(const QVector& localLights); - Q_INVOKABLE QVector getLocalLights() const; - - void getObjectsToRemoveFromPhysics(VectorOfMotionStates& motionStates); void getObjectsToAddToPhysics(VectorOfMotionStates& motionStates); void getObjectsToChange(VectorOfMotionStates& motionStates); @@ -116,8 +106,6 @@ private: std::shared_ptr _myAvatar; quint64 _lastSendAvatarDataTime = 0; // Controls MyAvatar send data rate. - QVector _localLights; - bool _shouldShowReceiveStats = false; std::list> _collisionInjectors; @@ -129,7 +117,4 @@ private: bool _shouldRender { true }; }; -Q_DECLARE_METATYPE(AvatarManager::LocalLight) -Q_DECLARE_METATYPE(QVector) - #endif // hifi_AvatarManager_h From 63939728740a7fea32d30f21695b87a3b8b1190b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 14 Apr 2017 13:36:20 -0700 Subject: [PATCH 08/31] remove AvatarManager dependency from Avatar --- interface/src/avatar/Avatar.cpp | 16 ++++++++++------ interface/src/avatar/Avatar.h | 3 ++- interface/src/avatar/AvatarManager.h | 6 +----- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index a639b6880b..84638f8008 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -28,7 +28,6 @@ #include #include -#include "AvatarManager.h" #include "AvatarMotionState.h" #include "Camera.h" #include "Menu.h" @@ -73,6 +72,12 @@ namespace render { } } +// static +bool showReceiveStats = false; +void Avatar::setShowReceiveStats(bool receiveStats) { + showReceiveStats = receiveStats; +} + Avatar::Avatar(QThread* thread, RigPointer rig) : AvatarData(), _skeletonOffset(0.0f), @@ -582,7 +587,6 @@ void Avatar::render(RenderArgs* renderArgs) { bool havePosition, haveRotation; if (_handState & LEFT_HAND_POINTING_FLAG) { - if (_handState & IS_FINGER_POINTING_FLAG) { int leftIndexTip = getJointIndex("LeftHandIndex4"); int leftIndexTipJoint = getJointIndex("LeftHandIndex3"); @@ -809,7 +813,7 @@ Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& view, const g void Avatar::renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const { PROFILE_RANGE_BATCH(batch, __FUNCTION__); - bool shouldShowReceiveStats = DependencyManager::get()->shouldShowReceiveStats() && !isMyAvatar(); + bool shouldShowReceiveStats = showReceiveStats && !isMyAvatar(); // If we have nothing to draw, or it's totally transparent, or it's too close or behind the camera, return static const float CLIP_DISTANCE = 0.2f; @@ -1473,16 +1477,16 @@ QList Avatar::getSkeleton() { void Avatar::addToScene(AvatarSharedPointer myHandle, const render::ScenePointer& scene) { if (scene) { - render::Transaction transaction; auto nodelist = DependencyManager::get(); if (DependencyManager::get()->shouldRenderAvatars() && !nodelist->isIgnoringNode(getSessionUUID()) && !nodelist->isRadiusIgnoringNode(getSessionUUID())) { + render::Transaction transaction; addToScene(myHandle, scene, transaction); + scene->enqueueTransaction(transaction); } - scene->enqueueTransaction(transaction); } else { - qCWarning(interfaceapp) << "AvatarManager::addAvatar() : Unexpected null scene, possibly during application shutdown"; + qCWarning(interfaceapp) << "Avatar::addAvatar() : Unexpected null scene, possibly during application shutdown"; } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 14d1da530a..9bb8010b0d 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -66,6 +66,8 @@ class Avatar : public AvatarData { Q_PROPERTY(glm::vec3 skeletonOffset READ getSkeletonOffset WRITE setSkeletonOffset) public: + static void setShowReceiveStats(bool receiveStats); + explicit Avatar(QThread* thread, RigPointer rig = nullptr); ~Avatar(); @@ -251,7 +253,6 @@ public slots: void setModelURLFinished(bool success); protected: - friend class AvatarManager; const float SMOOTH_TIME_POSITION = 0.125f; const float SMOOTH_TIME_ORIENTATION = 0.075f; diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 074e0f4fba..1832bc7126 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -62,8 +62,6 @@ public: void clearOtherAvatars(); void deleteAllAvatars(); - bool shouldShowReceiveStats() const { return _shouldShowReceiveStats; } - void getObjectsToRemoveFromPhysics(VectorOfMotionStates& motionStates); void getObjectsToAddToPhysics(VectorOfMotionStates& motionStates); void getObjectsToChange(VectorOfMotionStates& motionStates); @@ -85,7 +83,7 @@ public: float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); } public slots: - void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; } + void setShouldShowReceiveStats(bool shouldShowReceiveStats) const { Avatar::setShowReceiveStats(shouldShowReceiveStats); } void updateAvatarRenderStatus(bool shouldRenderAvatars); private: @@ -106,8 +104,6 @@ private: std::shared_ptr _myAvatar; quint64 _lastSendAvatarDataTime = 0; // Controls MyAvatar send data rate. - bool _shouldShowReceiveStats = false; - std::list> _collisionInjectors; RateCounter<> _myAvatarSendRate; From 010d1dfa222286744959e47a6d4a8fb370d3198c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 14 Apr 2017 14:39:33 -0700 Subject: [PATCH 09/31] remove Menu dependency from Avatar class --- interface/src/avatar/Avatar.cpp | 34 ++++++++++++++++++++------ interface/src/avatar/Avatar.h | 21 ++++++++++------ interface/src/avatar/AvatarManager.cpp | 6 +++++ 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 84638f8008..2234630504 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -30,7 +30,6 @@ #include "AvatarMotionState.h" #include "Camera.h" -#include "Menu.h" #include "InterfaceLogging.h" #include "SceneScriptingInterface.h" #include "SoftAttachmentModel.h" @@ -78,6 +77,26 @@ void Avatar::setShowReceiveStats(bool receiveStats) { showReceiveStats = receiveStats; } +// static +bool renderMyLookAtVectors = false; +bool renderOtherLookAtVectors = false; +void Avatar::setShowLookAtVectors(bool showMine, bool showOthers) { + renderMyLookAtVectors = showMine; + renderOtherLookAtVectors = showOthers; +} + +// static +bool renderCollisionShapes = false; +void Avatar::setRenderCollisionShapes(bool render) { + renderCollisionShapes = render; +} + +// static +bool showNamesAboveHeads = false; +void Avatar::setShowNamesAboveHeads(bool show) { + showNamesAboveHeads = show; +} + Avatar::Avatar(QThread* thread, RigPointer rig) : AvatarData(), _skeletonOffset(0.0f), @@ -354,7 +373,7 @@ void Avatar::simulate(float deltaTime, bool inView) { _smoothPositionTimer += deltaTime; if (_smoothPositionTimer < _smoothPositionTime) { AvatarData::setPosition( - lerp(_smoothPositionInitial, + lerp(_smoothPositionInitial, _smoothPositionTarget, easeInOutQuad(glm::clamp(_smoothPositionTimer / _smoothPositionTime, 0.0f, 1.0f))) ); @@ -367,7 +386,7 @@ void Avatar::simulate(float deltaTime, bool inView) { _smoothOrientationTimer += deltaTime; if (_smoothOrientationTimer < _smoothOrientationTime) { AvatarData::setOrientation( - slerp(_smoothOrientationInitial, + slerp(_smoothOrientationInitial, _smoothOrientationTarget, easeInOutQuad(glm::clamp(_smoothOrientationTimer / _smoothOrientationTime, 0.0f, 1.0f))) ); @@ -541,9 +560,9 @@ void Avatar::postUpdate(float deltaTime) { bool renderLookAtVectors; if (isMyAvatar()) { - renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::RenderMyLookAtVectors); + renderLookAtVectors = renderMyLookAtVectors; } else { - renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::RenderOtherLookAtVectors); + renderLookAtVectors = renderOtherLookAtVectors; } if (renderLookAtVectors) { @@ -644,8 +663,7 @@ void Avatar::render(RenderArgs* renderArgs) { fixupModelsInScene(renderArgs->_scene); - bool renderBounding = Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes); - if (renderBounding && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) { + if (renderCollisionShapes && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) { PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); const float BOUNDING_SHAPE_ALPHA = 0.7f; _skeletonModel->renderBoundingCollisionShapes(*renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA); @@ -1269,7 +1287,7 @@ float Avatar::getPelvisFloatingHeight() const { } void Avatar::setShowDisplayName(bool showDisplayName) { - if (!Menu::getInstance()->isOptionChecked(MenuOption::NamesAboveHeads)) { + if (!showNamesAboveHeads) { _displayNameAlpha = 0.0f; return; } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 9bb8010b0d..116e5aad11 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -67,6 +67,9 @@ class Avatar : public AvatarData { public: static void setShowReceiveStats(bool receiveStats); + static void setShowLookAtVectors(bool showMine, bool showOthers); + static void setRenderCollisionShapes(bool render); + static void setShowNamesAboveHeads(bool show); explicit Avatar(QThread* thread, RigPointer rig = nullptr); ~Avatar(); @@ -240,6 +243,13 @@ public: return (lerpValue*(4.0f - 2.0f * lerpValue) - 1.0f); } + float getBoundingRadius() const; + + void addToScene(AvatarSharedPointer self, const render::ScenePointer& scene); + void ensureInScene(AvatarSharedPointer self, const render::ScenePointer& scene); + bool isInScene() const { return render::Item::isValidID(_renderItemID); } + + void setMotionState(AvatarMotionState* motionState); public slots: @@ -261,8 +271,6 @@ protected: QString _empty{}; virtual void maybeUpdateSessionDisplayNameFromTransport(const QString& sessionDisplayName) override { _sessionDisplayName = sessionDisplayName; } // don't use no-op setter! - void setMotionState(AvatarMotionState* motionState); - SkeletonModelPointer _skeletonModel; glm::vec3 _skeletonOffset; std::vector> _attachmentModels; @@ -316,16 +324,13 @@ protected: ThreadSafeValueCache _rightPalmPositionCache { glm::vec3() }; ThreadSafeValueCache _rightPalmRotationCache { glm::quat() }; - void addToScene(AvatarSharedPointer self, const render::ScenePointer& scene); - void ensureInScene(AvatarSharedPointer self, const render::ScenePointer& scene); - bool isInScene() const { return render::Item::isValidID(_renderItemID); } - // Some rate tracking support RateCounter<> _simulationRate; RateCounter<> _simulationInViewRate; RateCounter<> _skeletonModelSimulationRate; RateCounter<> _jointDataSimulationRate; +<<<<<<< 4318cce04a59543d80a9364c86aab79408dcb50e // Smoothing data for blending from one position/orientation to another on remote agents. float _smoothPositionTime; float _smoothPositionTimer; @@ -336,6 +341,8 @@ protected: glm::quat _smoothOrientationInitial; glm::quat _smoothOrientationTarget; +======= +>>>>>>> remove Menu dependency from Avatar class private: class AvatarEntityDataHash { public: @@ -355,8 +362,6 @@ private: bool _isLookAtTarget { false }; bool _isAnimatingScale { false }; - float getBoundingRadius() const; - static int _jointConesID; int _voiceSphereID; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index ef57211d5c..35a5681213 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -147,6 +147,12 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { ViewFrustum cameraView; qApp->copyDisplayViewFrustum(cameraView); + // HACK: update Avatar namespace settings + Avatar::setShowLookAtVectors( + Menu::getInstance()->isOptionChecked(MenuOption::RenderMyLookAtVectors), + Menu::getInstance()->isOptionChecked(MenuOption::RenderOtherLookAtVectors)); + Avatar::setRenderCollisionShapes(Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes)); + std::priority_queue sortedAvatars; AvatarData::sortAvatars(avatarList, cameraView, sortedAvatars, From aceac12398674418786cc99165bc01556d5b0b27 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Apr 2017 13:36:33 -0700 Subject: [PATCH 10/31] use 'using' instead of 'typedef' --- libraries/physics/src/PhysicsEngine.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 9f2f1aff5c..07de0e7b5c 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -41,8 +41,8 @@ public: void* _b; // ObjectMotionState pointer }; -typedef std::map ContactMap; -typedef std::vector CollisionEvents; +using ContactMap = std::map; +using CollisionEvents = std::vector; class PhysicsEngine { public: From 2441536de387637b48531fcbec6121d68206d968 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Apr 2017 13:37:36 -0700 Subject: [PATCH 11/31] remove Avatar dependency on AvatarMotionState --- interface/src/avatar/Avatar.cpp | 25 ++++--- interface/src/avatar/Avatar.h | 14 ++-- interface/src/avatar/AvatarManager.cpp | 76 ++++++++++++++-------- interface/src/avatar/AvatarManager.h | 4 +- interface/src/avatar/AvatarMotionState.cpp | 6 +- interface/src/avatar/AvatarMotionState.h | 8 +-- libraries/physics/src/PhysicsEngine.cpp | 1 + 7 files changed, 79 insertions(+), 55 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 2234630504..91d8dfb447 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -149,11 +149,6 @@ Avatar::~Avatar() { }); } - if (_motionState) { - delete _motionState; - _motionState = nullptr; - } - auto geometryCache = DependencyManager::get(); if (geometryCache) { geometryCache->releaseID(_nameRectGeometryID); @@ -1202,8 +1197,8 @@ int Avatar::parseDataFromBuffer(const QByteArray& buffer) { const float MOVE_DISTANCE_THRESHOLD = 0.001f; _moving = glm::distance(oldPosition, getPosition()) > MOVE_DISTANCE_THRESHOLD; - if (_moving && _motionState) { - _motionState->addDirtyFlags(Simulation::DIRTY_POSITION); + if (_moving) { + addPhysicsFlags(Simulation::DIRTY_POSITION); } if (_moving || _hasNewJointData) { locationChanged(); @@ -1325,14 +1320,18 @@ void Avatar::getCapsule(glm::vec3& start, glm::vec3& end, float& radius) { radius = halfExtents.x; } -void Avatar::setMotionState(AvatarMotionState* motionState) { - _motionState = motionState; -} - // virtual void Avatar::rebuildCollisionShape() { - if (_motionState) { - _motionState->addDirtyFlags(Simulation::DIRTY_SHAPE); + addPhysicsFlags(Simulation::DIRTY_SHAPE); +} + +void Avatar::setPhysicsCallback(AvatarPhysicsCallback cb) { + _physicsCallback = cb; +} + +void Avatar::addPhysicsFlags(uint32_t flags) { + if (_physicsCallback) { + _physicsCallback(flags); } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 116e5aad11..17b5ea926e 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -11,6 +11,7 @@ #ifndef hifi_Avatar_h #define hifi_Avatar_h +#include #include #include @@ -48,9 +49,10 @@ enum ScreenTintLayer { NUM_SCREEN_TINT_LAYERS }; -class AvatarMotionState; class Texture; +using AvatarPhysicsCallback = std::function; + class Avatar : public AvatarData { Q_OBJECT @@ -190,7 +192,7 @@ public: virtual void computeShapeInfo(ShapeInfo& shapeInfo); void getCapsule(glm::vec3& start, glm::vec3& end, float& radius); - AvatarMotionState* getMotionState() { return _motionState; } + //AvatarMotionState* getMotionState() { return _motionState; } using SpatiallyNestable::setPosition; virtual void setPosition(const glm::vec3& position) override; @@ -248,8 +250,12 @@ public: void addToScene(AvatarSharedPointer self, const render::ScenePointer& scene); void ensureInScene(AvatarSharedPointer self, const render::ScenePointer& scene); bool isInScene() const { return render::Item::isValidID(_renderItemID); } + bool isMoving() const { return _moving; } - void setMotionState(AvatarMotionState* motionState); + //void setMotionState(AvatarMotionState* motionState); + void setPhysicsCallback(AvatarPhysicsCallback cb); + void addPhysicsFlags(uint32_t flags); + bool isInPhysicsSimulation() const { return _physicsCallback != nullptr; } public slots: @@ -366,7 +372,7 @@ private: int _voiceSphereID; - AvatarMotionState* _motionState = nullptr; + AvatarPhysicsCallback _physicsCallback { nullptr }; }; #endif // hifi_Avatar_h diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 35a5681213..41cf797eba 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -74,6 +74,7 @@ AvatarManager::AvatarManager(QObject* parent) : } AvatarManager::~AvatarManager() { + assert(_motionStates.empty()); } void AvatarManager::init() { @@ -128,10 +129,9 @@ float AvatarManager::getAvatarUpdateRate(const QUuid& sessionID, const QString& float AvatarManager::getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName) const { auto avatar = std::static_pointer_cast(getAvatarBySessionID(sessionID)); - return avatar ? avatar->getSimulationRate(rateName) : 0.0f; + return avatar ? avatar->getSimulationRate(rateName) : 0.0f; } - void AvatarManager::updateOtherAvatars(float deltaTime) { // lock the hash for read to check the size QReadLocker lock(&_hashLock); @@ -189,16 +189,15 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { if (_shouldRender) { avatar->ensureInScene(avatar, qApp->getMain3DScene()); } - if (!avatar->getMotionState()) { + if (!avatar->isInPhysicsSimulation()) { ShapeInfo shapeInfo; avatar->computeShapeInfo(shapeInfo); btCollisionShape* shape = const_cast(ObjectMotionState::getShapeManager()->getShape(shapeInfo)); if (shape) { - // don't add to the simulation now, instead put it on a list to be added later - AvatarMotionState* motionState = new AvatarMotionState(avatar.get(), shape); - avatar->setMotionState(motionState); + AvatarMotionState* motionState = new AvatarMotionState(avatar, shape); + avatar->setPhysicsCallback([=] (uint32_t flags) { motionState->addDirtyFlags(flags); }); + _motionStates.insert(avatar.get(), motionState); _motionStatesToAddToPhysics.insert(motionState); - _motionStatesThatMightUpdate.insert(motionState); } } avatar->animateScaleChanges(deltaTime); @@ -283,30 +282,34 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { const float MIN_FADE_SCALE = MIN_AVATAR_SCALE; QReadLocker locker(&_hashLock); - QVector::iterator itr = _avatarsToFade.begin(); - while (itr != _avatarsToFade.end()) { - auto avatar = std::static_pointer_cast(*itr); + QVector::iterator avatarItr = _avatarsToFade.begin(); + while (avatarItr != _avatarsToFade.end()) { + auto avatar = std::static_pointer_cast(*avatarItr); avatar->setTargetScale(avatar->getUniformScale() * SHRINK_RATE); avatar->animateScaleChanges(deltaTime); if (avatar->getTargetScale() <= MIN_FADE_SCALE) { - // fading to zero is such a rare event we push unique transaction for each one + // fading to zero is such a rare event we push a unique transaction for each if (avatar->isInScene()) { const render::ScenePointer& scene = qApp->getMain3DScene(); render::Transaction transaction; - avatar->removeFromScene(*itr, scene, transaction); + avatar->removeFromScene(*avatarItr, scene, transaction); scene->enqueueTransaction(transaction); } - // only remove from _avatarsToFade if we're sure its motionState has been removed from PhysicsEngine - if (_motionStatesToRemoveFromPhysics.empty()) { - itr = _avatarsToFade.erase(itr); - } else { - ++itr; + // delete the motionState + // TODO: use SharedPointer technology to make this happen automagically + assert(!avatar->isInPhysicsSimulation()); + AvatarMotionStateMap::iterator motionStateItr = _motionStates.find(avatar.get()); + if (motionStateItr != _motionStates.end()) { + delete *motionStateItr; + _motionStates.erase(motionStateItr); } + + avatarItr = _avatarsToFade.erase(avatarItr); } else { const bool inView = true; // HACK avatar->simulate(deltaTime, inView); - ++itr; + ++avatarItr; } } } @@ -315,19 +318,24 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() { return std::make_shared(qApp->thread(), std::make_shared()); } +void AvatarManager::removeAvatarFromPhysicsSimulation(Avatar* avatar) { + assert(avatar); + avatar->setPhysicsCallback(nullptr); + AvatarMotionStateMap::iterator itr = _motionStates.find(avatar); + if (itr != _motionStates.end()) { + AvatarMotionState* motionState = *itr; + _motionStatesToAddToPhysics.remove(motionState); + _motionStatesToRemoveFromPhysics.push_back(motionState); + } +} + void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) { AvatarHashMap::handleRemovedAvatar(removedAvatar, removalReason); // removedAvatar is a shared pointer to an AvatarData but we need to get to the derived Avatar // class in this context so we can call methods that don't exist at the base class. auto avatar = std::static_pointer_cast(removedAvatar); - - AvatarMotionState* motionState = avatar->getMotionState(); - if (motionState) { - _motionStatesThatMightUpdate.remove(motionState); - _motionStatesToAddToPhysics.remove(motionState); - _motionStatesToRemoveFromPhysics.push_back(motionState); - } + removeAvatarFromPhysicsSimulation(avatar.get()); if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) { emit DependencyManager::get()->enteredIgnoreRadius(); @@ -362,11 +370,21 @@ void AvatarManager::clearOtherAvatars() { ++avatarIterator; } } + assert(scene); scene->enqueueTransaction(transaction); _myAvatar->clearLookAtTargetAvatar(); } void AvatarManager::deleteAllAvatars() { + // delete motionStates + // TODO: use shared_ptr technology to make this work automagically + AvatarMotionStateMap::iterator motionStateItr = _motionStates.begin(); + while (motionStateItr != _motionStates.end()) { + delete *motionStateItr; + ++motionStateItr; + } + _motionStates.clear(); + QReadLocker locker(&_hashLock); AvatarHash::iterator avatarIterator = _avatarHash.begin(); while (avatarIterator != _avatarHash.end()) { @@ -391,10 +409,12 @@ void AvatarManager::getObjectsToAddToPhysics(VectorOfMotionStates& result) { void AvatarManager::getObjectsToChange(VectorOfMotionStates& result) { result.clear(); - for (auto state : _motionStatesThatMightUpdate) { - if (state->_dirtyFlags > 0) { - result.push_back(state); + AvatarMotionStateMap::iterator motionStateItr = _motionStates.begin(); + while (motionStateItr != _motionStates.end()) { + if ((*motionStateItr)->getIncomingDirtyFlags() != 0) { + result.push_back(*motionStateItr); } + ++motionStateItr; } } diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 1832bc7126..5c8935417b 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -93,11 +93,13 @@ private: void simulateAvatarFades(float deltaTime); AvatarSharedPointer newSharedAvatar() override; + void removeAvatarFromPhysicsSimulation(Avatar* avatar); void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override; QVector _avatarsToFade; - QSet _motionStatesThatMightUpdate; + using AvatarMotionStateMap = QMap; + AvatarMotionStateMap _motionStates; VectorOfMotionStates _motionStatesToRemoveFromPhysics; SetOfMotionStates _motionStatesToAddToPhysics; diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp index 335245670b..ffa99e3990 100644 --- a/interface/src/avatar/AvatarMotionState.cpp +++ b/interface/src/avatar/AvatarMotionState.cpp @@ -17,7 +17,7 @@ #include "AvatarMotionState.h" #include "BulletUtil.h" -AvatarMotionState::AvatarMotionState(Avatar* avatar, const btCollisionShape* shape) : ObjectMotionState(shape), _avatar(avatar) { +AvatarMotionState::AvatarMotionState(AvatarSharedPointer avatar, const btCollisionShape* shape) : ObjectMotionState(shape), _avatar(avatar) { assert(_avatar); _type = MOTIONSTATE_TYPE_AVATAR; if (_shape) { @@ -49,7 +49,7 @@ PhysicsMotionType AvatarMotionState::computePhysicsMotionType() const { // virtual and protected const btCollisionShape* AvatarMotionState::computeNewShape() { ShapeInfo shapeInfo; - _avatar->computeShapeInfo(shapeInfo); + std::static_pointer_cast(_avatar)->computeShapeInfo(shapeInfo); return getShapeManager()->getShape(shapeInfo); } @@ -130,7 +130,7 @@ glm::vec3 AvatarMotionState::getObjectAngularVelocity() const { // virtual glm::vec3 AvatarMotionState::getObjectGravity() const { - return _avatar->getAcceleration(); + return std::static_pointer_cast(_avatar)->getAcceleration(); } // virtual diff --git a/interface/src/avatar/AvatarMotionState.h b/interface/src/avatar/AvatarMotionState.h index 98b2b69373..a8dd7327ca 100644 --- a/interface/src/avatar/AvatarMotionState.h +++ b/interface/src/avatar/AvatarMotionState.h @@ -20,7 +20,7 @@ class Avatar; class AvatarMotionState : public ObjectMotionState { public: - AvatarMotionState(Avatar* avatar, const btCollisionShape* shape); + AvatarMotionState(AvatarSharedPointer avatar, const btCollisionShape* shape); virtual PhysicsMotionType getMotionType() const override { return _motionType; } @@ -74,11 +74,7 @@ protected: virtual bool isReadyToComputeShape() const override { return true; } virtual const btCollisionShape* computeNewShape() override; - // The AvatarMotionState keeps a RAW backpointer to its Avatar because all AvatarMotionState - // instances are "owned" by their corresponding Avatar instance and are deleted in the Avatar dtor. - // In other words, it is impossible for the Avatar to be deleted out from under its MotionState. - // In conclusion: weak pointer shennanigans would be pure overhead. - Avatar* _avatar; // do NOT use smartpointer here, no need for weakpointer + AvatarSharedPointer _avatar; uint32_t _dirtyFlags; }; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index ca6889485a..87a15eb264 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -220,6 +220,7 @@ void PhysicsEngine::removeObjects(const SetOfMotionStates& objects) { body->setMotionState(nullptr); delete body; } + object->clearIncomingDirtyFlags(); } } From caf6a77baf15c8f6cacd420ef5c273f651b8b093 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Apr 2017 16:35:32 -0700 Subject: [PATCH 12/31] repair bad merge during rebase --- interface/src/FancyCamera.h | 2 ++ interface/src/avatar/Avatar.h | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/interface/src/FancyCamera.h b/interface/src/FancyCamera.h index 9ffa6cafd8..66f7a07dbd 100644 --- a/interface/src/FancyCamera.h +++ b/interface/src/FancyCamera.h @@ -13,6 +13,8 @@ #include "Camera.h" +#include + class FancyCamera : public Camera { Q_OBJECT diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 17b5ea926e..e777460ecb 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -336,7 +336,6 @@ protected: RateCounter<> _skeletonModelSimulationRate; RateCounter<> _jointDataSimulationRate; -<<<<<<< 4318cce04a59543d80a9364c86aab79408dcb50e // Smoothing data for blending from one position/orientation to another on remote agents. float _smoothPositionTime; float _smoothPositionTimer; @@ -347,8 +346,6 @@ protected: glm::quat _smoothOrientationInitial; glm::quat _smoothOrientationTarget; -======= ->>>>>>> remove Menu dependency from Avatar class private: class AvatarEntityDataHash { public: From 72f5860538de8f3467b432d2141b53e8e09f2a5d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 19 Apr 2017 10:37:49 -0700 Subject: [PATCH 13/31] restore RecordingScriptingInterface to Application --- interface/src/Application.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8801989e44..5fd0b30d01 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5451,6 +5451,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri entityScriptingInterface->setPacketSender(&_entityEditSender); entityScriptingInterface->setEntityTree(getEntities()->getTree()); + // give the script engine to the RecordingScriptingInterface for its callbacks + DependencyManager::get()->setScriptEngine(scriptEngine); + if (property(hifi::properties::TEST).isValid()) { scriptEngine->registerGlobalObject("Test", TestScriptingInterface::getInstance()); } From 823f3a73c6b96d1afee64304e7afd8a66fe355ae Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 19 Apr 2017 11:00:29 -0700 Subject: [PATCH 14/31] remove commented out cruft --- interface/src/avatar/Avatar.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index e777460ecb..b323954049 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -192,8 +192,6 @@ public: virtual void computeShapeInfo(ShapeInfo& shapeInfo); void getCapsule(glm::vec3& start, glm::vec3& end, float& radius); - //AvatarMotionState* getMotionState() { return _motionState; } - using SpatiallyNestable::setPosition; virtual void setPosition(const glm::vec3& position) override; using SpatiallyNestable::setOrientation; From 00b05ed137bf064aaa21e23ed9c9deca2f80180c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 21 Apr 2017 09:31:33 -0700 Subject: [PATCH 15/31] connect menu options to avatar render features --- interface/src/Menu.cpp | 11 +++--- interface/src/Menu.h | 8 ++--- interface/src/avatar/Avatar.cpp | 46 +++++++++++--------------- interface/src/avatar/Avatar.h | 10 +++--- interface/src/avatar/AvatarManager.cpp | 6 ---- interface/src/avatar/AvatarManager.h | 1 - 6 files changed, 36 insertions(+), 46 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8754951317..97e566309f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -504,11 +504,14 @@ Menu::Menu() { #endif addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AvatarReceiveStats, 0, false, - avatarManager.data(), SLOT(setShouldShowReceiveStats(bool))); + avatar.get(), SLOT(setShowReceiveStats(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowBoundingCollisionShapes, 0, false, + avatar.get(), SLOT(setShowCollisionShapes(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowMyLookAtVectors, 0, false, + avatar.get(), SLOT(setShowMyLookAtVectors(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowOtherLookAtVectors, 0, false, + avatar.get(), SLOT(setShowOtherLookAtVectors(bool))); - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderBoundingCollisionShapes); - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderMyLookAtVectors, 0, false); - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::RenderOtherLookAtVectors, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::FixGaze, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawDefaultPose, 0, false, avatar.get(), SLOT(setEnableDebugDrawDefaultPose(bool))); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index eeffcac7ca..d46c2736a4 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -146,9 +146,6 @@ namespace MenuOption { const QString Quit = "Quit"; const QString ReloadAllScripts = "Reload All Scripts"; const QString ReloadContent = "Reload Content (Clears all caches)"; - const QString RenderBoundingCollisionShapes = "Show Bounding Collision Shapes"; - const QString RenderMyLookAtVectors = "Show My Eye Vectors"; - const QString RenderOtherLookAtVectors = "Show Other Eye Vectors"; const QString RenderMaxTextureMemory = "Maximum Texture Memory"; const QString RenderMaxTextureAutomatic = "Automatic Texture Memory"; const QString RenderMaxTexture4MB = "4 MB"; @@ -174,8 +171,11 @@ namespace MenuOption { const QString SendWrongDSConnectVersion = "Send wrong DS connect version"; const QString SendWrongProtocolVersion = "Send wrong protocol version"; const QString SetHomeLocation = "Set Home Location"; - const QString ShowDSConnectTable = "Show Domain Connection Timing"; const QString ShowBordersEntityNodes = "Show Entity Nodes"; + const QString ShowBoundingCollisionShapes = "Show Bounding Collision Shapes"; + const QString ShowDSConnectTable = "Show Domain Connection Timing"; + const QString ShowMyLookAtVectors = "Show My Eye Vectors"; + const QString ShowOtherLookAtVectors = "Show Other Eye Vectors"; const QString ShowRealtimeEntityStats = "Show Realtime Entity Stats"; const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; const QString SimulateEyeTracking = "Simulate"; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 91d8dfb447..1e759ed396 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -71,28 +71,27 @@ namespace render { } } -// static -bool showReceiveStats = false; +static bool showReceiveStats = false; void Avatar::setShowReceiveStats(bool receiveStats) { showReceiveStats = receiveStats; } -// static -bool renderMyLookAtVectors = false; -bool renderOtherLookAtVectors = false; -void Avatar::setShowLookAtVectors(bool showMine, bool showOthers) { - renderMyLookAtVectors = showMine; - renderOtherLookAtVectors = showOthers; +static bool showMyLookAtVectors = false; +void Avatar::setShowMyLookAtVectors(bool showMine) { + showMyLookAtVectors = showMine; } -// static -bool renderCollisionShapes = false; -void Avatar::setRenderCollisionShapes(bool render) { - renderCollisionShapes = render; +static bool showOtherLookAtVectors = false; +void Avatar::setShowOtherLookAtVectors(bool showOthers) { + showOtherLookAtVectors = showOthers; } -// static -bool showNamesAboveHeads = false; +static bool showCollisionShapes = false; +void Avatar::setShowCollisionShapes(bool render) { + showCollisionShapes = render; +} + +static bool showNamesAboveHeads = false; void Avatar::setShowNamesAboveHeads(bool show) { showNamesAboveHeads = show; } @@ -553,14 +552,7 @@ void Avatar::updateRenderItem(render::Transaction& transaction) { void Avatar::postUpdate(float deltaTime) { - bool renderLookAtVectors; - if (isMyAvatar()) { - renderLookAtVectors = renderMyLookAtVectors; - } else { - renderLookAtVectors = renderOtherLookAtVectors; - } - - if (renderLookAtVectors) { + if (isMyAvatar() ? showMyLookAtVectors : showOtherLookAtVectors) { const float EYE_RAY_LENGTH = 10.0; const glm::vec4 BLUE(0.0f, 0.0f, 1.0f, 1.0f); const glm::vec4 RED(1.0f, 0.0f, 0.0f, 1.0f); @@ -653,17 +645,18 @@ void Avatar::render(RenderArgs* renderArgs) { return; } - glm::vec3 toTarget = frustum.getPosition() - getPosition(); - float distanceToTarget = glm::length(toTarget); - fixupModelsInScene(renderArgs->_scene); - if (renderCollisionShapes && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) { + if (showCollisionShapes && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) { PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); const float BOUNDING_SHAPE_ALPHA = 0.7f; _skeletonModel->renderBoundingCollisionShapes(*renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA); } +#if 0 /// -------------- REMOVED FOR NOW -------------- + // removed CPU calculations as per removal of menu option + glm::vec3 toTarget = frustum.getPosition() - getPosition(); + float distanceToTarget = glm::length(toTarget); const float DISPLAYNAME_DISTANCE = 20.0f; setShowDisplayName(distanceToTarget < DISPLAYNAME_DISTANCE); if (!isMyAvatar() || renderArgs->_cameraMode != (int8_t)CAMERA_MODE_FIRST_PERSON) { @@ -673,6 +666,7 @@ void Avatar::render(RenderArgs* renderArgs) { renderDisplayName(batch, frustum, textPosition); } } +#endif } glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index b323954049..b2b0120b9a 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -68,11 +68,6 @@ class Avatar : public AvatarData { Q_PROPERTY(glm::vec3 skeletonOffset READ getSkeletonOffset WRITE setSkeletonOffset) public: - static void setShowReceiveStats(bool receiveStats); - static void setShowLookAtVectors(bool showMine, bool showOthers); - static void setRenderCollisionShapes(bool render); - static void setShowNamesAboveHeads(bool show); - explicit Avatar(QThread* thread, RigPointer rig = nullptr); ~Avatar(); @@ -256,6 +251,11 @@ public: bool isInPhysicsSimulation() const { return _physicsCallback != nullptr; } public slots: + void setShowReceiveStats(bool receiveStats); + void setShowMyLookAtVectors(bool showMine); + void setShowOtherLookAtVectors(bool showOthers); + void setShowCollisionShapes(bool render); + void setShowNamesAboveHeads(bool show); // FIXME - these should be migrated to use Pose data instead // thread safe, will return last valid palm from cache diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 41cf797eba..ec22c3403a 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -147,12 +147,6 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { ViewFrustum cameraView; qApp->copyDisplayViewFrustum(cameraView); - // HACK: update Avatar namespace settings - Avatar::setShowLookAtVectors( - Menu::getInstance()->isOptionChecked(MenuOption::RenderMyLookAtVectors), - Menu::getInstance()->isOptionChecked(MenuOption::RenderOtherLookAtVectors)); - Avatar::setRenderCollisionShapes(Menu::getInstance()->isOptionChecked(MenuOption::RenderBoundingCollisionShapes)); - std::priority_queue sortedAvatars; AvatarData::sortAvatars(avatarList, cameraView, sortedAvatars, diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 5c8935417b..e5b2117beb 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -83,7 +83,6 @@ public: float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); } public slots: - void setShouldShowReceiveStats(bool shouldShowReceiveStats) const { Avatar::setShowReceiveStats(shouldShowReceiveStats); } void updateAvatarRenderStatus(bool shouldRenderAvatars); private: From 442080dec7134ba01c38703f7cae2b9c7bc74d54 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 21 Apr 2017 09:32:07 -0700 Subject: [PATCH 16/31] remove unused RenderArgs::_cameraMode hack --- interface/src/Application.cpp | 1 - libraries/shared/src/RenderArgs.h | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5fd0b30d01..dff50fd616 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5119,7 +5119,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se QMutexLocker viewLocker(&_viewMutex); renderArgs->setViewFrustum(_displayViewFrustum); } - renderArgs->_cameraMode = (int8_t)theCamera.getMode(); // HACK renderArgs->_scene = getMain3DScene(); _renderEngine->getRenderContext()->args = renderArgs; diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 10a9a20287..9d81913078 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -130,8 +130,7 @@ public: bool _enableTexturing { true }; RenderDetails _details; - render::ScenePointer _scene; // HACK - int8_t _cameraMode { -1 }; // HACK + render::ScenePointer _scene; }; #endif // hifi_RenderArgs_h From 75b563d5982b5fa0651c40ad2ae4dcc4acf831ec Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 21 Apr 2017 11:07:12 -0700 Subject: [PATCH 17/31] restore rendering of avatar receive stats --- interface/src/Application.cpp | 1 + interface/src/avatar/Avatar.cpp | 27 +++++++++++++-------------- interface/src/avatar/Avatar.h | 6 +++++- libraries/avatars/src/AvatarData.cpp | 2 -- libraries/avatars/src/AvatarData.h | 3 --- libraries/shared/src/RenderArgs.h | 1 + 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dff50fd616..5fd0b30d01 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5119,6 +5119,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se QMutexLocker viewLocker(&_viewMutex); renderArgs->setViewFrustum(_displayViewFrustum); } + renderArgs->_cameraMode = (int8_t)theCamera.getMode(); // HACK renderArgs->_scene = getMain3DScene(); _renderEngine->getRenderContext()->args = renderArgs; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 1e759ed396..3bd4c663d2 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -653,20 +653,19 @@ void Avatar::render(RenderArgs* renderArgs) { _skeletonModel->renderBoundingCollisionShapes(*renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA); } -#if 0 /// -------------- REMOVED FOR NOW -------------- - // removed CPU calculations as per removal of menu option - glm::vec3 toTarget = frustum.getPosition() - getPosition(); - float distanceToTarget = glm::length(toTarget); - const float DISPLAYNAME_DISTANCE = 20.0f; - setShowDisplayName(distanceToTarget < DISPLAYNAME_DISTANCE); - if (!isMyAvatar() || renderArgs->_cameraMode != (int8_t)CAMERA_MODE_FIRST_PERSON) { - auto& frustum = renderArgs->getViewFrustum(); - auto textPosition = getDisplayNamePosition(); - if (frustum.pointIntersectsFrustum(textPosition)) { - renderDisplayName(batch, frustum, textPosition); + if (showReceiveStats || showNamesAboveHeads) { + glm::vec3 toTarget = frustum.getPosition() - getPosition(); + float distanceToTarget = glm::length(toTarget); + const float DISPLAYNAME_DISTANCE = 20.0f; + updateDisplayNameAlpha(distanceToTarget < DISPLAYNAME_DISTANCE); + if (!isMyAvatar() || renderArgs->_cameraMode != (int8_t)CAMERA_MODE_FIRST_PERSON) { + auto& frustum = renderArgs->getViewFrustum(); + auto textPosition = getDisplayNamePosition(); + if (frustum.pointIntersectsFrustum(textPosition)) { + renderDisplayName(batch, frustum, textPosition); + } } } -#endif } glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { @@ -1275,8 +1274,8 @@ float Avatar::getPelvisFloatingHeight() const { return -_skeletonModel->getBindExtents().minimum.y; } -void Avatar::setShowDisplayName(bool showDisplayName) { - if (!showNamesAboveHeads) { +void Avatar::updateDisplayNameAlpha(bool showDisplayName) { + if (!(showNamesAboveHeads || showReceiveStats)) { _displayNameAlpha = 0.0f; return; } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index b2b0120b9a..192de146b9 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -150,7 +150,7 @@ public: virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; virtual void setAttachmentData(const QVector& attachmentData) override; - void setShowDisplayName(bool showDisplayName); + void updateDisplayNameAlpha(bool showDisplayName); virtual void setSessionDisplayName(const QString& sessionDisplayName) override { }; // no-op virtual int parseDataFromBuffer(const QByteArray& buffer) override; @@ -368,6 +368,10 @@ private: int _voiceSphereID; AvatarPhysicsCallback _physicsCallback { nullptr }; + + float _displayNameTargetAlpha { 1.0f }; + float _displayNameAlpha { 1.0f }; + }; #endif // hifi_Avatar_h diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 1427ce6359..55c8cc3b65 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -63,8 +63,6 @@ AvatarData::AvatarData() : _keyState(NO_KEY_DOWN), _forceFaceTrackerConnected(false), _headData(NULL), - _displayNameTargetAlpha(1.0f), - _displayNameAlpha(1.0f), _errorLogExpiry(0), _owningAvatarMixer(), _targetVelocity(0.0f) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 545a5f1f8c..f325b6bce7 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -692,9 +692,6 @@ protected: QString _sessionDisplayName { }; QUrl cannonicalSkeletonModelURL(const QUrl& empty) const; - float _displayNameTargetAlpha; - float _displayNameAlpha; - QHash _jointIndices; ///< 1-based, since zero is returned for missing keys QStringList _jointNames; ///< in order of depth-first traversal diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 9d81913078..f44d736e1a 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -131,6 +131,7 @@ public: RenderDetails _details; render::ScenePointer _scene; + int8_t _cameraMode { -1 }; }; #endif // hifi_RenderArgs_h From aa90a6bd028e729060fd1ead9bb99c51a67ebfe8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 21 Apr 2017 11:41:00 -0700 Subject: [PATCH 18/31] use static methods for setting avatar debug options --- interface/src/Menu.cpp | 16 ++++++++-------- interface/src/avatar/Avatar.h | 11 ++++++----- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 97e566309f..1fbf3f9cf2 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -503,14 +503,14 @@ Menu::Menu() { qApp, SLOT(setActiveEyeTracker())); #endif - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AvatarReceiveStats, 0, false, - avatar.get(), SLOT(setShowReceiveStats(bool))); - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowBoundingCollisionShapes, 0, false, - avatar.get(), SLOT(setShowCollisionShapes(bool))); - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowMyLookAtVectors, 0, false, - avatar.get(), SLOT(setShowMyLookAtVectors(bool))); - addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowOtherLookAtVectors, 0, false, - avatar.get(), SLOT(setShowOtherLookAtVectors(bool))); + action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AvatarReceiveStats, 0, false); + connect(action, &QAction::triggered, []{ Avatar::setShowReceiveStats(Menu::getInstance()->isOptionChecked(MenuOption::AvatarReceiveStats)); }); + action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowBoundingCollisionShapes, 0, false); + connect(action, &QAction::triggered, []{ Avatar::setShowCollisionShapes(Menu::getInstance()->isOptionChecked(MenuOption::ShowBoundingCollisionShapes)); }); + action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowMyLookAtVectors, 0, false); + connect(action, &QAction::triggered, []{ Avatar::setShowMyLookAtVectors(Menu::getInstance()->isOptionChecked(MenuOption::ShowMyLookAtVectors)); }); + action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowOtherLookAtVectors, 0, false); + connect(action, &QAction::triggered, []{ Avatar::setShowOtherLookAtVectors(Menu::getInstance()->isOptionChecked(MenuOption::ShowOtherLookAtVectors)); }); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::FixGaze, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawDefaultPose, 0, false, diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 192de146b9..f86bf35bd9 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -68,6 +68,12 @@ class Avatar : public AvatarData { Q_PROPERTY(glm::vec3 skeletonOffset READ getSkeletonOffset WRITE setSkeletonOffset) public: + static void setShowReceiveStats(bool receiveStats); + static void setShowMyLookAtVectors(bool showMine); + static void setShowOtherLookAtVectors(bool showOthers); + static void setShowCollisionShapes(bool render); + static void setShowNamesAboveHeads(bool show); + explicit Avatar(QThread* thread, RigPointer rig = nullptr); ~Avatar(); @@ -251,11 +257,6 @@ public: bool isInPhysicsSimulation() const { return _physicsCallback != nullptr; } public slots: - void setShowReceiveStats(bool receiveStats); - void setShowMyLookAtVectors(bool showMine); - void setShowOtherLookAtVectors(bool showOthers); - void setShowCollisionShapes(bool render); - void setShowNamesAboveHeads(bool show); // FIXME - these should be migrated to use Pose data instead // thread safe, will return last valid palm from cache From 5cf233db3a7e0c16bc97d158f03dc74f053bdb97 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 21 Apr 2017 16:17:53 -0700 Subject: [PATCH 19/31] less labyrinth --- interface/src/Menu.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 1fbf3f9cf2..4ce9085053 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -504,13 +504,13 @@ Menu::Menu() { #endif action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AvatarReceiveStats, 0, false); - connect(action, &QAction::triggered, []{ Avatar::setShowReceiveStats(Menu::getInstance()->isOptionChecked(MenuOption::AvatarReceiveStats)); }); + connect(action, &QAction::triggered, [this]{ Avatar::setShowReceiveStats(isOptionChecked(MenuOption::AvatarReceiveStats)); }); action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowBoundingCollisionShapes, 0, false); - connect(action, &QAction::triggered, []{ Avatar::setShowCollisionShapes(Menu::getInstance()->isOptionChecked(MenuOption::ShowBoundingCollisionShapes)); }); + connect(action, &QAction::triggered, [this]{ Avatar::setShowCollisionShapes(isOptionChecked(MenuOption::ShowBoundingCollisionShapes)); }); action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowMyLookAtVectors, 0, false); - connect(action, &QAction::triggered, []{ Avatar::setShowMyLookAtVectors(Menu::getInstance()->isOptionChecked(MenuOption::ShowMyLookAtVectors)); }); + connect(action, &QAction::triggered, [this]{ Avatar::setShowMyLookAtVectors(isOptionChecked(MenuOption::ShowMyLookAtVectors)); }); action = addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ShowOtherLookAtVectors, 0, false); - connect(action, &QAction::triggered, []{ Avatar::setShowOtherLookAtVectors(Menu::getInstance()->isOptionChecked(MenuOption::ShowOtherLookAtVectors)); }); + connect(action, &QAction::triggered, [this]{ Avatar::setShowOtherLookAtVectors(isOptionChecked(MenuOption::ShowOtherLookAtVectors)); }); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::FixGaze, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::AnimDebugDrawDefaultPose, 0, false, From 32c367b644181ecc3db953f5a8df5914df66fd0c Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 28 Apr 2017 10:18:15 -0700 Subject: [PATCH 20/31] use 'using' rather than 'typedef' --- libraries/physics/src/ObjectMotionState.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 1d258560c3..4230f636b3 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -170,7 +170,7 @@ protected: bool _hasInternalKinematicChanges { false }; }; -typedef QSet SetOfMotionStates; -typedef QVector VectorOfMotionStates; +using SetOfMotionStates = QSet; +using VectorOfMotionStates = QVector; #endif // hifi_ObjectMotionState_h From 994eed7b83a58b60a6a40f3e550b4366e9cd10aa Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 28 Apr 2017 10:18:19 -0700 Subject: [PATCH 21/31] safer delete of AvatarMotionStates --- interface/src/avatar/AvatarManager.cpp | 52 ++++++++++---------------- interface/src/avatar/AvatarManager.h | 3 +- 2 files changed, 22 insertions(+), 33 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index ec22c3403a..04ab1531ba 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -289,16 +289,6 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { avatar->removeFromScene(*avatarItr, scene, transaction); scene->enqueueTransaction(transaction); } - - // delete the motionState - // TODO: use SharedPointer technology to make this happen automagically - assert(!avatar->isInPhysicsSimulation()); - AvatarMotionStateMap::iterator motionStateItr = _motionStates.find(avatar.get()); - if (motionStateItr != _motionStates.end()) { - delete *motionStateItr; - _motionStates.erase(motionStateItr); - } - avatarItr = _avatarsToFade.erase(avatarItr); } else { const bool inView = true; // HACK @@ -312,24 +302,19 @@ AvatarSharedPointer AvatarManager::newSharedAvatar() { return std::make_shared(qApp->thread(), std::make_shared()); } -void AvatarManager::removeAvatarFromPhysicsSimulation(Avatar* avatar) { - assert(avatar); +void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) { + AvatarHashMap::handleRemovedAvatar(removedAvatar, removalReason); + + // remove from physics + auto avatar = std::static_pointer_cast(removedAvatar); avatar->setPhysicsCallback(nullptr); - AvatarMotionStateMap::iterator itr = _motionStates.find(avatar); + AvatarMotionStateMap::iterator itr = _motionStates.find(avatar.get()); if (itr != _motionStates.end()) { AvatarMotionState* motionState = *itr; _motionStatesToAddToPhysics.remove(motionState); _motionStatesToRemoveFromPhysics.push_back(motionState); + _motionStates.erase(itr); } -} - -void AvatarManager::handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason) { - AvatarHashMap::handleRemovedAvatar(removedAvatar, removalReason); - - // removedAvatar is a shared pointer to an AvatarData but we need to get to the derived Avatar - // class in this context so we can call methods that don't exist at the base class. - auto avatar = std::static_pointer_cast(removedAvatar); - removeAvatarFromPhysicsSimulation(avatar.get()); if (removalReason == KillAvatarReason::TheirAvatarEnteredYourBubble) { emit DependencyManager::get()->enteredIgnoreRadius(); @@ -370,14 +355,8 @@ void AvatarManager::clearOtherAvatars() { } void AvatarManager::deleteAllAvatars() { - // delete motionStates - // TODO: use shared_ptr technology to make this work automagically - AvatarMotionStateMap::iterator motionStateItr = _motionStates.begin(); - while (motionStateItr != _motionStates.end()) { - delete *motionStateItr; - ++motionStateItr; - } - _motionStates.clear(); + assert(_motionStates.empty()); // should have called clearOtherAvatars() before getting here + deleteMotionStates(); QReadLocker locker(&_hashLock); AvatarHash::iterator avatarIterator = _avatarHash.begin(); @@ -388,9 +367,18 @@ void AvatarManager::deleteAllAvatars() { } } +void AvatarManager::deleteMotionStates() { + // delete motionstates that were removed from physics last frame + for (auto state : _motionStatesToDelete) { + delete state; + } + _motionStatesToDelete.clear(); +} + void AvatarManager::getObjectsToRemoveFromPhysics(VectorOfMotionStates& result) { - result.clear(); - result.swap(_motionStatesToRemoveFromPhysics); + deleteMotionStates(); + result = _motionStatesToRemoveFromPhysics; + _motionStatesToDelete.swap(_motionStatesToRemoveFromPhysics); } void AvatarManager::getObjectsToAddToPhysics(VectorOfMotionStates& result) { diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index e5b2117beb..c67088a4be 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -92,7 +92,7 @@ private: void simulateAvatarFades(float deltaTime); AvatarSharedPointer newSharedAvatar() override; - void removeAvatarFromPhysicsSimulation(Avatar* avatar); + void deleteMotionStates(); void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason) override; QVector _avatarsToFade; @@ -100,6 +100,7 @@ private: using AvatarMotionStateMap = QMap; AvatarMotionStateMap _motionStates; VectorOfMotionStates _motionStatesToRemoveFromPhysics; + VectorOfMotionStates _motionStatesToDelete; SetOfMotionStates _motionStatesToAddToPhysics; std::shared_ptr _myAvatar; From ac86c134779c5ee356efb1e56aa7e9753cfd0ece Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 1 May 2017 12:18:06 -0700 Subject: [PATCH 22/31] Fix sharing; disable HiFi buttons independently --- scripts/system/html/js/SnapshotReview.js | 32 ++-- scripts/system/snapshot.js | 199 +++++++++++++---------- 2 files changed, 128 insertions(+), 103 deletions(-) diff --git a/scripts/system/html/js/SnapshotReview.js b/scripts/system/html/js/SnapshotReview.js index 53f4d17930..b1a6bb2303 100644 --- a/scripts/system/html/js/SnapshotReview.js +++ b/scripts/system/html/js/SnapshotReview.js @@ -52,7 +52,7 @@ function clearImages() { imageCount = 0; idCounter = 0; } -function addImage(image_data, isGifLoading, isShowingPreviousImages, canSharePreviousImages, hifiShareButtonsDisabled) { +function addImage(image_data, isGifLoading, canShare, isShowingPreviousImages, blastButtonDisabled, hifiButtonDisabled) { if (!image_data.localPath) { return; } @@ -80,22 +80,22 @@ function addImage(image_data, isGifLoading, isShowingPreviousImages, canSharePre if (isGif) { imageContainer.innerHTML += 'GIF'; } - if (!isGifLoading && !isShowingPreviousImages) { + if (!isGifLoading && !isShowingPreviousImages && canShare) { shareForUrl(id); - } else if (isShowingPreviousImages && canSharePreviousImages) { - appendShareBar(id, image_data.story_id, isGif, hifiShareButtonsDisabled) + } else if (isShowingPreviousImages && canShare) { + appendShareBar(id, image_data.story_id, isGif, blastButtonDisabled, hifiButtonDisabled) } } -function appendShareBar(divID, story_id, isGif, hifiShareButtonsDisabled) { +function appendShareBar(divID, story_id, isGif, blastButtonDisabled, hifiButtonDisabled) { var story_url = "https://highfidelity.com/user_stories/" + story_id; var parentDiv = document.getElementById(divID); parentDiv.setAttribute('data-story-id', story_id); - document.getElementById(divID).appendChild(createShareBar(divID, isGif, story_url, hifiShareButtonsDisabled)); + document.getElementById(divID).appendChild(createShareBar(divID, isGif, story_url, blastButtonDisabled, hifiButtonDisabled)); if (divID === "p0") { selectImageToShare(divID, true); } } -function createShareBar(parentID, isGif, shareURL, hifiShareButtonsDisabled) { +function createShareBar(parentID, isGif, shareURL, blastButtonDisabled, hifiButtonDisabled) { var shareBar = document.createElement("div"); shareBar.id = parentID + "shareBar"; shareBar.className = "shareControls"; @@ -109,8 +109,8 @@ function createShareBar(parentID, isGif, shareURL, hifiShareButtonsDisabled) { var twitterButtonID = parentID + "twitterButton"; shareBar.innerHTML += '' + '' + @@ -173,7 +173,6 @@ function blastToConnections(selectedID, isGif) { selectedID = selectedID.id; // `selectedID` is passed as an HTML object to these functions; we just want the ID document.getElementById(selectedID + "blastToConnectionsButton").disabled = true; - document.getElementById(selectedID + "shareWithEveryoneButton").disabled = true; EventBridge.emitWebEvent(JSON.stringify({ type: "snapshot", @@ -185,7 +184,6 @@ function blastToConnections(selectedID, isGif) { function shareWithEveryone(selectedID, isGif) { selectedID = selectedID.id; // `selectedID` is passed as an HTML object to these functions; we just want the ID - document.getElementById(selectedID + "blastToConnectionsButton").disabled = true; document.getElementById(selectedID + "shareWithEveryoneButton").disabled = true; EventBridge.emitWebEvent(JSON.stringify({ @@ -260,7 +258,7 @@ window.onload = function () { var messageOptions = message.options; imageCount = message.image_data.length; message.image_data.forEach(function (element, idx, array) { - addImage(element, true, true, message.canShare, message.image_data[idx].buttonDisabled); + addImage(element, true, message.canShare, true, message.image_data[idx].blastButtonDisabled, message.image_data[idx].hifiButtonDisabled); }); break; case 'addImages': @@ -274,7 +272,7 @@ window.onload = function () { imageCount = message.image_data.length + 1; // "+1" for the GIF that'll finish processing soon message.image_data.unshift({ localPath: messageOptions.loadingGifPath }); message.image_data.forEach(function (element, idx, array) { - addImage(element, idx === 0, false, false); + addImage(element, idx === 0, messageOptions.canShare, false); }); } else { var gifPath = message.image_data[0].localPath; @@ -282,12 +280,14 @@ window.onload = function () { p0img.src = gifPath; paths[0] = gifPath; - shareForUrl("p0"); + if (messageOptions.canShare) { + shareForUrl("p0"); + } } } else { imageCount = message.image_data.length; message.image_data.forEach(function (element, idx, array) { - addImage(element, false, false, false); + addImage(element, false, messageOptions.canShare, false); }); } break; @@ -329,6 +329,6 @@ function testInBrowser(isTestingSetupInstructions) { } else { imageCount = 1; //addImage({ localPath: 'http://lorempixel.com/553/255' }); - addImage({ localPath: 'C:/Users/valef/Desktop/hifi-snap-by-zfox-on-2017-04-26_10-26-53.gif' }, false, true, true, false); + addImage({ localPath: 'C:/Users/valef/Desktop/hifi-snap-by-zfox-on-2017-04-26_10-26-53.gif' }, false, true, true, false, false); } } diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 1cc24b8265..d8635dcb03 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -117,13 +117,15 @@ function onMessage(message) { setting: Settings.getValue("alsoTakeAnimatedSnapshot", true) })); if (Snapshot.getSnapshotsLocation() !== "") { - tablet.emitScriptEvent(JSON.stringify({ - type: "snapshot", - action: "showPreviousImages", - options: snapshotOptions, - image_data: imageData, - canShare: !isDomainOpen(Settings.getValue("previousSnapshotDomainID")) - })); + isDomainOpen(Settings.getValue("previousSnapshotDomainID"), function (canShare) { + tablet.emitScriptEvent(JSON.stringify({ + type: "snapshot", + action: "showPreviousImages", + options: snapshotOptions, + image_data: imageData, + canShare: canShare + })); + }); } else { tablet.emitScriptEvent(JSON.stringify({ type: "snapshot", @@ -131,10 +133,12 @@ function onMessage(message) { })); Settings.setValue("previousStillSnapPath", ""); Settings.setValue("previousStillSnapStoryID", ""); - Settings.setValue("previousStillSnapSharingDisabled", false); + Settings.setValue("previousStillSnapBlastingDisabled", false); + Settings.setValue("previousStillSnapHifiSharingDisabled", false); Settings.setValue("previousAnimatedSnapPath", ""); Settings.setValue("previousAnimatedSnapStoryID", ""); - Settings.setValue("previousAnimatedSnapSharingDisabled", false); + Settings.setValue("previousAnimatedSnapBlastingDisabled", false); + Settings.setValue("previousAnimatedSnapHifiSharingDisabled", false); } break; case 'chooseSnapshotLocation': @@ -180,9 +184,9 @@ function onMessage(message) { isLoggedIn = Account.isLoggedIn(); storyIDsToMaybeDelete.splice(storyIDsToMaybeDelete.indexOf(message.story_id), 1); if (message.isGif) { - Settings.setValue("previousAnimatedSnapSharingDisabled", true); + Settings.setValue("previousAnimatedSnapBlastingDisabled", true); } else { - Settings.setValue("previousStillSnapSharingDisabled", true); + Settings.setValue("previousStillSnapBlastingDisabled", true); } if (isLoggedIn) { @@ -220,9 +224,9 @@ function onMessage(message) { if (error || (response.status !== 'success')) { print("ERROR uploading announcement story: ", error || response.status); if (message.isGif) { - Settings.setValue("previousAnimatedSnapSharingDisabled", false); + Settings.setValue("previousAnimatedSnapBlastingDisabled", false); } else { - Settings.setValue("previousStillSnapSharingDisabled", false); + Settings.setValue("previousStillSnapBlastingDisabled", false); } return; } else { @@ -240,9 +244,9 @@ function onMessage(message) { isLoggedIn = Account.isLoggedIn(); storyIDsToMaybeDelete.splice(storyIDsToMaybeDelete.indexOf(message.story_id), 1); if (message.isGif) { - Settings.setValue("previousAnimatedSnapSharingDisabled", true); + Settings.setValue("previousAnimatedSnapHifiSharingDisabled", true); } else { - Settings.setValue("previousStillSnapSharingDisabled", true); + Settings.setValue("previousStillSnapHifiSharingDisabled", true); } if (isLoggedIn) { @@ -264,9 +268,9 @@ function onMessage(message) { if (error || (response.status !== 'success')) { print("ERROR changing audience: ", error || response.status); if (message.isGif) { - Settings.setValue("previousAnimatedSnapSharingDisabled", false); + Settings.setValue("previousAnimatedSnapHifiSharingDisabled", false); } else { - Settings.setValue("previousStillSnapSharingDisabled", false); + Settings.setValue("previousStillSnapHifiSharingDisabled", false); } return; } else { @@ -301,10 +305,12 @@ function onButtonClicked() { shouldActivateButton = true; var previousStillSnapPath = Settings.getValue("previousStillSnapPath"); var previousStillSnapStoryID = Settings.getValue("previousStillSnapStoryID"); - var previousStillSnapSharingDisabled = Settings.getValue("previousStillSnapSharingDisabled"); + var previousStillSnapBlastingDisabled = Settings.getValue("previousStillSnapBlastingDisabled"); + var previousStillSnapHifiSharingDisabled = Settings.getValue("previousStillSnapHifiSharingDisabled"); var previousAnimatedSnapPath = Settings.getValue("previousAnimatedSnapPath"); var previousAnimatedSnapStoryID = Settings.getValue("previousAnimatedSnapStoryID"); - var previousAnimatedSnapSharingDisabled = Settings.getValue("previousAnimatedSnapSharingDisabled"); + var previousAnimatedSnapBlastingDisabled = Settings.getValue("previousAnimatedSnapBlastingDisabled"); + var previousAnimatedSnapHifiSharingDisabled = Settings.getValue("previousAnimatedSnapHifiSharingDisabled"); snapshotOptions = { containsGif: previousAnimatedSnapPath !== "", processingGif: false, @@ -312,10 +318,20 @@ function onButtonClicked() { } imageData = []; if (previousAnimatedSnapPath !== "") { - imageData.push({ localPath: previousAnimatedSnapPath, story_id: previousAnimatedSnapStoryID, buttonDisabled: previousAnimatedSnapSharingDisabled }); + imageData.push({ + localPath: previousAnimatedSnapPath, + story_id: previousAnimatedSnapStoryID, + blastButtonDisabled: previousAnimatedSnapBlastingDisabled, + hifiButtonDisabled: previousAnimatedSnapHifiSharingDisabled + }); } if (previousStillSnapPath !== "") { - imageData.push({ localPath: previousStillSnapPath, story_id: previousStillSnapStoryID, buttonDisabled: previousStillSnapSharingDisabled }); + imageData.push({ + localPath: previousStillSnapPath, + story_id: previousStillSnapStoryID, + blastButtonDisabled: previousStillSnapBlastingDisabled, + hifiButtonDisabled: previousStillSnapHifiSharingDisabled + }); } tablet.gotoWebScreen(SNAPSHOT_REVIEW_URL); tablet.webEventReceived.connect(onMessage); @@ -355,10 +371,12 @@ function takeSnapshot() { })); Settings.setValue("previousStillSnapPath", ""); Settings.setValue("previousStillSnapStoryID", ""); - Settings.setValue("previousStillSnapSharingDisabled", false); + Settings.setValue("previousStillSnapBlastingDisabled", false); + Settings.setValue("previousStillSnapHifiSharingDisabled", false); Settings.setValue("previousAnimatedSnapPath", ""); Settings.setValue("previousAnimatedSnapStoryID", ""); - Settings.setValue("previousAnimatedSnapSharingDisabled", false); + Settings.setValue("previousAnimatedSnapBlastingDisabled", false); + Settings.setValue("previousAnimatedSnapHifiSharingDisabled", false); // Raising the desktop for the share dialog at end will interact badly with clearOverlayWhenMoving. // Turn it off now, before we start futzing with things (and possibly moving). @@ -403,32 +421,34 @@ function takeSnapshot() { }, FINISH_SOUND_DELAY); } -function isDomainOpen(id) { +function isDomainOpen(id, callback) { print("Checking open status of domain with ID:", id); - if (!id) { - return false; + var status = false; + if (id) { + var options = [ + 'now=' + new Date().toISOString(), + 'include_actions=concurrency', + 'domain_id=' + id.slice(1, -1), + 'restriction=open,hifi' // If we're sharing, we're logged in + // If we're here, protocol matches, and it is online + ]; + var url = METAVERSE_BASE + "/api/v1/user_stories?" + options.join('&'); + + request({ + uri: url, + method: 'GET' + }, function (error, response) { + if (error || (response.status !== 'success')) { + print("ERROR getting open status of domain: ", error || response.status); + } else { + status = response.total_entries ? true : false; + } + print("Domain open status:", status); + callback(status); + }); + } else { + callback(status); } - - var options = [ - 'now=' + new Date().toISOString(), - 'include_actions=concurrency', - 'domain_id=' + id.slice(1, -1), - 'restriction=open,hifi' // If we're sharing, we're logged in - // If we're here, protocol matches, and it is online - ]; - var url = METAVERSE_BASE + "/api/v1/user_stories?" + options.join('&'); - - return request({ - uri: url, - method: 'GET' - }, function (error, response) { - if (error || (response.status !== 'success')) { - print("ERROR getting open status of domain: ", error || response.status); - return false; - } else { - return response.total_entries; - } - }); } function stillSnapshotTaken(pathStillSnapshot, notify) { @@ -448,25 +468,27 @@ function stillSnapshotTaken(pathStillSnapshot, notify) { // during which time the user may have moved. So stash that info in the dialog so that // it records the correct href. (We can also stash in .jpegs, but not .gifs.) // last element in data array tells dialog whether we can share or not - snapshotOptions = { - containsGif: false, - processingGif: false, - canShare: !isDomainOpen(domainId) - }; - imageData = [{ localPath: pathStillSnapshot, href: href }]; Settings.setValue("previousStillSnapPath", pathStillSnapshot); - tablet.emitScriptEvent(JSON.stringify({ - type: "snapshot", - action: "addImages", - options: snapshotOptions, - image_data: imageData - })); - if (clearOverlayWhenMoving) { MyAvatar.setClearOverlayWhenMoving(true); // not until after the share dialog } HMD.openTablet(); + + isDomainOpen(domainId, function (canShare) { + snapshotOptions = { + containsGif: false, + processingGif: false, + canShare: canShare + }; + imageData = [{ localPath: pathStillSnapshot, href: href }]; + tablet.emitScriptEvent(JSON.stringify({ + type: "snapshot", + action: "addImages", + options: snapshotOptions, + image_data: imageData + })); + }); } function processingGifStarted(pathStillSnapshot) { @@ -478,27 +500,28 @@ function processingGifStarted(pathStillSnapshot) { if (resetOverlays) { Menu.setIsOptionChecked("Overlays", true); } - - snapshotOptions = { - containsGif: true, - processingGif: true, - loadingGifPath: Script.resolvePath(Script.resourcesPath() + 'icons/loadingDark.gif'), - canShare: !isDomainOpen(domainId) - }; - imageData = [{ localPath: pathStillSnapshot, href: href }]; Settings.setValue("previousStillSnapPath", pathStillSnapshot); - tablet.emitScriptEvent(JSON.stringify({ - type: "snapshot", - action: "addImages", - options: snapshotOptions, - image_data: imageData - })); - if (clearOverlayWhenMoving) { MyAvatar.setClearOverlayWhenMoving(true); // not until after the share dialog } HMD.openTablet(); + + isDomainOpen(domainId, function (canShare) { + snapshotOptions = { + containsGif: true, + processingGif: true, + loadingGifPath: Script.resolvePath(Script.resourcesPath() + 'icons/loadingDark.gif'), + canShare: canShare + }; + imageData = [{ localPath: pathStillSnapshot, href: href }]; + tablet.emitScriptEvent(JSON.stringify({ + type: "snapshot", + action: "addImages", + options: snapshotOptions, + image_data: imageData + })); + }); } function processingGifCompleted(pathAnimatedSnapshot) { @@ -508,20 +531,22 @@ function processingGifCompleted(pathAnimatedSnapshot) { buttonConnected = true; } - snapshotOptions = { - containsGif: true, - processingGif: false, - canShare: !isDomainOpen(domainId) - } - imageData = [{ localPath: pathAnimatedSnapshot, href: href }]; Settings.setValue("previousAnimatedSnapPath", pathAnimatedSnapshot); - tablet.emitScriptEvent(JSON.stringify({ - type: "snapshot", - action: "addImages", - options: snapshotOptions, - image_data: imageData - })); + isDomainOpen(domainId, function (canShare) { + snapshotOptions = { + containsGif: true, + processingGif: false, + canShare: canShare + }; + imageData = [{ localPath: pathAnimatedSnapshot, href: href }]; + tablet.emitScriptEvent(JSON.stringify({ + type: "snapshot", + action: "addImages", + options: snapshotOptions, + image_data: imageData + })); + }); } function maybeDeleteSnapshotStories() { storyIDsToMaybeDelete.forEach(function (element, idx, array) { From 5b168301bcac0fc6f046806f892e72f3c6c625c4 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 1 May 2017 15:28:50 -0700 Subject: [PATCH 23/31] Update some typefaces; Add margins to pics --- scripts/system/html/css/SnapshotReview.css | 33 ++++++++++------------ scripts/system/html/css/hifi-style.css | 9 +++--- scripts/system/html/js/SnapshotReview.js | 9 +++--- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/scripts/system/html/css/SnapshotReview.css b/scripts/system/html/css/SnapshotReview.css index 12b91d372b..fc0f9b461b 100644 --- a/scripts/system/html/css/SnapshotReview.css +++ b/scripts/system/html/css/SnapshotReview.css @@ -80,6 +80,8 @@ input[type=button].naked:active { #snapshot-images { width: 100%; + display: flex; + justify-content: center; } #snapshot-images img { @@ -119,13 +121,13 @@ input[type=button].naked:active { .shareButtons { display: flex; align-items: center; - margin-left: 30px; + margin-left: 15px; height: 100%; - width: 80%; + width: 75%; } .blastToConnections { text-align: left; - margin-right: 25px; + margin-right: 20px; height: 29px; } .shareWithEveryone { @@ -158,10 +160,11 @@ input[type=button].naked:active { font-family: Raleway-SemiBold; font-size: 14px; color: white; - text-shadow: 2px 2px 3px #000000; height: 100%; margin-right: 10px; - width: 20%; +} +.showShareButtonsButtonDiv > label { + text-shadow: 2px 2px 3px #000000; } .showShareButton { width: 40px; @@ -193,23 +196,17 @@ input[type=button].naked:active { background-color: white; } .showShareButtonDots { - display: flex; - width: 32px; + display: block; + width: 40px; height: 40px; + font-family: HiFi-Glyphs; + font-size: 60px; position: absolute; - top: 5px; - right: 14px; + right: 20px; + bottom: 15px; + color: #00b4ef; pointer-events: none; } -.showShareButtonDots > span { - width: 10px; - height: 10px; - margin: auto; - background-color: #0093C5; - border-radius: 50%; - border-width: 0; - display: inline; -} /* // END styling of share overlay */ diff --git a/scripts/system/html/css/hifi-style.css b/scripts/system/html/css/hifi-style.css index f1ace02eb0..ac34cee09f 100644 --- a/scripts/system/html/css/hifi-style.css +++ b/scripts/system/html/css/hifi-style.css @@ -101,9 +101,11 @@ input[type=radio] { opacity: 0; } input[type=radio] + label{ - display: inline-block; - margin-left: -2em; - line-height: 2em; + display: inline-block; + margin-left: -2em; + line-height: 2em; + font-family: Raleway-SemiBold; + font-size: 14px; } input[type=radio] + label > span{ display: inline-block; @@ -157,7 +159,6 @@ input[type=radio]:active + label > span > span{ border-width: 0px; background-image: linear-gradient(#00B4EF, #1080B8); min-height: 30px; - } .blueButton:hover { background-image: linear-gradient(#00B4EF, #00B4EF); diff --git a/scripts/system/html/js/SnapshotReview.js b/scripts/system/html/js/SnapshotReview.js index b1a6bb2303..475a1e71ff 100644 --- a/scripts/system/html/js/SnapshotReview.js +++ b/scripts/system/html/js/SnapshotReview.js @@ -60,8 +60,9 @@ function addImage(image_data, isGifLoading, canShare, isShowingPreviousImages, b // imageContainer setup var imageContainer = document.createElement("DIV"); imageContainer.id = id; - imageContainer.style.width = "100%"; - imageContainer.style.height = "251px"; + imageContainer.style.width = "95%"; + imageContainer.style.height = "240px"; + imageContainer.style.margin = "5px 0"; imageContainer.style.display = "flex"; imageContainer.style.justifyContent = "center"; imageContainer.style.alignItems = "center"; @@ -118,7 +119,7 @@ function createShareBar(parentID, isGif, shareURL, blastButtonDisabled, hifiButt '' + '' + '
' + - '' + + '' + '
' + ''; @@ -231,7 +232,7 @@ function handleCaptureSetting(setting) { window.onload = function () { // Uncomment the line below to test functionality in a browser. // See definition of "testInBrowser()" to modify tests. - //testInBrowser(true); + testInBrowser(false); openEventBridge(function () { // Set up a handler for receiving the data, and tell the .js we are ready to receive it. EventBridge.scriptEventReceived.connect(function (message) { From d295b5a69d6067ca516945c7dd21b53596c31776 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 1 May 2017 15:31:22 -0700 Subject: [PATCH 24/31] ShareBarHeight-= 5px; Remove test call --- scripts/system/html/css/SnapshotReview.css | 4 ++-- scripts/system/html/js/SnapshotReview.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/html/css/SnapshotReview.css b/scripts/system/html/css/SnapshotReview.css index fc0f9b461b..f8fa21a1f7 100644 --- a/scripts/system/html/css/SnapshotReview.css +++ b/scripts/system/html/css/SnapshotReview.css @@ -110,7 +110,7 @@ input[type=button].naked:active { justify-content: space-between; flex-direction: row; align-items: center; - height: 50px; + height: 45px; line-height: 60px; width: calc(100% - 8px); position: absolute; @@ -203,7 +203,7 @@ input[type=button].naked:active { font-size: 60px; position: absolute; right: 20px; - bottom: 15px; + bottom: 12px; color: #00b4ef; pointer-events: none; } diff --git a/scripts/system/html/js/SnapshotReview.js b/scripts/system/html/js/SnapshotReview.js index 475a1e71ff..ad7578b4c0 100644 --- a/scripts/system/html/js/SnapshotReview.js +++ b/scripts/system/html/js/SnapshotReview.js @@ -232,7 +232,7 @@ function handleCaptureSetting(setting) { window.onload = function () { // Uncomment the line below to test functionality in a browser. // See definition of "testInBrowser()" to modify tests. - testInBrowser(false); + //testInBrowser(false); openEventBridge(function () { // Set up a handler for receiving the data, and tell the .js we are ready to receive it. EventBridge.scriptEventReceived.connect(function (message) { From 0ead9e5a2468c0877dd5a8eb670ca7ef619c78d0 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 1 May 2017 16:17:38 -0700 Subject: [PATCH 25/31] Visual fixes; Select only 1 image at a time --- scripts/system/html/css/SnapshotReview.css | 1 + scripts/system/html/js/SnapshotReview.js | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/scripts/system/html/css/SnapshotReview.css b/scripts/system/html/css/SnapshotReview.css index f8fa21a1f7..ccc9386d13 100644 --- a/scripts/system/html/css/SnapshotReview.css +++ b/scripts/system/html/css/SnapshotReview.css @@ -82,6 +82,7 @@ input[type=button].naked:active { width: 100%; display: flex; justify-content: center; + flex-direction: column; } #snapshot-images img { diff --git a/scripts/system/html/js/SnapshotReview.js b/scripts/system/html/js/SnapshotReview.js index ad7578b4c0..b7380e83c9 100644 --- a/scripts/system/html/js/SnapshotReview.js +++ b/scripts/system/html/js/SnapshotReview.js @@ -62,7 +62,7 @@ function addImage(image_data, isGifLoading, canShare, isShowingPreviousImages, b imageContainer.id = id; imageContainer.style.width = "95%"; imageContainer.style.height = "240px"; - imageContainer.style.margin = "5px 0"; + imageContainer.style.margin = "5px auto"; imageContainer.style.display = "flex"; imageContainer.style.justifyContent = "center"; imageContainer.style.alignItems = "center"; @@ -150,6 +150,15 @@ function selectImageToShare(selectedID, isSelected) { shareBar.style.backgroundColor = "rgba(0, 0, 0, 0.5)"; shareButtonsDiv.style.visibility = "visible"; + + var containers = document.getElementsByClassName("shareControls"); + var parentID; + for (var i = 0; i < containers.length; ++i) { + parentID = containers[i].id.slice(0, 2); + if (parentID !== selectedID) { + selectImageToShare(parentID, false); + } + } } else { showShareButtonsButton.onclick = function () { selectImageToShare(selectedID, true) }; showShareButtonsButton.classList.remove("active"); @@ -232,7 +241,7 @@ function handleCaptureSetting(setting) { window.onload = function () { // Uncomment the line below to test functionality in a browser. // See definition of "testInBrowser()" to modify tests. - //testInBrowser(false); + testInBrowser(false); openEventBridge(function () { // Set up a handler for receiving the data, and tell the .js we are ready to receive it. EventBridge.scriptEventReceived.connect(function (message) { @@ -330,6 +339,7 @@ function testInBrowser(isTestingSetupInstructions) { } else { imageCount = 1; //addImage({ localPath: 'http://lorempixel.com/553/255' }); - addImage({ localPath: 'C:/Users/valef/Desktop/hifi-snap-by-zfox-on-2017-04-26_10-26-53.gif' }, false, true, true, false, false); + addImage({ localPath: 'C:/Users/valef/Desktop/hifi-snap-by-zfox-on-2017-05-01_15-48-15.gif' }, false, true, true, false, false); + addImage({ localPath: 'C:/Users/valef/Desktop/hifi-snap-by-zfox-on-2017-05-01_15-48-15.jpg' }, false, true, true, false, false); } } From a754c4d6cc2639e36206a52f956ab262568fe991 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 1 May 2017 16:40:47 -0700 Subject: [PATCH 26/31] Still image on top --- scripts/system/html/js/SnapshotReview.js | 18 +++++++++--------- scripts/system/snapshot.js | 16 ++++++++-------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/scripts/system/html/js/SnapshotReview.js b/scripts/system/html/js/SnapshotReview.js index b7380e83c9..ed290e9756 100644 --- a/scripts/system/html/js/SnapshotReview.js +++ b/scripts/system/html/js/SnapshotReview.js @@ -83,7 +83,7 @@ function addImage(image_data, isGifLoading, canShare, isShowingPreviousImages, b } if (!isGifLoading && !isShowingPreviousImages && canShare) { shareForUrl(id); - } else if (isShowingPreviousImages && canShare) { + } else if (isShowingPreviousImages && canShare && image_data.story_id) { appendShareBar(id, image_data.story_id, isGif, blastButtonDisabled, hifiButtonDisabled) } } @@ -241,7 +241,7 @@ function handleCaptureSetting(setting) { window.onload = function () { // Uncomment the line below to test functionality in a browser. // See definition of "testInBrowser()" to modify tests. - testInBrowser(false); + //testInBrowser(false); openEventBridge(function () { // Set up a handler for receiving the data, and tell the .js we are ready to receive it. EventBridge.scriptEventReceived.connect(function (message) { @@ -280,18 +280,18 @@ window.onload = function () { if (messageOptions.containsGif) { if (messageOptions.processingGif) { imageCount = message.image_data.length + 1; // "+1" for the GIF that'll finish processing soon - message.image_data.unshift({ localPath: messageOptions.loadingGifPath }); + message.image_data.push({ localPath: messageOptions.loadingGifPath }); message.image_data.forEach(function (element, idx, array) { - addImage(element, idx === 0, messageOptions.canShare, false); + addImage(element, idx === 1, idx === 0 && messageOptions.canShare, false); }); } else { var gifPath = message.image_data[0].localPath; - var p0img = document.getElementById('p0img'); - p0img.src = gifPath; + var p1img = document.getElementById('p1img'); + p1img.src = gifPath; - paths[0] = gifPath; + paths[1] = gifPath; if (messageOptions.canShare) { - shareForUrl("p0"); + shareForUrl("p1"); } } } else { @@ -306,7 +306,7 @@ window.onload = function () { break; case 'snapshotUploadComplete': var isGif = message.image_url.split('.').pop().toLowerCase() === "gif"; - appendShareBar(isGif || imageCount === 1 ? "p0" : "p1", message.story_id, isGif); + appendShareBar(isGif ? "p1" : "p0", message.story_id, isGif); break; default: console.log("Unknown message action received in SnapshotReview.js."); diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index d8635dcb03..b2d39484b0 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -317,14 +317,6 @@ function onButtonClicked() { shouldUpload: false } imageData = []; - if (previousAnimatedSnapPath !== "") { - imageData.push({ - localPath: previousAnimatedSnapPath, - story_id: previousAnimatedSnapStoryID, - blastButtonDisabled: previousAnimatedSnapBlastingDisabled, - hifiButtonDisabled: previousAnimatedSnapHifiSharingDisabled - }); - } if (previousStillSnapPath !== "") { imageData.push({ localPath: previousStillSnapPath, @@ -333,6 +325,14 @@ function onButtonClicked() { hifiButtonDisabled: previousStillSnapHifiSharingDisabled }); } + if (previousAnimatedSnapPath !== "") { + imageData.push({ + localPath: previousAnimatedSnapPath, + story_id: previousAnimatedSnapStoryID, + blastButtonDisabled: previousAnimatedSnapBlastingDisabled, + hifiButtonDisabled: previousAnimatedSnapHifiSharingDisabled + }); + } tablet.gotoWebScreen(SNAPSHOT_REVIEW_URL); tablet.webEventReceived.connect(onMessage); HMD.openTablet(); From f453df36cf22974202a6831a20e136e7b516c6d2 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 1 May 2017 16:53:44 -0700 Subject: [PATCH 27/31] Prevent cursor appearance in snaps --- scripts/system/snapshot.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index b2d39484b0..94630d3a72 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -395,6 +395,7 @@ function takeSnapshot() { resetOverlays = Menu.isOptionChecked("Overlays"); // For completeness. Certainly true if the button is visible to be clicked. reticleVisible = Reticle.visible; Reticle.visible = false; + Reticle.allowMouseCapture = false; var includeAnimated = Settings.getValue("alsoTakeAnimatedSnapshot", true); if (includeAnimated) { @@ -454,6 +455,7 @@ function isDomainOpen(id, callback) { function stillSnapshotTaken(pathStillSnapshot, notify) { // show hud Reticle.visible = reticleVisible; + Reticle.allowMouseCapture = true; // show overlays if they were on if (resetOverlays) { Menu.setIsOptionChecked("Overlays", true); @@ -496,6 +498,7 @@ function processingGifStarted(pathStillSnapshot) { Window.processingGifCompleted.connect(processingGifCompleted); // show hud Reticle.visible = reticleVisible; + Reticle.allowMouseCapture = true; // show overlays if they were on if (resetOverlays) { Menu.setIsOptionChecked("Overlays", true); From c9e0679b70b6d07fd456f33b575cf1625b0e2ec7 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 2 May 2017 10:55:57 -0700 Subject: [PATCH 28/31] Subscribe to changes to snapshotsLocation setter for better UX --- interface/src/ui/PreferencesDialog.cpp | 2 +- interface/src/ui/Snapshot.h | 3 +++ scripts/system/snapshot.js | 10 ++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index bf4be7fd17..e2e22fe366 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -111,7 +111,7 @@ void setupPreferences() { static const QString SNAPSHOTS { "Snapshots" }; { auto getter = []()->QString { return Snapshot::snapshotsLocation.get(); }; - auto setter = [](const QString& value) { Snapshot::snapshotsLocation.set(value); }; + auto setter = [](const QString& value) { Snapshot::snapshotsLocation.set(value); emit DependencyManager::get()->snapshotLocationSet(value); }; auto preference = new BrowsePreference(SNAPSHOTS, "Put my snapshots here", getter, setter); preferences->addPreference(preference); } diff --git a/interface/src/ui/Snapshot.h b/interface/src/ui/Snapshot.h index 93ffbbc7bb..1246e1d004 100644 --- a/interface/src/ui/Snapshot.h +++ b/interface/src/ui/Snapshot.h @@ -44,6 +44,9 @@ public: static Setting::Handle snapshotsLocation; static void uploadSnapshot(const QString& filename, const QUrl& href = QUrl("")); +signals: + void snapshotLocationSet(const QString& value); + public slots: Q_INVOKABLE QString getSnapshotsLocation(); Q_INVOKABLE void setSnapshotsLocation(const QString& location); diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 94630d3a72..d0d1bd96f5 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -582,12 +582,21 @@ function onUsernameChanged() { shareAfterLogin = false; } } +function snapshotLocationSet(location) { + if (location !== "") { + tablet.emitScriptEvent(JSON.stringify({ + type: "snapshot", + action: "snapshotLocationChosen" + })); + } +} button.clicked.connect(onButtonClicked); buttonConnected = true; Window.snapshotShared.connect(snapshotUploaded); tablet.screenChanged.connect(onTabletScreenChanged); Account.usernameChanged.connect(onUsernameChanged); +Snapshot.snapshotLocationSet.connect(snapshotLocationSet); Script.scriptEnding.connect(function () { if (buttonConnected) { button.clicked.disconnect(onButtonClicked); @@ -598,6 +607,7 @@ Script.scriptEnding.connect(function () { } Window.snapshotShared.disconnect(snapshotUploaded); tablet.screenChanged.disconnect(onTabletScreenChanged); + Snapshot.snapshotLocationSet.disconnect(snapshotLocationSet); }); }()); // END LOCAL_SCOPE From 3a36feacad422a1f7d9238a68acd1d2aa49c171c Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 2 May 2017 11:29:51 -0700 Subject: [PATCH 29/31] On touch, grip is a trigger, not a button, so it can have lots of callbacks with slightly different values that we ignore. In that case, don't update hand/joint. --- scripts/system/makeUserConnection.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index 47082e882f..33d6b363ab 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -519,11 +519,9 @@ function updateTriggers(value, fromKeyboard, hand) { if (currentHand && hand !== currentHand) { - debug("currentHand", currentHand, "ignoring messages from", hand); + debug("currentHand", currentHand, "ignoring messages from", hand); // this can be a lot of spam on Touch. Should guard that someday. return; } - currentHand = hand; - currentHandJointIndex = getIdealHandJointIndex(MyAvatar, handToString(currentHand)); // Always, in case of changed skeleton. // ok now, we are either initiating or quitting... var isGripping = value > GRIP_MIN; if (isGripping) { @@ -531,6 +529,8 @@ if (state !== STATES.INACTIVE) { return; } + currentHand = hand; + currentHandJointIndex = getIdealHandJointIndex(MyAvatar, handToString(currentHand)); // Always, in case of changed skeleton. startHandshake(fromKeyboard); } else { // TODO: should we end handshake even when inactive? Ponder From a22be93d69a113fc26ca9aeafc2c4d1035aa060b Mon Sep 17 00:00:00 2001 From: Anshuman Dewangan Date: Tue, 2 May 2017 12:15:06 -0700 Subject: [PATCH 30/31] Move old recorder.js script to script-archive --- .../developer/utilities/record/recorder.js | 360 ------------------ 1 file changed, 360 deletions(-) delete mode 100644 scripts/developer/utilities/record/recorder.js diff --git a/scripts/developer/utilities/record/recorder.js b/scripts/developer/utilities/record/recorder.js deleted file mode 100644 index bda4edc125..0000000000 --- a/scripts/developer/utilities/record/recorder.js +++ /dev/null @@ -1,360 +0,0 @@ -// -// Recorder.js -// examples -// -// Created by Clément Brisset on 8/20/14. -// Copyright 2014 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 -// - -/* globals HIFI_PUBLIC_BUCKET:true, Tool, ToolBar */ - -HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; -Script.include("/~/system/libraries/toolBars.js"); - -var recordingFile = "recording.hfr"; - -function setDefaultPlayerOptions() { - Recording.setPlayFromCurrentLocation(true); - Recording.setPlayerUseDisplayName(false); - Recording.setPlayerUseAttachments(false); - Recording.setPlayerUseHeadModel(false); - Recording.setPlayerUseSkeletonModel(true); -} - -var windowDimensions = Controller.getViewportDimensions(); -var TOOL_ICON_URL = HIFI_PUBLIC_BUCKET + "images/tools/"; -var ALPHA_ON = 1.0; -var ALPHA_OFF = 0.7; -var COLOR_ON = { red: 128, green: 0, blue: 0 }; -var COLOR_OFF = { red: 128, green: 128, blue: 128 }; -var COLOR_TOOL_BAR = { red: 0, green: 0, blue: 0 }; - -var toolBar = null; -var recordIcon; -var playIcon; -var playLoopIcon; -var saveIcon; -var loadIcon; -var spacing; -var timerOffset; -var timer = null; -var slider = null; - -setupToolBar(); -setupTimer(); - -var watchStop = false; - -function setupToolBar() { - if (toolBar !== null) { - print("Multiple calls to Recorder.js:setupToolBar()"); - return; - } - Tool.IMAGE_HEIGHT /= 2; - Tool.IMAGE_WIDTH /= 2; - - toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); - - toolBar.onMove = onToolbarMove; - - toolBar.setBack(COLOR_TOOL_BAR, ALPHA_OFF); - - recordIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "recording-record.svg", - subImage: { x: 0, y: 0, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - x: 0, y: 0, - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT, - alpha: Recording.isPlaying() ? ALPHA_OFF : ALPHA_ON, - visible: true - }, true, !Recording.isRecording()); - - var playLoopWidthFactor = 1.65; - playIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "play-pause.svg", - width: playLoopWidthFactor * Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT, - alpha: (Recording.isRecording() || Recording.playerLength() === 0) ? ALPHA_OFF : ALPHA_ON, - visible: true - }, false); - - playLoopIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "play-and-loop.svg", - subImage: { x: 0, y: 0, width: playLoopWidthFactor * Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, - width: playLoopWidthFactor * Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT, - alpha: (Recording.isRecording() || Recording.playerLength() === 0) ? ALPHA_OFF : ALPHA_ON, - visible: true - }, false); - - timerOffset = toolBar.width + ToolBar.SPACING; - spacing = toolBar.addSpacing(0); - - saveIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "recording-save.svg", - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT, - alpha: (Recording.isRecording() || Recording.isPlaying() || Recording.playerLength() === 0) ? ALPHA_OFF : ALPHA_ON, - visible: true - }, false); - - loadIcon = toolBar.addTool({ - imageURL: TOOL_ICON_URL + "recording-upload.svg", - width: Tool.IMAGE_WIDTH, - height: Tool.IMAGE_HEIGHT, - alpha: (Recording.isRecording() || Recording.isPlaying()) ? ALPHA_OFF : ALPHA_ON, - visible: true - }, false); -} - -function setupTimer() { - timer = Overlays.addOverlay("text", { - font: { size: 15 }, - text: (0.00).toFixed(3), - backgroundColor: COLOR_OFF, - x: 0, y: 0, - width: 200, height: 25, - leftMargin: 5, topMargin: 3, - alpha: 1.0, backgroundAlpha: 1.0, - visible: true - }); - - slider = { x: 0, y: 0, - w: 200, h: 20, - pos: 0.0 // 0.0 <= pos <= 1.0 - }; - slider.background = Overlays.addOverlay("text", { - text: "", - backgroundColor: { red: 128, green: 128, blue: 128 }, - x: slider.x, y: slider.y, - width: slider.w, - height: slider.h, - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true - }); - slider.foreground = Overlays.addOverlay("text", { - text: "", - backgroundColor: { red: 200, green: 200, blue: 200 }, - x: slider.x, y: slider.y, - width: slider.pos * slider.w, - height: slider.h, - alpha: 1.0, - backgroundAlpha: 1.0, - visible: true - }); -} - -function onToolbarMove(newX, newY, deltaX, deltaY) { - Overlays.editOverlay(timer, { - x: newX + timerOffset - ToolBar.SPACING, - y: newY - }); - - slider.x = newX - ToolBar.SPACING; - slider.y = newY - slider.h - ToolBar.SPACING; - - Overlays.editOverlay(slider.background, { - x: slider.x, - y: slider.y - }); - Overlays.editOverlay(slider.foreground, { - x: slider.x, - y: slider.y - }); -} - -function updateTimer() { - var text = ""; - if (Recording.isRecording()) { - text = formatTime(Recording.recorderElapsed()); - } else { - text = formatTime(Recording.playerElapsed()) + " / " + formatTime(Recording.playerLength()); - } - - var timerWidth = text.length * 8 + ((Recording.isRecording()) ? 15 : 0); - - Overlays.editOverlay(timer, { - text: text, - width: timerWidth - }); - toolBar.changeSpacing(timerWidth + ToolBar.SPACING, spacing); - - if (Recording.isRecording()) { - slider.pos = 1.0; - } else if (Recording.playerLength() > 0) { - slider.pos = Recording.playerElapsed() / Recording.playerLength(); - } - - Overlays.editOverlay(slider.foreground, { - width: slider.pos * slider.w - }); -} - -function formatTime(time) { - var MIN_PER_HOUR = 60; - var SEC_PER_MIN = 60; - var MSEC_DIGITS = 3; - - var hours = Math.floor(time / (SEC_PER_MIN * MIN_PER_HOUR)); - time -= hours * (SEC_PER_MIN * MIN_PER_HOUR); - - var minutes = Math.floor(time / (SEC_PER_MIN)); - time -= minutes * (SEC_PER_MIN); - - var seconds = time; - - var text = ""; - text += (hours > 0) ? hours + ":" : ""; - text += (minutes > 0) ? ((minutes < 10 && text !== "") ? "0" : "") + minutes + ":" : ""; - text += ((seconds < 10 && text !== "") ? "0" : "") + seconds.toFixed(MSEC_DIGITS); - return text; -} - -function moveUI() { - var relative = { x: 70, y: 40 }; - toolBar.move(relative.x, windowDimensions.y - relative.y); -} - -function mousePressEvent(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (recordIcon === toolBar.clicked(clickedOverlay, false) && !Recording.isPlaying()) { - if (!Recording.isRecording()) { - Recording.startRecording(); - toolBar.selectTool(recordIcon, false); - toolBar.setAlpha(ALPHA_OFF, playIcon); - toolBar.setAlpha(ALPHA_OFF, playLoopIcon); - toolBar.setAlpha(ALPHA_OFF, saveIcon); - toolBar.setAlpha(ALPHA_OFF, loadIcon); - } else { - Recording.stopRecording(); - toolBar.selectTool(recordIcon, true); - setDefaultPlayerOptions(); - // Plays the recording at the same spot as you recorded it - Recording.setPlayFromCurrentLocation(false); - Recording.setPlayerTime(0); - Recording.loadLastRecording(); - toolBar.setAlpha(ALPHA_ON, playIcon); - toolBar.setAlpha(ALPHA_ON, playLoopIcon); - toolBar.setAlpha(ALPHA_ON, saveIcon); - toolBar.setAlpha(ALPHA_ON, loadIcon); - } - } else if (playIcon === toolBar.clicked(clickedOverlay) && !Recording.isRecording()) { - if (Recording.isPlaying()) { - Recording.pausePlayer(); - toolBar.setAlpha(ALPHA_ON, recordIcon); - toolBar.setAlpha(ALPHA_ON, saveIcon); - toolBar.setAlpha(ALPHA_ON, loadIcon); - } else if (Recording.playerLength() > 0) { - Recording.setPlayerLoop(false); - Recording.startPlaying(); - toolBar.setAlpha(ALPHA_OFF, recordIcon); - toolBar.setAlpha(ALPHA_OFF, saveIcon); - toolBar.setAlpha(ALPHA_OFF, loadIcon); - watchStop = true; - } - } else if (playLoopIcon === toolBar.clicked(clickedOverlay) && !Recording.isRecording()) { - if (Recording.isPlaying()) { - Recording.pausePlayer(); - toolBar.setAlpha(ALPHA_ON, recordIcon); - toolBar.setAlpha(ALPHA_ON, saveIcon); - toolBar.setAlpha(ALPHA_ON, loadIcon); - } else if (Recording.playerLength() > 0) { - Recording.setPlayerLoop(true); - Recording.startPlaying(); - toolBar.setAlpha(ALPHA_OFF, recordIcon); - toolBar.setAlpha(ALPHA_OFF, saveIcon); - toolBar.setAlpha(ALPHA_OFF, loadIcon); - } - } else if (saveIcon === toolBar.clicked(clickedOverlay)) { - if (!Recording.isRecording() && !Recording.isPlaying() && Recording.playerLength() !== 0) { - recordingFile = Window.save("Save recording to file", ".", "Recordings (*.hfr)"); - if (!(recordingFile === "null" || recordingFile === null || recordingFile === "")) { - Recording.saveRecording(recordingFile); - } - } - } else if (loadIcon === toolBar.clicked(clickedOverlay)) { - if (!Recording.isRecording() && !Recording.isPlaying()) { - recordingFile = Window.browse("Load recording from file", ".", "Recordings (*.hfr *.rec *.HFR *.REC)"); - if (!(recordingFile === "null" || recordingFile === null || recordingFile === "")) { - Recording.loadRecording(recordingFile, function(success) { - if (success) { - setDefaultPlayerOptions(); - } else { - print("Failed to load recording from " + recordingFile); - } - }); - } - if (Recording.playerLength() > 0) { - toolBar.setAlpha(ALPHA_ON, playIcon); - toolBar.setAlpha(ALPHA_ON, playLoopIcon); - toolBar.setAlpha(ALPHA_ON, saveIcon); - } - } - } else if (Recording.playerLength() > 0 && - slider.x < event.x && event.x < slider.x + slider.w && - slider.y < event.y && event.y < slider.y + slider.h) { - isSliding = true; - slider.pos = (event.x - slider.x) / slider.w; - Recording.setPlayerTime(slider.pos * Recording.playerLength()); - } -} -var isSliding = false; - -function mouseMoveEvent(event) { - if (isSliding) { - slider.pos = (event.x - slider.x) / slider.w; - if (slider.pos < 0.0 || slider.pos > 1.0) { - Recording.stopPlaying(); - slider.pos = 0.0; - } - Recording.setPlayerTime(slider.pos * Recording.playerLength()); - } -} - -function mouseReleaseEvent(event) { - isSliding = false; -} - -function update() { - var newDimensions = Controller.getViewportDimensions(); - if (windowDimensions.x !== newDimensions.x || windowDimensions.y !== newDimensions.y) { - windowDimensions = newDimensions; - moveUI(); - } - - updateTimer(); - - if (watchStop && !Recording.isPlaying()) { - watchStop = false; - toolBar.setAlpha(ALPHA_ON, recordIcon); - toolBar.setAlpha(ALPHA_ON, saveIcon); - toolBar.setAlpha(ALPHA_ON, loadIcon); - } -} - -function scriptEnding() { - if (Recording.isRecording()) { - Recording.stopRecording(); - } - if (Recording.isPlaying()) { - Recording.stopPlaying(); - } - toolBar.cleanup(); - Overlays.deleteOverlay(timer); - Overlays.deleteOverlay(slider.background); - Overlays.deleteOverlay(slider.foreground); -} - -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); -Script.update.connect(update); -Script.scriptEnding.connect(scriptEnding); - -// Should be called last to put everything into position -moveUI(); From 0d1d6924e86deada4651c9c6b85a9e742e08e269 Mon Sep 17 00:00:00 2001 From: Anshuman Dewangan Date: Tue, 2 May 2017 12:20:05 -0700 Subject: [PATCH 31/31] Adding to script-archive --- script-archive/recorder.js | 360 +++++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 script-archive/recorder.js diff --git a/script-archive/recorder.js b/script-archive/recorder.js new file mode 100644 index 0000000000..bda4edc125 --- /dev/null +++ b/script-archive/recorder.js @@ -0,0 +1,360 @@ +// +// Recorder.js +// examples +// +// Created by Clément Brisset on 8/20/14. +// Copyright 2014 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 +// + +/* globals HIFI_PUBLIC_BUCKET:true, Tool, ToolBar */ + +HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; +Script.include("/~/system/libraries/toolBars.js"); + +var recordingFile = "recording.hfr"; + +function setDefaultPlayerOptions() { + Recording.setPlayFromCurrentLocation(true); + Recording.setPlayerUseDisplayName(false); + Recording.setPlayerUseAttachments(false); + Recording.setPlayerUseHeadModel(false); + Recording.setPlayerUseSkeletonModel(true); +} + +var windowDimensions = Controller.getViewportDimensions(); +var TOOL_ICON_URL = HIFI_PUBLIC_BUCKET + "images/tools/"; +var ALPHA_ON = 1.0; +var ALPHA_OFF = 0.7; +var COLOR_ON = { red: 128, green: 0, blue: 0 }; +var COLOR_OFF = { red: 128, green: 128, blue: 128 }; +var COLOR_TOOL_BAR = { red: 0, green: 0, blue: 0 }; + +var toolBar = null; +var recordIcon; +var playIcon; +var playLoopIcon; +var saveIcon; +var loadIcon; +var spacing; +var timerOffset; +var timer = null; +var slider = null; + +setupToolBar(); +setupTimer(); + +var watchStop = false; + +function setupToolBar() { + if (toolBar !== null) { + print("Multiple calls to Recorder.js:setupToolBar()"); + return; + } + Tool.IMAGE_HEIGHT /= 2; + Tool.IMAGE_WIDTH /= 2; + + toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); + + toolBar.onMove = onToolbarMove; + + toolBar.setBack(COLOR_TOOL_BAR, ALPHA_OFF); + + recordIcon = toolBar.addTool({ + imageURL: TOOL_ICON_URL + "recording-record.svg", + subImage: { x: 0, y: 0, width: Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + x: 0, y: 0, + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: Recording.isPlaying() ? ALPHA_OFF : ALPHA_ON, + visible: true + }, true, !Recording.isRecording()); + + var playLoopWidthFactor = 1.65; + playIcon = toolBar.addTool({ + imageURL: TOOL_ICON_URL + "play-pause.svg", + width: playLoopWidthFactor * Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: (Recording.isRecording() || Recording.playerLength() === 0) ? ALPHA_OFF : ALPHA_ON, + visible: true + }, false); + + playLoopIcon = toolBar.addTool({ + imageURL: TOOL_ICON_URL + "play-and-loop.svg", + subImage: { x: 0, y: 0, width: playLoopWidthFactor * Tool.IMAGE_WIDTH, height: Tool.IMAGE_HEIGHT }, + width: playLoopWidthFactor * Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: (Recording.isRecording() || Recording.playerLength() === 0) ? ALPHA_OFF : ALPHA_ON, + visible: true + }, false); + + timerOffset = toolBar.width + ToolBar.SPACING; + spacing = toolBar.addSpacing(0); + + saveIcon = toolBar.addTool({ + imageURL: TOOL_ICON_URL + "recording-save.svg", + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: (Recording.isRecording() || Recording.isPlaying() || Recording.playerLength() === 0) ? ALPHA_OFF : ALPHA_ON, + visible: true + }, false); + + loadIcon = toolBar.addTool({ + imageURL: TOOL_ICON_URL + "recording-upload.svg", + width: Tool.IMAGE_WIDTH, + height: Tool.IMAGE_HEIGHT, + alpha: (Recording.isRecording() || Recording.isPlaying()) ? ALPHA_OFF : ALPHA_ON, + visible: true + }, false); +} + +function setupTimer() { + timer = Overlays.addOverlay("text", { + font: { size: 15 }, + text: (0.00).toFixed(3), + backgroundColor: COLOR_OFF, + x: 0, y: 0, + width: 200, height: 25, + leftMargin: 5, topMargin: 3, + alpha: 1.0, backgroundAlpha: 1.0, + visible: true + }); + + slider = { x: 0, y: 0, + w: 200, h: 20, + pos: 0.0 // 0.0 <= pos <= 1.0 + }; + slider.background = Overlays.addOverlay("text", { + text: "", + backgroundColor: { red: 128, green: 128, blue: 128 }, + x: slider.x, y: slider.y, + width: slider.w, + height: slider.h, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); + slider.foreground = Overlays.addOverlay("text", { + text: "", + backgroundColor: { red: 200, green: 200, blue: 200 }, + x: slider.x, y: slider.y, + width: slider.pos * slider.w, + height: slider.h, + alpha: 1.0, + backgroundAlpha: 1.0, + visible: true + }); +} + +function onToolbarMove(newX, newY, deltaX, deltaY) { + Overlays.editOverlay(timer, { + x: newX + timerOffset - ToolBar.SPACING, + y: newY + }); + + slider.x = newX - ToolBar.SPACING; + slider.y = newY - slider.h - ToolBar.SPACING; + + Overlays.editOverlay(slider.background, { + x: slider.x, + y: slider.y + }); + Overlays.editOverlay(slider.foreground, { + x: slider.x, + y: slider.y + }); +} + +function updateTimer() { + var text = ""; + if (Recording.isRecording()) { + text = formatTime(Recording.recorderElapsed()); + } else { + text = formatTime(Recording.playerElapsed()) + " / " + formatTime(Recording.playerLength()); + } + + var timerWidth = text.length * 8 + ((Recording.isRecording()) ? 15 : 0); + + Overlays.editOverlay(timer, { + text: text, + width: timerWidth + }); + toolBar.changeSpacing(timerWidth + ToolBar.SPACING, spacing); + + if (Recording.isRecording()) { + slider.pos = 1.0; + } else if (Recording.playerLength() > 0) { + slider.pos = Recording.playerElapsed() / Recording.playerLength(); + } + + Overlays.editOverlay(slider.foreground, { + width: slider.pos * slider.w + }); +} + +function formatTime(time) { + var MIN_PER_HOUR = 60; + var SEC_PER_MIN = 60; + var MSEC_DIGITS = 3; + + var hours = Math.floor(time / (SEC_PER_MIN * MIN_PER_HOUR)); + time -= hours * (SEC_PER_MIN * MIN_PER_HOUR); + + var minutes = Math.floor(time / (SEC_PER_MIN)); + time -= minutes * (SEC_PER_MIN); + + var seconds = time; + + var text = ""; + text += (hours > 0) ? hours + ":" : ""; + text += (minutes > 0) ? ((minutes < 10 && text !== "") ? "0" : "") + minutes + ":" : ""; + text += ((seconds < 10 && text !== "") ? "0" : "") + seconds.toFixed(MSEC_DIGITS); + return text; +} + +function moveUI() { + var relative = { x: 70, y: 40 }; + toolBar.move(relative.x, windowDimensions.y - relative.y); +} + +function mousePressEvent(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); + + if (recordIcon === toolBar.clicked(clickedOverlay, false) && !Recording.isPlaying()) { + if (!Recording.isRecording()) { + Recording.startRecording(); + toolBar.selectTool(recordIcon, false); + toolBar.setAlpha(ALPHA_OFF, playIcon); + toolBar.setAlpha(ALPHA_OFF, playLoopIcon); + toolBar.setAlpha(ALPHA_OFF, saveIcon); + toolBar.setAlpha(ALPHA_OFF, loadIcon); + } else { + Recording.stopRecording(); + toolBar.selectTool(recordIcon, true); + setDefaultPlayerOptions(); + // Plays the recording at the same spot as you recorded it + Recording.setPlayFromCurrentLocation(false); + Recording.setPlayerTime(0); + Recording.loadLastRecording(); + toolBar.setAlpha(ALPHA_ON, playIcon); + toolBar.setAlpha(ALPHA_ON, playLoopIcon); + toolBar.setAlpha(ALPHA_ON, saveIcon); + toolBar.setAlpha(ALPHA_ON, loadIcon); + } + } else if (playIcon === toolBar.clicked(clickedOverlay) && !Recording.isRecording()) { + if (Recording.isPlaying()) { + Recording.pausePlayer(); + toolBar.setAlpha(ALPHA_ON, recordIcon); + toolBar.setAlpha(ALPHA_ON, saveIcon); + toolBar.setAlpha(ALPHA_ON, loadIcon); + } else if (Recording.playerLength() > 0) { + Recording.setPlayerLoop(false); + Recording.startPlaying(); + toolBar.setAlpha(ALPHA_OFF, recordIcon); + toolBar.setAlpha(ALPHA_OFF, saveIcon); + toolBar.setAlpha(ALPHA_OFF, loadIcon); + watchStop = true; + } + } else if (playLoopIcon === toolBar.clicked(clickedOverlay) && !Recording.isRecording()) { + if (Recording.isPlaying()) { + Recording.pausePlayer(); + toolBar.setAlpha(ALPHA_ON, recordIcon); + toolBar.setAlpha(ALPHA_ON, saveIcon); + toolBar.setAlpha(ALPHA_ON, loadIcon); + } else if (Recording.playerLength() > 0) { + Recording.setPlayerLoop(true); + Recording.startPlaying(); + toolBar.setAlpha(ALPHA_OFF, recordIcon); + toolBar.setAlpha(ALPHA_OFF, saveIcon); + toolBar.setAlpha(ALPHA_OFF, loadIcon); + } + } else if (saveIcon === toolBar.clicked(clickedOverlay)) { + if (!Recording.isRecording() && !Recording.isPlaying() && Recording.playerLength() !== 0) { + recordingFile = Window.save("Save recording to file", ".", "Recordings (*.hfr)"); + if (!(recordingFile === "null" || recordingFile === null || recordingFile === "")) { + Recording.saveRecording(recordingFile); + } + } + } else if (loadIcon === toolBar.clicked(clickedOverlay)) { + if (!Recording.isRecording() && !Recording.isPlaying()) { + recordingFile = Window.browse("Load recording from file", ".", "Recordings (*.hfr *.rec *.HFR *.REC)"); + if (!(recordingFile === "null" || recordingFile === null || recordingFile === "")) { + Recording.loadRecording(recordingFile, function(success) { + if (success) { + setDefaultPlayerOptions(); + } else { + print("Failed to load recording from " + recordingFile); + } + }); + } + if (Recording.playerLength() > 0) { + toolBar.setAlpha(ALPHA_ON, playIcon); + toolBar.setAlpha(ALPHA_ON, playLoopIcon); + toolBar.setAlpha(ALPHA_ON, saveIcon); + } + } + } else if (Recording.playerLength() > 0 && + slider.x < event.x && event.x < slider.x + slider.w && + slider.y < event.y && event.y < slider.y + slider.h) { + isSliding = true; + slider.pos = (event.x - slider.x) / slider.w; + Recording.setPlayerTime(slider.pos * Recording.playerLength()); + } +} +var isSliding = false; + +function mouseMoveEvent(event) { + if (isSliding) { + slider.pos = (event.x - slider.x) / slider.w; + if (slider.pos < 0.0 || slider.pos > 1.0) { + Recording.stopPlaying(); + slider.pos = 0.0; + } + Recording.setPlayerTime(slider.pos * Recording.playerLength()); + } +} + +function mouseReleaseEvent(event) { + isSliding = false; +} + +function update() { + var newDimensions = Controller.getViewportDimensions(); + if (windowDimensions.x !== newDimensions.x || windowDimensions.y !== newDimensions.y) { + windowDimensions = newDimensions; + moveUI(); + } + + updateTimer(); + + if (watchStop && !Recording.isPlaying()) { + watchStop = false; + toolBar.setAlpha(ALPHA_ON, recordIcon); + toolBar.setAlpha(ALPHA_ON, saveIcon); + toolBar.setAlpha(ALPHA_ON, loadIcon); + } +} + +function scriptEnding() { + if (Recording.isRecording()) { + Recording.stopRecording(); + } + if (Recording.isPlaying()) { + Recording.stopPlaying(); + } + toolBar.cleanup(); + Overlays.deleteOverlay(timer); + Overlays.deleteOverlay(slider.background); + Overlays.deleteOverlay(slider.foreground); +} + +Controller.mousePressEvent.connect(mousePressEvent); +Controller.mouseMoveEvent.connect(mouseMoveEvent); +Controller.mouseReleaseEvent.connect(mouseReleaseEvent); +Script.update.connect(update); +Script.scriptEnding.connect(scriptEnding); + +// Should be called last to put everything into position +moveUI();