From 321d281919eaacec5b9f608bbe73098ab6b3ca15 Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Fri, 21 Apr 2017 01:46:44 -0700 Subject: [PATCH 01/15] 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/15] 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/15] 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/15] 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/15] 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 ac86c134779c5ee356efb1e56aa7e9753cfd0ece Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Mon, 1 May 2017 12:18:06 -0700 Subject: [PATCH 06/15] 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 07/15] 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 08/15] 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 09/15] 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 10/15] 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 11/15] 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 12/15] 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 13/15] 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 14/15] 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 15/15] 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();