From 99e69616fabe9cd2fba6d77ef0ce27594c53e74c Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 20 Jan 2016 17:50:52 -0800 Subject: [PATCH 001/145] basic comms --- .../junkyard/junkyardResetEntityScript.js | 32 ++++++++++++++ .../junkyard/junkyardResetEntitySpawner.js | 43 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 examples/junkyard/junkyardResetEntityScript.js create mode 100644 examples/junkyard/junkyardResetEntitySpawner.js diff --git a/examples/junkyard/junkyardResetEntityScript.js b/examples/junkyard/junkyardResetEntityScript.js new file mode 100644 index 0000000000..71308f81cd --- /dev/null +++ b/examples/junkyard/junkyardResetEntityScript.js @@ -0,0 +1,32 @@ +// junkyardResetEntityScript.js +// +// Script Type: Entity +// Created by Eric Levin on 1/20/16. +// Copyright 2016 High Fidelity, Inc. +// +// This entity script resets the junkyard when triggered +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + Script.include("../libraries/utils.js"); + var _this; + var JunkyardResetter = function() { + _this = this; + }; + + JunkyardResetter.prototype = { + startDistantGrab: function() { + print("YAAAAAAAA") + }, + + startNearGrab: function() { + }, + + preload: function(entityID) { + this.entityID = entityID; + }, + }; + return new JunkyardResetter(); +}); \ No newline at end of file diff --git a/examples/junkyard/junkyardResetEntitySpawner.js b/examples/junkyard/junkyardResetEntitySpawner.js new file mode 100644 index 0000000000..8db23517a3 --- /dev/null +++ b/examples/junkyard/junkyardResetEntitySpawner.js @@ -0,0 +1,43 @@ + // + // junkyardResetEntitySpawner.js + // examples/junkyard + // + // Created by Eric Levin on 1/20/16. + // Copyright 2016 High Fidelity, Inc. + // + // This script spawns an entity which, when triggered, will reset the junkyard + // + // + // Distributed under the Apache License, Version 2.0. + // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + // + + var orientation = Camera.getOrientation(); + orientation = Quat.safeEulerAngles(orientation); + orientation.x = 0; + orientation = Quat.fromVec3Degrees(orientation); + var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(orientation))); + + + var scriptURL = Script.resolvePath("junkyardResetEntityScript.js"); + var resetEntity = Entities.addEntity({ + type: "Box", + position: center, + script: scriptURL, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + color: { + red: 200, + green: 10, + blue: 200 + } + }); + + function cleanup() { + Entities.deleteEntity(resetEntity); + } + + Script.scriptEnding.connect(cleanup); \ No newline at end of file From 641607f334df1798a7847d3c8c4e08e5c2f8697b Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 21 Jan 2016 10:22:56 -0800 Subject: [PATCH 002/145] reset script --- examples/edit.js | 2 ++ .../junkyard/junkyardResetEntityScript.js | 28 +++++++++++++++++++ .../junkyard/junkyardResetEntitySpawner.js | 2 +- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/examples/edit.js b/examples/edit.js index 41f25cb2e5..e2b4d83541 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -1355,6 +1355,8 @@ function importSVO(importURL) { position = getPositionToCreateEntity(); } if (position != null) { + + print("POSITION OF ENTITIES" + JSON.stringify(position)) var pastedEntityIDs = Clipboard.pasteEntities(position); if (isActive) { diff --git a/examples/junkyard/junkyardResetEntityScript.js b/examples/junkyard/junkyardResetEntityScript.js index 71308f81cd..7911a6a74b 100644 --- a/examples/junkyard/junkyardResetEntityScript.js +++ b/examples/junkyard/junkyardResetEntityScript.js @@ -12,6 +12,7 @@ (function() { Script.include("../libraries/utils.js"); var _this; + var importURL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/arfs/junkyard.json"; var JunkyardResetter = function() { _this = this; }; @@ -22,6 +23,33 @@ }, startNearGrab: function() { + + }, + + clickReleaseOnEntity: function(entityId, mouseEvent) { + if (!mouseEvent.isLeftButton) { + return; + } + this.reset(); + + }, + + reset: function() { + // Delete everything and re-import the junkyard arf + var e = Entities.findEntities(MyAvatar.position, 1000); + for (i = 0; i < e.length; i++) { + Entities.deleteEntity(e[i]); + } + this.importArf(); + }, + + importArf: function() { + Clipboard.importEntities(importURL); + Clipboard.pasteEntities({ + x: 0, + y: 0, + z: 0 + }); }, preload: function(entityID) { diff --git a/examples/junkyard/junkyardResetEntitySpawner.js b/examples/junkyard/junkyardResetEntitySpawner.js index 8db23517a3..24eb29b950 100644 --- a/examples/junkyard/junkyardResetEntitySpawner.js +++ b/examples/junkyard/junkyardResetEntitySpawner.js @@ -19,7 +19,7 @@ var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(orientation))); - var scriptURL = Script.resolvePath("junkyardResetEntityScript.js"); + var scriptURL = Script.resolvePath("junkyardResetEntityScript.js?v1" + Math.random()); var resetEntity = Entities.addEntity({ type: "Box", position: center, From b3b1793035adbd39636dced583405f7b7fdec35a Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 21 Jan 2016 12:03:09 -0800 Subject: [PATCH 003/145] removed edit.js changes --- examples/edit.js | 2 -- examples/junkyard/junkyardClientReset.js | 35 +++++++++++++++++++ .../junkyard/junkyardResetEntityScript.js | 12 +++---- .../junkyard/junkyardResetEntitySpawner.js | 9 ++--- 4 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 examples/junkyard/junkyardClientReset.js diff --git a/examples/edit.js b/examples/edit.js index e2b4d83541..41f25cb2e5 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -1355,8 +1355,6 @@ function importSVO(importURL) { position = getPositionToCreateEntity(); } if (position != null) { - - print("POSITION OF ENTITIES" + JSON.stringify(position)) var pastedEntityIDs = Clipboard.pasteEntities(position); if (isActive) { diff --git a/examples/junkyard/junkyardClientReset.js b/examples/junkyard/junkyardClientReset.js new file mode 100644 index 0000000000..c712737cca --- /dev/null +++ b/examples/junkyard/junkyardClientReset.js @@ -0,0 +1,35 @@ +// +// junkyardClientReset.js +// examples/junkyard +// +// Created by Eric Levin on 1/21/16. +// Copyright 2016 High Fidelity, Inc. +// +// This script resets the junkyard scene +// +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var importURL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/arfs/junkyard.json"; + +reset(); + +function reset() { + // Delete everything and re-import the junkyard arf + var e = Entities.findEntities(MyAvatar.position, 1000); + for (i = 0; i < e.length; i++) { + Entities.deleteEntity(e[i]); + } + importArf(); +} + +function importArf() { + Clipboard.importEntities(importURL); + Clipboard.pasteEntities({ + x: 0, + y: 0, + z: 0 + }); +} \ No newline at end of file diff --git a/examples/junkyard/junkyardResetEntityScript.js b/examples/junkyard/junkyardResetEntityScript.js index 7911a6a74b..7a9ee54d22 100644 --- a/examples/junkyard/junkyardResetEntityScript.js +++ b/examples/junkyard/junkyardResetEntityScript.js @@ -18,13 +18,6 @@ }; JunkyardResetter.prototype = { - startDistantGrab: function() { - print("YAAAAAAAA") - }, - - startNearGrab: function() { - - }, clickReleaseOnEntity: function(entityId, mouseEvent) { if (!mouseEvent.isLeftButton) { @@ -38,7 +31,10 @@ // Delete everything and re-import the junkyard arf var e = Entities.findEntities(MyAvatar.position, 1000); for (i = 0; i < e.length; i++) { - Entities.deleteEntity(e[i]); + // Don't delete our reset entity + if (JSON.stringify(this.entityID) !== JSON.stringify(e[i])) { + Entities.deleteEntity(e[i]); + } } this.importArf(); }, diff --git a/examples/junkyard/junkyardResetEntitySpawner.js b/examples/junkyard/junkyardResetEntitySpawner.js index 24eb29b950..b2627c7cd9 100644 --- a/examples/junkyard/junkyardResetEntitySpawner.js +++ b/examples/junkyard/junkyardResetEntitySpawner.js @@ -21,13 +21,14 @@ var scriptURL = Script.resolvePath("junkyardResetEntityScript.js?v1" + Math.random()); var resetEntity = Entities.addEntity({ - type: "Box", + type: "Model", + modelURL: "http://hifi-content.s3.amazonaws.com/caitlyn/dev/Blueprint%20Objects/Asylum/Asylum_Table/Asylum_Table.fbx", position: center, script: scriptURL, dimensions: { - x: 1, - y: 1, - z: 1 + x: 2.8, + y: 1.76, + z: 1.32 }, color: { red: 200, From e11e4d196b87ce9a28caa57ab5a9a21ca671d518 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 21 Jan 2016 13:24:07 -0800 Subject: [PATCH 004/145] tweaks for coding standards --- examples/junkyard/junkyardClientReset.js | 12 ++++-------- examples/junkyard/junkyardResetEntityScript.js | 11 ++++------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/examples/junkyard/junkyardClientReset.js b/examples/junkyard/junkyardClientReset.js index c712737cca..8aea8470dd 100644 --- a/examples/junkyard/junkyardClientReset.js +++ b/examples/junkyard/junkyardClientReset.js @@ -12,8 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -var importURL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/arfs/junkyard.json"; - +var IMPORT_URL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/arfs/junkyard.json"; +var PASTE_ENTITIES_LOCATION = {x: 0, y: 0, z: 0}; reset(); function reset() { @@ -26,10 +26,6 @@ function reset() { } function importArf() { - Clipboard.importEntities(importURL); - Clipboard.pasteEntities({ - x: 0, - y: 0, - z: 0 - }); + Clipboard.importEntities(IMPORT_URL); + Clipboard.pasteEntities(PASTE_ENTITIES_LOCATION); } \ No newline at end of file diff --git a/examples/junkyard/junkyardResetEntityScript.js b/examples/junkyard/junkyardResetEntityScript.js index 7a9ee54d22..9bd7ec02a5 100644 --- a/examples/junkyard/junkyardResetEntityScript.js +++ b/examples/junkyard/junkyardResetEntityScript.js @@ -12,7 +12,8 @@ (function() { Script.include("../libraries/utils.js"); var _this; - var importURL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/arfs/junkyard.json"; + var IMPORT_URL = "https://s3-us-west-1.amazonaws.com/hifi-content/eric/arfs/junkyard.json"; + var PASTE_ENTITIES_LOCATION = {x: 0, y: 0, z: 0}; var JunkyardResetter = function() { _this = this; }; @@ -40,12 +41,8 @@ }, importArf: function() { - Clipboard.importEntities(importURL); - Clipboard.pasteEntities({ - x: 0, - y: 0, - z: 0 - }); + Clipboard.importEntities(IMPORT_URL); + Clipboard.pasteEntities(PASTE_ENTITIES_LOCATION); }, preload: function(entityID) { From 2e1727610ef061167db5bae3743e590ebc8104d5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 21 Jan 2016 15:52:59 -0800 Subject: [PATCH 005/145] MyAvatar updates the entity-server about queryAACubes of children entities --- interface/src/avatar/MyAvatar.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b1688b8f9e..b6dcc96c22 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -50,6 +50,7 @@ #include "Util.h" #include "InterfaceLogging.h" #include "DebugDraw.h" +#include "EntityEditPacketSender.h" using namespace std; @@ -352,6 +353,21 @@ void MyAvatar::simulate(float deltaTime) { // consider updating our billboard maybeUpdateBillboard(); + + locationChanged(); + // if a entity-child of this avatar has moved outside of its queryAACube, update the cube and tell the entity server. + forEachDescendant([&](SpatiallyNestablePointer object) { + if (object->computePuffedQueryAACube() && object->getNestableType() == NestableType::Entity) { + EntityItemPointer entity = std::static_pointer_cast(object); + EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender(); + if (packetSender) { + EntityItemProperties properties = entity->getProperties(); + properties.setQueryAACubeDirty(); + packetSender->queueEditEntityMessage(PacketType::EntityEdit, entity->getID(), properties); + entity->setLastBroadcast(usecTimestampNow()); + } + } + }); } glm::mat4 MyAvatar::getSensorToWorldMatrix() const { From cbed54268212265943f4ccebf57f370001c92704 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 21 Jan 2016 15:53:19 -0800 Subject: [PATCH 006/145] MyAvatar updates the entity-server about queryAACubes of children entities --- libraries/entities/src/EntityItemProperties.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 0f0bab5fdd..8a2431eb9e 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -254,6 +254,8 @@ public: void setLinePointsDirty() {_linePointsChanged = true; } + void setQueryAACubeDirty() { _queryAACubeChanged = true; } + void setCreated(QDateTime& v); bool hasTerseUpdateChanges() const; From 872a00d518d8cc1636cd857f824343cad4c870dd Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 21 Jan 2016 15:53:47 -0800 Subject: [PATCH 007/145] entities that are children shouldn't (at this point) be dynamic. --- libraries/physics/src/EntityMotionState.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 4e5f942265..9982b4d107 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -144,7 +144,12 @@ PhysicsMotionType EntityMotionState::computePhysicsMotionType() const { return MOTION_TYPE_STATIC; } assert(entityTreeIsLocked()); + if (_entity->getDynamic()) { + if (!_entity->getParentID().isNull()) { + // if something would have been dynamic but is a child of something else, force it to be kinematic, instead. + return MOTION_TYPE_KINEMATIC; + } return MOTION_TYPE_DYNAMIC; } return (_entity->isMoving() || _entity->hasActions()) ? MOTION_TYPE_KINEMATIC : MOTION_TYPE_STATIC; From 3dab1571a586d368ce595be24630dd771a9c07e3 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 19 Jan 2016 16:21:23 -0800 Subject: [PATCH 008/145] Make Task a Job --- libraries/render/src/render/Task.h | 292 ++++++++++++++--------------- 1 file changed, 145 insertions(+), 147 deletions(-) diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index b63cb88dcf..396d954830 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -49,179 +49,177 @@ protected: }; // FIXME: In c++17, use default classes of nullptr_t to combine these -template void jobRun(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - jobModel.run(sceneContext, renderContext); +template void jobRun(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + model.run(sceneContext, renderContext); } -template void jobRunI(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) { - jobModel.run(sceneContext, renderContext, input); +template void jobRunI(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) { + model.run(sceneContext, renderContext, input); } -template void jobRunO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) { - jobModel.run(sceneContext, renderContext, output); +template void jobRunO(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) { + model.run(sceneContext, renderContext, output); } -template void jobRunIO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) { - jobModel.run(sceneContext, renderContext, input, output); +template void jobRunIO(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) { + model.run(sceneContext, renderContext, input, output); } -// The base class for a task that runs on the SceneContext -class Task { +class Job { public: - // The guts of a task; tasks are composed of multiple Jobs that execute serially - class Job { + // The guts of a job; jobs are composed of a concept + class Concept { public: - friend class Task; + Concept() = default; + virtual ~Concept() = default; - // The guts of a job; jobs are composed of a concept - class Concept { - public: - Concept() = default; - virtual ~Concept() = default; + bool isEnabled() const { return _isEnabled; } + void setEnabled(bool isEnabled) { _isEnabled = isEnabled; } - bool isEnabled() const { return _isEnabled; } - void setEnabled(bool isEnabled) { _isEnabled = isEnabled; } + virtual const Varying getInput() const { return Varying(); } + virtual const Varying getOutput() const { return Varying(); } + virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; - virtual const Varying getInput() const { return Varying(); } - virtual const Varying getOutput() const { return Varying(); } - virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; + protected: - protected: + bool _isEnabled = true; + }; + using ConceptPointer = std::shared_ptr; - bool _isEnabled = true; - }; - using ConceptPointer = std::shared_ptr; + template class Model : public Concept { + public: + typedef T Data; + Data _data; - template class Model : public Concept { - public: - typedef T Data; - - Data _data; - - Model() {} - Model(Data data): _data(data) {} - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRun(_data, sceneContext, renderContext); - } - } - }; - - template class ModelI : public Concept { - public: - typedef T Data; - typedef I Input; - - Data _data; - Varying _input; - - const Varying getInput() const { return _input; } - - ModelI(const Varying& input, Data data = Data()) : _data(data), _input(input) {} - ModelI(Data data) : _data(data) {} - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRunI(_data, sceneContext, renderContext, _input.get()); - } - } - }; - - template class ModelO : public Concept { - public: - typedef T Data; - typedef O Output; - - Data _data; - Varying _output; - - const Varying getOutput() const { return _output; } - - ModelO(Data data) : _data(data), _output(Output()) {} - ModelO() : _output(Output()) {} - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRunO(_data, sceneContext, renderContext, _output.edit()); - } - } - }; - - template class ModelIO : public Concept { - public: - typedef T Data; - typedef I Input; - typedef O Output; - - Data _data; - Varying _input; - Varying _output; - - const Varying getInput() const { return _input; } - const Varying getOutput() const { return _output; } - - ModelIO(const Varying& input, Data data = Data()) : _data(data), _input(input), _output(Output()) {} - ModelIO(Data data) : _data(data), _output(Output()) {} - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); - } - } - }; - - Job(ConceptPointer concept) : _concept(concept) {} - Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} - - bool isEnabled() const { return _concept->isEnabled(); } - void setEnabled(bool isEnabled) { _concept->setEnabled(isEnabled); } - - const Varying getInput() const { return _concept->getInput(); } - const Varying getOutput() const { return _concept->getOutput(); } - - template T& edit() { - auto concept = std::static_pointer_cast(_concept); - assert(concept); - return concept->_data; - } - template const T& get() const { - auto concept = std::static_pointer_cast(_concept); - assert(concept); - return concept->_data; - } + Model() {} + Model(Data data) : _data(data) {} void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - PerformanceTimer perfTimer(_name.c_str()); - PROFILE_RANGE(_name.c_str()); - - _concept->run(sceneContext, renderContext); + if (isEnabled()) { + jobRun(_data, sceneContext, renderContext); + } } - protected: - ConceptPointer _concept; - std::string _name = ""; - }; - using Jobs = std::vector; -public: - Task() = default; - virtual ~Task() = default; + template class ModelI : public Concept { + public: + typedef T Data; + typedef I Input; - // Queue a new job to the task; returns the job's index - template const Varying addJob(std::string name, A&&... args) { - _jobs.emplace_back(name, std::make_shared(std::forward(args)...)); - return _jobs.back().getOutput(); + Data _data; + Varying _input; + + const Varying getInput() const { return _input; } + + ModelI(const Varying& input, Data data = Data()) : _data(data), _input(input) {} + ModelI(Data data) : _data(data) {} + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRunI(_data, sceneContext, renderContext, _input.get()); + } + } + }; + + template class ModelO : public Concept { + public: + typedef T Data; + typedef O Output; + + Data _data; + Varying _output; + + const Varying getOutput() const { return _output; } + + ModelO(Data data) : _data(data), _output(Output()) {} + ModelO() : _output(Output()) {} + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRunO(_data, sceneContext, renderContext, _output.edit()); + } + } + }; + + template class ModelIO : public Concept { + public: + typedef T Data; + typedef I Input; + typedef O Output; + + Data _data; + Varying _input; + Varying _output; + + const Varying getInput() const { return _input; } + const Varying getOutput() const { return _output; } + + ModelIO(const Varying& input, Data data = Data()) : _data(data), _input(input), _output(Output()) {} + ModelIO(Data data) : _data(data), _output(Output()) {} + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); + } + } + }; + + Job(ConceptPointer concept) : _concept(concept) {} + Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} + + bool isEnabled() const { return _concept->isEnabled(); } + void setEnabled(bool isEnabled) { _concept->setEnabled(isEnabled); } + + const Varying getInput() const { return _concept->getInput(); } + const Varying getOutput() const { return _concept->getOutput(); } + + template T& edit() { + auto concept = std::static_pointer_cast(_concept); + assert(concept); + return concept->_data; + } + template const T& get() const { + auto concept = std::static_pointer_cast(_concept); + assert(concept); + return concept->_data; } - void enableJob(size_t jobIndex, bool enable = true) { _jobs.at(jobIndex).setEnabled(enable); } - bool getEnableJob(size_t jobIndex) const { return _jobs.at(jobIndex).isEnabled(); } + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + PerformanceTimer perfTimer(_name.c_str()); + PROFILE_RANGE(_name.c_str()); - virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {} + _concept->run(sceneContext, renderContext); + } + + class Container { + public: + using Job = Job; + using Jobs = std::vector; + + Container() = default; + virtual ~Container() = default; + + // Queue a new job to the container; returns the job's output + template const Varying addJob(std::string name, A&&... args) { + _jobs.emplace_back(name, std::make_shared(std::forward(args)...)); + return _jobs.back().getOutput(); + } + + void enableJob(size_t jobIndex, bool enable = true) { _jobs.at(jobIndex).setEnabled(enable); } + bool getEnableJob(size_t jobIndex) const { return _jobs.at(jobIndex).isEnabled(); } + + protected: + Jobs _jobs; + }; protected: - Jobs _jobs; + friend class Container; + + ConceptPointer _concept; + std::string _name = ""; }; -typedef std::shared_ptr TaskPointer; -typedef std::vector Tasks; +// Define our vernacular: Engine->Tasks->Jobs +using Task = Job::Container; +using TaskPointer = std::shared_ptr; +using Tasks = std::vector; } From 8b68d5922c93caba72098acdf76334e57bb75d18 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 19 Jan 2016 16:48:45 -0800 Subject: [PATCH 009/145] Make Engine a Task --- interface/src/Application.cpp | 4 +-- .../render-utils/src/RenderDeferredTask.h | 5 +++- libraries/render-utils/src/RenderShadowTask.h | 2 ++ libraries/render/src/render/Engine.cpp | 18 ++----------- libraries/render/src/render/Engine.h | 27 ++++++++----------- 5 files changed, 21 insertions(+), 35 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a7bac40033..942f1c3780 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -677,8 +677,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : // Start rendering render::CullFunctor cullFunctor = LODManager::shouldRender; - _renderEngine->addTask(make_shared(cullFunctor)); - _renderEngine->addTask(make_shared(cullFunctor)); + _renderEngine->addJob("RenderShadowTask", cullFunctor); + _renderEngine->addJob("RenderDeferredTask", cullFunctor); _renderEngine->registerScene(_main3DScene); _offscreenContext->makeCurrent(); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 78327006cd..1b4afcc058 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -115,6 +115,10 @@ class RenderDeferredTask : public render::Task { public: RenderDeferredTask(render::CullFunctor cullFunctor); + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + + using JobModel = render::Task::Job::Model; + void setDrawDebugDeferredBuffer(int draw) { enableJob(_drawDebugDeferredBufferIndex, draw >= 0); } bool doDrawDebugDeferredBuffer() const { return getEnableJob(_drawDebugDeferredBufferIndex); } @@ -136,7 +140,6 @@ public: void setToneMappingToneCurve(int toneCurve); int getToneMappingToneCurve() const; - virtual void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); protected: int _drawDebugDeferredBufferIndex; diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index add021994a..61f8bccb3c 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -35,6 +35,8 @@ public: RenderShadowTask(render::CullFunctor shouldRender); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + + using JobModel = render::Task::Job::Model; }; #endif // hifi_RenderShadowTask_h diff --git a/libraries/render/src/render/Engine.cpp b/libraries/render/src/render/Engine.cpp index 06cfd2e78b..ef949247b6 100644 --- a/libraries/render/src/render/Engine.cpp +++ b/libraries/render/src/render/Engine.cpp @@ -21,25 +21,11 @@ Engine::Engine() : { } -void Engine::registerScene(const ScenePointer& scene) { - _sceneContext->_scene = scene; -} - -void Engine::setRenderContext(const RenderContext& renderContext) { - (*_renderContext) = renderContext; -} - -void Engine::addTask(const TaskPointer& task) { - if (task) { - _tasks.push_back(task); - } -} - void Engine::run() { // Sync GPU state before beginning to render _renderContext->getArgs()->_context->syncCache(); - for (auto task : _tasks) { - task->run(_sceneContext, _renderContext); + for (auto job : _jobs) { + job.run(_sceneContext, _renderContext); } } diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index fa01ef6018..e94de6f266 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -17,36 +17,31 @@ namespace render { -// The root of the tasks, the Engine, should not be known from the Tasks, -// The SceneContext is what navigates from the engine down to the Tasks -class Engine { +// 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. +class Engine : public Task { public: - Engine(); - ~Engine() {} + ~Engine() = default; - // Register the scene should be [art of the init phase before running the engine - void registerScene(const ScenePointer& scene); + // Register the scene + void registerScene(const ScenePointer& scene) { _sceneContext->_scene = scene; } // Push a RenderContext - void setRenderContext(const RenderContext& renderContext); + void setRenderContext(const RenderContext& renderContext) { (*_renderContext) = renderContext; } RenderContextPointer getRenderContext() const { return _renderContext; } - void addTask(const TaskPointer& task); - const Tasks& getTasks() const { return _tasks; } - - + // Render a frame + // A frame must have a scene registered and a context set to render void run(); protected: - Tasks _tasks; - SceneContextPointer _sceneContext; RenderContextPointer _renderContext; }; -typedef std::shared_ptr EnginePointer; +using EnginePointer = std::shared_ptr; } #endif // hifi_render_Engine_h - From 581003ec838815a96d7af01a7fce37d6703f4f90 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 20 Jan 2016 18:35:40 -0800 Subject: [PATCH 010/145] Use QObject-derived Configuration for render::Job --- .../render-utils/src/RenderDeferredTask.cpp | 26 +++--- .../render-utils/src/RenderDeferredTask.h | 17 +++- libraries/render/src/render/Task.h | 90 ++++++++++++++----- 3 files changed, 91 insertions(+), 42 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 7afab44c6c..85f9859216 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -67,6 +67,16 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo DependencyManager::get()->render(renderContext); } +void ToneMappingDeferred::configure(const Configuration& configuration) { + if (configuration.exposure >= 0) { + _toneMappingEffect.setExposure(configuration.curve); + } + if (configuration.curve >= 0) { + _toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)configuration.curve); + + } +} + void ToneMappingDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { _toneMappingEffect.render(renderContext->getArgs()); } @@ -499,28 +509,12 @@ void RenderDeferredTask::setToneMappingExposure(float exposure) { } } -float RenderDeferredTask::getToneMappingExposure() const { - if (_toneMappingJobIndex >= 0) { - return _jobs[_toneMappingJobIndex].get()._toneMappingEffect.getExposure(); - } else { - return 0.0f; - } -} - void RenderDeferredTask::setToneMappingToneCurve(int toneCurve) { if (_toneMappingJobIndex >= 0) { _jobs[_toneMappingJobIndex].edit()._toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)toneCurve); } } -int RenderDeferredTask::getToneMappingToneCurve() const { - if (_toneMappingJobIndex >= 0) { - return _jobs[_toneMappingJobIndex].get()._toneMappingEffect.getToneCurve(); - } else { - return 0.0f; - } -} - void pipelineBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { if (pipeline.locations->normalFittingMapUnit > -1) { batch.setResourceTexture(pipeline.locations->normalFittingMapUnit, diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 1b4afcc058..da9d99243b 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -40,13 +40,24 @@ public: using JobModel = render::Task::Job::Model; }; +class ToneMappingConfiguration : public QObject { + Q_OBJECT +public: + Q_PROPERTY(float exposure MEMBER exposure); + Q_PROPERTY(int curve MEMBER curve); + float exposure; + int curve; +}; + class ToneMappingDeferred { public: + using Configuration = ToneMappingConfiguration; + void configure(const Configuration&); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - ToneMappingEffect _toneMappingEffect; + using JobModel = render::Task::Job::Model; - using JobModel = render::Task::Job::Model; + ToneMappingEffect _toneMappingEffect; }; class DrawOpaqueDeferred { @@ -135,10 +146,8 @@ public: bool doAntialiasingStatus() const { return getEnableJob(_antialiasingJobIndex); } void setToneMappingExposure(float exposure); - float getToneMappingExposure() const; void setToneMappingToneCurve(int toneCurve); - int getToneMappingToneCurve() const; protected: diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 396d954830..a9c09b6a38 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -12,6 +12,8 @@ #ifndef hifi_render_Task_h #define hifi_render_Task_h +#include // QObject + #include "Context.h" #include "gpu/Batch.h" @@ -48,6 +50,16 @@ protected: std::shared_ptr _concept; }; +class NoConfiguration : public QObject { + Q_OBJECT +}; + +template void jobConfigure(T& model, const C& configuration) { + model.configure(configuration); +} +template void jobConfigure(T&, const NoConfiguration&) { +} + // FIXME: In c++17, use default classes of nullptr_t to combine these template void jobRun(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { model.run(sceneContext, renderContext); @@ -64,7 +76,9 @@ template void jobRunIO(T& model, const SceneContextP class Job { public: - // The guts of a job; jobs are composed of a concept + using QObjectPointer = std::shared_ptr; + + // The guts of a job class Concept { public: Concept() = default; @@ -75,22 +89,33 @@ public: virtual const Varying getInput() const { return Varying(); } virtual const Varying getOutput() const { return Varying(); } + virtual const QObjectPointer getConfiguration() = 0; + virtual void setConfiguration(const QObjectPointer& configuration) = 0; virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; protected: - bool _isEnabled = true; }; using ConceptPointer = std::shared_ptr; - template class Model : public Concept { + template class Model : public Concept { public: - typedef T Data; + using Data = T; + using ConfigurationPointer = std::shared_ptr; Data _data; + ConfigurationPointer _configuration; - Model() {} - Model(Data data) : _data(data) {} + Model() : _configuration{ std::make_shared() } {} + Model(Data data) : _data(data), _configuration{ std::make_shared() } { + jobConfigure(_data, *_configuration); + } + + const QObjectPointer getConfiguration() { return _configuration; } + void setConfiguration(const QObjectPointer& configuration) { + _configuration = std::static_pointer_cast(configuration); + jobConfigure(_data, *_configuration); + } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { if (isEnabled()) { @@ -99,12 +124,14 @@ public: } }; - template class ModelI : public Concept { + template class ModelI : public Concept { public: - typedef T Data; - typedef I Input; + using Data = T; + using ConfigurationPointer = std::shared_ptr; + using Input = I; Data _data; + ConfigurationPointer _configuration; Varying _input; const Varying getInput() const { return _input; } @@ -112,6 +139,12 @@ public: ModelI(const Varying& input, Data data = Data()) : _data(data), _input(input) {} ModelI(Data data) : _data(data) {} + const QObjectPointer getConfiguration() { return _configuration; } + void setConfiguration(const QObjectPointer& configuration) { + _configuration = std::static_pointer_cast(configuration); + jobConfigure(_data, *_configuration); + } + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { if (isEnabled()) { jobRunI(_data, sceneContext, renderContext, _input.get()); @@ -119,12 +152,14 @@ public: } }; - template class ModelO : public Concept { + template class ModelO : public Concept { public: - typedef T Data; - typedef O Output; + using Data = T; + using ConfigurationPointer = std::shared_ptr; + using Output = O; Data _data; + ConfigurationPointer _configuration; Varying _output; const Varying getOutput() const { return _output; } @@ -132,6 +167,12 @@ public: ModelO(Data data) : _data(data), _output(Output()) {} ModelO() : _output(Output()) {} + const QObjectPointer getConfiguration() { return _configuration; } + void setConfiguration(const QObjectPointer& configuration) { + _configuration = std::static_pointer_cast(configuration); + jobConfigure(_data, *_configuration); + } + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { if (isEnabled()) { jobRunO(_data, sceneContext, renderContext, _output.edit()); @@ -139,13 +180,15 @@ public: } }; - template class ModelIO : public Concept { + template class ModelIO : public Concept { public: - typedef T Data; - typedef I Input; - typedef O Output; + using Data = T; + using ConfigurationPointer = std::shared_ptr; + using Input = I; + using Output = O; Data _data; + ConfigurationPointer _configuration; Varying _input; Varying _output; @@ -155,6 +198,12 @@ public: ModelIO(const Varying& input, Data data = Data()) : _data(data), _input(input), _output(Output()) {} ModelIO(Data data) : _data(data), _output(Output()) {} + const QObjectPointer getConfiguration() { return _configuration; } + void setConfiguration(const QObjectPointer& configuration) { + _configuration = std::static_pointer_cast(configuration); + jobConfigure(_data, *_configuration); + } + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { if (isEnabled()) { jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); @@ -162,7 +211,7 @@ public: } }; - Job(ConceptPointer concept) : _concept(concept) {} + Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} bool isEnabled() const { return _concept->isEnabled(); } @@ -170,17 +219,14 @@ public: const Varying getInput() const { return _concept->getInput(); } const Varying getOutput() const { return _concept->getOutput(); } + const QObjectPointer getConfiguration() const { return _concept->getConfiguration(); } + void setConfiguration(const QObjectPointer& configuration) { return _concept->setConfiguration(configuration); } template T& edit() { auto concept = std::static_pointer_cast(_concept); assert(concept); return concept->_data; } - template const T& get() const { - auto concept = std::static_pointer_cast(_concept); - assert(concept); - return concept->_data; - } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { PerformanceTimer perfTimer(_name.c_str()); From 2e1fbf66ad45b304c2becb95c61e101251819fb8 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 21 Jan 2016 11:44:22 -0800 Subject: [PATCH 011/145] Refine Configuration for render::Job wip wip wip wip --- interface/src/Application.cpp | 2 + .../render-utils/src/AmbientOcclusionEffect.h | 3 +- .../render-utils/src/AntialiasingEffect.h | 2 +- .../render-utils/src/DebugDeferredBuffer.h | 2 +- libraries/render-utils/src/HitEffect.h | 2 +- .../render-utils/src/RenderDeferredTask.cpp | 4 +- .../render-utils/src/RenderDeferredTask.h | 41 ++-- .../render-utils/src/RenderShadowTask.cpp | 2 +- libraries/render-utils/src/RenderShadowTask.h | 4 +- libraries/render/src/render/DrawStatus.h | 2 +- libraries/render/src/render/DrawTask.h | 12 +- libraries/render/src/render/Task.h | 194 +++++++++++------- 12 files changed, 161 insertions(+), 109 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 942f1c3780..76300edb55 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1251,6 +1251,7 @@ void Application::initializeUi() { rootContext->setContextProperty("HMD", DependencyManager::get().data()); rootContext->setContextProperty("Scene", DependencyManager::get().data()); rootContext->setContextProperty("Render", DependencyManager::get().data()); + // TODO: Expose Engine here _glWidget->installEventFilter(offscreenUi.data()); offscreenUi->setMouseTranslator([=](const QPointF& pt) { @@ -4200,6 +4201,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerGlobalObject("Scene", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Render", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("Engine", _renderEngine->getConfiguration().get()); scriptEngine->registerGlobalObject("ScriptDiscoveryService", DependencyManager::get().data()); } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 9973bd9ec8..5bfeca38a4 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -67,10 +67,9 @@ public: void setBlurDeviation(float deviation); float getBlurDeviation() const { return _parametersBuffer.get().blurInfo.z; } - double getGPUTime() const { return _gpuTimer.getAverage(); } - using JobModel = render::Task::Job::Model; + using JobModel = render::Job::Model; private: diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index 51a8e3a1de..624add87b6 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -22,7 +22,7 @@ public: Antialiasing(); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Task::Job::Model; + using JobModel = render::Job::Model; const gpu::PipelinePointer& getAntialiasingPipeline(); const gpu::PipelinePointer& getBlendPipeline(); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index ef0fe512b2..7a95972c83 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -18,7 +18,7 @@ class DebugDeferredBuffer { public: - using JobModel = render::Task::Job::Model; + using JobModel = render::Job::Model; DebugDeferredBuffer(); diff --git a/libraries/render-utils/src/HitEffect.h b/libraries/render-utils/src/HitEffect.h index a83fb36693..c872ec55e4 100644 --- a/libraries/render-utils/src/HitEffect.h +++ b/libraries/render-utils/src/HitEffect.h @@ -17,7 +17,7 @@ public: HitEffect(); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Task::Job::Model; + using JobModel = render::Job::Model; const gpu::PipelinePointer& getHitEffectPipeline(); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 85f9859216..7e013f12de 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -67,7 +67,7 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo DependencyManager::get()->render(renderContext); } -void ToneMappingDeferred::configure(const Configuration& configuration) { +void ToneMappingDeferred::configure(const Config& configuration) { if (configuration.exposure >= 0) { _toneMappingEffect.setExposure(configuration.curve); } @@ -81,7 +81,7 @@ void ToneMappingDeferred::run(const SceneContextPointer& sceneContext, const Ren _toneMappingEffect.render(renderContext->getArgs()); } -RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) : Task() { +RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; // Prepare the ShapePipelines diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index da9d99243b..b718d49dfd 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -22,14 +22,14 @@ class SetupDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Task::Job::Model; + using JobModel = render::Job::Model; }; class PrepareDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Task::Job::Model; + using JobModel = render::Job::Model; }; @@ -37,25 +37,28 @@ class RenderDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Task::Job::Model; + using JobModel = render::Job::Model; }; -class ToneMappingConfiguration : public QObject { + +class ToneMappingConfig : public render::Job::Config { Q_OBJECT public: - Q_PROPERTY(float exposure MEMBER exposure); - Q_PROPERTY(int curve MEMBER curve); - float exposure; - int curve; + Q_PROPERTY(float exposure MEMBER exposure NOTIFY dirty); + Q_PROPERTY(int curve MEMBER curve NOTIFY dirty); + float exposure{ 0.0 }; + int curve{ 3 }; +signals: + void dirty(); }; class ToneMappingDeferred { public: - using Configuration = ToneMappingConfiguration; - void configure(const Configuration&); - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + using Config = ToneMappingConfig; + using JobModel = render::Job::Model; - using JobModel = render::Task::Job::Model; + void configure(const Config&); + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); ToneMappingEffect _toneMappingEffect; }; @@ -65,7 +68,7 @@ public: DrawOpaqueDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); - using JobModel = render::Task::Job::ModelI; + using JobModel = render::Job::ModelI; protected: render::ShapePlumberPointer _shapePlumber; @@ -76,7 +79,7 @@ public: DrawTransparentDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); - using JobModel = render::Task::Job::ModelI; + using JobModel = render::Job::ModelI; protected: render::ShapePlumberPointer _shapePlumber; @@ -88,7 +91,7 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Task::Job::Model; + using JobModel = render::Job::Model; protected: static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable @@ -98,7 +101,7 @@ class DrawBackgroundDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Task::Job::Model; + using JobModel = render::Job::Model; }; class DrawOverlay3D { @@ -108,7 +111,7 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Task::Job::Model; + using JobModel = render::Job::Model; protected: static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable @@ -119,7 +122,7 @@ class Blit { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Task::Job::Model; + using JobModel = render::Job::Model; }; class RenderDeferredTask : public render::Task { @@ -128,7 +131,7 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Task::Job::Model; + using JobModel = Model; void setDrawDebugDeferredBuffer(int draw) { enableJob(_drawDebugDeferredBufferIndex, draw >= 0); } bool doDrawDebugDeferredBuffer() const { return getEnableJob(_drawDebugDeferredBufferIndex); } diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 7240fba105..8bf12d6eb7 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -78,7 +78,7 @@ void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const }); } -RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) : Task() { +RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) { cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; // Prepare the ShapePipeline diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 61f8bccb3c..64debedc65 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -25,7 +25,7 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ShapesIDsBounds& inShapes); - using JobModel = render::Task::Job::ModelI; + using JobModel = render::Job::ModelI; protected: render::ShapePlumberPointer _shapePlumber; }; @@ -36,7 +36,7 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Task::Job::Model; + using JobModel = Model; }; #endif // hifi_RenderShadowTask_h diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index c9cf16c0cb..d64b484695 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -38,7 +38,7 @@ namespace render { void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); - using JobModel = Task::Job::ModelI; + using JobModel = Job::ModelI; const gpu::PipelinePointer getDrawItemBoundsPipeline(); const gpu::PipelinePointer getDrawItemStatusPipeline(); diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 684d8bf4ea..54fd8dbe31 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -38,7 +38,7 @@ public: ProbeNumItems _probeNumItems; void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems); - using JobModel = Task::Job::ModelO; + using JobModel = Job::ModelO; }; template @@ -54,7 +54,7 @@ public: render::cullItems(renderContext, _cullFunctor, details, inItems, outItems); } - using JobModel = Task::Job::ModelIO, ItemIDsBounds, ItemIDsBounds>; + using JobModel = Job::ModelIO, ItemIDsBounds, ItemIDsBounds>; protected: CullFunctor _cullFunctor; @@ -66,14 +66,14 @@ public: DepthSortItems(bool frontToBack = true) : _frontToBack(frontToBack) {} void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); - using JobModel = Task::Job::ModelIO; + using JobModel = Job::ModelIO; }; class DrawLight { public: DrawLight(CullFunctor cullFunctor) : _cullFunctor{ cullFunctor } {} void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); - using JobModel = Task::Job::Model; + using JobModel = Job::Model; protected: CullFunctor _cullFunctor; @@ -82,7 +82,7 @@ protected: class PipelineSortShapes { public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ShapesIDsBounds& outShapes); - using JobModel = Task::Job::ModelIO; + using JobModel = Job::ModelIO; }; class DepthSortShapes { @@ -91,7 +91,7 @@ public: DepthSortShapes(bool frontToBack = true) : _frontToBack(frontToBack) {} void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapesIDsBounds& inShapes, ShapesIDsBounds& outShapes); - using JobModel = Task::Job::ModelIO; + using JobModel = Job::ModelIO; }; } diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index a9c09b6a38..434674e198 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -19,6 +19,9 @@ #include "gpu/Batch.h" #include +// Prepare Qt for auto configurations +Q_DECLARE_METATYPE(std::shared_ptr) + namespace render { // A varying piece of data, to be used as Job/Task I/O @@ -50,14 +53,18 @@ protected: std::shared_ptr _concept; }; -class NoConfiguration : public QObject { +class JobConfig : public QObject { + Q_OBJECT +}; + +class DefaultJobConfig: public JobConfig { Q_OBJECT }; template void jobConfigure(T& model, const C& configuration) { model.configure(configuration); } -template void jobConfigure(T&, const NoConfiguration&) { +template void jobConfigure(T&, const DefaultJobConfig&) { } // FIXME: In c++17, use default classes of nullptr_t to combine these @@ -76,12 +83,13 @@ template void jobRunIO(T& model, const SceneContextP class Job { public: - using QObjectPointer = std::shared_ptr; + using Config = JobConfig; + using QConfig = std::shared_ptr; // The guts of a job class Concept { public: - Concept() = default; + Concept(QConfig config) : _config(config) {} virtual ~Concept() = default; bool isEnabled() const { return _isEnabled; } @@ -89,32 +97,31 @@ public: virtual const Varying getInput() const { return Varying(); } virtual const Varying getOutput() const { return Varying(); } - virtual const QObjectPointer getConfiguration() = 0; - virtual void setConfiguration(const QObjectPointer& configuration) = 0; + + virtual QConfig& getConfiguration() { return _config; } + virtual void applyConfiguration() = 0; + virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; protected: + QConfig _config; bool _isEnabled = true; }; using ConceptPointer = std::shared_ptr; - template class Model : public Concept { + template class Model : public Concept { public: using Data = T; - using ConfigurationPointer = std::shared_ptr; + using Config = C; Data _data; - ConfigurationPointer _configuration; - Model() : _configuration{ std::make_shared() } {} - Model(Data data) : _data(data), _configuration{ std::make_shared() } { - jobConfigure(_data, *_configuration); + Model(Data data = Data()) : _data(data), Concept(std::make_shared()) { + applyConfiguration(); } - const QObjectPointer getConfiguration() { return _configuration; } - void setConfiguration(const QObjectPointer& configuration) { - _configuration = std::static_pointer_cast(configuration); - jobConfigure(_data, *_configuration); + void applyConfiguration() { + jobConfigure(_data, *std::static_pointer_cast(_config)); } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -124,25 +131,23 @@ public: } }; - template class ModelI : public Concept { + template class ModelI : public Concept { public: using Data = T; - using ConfigurationPointer = std::shared_ptr; + using Config = C; using Input = I; Data _data; - ConfigurationPointer _configuration; Varying _input; const Varying getInput() const { return _input; } - ModelI(const Varying& input, Data data = Data()) : _data(data), _input(input) {} - ModelI(Data data) : _data(data) {} + ModelI(const Varying& input, Data data = Data()) : _input(input), _data(data), Concept(std::make_shared()) { + applyConfiguration(); + } - const QObjectPointer getConfiguration() { return _configuration; } - void setConfiguration(const QObjectPointer& configuration) { - _configuration = std::static_pointer_cast(configuration); - jobConfigure(_data, *_configuration); + void applyConfiguration() { + jobConfigure(_data, *std::static_pointer_cast(_config)); } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -152,25 +157,23 @@ public: } }; - template class ModelO : public Concept { + template class ModelO : public Concept { public: using Data = T; - using ConfigurationPointer = std::shared_ptr; + using Config = C; using Output = O; Data _data; - ConfigurationPointer _configuration; Varying _output; const Varying getOutput() const { return _output; } - ModelO(Data data) : _data(data), _output(Output()) {} - ModelO() : _output(Output()) {} + ModelO(Data data = Data()) : _data(data), _output(Output()), Concept(std::make_shared()) { + applyConfiguration(); + } - const QObjectPointer getConfiguration() { return _configuration; } - void setConfiguration(const QObjectPointer& configuration) { - _configuration = std::static_pointer_cast(configuration); - jobConfigure(_data, *_configuration); + void applyConfiguration() { + jobConfigure(_data, *std::static_pointer_cast(_config)); } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -180,28 +183,26 @@ public: } }; - template class ModelIO : public Concept { + template class ModelIO : public Concept { public: using Data = T; - using ConfigurationPointer = std::shared_ptr; + using Config = C; using Input = I; using Output = O; Data _data; - ConfigurationPointer _configuration; Varying _input; Varying _output; const Varying getInput() const { return _input; } const Varying getOutput() const { return _output; } - ModelIO(const Varying& input, Data data = Data()) : _data(data), _input(input), _output(Output()) {} - ModelIO(Data data) : _data(data), _output(Output()) {} + ModelIO(const Varying& input, Data data = Data()) : _data(data), _input(input), _output(Output()), Concept(std::make_shared()) { + applyConfiguration(); + } - const QObjectPointer getConfiguration() { return _configuration; } - void setConfiguration(const QObjectPointer& configuration) { - _configuration = std::static_pointer_cast(configuration); - jobConfigure(_data, *_configuration); + void applyConfiguration() { + jobConfigure(_data, *std::static_pointer_cast(_config)); } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -211,7 +212,6 @@ public: } }; - Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} bool isEnabled() const { return _concept->isEnabled(); } @@ -219,8 +219,8 @@ public: const Varying getInput() const { return _concept->getInput(); } const Varying getOutput() const { return _concept->getOutput(); } - const QObjectPointer getConfiguration() const { return _concept->getConfiguration(); } - void setConfiguration(const QObjectPointer& configuration) { return _concept->setConfiguration(configuration); } + QConfig& getConfiguration() const { return _concept->getConfiguration(); } + void applyConfiguration() { return _concept->applyConfiguration(); } template T& edit() { auto concept = std::static_pointer_cast(_concept); @@ -235,37 +235,85 @@ public: _concept->run(sceneContext, renderContext); } - class Container { - public: - using Job = Job; - using Jobs = std::vector; - - Container() = default; - virtual ~Container() = default; - - // Queue a new job to the container; returns the job's output - template const Varying addJob(std::string name, A&&... args) { - _jobs.emplace_back(name, std::make_shared(std::forward(args)...)); - return _jobs.back().getOutput(); - } - - void enableJob(size_t jobIndex, bool enable = true) { _jobs.at(jobIndex).setEnabled(enable); } - bool getEnableJob(size_t jobIndex) const { return _jobs.at(jobIndex).isEnabled(); } - protected: - Jobs _jobs; - }; - -protected: - friend class Container; - ConceptPointer _concept; std::string _name = ""; }; -// Define our vernacular: Engine->Tasks->Jobs -using Task = Job::Container; -using TaskPointer = std::shared_ptr; -using Tasks = std::vector; + +class Task; + +class TaskConfig : public QObject { + Q_OBJECT +public: + TaskConfig(Task& task) : _task{ task } {} +public slots: + void refresh() { + qDebug() << "ATTEMPTING REFRESH"; + //_task.configure(*this); + } +private: + Task& _task; +}; + +// A task is a specialized job to run a collection of other jobs +// It is defined with JobModel = Task::Model +class Task { +public: + using QConfig = Job::QConfig; + + template class Model : public Job::Concept { + public: + using Data = T; + using Config = TaskConfig; + + Data _data; + + Model(Data data = Data()) : _data(data), Concept(std::make_shared()) { + _config = _data._config; + } + + void applyConfiguration() { + jobConfigure(_data, *_config); + } + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRun(_data, sceneContext, renderContext); + } + } + }; + + using Jobs = std::vector; + + Task() : _config{ std::make_shared(*this) } {} + + // Queue a new job to the container; returns the job's output + template const Varying addJob(std::string name, A&&... args) { + _jobs.emplace_back(name, std::make_shared(std::forward(args)...)); + QConfig config = _jobs.back().getConfiguration(); + config->setParent(_config.get()); + config->setObjectName(name.c_str()); + QObject::connect( + config.get(), SIGNAL(dirty()), + _config.get(), SLOT(refresh())); + return _jobs.back().getOutput(); + } + + QConfig getConfiguration() { return _config; } + void configure(const QObject& configuration) { + for (auto& job : _jobs) { + job.applyConfiguration(); + } + } + void enableJob(size_t jobIndex, bool enable = true) { _jobs.at(jobIndex).setEnabled(enable); } + bool getEnableJob(size_t jobIndex) const { return _jobs.at(jobIndex).isEnabled(); } + +protected: + template friend class Model; + + QConfig _config; + Jobs _jobs; +}; } From fa2782e113e57d50ec3a887f849a155e1627b834 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 09:58:12 -0800 Subject: [PATCH 012/145] Add Task implementation --- libraries/render/src/render/Task.cpp | 320 +++++++++++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 libraries/render/src/render/Task.cpp diff --git a/libraries/render/src/render/Task.cpp b/libraries/render/src/render/Task.cpp new file mode 100644 index 0000000000..434674e198 --- /dev/null +++ b/libraries/render/src/render/Task.cpp @@ -0,0 +1,320 @@ +// +// Task.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_Task_h +#define hifi_render_Task_h + +#include // QObject + +#include "Context.h" + +#include "gpu/Batch.h" +#include + +// Prepare Qt for auto configurations +Q_DECLARE_METATYPE(std::shared_ptr) + +namespace render { + +// A varying piece of data, to be used as Job/Task I/O +// TODO: Task IO +class Varying { +public: + Varying() {} + Varying(const Varying& var) : _concept(var._concept) {} + template Varying(const T& data) : _concept(std::make_shared>(data)) {} + + template T& edit() { return std::static_pointer_cast>(_concept)->_data; } + template const T& get() { return std::static_pointer_cast>(_concept)->_data; } + +protected: + class Concept { + public: + virtual ~Concept() = default; + }; + template class Model : public Concept { + public: + using Data = T; + + Model(const Data& data) : _data(data) {} + virtual ~Model() = default; + + Data _data; + }; + + std::shared_ptr _concept; +}; + +class JobConfig : public QObject { + Q_OBJECT +}; + +class DefaultJobConfig: public JobConfig { + Q_OBJECT +}; + +template void jobConfigure(T& model, const C& configuration) { + model.configure(configuration); +} +template void jobConfigure(T&, const DefaultJobConfig&) { +} + +// FIXME: In c++17, use default classes of nullptr_t to combine these +template void jobRun(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + model.run(sceneContext, renderContext); +} +template void jobRunI(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) { + model.run(sceneContext, renderContext, input); +} +template void jobRunO(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) { + model.run(sceneContext, renderContext, output); +} +template void jobRunIO(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) { + model.run(sceneContext, renderContext, input, output); +} + +class Job { +public: + using Config = JobConfig; + using QConfig = std::shared_ptr; + + // The guts of a job + class Concept { + public: + Concept(QConfig config) : _config(config) {} + virtual ~Concept() = default; + + bool isEnabled() const { return _isEnabled; } + void setEnabled(bool isEnabled) { _isEnabled = isEnabled; } + + virtual const Varying getInput() const { return Varying(); } + virtual const Varying getOutput() const { return Varying(); } + + virtual QConfig& getConfiguration() { return _config; } + virtual void applyConfiguration() = 0; + + virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; + + protected: + QConfig _config; + bool _isEnabled = true; + }; + using ConceptPointer = std::shared_ptr; + + template class Model : public Concept { + public: + using Data = T; + using Config = C; + + Data _data; + + Model(Data data = Data()) : _data(data), Concept(std::make_shared()) { + applyConfiguration(); + } + + void applyConfiguration() { + jobConfigure(_data, *std::static_pointer_cast(_config)); + } + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRun(_data, sceneContext, renderContext); + } + } + }; + + template class ModelI : public Concept { + public: + using Data = T; + using Config = C; + using Input = I; + + Data _data; + Varying _input; + + const Varying getInput() const { return _input; } + + ModelI(const Varying& input, Data data = Data()) : _input(input), _data(data), Concept(std::make_shared()) { + applyConfiguration(); + } + + void applyConfiguration() { + jobConfigure(_data, *std::static_pointer_cast(_config)); + } + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRunI(_data, sceneContext, renderContext, _input.get()); + } + } + }; + + template class ModelO : public Concept { + public: + using Data = T; + using Config = C; + using Output = O; + + Data _data; + Varying _output; + + const Varying getOutput() const { return _output; } + + ModelO(Data data = Data()) : _data(data), _output(Output()), Concept(std::make_shared()) { + applyConfiguration(); + } + + void applyConfiguration() { + jobConfigure(_data, *std::static_pointer_cast(_config)); + } + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRunO(_data, sceneContext, renderContext, _output.edit()); + } + } + }; + + template class ModelIO : public Concept { + public: + using Data = T; + using Config = C; + using Input = I; + using Output = O; + + Data _data; + Varying _input; + Varying _output; + + const Varying getInput() const { return _input; } + const Varying getOutput() const { return _output; } + + ModelIO(const Varying& input, Data data = Data()) : _data(data), _input(input), _output(Output()), Concept(std::make_shared()) { + applyConfiguration(); + } + + void applyConfiguration() { + jobConfigure(_data, *std::static_pointer_cast(_config)); + } + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); + } + } + }; + + Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} + + bool isEnabled() const { return _concept->isEnabled(); } + void setEnabled(bool isEnabled) { _concept->setEnabled(isEnabled); } + + const Varying getInput() const { return _concept->getInput(); } + const Varying getOutput() const { return _concept->getOutput(); } + QConfig& 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; + } + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + PerformanceTimer perfTimer(_name.c_str()); + PROFILE_RANGE(_name.c_str()); + + _concept->run(sceneContext, renderContext); + } + + protected: + ConceptPointer _concept; + std::string _name = ""; +}; + +class Task; + +class TaskConfig : public QObject { + Q_OBJECT +public: + TaskConfig(Task& task) : _task{ task } {} +public slots: + void refresh() { + qDebug() << "ATTEMPTING REFRESH"; + //_task.configure(*this); + } +private: + Task& _task; +}; + +// A task is a specialized job to run a collection of other jobs +// It is defined with JobModel = Task::Model +class Task { +public: + using QConfig = Job::QConfig; + + template class Model : public Job::Concept { + public: + using Data = T; + using Config = TaskConfig; + + Data _data; + + Model(Data data = Data()) : _data(data), Concept(std::make_shared()) { + _config = _data._config; + } + + void applyConfiguration() { + jobConfigure(_data, *_config); + } + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRun(_data, sceneContext, renderContext); + } + } + }; + + using Jobs = std::vector; + + Task() : _config{ std::make_shared(*this) } {} + + // Queue a new job to the container; returns the job's output + template const Varying addJob(std::string name, A&&... args) { + _jobs.emplace_back(name, std::make_shared(std::forward(args)...)); + QConfig config = _jobs.back().getConfiguration(); + config->setParent(_config.get()); + config->setObjectName(name.c_str()); + QObject::connect( + config.get(), SIGNAL(dirty()), + _config.get(), SLOT(refresh())); + return _jobs.back().getOutput(); + } + + QConfig getConfiguration() { return _config; } + void configure(const QObject& configuration) { + for (auto& job : _jobs) { + job.applyConfiguration(); + } + } + void enableJob(size_t jobIndex, bool enable = true) { _jobs.at(jobIndex).setEnabled(enable); } + bool getEnableJob(size_t jobIndex) const { return _jobs.at(jobIndex).isEnabled(); } + +protected: + template friend class Model; + + QConfig _config; + Jobs _jobs; +}; + +} + +#endif // hifi_render_Task_h From 0188a9384a132993f291dd5a3e2017f94f4ca99a Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 10:32:38 -0800 Subject: [PATCH 013/145] Add enabled to Job::Config --- libraries/render/src/render/Task.cpp | 309 +-------------------------- libraries/render/src/render/Task.h | 43 ++-- 2 files changed, 25 insertions(+), 327 deletions(-) diff --git a/libraries/render/src/render/Task.cpp b/libraries/render/src/render/Task.cpp index 434674e198..21cb1e5be1 100644 --- a/libraries/render/src/render/Task.cpp +++ b/libraries/render/src/render/Task.cpp @@ -1,16 +1,15 @@ // -// Task.h +// Task.cpp // render/src/render // -// Created by Zach Pomerantz on 1/6/2015. -// Copyright 2015 High Fidelity, Inc. +// Created by Zach Pomerantz on 1/21/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 "Task.h" #include // QObject @@ -19,302 +18,8 @@ #include "gpu/Batch.h" #include -// Prepare Qt for auto configurations -Q_DECLARE_METATYPE(std::shared_ptr) +using namespace render; -namespace render { - -// A varying piece of data, to be used as Job/Task I/O -// TODO: Task IO -class Varying { -public: - Varying() {} - Varying(const Varying& var) : _concept(var._concept) {} - template Varying(const T& data) : _concept(std::make_shared>(data)) {} - - template T& edit() { return std::static_pointer_cast>(_concept)->_data; } - template const T& get() { return std::static_pointer_cast>(_concept)->_data; } - -protected: - class Concept { - public: - virtual ~Concept() = default; - }; - template class Model : public Concept { - public: - using Data = T; - - Model(const Data& data) : _data(data) {} - virtual ~Model() = default; - - Data _data; - }; - - std::shared_ptr _concept; -}; - -class JobConfig : public QObject { - Q_OBJECT -}; - -class DefaultJobConfig: public JobConfig { - Q_OBJECT -}; - -template void jobConfigure(T& model, const C& configuration) { - model.configure(configuration); +void TaskConfig::refresh() { + _task.configure(*this); } -template void jobConfigure(T&, const DefaultJobConfig&) { -} - -// FIXME: In c++17, use default classes of nullptr_t to combine these -template void jobRun(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - model.run(sceneContext, renderContext); -} -template void jobRunI(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) { - model.run(sceneContext, renderContext, input); -} -template void jobRunO(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) { - model.run(sceneContext, renderContext, output); -} -template void jobRunIO(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) { - model.run(sceneContext, renderContext, input, output); -} - -class Job { -public: - using Config = JobConfig; - using QConfig = std::shared_ptr; - - // The guts of a job - class Concept { - public: - Concept(QConfig config) : _config(config) {} - virtual ~Concept() = default; - - bool isEnabled() const { return _isEnabled; } - void setEnabled(bool isEnabled) { _isEnabled = isEnabled; } - - virtual const Varying getInput() const { return Varying(); } - virtual const Varying getOutput() const { return Varying(); } - - virtual QConfig& getConfiguration() { return _config; } - virtual void applyConfiguration() = 0; - - virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; - - protected: - QConfig _config; - bool _isEnabled = true; - }; - using ConceptPointer = std::shared_ptr; - - template class Model : public Concept { - public: - using Data = T; - using Config = C; - - Data _data; - - Model(Data data = Data()) : _data(data), Concept(std::make_shared()) { - applyConfiguration(); - } - - void applyConfiguration() { - jobConfigure(_data, *std::static_pointer_cast(_config)); - } - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRun(_data, sceneContext, renderContext); - } - } - }; - - template class ModelI : public Concept { - public: - using Data = T; - using Config = C; - using Input = I; - - Data _data; - Varying _input; - - const Varying getInput() const { return _input; } - - ModelI(const Varying& input, Data data = Data()) : _input(input), _data(data), Concept(std::make_shared()) { - applyConfiguration(); - } - - void applyConfiguration() { - jobConfigure(_data, *std::static_pointer_cast(_config)); - } - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRunI(_data, sceneContext, renderContext, _input.get()); - } - } - }; - - template class ModelO : public Concept { - public: - using Data = T; - using Config = C; - using Output = O; - - Data _data; - Varying _output; - - const Varying getOutput() const { return _output; } - - ModelO(Data data = Data()) : _data(data), _output(Output()), Concept(std::make_shared()) { - applyConfiguration(); - } - - void applyConfiguration() { - jobConfigure(_data, *std::static_pointer_cast(_config)); - } - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRunO(_data, sceneContext, renderContext, _output.edit()); - } - } - }; - - template class ModelIO : public Concept { - public: - using Data = T; - using Config = C; - using Input = I; - using Output = O; - - Data _data; - Varying _input; - Varying _output; - - const Varying getInput() const { return _input; } - const Varying getOutput() const { return _output; } - - ModelIO(const Varying& input, Data data = Data()) : _data(data), _input(input), _output(Output()), Concept(std::make_shared()) { - applyConfiguration(); - } - - void applyConfiguration() { - jobConfigure(_data, *std::static_pointer_cast(_config)); - } - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); - } - } - }; - - Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} - - bool isEnabled() const { return _concept->isEnabled(); } - void setEnabled(bool isEnabled) { _concept->setEnabled(isEnabled); } - - const Varying getInput() const { return _concept->getInput(); } - const Varying getOutput() const { return _concept->getOutput(); } - QConfig& 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; - } - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - PerformanceTimer perfTimer(_name.c_str()); - PROFILE_RANGE(_name.c_str()); - - _concept->run(sceneContext, renderContext); - } - - protected: - ConceptPointer _concept; - std::string _name = ""; -}; - -class Task; - -class TaskConfig : public QObject { - Q_OBJECT -public: - TaskConfig(Task& task) : _task{ task } {} -public slots: - void refresh() { - qDebug() << "ATTEMPTING REFRESH"; - //_task.configure(*this); - } -private: - Task& _task; -}; - -// A task is a specialized job to run a collection of other jobs -// It is defined with JobModel = Task::Model -class Task { -public: - using QConfig = Job::QConfig; - - template class Model : public Job::Concept { - public: - using Data = T; - using Config = TaskConfig; - - Data _data; - - Model(Data data = Data()) : _data(data), Concept(std::make_shared()) { - _config = _data._config; - } - - void applyConfiguration() { - jobConfigure(_data, *_config); - } - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRun(_data, sceneContext, renderContext); - } - } - }; - - using Jobs = std::vector; - - Task() : _config{ std::make_shared(*this) } {} - - // Queue a new job to the container; returns the job's output - template const Varying addJob(std::string name, A&&... args) { - _jobs.emplace_back(name, std::make_shared(std::forward(args)...)); - QConfig config = _jobs.back().getConfiguration(); - config->setParent(_config.get()); - config->setObjectName(name.c_str()); - QObject::connect( - config.get(), SIGNAL(dirty()), - _config.get(), SLOT(refresh())); - return _jobs.back().getOutput(); - } - - QConfig getConfiguration() { return _config; } - void configure(const QObject& configuration) { - for (auto& job : _jobs) { - job.applyConfiguration(); - } - } - void enableJob(size_t jobIndex, bool enable = true) { _jobs.at(jobIndex).setEnabled(enable); } - bool getEnableJob(size_t jobIndex) const { return _jobs.at(jobIndex).isEnabled(); } - -protected: - template friend class Model; - - QConfig _config; - Jobs _jobs; -}; - -} - -#endif // hifi_render_Task_h diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 434674e198..f592ad1b2b 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -2,8 +2,8 @@ // Task.h // render/src/render // -// Created by Zach Pomerantz on 1/6/2015. -// Copyright 2015 High Fidelity, Inc. +// 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 @@ -55,16 +55,17 @@ protected: class JobConfig : public QObject { Q_OBJECT -}; - -class DefaultJobConfig: public JobConfig { - Q_OBJECT +public: + Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty) + bool enabled; +signals: + void dirty(); }; template void jobConfigure(T& model, const C& configuration) { model.configure(configuration); } -template void jobConfigure(T&, const DefaultJobConfig&) { +template void jobConfigure(T&, const JobConfig&) { } // FIXME: In c++17, use default classes of nullptr_t to combine these @@ -109,10 +110,9 @@ public: }; using ConceptPointer = std::shared_ptr; - template class Model : public Concept { + template class Model : public Concept { public: using Data = T; - using Config = C; Data _data; @@ -131,10 +131,9 @@ public: } }; - template class ModelI : public Concept { + template class ModelI : public Concept { public: using Data = T; - using Config = C; using Input = I; Data _data; @@ -157,10 +156,9 @@ public: } }; - template class ModelO : public Concept { + template class ModelO : public Concept { public: using Data = T; - using Config = C; using Output = O; Data _data; @@ -183,10 +181,9 @@ public: } }; - template class ModelIO : public Concept { + template class ModelIO : public Concept { public: using Data = T; - using Config = C; using Input = I; using Output = O; @@ -242,15 +239,12 @@ public: class Task; -class TaskConfig : public QObject { +class TaskConfig : public Job::Config { Q_OBJECT public: TaskConfig(Task& task) : _task{ task } {} public slots: - void refresh() { - qDebug() << "ATTEMPTING REFRESH"; - //_task.configure(*this); - } + void refresh(); private: Task& _task; }; @@ -259,15 +253,16 @@ private: // It is defined with JobModel = Task::Model class Task { public: + using Config = TaskConfig; using QConfig = Job::QConfig; template class Model : public Job::Concept { public: using Data = T; - using Config = TaskConfig; Data _data; + // The _config is unused; the model delegates to its data's _config Model(Data data = Data()) : _data(data), Concept(std::make_shared()) { _config = _data._config; } @@ -285,7 +280,7 @@ public: using Jobs = std::vector; - Task() : _config{ std::make_shared(*this) } {} + Task() : _config{ std::make_shared(*this) } {} // Queue a new job to the container; returns the job's output template const Varying addJob(std::string name, A&&... args) { @@ -293,9 +288,7 @@ public: QConfig config = _jobs.back().getConfiguration(); config->setParent(_config.get()); config->setObjectName(name.c_str()); - QObject::connect( - config.get(), SIGNAL(dirty()), - _config.get(), SLOT(refresh())); + QObject::connect(config.get(), SIGNAL(dirty()), _config.get(), SLOT(refresh())); return _jobs.back().getOutput(); } From b70108bb9a8d45a7f69b027da467d99ec9d85852 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 12:02:39 -0800 Subject: [PATCH 014/145] Working demo --- .../render-utils/src/DebugDeferredBuffer.h | 10 +++++++- libraries/render/src/render/Task.cpp | 2 +- libraries/render/src/render/Task.h | 23 +++++++++++++------ 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index 7a95972c83..f5c2d3f8a1 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -16,12 +16,20 @@ #include +class DebugDeferredBufferConfig : public render::Job::Config { + Q_OBJECT +public: + DebugDeferredBufferConfig() : render::Job::Config(false) {} +}; + class DebugDeferredBuffer { public: - using JobModel = render::Job::Model; + using Config = DebugDeferredBufferConfig; + using JobModel = render::Job::Model; DebugDeferredBuffer(); + void configure(const Config&) {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); private: diff --git a/libraries/render/src/render/Task.cpp b/libraries/render/src/render/Task.cpp index 21cb1e5be1..c1c607c587 100644 --- a/libraries/render/src/render/Task.cpp +++ b/libraries/render/src/render/Task.cpp @@ -21,5 +21,5 @@ using namespace render; void TaskConfig::refresh() { - _task.configure(*this); + _task->configure(*this); } diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index f592ad1b2b..b608ca987a 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -56,10 +56,11 @@ protected: class JobConfig : public QObject { Q_OBJECT public: - Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty) + JobConfig() : enabled{ true } {} + JobConfig(bool enabled) : enabled{ enabled } {} + + Q_PROPERTY(bool enabled MEMBER enabled) bool enabled; -signals: - void dirty(); }; template void jobConfigure(T& model, const C& configuration) { @@ -125,7 +126,7 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { + if (std::static_pointer_cast(_config)->enabled) { jobRun(_data, sceneContext, renderContext); } } @@ -242,11 +243,11 @@ class Task; class TaskConfig : public Job::Config { Q_OBJECT public: - TaskConfig(Task& task) : _task{ task } {} + void init(Task* task) { _task = task; } public slots: void refresh(); private: - Task& _task; + Task* _task; }; // A task is a specialized job to run a collection of other jobs @@ -260,6 +261,7 @@ public: public: using Data = T; + // TODO: Make Data a shared_ptr, and give Config a weak_ptr Data _data; // The _config is unused; the model delegates to its data's _config @@ -267,6 +269,12 @@ public: _config = _data._config; } + virtual QConfig& getConfiguration() { + // Hook up the configuration if it is to be used + std::static_pointer_cast(_config)->init(&_data); + return _config; + } + void applyConfiguration() { jobConfigure(_data, *_config); } @@ -280,7 +288,7 @@ public: using Jobs = std::vector; - Task() : _config{ std::make_shared(*this) } {} + Task() : _config{ std::make_shared() } {} // Queue a new job to the container; returns the job's output template const Varying addJob(std::string name, A&&... args) { @@ -293,6 +301,7 @@ public: } QConfig getConfiguration() { return _config; } + void configure(const QObject& configuration) { for (auto& job : _jobs) { job.applyConfiguration(); From 75cddec6477e76cb855358d9ac55db16b69d42be Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 13:42:11 -0800 Subject: [PATCH 015/145] Add alwaysEnabled render::Job::Config --- libraries/render-utils/src/RenderDeferredTask.h | 1 + libraries/render/src/render/Task.h | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index b718d49dfd..019134903d 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -44,6 +44,7 @@ public: class ToneMappingConfig : public render::Job::Config { Q_OBJECT public: + ToneMappingConfig() : render::Job::Config(true) {} Q_PROPERTY(float exposure MEMBER exposure NOTIFY dirty); Q_PROPERTY(int curve MEMBER curve NOTIFY dirty); float exposure{ 0.0 }; diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index b608ca987a..fb417eb087 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -53,13 +53,15 @@ protected: std::shared_ptr _concept; }; +// A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled) class JobConfig : public QObject { Q_OBJECT public: - JobConfig() : enabled{ true } {} - JobConfig(bool enabled) : enabled{ enabled } {} + JobConfig() : alwaysEnabled{ true }, enabled{ true } {} + JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} Q_PROPERTY(bool enabled MEMBER enabled) + bool alwaysEnabled{ true }; bool enabled; }; @@ -126,7 +128,8 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (std::static_pointer_cast(_config)->enabled) { + std::shared_ptr& config = std::static_pointer_cast(_config); + if (config->alwaysEnabled || config->enabled) { jobRun(_data, sceneContext, renderContext); } } From 5698be54350d0acc14a5bf986ad78b967ad179e5 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 14:18:59 -0800 Subject: [PATCH 016/145] It works --- libraries/render-utils/src/HitEffect.h | 11 +++++++++-- libraries/render-utils/src/RenderDeferredTask.cpp | 4 +--- libraries/render-utils/src/RenderShadowTask.h | 11 ++++++++++- libraries/render/src/render/Task.h | 9 ++++++--- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/libraries/render-utils/src/HitEffect.h b/libraries/render-utils/src/HitEffect.h index c872ec55e4..e7b9b839c0 100644 --- a/libraries/render-utils/src/HitEffect.h +++ b/libraries/render-utils/src/HitEffect.h @@ -11,13 +11,20 @@ #include +class HitEffectConfig : public render::Job::Config { + Q_OBJECT +public: + HitEffectConfig() : render::Job::Config(false) {} +}; + class HitEffect { public: + using Config = HitEffectConfig; + using JobModel = render::Job::Model; HitEffect(); - + void configure(const Config&) {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Job::Model; const gpu::PipelinePointer& getHitEffectPipeline(); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 7e013f12de..079b36be67 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -69,7 +69,7 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo void ToneMappingDeferred::configure(const Config& configuration) { if (configuration.exposure >= 0) { - _toneMappingEffect.setExposure(configuration.curve); + _toneMappingEffect.setExposure(configuration.exposure); } if (configuration.curve >= 0) { _toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)configuration.curve); @@ -197,8 +197,6 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend } setAntialiasingStatus(renderContext->getFxaaStatus()); - setToneMappingExposure(renderContext->getTone().exposure); - setToneMappingToneCurve(renderContext->getTone().toneCurve); // TODO: Allow runtime manipulation of culling ShouldRenderFunctor // TODO: For now, lighting is controlled through a singleton, so it is distinct diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 64debedc65..ed79c4e1fb 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -19,13 +19,22 @@ class ViewFrustum; +class RenderShadowMapConfig : public render::Job::Config { + Q_OBJECT +public: + RenderShadowMapConfig() : render::Job::Config(false) {} +}; + class RenderShadowMap { public: + using Config = RenderShadowMapConfig; + using JobModel = render::Job::ModelI; + RenderShadowMap(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + void configure(const Config&) {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ShapesIDsBounds& inShapes); - using JobModel = render::Job::ModelI; protected: render::ShapePlumberPointer _shapePlumber; }; diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index fb417eb087..a55d043299 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -154,7 +154,8 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { + std::shared_ptr& config = std::static_pointer_cast(_config); + if (config->alwaysEnabled || config->enabled) { jobRunI(_data, sceneContext, renderContext, _input.get()); } } @@ -179,7 +180,8 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { + std::shared_ptr& config = std::static_pointer_cast(_config); + if (config->alwaysEnabled || config->enabled) { jobRunO(_data, sceneContext, renderContext, _output.edit()); } } @@ -207,7 +209,8 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { + std::shared_ptr& config = std::static_pointer_cast(_config); + if (config->alwaysEnabled || config->enabled) { jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); } } From c903fc47392ca743e24dede1da9c3e968e25557f Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 14:31:58 -0800 Subject: [PATCH 017/145] Pass JobConfig to jobs --- libraries/render/src/render/Context.h | 3 +++ libraries/render/src/render/Task.h | 20 ++++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/libraries/render/src/render/Context.h b/libraries/render/src/render/Context.h index 33c4c13a4c..b2ba7614db 100644 --- a/libraries/render/src/render/Context.h +++ b/libraries/render/src/render/Context.h @@ -28,6 +28,8 @@ using SceneContextPointer = std::shared_ptr; const int showDisplayStatusFlag = 1; const int showNetworkStatusFlag = 2; +class JobConfig; + class RenderContext { public: class ItemsConfig { @@ -107,6 +109,7 @@ public: int _deferredDebugMode; glm::vec4 _deferredDebugSize; + std::shared_ptr jobConfig{ nullptr }; protected: RenderArgs* _args; diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index a55d043299..fe49f2ff6f 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -128,10 +128,11 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - std::shared_ptr& config = std::static_pointer_cast(_config); - if (config->alwaysEnabled || config->enabled) { + renderContext->jobConfig = std::static_pointer_cast(_config); + if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { jobRun(_data, sceneContext, renderContext); } + renderContext->jobConfig.reset(); } }; @@ -154,10 +155,11 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - std::shared_ptr& config = std::static_pointer_cast(_config); - if (config->alwaysEnabled || config->enabled) { + renderContext->jobConfig = std::static_pointer_cast(_config); + if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { jobRunI(_data, sceneContext, renderContext, _input.get()); } + renderContext->jobConfig.reset(); } }; @@ -180,10 +182,11 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - std::shared_ptr& config = std::static_pointer_cast(_config); - if (config->alwaysEnabled || config->enabled) { + renderContext->jobConfig = std::static_pointer_cast(_config); + if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { jobRunO(_data, sceneContext, renderContext, _output.edit()); } + renderContext->jobConfig.reset(); } }; @@ -209,10 +212,11 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - std::shared_ptr& config = std::static_pointer_cast(_config); - if (config->alwaysEnabled || config->enabled) { + renderContext->jobConfig = std::static_pointer_cast(_config); + if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); } + renderContext->jobConfig.reset(); } }; From adc9d2ea07caeeb080c9233639feb16eb18830e4 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 14:44:46 -0800 Subject: [PATCH 018/145] Add Job::Config to FetchItems --- .../render-utils/src/RenderDeferredTask.cpp | 10 ++---- libraries/render/src/render/DrawTask.cpp | 4 +-- libraries/render/src/render/DrawTask.h | 32 ++++++++++++------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 079b36be67..96b4a423d5 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -89,19 +89,13 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { initDeferredPipelines(*shapePlumber); // CPU: Fetch the renderOpaques - auto fetchedOpaques = addJob("FetchOpaque", FetchItems([](const RenderContextPointer& context, int count) { - context->getItemsConfig().opaque.numFeed = count; - })); + auto fetchedOpaques = addJob("FetchOpaque"); auto culledOpaques = addJob>("CullOpaque", fetchedOpaques, cullFunctor); auto opaques = addJob("DepthSortOpaque", culledOpaques); // CPU only, create the list of renderedTransparents items auto fetchedTransparents = addJob("FetchTransparent", FetchItems( - ItemFilter::Builder::transparentShape().withoutLayered(), - [](const RenderContextPointer& context, int count) { - context->getItemsConfig().transparent.numFeed = count; - } - )); + ItemFilter::Builder::transparentShape().withoutLayered())); auto culledTransparents = addJob>("CullTransparent", fetchedTransparents, cullFunctor); auto transparents = addJob("DepthSortTransparent", culledTransparents, DepthSortItems(false)); diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index ed35519b9d..d052221d97 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -177,9 +177,7 @@ void FetchItems::run(const SceneContextPointer& sceneContext, const RenderContex } } - if (_probeNumItems) { - _probeNumItems(renderContext, (int)outItems.size()); - } + std::static_pointer_cast(renderContext->jobConfig)->numItems = (int)outItems.size(); } void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 54fd8dbe31..eef4e0ade0 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -27,21 +27,29 @@ void depthSortItems(const SceneContextPointer& sceneContext, const RenderContext void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); -class FetchItems { +class FetchItemsConfig : public Job::Config { + Q_OBJECT public: - typedef std::function ProbeNumItems; - FetchItems() {} - FetchItems(const ProbeNumItems& probe): _probeNumItems(probe) {} - FetchItems(const ItemFilter& filter, const ProbeNumItems& probe): _filter(filter), _probeNumItems(probe) {} - - ItemFilter _filter = ItemFilter::Builder::opaqueShape().withoutLayered(); - ProbeNumItems _probeNumItems; - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems); - using JobModel = Job::ModelO; + Q_PROPERTY(int numItems READ getNumItems) + int getNumItems() { return numItems; } + int numItems{ 0 }; }; -template +class FetchItems { +public: + using Config = FetchItemsConfig; + using JobModel = Job::ModelO; + + FetchItems() {} + FetchItems(const ItemFilter& filter) : _filter(filter) {} + + ItemFilter _filter{ ItemFilter::Builder::opaqueShape().withoutLayered() }; + + void configure(const Config&) {} + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems); +}; + +template class CullItems { public: CullItems(CullFunctor cullFunctor) : _cullFunctor{ cullFunctor } {} From 9064438bf0f20e801a100096b8de70c8235a57d8 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 15:16:35 -0800 Subject: [PATCH 019/145] Replace RenderScriptingInterface with dynamic Task::Config --- interface/src/Application.cpp | 20 +-- .../src/RenderScriptingInterface.cpp | 56 ------- .../src/RenderScriptingInterface.h | 140 ------------------ 3 files changed, 5 insertions(+), 211 deletions(-) delete mode 100644 libraries/render-utils/src/RenderScriptingInterface.cpp delete mode 100644 libraries/render-utils/src/RenderScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 76300edb55..d5616bb453 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -102,7 +102,6 @@ #include #include #include -#include #include #include #include @@ -363,7 +362,6 @@ bool setupEssentials(int& argc, char** argv) { #endif DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -1250,8 +1248,7 @@ void Application::initializeUi() { rootContext->setContextProperty("Paths", DependencyManager::get().data()); rootContext->setContextProperty("HMD", DependencyManager::get().data()); rootContext->setContextProperty("Scene", DependencyManager::get().data()); - rootContext->setContextProperty("Render", DependencyManager::get().data()); - // TODO: Expose Engine here + rootContext->setContextProperty("Render", _renderEngine->getConfiguration().get()); _glWidget->installEventFilter(offscreenUi.data()); offscreenUi->setMouseTranslator([=](const QPointF& pt) { @@ -3769,19 +3766,14 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se { PerformanceTimer perfTimer("EngineRun"); - auto renderInterface = DependencyManager::get(); - auto renderContext = renderInterface->getRenderContext(); - renderArgs->_viewFrustum = getDisplayViewFrustum(); - renderContext.setArgs(renderArgs); + auto renderContext = _renderEngine->getRenderContext(); + renderContext->setArgs(renderArgs); bool occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion); bool shadowStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugShadows); bool antialiasingStatus = Menu::getInstance()->isOptionChecked(MenuOption::Antialiasing); bool showOwnedStatus = Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned); - renderContext.setOptions(occlusionStatus, antialiasingStatus, showOwnedStatus, shadowStatus); - - _renderEngine->setRenderContext(renderContext); // Before the deferred pass, let's try to use the render engine myAvatar->startRenderRun(); @@ -3789,8 +3781,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se myAvatar->endRenderRun(); auto engineContext = _renderEngine->getRenderContext(); - renderInterface->setItemCounts(engineContext->getItemsConfig()); - renderInterface->setJobGPUTimes(engineContext->getAmbientOcclusion().gpuTime); + //zzmp renderInterface->setJobGPUTimes(engineContext->getAmbientOcclusion().gpuTime); } @@ -4200,8 +4191,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri scriptEngine->registerFunction("HMD", "getHUDLookAtPosition3D", HMDScriptingInterface::getHUDLookAtPosition3D, 0); scriptEngine->registerGlobalObject("Scene", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("Render", DependencyManager::get().data()); - scriptEngine->registerGlobalObject("Engine", _renderEngine->getConfiguration().get()); + scriptEngine->registerGlobalObject("Render", _renderEngine->getConfiguration().get()); scriptEngine->registerGlobalObject("ScriptDiscoveryService", DependencyManager::get().data()); } diff --git a/libraries/render-utils/src/RenderScriptingInterface.cpp b/libraries/render-utils/src/RenderScriptingInterface.cpp deleted file mode 100644 index 6b3fedd97f..0000000000 --- a/libraries/render-utils/src/RenderScriptingInterface.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// -// RenderScriptingInterface.cpp -// libraries/render-utils -// -// Created by Zach Pomerantz on 12/16/15. -// 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 -// - -#include "RenderScriptingInterface.h" - -RenderScriptingInterface::RenderScriptingInterface() {}; - -void RenderScripting::Tone::setCurve(const QString& curve) { - if (curve == QString("None")) { - toneCurve = 0; - } else if (curve == QString("Gamma22")) { - toneCurve = 1; - } else if (curve == QString("Reinhard")) { - toneCurve = 2; - } else if (curve == QString("Filmic")) { - toneCurve = 3; - } -} - -QString RenderScripting::Tone::getCurve() const { - switch (toneCurve) { - case 0: - return QString("None"); - case 1: - return QString("Gamma22"); - case 2: - return QString("Reinhard"); - case 3: - return QString("Filmic"); - default: - return QString("Filmic"); - }; -} - -render::RenderContext RenderScriptingInterface::getRenderContext() { - render::RenderContext::ItemsConfig items{ *_opaque, *_transparent, *_overlay3D }; - return render::RenderContext{ items, *_tone, *_ambientOcclusion, _drawStatus, _drawHitEffect, _deferredDebugSize, _deferredDebugMode }; -} - -void RenderScriptingInterface::setItemCounts(const render::RenderContext::ItemsConfig& items) { - _opaque->setCounts(items.opaque); - _transparent->setCounts(items.transparent); - _overlay3D->setCounts(items.overlay3D); -} - -void RenderScriptingInterface::setJobGPUTimes(double aoTime) { - _ambientOcclusion->gpuTime = aoTime; -} \ No newline at end of file diff --git a/libraries/render-utils/src/RenderScriptingInterface.h b/libraries/render-utils/src/RenderScriptingInterface.h deleted file mode 100644 index 947240fea6..0000000000 --- a/libraries/render-utils/src/RenderScriptingInterface.h +++ /dev/null @@ -1,140 +0,0 @@ -// -// RenderScriptingInterface.h -// libraries/render-utils -// -// Created by Zach Pomerantz on 12/16/15. -// 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 -// - -#ifndef hifi_RenderScriptingInterface_h -#define hifi_RenderScriptingInterface_h - -#include // QObject -#include // Dependency - -#include "render/Engine.h" - -namespace RenderScripting { - using State = render::RenderContext::ItemsConfig::State; - using Counter = render::RenderContext::ItemsConfig::Counter; - - class ItemCounter : public QObject, public Counter { - Q_OBJECT - - public: - Q_PROPERTY(int numFeed READ getNumFeed) - Q_PROPERTY(int numDrawn READ getNumDrawn) - Q_PROPERTY(int maxDrawn MEMBER maxDrawn) - - protected: - int getNumFeed() const { return numFeed; } - int getNumDrawn() const { return numDrawn; } - }; - using ItemCounterPointer = std::unique_ptr; - - class ItemState : public QObject, public State { - Q_OBJECT - - public: - Q_PROPERTY(bool render MEMBER render) - Q_PROPERTY(bool cull MEMBER cull) - Q_PROPERTY(bool sort MEMBER sort) - - Q_PROPERTY(int numFeed READ getNumFeed) - Q_PROPERTY(int numDrawn READ getNumDrawn) - Q_PROPERTY(int maxDrawn MEMBER maxDrawn) - - protected: - int getNumFeed() const { return numFeed; } - int getNumDrawn() const { return numDrawn; } - }; - using ItemStatePointer = std::unique_ptr; - - class Tone : public QObject, public render::RenderContext::Tone { - Q_OBJECT - - public: - Q_PROPERTY(float exposure MEMBER exposure) - Q_PROPERTY(QString curve READ getCurve WRITE setCurve) - - QString getCurve() const; - int getCurveValue() const { return toneCurve; } - void setCurve(const QString& curve); - }; - using TonePointer = std::unique_ptr; - - class AmbientOcclusion : public QObject, public render::RenderContext::AmbientOcclusion { - Q_OBJECT - - public: - Q_PROPERTY(int resolutionLevel MEMBER resolutionLevel) - Q_PROPERTY(float radius MEMBER radius) - Q_PROPERTY(float level MEMBER level) - Q_PROPERTY(int numSamples MEMBER numSamples) - Q_PROPERTY(float numSpiralTurns MEMBER numSpiralTurns) - Q_PROPERTY(bool ditheringEnabled MEMBER ditheringEnabled) - Q_PROPERTY(float falloffBias MEMBER falloffBias) - Q_PROPERTY(float edgeSharpness MEMBER edgeSharpness) - Q_PROPERTY(int blurRadius MEMBER blurRadius) - Q_PROPERTY(float blurDeviation MEMBER blurDeviation) - Q_PROPERTY(double gpuTime MEMBER gpuTime) - }; - using AmbientOcclusionPointer = std::unique_ptr; -}; - -class RenderScriptingInterface : public QObject, public Dependency { - Q_OBJECT - SINGLETON_DEPENDENCY - - public: - Q_PROPERTY(RenderScripting::ItemState* opaque READ getOpaque) - Q_PROPERTY(RenderScripting::ItemState* transparent READ getTransparent) - Q_PROPERTY(RenderScripting::ItemCounter* overlay3D READ getOverlay3D) - - Q_PROPERTY(RenderScripting::Tone* tone READ getTone) - Q_PROPERTY(RenderScripting::AmbientOcclusion* ambientOcclusion READ getAmbientOcclusion) - - Q_PROPERTY(int displayItemStatus MEMBER _drawStatus) - Q_PROPERTY(bool displayHitEffect MEMBER _drawHitEffect) - - Q_PROPERTY(int deferredDebugMode MEMBER _deferredDebugMode) - Q_PROPERTY(glm::vec4 deferredDebugSize MEMBER _deferredDebugSize) - - render::RenderContext getRenderContext(); - void setItemCounts(const render::RenderContext::ItemsConfig& items); - - // FIXME: It is ugly, we need a cleaner solution - void setJobGPUTimes(double aoTime); - -protected: - RenderScriptingInterface(); - ~RenderScriptingInterface() {}; - - RenderScripting::ItemState* getOpaque() const { return _opaque.get(); } - RenderScripting::ItemState* getTransparent() const { return _transparent.get(); } - RenderScripting::ItemCounter* getOverlay3D() const { return _overlay3D.get(); } - - RenderScripting::Tone* getTone() const { return _tone.get(); } - RenderScripting::AmbientOcclusion* getAmbientOcclusion() const { return _ambientOcclusion.get(); } - - RenderScripting::ItemStatePointer _opaque = RenderScripting::ItemStatePointer{new RenderScripting::ItemState{}}; - RenderScripting::ItemStatePointer _transparent = RenderScripting::ItemStatePointer{new RenderScripting::ItemState{}}; - RenderScripting::ItemCounterPointer _overlay3D = RenderScripting::ItemCounterPointer{new RenderScripting::ItemCounter{}}; - - RenderScripting::TonePointer _tone = RenderScripting::TonePointer{ new RenderScripting::Tone{} }; - - RenderScripting::AmbientOcclusionPointer _ambientOcclusion = RenderScripting::AmbientOcclusionPointer{ new RenderScripting::AmbientOcclusion{} }; - - // Options - int _drawStatus = 0; - bool _drawHitEffect = false; - - // Debugging - int _deferredDebugMode = -1; - glm::vec4 _deferredDebugSize { 0.0f, -1.0f, 1.0f, 1.0f }; -}; - -#endif // hifi_RenderScriptingInterface_h From f1b7807db7ad22d31c20e10fe6625b0fa539dec0 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 15:17:05 -0800 Subject: [PATCH 020/145] Add Job::Config to Draw --- .../render-utils/src/RenderDeferredTask.cpp | 51 +++++------------- .../render-utils/src/RenderDeferredTask.h | 54 ++++++++++++++----- libraries/render/src/render/Context.cpp | 4 +- libraries/render/src/render/Context.h | 48 +---------------- 4 files changed, 56 insertions(+), 101 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 96b4a423d5..6e5c559c12 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -103,7 +103,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { addJob("PrepareDeferred"); // Render opaque objects in DeferredBuffer - addJob("DrawOpaqueDeferred", opaques, shapePlumber); + addJob("DrawOpaqueDeferred", opaques, shapePlumber); // Once opaque is all rendered create stencil background addJob("DrawOpaqueStencil"); @@ -127,9 +127,9 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { _antialiasingJobIndex = (int)_jobs.size() - 1; enableJob(_antialiasingJobIndex, false); - // Render transparent objects forward in LigthingBuffer - addJob("DrawTransparentDeferred", transparents, shapePlumber); - + // Render transparent objects forward in LightingBuffer + addJob("DrawTransparentDeferred", transparents, shapePlumber); + // Lighting Buffer ready for tone mapping addJob("ToneMapping"); _toneMappingJobIndex = (int)_jobs.size() - 1; @@ -209,18 +209,19 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend } }; -void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { +void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { assert(renderContext->getArgs()); assert(renderContext->getArgs()->_viewFrustum); + auto& config = std::static_pointer_cast(renderContext->jobConfig); + RenderArgs* args = renderContext->getArgs(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); args->_batch = &batch; - auto& opaque = renderContext->getItemsConfig().opaque; - opaque.numDrawn = (int)inItems.size(); + config->numDrawn = (int)inItems.size(); glm::mat4 projMat; Transform viewMat; @@ -230,33 +231,7 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderShapes(sceneContext, renderContext, _shapePlumber, inItems, opaque.maxDrawn); - args->_batch = nullptr; - }); -} - -void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); - - RenderArgs* args = renderContext->getArgs(); - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - args->_batch = &batch; - - auto& transparent = renderContext->getItemsConfig().transparent; - transparent.numDrawn = (int)inItems.size(); - - glm::mat4 projMat; - Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); - - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - - renderShapes(sceneContext, renderContext, _shapePlumber, inItems, transparent.maxDrawn); + renderShapes(sceneContext, renderContext, _shapePlumber, inItems, config->maxDrawn); args->_batch = nullptr; }); } @@ -287,6 +262,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon auto& scene = sceneContext->_scene; auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withLayered()); + auto& config = std::static_pointer_cast(renderContext->jobConfig); ItemIDsBounds inItems; inItems.reserve(items.size()); @@ -296,9 +272,8 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon inItems.emplace_back(id); } } - auto& overlay3D = renderContext->getItemsConfig().overlay3D; - overlay3D.numFeed = (int)inItems.size(); - overlay3D.numDrawn = (int)inItems.size(); + config->numItems = (int)inItems.size(); + config->numDrawn = (int)inItems.size(); if (!inItems.empty()) { RenderArgs* args = renderContext->getArgs(); @@ -330,7 +305,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); - renderShapes(sceneContext, renderContext, _shapePlumber, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); + renderShapes(sceneContext, renderContext, _shapePlumber, inItems, config->maxDrawn); }); args->_batch = nullptr; args->_whiteTexture.reset(); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 019134903d..fc41b33bee 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -64,26 +64,32 @@ public: ToneMappingEffect _toneMappingEffect; }; -class DrawOpaqueDeferred { +class DrawConfig : public render::Job::Config { + Q_OBJECT public: - DrawOpaqueDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); + Q_PROPERTY(int numDrawn READ getNumDrawn) + Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) + int getNumDrawn() { return numDrawn; } - using JobModel = render::Job::ModelI; - -protected: - render::ShapePlumberPointer _shapePlumber; + int numDrawn{ 0 }; + int maxDrawn{ -1 }; +signals: + void dirty(); }; -class DrawTransparentDeferred { +class DrawDeferred { public: - DrawTransparentDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); + using Config = DrawConfig; + using JobModel = render::Job::ModelI; - using JobModel = render::Job::ModelI; + DrawDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + + void configure(const Config& config) { _maxDrawn = config.maxDrawn; } + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); protected: render::ShapePlumberPointer _shapePlumber; + int _maxDrawn{ -1 }; }; class DrawStencilDeferred { @@ -105,18 +111,38 @@ public: using JobModel = render::Job::Model; }; +class DrawOverlay3DConfig : public render::Job::Config { + Q_OBJECT +public: + Q_PROPERTY(int numItems READ getNumItems) + Q_PROPERTY(int numDrawn READ getNumDrawn) + Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) + int getNumItems() { return numItems; } + int getNumDrawn() { return numDrawn; } + + int numItems{ 0 }; + int numDrawn{ 0 }; + int maxDrawn{ -1 }; +signals: + void dirty(); +}; + class DrawOverlay3D { public: - DrawOverlay3D(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - static const gpu::PipelinePointer& getOpaquePipeline(); + using Config = DrawOverlay3DConfig; + using JobModel = render::Job::Model; + DrawOverlay3D(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + + void configure(const Config& config) { _maxDrawn = config.maxDrawn; } void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Job::Model; + static const gpu::PipelinePointer& getOpaquePipeline(); protected: static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable render::ShapePlumberPointer _shapePlumber; + int _maxDrawn{ -1 }; }; class Blit { diff --git a/libraries/render/src/render/Context.cpp b/libraries/render/src/render/Context.cpp index 0a392e366e..5c9d070036 100644 --- a/libraries/render/src/render/Context.cpp +++ b/libraries/render/src/render/Context.cpp @@ -13,11 +13,11 @@ using namespace render; -RenderContext::RenderContext(ItemsConfig items, Tone tone, AmbientOcclusion ao, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode) +RenderContext::RenderContext(AmbientOcclusion ao, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode) : _deferredDebugMode{ deferredDebugMode }, _deferredDebugSize{ deferredDebugSize }, _args{ nullptr }, _drawStatus{ drawStatus }, _drawHitEffect{ drawHitEffect }, - _items{ items }, _tone{ tone }, _ambientOcclusion{ ao } {} + _ambientOcclusion{ ao } {} void RenderContext::setOptions(bool occlusion, bool fxaa, bool showOwned, bool shadowMap) { _occlusionStatus = occlusion; diff --git a/libraries/render/src/render/Context.h b/libraries/render/src/render/Context.h index b2ba7614db..d82b12e202 100644 --- a/libraries/render/src/render/Context.h +++ b/libraries/render/src/render/Context.h @@ -32,48 +32,6 @@ class JobConfig; class RenderContext { public: - class ItemsConfig { - public: - class Counter { - public: - Counter() {} - Counter(const Counter& counter) : maxDrawn { counter.maxDrawn } {} - - void setCounts(const Counter& counter) { - numFeed = counter.numFeed; - numDrawn = counter.numDrawn; - }; - - int numFeed { 0 }; - int numDrawn { 0 }; - int maxDrawn { -1 }; - }; - - class State : public Counter { - public: - bool render { true }; - bool cull { true }; - bool sort { true }; - - Counter counter{}; - }; - - ItemsConfig(State opaqueState, State transparentState, Counter overlay3DCounter) - : opaque{ opaqueState }, transparent{ transparentState }, overlay3D{ overlay3DCounter } {} - ItemsConfig() : ItemsConfig{ {}, {}, {} } {} - - // TODO: If member count increases, store counters in a map instead of multiple members - State opaque{}; - State transparent{}; - Counter overlay3D{}; - }; - - class Tone { - public: - int toneCurve = 1; // Means just Gamma 2.2 correction - float exposure = 0.0; - }; - class AmbientOcclusion { public: int resolutionLevel { 1 }; @@ -90,13 +48,11 @@ public: double gpuTime { 0.0 }; }; - RenderContext(ItemsConfig items, Tone tone, AmbientOcclusion ao, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode); + RenderContext(AmbientOcclusion ao, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode); RenderContext() {}; void setArgs(RenderArgs* args) { _args = args; } RenderArgs* getArgs() { return _args; } - ItemsConfig& getItemsConfig() { return _items; } - Tone& getTone() { return _tone; } AmbientOcclusion& getAmbientOcclusion() { return _ambientOcclusion; } int getDrawStatus() { return _drawStatus; } bool getDrawHitEffect() { return _drawHitEffect; } @@ -120,8 +76,6 @@ protected: bool _fxaaStatus { false }; bool _shadowMapStatus { false }; - ItemsConfig _items; - Tone _tone; AmbientOcclusion _ambientOcclusion; }; typedef std::shared_ptr RenderContextPointer; From f5a408d82ac15d85f9a39b21f3c6cf8a83173379 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 16:18:29 -0800 Subject: [PATCH 021/145] Notes for later --- interface/src/Application.cpp | 1 + libraries/render/src/render/Task.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d5616bb453..92e0bec131 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -678,6 +678,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : _renderEngine->addJob("RenderShadowTask", cullFunctor); _renderEngine->addJob("RenderDeferredTask", cullFunctor); _renderEngine->registerScene(_main3DScene); + // TODO: Load a cached config file _offscreenContext->makeCurrent(); diff --git a/libraries/render/src/render/Task.cpp b/libraries/render/src/render/Task.cpp index c1c607c587..904c89cc6e 100644 --- a/libraries/render/src/render/Task.cpp +++ b/libraries/render/src/render/Task.cpp @@ -21,5 +21,6 @@ using namespace render; void TaskConfig::refresh() { + // FIXME: Only configure when on own thread (see RecordingInterface for example) _task->configure(*this); } From ccbec54f2dc81c98e063e96cda90d92499dbd8d9 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 16:19:40 -0800 Subject: [PATCH 022/145] Add Job::Config to DebugDeferredBuffer --- .../render-utils/src/DebugDeferredBuffer.cpp | 55 +++++++++--------- .../render-utils/src/DebugDeferredBuffer.h | 57 ++++++++++++------- libraries/render/src/render/Context.cpp | 5 +- libraries/render/src/render/Context.h | 6 +- 4 files changed, 69 insertions(+), 54 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index bb45d3945a..f1a1f70369 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -27,6 +27,14 @@ using namespace render; +void DebugDeferredBufferConfig::setMode(int newMode) { + if (newMode > (int)DebugDeferredBuffer::Custom || newMode < 0) { + mode = (int)DebugDeferredBuffer::Custom; + } else { + mode = newMode; + } +} + enum Slots { Diffuse = 0, Normal, @@ -129,37 +137,37 @@ DebugDeferredBuffer::DebugDeferredBuffer() { _customPipelines.emplace(CUSTOM_FILE, pipeline); } -std::string DebugDeferredBuffer::getShaderSourceCode(Modes mode, std::string customFile) { +std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string customFile) { switch (mode) { - case DiffuseMode: + case Diffuse: return DEFAULT_DIFFUSE_SHADER; - case SpecularMode: + case Specular: return DEFAULT_SPECULAR_SHADER; - case RoughnessMode: + case Roughness: return DEFAULT_ROUGHNESS_SHADER; - case NormalMode: + case Normal: return DEFAULT_NORMAL_SHADER; - case DepthMode: + case Depth: return DEFAULT_DEPTH_SHADER; - case LightingMode: + case Lighting: return DEFAULT_LIGHTING_SHADER; - case ShadowMode: + case Shadow: return DEFAULT_SHADOW_SHADER; - case PyramidDepthMode: + case PyramidDepth: return DEFAULT_PYRAMID_DEPTH_SHADER; - case AmbientOcclusionMode: + case AmbientOcclusion: return DEFAULT_AMBIENT_OCCLUSION_SHADER; - case AmbientOcclusionBlurredMode: + case AmbientOcclusionBlurred: return DEFAULT_AMBIENT_OCCLUSION_BLURRED_SHADER; - case CustomMode: + case Custom: return getFileContent(customFile, DEFAULT_CUSTOM_SHADER); } Q_UNREACHABLE(); return std::string(); } -bool DebugDeferredBuffer::pipelineNeedsUpdate(Modes mode, std::string customFile) const { - if (mode != CustomMode) { +bool DebugDeferredBuffer::pipelineNeedsUpdate(Mode mode, std::string customFile) const { + if (mode != Custom) { return !_pipelines[mode]; } @@ -175,7 +183,7 @@ bool DebugDeferredBuffer::pipelineNeedsUpdate(Modes mode, std::string customFile return true; } -const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode, std::string customFile) { +const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Mode mode, std::string customFile) { if (pipelineNeedsUpdate(mode, customFile)) { static const std::string VERTEX_SHADER { debug_deferred_buffer_vert }; static const std::string FRAGMENT_SHADER { debug_deferred_buffer_frag }; @@ -207,14 +215,14 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode, std::st auto pipeline = gpu::Pipeline::create(program, std::make_shared()); // Good to go add the brand new pipeline - if (mode != CustomMode) { + if (mode != Custom) { _pipelines[mode] = pipeline; } else { _customPipelines[customFile].pipeline = pipeline; } } - if (mode != CustomMode) { + if (mode != Custom) { return _pipelines[mode]; } else { return _customPipelines[customFile].pipeline; @@ -227,13 +235,6 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren assert(renderContext->getArgs()->_viewFrustum); RenderArgs* args = renderContext->getArgs(); - // Guard against unspecified modes - auto mode = renderContext->_deferredDebugMode; - if (mode > (int)CustomMode) { - renderContext->_deferredDebugMode = -1; - return; - } - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { const auto geometryBuffer = DependencyManager::get(); const auto framebufferCache = DependencyManager::get(); @@ -250,7 +251,7 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren // TODO REMOVE: Temporary until UI auto first = _customPipelines.begin()->first; - batch.setPipeline(getPipeline(Modes(renderContext->_deferredDebugMode), first)); + batch.setPipeline(getPipeline(_mode, first)); batch.setResourceTexture(Diffuse, framebufferCache->getDeferredColorTexture()); batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture()); @@ -263,8 +264,8 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren batch.setResourceTexture(AmbientOcclusionBlurred, framebufferCache->getOcclusionBlurredTexture()); const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); - const glm::vec2 bottomLeft(renderContext->_deferredDebugSize.x, renderContext->_deferredDebugSize.y); - const glm::vec2 topRight(renderContext->_deferredDebugSize.z, renderContext->_deferredDebugSize.w); + const glm::vec2 bottomLeft(_size.x, _size.y); + const glm::vec2 topRight(_size.z, _size.w); geometryBuffer->renderQuad(batch, bottomLeft, topRight, color); }); } diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index f5c2d3f8a1..90a8f91575 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -20,6 +20,15 @@ class DebugDeferredBufferConfig : public render::Job::Config { Q_OBJECT public: DebugDeferredBufferConfig() : render::Job::Config(false) {} + + Q_PROPERTY(int mode MEMBER mode WRITE setMode NOTIFY dirty) + Q_PROPERTY(glm::vec4 size MEMBER size NOTIFY dirty) + void setMode(int newMode); + + int mode{ 0 }; + glm::vec4 size{ 0, 0, 0, 0 }; +signals: + void dirty(); }; class DebugDeferredBuffer { @@ -28,34 +37,44 @@ public: using JobModel = render::Job::Model; DebugDeferredBuffer(); - - void configure(const Config&) {} + + void configure(const Config& config) { + _mode = (Mode)config.mode; + _size = config.size; + } void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); -private: - enum Modes : uint8_t { - DiffuseMode = 0, - SpecularMode, - RoughnessMode, - NormalMode, - DepthMode, - LightingMode, - ShadowMode, - PyramidDepthMode, - AmbientOcclusionMode, - AmbientOcclusionBlurredMode, - CustomMode // Needs to stay last +protected: + friend class Config; + + enum Mode : uint8_t { + Diffuse = 0, + Specular, + Roughness, + Normal, + Depth, + Lighting, + Shadow, + PyramidDepth, + AmbientOcclusion, + AmbientOcclusionBlurred, + Custom // Needs to stay last }; + +private: + Mode _mode; + glm::vec4 _size; + struct CustomPipeline { gpu::PipelinePointer pipeline; mutable QFileInfo info; }; - using StandardPipelines = std::array; + using StandardPipelines = std::array; using CustomPipelines = std::unordered_map; - bool pipelineNeedsUpdate(Modes mode, std::string customFile = std::string()) const; - const gpu::PipelinePointer& getPipeline(Modes mode, std::string customFile = std::string()); - std::string getShaderSourceCode(Modes mode, std::string customFile = std::string()); + bool pipelineNeedsUpdate(Mode mode, std::string customFile = std::string()) const; + const gpu::PipelinePointer& getPipeline(Mode mode, std::string customFile = std::string()); + std::string getShaderSourceCode(Mode mode, std::string customFile = std::string()); StandardPipelines _pipelines; CustomPipelines _customPipelines; diff --git a/libraries/render/src/render/Context.cpp b/libraries/render/src/render/Context.cpp index 5c9d070036..b00fc319ef 100644 --- a/libraries/render/src/render/Context.cpp +++ b/libraries/render/src/render/Context.cpp @@ -13,9 +13,8 @@ using namespace render; -RenderContext::RenderContext(AmbientOcclusion ao, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode) - : _deferredDebugMode{ deferredDebugMode }, _deferredDebugSize{ deferredDebugSize }, - _args{ nullptr }, +RenderContext::RenderContext(AmbientOcclusion ao, int drawStatus, bool drawHitEffect) + : _args{ nullptr }, _drawStatus{ drawStatus }, _drawHitEffect{ drawHitEffect }, _ambientOcclusion{ ao } {} diff --git a/libraries/render/src/render/Context.h b/libraries/render/src/render/Context.h index d82b12e202..a00728ccfb 100644 --- a/libraries/render/src/render/Context.h +++ b/libraries/render/src/render/Context.h @@ -48,7 +48,7 @@ public: double gpuTime { 0.0 }; }; - RenderContext(AmbientOcclusion ao, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode); + RenderContext(AmbientOcclusion ao, int drawStatus, bool drawHitEffect); RenderContext() {}; void setArgs(RenderArgs* args) { _args = args; } @@ -61,10 +61,6 @@ public: bool getShadowMapStatus() { return _shadowMapStatus; } void setOptions(bool occlusion, bool fxaa, bool showOwned, bool shadowMap); - // Debugging - int _deferredDebugMode; - glm::vec4 _deferredDebugSize; - std::shared_ptr jobConfig{ nullptr }; protected: RenderArgs* _args; From ba61c1f8653e774d2ca67c0ed9e9367d3e518aa8 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 16:21:58 -0800 Subject: [PATCH 023/145] Fix draw calls to use members --- libraries/render-utils/src/RenderDeferredTask.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 6e5c559c12..22aac54129 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -171,8 +171,6 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend return; } - setDrawDebugDeferredBuffer(renderContext->_deferredDebugMode); - setDrawItemStatus(renderContext->getDrawStatus()); setDrawHitEffect(renderContext->getDrawHitEffect()); // TODO: turn on/off AO through menu item setOcclusionStatus(renderContext->getOcclusionStatus()); @@ -231,7 +229,7 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderShapes(sceneContext, renderContext, _shapePlumber, inItems, config->maxDrawn); + renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); args->_batch = nullptr; }); } @@ -305,7 +303,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); - renderShapes(sceneContext, renderContext, _shapePlumber, inItems, config->maxDrawn); + renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); }); args->_batch = nullptr; args->_whiteTexture.reset(); From 772aedde9129998183f6a22ef600021024193274 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 17:04:55 -0800 Subject: [PATCH 024/145] Add Job::Config to AmbientOcclusion --- .../src/AmbientOcclusionEffect.cpp | 213 ++++++++++-------- .../render-utils/src/AmbientOcclusionEffect.h | 102 +++++---- .../render-utils/src/RenderDeferredTask.cpp | 20 -- libraries/render/src/render/Context.cpp | 6 +- libraries/render/src/render/Context.h | 21 +- 5 files changed, 176 insertions(+), 186 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 30360fdbce..2ba02f922d 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -32,6 +32,44 @@ #include "ssao_makeHorizontalBlur_frag.h" #include "ssao_makeVerticalBlur_frag.h" +void AmbientOcclusionEffectConfig::setRadius(float newRadius) { + radius = std::max(0.01f, radius); +} + +void AmbientOcclusionEffectConfig::setObscuranceLevel(float level) { + level = std::max(0.01f, level); +} + +void AmbientOcclusionEffectConfig::setFalloffBias(float bias) { + bias = std::max(0.0f, std::min(bias, 0.2f)); +} + +void AmbientOcclusionEffectConfig::setEdgeSharpness(float sharpness) { + sharpness = std::max(0.0f, (float)sharpness); +} + +void AmbientOcclusionEffectConfig::setBlurDeviation(float deviation) { + deviation = std::max(0.0f, deviation); +} + +void AmbientOcclusionEffectConfig::setNumSpiralTurns(float numTurns) { + numTurns = std::max(0.0f, (float)numTurns); +} + +void AmbientOcclusionEffectConfig::setNumSamples(int numSamples) { + numSamples = std::max(1.0f, (float) numSamples); +} + +void AmbientOcclusionEffectConfig::setResolutionLevel(int level) { + const int MAX_RESOLUTION_LEVEL = 4; + level = std::max(0, std::min(level, MAX_RESOLUTION_LEVEL)); +} + +void AmbientOcclusionEffectConfig::setBlurRadius(int radius) { + const int MAX_BLUR_RADIUS = 6; + radius = std::max(0, std::min(MAX_BLUR_RADIUS, radius)); +} + class GaussianDistribution { public: @@ -100,6 +138,80 @@ AmbientOcclusionEffect::AmbientOcclusionEffect() { _parametersBuffer = gpu::BufferView(std::make_shared(sizeof(Parameters), (const gpu::Byte*) ¶meters)); } +void AmbientOcclusionEffect::configure(const Config& configuration) { + bool shouldUpdateGaussion = false; + + const double RADIUS_POWER = 6.0; + const auto& radius = configuration.radius; + if (radius != getRadius()) { + auto& current = _parametersBuffer.edit().radiusInfo; + current.x = radius; + current.y = radius * radius; + current.z = (float)(1.0 / pow((double)radius, RADIUS_POWER)); + } + + if (configuration.obscuranceLevel != getObscuranceLevel()) { + auto& current = _parametersBuffer.edit().radiusInfo; + current.w = configuration.obscuranceLevel; + } + + if (configuration.falloffBias != getFalloffBias()) { + auto& current = _parametersBuffer.edit().ditheringInfo; + current.z = configuration.falloffBias; + } + + if (configuration.edgeSharpness != getEdgeSharpness()) { + auto& current = _parametersBuffer.edit().blurInfo; + current.x = configuration.edgeSharpness; + } + + if (configuration.blurDeviation != getBlurDeviation()) { + auto& current = _parametersBuffer.edit().blurInfo; + current.z = configuration.blurDeviation; + shouldUpdateGaussion = true; + } + + if (configuration.numSpiralTurns != getNumSpiralTurns()) { + auto& current = _parametersBuffer.edit().sampleInfo; + current.z = configuration.numSpiralTurns; + } + + if (configuration.numSamples != getNumSamples()) { + auto& current = _parametersBuffer.edit().sampleInfo; + current.x = configuration.numSamples; + current.y = 1.0f / configuration.numSamples; + } + + const auto& resolutionLevel = configuration.resolutionLevel; + if (resolutionLevel != getResolutionLevel()) { + auto& current = _parametersBuffer.edit().resolutionInfo; + current.x = (float)resolutionLevel; + + // Communicate the change to the Framebuffer cache + DependencyManager::get()->setAmbientOcclusionResolutionLevel(resolutionLevel); + } + + if (configuration.blurRadius != getBlurRadius()) { + auto& current = _parametersBuffer.edit().blurInfo; + current.y = (float)configuration.blurRadius; + shouldUpdateGaussion = true; + } + + if (configuration.ditheringEnabled != isDitheringEnabled()) { + auto& current = _parametersBuffer.edit().ditheringInfo; + current.x = (float)configuration.ditheringEnabled; + } + + if (configuration.borderingEnabled != isBorderingEnabled()) { + auto& current = _parametersBuffer.edit().ditheringInfo; + current.w = (float)configuration.borderingEnabled; + } + + if (shouldUpdateGaussion) { + updateGaussianDistribution(); + } +} + const gpu::PipelinePointer& AmbientOcclusionEffect::getPyramidPipeline() { if (!_pyramidPipeline) { auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); @@ -200,103 +312,6 @@ void AmbientOcclusionEffect::setDepthInfo(float nearZ, float farZ) { _frameTransformBuffer.edit().depthInfo = glm::vec4(nearZ*farZ, farZ -nearZ, -farZ, 0.0f); } -void AmbientOcclusionEffect::setResolutionLevel(int level) { - const int MAX_RESOLUTION_LEVEL = 4; - level = std::max(0, std::min(level, MAX_RESOLUTION_LEVEL)); - if (level != getResolutionLevel()) { - auto& current = _parametersBuffer.edit().resolutionInfo; - current.x = (float)level; - - // Communicate the change to the Framebuffer cache - DependencyManager::get()->setAmbientOcclusionResolutionLevel(level); - } -} - -void AmbientOcclusionEffect::setRadius(float radius) { - const double RADIUS_POWER = 6.0; - radius = std::max(0.01f, radius); - if (radius != getRadius()) { - auto& current = _parametersBuffer.edit().radiusInfo; - current.x = radius; - current.y = radius * radius; - current.z = (float)(1.0 / pow((double)radius, RADIUS_POWER)); - } -} - -void AmbientOcclusionEffect::setLevel(float level) { - level = std::max(0.01f, level); - if (level != getLevel()) { - auto& current = _parametersBuffer.edit().radiusInfo; - current.w = level; - } -} - -void AmbientOcclusionEffect::setDithering(bool enabled) { - if (enabled != isDitheringEnabled()) { - auto& current = _parametersBuffer.edit().ditheringInfo; - current.x = (float)enabled; - } -} - -void AmbientOcclusionEffect::setBordering(bool enabled) { - if (enabled != isBorderingEnabled()) { - auto& current = _parametersBuffer.edit().ditheringInfo; - current.w = (float)enabled; - } -} - -void AmbientOcclusionEffect::setFalloffBias(float bias) { - bias = std::max(0.0f, std::min(bias, 0.2f)); - if (bias != getFalloffBias()) { - auto& current = _parametersBuffer.edit().ditheringInfo; - current.z = (float)bias; - } -} - - -void AmbientOcclusionEffect::setNumSamples(int numSamples) { - numSamples = std::max(1.0f, (float) numSamples); - if (numSamples != getNumSamples()) { - auto& current = _parametersBuffer.edit().sampleInfo; - current.x = numSamples; - current.y = 1.0f / numSamples; - } -} - -void AmbientOcclusionEffect::setNumSpiralTurns(float numTurns) { - numTurns = std::max(0.0f, (float)numTurns); - if (numTurns != getNumSpiralTurns()) { - auto& current = _parametersBuffer.edit().sampleInfo; - current.z = numTurns; - } -} - -void AmbientOcclusionEffect::setEdgeSharpness(float sharpness) { - sharpness = std::max(0.0f, (float)sharpness); - if (sharpness != getEdgeSharpness()) { - auto& current = _parametersBuffer.edit().blurInfo; - current.x = sharpness; - } -} - -void AmbientOcclusionEffect::setBlurRadius(int radius) { - const int MAX_BLUR_RADIUS = 6; - radius = std::max(0, std::min(MAX_BLUR_RADIUS, radius)); - if (radius != getBlurRadius()) { - auto& current = _parametersBuffer.edit().blurInfo; - current.y = (float)radius; - updateGaussianDistribution(); - } -} - -void AmbientOcclusionEffect::setBlurDeviation(float deviation) { - deviation = std::max(0.0f, deviation); - if (deviation != getBlurDeviation()) { - auto& current = _parametersBuffer.edit().blurInfo; - current.z = deviation; - updateGaussianDistribution(); - } -} void AmbientOcclusionEffect::updateGaussianDistribution() { auto coefs = _parametersBuffer.edit()._gaussianCoefs; GaussianDistribution::evalSampling(coefs, Parameters::GAUSSIAN_COEFS_LENGTH, getBlurRadius(), getBlurDeviation()); @@ -417,6 +432,8 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext } _gpuTimer.end(batch); - }); + + // Update the timer + std::static_pointer_cast(renderContext->jobConfig)->gpuTime = _gpuTimer.getAverage(); } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 5bfeca38a4..3d619ea958 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -16,63 +16,75 @@ #include "render/DrawTask.h" +class AmbientOcclusionEffectConfig : public render::Job::Config { + Q_OBJECT +public: + AmbientOcclusionEffectConfig() : render::Job::Config(false) {} + + Q_PROPERTY(float radius MEMBER radius WRITE setRadius NOTIFY dirty) + Q_PROPERTY(float obscuranceLevel MEMBER obscuranceLevel WRITE setObscuranceLevel NOTIFY dirty) + Q_PROPERTY(float falloffBias MEMBER falloffBias WRITE setFalloffBias NOTIFY dirty) + Q_PROPERTY(float edgeSharpness MEMBER edgeSharpness WRITE setEdgeSharpness NOTIFY dirty) + Q_PROPERTY(float blurDeviation MEMBER blurDeviation WRITE setBlurDeviation NOTIFY dirty) + Q_PROPERTY(float numSpiralTurns MEMBER numSpiralTurns WRITE setNumSpiralTurns NOTIFY dirty) + Q_PROPERTY(int numSamples MEMBER numSamples WRITE setNumSamples NOTIFY dirty) + Q_PROPERTY(int resolutionLevel MEMBER resolutionLevel WRITE setResolutionLevel NOTIFY dirty) + Q_PROPERTY(int blurRadius MEMBER blurRadius WRITE setBlurRadius NOTIFY dirty) + Q_PROPERTY(bool ditheringEnabled MEMBER ditheringEnabled NOTIFY dirty) + Q_PROPERTY(bool borderingEnabled MEMBER borderingEnabled NOTIFY dirty) + Q_PROPERTY(double gpuTime READ getGpuTime) + + void setRadius(float radius); + void setObscuranceLevel(float obscuranceLevel); + void setFalloffBias(float falloffBias); + void setEdgeSharpness(float edgeSharpness); + void setBlurDeviation(float blurDeviation); + void setNumSpiralTurns(float numSpiralTurns); + void setNumSamples(int numSamples); + void setResolutionLevel(int resolutionLevel); + void setBlurRadius(int blurRadius); + double getGpuTime() { return gpuTime; } + + float radius{ 0.5f }; + float obscuranceLevel{ 0.5f }; // intensify or dim down the obscurance effect + float falloffBias{ 0.01f }; + float edgeSharpness{ 1.0f }; + float blurDeviation{ 2.5f }; + float numSpiralTurns{ 7.0f }; // defining an angle span to distribute the samples ray directions + int numSamples{ 11 }; + int resolutionLevel{ 1 }; + int blurRadius{ 4 }; // 0 means no blurring + bool ditheringEnabled{ true }; // randomize the distribution of rays per pixel, should always be true + bool borderingEnabled{ true }; // avoid evaluating information from non existing pixels out of the frame, should always be true + double gpuTime{ 0.0 }; + +signals: + void dirty(); +}; class AmbientOcclusionEffect { public: + using Config = AmbientOcclusionEffectConfig; + using JobModel = render::Job::Model; AmbientOcclusionEffect(); + void configure(const Config& configuration); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - void setResolutionLevel(int level); - int getResolutionLevel() const { return _parametersBuffer.get().resolutionInfo.x; } - - void setRadius(float radius); float getRadius() const { return _parametersBuffer.get().radiusInfo.x; } - - // Obscurance level which intensify or dim down the obscurance effect - void setLevel(float level); - float getLevel() const { return _parametersBuffer.get().radiusInfo.w; } - - // On to randomize the distribution of rays per pixel, should always be true - void setDithering(bool enabled); - bool isDitheringEnabled() const { return _parametersBuffer.get().ditheringInfo.x; } - - // On to avoid evaluating information from non existing pixels Out of the frame, should always be true - void setBordering(bool enabled); - bool isBorderingEnabled() const { return _parametersBuffer.get().ditheringInfo.w; } - - // Faloff Bias - void setFalloffBias(float bias); - int getFalloffBias() const { return (int)_parametersBuffer.get().ditheringInfo.z; } - - // Number of samples per pixel to evaluate the Obscurance - void setNumSamples(int numSamples); - int getNumSamples() const { return (int)_parametersBuffer.get().sampleInfo.x; } - - // Number of spiral turns defining an angle span to distribute the samples ray directions - void setNumSpiralTurns(float numTurns); - float getNumSpiralTurns() const { return _parametersBuffer.get().sampleInfo.z; } - - // Edge blurring setting - void setEdgeSharpness(float sharpness); - int getEdgeSharpness() const { return (int)_parametersBuffer.get().blurInfo.x; } - - // Blurring Radius - // 0 means no blurring - const int MAX_BLUR_RADIUS = 6; - void setBlurRadius(int radius); - int getBlurRadius() const { return (int)_parametersBuffer.get().blurInfo.y; } - - void setBlurDeviation(float deviation); + float getObscuranceLevel() const { return _parametersBuffer.get().radiusInfo.w; } + float getFalloffBias() const { return (float)_parametersBuffer.get().ditheringInfo.z; } + float getEdgeSharpness() const { return (float)_parametersBuffer.get().blurInfo.x; } float getBlurDeviation() const { return _parametersBuffer.get().blurInfo.z; } - - double getGPUTime() const { return _gpuTimer.getAverage(); } + float getNumSpiralTurns() const { return _parametersBuffer.get().sampleInfo.z; } + int getNumSamples() const { return (int)_parametersBuffer.get().sampleInfo.x; } + int getResolutionLevel() const { return _parametersBuffer.get().resolutionInfo.x; } + int getBlurRadius() const { return (int)_parametersBuffer.get().blurInfo.y; } + bool isDitheringEnabled() const { return _parametersBuffer.get().ditheringInfo.x; } + bool isBorderingEnabled() const { return _parametersBuffer.get().ditheringInfo.w; } - using JobModel = render::Job::Model; - private: - void updateGaussianDistribution(); void setDepthInfo(float nearZ, float farZ); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 22aac54129..928eaea255 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -173,21 +173,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend setDrawHitEffect(renderContext->getDrawHitEffect()); // TODO: turn on/off AO through menu item - setOcclusionStatus(renderContext->getOcclusionStatus()); - if (_occlusionJobIndex >= 0) { - _jobs[_occlusionJobIndex].edit().setResolutionLevel(renderContext->getAmbientOcclusion().resolutionLevel); - _jobs[_occlusionJobIndex].edit().setRadius(renderContext->getAmbientOcclusion().radius); - _jobs[_occlusionJobIndex].edit().setLevel(renderContext->getAmbientOcclusion().level); - _jobs[_occlusionJobIndex].edit().setNumSamples(renderContext->getAmbientOcclusion().numSamples); - _jobs[_occlusionJobIndex].edit().setNumSpiralTurns(renderContext->getAmbientOcclusion().numSpiralTurns); - _jobs[_occlusionJobIndex].edit().setDithering(renderContext->getAmbientOcclusion().ditheringEnabled); - _jobs[_occlusionJobIndex].edit().setFalloffBias(renderContext->getAmbientOcclusion().falloffBias); - _jobs[_occlusionJobIndex].edit().setEdgeSharpness(renderContext->getAmbientOcclusion().edgeSharpness); - _jobs[_occlusionJobIndex].edit().setBlurRadius(renderContext->getAmbientOcclusion().blurRadius); - _jobs[_occlusionJobIndex].edit().setBlurDeviation(renderContext->getAmbientOcclusion().blurDeviation); - } - setAntialiasingStatus(renderContext->getFxaaStatus()); // TODO: Allow runtime manipulation of culling ShouldRenderFunctor @@ -199,12 +185,6 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend for (auto job : _jobs) { job.run(sceneContext, renderContext); } - - if (_occlusionJobIndex >= 0 && renderContext->getOcclusionStatus()) { - renderContext->getAmbientOcclusion().gpuTime = _jobs[_occlusionJobIndex].edit().getGPUTime(); - } else { - renderContext->getAmbientOcclusion().gpuTime = 0.0; - } }; void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { diff --git a/libraries/render/src/render/Context.cpp b/libraries/render/src/render/Context.cpp index b00fc319ef..7f69c5af3a 100644 --- a/libraries/render/src/render/Context.cpp +++ b/libraries/render/src/render/Context.cpp @@ -13,10 +13,10 @@ using namespace render; -RenderContext::RenderContext(AmbientOcclusion ao, int drawStatus, bool drawHitEffect) +RenderContext::RenderContext(int drawStatus, bool drawHitEffect) : _args{ nullptr }, - _drawStatus{ drawStatus }, _drawHitEffect{ drawHitEffect }, - _ambientOcclusion{ ao } {} + _drawStatus{ drawStatus }, _drawHitEffect{ drawHitEffect } { +} void RenderContext::setOptions(bool occlusion, bool fxaa, bool showOwned, bool shadowMap) { _occlusionStatus = occlusion; diff --git a/libraries/render/src/render/Context.h b/libraries/render/src/render/Context.h index a00728ccfb..3f297c1696 100644 --- a/libraries/render/src/render/Context.h +++ b/libraries/render/src/render/Context.h @@ -32,28 +32,11 @@ class JobConfig; class RenderContext { public: - class AmbientOcclusion { - public: - int resolutionLevel { 1 }; - float radius { 0.5f }; // radius in meters of the AO effect - float level { 0.5f }; // Level of the obscrance value - int numSamples { 11 }; // Num Samples per pixel - float numSpiralTurns { 7.0f }; - bool ditheringEnabled { true }; - float falloffBias { 0.01f }; - float edgeSharpness { 1.0f }; - int blurRadius { 4 }; - float blurDeviation { 2.5f}; - - double gpuTime { 0.0 }; - }; - - RenderContext(AmbientOcclusion ao, int drawStatus, bool drawHitEffect); + RenderContext(int drawStatus, bool drawHitEffect); RenderContext() {}; void setArgs(RenderArgs* args) { _args = args; } RenderArgs* getArgs() { return _args; } - AmbientOcclusion& getAmbientOcclusion() { return _ambientOcclusion; } int getDrawStatus() { return _drawStatus; } bool getDrawHitEffect() { return _drawHitEffect; } bool getOcclusionStatus() { return _occlusionStatus; } @@ -71,8 +54,6 @@ protected: bool _occlusionStatus { false }; bool _fxaaStatus { false }; bool _shadowMapStatus { false }; - - AmbientOcclusion _ambientOcclusion; }; typedef std::shared_ptr RenderContextPointer; From e8b8f4d53551d65d6ef0f33af5eb0dec877de5f4 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 17:07:30 -0800 Subject: [PATCH 025/145] Add Job::Config to HitEffect --- libraries/render-utils/src/RenderDeferredTask.cpp | 3 --- libraries/render/src/render/Context.cpp | 4 ++-- libraries/render/src/render/Context.h | 4 +--- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 928eaea255..437ca870d5 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -171,9 +171,6 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend return; } - setDrawHitEffect(renderContext->getDrawHitEffect()); - // TODO: turn on/off AO through menu item - setAntialiasingStatus(renderContext->getFxaaStatus()); // TODO: Allow runtime manipulation of culling ShouldRenderFunctor diff --git a/libraries/render/src/render/Context.cpp b/libraries/render/src/render/Context.cpp index 7f69c5af3a..7cb71ce4cd 100644 --- a/libraries/render/src/render/Context.cpp +++ b/libraries/render/src/render/Context.cpp @@ -13,9 +13,9 @@ using namespace render; -RenderContext::RenderContext(int drawStatus, bool drawHitEffect) +RenderContext::RenderContext(int drawStatus) : _args{ nullptr }, - _drawStatus{ drawStatus }, _drawHitEffect{ drawHitEffect } { + _drawStatus{ drawStatus } { } void RenderContext::setOptions(bool occlusion, bool fxaa, bool showOwned, bool shadowMap) { diff --git a/libraries/render/src/render/Context.h b/libraries/render/src/render/Context.h index 3f297c1696..096dff2eae 100644 --- a/libraries/render/src/render/Context.h +++ b/libraries/render/src/render/Context.h @@ -32,13 +32,12 @@ class JobConfig; class RenderContext { public: - RenderContext(int drawStatus, bool drawHitEffect); + RenderContext(int drawStatus); RenderContext() {}; void setArgs(RenderArgs* args) { _args = args; } RenderArgs* getArgs() { return _args; } int getDrawStatus() { return _drawStatus; } - bool getDrawHitEffect() { return _drawHitEffect; } bool getOcclusionStatus() { return _occlusionStatus; } bool getFxaaStatus() { return _fxaaStatus; } bool getShadowMapStatus() { return _shadowMapStatus; } @@ -50,7 +49,6 @@ protected: // Options int _drawStatus; // bitflag - bool _drawHitEffect; bool _occlusionStatus { false }; bool _fxaaStatus { false }; bool _shadowMapStatus { false }; From f3265db298f284ce0432f5d0cba2aee7fba2cb3a Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 17:47:13 -0800 Subject: [PATCH 026/145] Gut RenderContext --- interface/src/Application.cpp | 12 +---- .../src/AmbientOcclusionEffect.cpp | 9 ++-- .../render-utils/src/AmbientOcclusionEffect.h | 1 + .../render-utils/src/AntialiasingEffect.cpp | 9 ++-- .../render-utils/src/AntialiasingEffect.h | 11 ++++- .../render-utils/src/DebugDeferredBuffer.cpp | 6 +-- .../src/DeferredLightingEffect.cpp | 6 +-- .../render-utils/src/DeferredLightingEffect.h | 5 +- libraries/render-utils/src/HitEffect.cpp | 7 +-- .../render-utils/src/RenderDeferredTask.cpp | 41 ++++++++--------- .../render-utils/src/RenderShadowTask.cpp | 8 ++-- libraries/render/src/render/Context.cpp | 30 ------------ libraries/render/src/render/Context.h | 24 +--------- libraries/render/src/render/DrawStatus.cpp | 15 ++++-- libraries/render/src/render/DrawStatus.h | 46 +++++++++++++------ libraries/render/src/render/DrawTask.cpp | 22 ++++----- libraries/render/src/render/DrawTask.h | 2 +- libraries/render/src/render/Engine.cpp | 2 +- libraries/render/src/render/Task.h | 3 +- 19 files changed, 117 insertions(+), 142 deletions(-) delete mode 100644 libraries/render/src/render/Context.cpp diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 92e0bec131..ea853bc6a6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3768,22 +3768,12 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se PerformanceTimer perfTimer("EngineRun"); renderArgs->_viewFrustum = getDisplayViewFrustum(); - auto renderContext = _renderEngine->getRenderContext(); - renderContext->setArgs(renderArgs); - - bool occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion); - bool shadowStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugShadows); - bool antialiasingStatus = Menu::getInstance()->isOptionChecked(MenuOption::Antialiasing); - bool showOwnedStatus = Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned); + _renderEngine->getRenderContext()->args = renderArgs; // Before the deferred pass, let's try to use the render engine myAvatar->startRenderRun(); _renderEngine->run(); myAvatar->endRenderRun(); - - auto engineContext = _renderEngine->getRenderContext(); - //zzmp renderInterface->setJobGPUTimes(engineContext->getAmbientOcclusion().gpuTime); - } activeRenderingThread = nullptr; diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 2ba02f922d..4cb6d75f46 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -21,6 +21,7 @@ #include #include "RenderUtilsLogging.h" +#include "DeferredLightingEffect.h" #include "AmbientOcclusionEffect.h" #include "TextureCache.h" #include "FramebufferCache.h" @@ -139,6 +140,8 @@ AmbientOcclusionEffect::AmbientOcclusionEffect() { } void AmbientOcclusionEffect::configure(const Config& configuration) { + DependencyManager::get()->setAmbientOcclusionEnabled(configuration.enabled); + bool shouldUpdateGaussion = false; const double RADIUS_POWER = 6.0; @@ -318,10 +321,10 @@ void AmbientOcclusionEffect::updateGaussianDistribution() { } void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); - RenderArgs* args = renderContext->getArgs(); + RenderArgs* args = renderContext->args; auto framebufferCache = DependencyManager::get(); auto depthBuffer = framebufferCache->getPrimaryDepthTexture(); diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 3d619ea958..6b91446b9c 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -21,6 +21,7 @@ class AmbientOcclusionEffectConfig : public render::Job::Config { public: AmbientOcclusionEffectConfig() : render::Job::Config(false) {} + Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty) Q_PROPERTY(float radius MEMBER radius WRITE setRadius NOTIFY dirty) Q_PROPERTY(float obscuranceLevel MEMBER obscuranceLevel WRITE setObscuranceLevel NOTIFY dirty) Q_PROPERTY(float falloffBias MEMBER falloffBias WRITE setFalloffBias NOTIFY dirty) diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index f56514c7ec..6c26b16124 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -92,14 +92,15 @@ const gpu::PipelinePointer& Antialiasing::getBlendPipeline() { } void Antialiasing::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); - if (renderContext->getArgs()->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + RenderArgs* args = renderContext->args; + + if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { return; } - RenderArgs* args = renderContext->getArgs(); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); batch.setViewportTransform(args->_viewport); diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index 624add87b6..21be235921 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -16,13 +16,20 @@ #include "render/DrawTask.h" +class AntiAliasingConfig : public render::Job::Config { + Q_OBJECT +public: + AntiAliasingConfig() : render::Job::Config(false) {} +}; + class Antialiasing { public: + using Config = AntiAliasingConfig; + using JobModel = render::Job::Model; Antialiasing(); - + void configure(const Config& configuration) {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - using JobModel = render::Job::Model; const gpu::PipelinePointer& getAntialiasingPipeline(); const gpu::PipelinePointer& getBlendPipeline(); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index f1a1f70369..744a2fb4ff 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -231,9 +231,9 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Mode mode, std::str void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); - RenderArgs* args = renderContext->getArgs(); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { const auto geometryBuffer = DependencyManager::get(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 723eacd6be..631f299a8d 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -162,7 +162,7 @@ void DeferredLightingEffect::prepare(RenderArgs* args) { } void DeferredLightingEffect::render(const render::RenderContextPointer& renderContext) { - auto args = renderContext->getArgs(); + auto args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { // Allocate the parameters buffer used by all the deferred shaders @@ -188,14 +188,14 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); - // BInd the G-Buffer surfaces + // Bind the G-Buffer surfaces batch.setResourceTexture(DEFERRED_BUFFER_COLOR_UNIT, framebufferCache->getDeferredColorTexture()); batch.setResourceTexture(DEFERRED_BUFFER_NORMAL_UNIT, framebufferCache->getDeferredNormalTexture()); batch.setResourceTexture(DEFERRED_BUFFER_EMISSIVE_UNIT, framebufferCache->getDeferredSpecularTexture()); batch.setResourceTexture(DEFERRED_BUFFER_DEPTH_UNIT, framebufferCache->getPrimaryDepthTexture()); // need to assign the white texture if ao is off - if (renderContext->getOcclusionStatus()) { + if (_ambientOcclusionEnabled) { batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, framebufferCache->getOcclusionTexture()); } else { batch.setResourceTexture(DEFERRED_BUFFER_OBSCURANCE_UNIT, textureCache->getWhiteTexture()); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 82b9eeadba..a9a76e00d9 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -55,12 +55,15 @@ public: const LightStage& getLightStage() { return _lightStage; } void setShadowMapStatus(bool enable) { _shadowMapStatus = enable; }; + void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } private: + DeferredLightingEffect() = default; + LightStage _lightStage; bool _shadowMapStatus{ false }; - DeferredLightingEffect() = default; + bool _ambientOcclusionEnabled{ false }; model::MeshPointer _spotLightMesh; model::MeshPointer getSpotLightMesh(); diff --git a/libraries/render-utils/src/HitEffect.cpp b/libraries/render-utils/src/HitEffect.cpp index 89f950d830..8f1e9259d4 100644 --- a/libraries/render-utils/src/HitEffect.cpp +++ b/libraries/render-utils/src/HitEffect.cpp @@ -61,9 +61,10 @@ const gpu::PipelinePointer& HitEffect::getHitEffectPipeline() { } void HitEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); - RenderArgs* args = renderContext->getArgs(); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + RenderArgs* args = renderContext->args; + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { glm::mat4 projMat; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 437ca870d5..ee5f99cc0b 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -60,7 +60,7 @@ using namespace render; void initDeferredPipelines(render::ShapePlumber& plumber); void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - DependencyManager::get()->prepare(renderContext->getArgs()); + DependencyManager::get()->prepare(renderContext->args); } void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -78,7 +78,7 @@ void ToneMappingDeferred::configure(const Config& configuration) { } void ToneMappingDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - _toneMappingEffect.render(renderContext->getArgs()); + _toneMappingEffect.render(renderContext->args); } RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { @@ -167,17 +167,14 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend // Is it possible that we render without a viewFrustum ? - if (!(renderContext->getArgs() && renderContext->getArgs()->_viewFrustum)) { + if (!(renderContext->args && renderContext->args->_viewFrustum)) { return; } - setAntialiasingStatus(renderContext->getFxaaStatus()); - // TODO: Allow runtime manipulation of culling ShouldRenderFunctor - // TODO: For now, lighting is controlled through a singleton, so it is distinct DependencyManager::get()->setShadowMapStatus(renderContext->getShadowMapStatus()); - renderContext->getArgs()->_context->syncCache(); + renderContext->args->_context->syncCache(); for (auto job : _jobs) { job.run(sceneContext, renderContext); @@ -185,12 +182,12 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend }; void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); auto& config = std::static_pointer_cast(renderContext->jobConfig); - RenderArgs* args = renderContext->getArgs(); + RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); @@ -230,8 +227,8 @@ const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() { } void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); // render backgrounds auto& scene = sceneContext->_scene; @@ -251,7 +248,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon config->numDrawn = (int)inItems.size(); if (!inItems.empty()) { - RenderArgs* args = renderContext->getArgs(); + RenderArgs* args = renderContext->args; // Clear the framebuffer without stereo // Needs to be distinct from the other batch because using the clear call @@ -309,11 +306,11 @@ const gpu::PipelinePointer& DrawStencilDeferred::getOpaquePipeline() { } void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); // from the touched pixel generate the stencil buffer - RenderArgs* args = renderContext->getArgs(); + RenderArgs* args = renderContext->args; doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -335,8 +332,8 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren } void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); // render backgrounds auto& scene = sceneContext->_scene; @@ -348,7 +345,7 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const for (auto id : items) { inItems.emplace_back(id); } - RenderArgs* args = renderContext->getArgs(); + RenderArgs* args = renderContext->args; doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -375,10 +372,10 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const } void Blit::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_context); + assert(renderContext->args); + assert(renderContext->args->_context); - RenderArgs* renderArgs = renderContext->getArgs(); + RenderArgs* renderArgs = renderContext->args; auto blitFbo = renderArgs->_blitFramebuffer; if (!blitFbo) { diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 8bf12d6eb7..75d01683ed 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -29,15 +29,15 @@ using namespace render; void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ShapesIDsBounds& inShapes) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); const auto& lightStage = DependencyManager::get()->getLightStage(); const auto globalLight = lightStage.lights[0]; const auto& shadow = globalLight->shadow; const auto& fbo = shadow.framebuffer; - RenderArgs* args = renderContext->getArgs(); + RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -121,7 +121,7 @@ RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) { void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { assert(sceneContext); - RenderArgs* args = renderContext->getArgs(); + RenderArgs* args = renderContext->args; // This feature is in a debugging stage - it must be turned on explicitly if (!renderContext->getShadowMapStatus()) { diff --git a/libraries/render/src/render/Context.cpp b/libraries/render/src/render/Context.cpp deleted file mode 100644 index 7cb71ce4cd..0000000000 --- a/libraries/render/src/render/Context.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// -// Context.cpp -// 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 -// - -#include "Context.h" - -using namespace render; - -RenderContext::RenderContext(int drawStatus) - : _args{ nullptr }, - _drawStatus{ drawStatus } { -} - -void RenderContext::setOptions(bool occlusion, bool fxaa, bool showOwned, bool shadowMap) { - _occlusionStatus = occlusion; - _fxaaStatus = fxaa; - _shadowMapStatus = shadowMap; - - if (showOwned) { - _drawStatus |= render::showNetworkStatusFlag; - } -}; - diff --git a/libraries/render/src/render/Context.h b/libraries/render/src/render/Context.h index 096dff2eae..dda20386fa 100644 --- a/libraries/render/src/render/Context.h +++ b/libraries/render/src/render/Context.h @@ -24,33 +24,13 @@ public: }; using SceneContextPointer = std::shared_ptr; -// see examples/utilities/tools/renderEngineDebug.js -const int showDisplayStatusFlag = 1; -const int showNetworkStatusFlag = 2; - class JobConfig; class RenderContext { public: - RenderContext(int drawStatus); - RenderContext() {}; - - void setArgs(RenderArgs* args) { _args = args; } - RenderArgs* getArgs() { return _args; } - int getDrawStatus() { return _drawStatus; } - bool getOcclusionStatus() { return _occlusionStatus; } - bool getFxaaStatus() { return _fxaaStatus; } - bool getShadowMapStatus() { return _shadowMapStatus; } - void setOptions(bool occlusion, bool fxaa, bool showOwned, bool shadowMap); - + RenderArgs* args; std::shared_ptr jobConfig{ nullptr }; -protected: - RenderArgs* _args; - - // Options - int _drawStatus; // bitflag - bool _occlusionStatus { false }; - bool _fxaaStatus { false }; + // TODO: gut this bool _shadowMapStatus { false }; }; typedef std::shared_ptr RenderContextPointer; diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index 3f919b3d8c..eb7155c513 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -94,12 +94,17 @@ const gpu::TexturePointer DrawStatus::getStatusIconMap() const { return _statusIconMap; } +void DrawStatus::configure(const Config& configuration) { + _showDisplay = configuration.showDisplay; + _showNetwork = configuration.showNetwork; +} + void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); - RenderArgs* args = renderContext->getArgs(); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + RenderArgs* args = renderContext->args; auto& scene = sceneContext->_scene; const int NUM_STATUS_VEC4_PER_ITEM = 2; const int VEC4_LENGTH = 4; @@ -179,7 +184,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const unsigned int VEC3_ADRESS_OFFSET = 3; - if ((renderContext->getDrawStatus() & showDisplayStatusFlag) > 0) { + if (_showDisplay) { for (int i = 0; i < nbItems; i++) { batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const float*) (itemAABox + i)); batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); @@ -192,7 +197,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, batch.setPipeline(getDrawItemStatusPipeline()); - if ((renderContext->getDrawStatus() & showNetworkStatusFlag) > 0) { + if (_showNetwork) { for (int i = 0; i < nbItems; i++) { batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const float*) (itemAABox + i)); batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET); diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index d64b484695..f6d9f19206 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -16,7 +16,38 @@ #include "gpu/Batch.h" namespace render { + class DrawStatusConfig : public Job::Config { + Q_OBJECT + public: + Q_PROPERTY(bool showDisplay MEMBER showDisplay NOTIFY dirty) + Q_PROPERTY(bool showNetwork MEMBER showDisplay NOTIFY dirty) + bool showDisplay{ false }; + bool showNetwork{ false }; + signals: + void dirty(); + }; + class DrawStatus { + public: + using Config = DrawStatusConfig; + using JobModel = Job::ModelI; + + DrawStatus() {} + DrawStatus(const gpu::TexturePointer statusIconMap) { setStatusIconMap(statusIconMap); } + + void configure(const Config& configuration); + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); + + const gpu::PipelinePointer getDrawItemBoundsPipeline(); + const gpu::PipelinePointer getDrawItemStatusPipeline(); + + void setStatusIconMap(const gpu::TexturePointer& map); + const gpu::TexturePointer getStatusIconMap() const; + + protected: + bool _showDisplay{ false }; + bool _showNetwork{ false }; + int _drawItemBoundPosLoc = -1; int _drawItemBoundDimLoc = -1; int _drawItemStatusPosLoc = -1; @@ -30,21 +61,6 @@ namespace render { gpu::BufferPointer _itemBounds; gpu::BufferPointer _itemStatus; gpu::TexturePointer _statusIconMap; - - public: - - DrawStatus() {} - DrawStatus(const gpu::TexturePointer statusIconMap) { setStatusIconMap(statusIconMap); } - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); - - using JobModel = Job::ModelI; - - const gpu::PipelinePointer getDrawItemBoundsPipeline(); - const gpu::PipelinePointer getDrawItemStatusPipeline(); - - void setStatusIconMap(const gpu::TexturePointer& map); - const gpu::TexturePointer getStatusIconMap() const; }; } diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index d052221d97..9bf9a9acd3 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -22,10 +22,10 @@ using namespace render; void render::cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); - RenderArgs* args = renderContext->getArgs(); + RenderArgs* args = renderContext->args; ViewFrustum* frustum = args->_viewFrustum; details._considered += inItems.size(); @@ -86,11 +86,11 @@ struct BackToFrontSort { }; void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); auto& scene = sceneContext->_scene; - RenderArgs* args = renderContext->getArgs(); + RenderArgs* args = renderContext->args; // Allocate and simply copy @@ -127,7 +127,7 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { auto& scene = sceneContext->_scene; - RenderArgs* args = renderContext->getArgs(); + RenderArgs* args = renderContext->args; for (const auto& itemDetails : inItems) { auto& item = scene->getItem(itemDetails.id); @@ -153,7 +153,7 @@ void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, cons void render::renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems) { auto& scene = sceneContext->_scene; - RenderArgs* args = renderContext->getArgs(); + RenderArgs* args = renderContext->args; auto numItemsToDraw = glm::max((int)inItems.size(), maxDrawnItems); for (auto i = 0; i < numItemsToDraw; ++i) { @@ -185,8 +185,8 @@ void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderCo } void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); // render lights auto& scene = sceneContext->_scene; @@ -199,7 +199,7 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext inItems.emplace_back(ItemIDAndBounds(id, item.getBound())); } - RenderArgs* args = renderContext->getArgs(); + RenderArgs* args = renderContext->args; auto& details = args->_details.edit(RenderDetails::OTHER_ITEM); ItemIDsBounds culledItems; diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index eef4e0ade0..3ce1ed67fe 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -55,7 +55,7 @@ public: CullItems(CullFunctor cullFunctor) : _cullFunctor{ cullFunctor } {} void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { - const auto& args = renderContext->getArgs(); + const auto& args = renderContext->args; auto& details = args->_details.edit(T); outItems.clear(); outItems.reserve(inItems.size()); diff --git a/libraries/render/src/render/Engine.cpp b/libraries/render/src/render/Engine.cpp index ef949247b6..a68306939f 100644 --- a/libraries/render/src/render/Engine.cpp +++ b/libraries/render/src/render/Engine.cpp @@ -23,7 +23,7 @@ Engine::Engine() : void Engine::run() { // Sync GPU state before beginning to render - _renderContext->getArgs()->_context->syncCache(); + _renderContext->args->_context->syncCache(); for (auto job : _jobs) { job.run(_sceneContext, _renderContext); diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index fe49f2ff6f..b042fe32fe 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -60,7 +60,8 @@ public: JobConfig() : alwaysEnabled{ true }, enabled{ true } {} JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} - Q_PROPERTY(bool enabled MEMBER enabled) + Q_PROPERTY(bool enabled MEMBER enabled READ isEnabled) + bool isEnabled() { return alwaysEnabled || enabled; } bool alwaysEnabled{ true }; bool enabled; }; From 56cc4dc2238620559a0eec0c3964f49280772af3 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 22 Jan 2016 19:07:21 -0800 Subject: [PATCH 027/145] Add Job::Config to RenderShadowTask --- .../src/DeferredLightingEffect.cpp | 6 +- .../render-utils/src/DeferredLightingEffect.h | 4 +- .../render-utils/src/RenderDeferredTask.cpp | 5 -- .../render-utils/src/RenderShadowTask.cpp | 11 ++-- libraries/render-utils/src/RenderShadowTask.h | 27 ++++---- libraries/render/src/render/Context.h | 2 - libraries/render/src/render/Engine.cpp | 3 +- libraries/render/src/render/Task.h | 62 ++++++++++++------- 8 files changed, 66 insertions(+), 54 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 631f299a8d..f81ac2efd1 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -313,12 +313,12 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo { bool useSkyboxCubemap = (_skybox) && (_skybox->getCubemap()); - auto& program = _shadowMapStatus ? _directionalLightShadow : _directionalLight; - LightLocationsPtr locations = _shadowMapStatus ? _directionalLightShadowLocations : _directionalLightLocations; + auto& program = _shadowMapEnabled ? _directionalLightShadow : _directionalLight; + LightLocationsPtr locations = _shadowMapEnabled ? _directionalLightShadowLocations : _directionalLightLocations; // Setup the global directional pass pipeline { - if (_shadowMapStatus) { + if (_shadowMapEnabled) { if (useSkyboxCubemap) { program = _directionalSkyboxLightShadow; locations = _directionalSkyboxLightShadowLocations; diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index a9a76e00d9..ee4eeb445e 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -54,15 +54,15 @@ public: void setGlobalSkybox(const model::SkyboxPointer& skybox); const LightStage& getLightStage() { return _lightStage; } - void setShadowMapStatus(bool enable) { _shadowMapStatus = enable; }; + void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } private: DeferredLightingEffect() = default; LightStage _lightStage; - bool _shadowMapStatus{ false }; + bool _shadowMapEnabled{ false }; bool _ambientOcclusionEnabled{ false }; model::MeshPointer _spotLightMesh; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index ee5f99cc0b..d724a31de0 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -171,11 +171,6 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend return; } - // TODO: For now, lighting is controlled through a singleton, so it is distinct - DependencyManager::get()->setShadowMapStatus(renderContext->getShadowMapStatus()); - - renderContext->args->_context->syncCache(); - for (auto job : _jobs) { job.run(sceneContext, renderContext); } diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 75d01683ed..cc82079fd2 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -78,7 +78,7 @@ void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const }); } -RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) { +RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) : Task(std::make_shared()) { cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; // Prepare the ShapePipeline @@ -119,15 +119,14 @@ RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) { addJob("RenderShadowMap", shadowShapes, shapePlumber); } +void RenderShadowTask::configure(const Config& configuration) { + DependencyManager::get()->setShadowMapEnabled(configuration.enabled); +} + void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { assert(sceneContext); RenderArgs* args = renderContext->args; - // This feature is in a debugging stage - it must be turned on explicitly - if (!renderContext->getShadowMapStatus()) { - return; - } - // sanity checks if (!sceneContext->_scene || !args) { return; diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index ed79c4e1fb..5a5186f6f1 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -19,19 +19,11 @@ class ViewFrustum; -class RenderShadowMapConfig : public render::Job::Config { - Q_OBJECT -public: - RenderShadowMapConfig() : render::Job::Config(false) {} -}; - class RenderShadowMap { public: - using Config = RenderShadowMapConfig; - using JobModel = render::Job::ModelI; + using JobModel = render::Job::ModelI; RenderShadowMap(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - void configure(const Config&) {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ShapesIDsBounds& inShapes); @@ -39,13 +31,26 @@ protected: render::ShapePlumberPointer _shapePlumber; }; +class RenderShadowTaskConfig : public render::Task::Config { + Q_OBJECT +public: + RenderShadowTaskConfig() : render::Task::Config(false) {} + + Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty) + +signals: + void dirty(); +}; + class RenderShadowTask : public render::Task { public: + using Config = RenderShadowTaskConfig; + using JobModel = Model; + RenderShadowTask(render::CullFunctor shouldRender); + void configure(const Config& configuration); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - - using JobModel = Model; }; #endif // hifi_RenderShadowTask_h diff --git a/libraries/render/src/render/Context.h b/libraries/render/src/render/Context.h index dda20386fa..0d8c1c8d04 100644 --- a/libraries/render/src/render/Context.h +++ b/libraries/render/src/render/Context.h @@ -30,8 +30,6 @@ class RenderContext { public: RenderArgs* args; std::shared_ptr jobConfig{ nullptr }; - // TODO: gut this - bool _shadowMapStatus { false }; }; typedef std::shared_ptr RenderContextPointer; diff --git a/libraries/render/src/render/Engine.cpp b/libraries/render/src/render/Engine.cpp index a68306939f..be0481f97c 100644 --- a/libraries/render/src/render/Engine.cpp +++ b/libraries/render/src/render/Engine.cpp @@ -17,8 +17,7 @@ using namespace render; Engine::Engine() : _sceneContext(std::make_shared()), - _renderContext(std::make_shared()) -{ + _renderContext(std::make_shared()) { } void Engine::run() { diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index b042fe32fe..740090b39e 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -61,16 +61,39 @@ public: JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} Q_PROPERTY(bool enabled MEMBER enabled READ isEnabled) + Q_PROPERTY(bool alwaysEnabled READ isAlwaysEnabled) + bool isEnabled() { return alwaysEnabled || enabled; } + bool isAlwaysEnabled() { return alwaysEnabled; } + bool alwaysEnabled{ true }; bool enabled; }; +class Task; + +class TaskConfig : public JobConfig { + Q_OBJECT +public: + TaskConfig() : JobConfig() {} + TaskConfig(bool enabled) : JobConfig(enabled) {} + + void init(Task* task) { _task = task; } + +public slots: + void refresh(); + +private: + Task* _task; +}; + template void jobConfigure(T& model, const C& configuration) { model.configure(configuration); } template void jobConfigure(T&, const JobConfig&) { } +template void jobConfigure(T&, const TaskConfig&) { +} // FIXME: In c++17, use default classes of nullptr_t to combine these template void jobRun(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -249,26 +272,16 @@ public: std::string _name = ""; }; -class Task; - -class TaskConfig : public Job::Config { - Q_OBJECT -public: - void init(Task* task) { _task = task; } -public slots: - void refresh(); -private: - Task* _task; -}; - // A task is a specialized job to run a collection of other jobs // It is defined with JobModel = Task::Model +// +// A task with a custom config *must* use the templated constructor class Task { public: using Config = TaskConfig; using QConfig = Job::QConfig; - template class Model : public Job::Concept { + template class Model : public Job::Concept { public: using Data = T; @@ -276,18 +289,15 @@ public: Data _data; // The _config is unused; the model delegates to its data's _config - Model(Data data = Data()) : _data(data), Concept(std::make_shared()) { + Model(Data data = Data()) : _data(data), Concept(std::make_shared()) { _config = _data._config; - } - - virtual QConfig& getConfiguration() { - // Hook up the configuration if it is to be used std::static_pointer_cast(_config)->init(&_data); - return _config; + + applyConfiguration(); } void applyConfiguration() { - jobConfigure(_data, *_config); + jobConfigure(_data, *std::static_pointer_cast(_config)); } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { @@ -299,7 +309,9 @@ public: using Jobs = std::vector; + // A task must use its Config for construction Task() : _config{ std::make_shared() } {} + template Task(std::shared_ptr config) : _config{ config } {} // Queue a new job to the container; returns the job's output template const Varying addJob(std::string name, A&&... args) { @@ -311,7 +323,11 @@ public: return _jobs.back().getOutput(); } - QConfig getConfiguration() { return _config; } + QConfig getConfiguration() { + // If we are here, we were not made by a Model, so we must initialize our own config + std::static_pointer_cast(_config)->init(this); + return _config; + } void configure(const QObject& configuration) { for (auto& job : _jobs) { @@ -322,9 +338,9 @@ public: bool getEnableJob(size_t jobIndex) const { return _jobs.at(jobIndex).isEnabled(); } protected: - template friend class Model; + template friend class Model; - QConfig _config; + QConfig _config { nullptr }; Jobs _jobs; }; From 29f9d15af0ce83a89aa867ff3247d47ffa40cd8d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Sat, 23 Jan 2016 03:36:09 -0800 Subject: [PATCH 028/145] Remove render engine items from developer menu --- interface/src/Menu.cpp | 3 --- interface/src/Menu.h | 3 --- 2 files changed, 6 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9cbb031a61..8d96a68046 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -333,9 +333,6 @@ Menu::Menu() { // Developer > Render >>> MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render"); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes); - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DebugAmbientOcclusion); - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DebugShadows); - addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Antialiasing); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Stars, 0, true); // Developer > Render > Ambient Light diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 408ab15d5e..21454b7d66 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -152,7 +152,6 @@ namespace MenuOption { const QString AnimDebugDrawAnimPose = "Debug Draw Animation"; const QString AnimDebugDrawDefaultPose = "Debug Draw Default Pose"; const QString AnimDebugDrawPosition= "Debug Draw Position"; - const QString Antialiasing = "Antialiasing"; const QString AssetMigration = "ATP Asset Migration"; const QString Attachments = "Attachments..."; const QString AudioNetworkStats = "Audio Network Stats"; @@ -186,8 +185,6 @@ namespace MenuOption { const QString CopyPath = "Copy Path to Clipboard"; const QString CoupleEyelids = "Couple Eyelids"; const QString CrashInterface = "Crash Interface"; - const QString DebugShadows = "Shadows"; - const QString DebugAmbientOcclusion = "Ambient Occlusion"; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DeleteBookmark = "Delete Bookmark..."; const QString DisableActivityLogger = "Disable Activity Logger"; From e4af8d89f1be498dc74e93dacee96cecb2a2352c Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Sat, 23 Jan 2016 03:39:09 -0800 Subject: [PATCH 029/145] Only refresh engine settings on own thread --- libraries/render/src/render/Task.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/render/src/render/Task.cpp b/libraries/render/src/render/Task.cpp index 904c89cc6e..1ceea6befe 100644 --- a/libraries/render/src/render/Task.cpp +++ b/libraries/render/src/render/Task.cpp @@ -9,8 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "Task.h" - +#include #include // QObject #include "Context.h" @@ -18,9 +17,15 @@ #include "gpu/Batch.h" #include +#include "Task.h" + using namespace render; void TaskConfig::refresh() { - // FIXME: Only configure when on own thread (see RecordingInterface for example) + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "refresh", Qt::BlockingQueuedConnection); + return; + } + _task->configure(*this); } From 83827b6d241290c1f7c2b658480ecd61e1c8a3a7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jan 2016 14:57:32 -0800 Subject: [PATCH 030/145] add startup shortcut in current users context --- cmake/templates/NSIS.template.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 0b37cd5853..b398c2af7d 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -993,6 +993,12 @@ Function HandlePostInstallOptions ${NSD_GetState} $ServerStartupCheckbox $ServerStartupState ${If} $ServerStartupState == ${BST_CHECKED} + ; in case we added a shortcut in the global context, pull that now + SetShellVarContext all + Delete "$SMSTARTUP\@CONSOLE_SHORTCUT_NAME@.lnk" + + ; make a startup shortcut in this user's current context + SetShellVarContext current CreateShortCut "$SMSTARTUP\@CONSOLE_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" !insertmacro WritePostInstallOption @CONSOLE_STARTUP_REG_KEY@ YES From b42ab2179e1e8398e2a0258db95607b50ae87ccf Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 25 Jan 2016 13:48:23 -0800 Subject: [PATCH 031/145] Call QConfig QConfigPointer --- libraries/render/src/render/Task.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 740090b39e..a4ba7256aa 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -112,12 +112,12 @@ template void jobRunIO(T& model, const SceneContextP class Job { public: using Config = JobConfig; - using QConfig = std::shared_ptr; + using QConfigPointer = std::shared_ptr; // The guts of a job class Concept { public: - Concept(QConfig config) : _config(config) {} + Concept(QConfigPointer config) : _config(config) {} virtual ~Concept() = default; bool isEnabled() const { return _isEnabled; } @@ -126,13 +126,13 @@ public: virtual const Varying getInput() const { return Varying(); } virtual const Varying getOutput() const { return Varying(); } - virtual QConfig& getConfiguration() { return _config; } + virtual QConfigPointer& getConfiguration() { return _config; } virtual void applyConfiguration() = 0; virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; protected: - QConfig _config; + QConfigPointer _config; bool _isEnabled = true; }; using ConceptPointer = std::shared_ptr; @@ -251,7 +251,7 @@ public: const Varying getInput() const { return _concept->getInput(); } const Varying getOutput() const { return _concept->getOutput(); } - QConfig& getConfiguration() const { return _concept->getConfiguration(); } + QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); } void applyConfiguration() { return _concept->applyConfiguration(); } template T& edit() { @@ -279,7 +279,7 @@ public: class Task { public: using Config = TaskConfig; - using QConfig = Job::QConfig; + using QConfigPointer = Job::QConfigPointer; template class Model : public Job::Concept { public: @@ -316,7 +316,7 @@ public: // Queue a new job to the container; returns the job's output template const Varying addJob(std::string name, A&&... args) { _jobs.emplace_back(name, std::make_shared(std::forward(args)...)); - QConfig config = _jobs.back().getConfiguration(); + QConfigPointer config = _jobs.back().getConfiguration(); config->setParent(_config.get()); config->setObjectName(name.c_str()); QObject::connect(config.get(), SIGNAL(dirty()), _config.get(), SLOT(refresh())); @@ -340,7 +340,7 @@ public: protected: template friend class Model; - QConfig _config { nullptr }; + QConfigPointer _config { nullptr }; Jobs _jobs; }; From bed325d675444b36b446357274d8f3b210368975 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 25 Jan 2016 13:47:25 -0800 Subject: [PATCH 032/145] Add Graphics to general settings --- .../hifi/dialogs/GeneralPreferencesDialog.qml | 2 +- interface/src/ui/PreferencesDialog.cpp | 29 +++++++++++++++++++ libraries/render/src/render/Task.h | 24 ++++++++++----- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml index 81e4924204..c876ac6abb 100644 --- a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml @@ -7,7 +7,7 @@ PreferencesDialog { id: root objectName: "GeneralPreferencesDialog" title: "General Preferences" - showCategories: ["Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers"] + showCategories: ["Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Graphics"] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 7609939676..b25fe6775a 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -24,6 +24,10 @@ #include "Snapshot.h" #include "UserActivityLogger.h" +#include "AmbientOcclusionEffect.h" +#include "AntialiasingEffect.h" +#include "RenderShadowTask.h" + void setupPreferences() { auto preferences = DependencyManager::get(); @@ -310,4 +314,29 @@ void setupPreferences() { preference->setStep(1); preferences->addPreference(preference); } + + { + static const QString RENDER("Graphics"); + auto renderConfig = qApp->getRenderEngine()->getConfiguration(); + { + auto getter = [renderConfig]()->bool { return renderConfig->isJobEnabled(); }; + auto setter = [renderConfig](bool enable) { renderConfig->setJobEnabled(enable); }; + auto preference = new CheckPreference(RENDER, "Ambient Occlusion", getter, setter); + preferences->addPreference(preference); + } + + { + auto getter = [renderConfig]()->bool { return renderConfig->isJobEnabled(); }; + auto setter = [renderConfig](bool enable) { renderConfig->setJobEnabled(enable); }; + auto preference = new CheckPreference(RENDER, "Antialiasing", getter, setter); + preferences->addPreference(preference); + } + + { + auto getter = [renderConfig]()->bool { return renderConfig->isJobEnabled(); }; + auto setter = [renderConfig](bool enable) { renderConfig->setJobEnabled(enable); }; + auto preference = new CheckPreference(RENDER, "Shadows", getter, setter); + preferences->addPreference(preference); + } + } } diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index a4ba7256aa..37e6fdb8c5 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -60,11 +60,7 @@ public: JobConfig() : alwaysEnabled{ true }, enabled{ true } {} JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} - Q_PROPERTY(bool enabled MEMBER enabled READ isEnabled) - Q_PROPERTY(bool alwaysEnabled READ isAlwaysEnabled) - bool isEnabled() { return alwaysEnabled || enabled; } - bool isAlwaysEnabled() { return alwaysEnabled; } bool alwaysEnabled{ true }; bool enabled; @@ -80,6 +76,19 @@ public: void init(Task* task) { _task = task; } + 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); + } + + template void setJobEnabled(bool enable = true, std::string job = "") const { + getConfig(name)->enabled = enable; + refresh(); // trigger a Job->configure + } + template bool isJobEnabled(bool enable = true, std::string job = "") const { + return getConfig(job)->isEnabled(); + } + public slots: void refresh(); @@ -323,10 +332,11 @@ public: return _jobs.back().getOutput(); } - QConfig getConfiguration() { + std::shared_ptr getConfiguration() { + auto config = std::static_pointer_cast(_config); // If we are here, we were not made by a Model, so we must initialize our own config - std::static_pointer_cast(_config)->init(this); - return _config; + config->init(this); + return config; } void configure(const QObject& configuration) { From 14d907206eba769ac38411e86b9d032539ac6547 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 25 Jan 2016 14:36:14 -0800 Subject: [PATCH 033/145] Clean out job enable logic from Job --- .../render-utils/src/RenderDeferredTask.cpp | 23 --------------- .../render-utils/src/RenderDeferredTask.h | 28 ------------------- libraries/render/src/render/DrawStatus.h | 2 ++ libraries/render/src/render/Task.h | 23 ++++++--------- 4 files changed, 10 insertions(+), 66 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index d724a31de0..47a9c66111 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -113,8 +113,6 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { // AO job addJob("AmbientOcclusion"); - _jobs.back().setEnabled(false); - _occlusionJobIndex = (int)_jobs.size() - 1; // Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now. addJob("DrawLight", cullFunctor); @@ -124,20 +122,15 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { // AA job to be revisited addJob("Antialiasing"); - _antialiasingJobIndex = (int)_jobs.size() - 1; - enableJob(_antialiasingJobIndex, false); // Render transparent objects forward in LightingBuffer addJob("DrawTransparentDeferred", transparents, shapePlumber); // Lighting Buffer ready for tone mapping addJob("ToneMapping"); - _toneMappingJobIndex = (int)_jobs.size() - 1; // Debugging Deferred buffer job addJob("DebugDeferredBuffer"); - _drawDebugDeferredBufferIndex = (int)_jobs.size() - 1; - enableJob(_drawDebugDeferredBufferIndex, false); // Status icon rendering job { @@ -145,15 +138,11 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg"; auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath); addJob("DrawStatus", opaques, DrawStatus(statusIconMap)); - _drawStatusJobIndex = (int)_jobs.size() - 1; - enableJob(_drawStatusJobIndex, false); } addJob("DrawOverlay3D", shapePlumber); addJob("HitEffect"); - _drawHitEffectJobIndex = (int)_jobs.size() -1; - enableJob(_drawHitEffectJobIndex, false); addJob("Blit"); } @@ -437,18 +426,6 @@ void Blit::run(const SceneContextPointer& sceneContext, const RenderContextPoint }); } -void RenderDeferredTask::setToneMappingExposure(float exposure) { - if (_toneMappingJobIndex >= 0) { - _jobs[_toneMappingJobIndex].edit()._toneMappingEffect.setExposure(exposure); - } -} - -void RenderDeferredTask::setToneMappingToneCurve(int toneCurve) { - if (_toneMappingJobIndex >= 0) { - _jobs[_toneMappingJobIndex].edit()._toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)toneCurve); - } -} - void pipelineBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { if (pipeline.locations->normalFittingMapUnit > -1) { batch.setResourceTexture(pipeline.locations->normalFittingMapUnit, diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index fc41b33bee..f1115ab2b9 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -159,34 +159,6 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); using JobModel = Model; - - void setDrawDebugDeferredBuffer(int draw) { enableJob(_drawDebugDeferredBufferIndex, draw >= 0); } - bool doDrawDebugDeferredBuffer() const { return getEnableJob(_drawDebugDeferredBufferIndex); } - - void setDrawItemStatus(int draw) { enableJob(_drawStatusJobIndex, draw > 0); } - bool doDrawItemStatus() const { return getEnableJob(_drawStatusJobIndex); } - - void setDrawHitEffect(bool draw) { enableJob(_drawHitEffectJobIndex, draw); } - bool doDrawHitEffect() const { return getEnableJob(_drawHitEffectJobIndex); } - - void setOcclusionStatus(bool draw) { enableJob(_occlusionJobIndex, draw); } - bool doOcclusionStatus() const { return getEnableJob(_occlusionJobIndex); } - - void setAntialiasingStatus(bool draw) { enableJob(_antialiasingJobIndex, draw); } - bool doAntialiasingStatus() const { return getEnableJob(_antialiasingJobIndex); } - - void setToneMappingExposure(float exposure); - - void setToneMappingToneCurve(int toneCurve); - - -protected: - int _drawDebugDeferredBufferIndex; - int _drawStatusJobIndex; - int _drawHitEffectJobIndex; - int _occlusionJobIndex; - int _antialiasingJobIndex; - int _toneMappingJobIndex; }; #endif // hifi_RenderDeferredTask_h diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index f6d9f19206..c0d73ac40d 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -19,6 +19,8 @@ namespace render { class DrawStatusConfig : public Job::Config { Q_OBJECT public: + DrawStatusConfig() : Job::Config(false) {} + Q_PROPERTY(bool showDisplay MEMBER showDisplay NOTIFY dirty) Q_PROPERTY(bool showNetwork MEMBER showDisplay NOTIFY dirty) bool showDisplay{ false }; diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 37e6fdb8c5..578761a379 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -82,7 +82,7 @@ public: } template void setJobEnabled(bool enable = true, std::string job = "") const { - getConfig(name)->enabled = enable; + getConfig(job)->enabled = enable; refresh(); // trigger a Job->configure } template bool isJobEnabled(bool enable = true, std::string job = "") const { @@ -129,9 +129,6 @@ public: Concept(QConfigPointer config) : _config(config) {} virtual ~Concept() = default; - bool isEnabled() const { return _isEnabled; } - void setEnabled(bool isEnabled) { _isEnabled = isEnabled; } - virtual const Varying getInput() const { return Varying(); } virtual const Varying getOutput() const { return Varying(); } @@ -142,7 +139,6 @@ public: protected: QConfigPointer _config; - bool _isEnabled = true; }; using ConceptPointer = std::shared_ptr; @@ -161,7 +157,7 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - renderContext->jobConfig = std::static_pointer_cast(_config); + renderContext->jobConfig = std::static_pointer_cast(_config); if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { jobRun(_data, sceneContext, renderContext); } @@ -188,7 +184,7 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - renderContext->jobConfig = std::static_pointer_cast(_config); + renderContext->jobConfig = std::static_pointer_cast(_config); if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { jobRunI(_data, sceneContext, renderContext, _input.get()); } @@ -215,7 +211,7 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - renderContext->jobConfig = std::static_pointer_cast(_config); + renderContext->jobConfig = std::static_pointer_cast(_config); if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { jobRunO(_data, sceneContext, renderContext, _output.edit()); } @@ -245,7 +241,7 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - renderContext->jobConfig = std::static_pointer_cast(_config); + renderContext->jobConfig = std::static_pointer_cast(_config); if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); } @@ -255,9 +251,6 @@ public: Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} - bool isEnabled() const { return _concept->isEnabled(); } - void setEnabled(bool isEnabled) { _concept->setEnabled(isEnabled); } - const Varying getInput() const { return _concept->getInput(); } const Varying getOutput() const { return _concept->getOutput(); } QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); } @@ -310,9 +303,11 @@ public: } void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { + renderContext->jobConfig = std::static_pointer_cast(_config); + if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { jobRun(_data, sceneContext, renderContext); } + renderContext->jobConfig.reset(); } }; @@ -344,8 +339,6 @@ public: job.applyConfiguration(); } } - void enableJob(size_t jobIndex, bool enable = true) { _jobs.at(jobIndex).setEnabled(enable); } - bool getEnableJob(size_t jobIndex) const { return _jobs.at(jobIndex).isEnabled(); } protected: template friend class Model; From 46c937325eed013f2011d9d7518ef3a566969f7b Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 25 Jan 2016 14:40:13 -0800 Subject: [PATCH 034/145] Make Job MEMBER enabled explicit --- libraries/render-utils/src/AntialiasingEffect.h | 2 ++ libraries/render-utils/src/DebugDeferredBuffer.h | 1 + libraries/render-utils/src/HitEffect.h | 2 ++ libraries/render-utils/src/RenderDeferredTask.h | 2 ++ libraries/render/src/render/DrawStatus.h | 1 + libraries/render/src/render/Task.h | 2 +- 6 files changed, 9 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index 21be235921..1dd3a9ddcc 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -20,6 +20,8 @@ class AntiAliasingConfig : public render::Job::Config { Q_OBJECT public: AntiAliasingConfig() : render::Job::Config(false) {} + + Q_PROPERTY(bool enabled MEMBER enabled) }; class Antialiasing { diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index 90a8f91575..9940f3bfcc 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -21,6 +21,7 @@ class DebugDeferredBufferConfig : public render::Job::Config { public: DebugDeferredBufferConfig() : render::Job::Config(false) {} + Q_PROPERTY(bool enabled MEMBER enabled) Q_PROPERTY(int mode MEMBER mode WRITE setMode NOTIFY dirty) Q_PROPERTY(glm::vec4 size MEMBER size NOTIFY dirty) void setMode(int newMode); diff --git a/libraries/render-utils/src/HitEffect.h b/libraries/render-utils/src/HitEffect.h index e7b9b839c0..7d683534d0 100644 --- a/libraries/render-utils/src/HitEffect.h +++ b/libraries/render-utils/src/HitEffect.h @@ -15,6 +15,8 @@ class HitEffectConfig : public render::Job::Config { Q_OBJECT public: HitEffectConfig() : render::Job::Config(false) {} + + Q_PROPERTY(bool enabled MEMBER enabled) }; class HitEffect { diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index f1115ab2b9..2aa6199b90 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -45,6 +45,8 @@ class ToneMappingConfig : public render::Job::Config { Q_OBJECT public: ToneMappingConfig() : render::Job::Config(true) {} + + Q_PROPERTY(bool enabled MEMBER enabled) Q_PROPERTY(float exposure MEMBER exposure NOTIFY dirty); Q_PROPERTY(int curve MEMBER curve NOTIFY dirty); float exposure{ 0.0 }; diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index c0d73ac40d..982eba4990 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -21,6 +21,7 @@ namespace render { public: DrawStatusConfig() : Job::Config(false) {} + Q_PROPERTY(bool enabled MEMBER enabled) Q_PROPERTY(bool showDisplay MEMBER showDisplay NOTIFY dirty) Q_PROPERTY(bool showNetwork MEMBER showDisplay NOTIFY dirty) bool showDisplay{ false }; diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 578761a379..89407a2e2b 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -81,7 +81,7 @@ public: return findChild(name); } - template void setJobEnabled(bool enable = true, std::string job = "") const { + template void setJobEnabled(bool enable = true, std::string job = "") { getConfig(job)->enabled = enable; refresh(); // trigger a Job->configure } From e73902899b40607457e18f5f35c9be8658ce74a7 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 25 Jan 2016 15:02:03 -0800 Subject: [PATCH 035/145] Explicitly emit dirty for AO/Debug --- .../src/AmbientOcclusionEffect.cpp | 38 ------------------ .../render-utils/src/AmbientOcclusionEffect.h | 39 ++++++++++--------- .../render-utils/src/DebugDeferredBuffer.cpp | 5 ++- .../render-utils/src/DebugDeferredBuffer.h | 2 +- 4 files changed, 26 insertions(+), 58 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 4cb6d75f46..6bcb4bbdcb 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -33,44 +33,6 @@ #include "ssao_makeHorizontalBlur_frag.h" #include "ssao_makeVerticalBlur_frag.h" -void AmbientOcclusionEffectConfig::setRadius(float newRadius) { - radius = std::max(0.01f, radius); -} - -void AmbientOcclusionEffectConfig::setObscuranceLevel(float level) { - level = std::max(0.01f, level); -} - -void AmbientOcclusionEffectConfig::setFalloffBias(float bias) { - bias = std::max(0.0f, std::min(bias, 0.2f)); -} - -void AmbientOcclusionEffectConfig::setEdgeSharpness(float sharpness) { - sharpness = std::max(0.0f, (float)sharpness); -} - -void AmbientOcclusionEffectConfig::setBlurDeviation(float deviation) { - deviation = std::max(0.0f, deviation); -} - -void AmbientOcclusionEffectConfig::setNumSpiralTurns(float numTurns) { - numTurns = std::max(0.0f, (float)numTurns); -} - -void AmbientOcclusionEffectConfig::setNumSamples(int numSamples) { - numSamples = std::max(1.0f, (float) numSamples); -} - -void AmbientOcclusionEffectConfig::setResolutionLevel(int level) { - const int MAX_RESOLUTION_LEVEL = 4; - level = std::max(0, std::min(level, MAX_RESOLUTION_LEVEL)); -} - -void AmbientOcclusionEffectConfig::setBlurRadius(int radius) { - const int MAX_BLUR_RADIUS = 6; - radius = std::max(0, std::min(MAX_BLUR_RADIUS, radius)); -} - class GaussianDistribution { public: diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 6b91446b9c..2c2c9cfff2 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -22,28 +22,31 @@ public: AmbientOcclusionEffectConfig() : render::Job::Config(false) {} Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty) - Q_PROPERTY(float radius MEMBER radius WRITE setRadius NOTIFY dirty) - Q_PROPERTY(float obscuranceLevel MEMBER obscuranceLevel WRITE setObscuranceLevel NOTIFY dirty) - Q_PROPERTY(float falloffBias MEMBER falloffBias WRITE setFalloffBias NOTIFY dirty) - Q_PROPERTY(float edgeSharpness MEMBER edgeSharpness WRITE setEdgeSharpness NOTIFY dirty) - Q_PROPERTY(float blurDeviation MEMBER blurDeviation WRITE setBlurDeviation NOTIFY dirty) - Q_PROPERTY(float numSpiralTurns MEMBER numSpiralTurns WRITE setNumSpiralTurns NOTIFY dirty) - Q_PROPERTY(int numSamples MEMBER numSamples WRITE setNumSamples NOTIFY dirty) - Q_PROPERTY(int resolutionLevel MEMBER resolutionLevel WRITE setResolutionLevel NOTIFY dirty) - Q_PROPERTY(int blurRadius MEMBER blurRadius WRITE setBlurRadius NOTIFY dirty) Q_PROPERTY(bool ditheringEnabled MEMBER ditheringEnabled NOTIFY dirty) Q_PROPERTY(bool borderingEnabled MEMBER borderingEnabled NOTIFY dirty) + Q_PROPERTY(float radius MEMBER radius WRITE setRadius) + Q_PROPERTY(float obscuranceLevel MEMBER obscuranceLevel WRITE setObscuranceLevel) + Q_PROPERTY(float falloffBias MEMBER falloffBias WRITE setFalloffBias) + Q_PROPERTY(float edgeSharpness MEMBER edgeSharpness WRITE setEdgeSharpness) + Q_PROPERTY(float blurDeviation MEMBER blurDeviation WRITE setBlurDeviation) + Q_PROPERTY(float numSpiralTurns MEMBER numSpiralTurns WRITE setNumSpiralTurns) + Q_PROPERTY(int numSamples MEMBER numSamples WRITE setNumSamples) + Q_PROPERTY(int resolutionLevel MEMBER resolutionLevel WRITE setResolutionLevel) + Q_PROPERTY(int blurRadius MEMBER blurRadius WRITE setBlurRadius) Q_PROPERTY(double gpuTime READ getGpuTime) - void setRadius(float radius); - void setObscuranceLevel(float obscuranceLevel); - void setFalloffBias(float falloffBias); - void setEdgeSharpness(float edgeSharpness); - void setBlurDeviation(float blurDeviation); - void setNumSpiralTurns(float numSpiralTurns); - void setNumSamples(int numSamples); - void setResolutionLevel(int resolutionLevel); - void setBlurRadius(int blurRadius); + const int MAX_RESOLUTION_LEVEL = 4; + const int MAX_BLUR_RADIUS = 6; + + void setRadius(float newRadius) { radius = std::max(0.01f, newRadius); emit dirty(); } + void setObscuranceLevel(float level) { obscuranceLevel = std::max(0.01f, level); emit dirty(); } + void setFalloffBias(float bias) { falloffBias = std::max(0.0f, std::min(bias, 0.2f)); emit dirty(); } + void setEdgeSharpness(float sharpness) { edgeSharpness = std::max(0.0f, (float)sharpness); emit dirty(); } + void setBlurDeviation(float deviation) { blurDeviation = std::max(0.0f, deviation); emit dirty(); } + void setNumSpiralTurns(float turns) { numSpiralTurns = std::max(0.0f, (float)turns); emit dirty(); } + void setNumSamples(int samples) { numSamples = std::max(1.0f, (float)samples); emit dirty(); } + void setResolutionLevel(int level) { resolutionLevel = std::max(0, std::min(level, MAX_RESOLUTION_LEVEL)); emit dirty(); } + void setBlurRadius(int radius) { blurRadius = std::max(0, std::min(MAX_BLUR_RADIUS, radius)); emit dirty(); } double getGpuTime() { return gpuTime; } float radius{ 0.5f }; diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 744a2fb4ff..f8a35ad0df 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -28,11 +28,14 @@ using namespace render; void DebugDeferredBufferConfig::setMode(int newMode) { - if (newMode > (int)DebugDeferredBuffer::Custom || newMode < 0) { + if (newMode == mode) { + return; + } else if (newMode > (int)DebugDeferredBuffer::Custom || newMode < 0) { mode = (int)DebugDeferredBuffer::Custom; } else { mode = newMode; } + emit dirty(); } enum Slots { diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index 9940f3bfcc..c8e2ee0485 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -22,7 +22,7 @@ public: DebugDeferredBufferConfig() : render::Job::Config(false) {} Q_PROPERTY(bool enabled MEMBER enabled) - Q_PROPERTY(int mode MEMBER mode WRITE setMode NOTIFY dirty) + Q_PROPERTY(int mode MEMBER mode WRITE setMode) Q_PROPERTY(glm::vec4 size MEMBER size NOTIFY dirty) void setMode(int newMode); From 59ac93485e3efba23f79747e4348f4077e892b3c Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 25 Jan 2016 15:13:06 -0800 Subject: [PATCH 036/145] Propogate configuration changes through tasks --- libraries/render-utils/src/RenderShadowTask.cpp | 1 + libraries/render/src/render/Task.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index cc82079fd2..0771fcd9bf 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -121,6 +121,7 @@ RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) : Task(std::make_sha void RenderShadowTask::configure(const Config& configuration) { DependencyManager::get()->setShadowMapEnabled(configuration.enabled); + Task::configure(configuration); } void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 89407a2e2b..e2678f2735 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -101,8 +101,6 @@ template void jobConfigure(T& model, const C& configuration) } template void jobConfigure(T&, const JobConfig&) { } -template void jobConfigure(T&, const TaskConfig&) { -} // FIXME: In c++17, use default classes of nullptr_t to combine these template void jobRun(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { From 6934594bb96bb95c7c9ac413f70ba801a4914a70 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jan 2016 15:20:51 -0800 Subject: [PATCH 037/145] always use current context, ignore CPack InstallOptions --- cmake/templates/NSIS.template.in | 121 +------------------------------ 1 file changed, 2 insertions(+), 119 deletions(-) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index b398c2af7d..24f1e0000f 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -12,13 +12,7 @@ Var MUI_TEMP Var STARTMENU_FOLDER - Var SV_ALLUSERS Var START_MENU - Var DO_NOT_ADD_TO_PATH - Var ADD_TO_PATH_ALL_USERS - Var ADD_TO_PATH_CURRENT_USER - Var INSTALL_DESKTOP - Var IS_DEFAULT_INSTALLDIR ;-------------------------------- ;Include Modern UI @@ -678,7 +672,6 @@ FunctionEnd ;Keep these lines before any File command ;Only for solid compression (by default, solid compression is enabled for BZIP2 and LZMA) - ReserveFile "NSIS.InstallOptions.ini" ReserveFile "@POST_INSTALL_OPTIONS_PATH@" ;-------------------------------- @@ -768,7 +761,6 @@ Section "-Core installation" Push "Contact" Push "@CPACK_NSIS_CONTACT@" Call ConditionalAddToRegisty - !insertmacro INSTALLOPTIONS_READ $INSTALL_DESKTOP "NSIS.InstallOptions.ini" "Field 5" "State" !insertmacro MUI_STARTMENU_WRITE_BEGIN Application ;Create shortcuts @@ -799,27 +791,10 @@ Section "-Core installation" CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\@UNINSTALLER_NAME@" - ;Read a value from an InstallOptions INI file - !insertmacro INSTALLOPTIONS_READ $DO_NOT_ADD_TO_PATH "NSIS.InstallOptions.ini" "Field 2" "State" - !insertmacro INSTALLOPTIONS_READ $ADD_TO_PATH_ALL_USERS "NSIS.InstallOptions.ini" "Field 3" "State" - !insertmacro INSTALLOPTIONS_READ $ADD_TO_PATH_CURRENT_USER "NSIS.InstallOptions.ini" "Field 4" "State" - ; Write special uninstall registry entries Push "StartMenu" Push "$STARTMENU_FOLDER" Call ConditionalAddToRegisty - Push "DoNotAddToPath" - Push "$DO_NOT_ADD_TO_PATH" - Call ConditionalAddToRegisty - Push "AddToPathAllUsers" - Push "$ADD_TO_PATH_ALL_USERS" - Call ConditionalAddToRegisty - Push "AddToPathCurrentUser" - Push "$ADD_TO_PATH_CURRENT_USER" - Call ConditionalAddToRegisty - Push "InstallToDesktop" - Push "$INSTALL_DESKTOP" - Call ConditionalAddToRegisty !insertmacro MUI_STARTMENU_WRITE_END @@ -835,14 +810,6 @@ Section "-Add to path" doNotAddToPath: SectionEnd -;-------------------------------- -; Create custom pages -Function InstallOptionsPage - !insertmacro MUI_HEADER_TEXT "Install Options" "Choose options for installing @CPACK_NSIS_PACKAGE_NAME@" - !insertmacro INSTALLOPTIONS_DISPLAY "NSIS.InstallOptions.ini" - -FunctionEnd - ; Make sure nsDialogs is included before we use it !include "nsdialogs.nsh" @@ -1012,8 +979,6 @@ Function HandlePostInstallOptions ${NSD_GetState} $CopyFromProductionCheckbox $CopyFromProductionState ${If} $CopyFromProductionState == ${BST_CHECKED} - SetShellVarContext current - StrCpy $0 "$APPDATA\@BUILD_ORGANIZATION@" ; we need to copy whatever is in the data folder for production build to the data folder for this build @@ -1115,26 +1080,6 @@ Function un.onInit Quit ${EndSwitch} - ClearErrors - UserInfo::GetName - IfErrors noLM - Pop $0 - UserInfo::GetAccountType - Pop $1 - StrCmp $1 "Admin" 0 +3 - SetShellVarContext all - ;MessageBox MB_OK 'User "$0" is in the Admin group' - Goto done - StrCmp $1 "Power" 0 +3 - SetShellVarContext all - ;MessageBox MB_OK 'User "$0" is in the Power Users group' - Goto done - - noLM: - ;Get installation folder from registry if available - - done: - FunctionEnd ;--- Add/Remove callback functions: --- @@ -1195,16 +1140,6 @@ Section "Uninstall" ReadRegStr $START_MENU SHCTX \ "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu" ;MessageBox MB_OK "Start menu is in: $START_MENU" - ReadRegStr $DO_NOT_ADD_TO_PATH SHCTX \ - "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "DoNotAddToPath" - ReadRegStr $ADD_TO_PATH_ALL_USERS SHCTX \ - "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "AddToPathAllUsers" - ReadRegStr $ADD_TO_PATH_CURRENT_USER SHCTX \ - "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "AddToPathCurrentUser" - ;MessageBox MB_OK "Add to path: $DO_NOT_ADD_TO_PATH all users: $ADD_TO_PATH_ALL_USERS" - ReadRegStr $INSTALL_DESKTOP SHCTX \ - "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "InstallToDesktop" - ;MessageBox MB_OK "Install to desktop: $INSTALL_DESKTOP " @CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@ @@ -1294,16 +1229,6 @@ Section "Uninstall" SectionEnd !endif -;-------------------------------- -; determine admin versus local install -; Is install for "AllUsers" or "JustMe"? -; Default to "JustMe" - set to "AllUsers" if admin or on Win9x -; This function is used for the very first "custom page" of the installer. -; This custom page does not show up visibly, but it executes prior to the -; first visible page and sets up $INSTDIR properly... -; Choose different default installation folder based on SV_ALLUSERS... -; "Program Files" for AllUsers, "My Documents" for JustMe... - Function .onInit !ifdef INNER @@ -1348,48 +1273,6 @@ inst: ; Reads components status for registry !insertmacro SectionList "InitSection" - ; check to see if /D has been used to change - ; the install directory by comparing it to the - ; install directory that is expected to be the - ; default - StrCpy $IS_DEFAULT_INSTALLDIR 0 - StrCmp "$INSTDIR" "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" 0 +2 - StrCpy $IS_DEFAULT_INSTALLDIR 1 - - StrCpy $SV_ALLUSERS "JustMe" - ; if default install dir then change the default - ; if it is installed for JustMe - StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2 - StrCpy $INSTDIR "$DOCUMENTS\@CPACK_PACKAGE_INSTALL_DIRECTORY@" - - ClearErrors - UserInfo::GetName - IfErrors noLM - Pop $0 - UserInfo::GetAccountType - Pop $1 - StrCmp $1 "Admin" 0 +4 - SetShellVarContext all - ;MessageBox MB_OK 'User "$0" is in the Admin group' - StrCpy $SV_ALLUSERS "AllUsers" - Goto done - StrCmp $1 "Power" 0 +4 - SetShellVarContext all - ;MessageBox MB_OK 'User "$0" is in the Power Users group' - StrCpy $SV_ALLUSERS "AllUsers" - Goto done - - noLM: - StrCpy $SV_ALLUSERS "AllUsers" - ;Get installation folder from registry if available - - done: - StrCmp $SV_ALLUSERS "AllUsers" 0 +3 - StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2 - StrCpy $INSTDIR "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" - - StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 noOptionsPage - !insertmacro INSTALLOPTIONS_EXTRACT "NSIS.InstallOptions.ini" - - noOptionsPage: + ; use user for context of data/startup folders + SetShellVarContext current FunctionEnd From f393c5eeda0f098aa04f13ce473a11bcd35c9fc8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jan 2016 15:25:35 -0800 Subject: [PATCH 038/145] remove CMake templated code for path changes --- cmake/templates/NSIS.template.in | 279 ------------------------------- 1 file changed, 279 deletions(-) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 24f1e0000f..0bd1dfd214 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -199,277 +199,10 @@ Var AR_RegFlags !define MUI_HEADERIMAGE_UNBITMAP "@UNINSTALLER_HEADER_IMAGE@" !define MUI_ABORTWARNING -;-------------------------------- -; path functions - -!verbose 3 -!include "WinMessages.NSH" -!verbose 4 - -;---------------------------------------- -; based upon a script of "Written by KiCHiK 2003-01-18 05:57:02" -;---------------------------------------- -!verbose 3 -!include "WinMessages.NSH" -!verbose 4 -;==================================================== -; get_NT_environment -; Returns: the selected environment -; Output : head of the stack -;==================================================== -!macro select_NT_profile UN -Function ${UN}select_NT_profile - StrCmp $ADD_TO_PATH_ALL_USERS "1" 0 environment_single - DetailPrint "Selected environment for all users" - Push "all" - Return - environment_single: - DetailPrint "Selected environment for current user only." - Push "current" - Return -FunctionEnd -!macroend -!insertmacro select_NT_profile "" -!insertmacro select_NT_profile "un." -;---------------------------------------------------- -!define NT_current_env 'HKCU "Environment"' -!define NT_all_env 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' - -!ifndef WriteEnvStr_RegKey - !ifdef ALL_USERS - !define WriteEnvStr_RegKey \ - 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' - !else - !define WriteEnvStr_RegKey 'HKCU "Environment"' - !endif -!endif - -; AddToPath - Adds the given dir to the search path. -; Input - head of the stack -; Note - Win9x systems requires reboot - -Function AddToPath - Exch $0 - Push $1 - Push $2 - Push $3 - - # don't add if the path doesn't exist - IfFileExists "$0\*.*" "" AddToPath_done - - ReadEnvStr $1 PATH - ; if the path is too long for a NSIS variable NSIS will return a 0 - ; length string. If we find that, then warn and skip any path - ; modification as it will trash the existing path. - StrLen $2 $1 - IntCmp $2 0 CheckPathLength_ShowPathWarning CheckPathLength_Done CheckPathLength_Done - CheckPathLength_ShowPathWarning: - Messagebox MB_OK|MB_ICONEXCLAMATION "Warning! PATH too long installer unable to modify PATH!" - Goto AddToPath_done - CheckPathLength_Done: - Push "$1;" - Push "$0;" - Call StrStr - Pop $2 - StrCmp $2 "" "" AddToPath_done - Push "$1;" - Push "$0\;" - Call StrStr - Pop $2 - StrCmp $2 "" "" AddToPath_done - GetFullPathName /SHORT $3 $0 - Push "$1;" - Push "$3;" - Call StrStr - Pop $2 - StrCmp $2 "" "" AddToPath_done - Push "$1;" - Push "$3\;" - Call StrStr - Pop $2 - StrCmp $2 "" "" AddToPath_done - - Call IsNT - Pop $1 - StrCmp $1 1 AddToPath_NT - ; Not on NT - StrCpy $1 $WINDIR 2 - FileOpen $1 "$1\autoexec.bat" a - FileSeek $1 -1 END - FileReadByte $1 $2 - IntCmp $2 26 0 +2 +2 # DOS EOF - FileSeek $1 -1 END # write over EOF - FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n" - FileClose $1 - SetRebootFlag true - Goto AddToPath_done - - AddToPath_NT: - StrCmp $ADD_TO_PATH_ALL_USERS "1" ReadAllKey - ReadRegStr $1 ${NT_current_env} "PATH" - Goto DoTrim - ReadAllKey: - ReadRegStr $1 ${NT_all_env} "PATH" - DoTrim: - StrCmp $1 "" AddToPath_NTdoIt - Push $1 - Call Trim - Pop $1 - StrCpy $0 "$1;$0" - AddToPath_NTdoIt: - StrCmp $ADD_TO_PATH_ALL_USERS "1" WriteAllKey - WriteRegExpandStr ${NT_current_env} "PATH" $0 - Goto DoSend - WriteAllKey: - WriteRegExpandStr ${NT_all_env} "PATH" $0 - DoSend: - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - - AddToPath_done: - Pop $3 - Pop $2 - Pop $1 - Pop $0 -FunctionEnd - - -; RemoveFromPath - Remove a given dir from the path -; Input: head of the stack - -Function un.RemoveFromPath - Exch $0 - Push $1 - Push $2 - Push $3 - Push $4 - Push $5 - Push $6 - - IntFmt $6 "%c" 26 # DOS EOF - - Call un.IsNT - Pop $1 - StrCmp $1 1 unRemoveFromPath_NT - ; Not on NT - StrCpy $1 $WINDIR 2 - FileOpen $1 "$1\autoexec.bat" r - GetTempFileName $4 - FileOpen $2 $4 w - GetFullPathName /SHORT $0 $0 - StrCpy $0 "SET PATH=%PATH%;$0" - Goto unRemoveFromPath_dosLoop - - unRemoveFromPath_dosLoop: - FileRead $1 $3 - StrCpy $5 $3 1 -1 # read last char - StrCmp $5 $6 0 +2 # if DOS EOF - StrCpy $3 $3 -1 # remove DOS EOF so we can compare - StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine - StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine - StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine - StrCmp $3 "" unRemoveFromPath_dosLoopEnd - FileWrite $2 $3 - Goto unRemoveFromPath_dosLoop - unRemoveFromPath_dosLoopRemoveLine: - SetRebootFlag true - Goto unRemoveFromPath_dosLoop - - unRemoveFromPath_dosLoopEnd: - FileClose $2 - FileClose $1 - StrCpy $1 $WINDIR 2 - Delete "$1\autoexec.bat" - CopyFiles /SILENT $4 "$1\autoexec.bat" - Delete $4 - Goto unRemoveFromPath_done - - unRemoveFromPath_NT: - StrCmp $ADD_TO_PATH_ALL_USERS "1" unReadAllKey - ReadRegStr $1 ${NT_current_env} "PATH" - Goto unDoTrim - unReadAllKey: - ReadRegStr $1 ${NT_all_env} "PATH" - unDoTrim: - StrCpy $5 $1 1 -1 # copy last char - StrCmp $5 ";" +2 # if last char != ; - StrCpy $1 "$1;" # append ; - Push $1 - Push "$0;" - Call un.StrStr ; Find `$0;` in $1 - Pop $2 ; pos of our dir - StrCmp $2 "" unRemoveFromPath_done - ; else, it is in path - # $0 - path to add - # $1 - path var - StrLen $3 "$0;" - StrLen $4 $2 - StrCpy $5 $1 -$4 # $5 is now the part before the path to remove - StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove - StrCpy $3 $5$6 - - StrCpy $5 $3 1 -1 # copy last char - StrCmp $5 ";" 0 +2 # if last char == ; - StrCpy $3 $3 -1 # remove last char - - StrCmp $ADD_TO_PATH_ALL_USERS "1" unWriteAllKey - WriteRegExpandStr ${NT_current_env} "PATH" $3 - Goto unDoSend - unWriteAllKey: - WriteRegExpandStr ${NT_all_env} "PATH" $3 - unDoSend: - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - - unRemoveFromPath_done: - Pop $6 - Pop $5 - Pop $4 - Pop $3 - Pop $2 - Pop $1 - Pop $0 -FunctionEnd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Uninstall sutff -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ########################################### # Utility Functions # ########################################### -;==================================================== -; IsNT - Returns 1 if the current system is NT, 0 -; otherwise. -; Output: head of the stack -;==================================================== -; IsNT -; no input -; output, top of the stack = 1 if NT or 0 if not -; -; Usage: -; Call IsNT -; Pop $R0 -; ($R0 at this point is 1 or 0) - -!macro IsNT un -Function ${un}IsNT - Push $0 - ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion - StrCmp $0 "" 0 IsNT_yes - ; we are not NT. - Pop $0 - Push 0 - Return - - IsNT_yes: - ; NT!!! - Pop $0 - Push 1 -FunctionEnd -!macroend -!insertmacro IsNT "" -!insertmacro IsNT "un." - ; StrStr ; input, top of stack = string to search for ; top of stack-1 = string to search in @@ -802,14 +535,6 @@ Section "-Core installation" SectionEnd -Section "-Add to path" - Push $INSTDIR\bin - StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 doNotAddToPath - StrCmp $DO_NOT_ADD_TO_PATH "1" doNotAddToPath 0 - Call AddToPath - doNotAddToPath: -SectionEnd - ; Make sure nsDialogs is included before we use it !include "nsdialogs.nsh" @@ -1222,10 +947,6 @@ Section "Uninstall" DeleteRegKey /ifempty SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" - Push $INSTDIR\bin - StrCmp $DO_NOT_ADD_TO_PATH_ "1" doNotRemoveFromPath 0 - Call un.RemoveFromPath - doNotRemoveFromPath: SectionEnd !endif From aa2d19a61148a618c0aa2754351b3016d4f08f1f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jan 2016 15:32:23 -0800 Subject: [PATCH 039/145] remove two unused utility functions --- cmake/templates/NSIS.template.in | 64 -------------------------------- 1 file changed, 64 deletions(-) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 0bd1dfd214..09aa92ed47 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -203,70 +203,6 @@ Var AR_RegFlags # Utility Functions # ########################################### -; StrStr -; input, top of stack = string to search for -; top of stack-1 = string to search in -; output, top of stack (replaces with the portion of the string remaining) -; modifies no other variables. -; -; Usage: -; Push "this is a long ass string" -; Push "ass" -; Call StrStr -; Pop $R0 -; ($R0 at this point is "ass string") - -!macro StrStr un -Function ${un}StrStr -Exch $R1 ; st=haystack,old$R1, $R1=needle - Exch ; st=old$R1,haystack - Exch $R2 ; st=old$R1,old$R2, $R2=haystack - Push $R3 - Push $R4 - Push $R5 - StrLen $R3 $R1 - StrCpy $R4 0 - ; $R1=needle - ; $R2=haystack - ; $R3=len(needle) - ; $R4=cnt - ; $R5=tmp - loop: - StrCpy $R5 $R2 $R3 $R4 - StrCmp $R5 $R1 done - StrCmp $R5 "" done - IntOp $R4 $R4 + 1 - Goto loop -done: - StrCpy $R1 $R2 "" $R4 - Pop $R5 - Pop $R4 - Pop $R3 - Pop $R2 - Exch $R1 -FunctionEnd -!macroend -!insertmacro StrStr "" -!insertmacro StrStr "un." - -Function Trim ; Added by Pelaca - Exch $R1 - Push $R2 -Loop: - StrCpy $R2 "$R1" 1 -1 - StrCmp "$R2" " " RTrim - StrCmp "$R2" "$\n" RTrim - StrCmp "$R2" "$\r" RTrim - StrCmp "$R2" ";" RTrim - GoTo Done -RTrim: - StrCpy $R1 "$R1" -1 - Goto Loop -Done: - Pop $R2 - Exch $R1 -FunctionEnd - Function ConditionalAddToRegisty Pop $0 Pop $1 From 150a8d388ca879ea71aaf532bec43037bf020ce7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jan 2016 15:37:11 -0800 Subject: [PATCH 040/145] allow user to close running exec and continue --- cmake/templates/NSIS.template.in | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 09aa92ed47..801b773844 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -682,14 +682,25 @@ FunctionEnd !include nsProcess.nsh !macro PromptForRunningApplication applicationName displayName action prompter - ${nsProcess::FindProcess} ${applicationName} $R0 + !define UniqueID ${__LINE__} - ${If} $R0 == 0 - ; the process is running, ask the user if they want us to close it - MessageBox MB_OK|MB_ICONEXCLAMATION \ - "${displayName} cannot be ${action} while ${displayName} is running.$\r$\nPlease close it and try again." - Abort - ${EndIf} + Prompt_${UniqueID}: + + ${nsProcess::FindProcess} ${applicationName} $R0 + + ${If} $R0 == 0 + + ; the process is running, ask the user to close it + MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION \ + "${displayName} cannot be ${action} while ${displayName} is running.$\r$\nPlease close it to continue." \ + /SD IDCANCEL IDRETRY Prompt_${UniqueID} IDCANCEL 0 + + ; If the user decided to cancel, stop the current installer/uninstaller + Abort + + ${EndIf} + + !undef UniqueID !macroend !macro CheckForRunningApplications action prompter From aeb097664ee44781e4e9fe24c0c919c5b01825ed Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jan 2016 15:38:57 -0800 Subject: [PATCH 041/145] remove InstallOptionsPage from list of pages --- cmake/templates/NSIS.template.in | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 801b773844..a620347e0d 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -261,7 +261,6 @@ FunctionEnd !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@" - Page custom InstallOptionsPage !insertmacro MUI_PAGE_DIRECTORY ;Start Menu Folder Page Configuration From eabafa800cebf913e063deefa954413014361fde Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jan 2016 15:51:47 -0800 Subject: [PATCH 042/145] clarify application close behaviour --- cmake/templates/NSIS.template.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index a620347e0d..9c29e91e81 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -691,7 +691,7 @@ FunctionEnd ; the process is running, ask the user to close it MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION \ - "${displayName} cannot be ${action} while ${displayName} is running.$\r$\nPlease close it to continue." \ + "${displayName} cannot be ${action} while ${displayName} is running.$\r$\nPlease close it and click Retry to continue." \ /SD IDCANCEL IDRETRY Prompt_${UniqueID} IDCANCEL 0 ; If the user decided to cancel, stop the current installer/uninstaller From 9d4b5292236d16ac8a83c0fd26309a55ea46070b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jan 2016 15:57:42 -0800 Subject: [PATCH 043/145] remove any old admin desktop/sm shortcuts --- cmake/templates/NSIS.template.in | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 9c29e91e81..0505e44c43 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -432,12 +432,21 @@ Section "-Core installation" !insertmacro MUI_STARTMENU_WRITE_BEGIN Application ;Create shortcuts + + ; in case the user has any shortcuts from prior to when we were using the user context, remove those now + SetShellVarContext all + RMDir /r "$SMPROGRAMS\$STARTMENU_FOLDER" + + ; go back to current user context before setting up the startmenu folder + SetShellVarContext current + CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" @CPACK_NSIS_CREATE_ICONS@ @CPACK_NSIS_CREATE_ICONS_EXTRA@ ; Conditional handling for Interface specific options ${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@} + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@INTERFACE_SHORTCUT_NAME@.lnk" \ "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@" @@ -592,6 +601,15 @@ Var LaunchNowState Var CopyFromProductionState Function HandlePostInstallOptions + ; If the user created shortcuts from a time prior to when we using current user context, pull them now + SetShellVarContext all + + Delete "$DESKTOP\@INTERFACE_SHORTCUT_NAME@.lnk" + Delete "$DESKTOP\@CONSOLE_SHORTCUT_NAME@.lnk" + + ; return the context to the current user so the shortcuts are correct + SetShellVarContext current + ${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@} ; check if the user asked for a desktop shortcut to High Fidelity ${NSD_GetState} $DesktopClientCheckbox $DesktopClientState From c7228ce02073a3680e9aebc65ecb5d353c540f45 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jan 2016 15:59:17 -0800 Subject: [PATCH 044/145] ensure current user context for uninstaller --- cmake/templates/NSIS.template.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 0505e44c43..f8d7dfe75f 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -826,6 +826,9 @@ FunctionEnd !ifdef INNER Section "Uninstall" + ; use user for context of data/startup folders + SetShellVarContext current + ReadRegStr $START_MENU SHCTX \ "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu" ;MessageBox MB_OK "Start menu is in: $START_MENU" From 57f9d82efabca1ff53a3409908539acb22647d8d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jan 2016 16:13:39 -0800 Subject: [PATCH 045/145] remove shortcuts from custom start menu location --- cmake/templates/NSIS.template.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index f8d7dfe75f..fa424ea632 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -897,6 +897,8 @@ Section "Uninstall" ; try to fix it. StrCpy $MUI_TEMP "$START_MENU" Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" + Delete "$SMPROGRAMS\$MUI_TEMP\@INTERFACE_SHORTCUT_NAME@.lnk" + Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_SHORTCUT_NAME@.lnk" @CPACK_NSIS_DELETE_ICONS_EXTRA@ ;Delete empty start menu parent diretories From f4ece26271742587f0c4ea264c36dc46e3097347 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jan 2016 16:16:29 -0800 Subject: [PATCH 046/145] use install dir written to registry as potential default --- cmake/templates/NSIS.template.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index fa424ea632..2303ddee35 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -378,7 +378,7 @@ Section "-Core installation" @CPACK_NSIS_FULL_INSTALL@ ;Store installation folder - WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR + WriteRegStr HKLM "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR ;Package the signed uninstaller produced by the inner loop !ifndef INNER @@ -919,6 +919,8 @@ Section "Uninstall" SectionEnd !endif +InstallDirRegKey HKLM "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" + Function .onInit !ifdef INNER From e4110ea401976b1749ffa015dd11a62b9caa7adf Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 25 Jan 2016 17:21:54 -0800 Subject: [PATCH 047/145] install for all users, EXCEPT the startup menu item --- cmake/templates/NSIS.template.in | 40 +++++++++++--------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 2303ddee35..b698d6072a 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -207,7 +207,7 @@ Function ConditionalAddToRegisty Pop $0 Pop $1 StrCmp "$0" "" ConditionalAddToRegisty_EmptyString - WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \ + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \ "$1" "$0" ;MessageBox MB_OK "Set Registry: '$1' to '$0'" DetailPrint "Set install registry entry: '$1' to '$0'" @@ -264,7 +264,7 @@ FunctionEnd !insertmacro MUI_PAGE_DIRECTORY ;Start Menu Folder Page Configuration - !define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX" + !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKLM" !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER @@ -433,20 +433,12 @@ Section "-Core installation" ;Create shortcuts - ; in case the user has any shortcuts from prior to when we were using the user context, remove those now - SetShellVarContext all - RMDir /r "$SMPROGRAMS\$STARTMENU_FOLDER" - - ; go back to current user context before setting up the startmenu folder - SetShellVarContext current - CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" @CPACK_NSIS_CREATE_ICONS@ @CPACK_NSIS_CREATE_ICONS_EXTRA@ ; Conditional handling for Interface specific options ${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@} - CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\@INTERFACE_SHORTCUT_NAME@.lnk" \ "$INSTDIR\@INTERFACE_WIN_EXEC_NAME@" @@ -601,15 +593,6 @@ Var LaunchNowState Var CopyFromProductionState Function HandlePostInstallOptions - ; If the user created shortcuts from a time prior to when we using current user context, pull them now - SetShellVarContext all - - Delete "$DESKTOP\@INTERFACE_SHORTCUT_NAME@.lnk" - Delete "$DESKTOP\@CONSOLE_SHORTCUT_NAME@.lnk" - - ; return the context to the current user so the shortcuts are correct - SetShellVarContext current - ${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@} ; check if the user asked for a desktop shortcut to High Fidelity ${NSD_GetState} $DesktopClientCheckbox $DesktopClientState @@ -646,6 +629,9 @@ Function HandlePostInstallOptions SetShellVarContext current CreateShortCut "$SMSTARTUP\@CONSOLE_SHORTCUT_NAME@.lnk" "$INSTDIR\@CONSOLE_INSTALL_SUBDIR@\@CONSOLE_WIN_EXEC_NAME@" + ; reset the shell var context back + SetShellVarContext all + !insertmacro WritePostInstallOption @CONSOLE_STARTUP_REG_KEY@ YES ${Else} !insertmacro WritePostInstallOption @CONSOLE_STARTUP_REG_KEY@ NO @@ -826,10 +812,10 @@ FunctionEnd !ifdef INNER Section "Uninstall" - ; use user for context of data/startup folders - SetShellVarContext current + ; use all users context for data/startup folders + SetShellVarContext all - ReadRegStr $START_MENU SHCTX \ + ReadRegStr $START_MENU HKLM \ "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu" ;MessageBox MB_OK "Start menu is in: $START_MENU" @@ -850,13 +836,13 @@ Section "Uninstall" ;Remove the uninstaller itself. Delete "$INSTDIR\@UNINSTALLER_NAME@" - DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" ;Remove the installation directory if it is empty. RMDir "$INSTDIR" ; Remove the registry entries. - DeleteRegKey SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + DeleteRegKey HKLM "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" ; Removes all optional components !insertmacro SectionList "RemoveSection_CPack" @@ -914,7 +900,7 @@ Section "Uninstall" StrCmp "$MUI_TEMP" "$SMPROGRAMS" secondStartMenuDeleteLoopDone secondStartMenuDeleteLoop secondStartMenuDeleteLoopDone: - DeleteRegKey /ifempty SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + DeleteRegKey /ifempty HKLM "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" SectionEnd !endif @@ -965,6 +951,6 @@ inst: ; Reads components status for registry !insertmacro SectionList "InitSection" - ; use user for context of data/startup folders - SetShellVarContext current + ; use all users for context of data/startup folders + SetShellVarContext all FunctionEnd From 1bdeeeceeb75302016b67029e22f3a2f63349d66 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 12 Jan 2016 17:24:14 -0800 Subject: [PATCH 048/145] AnimSkeleton: Added getPre and Post rotation accessors --- libraries/animation/src/AnimSkeleton.cpp | 21 +++++++++++++++++---- libraries/animation/src/AnimSkeleton.h | 9 +++++++-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/libraries/animation/src/AnimSkeleton.cpp b/libraries/animation/src/AnimSkeleton.cpp index 8e3d716aac..8f45b785d1 100644 --- a/libraries/animation/src/AnimSkeleton.cpp +++ b/libraries/animation/src/AnimSkeleton.cpp @@ -59,8 +59,14 @@ const AnimPose& AnimSkeleton::getAbsoluteDefaultPose(int jointIndex) const { return _absoluteDefaultPoses[jointIndex]; } -const glm::quat AnimSkeleton::getPreRotation(int jointIndex) const { - return _joints[jointIndex].preRotation; +// get pre multiplied transform which should include FBX pre potations +const AnimPose& AnimSkeleton::getPreRotationPose(int jointIndex) const { + return _relativePreRotationPoses[jointIndex]; +} + +// get post multiplied transform which might include FBX offset transformations +const AnimPose& AnimSkeleton::getPostRotationPose(int jointIndex) const { + return _relativePostRotationPoses[jointIndex]; } int AnimSkeleton::getParentIndex(int jointIndex) const { @@ -99,13 +105,20 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector& joints) // build a chache of default poses _absoluteDefaultPoses.reserve(joints.size()); _relativeDefaultPoses.reserve(joints.size()); + _relativePreRotationPoses.reserve(joints.size()); + _relativePostRotationPoses.reserve(joints.size()); // iterate over FBXJoints and extract the bind pose information. for (int i = 0; i < (int)joints.size(); i++) { + // build pre and post transforms + glm::mat4 preRotationTransform = _joints[i].preTransform * glm::mat4_cast(_joints[i].preRotation); + glm::mat4 postRotationTransform = glm::mat4_cast(_joints[i].postRotation) * _joints[i].postTransform; + _relativePreRotationPoses.push_back(AnimPose(preRotationTransform)); + _relativePostRotationPoses.push_back(AnimPose(postRotationTransform)); + // build relative and absolute default poses - glm::mat4 rotTransform = glm::mat4_cast(_joints[i].preRotation * _joints[i].rotation * _joints[i].postRotation); - glm::mat4 relDefaultMat = glm::translate(_joints[i].translation) * _joints[i].preTransform * rotTransform * _joints[i].postTransform; + glm::mat4 relDefaultMat = glm::translate(_joints[i].translation) * preRotationTransform * glm::mat4_cast(_joints[i].rotation) * postRotationTransform; AnimPose relDefaultPose(relDefaultMat); _relativeDefaultPoses.push_back(relDefaultPose); int parentIndex = getParentIndex(i); diff --git a/libraries/animation/src/AnimSkeleton.h b/libraries/animation/src/AnimSkeleton.h index 7312fea6b1..757f4e5c3e 100644 --- a/libraries/animation/src/AnimSkeleton.h +++ b/libraries/animation/src/AnimSkeleton.h @@ -42,8 +42,11 @@ public: const AnimPose& getAbsoluteDefaultPose(int jointIndex) const; const AnimPoseVec& getAbsoluteDefaultPoses() const { return _absoluteDefaultPoses; } - // get pre-rotation aka Maya's joint orientation. - const glm::quat getPreRotation(int jointIndex) const; + // get pre transform which should include FBX pre potations + const AnimPose& getPreRotationPose(int jointIndex) const; + + // get post transform which might include FBX offset transformations + const AnimPose& getPostRotationPose(int jointIndex) const; int getParentIndex(int jointIndex) const; @@ -64,6 +67,8 @@ protected: AnimPoseVec _relativeBindPoses; AnimPoseVec _relativeDefaultPoses; AnimPoseVec _absoluteDefaultPoses; + AnimPoseVec _relativePreRotationPoses; + AnimPoseVec _relativePostRotationPoses; // no copies AnimSkeleton(const AnimSkeleton&) = delete; From 3cee3cbb5aa4b28f43cea90fb2e509e859f6127a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 25 Jan 2016 18:32:12 -0800 Subject: [PATCH 049/145] Avatar Developer Menu: added animation debug options This options are for for developers only and might help debug animation related issues. * Enable Inverse Kinematics: this can be toggled to disable IK for the avatar. * Enable Anim Pre and Post Rotations: this option can be used to use FBX pre-rotations from source avatar animations, instead of the current default, which is to use them from the source model. This only effects FBX files loaded by the animation system, it does not affect changing model orientations via JavaScript. --- interface/src/Menu.cpp | 4 ++ interface/src/Menu.h | 2 + interface/src/avatar/MyAvatar.cpp | 10 +++++ interface/src/avatar/MyAvatar.h | 2 + libraries/animation/src/AnimClip.cpp | 60 +++++++++++++++++----------- libraries/animation/src/AnimClip.h | 3 ++ libraries/animation/src/Rig.cpp | 10 +++++ libraries/animation/src/Rig.h | 4 ++ 8 files changed, 72 insertions(+), 23 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9cbb031a61..f1203b9df1 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -479,6 +479,10 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::TurnWithHead, 0, false); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ComfortMode, 0, true); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::UseAnimPreAndPostRotations, 0, false, + avatar, SLOT(setUseAnimPreAndPostRotations(bool))); + addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::EnableInverseKinematics, 0, true, + avatar, SLOT(setEnableInverseKinematics(bool))); addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::KeyboardMotorControl, Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehaviorFromMenu()), diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 408ab15d5e..7b9cca2c63 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -208,6 +208,7 @@ namespace MenuOption { const QString EchoServerAudio = "Echo Server Audio"; const QString Enable3DTVMode = "Enable 3DTV Mode"; const QString EnableCharacterController = "Enable avatar collisions"; + const QString EnableInverseKinematics = "Enable Inverse Kinematics"; const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation"; const QString ExpandMyAvatarTiming = "Expand /myAvatar"; const QString ExpandOtherAvatarTiming = "Expand /otherAvatar"; @@ -302,6 +303,7 @@ namespace MenuOption { const QString UploadAsset = "Upload File to Asset Server"; const QString UseAudioForMouth = "Use Audio for Mouth"; const QString UseCamera = "Use Camera"; + const QString UseAnimPreAndPostRotations = "Use Anim Pre and Post Rotations"; const QString VelocityFilter = "Velocity Filter"; const QString VisibleToEveryone = "Everyone"; const QString VisibleToFriends = "Friends"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e06dce2324..756dc6adea 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -647,6 +648,15 @@ void MyAvatar::setEnableMeshVisible(bool isEnabled) { _skeletonModel.setVisibleInScene(isEnabled, scene); } +void MyAvatar::setUseAnimPreAndPostRotations(bool isEnabled) { + AnimClip::usePreAndPostPoseFromAnim = isEnabled; + reset(true); +} + +void MyAvatar::setEnableInverseKinematics(bool isEnabled) { + _rig->setEnableInverseKinematics(isEnabled); +} + void MyAvatar::loadData() { Settings settings; settings.beginGroup("Avatar"); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 10ce962821..ed6c3cb883 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -260,6 +260,8 @@ public slots: void setEnableDebugDrawPosition(bool isEnabled); bool getEnableMeshVisible() const { return _skeletonModel.isVisible(); } void setEnableMeshVisible(bool isEnabled); + void setUseAnimPreAndPostRotations(bool isEnabled); + void setEnableInverseKinematics(bool isEnabled); Q_INVOKABLE void setAnimGraphUrl(const QUrl& url); glm::vec3 getPositionForAudio(); diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 986bb0a30e..32da64808b 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -13,6 +13,8 @@ #include "AnimationLogging.h" #include "AnimUtil.h" +bool AnimClip::usePreAndPostPoseFromAnim = false; + AnimClip::AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag) : AnimNode(AnimNode::Type::Clip, id), _startFrame(startFrame), @@ -109,6 +111,8 @@ void AnimClip::copyFromNetworkAnim() { for (int frame = 0; frame < frameCount; frame++) { + const FBXAnimationFrame& fbxAnimFrame = geom.animationFrames[frame]; + // init all joints in animation to default pose // this will give us a resonable result for bones in the model skeleton but not in the animation. _anim[frame].reserve(skeletonJointCount); @@ -119,36 +123,46 @@ void AnimClip::copyFromNetworkAnim() { for (int animJoint = 0; animJoint < animJointCount; animJoint++) { int skeletonJoint = jointMap[animJoint]; + const glm::vec3& fbxAnimTrans = fbxAnimFrame.translations[animJoint]; + const glm::quat& fbxAnimRot = fbxAnimFrame.rotations[animJoint]; + // skip joints that are in the animation but not in the skeleton. if (skeletonJoint >= 0 && skeletonJoint < skeletonJointCount) { - const glm::vec3& fbxZeroTrans = geom.animationFrames[0].translations[animJoint]; -#ifdef USE_PRE_ROT_FROM_ANIM - // TODO: This is the correct way to apply the pre rotations from maya, however - // the current animation set has incorrect preRotations for the left wrist and thumb - // so it looks wrong if we enable this code. - glm::quat preRotation = animSkeleton.getPreRotation(animJoint); -#else - // TODO: This is the legacy approach, this does not work when animations and models do not - // have the same set of pre rotations. For example when mixing maya models with blender animations. - glm::quat preRotation = _skeleton->getRelativeBindPose(skeletonJoint).rot; -#endif - const AnimPose& relDefaultPose = _skeleton->getRelativeDefaultPose(skeletonJoint); + AnimPose preRot, postRot; + if (usePreAndPostPoseFromAnim) { + preRot = animSkeleton.getPreRotationPose(animJoint); + postRot = animSkeleton.getPostRotationPose(animJoint); + } else { + // In order to support Blender, which does not have preRotation FBX support, we use the models defaultPose as the reference frame for the animations. + preRot = AnimPose(glm::vec3(1.0f), _skeleton->getRelativeBindPose(skeletonJoint).rot, glm::vec3()); + postRot = AnimPose::identity; + } - // used to adjust translation offsets, so large translation animatons on the reference skeleton + // cancel out scale + preRot.scale = glm::vec3(1.0f); + postRot.scale = glm::vec3(1.0f); + + AnimPose rot(glm::vec3(1.0f), fbxAnimRot, glm::vec3()); + + // adjust translation offsets, so large translation animatons on the reference skeleton // will be adjusted when played on a skeleton with short limbs. - float limbLengthScale = fabsf(glm::length(fbxZeroTrans)) <= 0.0001f ? 1.0f : (glm::length(relDefaultPose.trans) / glm::length(fbxZeroTrans)); + const glm::vec3& fbxZeroTrans = geom.animationFrames[0].translations[animJoint]; + const AnimPose& relDefaultPose = _skeleton->getRelativeDefaultPose(skeletonJoint); + float boneLengthScale = 1.0f; + const float EPSILON = 0.0001f; + if (fabsf(glm::length(fbxZeroTrans)) > EPSILON) { + boneLengthScale = glm::length(relDefaultPose.trans) / glm::length(fbxZeroTrans); + } - AnimPose& pose = _anim[frame][skeletonJoint]; - const FBXAnimationFrame& fbxAnimFrame = geom.animationFrames[frame]; + AnimPose trans; + if (usePreAndPostPoseFromAnim) { + trans = AnimPose(glm::vec3(1.0f), glm::quat(), boneLengthScale * (fbxAnimTrans + (fbxAnimTrans - fbxZeroTrans))); + } else { + trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans + boneLengthScale * (fbxAnimTrans - fbxZeroTrans)); + } - // rotation in fbxAnimationFrame is a delta from its preRotation. - pose.rot = preRotation * fbxAnimFrame.rotations[animJoint]; - - // translation in fbxAnimationFrame is not a delta. - // convert it into a delta by subtracting from the first frame. - const glm::vec3& fbxTrans = fbxAnimFrame.translations[animJoint]; - pose.trans = relDefaultPose.trans + limbLengthScale * (fbxTrans - fbxZeroTrans); + _anim[frame][skeletonJoint] = trans * preRot * rot * postRot; } } } diff --git a/libraries/animation/src/AnimClip.h b/libraries/animation/src/AnimClip.h index 934f3f3ed8..91215d0d44 100644 --- a/libraries/animation/src/AnimClip.h +++ b/libraries/animation/src/AnimClip.h @@ -25,6 +25,9 @@ class AnimClip : public AnimNode { public: friend class AnimTests; + static bool usePreAndPostPoseFromAnim; + static bool useTransFromAnim; + AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag); virtual ~AnimClip() override; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index df92d7d912..4d72bfbaea 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -464,6 +464,10 @@ void Rig::computeEyesInRootFrame(const AnimPoseVec& poses) { } } +void Rig::setEnableInverseKinematics(bool enable) { + _enableInverseKinematics = enable; +} + AnimPose Rig::getAbsoluteDefaultPose(int index) const { if (_animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints()) { return _absoluteDefaultPoses[index]; @@ -705,6 +709,12 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos } t += deltaTime; + + if (_enableInverseKinematics) { + _animVars.set("ikOverlayAlpha", 1.0f); + } else { + _animVars.set("ikOverlayAlpha", 0.0f); + } } _lastFront = front; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index d26be83d36..cf96c6dc16 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -208,6 +208,8 @@ public: void computeAvatarBoundingCapsule(const FBXGeometry& geometry, float& radiusOut, float& heightOut, glm::vec3& offsetOut) const; + void setEnableInverseKinematics(bool enable); + protected: bool isIndexValid(int index) const { return _animSkeleton && index >= 0 && index < _animSkeleton->getNumJoints(); } void updateAnimationStateHandlers(); @@ -290,6 +292,8 @@ public: std::map _origRoleAnimations; std::vector _prefetchedAnimations; + bool _enableInverseKinematics { true }; + private: QMap _stateHandlers; int _nextStateHandlerId { 0 }; From 3b062b7a31e334c73cc1d52add8be82f157b19bd Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 25 Jan 2016 18:47:45 -0800 Subject: [PATCH 050/145] AnimClip: special case the translation on the eyes --- libraries/animation/src/AnimClip.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 32da64808b..0ab83c1870 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -156,7 +156,10 @@ void AnimClip::copyFromNetworkAnim() { } AnimPose trans; - if (usePreAndPostPoseFromAnim) { + if (_skeleton->getJointName(skeletonJoint) == "RightEye" || _skeleton->getJointName(skeletonJoint) == "LeftEye") { + // preserve model eye translation + trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans); + } else if (usePreAndPostPoseFromAnim) { trans = AnimPose(glm::vec3(1.0f), glm::quat(), boneLengthScale * (fbxAnimTrans + (fbxAnimTrans - fbxZeroTrans))); } else { trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans + boneLengthScale * (fbxAnimTrans - fbxZeroTrans)); From 956e70e415471bd58c4e55364ff907cda8118da4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 26 Jan 2016 22:07:05 +1300 Subject: [PATCH 051/145] Make entity properties return undefined value after entity is deleted --- libraries/entities/src/EntityItemProperties.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 0ccd6a74bd..0a72789485 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -321,6 +321,11 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool QScriptValue properties = engine->newObject(); EntityItemProperties defaultEntityProperties; + if (_created == UNKNOWN_CREATED_TIME) { + // No entity properties can have been set so return without setting any default, zero property values. + return properties; + } + if (_idSet) { COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_ALWAYS(id, _id.toString()); } From 2834dee00d46c66d05d687d5100fca998f41808e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 26 Jan 2016 22:07:42 +1300 Subject: [PATCH 052/145] Remove erroneous edit.js call with missing entity ID --- examples/libraries/entitySelectionTool.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 94ffb48a71..c1675ef044 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -1515,7 +1515,6 @@ SelectionDisplay = (function() { } that.updateRotationHandles(); - that.highlightSelectable(); var rotation, dimensions, position, registrationPoint; From 641a6e9c30423159ae2a9b1d7d674f7f04a1123e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 26 Jan 2016 09:29:02 -0800 Subject: [PATCH 053/145] Fix injector handling for when it falls behind --- libraries/audio/src/AudioConstants.h | 2 +- libraries/audio/src/AudioInjector.cpp | 87 +++++++++++--------- libraries/audio/src/AudioInjector.h | 2 +- libraries/audio/src/AudioInjectorManager.cpp | 2 +- 4 files changed, 53 insertions(+), 40 deletions(-) diff --git a/libraries/audio/src/AudioConstants.h b/libraries/audio/src/AudioConstants.h index b1c810710e..91080017a5 100644 --- a/libraries/audio/src/AudioConstants.h +++ b/libraries/audio/src/AudioConstants.h @@ -29,7 +29,7 @@ namespace AudioConstants { const int NETWORK_FRAME_SAMPLES_PER_CHANNEL = NETWORK_FRAME_BYTES_PER_CHANNEL / sizeof(AudioSample); const float NETWORK_FRAME_MSECS = (AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL / (float)AudioConstants::SAMPLE_RATE) * 1000.0f; - const unsigned int NETWORK_FRAME_USECS = (unsigned int)floorf(NETWORK_FRAME_MSECS * 1000.0f); + const int NETWORK_FRAME_USECS = floorf(NETWORK_FRAME_MSECS * 1000.0f); const int MIN_SAMPLE_VALUE = std::numeric_limits::min(); const int MAX_SAMPLE_VALUE = std::numeric_limits::max(); } diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 1f15007339..bec4921675 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -158,10 +158,10 @@ bool AudioInjector::injectLocally() { } const uchar MAX_INJECTOR_VOLUME = 0xFF; -static const uint64_t NEXT_FRAME_DELTA_ERROR_OR_FINISHED = 0; -static const uint64_t NEXT_FRAME_DELTA_IMMEDIATELY = 1; +static const int64_t NEXT_FRAME_DELTA_ERROR_OR_FINISHED = -1; +static const int64_t NEXT_FRAME_DELTA_IMMEDIATELY = 0; -uint64_t AudioInjector::injectNextFrame() { +int64_t AudioInjector::injectNextFrame() { if (_state == AudioInjector::State::Finished) { qDebug() << "AudioInjector::injectNextFrame called but AudioInjector has finished and was not restarted. Returning."; @@ -198,110 +198,123 @@ uint64_t AudioInjector::injectNextFrame() { // pack some placeholder sequence number for now audioPacketStream << (quint16) 0; - + // pack stream identifier (a generated UUID) audioPacketStream << QUuid::createUuid(); - + // pack the stereo/mono type of the stream audioPacketStream << _options.stereo; - + // pack the flag for loopback - uchar loopbackFlag = (uchar) true; + uchar loopbackFlag = (uchar)true; audioPacketStream << loopbackFlag; - + // pack the position for injected audio positionOptionOffset = _currentPacket->pos(); audioPacketStream.writeRawData(reinterpret_cast(&_options.position), - sizeof(_options.position)); - + sizeof(_options.position)); + // pack our orientation for injected audio audioPacketStream.writeRawData(reinterpret_cast(&_options.orientation), - sizeof(_options.orientation)); - + sizeof(_options.orientation)); + // pack zero for radius float radius = 0; audioPacketStream << radius; - + // pack 255 for attenuation byte volumeOptionOffset = _currentPacket->pos(); quint8 volume = MAX_INJECTOR_VOLUME; audioPacketStream << volume; - + audioPacketStream << _options.ignorePenumbra; - + audioDataOffset = _currentPacket->pos(); - - } else { + + } + else { // no samples to inject, return immediately qDebug() << "AudioInjector::injectNextFrame() called with no samples to inject. Returning."; return NEXT_FRAME_DELTA_ERROR_OR_FINISHED; } } - + int bytesToCopy = std::min((_options.stereo ? 2 : 1) * AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL, - _audioData.size() - _currentSendOffset); - + _audioData.size() - _currentSendOffset); + // Measure the loudness of this frame _loudness = 0.0f; for (int i = 0; i < bytesToCopy; i += sizeof(int16_t)) { _loudness += abs(*reinterpret_cast(_audioData.data() + _currentSendOffset + i)) / - (AudioConstants::MAX_SAMPLE_VALUE / 2.0f); + (AudioConstants::MAX_SAMPLE_VALUE / 2.0f); } _loudness /= (float)(bytesToCopy / sizeof(int16_t)); - + _currentPacket->seek(0); - + // pack the sequence number _currentPacket->writePrimitive(_outgoingSequenceNumber); - + _currentPacket->seek(positionOptionOffset); _currentPacket->writePrimitive(_options.position); _currentPacket->writePrimitive(_options.orientation); - + quint8 volume = MAX_INJECTOR_VOLUME * _options.volume; _currentPacket->seek(volumeOptionOffset); _currentPacket->writePrimitive(volume); - + _currentPacket->seek(audioDataOffset); - + // copy the next NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL bytes to the packet _currentPacket->write(_audioData.data() + _currentSendOffset, bytesToCopy); - + // set the correct size used for this packet _currentPacket->setPayloadSize(_currentPacket->pos()); - + // grab our audio mixer from the NodeList, if it exists auto nodeList = DependencyManager::get(); SharedNodePointer audioMixer = nodeList->soloNodeOfType(NodeType::AudioMixer); - + if (audioMixer) { // send off this audio packet nodeList->sendUnreliablePacket(*_currentPacket, *audioMixer); _outgoingSequenceNumber++; } - + _currentSendOffset += bytesToCopy; - + if (_currentSendOffset >= _audioData.size()) { // we're at the end of the audio data to send if (_options.loop) { // we were asked to loop, set our send offset to 0 _currentSendOffset = 0; - } else { + } + else { // we weren't to loop, say that we're done now finish(); return NEXT_FRAME_DELTA_ERROR_OR_FINISHED; } } - + if (_currentSendOffset == bytesToCopy) { // ask AudioInjectorManager to call us right away again to // immediately send the first two frames so the mixer can start using the audio right away return NEXT_FRAME_DELTA_IMMEDIATELY; - } else { - return (++_nextFrame * AudioConstants::NETWORK_FRAME_USECS) - _frameTimer->nsecsElapsed() / 1000; } - + + const int MAX_ALLOWED_FRAMES_TO_FALL_BEHIND = 7; + int64_t currentTime = _frameTimer->nsecsElapsed() / 1000; + auto currentFrameBasedOnElapsedTime = currentTime / AudioConstants::NETWORK_FRAME_USECS; + + if (currentFrameBasedOnElapsedTime - _nextFrame > MAX_ALLOWED_FRAMES_TO_FALL_BEHIND) { + // If we are falling behind by more frames than our threshold, let's skip the frames ahead + _nextFrame = currentFrameBasedOnElapsedTime - MAX_ALLOWED_FRAMES_TO_FALL_BEHIND; + } else { + ++_nextFrame; + } + + int64_t playNextFrameAt = _nextFrame * AudioConstants::NETWORK_FRAME_USECS; + return std::max(0LL, playNextFrameAt - currentTime); } void AudioInjector::stop() { diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index f815b6fe3a..5155b87a74 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -84,7 +84,7 @@ private slots: private: void setupInjection(); - uint64_t injectNextFrame(); + int64_t injectNextFrame(); bool injectLocally(); QByteArray _audioData; diff --git a/libraries/audio/src/AudioInjectorManager.cpp b/libraries/audio/src/AudioInjectorManager.cpp index f504b31907..b91bddc553 100644 --- a/libraries/audio/src/AudioInjectorManager.cpp +++ b/libraries/audio/src/AudioInjectorManager.cpp @@ -88,7 +88,7 @@ void AudioInjectorManager::run() { // this is an injector that's ready to go, have it send a frame now auto nextCallDelta = injector->injectNextFrame(); - if (nextCallDelta > 0 && !injector->isFinished()) { + if (nextCallDelta >= 0 && !injector->isFinished()) { // re-enqueue the injector with the correct timing _injectors.emplace(usecTimestampNow() + nextCallDelta, injector); } From 0e1742588bce3dd6bdec5e580f8b480096118525 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 26 Jan 2016 09:35:35 -0800 Subject: [PATCH 054/145] Fix indentation --- libraries/audio/src/AudioInjector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index bec4921675..660effddeb 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -240,7 +240,7 @@ int64_t AudioInjector::injectNextFrame() { } int bytesToCopy = std::min((_options.stereo ? 2 : 1) * AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL, - _audioData.size() - _currentSendOffset); + _audioData.size() - _currentSendOffset); // Measure the loudness of this frame _loudness = 0.0f; From 5268ef8ac21f723e39654d0a7d6dd9735ed333f9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 26 Jan 2016 09:36:40 -0800 Subject: [PATCH 055/145] Fix else indentation --- libraries/audio/src/AudioInjector.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 660effddeb..e058a87636 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -288,8 +288,7 @@ int64_t AudioInjector::injectNextFrame() { if (_options.loop) { // we were asked to loop, set our send offset to 0 _currentSendOffset = 0; - } - else { + } else { // we weren't to loop, say that we're done now finish(); return NEXT_FRAME_DELTA_ERROR_OR_FINISHED; From 3160aa306867d791e2fb858b80ba74d37165f9a9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 26 Jan 2016 09:36:52 -0800 Subject: [PATCH 056/145] Change 0LL to INT64_C(0) --- libraries/audio/src/AudioInjector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index e058a87636..f32b96257d 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -313,7 +313,7 @@ int64_t AudioInjector::injectNextFrame() { } int64_t playNextFrameAt = _nextFrame * AudioConstants::NETWORK_FRAME_USECS; - return std::max(0LL, playNextFrameAt - currentTime); + return std::max(INT64_C(0), playNextFrameAt - currentTime); } void AudioInjector::stop() { From 2728290ffbeb6e95ed9db0343a80a42a69d755f8 Mon Sep 17 00:00:00 2001 From: "U-GAPOS\\andrew" Date: Tue, 26 Jan 2016 09:37:33 -0800 Subject: [PATCH 057/145] fix bug in IK and tune head/neck constraints --- .../animation/src/AnimInverseKinematics.cpp | 60 ++++++++++++------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 415ee72d7b..e47a12960e 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -153,7 +153,6 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vectorgetParentIndex(tipIndex); if (pivotIndex == -1 || pivotIndex == _hipsIndex) { @@ -165,12 +164,30 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vectorapply(tipRelativeRotation); + if (constrained) { + tipOrientation = glm::normalize(tipRelativeRotation * tipParentOrientation); + } + } + } + + // cache tip absolute position + glm::vec3 tipPosition = absolutePoses[tipIndex].trans; // descend toward root, pivoting each joint to get tip closer to target while (pivotIndex != _hipsIndex && pivotsParentIndex != -1) { @@ -201,9 +218,9 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vectorapply(newRot); if (constrained) { - // the constraint will modify the movement of the tip so we have to compute the modified - // model-frame deltaRotation + // the constraint will modify the local rotation of the tip so we must + // compute the corresponding model-frame deltaRotation // Q' = Qp^ * dQ * Q --> dQ = Qp * Q' * Q^ deltaRotation = absolutePoses[pivotsParentIndex].rot * - newRot * - glm::inverse(absolutePoses[pivotIndex].rot); + newRot * glm::inverse(absolutePoses[pivotIndex].rot); } } @@ -264,8 +280,8 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vectorgetParentIndex(pivotIndex); @@ -629,11 +645,11 @@ void AnimInverseKinematics::initConstraints() { } else if (0 == baseName.compare("Neck", Qt::CaseInsensitive)) { SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); - const float MAX_NECK_TWIST = PI / 4.0f; + const float MAX_NECK_TWIST = PI / 6.0f; stConstraint->setTwistLimits(-MAX_NECK_TWIST, MAX_NECK_TWIST); std::vector minDots; - const float MAX_NECK_SWING = PI / 3.0f; + const float MAX_NECK_SWING = PI / 4.0f; minDots.push_back(cosf(MAX_NECK_SWING)); stConstraint->setSwingLimits(minDots); @@ -641,11 +657,11 @@ void AnimInverseKinematics::initConstraints() { } else if (0 == baseName.compare("Head", Qt::CaseInsensitive)) { SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); - const float MAX_HEAD_TWIST = PI / 4.0f; + const float MAX_HEAD_TWIST = PI / 8.0f; stConstraint->setTwistLimits(-MAX_HEAD_TWIST, MAX_HEAD_TWIST); std::vector minDots; - const float MAX_HEAD_SWING = PI / 4.0f; + const float MAX_HEAD_SWING = PI / 6.0f; minDots.push_back(cosf(MAX_HEAD_SWING)); stConstraint->setSwingLimits(minDots); From b56668892e82c4bd81bb3973e8cf8532de45722b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 26 Jan 2016 09:39:11 -0800 Subject: [PATCH 058/145] Fix else style --- libraries/audio/src/AudioInjector.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index f32b96257d..b203800703 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -231,8 +231,7 @@ int64_t AudioInjector::injectNextFrame() { audioDataOffset = _currentPacket->pos(); - } - else { + } else { // no samples to inject, return immediately qDebug() << "AudioInjector::injectNextFrame() called with no samples to inject. Returning."; return NEXT_FRAME_DELTA_ERROR_OR_FINISHED; From ce97fae1be900a450a259009dfff91d063202fa4 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 26 Jan 2016 10:27:55 -0800 Subject: [PATCH 059/145] update dice location --- unpublishedScripts/hiddenEntityReset.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 0ba1c72e72..51104c06d5 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -1110,9 +1110,9 @@ collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav", name: "dice", position: { - x: 541, - y: 494.96, - z: 509.1 + x: 541.61, + y: 495.21, + z: 508.52 }, dimensions: { x: 0.09, @@ -1144,9 +1144,9 @@ var dice1 = Entities.addEntity(diceProps); diceProps.position = { - x: 541.05, - y: 494.96, - z: 509.0 + x: 541.52, + y: 495.21, + z: 508.41 }; var dice2 = Entities.addEntity(diceProps); From 64cb053c161da00d3f2ca483b0925cbe834207ea Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 26 Jan 2016 10:30:26 -0800 Subject: [PATCH 060/145] update it in the other spawner script --- unpublishedScripts/hiddenEntityReset.js | 1 - unpublishedScripts/masterReset.js | 15 +++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 51104c06d5..8d88d40ef0 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -1153,7 +1153,6 @@ } - function createGates() { var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/ryan/fence.fbx'; diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 8ff1333a78..34d42d2d1a 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -1098,9 +1098,9 @@ MasterReset = function() { collisionSoundURL: "http://s3.amazonaws.com/hifi-public/sounds/dice/diceCollide.wav", name: "dice", position: { - x: 541, - y: 494.96, - z: 509.1 + x: 541.61, + y: 495.21, + z: 508.52 }, dimensions: { x: 0.09, @@ -1132,16 +1132,15 @@ MasterReset = function() { var dice1 = Entities.addEntity(diceProps); diceProps.position = { - x: 541.05, - y: 494.96, - z: 509.0 + x: 541.52, + y: 495.21, + z: 508.41 }; var dice2 = Entities.addEntity(diceProps); } - - + function createGates() { var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/ryan/fence.fbx'; From 69d833a6c00b5e7416fec15a834ffedfc0661024 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 26 Jan 2016 10:53:21 -0800 Subject: [PATCH 061/145] AnimClip: consistent application of translations Apply animation translation the same way regardless of state of usePreAndPostPoseFromAnimation. --- libraries/animation/src/AnimClip.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 0ab83c1870..90cd85e727 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -155,15 +155,7 @@ void AnimClip::copyFromNetworkAnim() { boneLengthScale = glm::length(relDefaultPose.trans) / glm::length(fbxZeroTrans); } - AnimPose trans; - if (_skeleton->getJointName(skeletonJoint) == "RightEye" || _skeleton->getJointName(skeletonJoint) == "LeftEye") { - // preserve model eye translation - trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans); - } else if (usePreAndPostPoseFromAnim) { - trans = AnimPose(glm::vec3(1.0f), glm::quat(), boneLengthScale * (fbxAnimTrans + (fbxAnimTrans - fbxZeroTrans))); - } else { - trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans + boneLengthScale * (fbxAnimTrans - fbxZeroTrans)); - } + AnimPose trans = AnimPose(glm::vec3(1.0f), glm::quat(), relDefaultPose.trans + boneLengthScale * (fbxAnimTrans - fbxZeroTrans)); _anim[frame][skeletonJoint] = trans * preRot * rot * postRot; } From 79a2b7f2135fed3cb1622a784a70e3c1b3495a12 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Jan 2016 11:17:54 -0800 Subject: [PATCH 062/145] make sure shell var context is correct for AppData --- cmake/templates/NSIS.template.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index b698d6072a..42743196b5 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -639,10 +639,13 @@ Function HandlePostInstallOptions ${EndIf} ${If} @PR_BUILD@ == 1 + ; check if we need to copy settings/content from production for this PR build ${NSD_GetState} $CopyFromProductionCheckbox $CopyFromProductionState ${If} $CopyFromProductionState == ${BST_CHECKED} + SetShellVarContext current + StrCpy $0 "$APPDATA\@BUILD_ORGANIZATION@" ; we need to copy whatever is in the data folder for production build to the data folder for this build @@ -660,6 +663,8 @@ Function HandlePostInstallOptions "There was a problem copying your production content and settings to $0 for this PR build.$\r$\n$\r$\nPlease copy them manually." NoError: + + SetShellVarContext all ${EndIf} ${EndIf} From 068de5203c3aa8797dc7dba1af006295e51bdb9a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Jan 2016 11:40:50 -0800 Subject: [PATCH 063/145] use specific shortcut names for PR builds --- cmake/macros/SetPackagingParameters.cmake | 12 ++++++++---- cmake/templates/CPackProperties.cmake.in | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake index b0f093977a..de5a87e4d6 100644 --- a/cmake/macros/SetPackagingParameters.cmake +++ b/cmake/macros/SetPackagingParameters.cmake @@ -82,10 +82,14 @@ macro(SET_PACKAGING_PARAMETERS) set(DS_EXEC_NAME "domain-server.exe") set(AC_EXEC_NAME "assignment-client.exe") - # start menu shortcuts - set(INTERFACE_SM_SHORTCUT_NAME "High Fidelity") - set(CONSOLE_SM_SHORTCUT_NAME "Server Console") - + # shortcut names + if (NOT PR_BUILD) + set(INTERFACE_SHORTCUT_NAME "High Fidelity") + set(CONSOLE_SHORTCUT_NAME "Server Console") + else () + set(INTERFACE_SHORTCUT_NAME "High Fidelity - ${BUILD_VERSION}") + set(CONSOLE_SHORTCUT_NAME "Server Console - ${BUILD_VERSION}") + endif () # check if we need to find signtool if (PRODUCTION_BUILD OR PR_BUILD) find_program(SIGNTOOL_EXECUTABLE signtool PATHS "C:/Program Files (x86)/Windows Kits/8.1" PATH_SUFFIXES "bin/x64") diff --git a/cmake/templates/CPackProperties.cmake.in b/cmake/templates/CPackProperties.cmake.in index 285de84d39..164e432706 100644 --- a/cmake/templates/CPackProperties.cmake.in +++ b/cmake/templates/CPackProperties.cmake.in @@ -9,10 +9,10 @@ # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # -set(INTERFACE_SHORTCUT_NAME "@INTERFACE_SM_SHORTCUT_NAME@") +set(INTERFACE_SHORTCUT_NAME "@INTERFACE_SHORTCUT_NAME@") set(INTERFACE_WIN_EXEC_NAME "@INTERFACE_EXEC_PREFIX@.exe") set(CONSOLE_INSTALL_SUBDIR "@CONSOLE_INSTALL_DIR@") -set(CONSOLE_SHORTCUT_NAME "@CONSOLE_SM_SHORTCUT_NAME@") +set(CONSOLE_SHORTCUT_NAME "@CONSOLE_SHORTCUT_NAME@") set(CONSOLE_WIN_EXEC_NAME "@CONSOLE_EXEC_NAME@") set(DS_EXEC_NAME "@DS_EXEC_NAME@") set(AC_EXEC_NAME "@AC_EXEC_NAME@") From 4115d52d916251311597fc683a8851aa62fc07ec Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Jan 2016 11:46:37 -0800 Subject: [PATCH 064/145] default shortcut options off for PR builds --- cmake/templates/NSIS.template.in | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 42743196b5..ecf703f121 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -536,7 +536,6 @@ Function PostInstallOptionsPage ; set the checkbox state depending on what is present in the registry !insertmacro SetPostInstallOption $DesktopClientCheckbox @CLIENT_DESKTOP_SHORTCUT_REG_KEY@ ${BST_CHECKED} - ${EndIf} ${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@} @@ -569,6 +568,16 @@ Function PostInstallOptionsPage !insertmacro SetPostInstallOption $LaunchNowCheckbox @LAUNCH_NOW_REG_KEY@ ${BST_CHECKED} ${If} @PR_BUILD@ == 1 + ; a PR build defaults all install options expect LaunchNowCheckbox and the settings copy to unchecked + ${If} ${SectionIsSelected} ${@CLIENT_COMPONENT_NAME@} + ${NSD_SetState} $DesktopClientCheckbox ${BST_UNCHECKED} + ${EndIf} + + ${If} ${SectionIsSelected} ${@SERVER_COMPONENT_NAME@} + ${NSD_SetState} $DesktopServerCheckbox ${BST_UNCHECKED} + ${NSD_SetState} $ServerStartupCheckbox ${BST_UNCHECKED} + ${EndIf} + ; push the offset IntOp $CurrentOffset $CurrentOffset + 15 From 6daeefef6882a781fc2d4fba1a22bba8666528e0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Jan 2016 12:08:26 -0800 Subject: [PATCH 065/145] remove the correct startup shortcut during uninstall --- cmake/templates/NSIS.template.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index ecf703f121..070c12192c 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -868,7 +868,12 @@ Section "Uninstall" Delete "$SMPROGRAMS\$MUI_TEMP\@CONSOLE_SHORTCUT_NAME@.lnk" Delete "$DESKTOP\@INTERFACE_SHORTCUT_NAME@.lnk" Delete "$DESKTOP\@CONSOLE_SHORTCUT_NAME@.lnk" + + ; if it exists, delete the startup shortcut for the current user + SetShellVarContext current Delete "$SMSTARTUP\@CONSOLE_SHORTCUT_NAME@.lnk" + SetShellVarContext all + @CPACK_NSIS_DELETE_ICONS@ @CPACK_NSIS_DELETE_ICONS_EXTRA@ From 0a413904a098bab3c7a4dc7b88fc5a6e0bb2e7e1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Jan 2016 12:09:45 -0800 Subject: [PATCH 066/145] use non PR-specific names for close prompt --- cmake/templates/NSIS.template.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/templates/NSIS.template.in b/cmake/templates/NSIS.template.in index 070c12192c..b5699cb3b3 100644 --- a/cmake/templates/NSIS.template.in +++ b/cmake/templates/NSIS.template.in @@ -721,8 +721,8 @@ FunctionEnd !macroend !macro CheckForRunningApplications action prompter - !insertmacro PromptForRunningApplication "@INTERFACE_WIN_EXEC_NAME@" "@INTERFACE_SHORTCUT_NAME@" ${action} ${prompter} - !insertmacro PromptForRunningApplication "@CONSOLE_WIN_EXEC_NAME@" "@CONSOLE_SHORTCUT_NAME@" ${action} ${prompter} + !insertmacro PromptForRunningApplication "@INTERFACE_WIN_EXEC_NAME@" "High Fidelity client" ${action} ${prompter} + !insertmacro PromptForRunningApplication "@CONSOLE_WIN_EXEC_NAME@" "Server Console" ${action} ${prompter} !insertmacro PromptForRunningApplication "@DS_EXEC_NAME@" "Domain Server" ${action} ${prompter} !insertmacro PromptForRunningApplication "@AC_EXEC_NAME@" "Assignment Client" ${action} ${prompter} !macroend From 5b1834d7bebcbf66e0af50050f28cd33ee6a23ea Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 26 Jan 2016 12:44:37 -0800 Subject: [PATCH 067/145] Fix Wreorder for Job::Models --- libraries/render/src/render/Task.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index e2678f2735..cfe37c257e 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -146,7 +146,7 @@ public: Data _data; - Model(Data data = Data()) : _data(data), Concept(std::make_shared()) { + Model(Data data = Data()) : Concept(std::make_shared()), _data(data) { applyConfiguration(); } @@ -173,7 +173,7 @@ public: const Varying getInput() const { return _input; } - ModelI(const Varying& input, Data data = Data()) : _input(input), _data(data), Concept(std::make_shared()) { + ModelI(const Varying& input, Data data = Data()) : Concept(std::make_shared()), _data(data), _input(input) { applyConfiguration(); } @@ -200,7 +200,7 @@ public: const Varying getOutput() const { return _output; } - ModelO(Data data = Data()) : _data(data), _output(Output()), Concept(std::make_shared()) { + ModelO(Data data = Data()) : Concept(std::make_shared()), _data(data), _output(Output()) { applyConfiguration(); } @@ -230,7 +230,7 @@ public: const Varying getInput() const { return _input; } const Varying getOutput() const { return _output; } - ModelIO(const Varying& input, Data data = Data()) : _data(data), _input(input), _output(Output()), Concept(std::make_shared()) { + ModelIO(const Varying& input, Data data = Data()) : Concept(std::make_shared()), _data(data), _input(input), _output(Output()) { applyConfiguration(); } From 2d0d54276584d527acb59c88b6cc11c79aedccd4 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 26 Jan 2016 12:44:56 -0800 Subject: [PATCH 068/145] Fix friend class typedef confusion in gcc --- libraries/render-utils/src/DebugDeferredBuffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index c8e2ee0485..27aa8d30b2 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -46,7 +46,7 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); protected: - friend class Config; + friend class DebugDeferredBufferConfig; enum Mode : uint8_t { Diffuse = 0, From e6379fcaa868e3bd012c926cbd2709de353d3c60 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Tue, 26 Jan 2016 12:57:41 -0800 Subject: [PATCH 069/145] Naming changes --- examples/junkyard/junkyardClientReset.js | 4 ++-- examples/junkyard/junkyardResetEntitySpawner.js | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/junkyard/junkyardClientReset.js b/examples/junkyard/junkyardClientReset.js index 8aea8470dd..c4dfa19c4f 100644 --- a/examples/junkyard/junkyardClientReset.js +++ b/examples/junkyard/junkyardClientReset.js @@ -22,10 +22,10 @@ function reset() { for (i = 0; i < e.length; i++) { Entities.deleteEntity(e[i]); } - importArf(); + importAssetResourceFile(); } -function importArf() { +function importAssetResourceFile() { Clipboard.importEntities(IMPORT_URL); Clipboard.pasteEntities(PASTE_ENTITIES_LOCATION); } \ No newline at end of file diff --git a/examples/junkyard/junkyardResetEntitySpawner.js b/examples/junkyard/junkyardResetEntitySpawner.js index b2627c7cd9..f467e0e22f 100644 --- a/examples/junkyard/junkyardResetEntitySpawner.js +++ b/examples/junkyard/junkyardResetEntitySpawner.js @@ -19,12 +19,13 @@ var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(orientation))); - var scriptURL = Script.resolvePath("junkyardResetEntityScript.js?v1" + Math.random()); + var SCRIPT_URL = Script.resolvePath("junkyardResetEntityScript.js"); + var MODEL_URL = "http://hifi-content.s3.amazonaws.com/caitlyn/dev/Blueprint%20Objects/Asylum/Asylum_Table/Asylum_Table.fbx"; var resetEntity = Entities.addEntity({ type: "Model", - modelURL: "http://hifi-content.s3.amazonaws.com/caitlyn/dev/Blueprint%20Objects/Asylum/Asylum_Table/Asylum_Table.fbx", + modelURL: MODEL_URL, position: center, - script: scriptURL, + script: SCRIPT_URL, dimensions: { x: 2.8, y: 1.76, From 1fefe0fa0e48de2a3b0e042c0ae39ad347e3d0f8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 26 Jan 2016 13:30:55 -0800 Subject: [PATCH 070/145] when an avatar moves a child entity around, it has to invoke MovingEntitiesOperator to keep the local octree up-to-date --- interface/src/avatar/MyAvatar.cpp | 37 ++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 7180d8ec2c..04205d6a65 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -50,6 +50,7 @@ #include "InterfaceLogging.h" #include "DebugDraw.h" #include "EntityEditPacketSender.h" +#include "MovingEntitiesOperator.h" using namespace std; @@ -355,18 +356,34 @@ void MyAvatar::simulate(float deltaTime) { locationChanged(); // if a entity-child of this avatar has moved outside of its queryAACube, update the cube and tell the entity server. - forEachDescendant([&](SpatiallyNestablePointer object) { - if (object->computePuffedQueryAACube() && object->getNestableType() == NestableType::Entity) { - EntityItemPointer entity = std::static_pointer_cast(object); - EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender(); - if (packetSender) { - EntityItemProperties properties = entity->getProperties(); - properties.setQueryAACubeDirty(); - packetSender->queueEditEntityMessage(PacketType::EntityEdit, entity->getID(), properties); - entity->setLastBroadcast(usecTimestampNow()); + EntityTreeRenderer* entityTreeRenderer = qApp->getEntities(); + EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr; + if (entityTree) { + EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender(); + MovingEntitiesOperator moveOperator(entityTree); + forEachDescendant([&](SpatiallyNestablePointer object) { + // if the queryBox has changed, tell the entity-server + if (object->computePuffedQueryAACube() && object->getNestableType() == NestableType::Entity) { + EntityItemPointer entity = std::static_pointer_cast(object); + bool success; + AACube newCube = entity->getQueryAACube(success); + if (success) { + moveOperator.addEntityToMoveList(entity, newCube); + } + if (packetSender) { + EntityItemProperties properties = entity->getProperties(); + properties.setQueryAACubeDirty(); + packetSender->queueEditEntityMessage(PacketType::EntityEdit, entity->getID(), properties); + entity->setLastBroadcast(usecTimestampNow()); + } } + }); + // also update the position of children in our local octree + if (moveOperator.hasMovingEntities()) { + PerformanceTimer perfTimer("recurseTreeWithOperator"); + entityTree->recurseTreeWithOperator(&moveOperator); } - }); + } } glm::mat4 MyAvatar::getSensorToWorldMatrix() const { From 33993b8c444b025bbcddbcf726275c46a122d2dd Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 26 Jan 2016 13:34:21 -0800 Subject: [PATCH 071/145] AnimClip: removed unused static member. --- libraries/animation/src/AnimClip.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/animation/src/AnimClip.h b/libraries/animation/src/AnimClip.h index 91215d0d44..7d58ae4f9a 100644 --- a/libraries/animation/src/AnimClip.h +++ b/libraries/animation/src/AnimClip.h @@ -26,7 +26,6 @@ public: friend class AnimTests; static bool usePreAndPostPoseFromAnim; - static bool useTransFromAnim; AnimClip(const QString& id, const QString& url, float startFrame, float endFrame, float timeScale, bool loopFlag); virtual ~AnimClip() override; From a731a571e02809882abe638680d5813c4475b6dc Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 26 Jan 2016 13:50:58 -0800 Subject: [PATCH 072/145] Update entity server to always make resource directory if it does not exist --- assignment-client/src/octree/OctreeServer.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index d63e8e6620..81e25cc7ba 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -1172,15 +1172,15 @@ void OctreeServer::domainSettingsRequestComplete() { pathToCopyFrom = oldDefaultPersistPath; } + QDir persistFileDirectory = QDir(persistPath).filePath(".."); + if (!persistFileDirectory.exists()) { + qDebug() << "Creating data directory " << persistFileDirectory.absolutePath(); + persistFileDirectory.mkpath("."); + } + if (shouldCopy) { qDebug() << "Old persist file found, copying from " << pathToCopyFrom << " to " << persistPath; - QDir persistFileDirectory = QDir(persistPath).filePath(".."); - - if (!persistFileDirectory.exists()) { - qDebug() << "Creating data directory " << persistFileDirectory.path(); - persistFileDirectory.mkpath("."); - } QFile::copy(pathToCopyFrom, persistPath); } else { qDebug() << "No existing persist file found"; From d8dbb717d5654bd7855c605d9e35f9bf8b205cf9 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Tue, 26 Jan 2016 14:06:17 -0800 Subject: [PATCH 073/145] Update junkyardResetEntityScript.js --- examples/junkyard/junkyardResetEntityScript.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/junkyard/junkyardResetEntityScript.js b/examples/junkyard/junkyardResetEntityScript.js index 9bd7ec02a5..9a330d0cdc 100644 --- a/examples/junkyard/junkyardResetEntityScript.js +++ b/examples/junkyard/junkyardResetEntityScript.js @@ -37,10 +37,10 @@ Entities.deleteEntity(e[i]); } } - this.importArf(); + this.importAssetResourceFile(); }, - importArf: function() { + importAssetResourceFile: function() { Clipboard.importEntities(IMPORT_URL); Clipboard.pasteEntities(PASTE_ENTITIES_LOCATION); }, @@ -50,4 +50,4 @@ }, }; return new JunkyardResetter(); -}); \ No newline at end of file +}); From e6a8fd192cf46ba800478c35bba61bce53923283 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Jan 2016 15:54:08 -0800 Subject: [PATCH 074/145] use the VS2011 DLLs bundled with sixense for installer --- cmake/macros/GenerateInstallers.cmake | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmake/macros/GenerateInstallers.cmake b/cmake/macros/GenerateInstallers.cmake index e0523f32d3..b4744aa172 100644 --- a/cmake/macros/GenerateInstallers.cmake +++ b/cmake/macros/GenerateInstallers.cmake @@ -28,6 +28,15 @@ macro(GENERATE_INSTALLERS) # include CMake module that will install compiler system libraries # so that we have msvcr120 and msvcp120 installed with targets set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION ${INTERFACE_INSTALL_DIR}) + + # as long as we're including sixense plugin with installer + # we need re-distributables for VS 2011 as well + # this should be removed if/when sixense support is pulled + set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS + "${EXTERNALS_BINARY_DIR}/sixense/project/src/sixense/samples/win64/msvcr100.dll" + "${EXTERNALS_BINARY_DIR}/sixense/project/src/sixense/samples/win64/msvcp100.dll" + ) + include(InstallRequiredSystemLibraries) set(CPACK_NSIS_MUI_ICON "${HF_CMAKE_DIR}/installer/installer.ico") From 5009e8702ee435c813e8a109c064d5ce26ca3347 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 26 Jan 2016 13:57:30 -0800 Subject: [PATCH 075/145] Cleanup new render settings --- interface/src/Menu.cpp | 1 - interface/src/Menu.h | 1 - .../src/AmbientOcclusionEffect.cpp | 46 +++++++++---------- .../render-utils/src/AmbientOcclusionEffect.h | 7 ++- .../render-utils/src/AntialiasingEffect.h | 5 +- .../render-utils/src/DebugDeferredBuffer.cpp | 4 ++ .../render-utils/src/DebugDeferredBuffer.h | 13 ++---- libraries/render-utils/src/HitEffect.h | 5 +- .../render-utils/src/RenderDeferredTask.cpp | 14 +++--- .../render-utils/src/RenderDeferredTask.h | 18 ++++---- .../render-utils/src/RenderShadowTask.cpp | 2 + libraries/render-utils/src/RenderShadowTask.h | 3 +- libraries/render/src/render/Context.h | 2 +- libraries/render/src/render/DrawStatus.cpp | 6 +-- libraries/render/src/render/DrawStatus.h | 13 +++--- libraries/render/src/render/DrawTask.h | 5 +- libraries/render/src/render/Task.cpp | 6 --- libraries/render/src/render/Task.h | 46 +++++++++---------- 18 files changed, 93 insertions(+), 104 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8d96a68046..27d1ed9bc2 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -584,7 +584,6 @@ Menu::Menu() { // Developer > Physics >>> MenuWrapper* physicsOptionsMenu = developerMenu->addMenu("Physics"); - addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowOwned); addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowHulls); // Developer > Display Crash Options diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 21454b7d66..f07ce641d8 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -244,7 +244,6 @@ namespace MenuOption { const QString OutputMenu = "Display"; const QString PackageModel = "Package Model..."; const QString Pair = "Pair"; - const QString PhysicsShowOwned = "Highlight Simulation Ownership"; const QString PhysicsShowHulls = "Draw Collision Hulls"; const QString PipelineWarnings = "Log Render Pipeline Warnings"; const QString Preferences = "General..."; diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 6bcb4bbdcb..50b6c06254 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -101,13 +101,13 @@ AmbientOcclusionEffect::AmbientOcclusionEffect() { _parametersBuffer = gpu::BufferView(std::make_shared(sizeof(Parameters), (const gpu::Byte*) ¶meters)); } -void AmbientOcclusionEffect::configure(const Config& configuration) { - DependencyManager::get()->setAmbientOcclusionEnabled(configuration.enabled); +void AmbientOcclusionEffect::configure(const Config& config) { + DependencyManager::get()->setAmbientOcclusionEnabled(config.enabled); bool shouldUpdateGaussion = false; const double RADIUS_POWER = 6.0; - const auto& radius = configuration.radius; + const auto& radius = config.radius; if (radius != getRadius()) { auto& current = _parametersBuffer.edit().radiusInfo; current.x = radius; @@ -115,39 +115,39 @@ void AmbientOcclusionEffect::configure(const Config& configuration) { current.z = (float)(1.0 / pow((double)radius, RADIUS_POWER)); } - if (configuration.obscuranceLevel != getObscuranceLevel()) { + if (config.obscuranceLevel != getObscuranceLevel()) { auto& current = _parametersBuffer.edit().radiusInfo; - current.w = configuration.obscuranceLevel; + current.w = config.obscuranceLevel; } - if (configuration.falloffBias != getFalloffBias()) { + if (config.falloffBias != getFalloffBias()) { auto& current = _parametersBuffer.edit().ditheringInfo; - current.z = configuration.falloffBias; + current.z = config.falloffBias; } - if (configuration.edgeSharpness != getEdgeSharpness()) { + if (config.edgeSharpness != getEdgeSharpness()) { auto& current = _parametersBuffer.edit().blurInfo; - current.x = configuration.edgeSharpness; + current.x = config.edgeSharpness; } - if (configuration.blurDeviation != getBlurDeviation()) { + if (config.blurDeviation != getBlurDeviation()) { auto& current = _parametersBuffer.edit().blurInfo; - current.z = configuration.blurDeviation; + current.z = config.blurDeviation; shouldUpdateGaussion = true; } - if (configuration.numSpiralTurns != getNumSpiralTurns()) { + if (config.numSpiralTurns != getNumSpiralTurns()) { auto& current = _parametersBuffer.edit().sampleInfo; - current.z = configuration.numSpiralTurns; + current.z = config.numSpiralTurns; } - if (configuration.numSamples != getNumSamples()) { + if (config.numSamples != getNumSamples()) { auto& current = _parametersBuffer.edit().sampleInfo; - current.x = configuration.numSamples; - current.y = 1.0f / configuration.numSamples; + current.x = config.numSamples; + current.y = 1.0f / config.numSamples; } - const auto& resolutionLevel = configuration.resolutionLevel; + const auto& resolutionLevel = config.resolutionLevel; if (resolutionLevel != getResolutionLevel()) { auto& current = _parametersBuffer.edit().resolutionInfo; current.x = (float)resolutionLevel; @@ -156,20 +156,20 @@ void AmbientOcclusionEffect::configure(const Config& configuration) { DependencyManager::get()->setAmbientOcclusionResolutionLevel(resolutionLevel); } - if (configuration.blurRadius != getBlurRadius()) { + if (config.blurRadius != getBlurRadius()) { auto& current = _parametersBuffer.edit().blurInfo; - current.y = (float)configuration.blurRadius; + current.y = (float)config.blurRadius; shouldUpdateGaussion = true; } - if (configuration.ditheringEnabled != isDitheringEnabled()) { + if (config.ditheringEnabled != isDitheringEnabled()) { auto& current = _parametersBuffer.edit().ditheringInfo; - current.x = (float)configuration.ditheringEnabled; + current.x = (float)config.ditheringEnabled; } - if (configuration.borderingEnabled != isBorderingEnabled()) { + if (config.borderingEnabled != isBorderingEnabled()) { auto& current = _parametersBuffer.edit().ditheringInfo; - current.w = (float)configuration.borderingEnabled; + current.w = (float)config.borderingEnabled; } if (shouldUpdateGaussion) { diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 2c2c9cfff2..c040e31188 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -18,9 +18,6 @@ class AmbientOcclusionEffectConfig : public render::Job::Config { Q_OBJECT -public: - AmbientOcclusionEffectConfig() : render::Job::Config(false) {} - Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty) Q_PROPERTY(bool ditheringEnabled MEMBER ditheringEnabled NOTIFY dirty) Q_PROPERTY(bool borderingEnabled MEMBER borderingEnabled NOTIFY dirty) @@ -34,6 +31,8 @@ public: Q_PROPERTY(int resolutionLevel MEMBER resolutionLevel WRITE setResolutionLevel) Q_PROPERTY(int blurRadius MEMBER blurRadius WRITE setBlurRadius) Q_PROPERTY(double gpuTime READ getGpuTime) +public: + AmbientOcclusionEffectConfig() : render::Job::Config(false) {} const int MAX_RESOLUTION_LEVEL = 4; const int MAX_BLUR_RADIUS = 6; @@ -73,7 +72,7 @@ public: AmbientOcclusionEffect(); - void configure(const Config& configuration); + void configure(const Config& config); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); float getRadius() const { return _parametersBuffer.get().radiusInfo.x; } diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index 1dd3a9ddcc..f0a32c68ff 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -18,10 +18,9 @@ class AntiAliasingConfig : public render::Job::Config { Q_OBJECT + Q_PROPERTY(bool enabled MEMBER enabled) public: AntiAliasingConfig() : render::Job::Config(false) {} - - Q_PROPERTY(bool enabled MEMBER enabled) }; class Antialiasing { @@ -30,7 +29,7 @@ public: using JobModel = render::Job::Model; Antialiasing(); - void configure(const Config& configuration) {} + void configure(const Config& config) {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); const gpu::PipelinePointer& getAntialiasingPipeline(); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index f8a35ad0df..2dcfa35522 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -232,6 +232,10 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Mode mode, std::str } } +void DebugDeferredBuffer::configure(const Config& config) { + _mode = (Mode)config.mode; + _size = config.size; +} void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { assert(renderContext->args); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index 27aa8d30b2..1cd199c67b 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -18,16 +18,16 @@ class DebugDeferredBufferConfig : public render::Job::Config { Q_OBJECT -public: - DebugDeferredBufferConfig() : render::Job::Config(false) {} - Q_PROPERTY(bool enabled MEMBER enabled) Q_PROPERTY(int mode MEMBER mode WRITE setMode) Q_PROPERTY(glm::vec4 size MEMBER size NOTIFY dirty) +public: + DebugDeferredBufferConfig() : render::Job::Config(false) {} + void setMode(int newMode); int mode{ 0 }; - glm::vec4 size{ 0, 0, 0, 0 }; + glm::vec4 size{ 0.0f, 0.0f, 0.0f, 0.0f }; signals: void dirty(); }; @@ -39,10 +39,7 @@ public: DebugDeferredBuffer(); - void configure(const Config& config) { - _mode = (Mode)config.mode; - _size = config.size; - } + void configure(const Config& config); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); protected: diff --git a/libraries/render-utils/src/HitEffect.h b/libraries/render-utils/src/HitEffect.h index 7d683534d0..5252e63726 100644 --- a/libraries/render-utils/src/HitEffect.h +++ b/libraries/render-utils/src/HitEffect.h @@ -13,10 +13,9 @@ class HitEffectConfig : public render::Job::Config { Q_OBJECT + Q_PROPERTY(bool enabled MEMBER enabled) public: HitEffectConfig() : render::Job::Config(false) {} - - Q_PROPERTY(bool enabled MEMBER enabled) }; class HitEffect { @@ -25,7 +24,7 @@ public: using JobModel = render::Job::Model; HitEffect(); - void configure(const Config&) {} + void configure(const Config& config) {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); const gpu::PipelinePointer& getHitEffectPipeline(); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 47a9c66111..06fadb69b3 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -67,13 +67,13 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo DependencyManager::get()->render(renderContext); } -void ToneMappingDeferred::configure(const Config& configuration) { - if (configuration.exposure >= 0) { - _toneMappingEffect.setExposure(configuration.exposure); +void ToneMappingDeferred::configure(const Config& config) { + if (config.exposure >= 0.0f) { + _toneMappingEffect.setExposure(config.exposure); } - if (configuration.curve >= 0) { - _toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)configuration.curve); + if (config.curve >= 0) { + _toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)config.curve); } } @@ -169,7 +169,7 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont assert(renderContext->args); assert(renderContext->args->_viewFrustum); - auto& config = std::static_pointer_cast(renderContext->jobConfig); + auto config = std::static_pointer_cast(renderContext->jobConfig); RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { @@ -218,7 +218,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon auto& scene = sceneContext->_scene; auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape().withLayered()); - auto& config = std::static_pointer_cast(renderContext->jobConfig); + auto config = std::static_pointer_cast(renderContext->jobConfig); ItemIDsBounds inItems; inItems.reserve(items.size()); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 2aa6199b90..414b019b31 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -43,13 +43,13 @@ public: class ToneMappingConfig : public render::Job::Config { Q_OBJECT -public: - ToneMappingConfig() : render::Job::Config(true) {} - Q_PROPERTY(bool enabled MEMBER enabled) Q_PROPERTY(float exposure MEMBER exposure NOTIFY dirty); Q_PROPERTY(int curve MEMBER curve NOTIFY dirty); - float exposure{ 0.0 }; +public: + ToneMappingConfig() : render::Job::Config(true) {} + + float exposure{ 0.0f }; int curve{ 3 }; signals: void dirty(); @@ -60,7 +60,7 @@ public: using Config = ToneMappingConfig; using JobModel = render::Job::Model; - void configure(const Config&); + void configure(const Config& config); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); ToneMappingEffect _toneMappingEffect; @@ -68,9 +68,9 @@ public: class DrawConfig : public render::Job::Config { Q_OBJECT -public: Q_PROPERTY(int numDrawn READ getNumDrawn) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) +public: int getNumDrawn() { return numDrawn; } int numDrawn{ 0 }; @@ -91,7 +91,7 @@ public: protected: render::ShapePlumberPointer _shapePlumber; - int _maxDrawn{ -1 }; + int _maxDrawn; // initialized by Config }; class DrawStencilDeferred { @@ -115,10 +115,10 @@ public: class DrawOverlay3DConfig : public render::Job::Config { Q_OBJECT -public: Q_PROPERTY(int numItems READ getNumItems) Q_PROPERTY(int numDrawn READ getNumDrawn) Q_PROPERTY(int maxDrawn MEMBER maxDrawn NOTIFY dirty) +public: int getNumItems() { return numItems; } int getNumDrawn() { return numDrawn; } @@ -144,7 +144,7 @@ public: protected: static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable render::ShapePlumberPointer _shapePlumber; - int _maxDrawn{ -1 }; + int _maxDrawn; // initialized by Config }; class Blit { diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 0771fcd9bf..be6cd47f95 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -78,6 +78,7 @@ void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const }); } +// The shadow task *must* use this base ctor to initialize with its own Config, see Task.h RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) : Task(std::make_shared()) { cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; @@ -121,6 +122,7 @@ RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) : Task(std::make_sha void RenderShadowTask::configure(const Config& configuration) { DependencyManager::get()->setShadowMapEnabled(configuration.enabled); + // This is a task, so must still propogate configure() to its Jobs Task::configure(configuration); } diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 5a5186f6f1..e1bf983b79 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -33,11 +33,10 @@ protected: class RenderShadowTaskConfig : public render::Task::Config { Q_OBJECT + Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty) public: RenderShadowTaskConfig() : render::Task::Config(false) {} - Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty) - signals: void dirty(); }; diff --git a/libraries/render/src/render/Context.h b/libraries/render/src/render/Context.h index 0d8c1c8d04..04cf373146 100644 --- a/libraries/render/src/render/Context.h +++ b/libraries/render/src/render/Context.h @@ -31,7 +31,7 @@ public: RenderArgs* args; std::shared_ptr jobConfig{ nullptr }; }; -typedef std::shared_ptr RenderContextPointer; +using RenderContextPointer = std::shared_ptr; } diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index eb7155c513..c043867c88 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -94,9 +94,9 @@ const gpu::TexturePointer DrawStatus::getStatusIconMap() const { return _statusIconMap; } -void DrawStatus::configure(const Config& configuration) { - _showDisplay = configuration.showDisplay; - _showNetwork = configuration.showNetwork; +void DrawStatus::configure(const Config& config) { + _showDisplay = config.showDisplay; + _showNetwork = config.showNetwork; } void DrawStatus::run(const SceneContextPointer& sceneContext, diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index 982eba4990..d1caeca673 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -18,14 +18,15 @@ namespace render { class DrawStatusConfig : public Job::Config { Q_OBJECT - public: - DrawStatusConfig() : Job::Config(false) {} - Q_PROPERTY(bool enabled MEMBER enabled) Q_PROPERTY(bool showDisplay MEMBER showDisplay NOTIFY dirty) Q_PROPERTY(bool showNetwork MEMBER showDisplay NOTIFY dirty) + public: + DrawStatusConfig() : Job::Config(false) {} + bool showDisplay{ false }; bool showNetwork{ false }; + signals: void dirty(); }; @@ -38,7 +39,7 @@ namespace render { DrawStatus() {} DrawStatus(const gpu::TexturePointer statusIconMap) { setStatusIconMap(statusIconMap); } - void configure(const Config& configuration); + void configure(const Config& config); void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); const gpu::PipelinePointer getDrawItemBoundsPipeline(); @@ -48,8 +49,8 @@ namespace render { const gpu::TexturePointer getStatusIconMap() const; protected: - bool _showDisplay{ false }; - bool _showNetwork{ false }; + bool _showDisplay; // initialized by Config + bool _showNetwork; // initialized by Config int _drawItemBoundPosLoc = -1; int _drawItemBoundDimLoc = -1; diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 3ce1ed67fe..d2d9b0a80b 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -29,9 +29,10 @@ void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPo class FetchItemsConfig : public Job::Config { Q_OBJECT -public: Q_PROPERTY(int numItems READ getNumItems) +public: int getNumItems() { return numItems; } + int numItems{ 0 }; }; @@ -45,7 +46,7 @@ public: ItemFilter _filter{ ItemFilter::Builder::opaqueShape().withoutLayered() }; - void configure(const Config&) {} + void configure(const Config& config) {} void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems); }; diff --git a/libraries/render/src/render/Task.cpp b/libraries/render/src/render/Task.cpp index 1ceea6befe..0bf20c6042 100644 --- a/libraries/render/src/render/Task.cpp +++ b/libraries/render/src/render/Task.cpp @@ -10,12 +10,6 @@ // #include -#include // QObject - -#include "Context.h" - -#include "gpu/Batch.h" -#include #include "Task.h" diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index cfe37c257e..ac05fbe68a 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -19,9 +19,6 @@ #include "gpu/Batch.h" #include -// Prepare Qt for auto configurations -Q_DECLARE_METATYPE(std::shared_ptr) - namespace render { // A varying piece of data, to be used as Job/Task I/O @@ -53,25 +50,26 @@ protected: std::shared_ptr _concept; }; +class Job; +class Task; + // A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled) class JobConfig : public QObject { Q_OBJECT public: - JobConfig() : alwaysEnabled{ true }, enabled{ true } {} + JobConfig() = default; JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} bool isEnabled() { return alwaysEnabled || enabled; } bool alwaysEnabled{ true }; - bool enabled; + bool enabled{ true }; }; -class Task; - class TaskConfig : public JobConfig { Q_OBJECT public: - TaskConfig() : JobConfig() {} + TaskConfig() = default ; TaskConfig(bool enabled) : JobConfig(enabled) {} void init(Task* task) { _task = task; } @@ -82,6 +80,7 @@ public: } template void setJobEnabled(bool enable = true, std::string job = "") { + assert(getConfig(job)->alwaysEnabled != true); getConfig(job)->enabled = enable; refresh(); // trigger a Job->configure } @@ -96,24 +95,23 @@ private: Task* _task; }; -template void jobConfigure(T& model, const C& configuration) { - model.configure(configuration); +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 } - -// FIXME: In c++17, use default classes of nullptr_t to combine these -template void jobRun(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - model.run(sceneContext, renderContext); +template void jobRun(T& data, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + data.run(sceneContext, renderContext); } -template void jobRunI(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) { - model.run(sceneContext, renderContext, input); +template void jobRunI(T& data, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) { + data.run(sceneContext, renderContext, input); } -template void jobRunO(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) { - model.run(sceneContext, renderContext, output); +template void jobRunO(T& data, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) { + data.run(sceneContext, renderContext, output); } -template void jobRunIO(T& model, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) { - model.run(sceneContext, renderContext, input, output); +template void jobRunIO(T& data, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) { + data.run(sceneContext, renderContext, input, output); } class Job { @@ -285,12 +283,10 @@ public: public: using Data = T; - // TODO: Make Data a shared_ptr, and give Config a weak_ptr Data _data; - // The _config is unused; the model delegates to its data's _config - Model(Data data = Data()) : _data(data), Concept(std::make_shared()) { - _config = _data._config; + Model(Data data = Data()) : Concept(std::make_shared()), _data(data) { + _config = _data._config; // use the data's config std::static_pointer_cast(_config)->init(&_data); applyConfiguration(); @@ -341,7 +337,7 @@ public: protected: template friend class Model; - QConfigPointer _config { nullptr }; + QConfigPointer _config; Jobs _jobs; }; From 8ba0e3bc6ee40975832ce3012b3221db3d682d2f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 26 Jan 2016 16:21:18 -0800 Subject: [PATCH 076/145] give dev shortcuts a specific name too --- cmake/macros/SetPackagingParameters.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake index de5a87e4d6..92e3273f67 100644 --- a/cmake/macros/SetPackagingParameters.cmake +++ b/cmake/macros/SetPackagingParameters.cmake @@ -83,7 +83,7 @@ macro(SET_PACKAGING_PARAMETERS) set(AC_EXEC_NAME "assignment-client.exe") # shortcut names - if (NOT PR_BUILD) + if (PRODUCTION_BUILD) set(INTERFACE_SHORTCUT_NAME "High Fidelity") set(CONSOLE_SHORTCUT_NAME "Server Console") else () From 8dc066fc00332ac2e8352768f624bd6226a811b0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 Jan 2016 16:48:25 -0800 Subject: [PATCH 077/145] Fix the recursive launching of load script from URL --- interface/resources/qml/desktop/Desktop.qml | 2 +- .../resources/qml/dialogs/RunningScripts.qml | 21 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 96c84b49c0..f246f79be9 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -167,7 +167,7 @@ FocusScope { } if (setFocus) { - focus = true; + targetWindow.focus = true; } reposition(targetWindow); diff --git a/interface/resources/qml/dialogs/RunningScripts.qml b/interface/resources/qml/dialogs/RunningScripts.qml index 059c765f0e..eb56b59b66 100644 --- a/interface/resources/qml/dialogs/RunningScripts.qml +++ b/interface/resources/qml/dialogs/RunningScripts.qml @@ -184,9 +184,28 @@ Window { anchors.bottom: filterEdit.top anchors.bottomMargin: 8 anchors.right: parent.right + + // For some reason trigginer an API that enters + // an internal event loop directly from the button clicked + // trigger below causes the appliction to behave oddly. + // Most likely because the button onClicked handling is never + // completed until the function returns. + // FIXME find a better way of handling the input dialogs that + // doesn't trigger this. + Timer { + id: asyncAction + interval: 50 + repeat: false + running: false + onTriggered: ApplicationInterface.loadScriptURLDialog(); + } + Button { text: "from URL"; - onClicked: ApplicationInterface.loadScriptURLDialog(); + onClicked: { + focus = false; + asyncAction.running = true; + } } Button { text: "from Disk" From cea57a111bc6a5923f5250de164286fd2de96489 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 Jan 2016 16:56:33 -0800 Subject: [PATCH 078/145] Desktop cleanup --- interface/resources/qml/desktop/Desktop.qml | 72 ++++++++++----------- libraries/gl/src/gl/OffscreenQmlSurface.cpp | 1 + 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index f246f79be9..14687f387e 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -13,6 +13,9 @@ FocusScope { anchors.fill: parent; objectName: "desktop" + onHeightChanged: d.repositionAll(); + onWidthChanged: d.repositionAll(); + // Allows QML/JS to find the desktop through the parent chain property bool desktopRoot: true @@ -50,10 +53,6 @@ FocusScope { return item; } - function isDesktop(item) { - return item.desktopRoot; - } - function isTopLevelWindow(item) { return item.topLevelWindow; } @@ -147,6 +146,31 @@ FocusScope { var windows = getTopLevelWindows(predicate); fixupZOrder(windows, zBasis, targetWindow); } + + Component.onCompleted: { + offscreenWindow.activeFocusItemChanged.connect(onWindowFocusChanged); + focusHack.start(); + } + + function onWindowFocusChanged() { + console.log("Focus item is " + offscreenWindow.activeFocusItem); +// var focusedItem = offscreenWindow.activeFocusItem ; +// if (DebugQML && focusedItem) { +// var rect = desktop.mapFromItem(focusedItem, 0, 0, focusedItem.width, focusedItem.height); +// focusDebugger.x = rect.x; +// focusDebugger.y = rect.y; +// focusDebugger.width = rect.width +// focusDebugger.height = rect.height +// } + } + + + function repositionAll() { + var windows = d.getTopLevelWindows(); + for (var i = 0; i < windows.length; ++i) { + reposition(windows[i]); + } + } } function raise(item) { @@ -190,24 +214,16 @@ FocusScope { var newPosition; if (targetWindow.x === -1 && targetWindow.y === -1) { // Set initial window position - newPosition = Utils.randomPosition(minPosition, maxPosition); - } else { - newPosition = Utils.clampVector(Qt.vector2d(targetWindow.x, targetWindow.y), minPosition, maxPosition); + // newPosition = Utils.randomPosition(minPosition, maxPosition); + newPosition = Qt.vector2d(desktop.width / 2 - windowRect.width / 2, + desktop.height / 2 - windowRect.height / 2); } + + newPosition = Utils.clampVector(Qt.vector2d(targetWindow.x, targetWindow.y), minPosition, maxPosition); targetWindow.x = newPosition.x; targetWindow.y = newPosition.y; } - function repositionAll() { - var windows = d.getTopLevelWindows(); - for (var i = 0; i < windows.length; ++i) { - reposition(windows[i]); - } - } - - onHeightChanged: repositionAll(); - onWidthChanged: repositionAll(); - Component { id: messageDialogBuilder; MessageDialog { } } function messageBox(properties) { return messageDialogBuilder.createObject(desktop, properties); @@ -252,39 +268,21 @@ FocusScope { desktop.focus = true; } - // Debugging help for figuring out focus issues - property var offscreenWindow; - onOffscreenWindowChanged: { - offscreenWindow.activeFocusItemChanged.connect(onWindowFocusChanged); - focusHack.start(); - } - FocusHack { id: focusHack; } - function onWindowFocusChanged() { - console.log("Focus item is " + offscreenWindow.activeFocusItem); - var focusedItem = offscreenWindow.activeFocusItem ; - if (DebugQML && focusedItem) { - var rect = desktop.mapFromItem(focusedItem, 0, 0, focusedItem.width, focusedItem.height); - focusDebugger.x = rect.x; - focusDebugger.y = rect.y; - focusDebugger.width = rect.width - focusDebugger.height = rect.height - } - } - Rectangle { id: focusDebugger; z: 9999; visible: false; color: "red" ColorAnimation on color { from: "#7fffff00"; to: "#7f0000ff"; duration: 1000; loops: 9999 } } - + Action { text: "Toggle Focus Debugger" shortcut: "Ctrl+Shift+F" enabled: DebugQML onTriggered: focusDebugger.visible = !focusDebugger.visible } + } diff --git a/libraries/gl/src/gl/OffscreenQmlSurface.cpp b/libraries/gl/src/gl/OffscreenQmlSurface.cpp index 813386132c..3a72d98402 100644 --- a/libraries/gl/src/gl/OffscreenQmlSurface.cpp +++ b/libraries/gl/src/gl/OffscreenQmlSurface.cpp @@ -338,6 +338,7 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) { _updateTimer.start(); _qmlComponent = new QQmlComponent(_qmlEngine); + _qmlEngine->rootContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow())); } void OffscreenQmlSurface::resize(const QSize& newSize_) { From 5f38c5265c5dfb226b270884bc936fc9b8309ecc Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 Jan 2016 16:58:32 -0800 Subject: [PATCH 079/145] Fixing potential crash in dialog popups --- libraries/ui/src/OffscreenUi.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 8790c07f62..d7d28bef84 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -150,7 +150,9 @@ protected: } ~ModalDialogListener() { - disconnect(_dialog); + if (_dialog) { + disconnect(_dialog); + } } virtual QVariant waitForResult() { @@ -164,10 +166,11 @@ protected slots: void onDestroyed() { _finished = true; disconnect(_dialog); + _dialog = nullptr; } protected: - QQuickItem* const _dialog; + QQuickItem* _dialog; bool _finished { false }; QVariant _result; }; @@ -372,6 +375,7 @@ void OffscreenUi::createDesktop(const QUrl& url) { qDebug() << "Desktop already created"; return; } + #ifdef DEBUG getRootContext()->setContextProperty("DebugQML", QVariant(true)); #else @@ -382,9 +386,6 @@ void OffscreenUi::createDesktop(const QUrl& url) { Q_ASSERT(_desktop); getRootContext()->setContextProperty("desktop", _desktop); - // Enable focus debugging - _desktop->setProperty("offscreenWindow", QVariant::fromValue(getWindow())); - _toolWindow = _desktop->findChild("ToolWindow"); new VrMenu(this); From 940b0950139ecfe8cb34d0aa0c0fc57e86d582e7 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 Jan 2016 16:59:37 -0800 Subject: [PATCH 080/145] Removing menu logspam --- libraries/ui/src/VrMenu.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/ui/src/VrMenu.cpp b/libraries/ui/src/VrMenu.cpp index 103eb7660e..2006b22860 100644 --- a/libraries/ui/src/VrMenu.cpp +++ b/libraries/ui/src/VrMenu.cpp @@ -142,7 +142,6 @@ void VrMenu::addAction(QMenu* menu, QAction* action) { Q_ASSERT(menuQml); QQuickMenuItem* returnedValue { nullptr }; - qDebug() << menuQml; bool invokeResult = QMetaObject::invokeMethod(menuQml, "addItem", Qt::DirectConnection, Q_RETURN_ARG(QQuickMenuItem*, returnedValue), Q_ARG(QString, action->text())); From fee920723a04e675e91dca4a098f56b78f41da93 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 Jan 2016 17:25:20 -0800 Subject: [PATCH 081/145] Cleaning up test project --- tests/ui/qml/UI.js | 45 --------------- tests/ui/qmlscratch.pro | 122 +++++++--------------------------------- 2 files changed, 19 insertions(+), 148 deletions(-) delete mode 100644 tests/ui/qml/UI.js diff --git a/tests/ui/qml/UI.js b/tests/ui/qml/UI.js deleted file mode 100644 index 0286ac56a6..0000000000 --- a/tests/ui/qml/UI.js +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the Qt Quick Controls module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names -** of its contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -.pragma library - -var margin = 2 -var tabPosition = Qt.TopEdge -var label = "" diff --git a/tests/ui/qmlscratch.pro b/tests/ui/qmlscratch.pro index b3c8be0f22..7a1b5ab652 100644 --- a/tests/ui/qmlscratch.pro +++ b/tests/ui/qmlscratch.pro @@ -7,108 +7,24 @@ CONFIG += c++11 SOURCES += src/main.cpp \ ../../libraries/ui/src/FileDialogHelper.cpp -# Additional import path used to resolve QML modules in Qt Creator's code model -QML_IMPORT_PATH = - -DISTFILES += \ - qml/UI.js \ - qml/main.qml \ - qml/Palettes.qml \ - qml/StubMenu.qml \ - qml/Stubs.qml \ - qml/TestControllers.qml \ - qml/TestDialog.qml \ - qml/TestMenu.qml \ - qml/TestRoot.qml \ - qml/controlDemo/ButtonPage.qml \ - qml/controlDemo/InputPage.qml \ - qml/controlDemo/main.qml \ - qml/controlDemo/ProgressPage.qml \ - ../../interface/resources/qml/controller/hydra/HydraButtons.qml \ - ../../interface/resources/qml/controller/hydra/HydraStick.qml \ - ../../interface/resources/qml/controller/xbox/DPad.qml \ - ../../interface/resources/qml/controller/xbox/LeftAnalogStick.qml \ - ../../interface/resources/qml/controller/xbox/RightAnalogStick.qml \ - ../../interface/resources/qml/controller/xbox/XboxButtons.qml \ - ../../interface/resources/qml/controller/AnalogButton.qml \ - ../../interface/resources/qml/controller/AnalogStick.qml \ - ../../interface/resources/qml/controller/Hydra.qml \ - ../../interface/resources/qml/controller/Standard.qml \ - ../../interface/resources/qml/controller/ToggleButton.qml \ - ../../interface/resources/qml/controller/Xbox.qml \ - ../../interface/resources/qml/controls/Button.qml \ - ../../interface/resources/qml/controls/ButtonAwesome.qml \ - ../../interface/resources/qml/controls/CheckBox.qml \ - ../../interface/resources/qml/controls/FontAwesome.qml \ - ../../interface/resources/qml/controls/Player.qml \ - ../../interface/resources/qml/controls/Slider.qml \ - ../../interface/resources/qml/controls/Spacer.qml \ - ../../interface/resources/qml/controls/SpinBox.qml \ - ../../interface/resources/qml/controls/Text.qml \ - ../../interface/resources/qml/controls/TextAndSlider.qml \ - ../../interface/resources/qml/controls/TextAndSpinBox.qml \ - ../../interface/resources/qml/controls/TextArea.qml \ - ../../interface/resources/qml/controls/TextEdit.qml \ - ../../interface/resources/qml/controls/TextHeader.qml \ - ../../interface/resources/qml/controls/TextInput.qml \ - ../../interface/resources/qml/controls/TextInputAndButton.qml \ - ../../interface/resources/qml/controls/WebView.qml \ - ../../interface/resources/qml/dialogs/FileDialog.qml \ - ../../interface/resources/qml/dialogs/MessageDialog.qml \ - ../../interface/resources/qml/dialogs/RunningScripts.qml \ - ../../interface/resources/qml/hifi/MenuOption.qml \ - ../../interface/resources/qml/styles/Border.qml \ - ../../interface/resources/qml/styles/HifiConstants.qml \ - ../../interface/resources/qml/windows/DefaultFrame.qml \ - ../../interface/resources/qml/windows/Fadable.qml \ - ../../interface/resources/qml/windows/Frame.qml \ - ../../interface/resources/qml/windows/ModalFrame.qml \ - ../../interface/resources/qml/windows/Window.qml \ - ../../interface/resources/qml/AddressBarDialog.qml \ - ../../interface/resources/qml/AvatarInputs.qml \ - ../../interface/resources/qml/Browser.qml \ - ../../interface/resources/qml/InfoView.qml \ - ../../interface/resources/qml/LoginDialog.qml \ - ../../interface/resources/qml/QmlWebWindow.qml \ - ../../interface/resources/qml/QmlWindow.qml \ - ../../interface/resources/qml/Root.qml \ - ../../interface/resources/qml/ScrollingGraph.qml \ - ../../interface/resources/qml/Stats.qml \ - ../../interface/resources/qml/TextOverlayElement.qml \ - ../../interface/resources/qml/Tooltip.qml \ - ../../interface/resources/qml/ToolWindow.qml \ - ../../interface/resources/qml/UpdateDialog.qml \ - ../../interface/resources/qml/VrMenu.qml \ - ../../interface/resources/qml/VrMenuItem.qml \ - ../../interface/resources/qml/VrMenuView.qml \ - ../../interface/resources/qml/WebEntity.qml \ - ../../interface/resources/qml/desktop/Desktop.qml \ - ../../interface/resources/qml/hifi/Desktop.qml \ - ../../interface/resources/qml/menus/MenuMouseHandler.qml \ - ../../interface/resources/qml/menus/VrMenuItem.qml \ - ../../interface/resources/qml/menus/VrMenuView.qml \ - ../../interface/resources/qml/windows/ModalWindow.qml \ - ../../interface/resources/qml/desktop/FocusHack.qml \ - ../../interface/resources/qml/hifi/dialogs/PreferencesDialog.qml \ - ../../interface/resources/qml/hifi/dialogs/Section.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/Browsable.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/Section.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/Editable.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/Slider.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/Preference.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/CheckBox.qml \ - ../../interface/resources/qml/dialogs/fileDialog/FileTableView.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/Avatar.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/AvatarBrowser.qml \ - ../../interface/resources/qml/dialogs/QueryDialog.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/Button.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/AvatarPreference.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/BrowsablePreference.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/ButtonPreference.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/CheckBoxPreference.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/EditablePreference.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/SliderPreference.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/SpinBoxPreference.qml - HEADERS += \ ../../libraries/ui/src/FileDialogHelper.h + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = ../../interface/resources/qml + + +DISTFILES += \ + qml/*.qml \ + ../../interface/resources/qml/*.qml \ + ../../interface/resources/qml/controls/*.qml \ + ../../interface/resources/qml/dialogs/*.qml \ + ../../interface/resources/qml/dialogs/fileDialog/*.qml \ + ../../interface/resources/qml/desktop/*.qml \ + ../../interface/resources/qml/menus/*.qml \ + ../../interface/resources/qml/styles/*.qml \ + ../../interface/resources/qml/windows/*.qml \ + ../../interface/resources/qml/hifi/*.qml \ + ../../interface/resources/qml/hifi/dialogs/*.qml \ + ../../interface/resources/qml/hifi/dialogs/preferences/*.qml + From 9a8d56da77ea79a232f16017cfa75d4301c03068 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 Jan 2016 17:25:36 -0800 Subject: [PATCH 082/145] Center new windows without a defined position --- interface/resources/qml/desktop/Desktop.qml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 14687f387e..e87862aa56 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -211,15 +211,16 @@ FocusScope { var windowRect = targetWindow.framedRect(); var minPosition = Qt.vector2d(-windowRect.x, -windowRect.y); var maxPosition = Qt.vector2d(desktop.width - windowRect.width, desktop.height - windowRect.height); - var newPosition; - if (targetWindow.x === -1 && targetWindow.y === -1) { + var newPosition = Qt.vector2d(targetWindow.x, targetWindow.y); + if (newPosition.x === -1 && newPosition.y === -1) { // Set initial window position // newPosition = Utils.randomPosition(minPosition, maxPosition); + console.log("Target has no defined position, putting in center of the screen") newPosition = Qt.vector2d(desktop.width / 2 - windowRect.width / 2, desktop.height / 2 - windowRect.height / 2); } - newPosition = Utils.clampVector(Qt.vector2d(targetWindow.x, targetWindow.y), minPosition, maxPosition); + newPosition = Utils.clampVector(newPosition, minPosition, maxPosition); targetWindow.x = newPosition.x; targetWindow.y = newPosition.y; } From 5d157b059f796d45b9896355d83b8eba9c7203e3 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 26 Jan 2016 17:40:32 -0800 Subject: [PATCH 083/145] Collapse all Job/Task Models to one, including TaskIO --- libraries/render/src/render/Task.h | 132 +++++++++-------------------- 1 file changed, 40 insertions(+), 92 deletions(-) diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index ac05fbe68a..66258711cc 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -52,6 +52,7 @@ protected: class Job; class Task; +class JobNoIO {}; // A default Config is always on; to create an enableable Config, use the ctor JobConfig(bool enabled) class JobConfig : public QObject { @@ -101,16 +102,16 @@ template void jobConfigure(T& data, const C& 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 jobRun(T& data, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { +template void jobRun(T& data, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const JobNoIO& input, JobNoIO& output) { data.run(sceneContext, renderContext); } -template void jobRunI(T& data, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) { +template void jobRun(T& data, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, JobNoIO& output) { data.run(sceneContext, renderContext, input); } -template void jobRunO(T& data, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) { +template void jobRun(T& data, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const JobNoIO& input, O& output) { data.run(sceneContext, renderContext, output); } -template void jobRunIO(T& data, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) { +template void jobRun(T& data, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) { data.run(sceneContext, renderContext, input, output); } @@ -118,6 +119,7 @@ class Job { public: using Config = JobConfig; using QConfigPointer = std::shared_ptr; + using None = JobNoIO; // The guts of a job class Concept { @@ -138,84 +140,7 @@ public: }; using ConceptPointer = std::shared_ptr; - template class Model : public Concept { - public: - using Data = T; - - Data _data; - - Model(Data data = Data()) : Concept(std::make_shared()), _data(data) { - applyConfiguration(); - } - - void applyConfiguration() { - jobConfigure(_data, *std::static_pointer_cast(_config)); - } - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - renderContext->jobConfig = std::static_pointer_cast(_config); - if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { - jobRun(_data, sceneContext, renderContext); - } - renderContext->jobConfig.reset(); - } - }; - - template class ModelI : public Concept { - public: - using Data = T; - using Input = I; - - Data _data; - Varying _input; - - const Varying getInput() const { return _input; } - - ModelI(const Varying& input, Data data = Data()) : Concept(std::make_shared()), _data(data), _input(input) { - applyConfiguration(); - } - - void applyConfiguration() { - jobConfigure(_data, *std::static_pointer_cast(_config)); - } - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - renderContext->jobConfig = std::static_pointer_cast(_config); - if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { - jobRunI(_data, sceneContext, renderContext, _input.get()); - } - renderContext->jobConfig.reset(); - } - }; - - template class ModelO : public Concept { - public: - using Data = T; - using Output = O; - - Data _data; - Varying _output; - - const Varying getOutput() const { return _output; } - - ModelO(Data data = Data()) : Concept(std::make_shared()), _data(data), _output(Output()) { - applyConfiguration(); - } - - void applyConfiguration() { - jobConfigure(_data, *std::static_pointer_cast(_config)); - } - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - renderContext->jobConfig = std::static_pointer_cast(_config); - if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { - jobRunO(_data, sceneContext, renderContext, _output.edit()); - } - renderContext->jobConfig.reset(); - } - }; - - template class ModelIO : public Concept { + template class Model : public Concept { public: using Data = T; using Input = I; @@ -228,7 +153,7 @@ public: const Varying getInput() const { return _input; } const Varying getOutput() const { return _output; } - ModelIO(const Varying& input, Data data = Data()) : Concept(std::make_shared()), _data(data), _input(input), _output(Output()) { + Model(const Varying& input, Data data = Data()) : Concept(std::make_shared()), _data(data), _input(input), _output(Output()) { applyConfiguration(); } @@ -239,11 +164,14 @@ public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { renderContext->jobConfig = std::static_pointer_cast(_config); if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { - jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); + jobRun(_data, sceneContext, 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) {} @@ -278,17 +206,24 @@ class Task { public: using Config = TaskConfig; using QConfigPointer = Job::QConfigPointer; + using None = Job::None; - template class Model : public Job::Concept { + template class Model : public Job::Concept { public: using Data = T; + using Input = I; + using Output = O; Data _data; + Varying _input; + Varying _output; - Model(Data data = Data()) : Concept(std::make_shared()), _data(data) { + const Varying getInput() const { return _input; } + const Varying getOutput() const { return _output; } + + Model(const Varying& input, Data data = Data()) : Concept(std::make_shared()), _data(data), _input(input), _output(Output()) { _config = _data._config; // use the data's config std::static_pointer_cast(_config)->init(&_data); - applyConfiguration(); } @@ -299,11 +234,14 @@ public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { renderContext->jobConfig = std::static_pointer_cast(_config); if (renderContext->jobConfig->alwaysEnabled || renderContext->jobConfig->enabled) { - jobRun(_data, sceneContext, renderContext); + jobRun(_data, sceneContext, renderContext, _input.get(), _output.edit()); } renderContext->jobConfig.reset(); } }; + template using ModelI = Model; + template using ModelO = Model; + template using ModelIO = Model; using Jobs = std::vector; @@ -311,15 +249,25 @@ public: Task() : _config{ std::make_shared() } {} template Task(std::shared_ptr config) : _config{ config } {} - // Queue a new job to the container; returns the job's output - template const Varying addJob(std::string name, A&&... args) { - _jobs.emplace_back(name, std::make_shared(std::forward(args)...)); + // Create a new job in the container's queue; returns the job's output + template const Varying addJob(std::string name, const Varying& input, A&&... args) { + _jobs.emplace_back(name, std::make_shared( + input, + typename T::JobModel::Data(std::forward(args)...))); QConfigPointer config = _jobs.back().getConfiguration(); config->setParent(_config.get()); config->setObjectName(name.c_str()); QObject::connect(config.get(), SIGNAL(dirty()), _config.get(), SLOT(refresh())); return _jobs.back().getOutput(); } + template const Varying addJob(std::string name, Varying& input, A&&... args) { + const auto& in = input; + return addJob(name, in, std::forward(args)...); + } + template const Varying addJob(std::string name, A&&... args) { + auto input = Varying(typename T::JobModel::Input()); + return addJob(name, input, std::forward(args)...); + } std::shared_ptr getConfiguration() { auto config = std::static_pointer_cast(_config); @@ -335,7 +283,7 @@ public: } protected: - template friend class Model; + template friend class Model; QConfigPointer _config; Jobs _jobs; From 61f337b4909a2e6bbdd63721c7179a5ff4eecc3b Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 26 Jan 2016 17:42:54 -0800 Subject: [PATCH 084/145] Hold Varying constant over task ctor --- libraries/render-utils/src/RenderDeferredTask.cpp | 13 +++++++------ libraries/render-utils/src/RenderShadowTask.cpp | 8 ++++---- libraries/render/src/render/Task.h | 6 +----- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 06fadb69b3..eb46129777 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -89,15 +89,16 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { initDeferredPipelines(*shapePlumber); // CPU: Fetch the renderOpaques - auto fetchedOpaques = addJob("FetchOpaque"); - auto culledOpaques = addJob>("CullOpaque", fetchedOpaques, cullFunctor); - auto opaques = addJob("DepthSortOpaque", culledOpaques); + const auto fetchedOpaques = addJob("FetchOpaque"); + const auto culledOpaques = addJob>("CullOpaque", fetchedOpaques, cullFunctor); + const auto opaques = addJob("DepthSortOpaque", culledOpaques); // CPU only, create the list of renderedTransparents items - auto fetchedTransparents = addJob("FetchTransparent", FetchItems( + const auto fetchedTransparents = addJob("FetchTransparent", FetchItems( ItemFilter::Builder::transparentShape().withoutLayered())); - auto culledTransparents = addJob>("CullTransparent", fetchedTransparents, cullFunctor); - auto transparents = addJob("DepthSortTransparent", culledTransparents, DepthSortItems(false)); + const auto culledTransparents = + addJob>("CullTransparent", fetchedTransparents, cullFunctor); + const auto transparents = addJob("DepthSortTransparent", culledTransparents, DepthSortItems(false)); // GPU Jobs: Start preparing the deferred and lighting buffer addJob("PrepareDeferred"); diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index be6cd47f95..b8686a6c00 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -105,16 +105,16 @@ RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) : Task(std::make_sha } // CPU: Fetch shadow-casting opaques - auto fetchedItems = addJob("FetchShadowMap"); + const auto fetchedItems = addJob("FetchShadowMap"); // CPU: Cull against KeyLight frustum (nearby viewing camera) - auto culledItems = addJob>("CullShadowMap", fetchedItems, cullFunctor); + const auto culledItems = addJob>("CullShadowMap", fetchedItems, cullFunctor); // CPU: Sort by pipeline - auto sortedShapes = addJob("PipelineSortShadowSort", culledItems); + const auto sortedShapes = addJob("PipelineSortShadowSort", culledItems); // CPU: Sort front to back - auto shadowShapes = addJob("DepthSortShadowMap", sortedShapes); + const auto shadowShapes = addJob("DepthSortShadowMap", sortedShapes); // GPU: Render to shadow map addJob("RenderShadowMap", shadowShapes, shapePlumber); diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 66258711cc..148117eed6 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -260,12 +260,8 @@ public: QObject::connect(config.get(), SIGNAL(dirty()), _config.get(), SLOT(refresh())); return _jobs.back().getOutput(); } - template const Varying addJob(std::string name, Varying& input, A&&... args) { - const auto& in = input; - return addJob(name, in, std::forward(args)...); - } template const Varying addJob(std::string name, A&&... args) { - auto input = Varying(typename T::JobModel::Input()); + const auto input = Varying(typename T::JobModel::Input()); return addJob(name, input, std::forward(args)...); } From 4354eae129e740e3d086d684e3303eddb32bc88d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 26 Jan 2016 18:09:18 -0800 Subject: [PATCH 085/145] Fix type, gaussion->gaussian --- libraries/render-utils/src/AmbientOcclusionEffect.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 50b6c06254..185afade03 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -104,7 +104,7 @@ AmbientOcclusionEffect::AmbientOcclusionEffect() { void AmbientOcclusionEffect::configure(const Config& config) { DependencyManager::get()->setAmbientOcclusionEnabled(config.enabled); - bool shouldUpdateGaussion = false; + bool shouldUpdateGaussian = false; const double RADIUS_POWER = 6.0; const auto& radius = config.radius; @@ -133,7 +133,7 @@ void AmbientOcclusionEffect::configure(const Config& config) { if (config.blurDeviation != getBlurDeviation()) { auto& current = _parametersBuffer.edit().blurInfo; current.z = config.blurDeviation; - shouldUpdateGaussion = true; + shouldUpdateGaussian = true; } if (config.numSpiralTurns != getNumSpiralTurns()) { @@ -159,7 +159,7 @@ void AmbientOcclusionEffect::configure(const Config& config) { if (config.blurRadius != getBlurRadius()) { auto& current = _parametersBuffer.edit().blurInfo; current.y = (float)config.blurRadius; - shouldUpdateGaussion = true; + shouldUpdateGaussian = true; } if (config.ditheringEnabled != isDitheringEnabled()) { @@ -172,7 +172,7 @@ void AmbientOcclusionEffect::configure(const Config& config) { current.w = (float)config.borderingEnabled; } - if (shouldUpdateGaussion) { + if (shouldUpdateGaussian) { updateGaussianDistribution(); } } From fbee221966a7dd2dc7f21dd558cc161a33d8ad59 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 Jan 2016 18:15:41 -0800 Subject: [PATCH 086/145] Fix tool window breaking when visible while edit.js reloads --- interface/resources/qml/ToolWindow.qml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/ToolWindow.qml b/interface/resources/qml/ToolWindow.qml index 8e42f67ebc..9aad639ff3 100644 --- a/interface/resources/qml/ToolWindow.qml +++ b/interface/resources/qml/ToolWindow.qml @@ -103,6 +103,8 @@ Windows.Window { if (index < 0) { return; } + var tab = tabView.getTab(index); + tab.enabledChanged.disconnect(updateVisiblity); tabView.removeTab(index); console.log("Updating visibility based on child tab removed"); updateVisiblity(); @@ -137,10 +139,7 @@ Windows.Window { } console.log("Updating visibility based on child tab added"); - newTab.enabledChanged.connect(function() { - console.log("Updating visibility based on child tab enabled change"); - updateVisiblity(); - }) + newTab.enabledChanged.connect(updateVisiblity) updateVisiblity(); return newTab } From f178fc789c089465ce67cdfd3b2e68c119b7bb23 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Tue, 26 Jan 2016 18:44:34 -0800 Subject: [PATCH 087/145] fix for animations stopping after domain restart --- libraries/animation/src/AnimationLoop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/animation/src/AnimationLoop.cpp b/libraries/animation/src/AnimationLoop.cpp index 1e04af5dfa..f6a2877966 100644 --- a/libraries/animation/src/AnimationLoop.cpp +++ b/libraries/animation/src/AnimationLoop.cpp @@ -18,7 +18,7 @@ const float AnimationLoop::MAXIMUM_POSSIBLE_FRAME = 100000.0f; AnimationLoop::AnimationLoop() : _fps(30.0f), - _loop(false), + _loop(true), _hold(false), _startAutomatically(false), _firstFrame(0.0f), From 0a6be80578a1abd00ec23eac423443baab2061e1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 Jan 2016 18:50:55 -0800 Subject: [PATCH 088/145] Added some disabled modal focus protection code --- interface/resources/qml/desktop/Desktop.qml | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index e87862aa56..8c4f73c200 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -154,6 +154,28 @@ FocusScope { function onWindowFocusChanged() { console.log("Focus item is " + offscreenWindow.activeFocusItem); + + // FIXME this needs more testing before it can go into production + // and I already cant produce any way to have a modal dialog lose focus + // to a non-modal one. + /* + var focusedWindow = getDesktopWindow(offscreenWindow.activeFocusItem); + + if (isModalWindow(focusedWindow)) { + return; + } + + // new focused window is not modal... check if there are any modal windows + var windows = getTopLevelWindows(isModalWindow); + if (0 === windows.length) { + return; + } + + // There are modal windows present, force focus back to the top-most modal window + windows.sort(function(a, b){ return a.z - b.z; }); + windows[windows.length - 1].focus = true; + */ + // var focusedItem = offscreenWindow.activeFocusItem ; // if (DebugQML && focusedItem) { // var rect = desktop.mapFromItem(focusedItem, 0, 0, focusedItem.width, focusedItem.height); From e770d7b679c010593ccbacf190008c21c3538b8e Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 26 Jan 2016 18:56:22 -0800 Subject: [PATCH 089/145] Add PhysicsShowOwned back to Menu --- interface/src/Application.cpp | 15 ++++++++------- interface/src/Menu.cpp | 6 ++++++ interface/src/Menu.h | 1 + libraries/render/src/render/DrawStatus.cpp | 5 ++++- libraries/render/src/render/DrawStatus.h | 11 ++++++++--- 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ea853bc6a6..fdad0d6502 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -673,13 +673,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : _offscreenContext->makeCurrent(); initializeGL(); - // Start rendering - render::CullFunctor cullFunctor = LODManager::shouldRender; - _renderEngine->addJob("RenderShadowTask", cullFunctor); - _renderEngine->addJob("RenderDeferredTask", cullFunctor); - _renderEngine->registerScene(_main3DScene); - // TODO: Load a cached config file - _offscreenContext->makeCurrent(); // Tell our entity edit sender about our known jurisdictions @@ -1150,9 +1143,17 @@ void Application::initializeGL() { initDisplay(); qCDebug(interfaceapp, "Initialized Display."); + // Set up the render engine + render::CullFunctor cullFunctor = LODManager::shouldRender; + _renderEngine->addJob("RenderShadowTask", cullFunctor); + _renderEngine->addJob("RenderDeferredTask", cullFunctor); + _renderEngine->registerScene(_main3DScene); + // TODO: Load a cached config file + // The UI can't be created until the primary OpenGL // context is created, because it needs to share // texture resources + // Needs to happen AFTER the render engine initialization to access its configuration initializeUi(); qCDebug(interfaceapp, "Initialized Offscreen UI."); _offscreenContext->makeCurrent(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 27d1ed9bc2..fe545e0f2e 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -32,6 +32,7 @@ #include "devices/Faceshift.h" #include "input-plugins/SpacemouseManager.h" #include "MainWindow.h" +#include "render/DrawStatus.h" #include "scripting/MenuScriptingInterface.h" #include "ui/AssetUploadDialogFactory.h" #include "ui/DialogsManager.h" @@ -584,6 +585,11 @@ Menu::Menu() { // Developer > Physics >>> MenuWrapper* physicsOptionsMenu = developerMenu->addMenu("Physics"); + { + auto drawStatusConfig = qApp->getRenderEngine()->getConfiguration()->getConfig(); + addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowOwned, + 0, false, drawStatusConfig, SLOT(setShowNetwork(bool))); + } addCheckableActionToQMenuAndActionHash(physicsOptionsMenu, MenuOption::PhysicsShowHulls); // Developer > Display Crash Options diff --git a/interface/src/Menu.h b/interface/src/Menu.h index f07ce641d8..f0c742e361 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -245,6 +245,7 @@ namespace MenuOption { const QString PackageModel = "Package Model..."; const QString Pair = "Pair"; const QString PhysicsShowHulls = "Draw Collision Hulls"; + const QString PhysicsShowOwned = "Highlight Simulation Ownership"; const QString PipelineWarnings = "Log Render Pipeline Warnings"; const QString Preferences = "General..."; const QString Quit = "Quit"; diff --git a/libraries/render/src/render/DrawStatus.cpp b/libraries/render/src/render/DrawStatus.cpp index c043867c88..112aa0be03 100644 --- a/libraries/render/src/render/DrawStatus.cpp +++ b/libraries/render/src/render/DrawStatus.cpp @@ -27,7 +27,10 @@ using namespace render; - +void DrawStatusConfig::dirtyHelper() { + enabled = showNetwork || showDisplay; + emit dirty(); +} const gpu::PipelinePointer DrawStatus::getDrawItemBoundsPipeline() { if (!_drawItemBoundsPipeline) { diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index d1caeca673..b00e42b13d 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -18,15 +18,20 @@ namespace render { class DrawStatusConfig : public Job::Config { Q_OBJECT - Q_PROPERTY(bool enabled MEMBER enabled) - Q_PROPERTY(bool showDisplay MEMBER showDisplay NOTIFY dirty) - Q_PROPERTY(bool showNetwork MEMBER showDisplay NOTIFY dirty) + Q_PROPERTY(bool showDisplay MEMBER showDisplay WRITE setShowDisplay) + Q_PROPERTY(bool showNetwork MEMBER showNetwork WRITE setShowNetwork) public: DrawStatusConfig() : Job::Config(false) {} + void dirtyHelper(); + bool showDisplay{ false }; bool showNetwork{ false }; + public slots: + void setShowDisplay(bool enabled) { showDisplay = enabled; dirtyHelper(); } + void setShowNetwork(bool enabled) { showNetwork = enabled; dirtyHelper(); } + signals: void dirty(); }; From 49c1285837a1ce1c506f0ae456f473745b26b44a Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 26 Jan 2016 19:11:59 -0800 Subject: [PATCH 090/145] Add suffix Mode to DebugMode enum to avoid collision --- .../render-utils/src/DebugDeferredBuffer.cpp | 36 ++++++++++--------- .../render-utils/src/DebugDeferredBuffer.h | 25 ++++++------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 2dcfa35522..06d8709dc5 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -30,15 +30,15 @@ using namespace render; void DebugDeferredBufferConfig::setMode(int newMode) { if (newMode == mode) { return; - } else if (newMode > (int)DebugDeferredBuffer::Custom || newMode < 0) { - mode = (int)DebugDeferredBuffer::Custom; + } else if (newMode > DebugDeferredBuffer::CustomMode || newMode < 0) { + mode = DebugDeferredBuffer::CustomMode; } else { mode = newMode; } emit dirty(); } -enum Slots { +enum Slot { Diffuse = 0, Normal, Specular, @@ -50,6 +50,8 @@ enum Slots { AmbientOcclusionBlurred }; + + static const std::string DEFAULT_DIFFUSE_SHADER { "vec4 getFragmentColor() {" " return vec4(pow(texture(diffuseMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);" @@ -142,27 +144,27 @@ DebugDeferredBuffer::DebugDeferredBuffer() { std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string customFile) { switch (mode) { - case Diffuse: + case DiffuseMode: return DEFAULT_DIFFUSE_SHADER; - case Specular: + case SpecularMode: return DEFAULT_SPECULAR_SHADER; - case Roughness: + case RoughnessMode: return DEFAULT_ROUGHNESS_SHADER; - case Normal: + case NormalMode: return DEFAULT_NORMAL_SHADER; - case Depth: + case DepthMode: return DEFAULT_DEPTH_SHADER; - case Lighting: + case LightingMode: return DEFAULT_LIGHTING_SHADER; - case Shadow: + case ShadowMode: return DEFAULT_SHADOW_SHADER; - case PyramidDepth: + case PyramidDepthMode: return DEFAULT_PYRAMID_DEPTH_SHADER; - case AmbientOcclusion: + case AmbientOcclusionMode: return DEFAULT_AMBIENT_OCCLUSION_SHADER; - case AmbientOcclusionBlurred: + case AmbientOcclusionBlurredMode: return DEFAULT_AMBIENT_OCCLUSION_BLURRED_SHADER; - case Custom: + case CustomMode: return getFileContent(customFile, DEFAULT_CUSTOM_SHADER); } Q_UNREACHABLE(); @@ -170,7 +172,7 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string cust } bool DebugDeferredBuffer::pipelineNeedsUpdate(Mode mode, std::string customFile) const { - if (mode != Custom) { + if (mode != CustomMode) { return !_pipelines[mode]; } @@ -218,14 +220,14 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Mode mode, std::str auto pipeline = gpu::Pipeline::create(program, std::make_shared()); // Good to go add the brand new pipeline - if (mode != Custom) { + if (mode != CustomMode) { _pipelines[mode] = pipeline; } else { _customPipelines[customFile].pipeline = pipeline; } } - if (mode != Custom) { + if (mode != CustomMode) { return _pipelines[mode]; } else { return _customPipelines[customFile].pipeline; diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index 1cd199c67b..ecc2012466 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -46,17 +46,18 @@ protected: friend class DebugDeferredBufferConfig; enum Mode : uint8_t { - Diffuse = 0, - Specular, - Roughness, - Normal, - Depth, - Lighting, - Shadow, - PyramidDepth, - AmbientOcclusion, - AmbientOcclusionBlurred, - Custom // Needs to stay last + // Use Mode suffix to avoid collisions + DiffuseMode = 0, + SpecularMode, + RoughnessMode, + NormalMode, + DepthMode, + LightingMode, + ShadowMode, + PyramidDepthMode, + AmbientOcclusionMode, + AmbientOcclusionBlurredMode, + CustomMode // Needs to stay last }; private: @@ -67,7 +68,7 @@ private: gpu::PipelinePointer pipeline; mutable QFileInfo info; }; - using StandardPipelines = std::array; + using StandardPipelines = std::array; using CustomPipelines = std::unordered_map; bool pipelineNeedsUpdate(Mode mode, std::string customFile = std::string()) const; From 91b0f6931238ae9b9c061ff9fc97a9828f6fccca Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Tue, 26 Jan 2016 21:02:16 -0800 Subject: [PATCH 091/145] When the avatar marketplace is chosen from avatar preferences, let it be moveable so that the user can move it aside to see their avatar. --- .../resources/qml/dialogs/preferences/AvatarBrowser.qml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/dialogs/preferences/AvatarBrowser.qml b/interface/resources/qml/dialogs/preferences/AvatarBrowser.qml index 7af5dc851e..cdeddb5886 100644 --- a/interface/resources/qml/dialogs/preferences/AvatarBrowser.qml +++ b/interface/resources/qml/dialogs/preferences/AvatarBrowser.qml @@ -1,5 +1,5 @@ -import QtQuick 2.3 -import QtQuick.Controls 1.2 +import QtQuick 2.5 +import QtQuick.Controls 1.4 import QtWebEngine 1.1 import "../../windows" as Windows @@ -11,9 +11,7 @@ Windows.Window { HifiConstants { id: hifi } width: 900; height: 700 resizable: true - anchors.centerIn: parent modality: Qt.ApplicationModal - frame: Windows.ModalFrame {} Item { anchors.fill: parent From 664100b9b14e13eeea2ff2aae71be21c95dbd571 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 23 Jan 2016 17:14:30 -0800 Subject: [PATCH 092/145] Attachment dialog --- .../qml/hifi/dialogs/AttachmentsDialog.qml | 123 +++++++++++++ .../hifi/dialogs/AvatarAttachmentsDialog.qml | 128 ++++++++++++++ .../qml/hifi/dialogs/ModelBrowserDialog.qml | 128 ++++++++++++++ .../hifi/dialogs/attachments/Attachment.qml | 164 ++++++++++++++++++ .../qml/hifi/dialogs/attachments/Rotation.qml | 9 + .../hifi/dialogs/attachments/Translation.qml | 9 + .../qml/hifi/dialogs/attachments/Vector3.qml | 71 ++++++++ .../resources/qml/hifi/models/S3Model.qml | 41 +++++ interface/resources/qml/js/Utils.js | 14 ++ interface/src/Application.cpp | 5 + libraries/avatars/src/AvatarData.cpp | 63 +++++++ libraries/avatars/src/AvatarData.h | 6 + libraries/networking/src/LimitedNodeList.cpp | 2 +- tests/ui/qml/main.qml | 12 ++ 14 files changed, 774 insertions(+), 1 deletion(-) create mode 100644 interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml create mode 100644 interface/resources/qml/hifi/dialogs/AvatarAttachmentsDialog.qml create mode 100644 interface/resources/qml/hifi/dialogs/ModelBrowserDialog.qml create mode 100644 interface/resources/qml/hifi/dialogs/attachments/Attachment.qml create mode 100644 interface/resources/qml/hifi/dialogs/attachments/Rotation.qml create mode 100644 interface/resources/qml/hifi/dialogs/attachments/Translation.qml create mode 100644 interface/resources/qml/hifi/dialogs/attachments/Vector3.qml create mode 100644 interface/resources/qml/hifi/models/S3Model.qml diff --git a/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml b/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml new file mode 100644 index 0000000000..77771f65c4 --- /dev/null +++ b/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml @@ -0,0 +1,123 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import Qt.labs.settings 1.0 + +import "../../windows" +import "attachments" + +Window { + id: root + title: "Edit Attachments" + width: 600 + height: 600 + resizable: true + // User must click OK or cancel to close the window + closable: false + + readonly property var originalAttachments: MyAvatar.getAttachmentsVariant(); + property var attachments: []; + + property var settings: Settings { + category: "AttachmentsDialog" + property alias x: root.x + property alias y: root.y + property alias width: root.width + property alias height: root.height + } + + Component.onCompleted: { + for (var i = 0; i < originalAttachments.length; ++i) { + var attachment = originalAttachments[i]; + root.attachments.push(attachment); + listView.model.append({}); + } + } + + Rectangle { + anchors.fill: parent + radius: 4 + + Rectangle { + id: attachmentsBackground + anchors { left: parent.left; right: parent.right; top: parent.top; bottom: newAttachmentButton.top; margins: 8 } + color: "gray" + radius: 4 + + ScrollView{ + id: scrollView + anchors.fill: parent + anchors.margins: 4 + ListView { + id: listView + model: ListModel {} + delegate: Item { + implicitHeight: attachmentView.height + 8; + implicitWidth: attachmentView.width; + Attachment { + id: attachmentView + width: scrollView.width + attachment: root.attachments[index] + onDeleteAttachment: { + attachments.splice(index, 1); + listView.model.remove(index, 1); + } + onUpdateAttachment: MyAvatar.setAttachmentsVariant(attachments); + } + } + onCountChanged: MyAvatar.setAttachmentsVariant(attachments); + } + } + } + + Button { + id: newAttachmentButton + anchors { left: parent.left; right: parent.right; bottom: buttonRow.top; margins: 8 } + text: "New Attachment" + + onClicked: { + var template = { + modelUrl: "", + translation: { x: 0, y: 0, z: 0 }, + rotation: { x: 0, y: 0, z: 0 }, + scale: 1, + jointName: MyAvatar.jointNames[0], + soft: false + }; + attachments.push(template); + listView.model.append({}); + MyAvatar.setAttachmentsVariant(attachments); + } + } + + Row { + id: buttonRow + spacing: 8 + anchors { right: parent.right; bottom: parent.bottom; margins: 8 } + Button { action: cancelAction } + Button { action: okAction } + } + + Action { + id: cancelAction + text: "Cancel" + onTriggered: { + MyAvatar.setAttachmentsVariant(originalAttachments); + root.destroy() + } + } + + Action { + id: okAction + text: "OK" + onTriggered: { + for (var i = 0; i < attachments.length; ++i) { + console.log("Attachment " + i + ": " + attachments[i]); + } + + MyAvatar.setAttachmentsVariant(attachments); + root.destroy() + } + } + } +} + diff --git a/interface/resources/qml/hifi/dialogs/AvatarAttachmentsDialog.qml b/interface/resources/qml/hifi/dialogs/AvatarAttachmentsDialog.qml new file mode 100644 index 0000000000..252e4c629e --- /dev/null +++ b/interface/resources/qml/hifi/dialogs/AvatarAttachmentsDialog.qml @@ -0,0 +1,128 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.XmlListModel 2.0 + +import "../../windows" +import "../../js/Utils.js" as Utils +import "../models" + +ModalWindow { + id: root + resizable: true + width: 640 + height: 480 + + property var result; + + signal selected(var modelUrl); + signal canceled(); + + Rectangle { + anchors.fill: parent + color: "white" + + Item { + anchors { fill: parent; margins: 8 } + + TextField { + id: filterEdit + anchors { left: parent.left; right: parent.right; top: parent.top } + placeholderText: "filter" + onTextChanged: tableView.model.filter = text + } + + TableView { + id: tableView + anchors { left: parent.left; right: parent.right; top: filterEdit.bottom; topMargin: 8; bottom: buttonRow.top; bottomMargin: 8 } + model: S3Model{} + onCurrentRowChanged: { + if (currentRow == -1) { + root.result = null; + return; + } + result = model.baseUrl + "/" + model.get(tableView.currentRow).key; + } + itemDelegate: Component { + Item { + clip: true + Text { + x: 3 + anchors.verticalCenter: parent.verticalCenter + color: tableView.activeFocus && styleData.row === tableView.currentRow ? "yellow" : styleData.textColor + elide: styleData.elideMode + text: getText() + + function getText() { + switch(styleData.column) { + case 1: + return Utils.formatSize(styleData.value) + default: + return styleData.value; + } + } + + } + } + } + TableViewColumn { + role: "name" + title: "Name" + width: 200 + } + TableViewColumn { + role: "size" + title: "Size" + width: 100 + } + TableViewColumn { + role: "modified" + title: "Last Modified" + width: 200 + } + Rectangle { + anchors.fill: parent + visible: tableView.model.status !== XmlListModel.Ready + color: "#7fffffff" + BusyIndicator { + anchors.centerIn: parent + width: 48; height: 48 + running: true + } + } + } + + Row { + id: buttonRow + anchors { right: parent.right; bottom: parent.bottom } + Button { action: acceptAction } + Button { action: cancelAction } + } + + Action { + id: acceptAction + text: qsTr("OK") + enabled: root.result ? true : false + shortcut: Qt.Key_Return + onTriggered: { + root.selected(root.result); + root.destroy(); + } + } + + Action { + id: cancelAction + text: qsTr("Cancel") + shortcut: Qt.Key_Escape + onTriggered: { + root.canceled(); + root.destroy(); + } + } + } + + } +} + + + + diff --git a/interface/resources/qml/hifi/dialogs/ModelBrowserDialog.qml b/interface/resources/qml/hifi/dialogs/ModelBrowserDialog.qml new file mode 100644 index 0000000000..252e4c629e --- /dev/null +++ b/interface/resources/qml/hifi/dialogs/ModelBrowserDialog.qml @@ -0,0 +1,128 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.XmlListModel 2.0 + +import "../../windows" +import "../../js/Utils.js" as Utils +import "../models" + +ModalWindow { + id: root + resizable: true + width: 640 + height: 480 + + property var result; + + signal selected(var modelUrl); + signal canceled(); + + Rectangle { + anchors.fill: parent + color: "white" + + Item { + anchors { fill: parent; margins: 8 } + + TextField { + id: filterEdit + anchors { left: parent.left; right: parent.right; top: parent.top } + placeholderText: "filter" + onTextChanged: tableView.model.filter = text + } + + TableView { + id: tableView + anchors { left: parent.left; right: parent.right; top: filterEdit.bottom; topMargin: 8; bottom: buttonRow.top; bottomMargin: 8 } + model: S3Model{} + onCurrentRowChanged: { + if (currentRow == -1) { + root.result = null; + return; + } + result = model.baseUrl + "/" + model.get(tableView.currentRow).key; + } + itemDelegate: Component { + Item { + clip: true + Text { + x: 3 + anchors.verticalCenter: parent.verticalCenter + color: tableView.activeFocus && styleData.row === tableView.currentRow ? "yellow" : styleData.textColor + elide: styleData.elideMode + text: getText() + + function getText() { + switch(styleData.column) { + case 1: + return Utils.formatSize(styleData.value) + default: + return styleData.value; + } + } + + } + } + } + TableViewColumn { + role: "name" + title: "Name" + width: 200 + } + TableViewColumn { + role: "size" + title: "Size" + width: 100 + } + TableViewColumn { + role: "modified" + title: "Last Modified" + width: 200 + } + Rectangle { + anchors.fill: parent + visible: tableView.model.status !== XmlListModel.Ready + color: "#7fffffff" + BusyIndicator { + anchors.centerIn: parent + width: 48; height: 48 + running: true + } + } + } + + Row { + id: buttonRow + anchors { right: parent.right; bottom: parent.bottom } + Button { action: acceptAction } + Button { action: cancelAction } + } + + Action { + id: acceptAction + text: qsTr("OK") + enabled: root.result ? true : false + shortcut: Qt.Key_Return + onTriggered: { + root.selected(root.result); + root.destroy(); + } + } + + Action { + id: cancelAction + text: qsTr("Cancel") + shortcut: Qt.Key_Escape + onTriggered: { + root.canceled(); + root.destroy(); + } + } + } + + } +} + + + + diff --git a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml new file mode 100644 index 0000000000..b45e10d755 --- /dev/null +++ b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml @@ -0,0 +1,164 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +import "../../../windows" +import "." +import ".." + +Item { + height: column.height + 2 * 8 + + property var attachment; + + signal deleteAttachment(var attachment); + signal updateAttachment(); + property bool completed: false; + + Rectangle { color: "white"; anchors.fill: parent; radius: 4 } + + Component.onCompleted: { + completed = true; + } + + Column { + y: 8 + id: column + anchors { left: parent.left; right: parent.right; margins: 8 } + spacing: 8 + + Item { + height: modelChooserButton.height + anchors { left: parent.left; right: parent.right; } + Text { id: urlLabel; text: "Model URL:"; width: 80; anchors.verticalCenter: modelUrl.verticalCenter } + TextField { + id: modelUrl; + height: jointChooser.height; + anchors { left: urlLabel.right; leftMargin: 8; rightMargin: 8; right: modelChooserButton.left } + text: attachment ? attachment.modelUrl : "" + onTextChanged: { + if (completed && attachment && attachment.modelUrl !== text) { + attachment.modelUrl = text; + updateAttachment(); + } + } + } + Button { + id: modelChooserButton; + text: "Choose"; + anchors { right: parent.right; verticalCenter: modelUrl.verticalCenter } + Component { + id: modelBrowserBuiler; + ModelBrowserDialog {} + } + + onClicked: { + var browser = modelBrowserBuiler.createObject(desktop); + browser.selected.connect(function(newModelUrl){ + modelUrl.text = newModelUrl; + }) + } + } + } + + Item { + height: jointChooser.height + anchors { left: parent.left; right: parent.right; } + Text { + id: jointLabel; + width: 80; + text: "Joint:"; + anchors.verticalCenter: jointChooser.verticalCenter; + } + ComboBox { + id: jointChooser; + anchors { left: jointLabel.right; leftMargin: 8; right: parent.right } + model: MyAvatar.jointNames + currentIndex: attachment ? model.indexOf(attachment.jointName) : -1 + onCurrentIndexChanged: { + if (completed && attachment && currentIndex != -1 && currentText && currentText !== attachment.jointName) { + attachment.jointName = currentText; + updateAttachment(); + } + } + } + } + + Item { + height: translation.height + anchors { left: parent.left; right: parent.right; } + Text { id: translationLabel; width: 80; text: "Translation:"; anchors.verticalCenter: translation.verticalCenter; } + Translation { + id: translation; + anchors { left: translationLabel.right; leftMargin: 8; right: parent.right } + vector: attachment ? attachment.translation : {x: 0, y: 0, z: 0}; + onValueChanged: { + if (completed && attachment) { + attachment.translation = vector; + updateAttachment(); + } + } + } + } + + Item { + height: rotation.height + anchors { left: parent.left; right: parent.right; } + Text { id: rotationLabel; width: 80; text: "Rotation:"; anchors.verticalCenter: rotation.verticalCenter; } + Rotation { + id: rotation; + anchors { left: rotationLabel.right; leftMargin: 8; right: parent.right } + vector: attachment ? attachment.rotation : {x: 0, y: 0, z: 0}; + onValueChanged: { + if (completed && attachment) { + attachment.rotation = vector; + updateAttachment(); + } + } + } + } + + Item { + height: scaleSpinner.height + anchors { left: parent.left; right: parent.right; } + Text { id: scaleLabel; width: 80; text: "Scale:"; anchors.verticalCenter: scale.verticalCenter; } + SpinBox { + id: scaleSpinner; + anchors { left: scaleLabel.right; leftMargin: 8; right: parent.right } + decimals: 1; + minimumValue: 0.1 + maximumValue: 10 + stepSize: 0.1; + value: attachment ? attachment.scale : 1.0 + onValueChanged: { + if (completed && attachment && attachment.scale !== value) { + attachment.scale = value; + updateAttachment(); + } + } + } + } + + Item { + height: soft.height + anchors { left: parent.left; right: parent.right; } + Text { id: softLabel; width: 80; text: "Is soft:"; anchors.verticalCenter: soft.verticalCenter; } + CheckBox { + id: soft; + anchors { left: softLabel.right; leftMargin: 8; right: parent.right } + checked: attachment ? attachment.soft : false + onCheckedChanged: { + if (completed && attachment && attachment.soft !== checked) { + attachment.soft = checked; + updateAttachment(); + } + } + } + } + + Button { + anchors { left: parent.left; right: parent.right; } + text: "Delete" + onClicked: deleteAttachment(root.attachment); + } + } +} diff --git a/interface/resources/qml/hifi/dialogs/attachments/Rotation.qml b/interface/resources/qml/hifi/dialogs/attachments/Rotation.qml new file mode 100644 index 0000000000..6061efc4c8 --- /dev/null +++ b/interface/resources/qml/hifi/dialogs/attachments/Rotation.qml @@ -0,0 +1,9 @@ +import "." + +Vector3 { + decimals: 1; + stepSize: 1; + maximumValue: 180 + minimumValue: -180 +} + diff --git a/interface/resources/qml/hifi/dialogs/attachments/Translation.qml b/interface/resources/qml/hifi/dialogs/attachments/Translation.qml new file mode 100644 index 0000000000..f3a90cdf94 --- /dev/null +++ b/interface/resources/qml/hifi/dialogs/attachments/Translation.qml @@ -0,0 +1,9 @@ +import "." + +Vector3 { + decimals: 2; + stepSize: 0.01; + maximumValue: 10 + minimumValue: -10 +} + diff --git a/interface/resources/qml/hifi/dialogs/attachments/Vector3.qml b/interface/resources/qml/hifi/dialogs/attachments/Vector3.qml new file mode 100644 index 0000000000..02382749bd --- /dev/null +++ b/interface/resources/qml/hifi/dialogs/attachments/Vector3.qml @@ -0,0 +1,71 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Item { + id: root + implicitHeight: xspinner.height + readonly property real spacing: 8 + property real spinboxWidth: (width / 3) - spacing + property var vector; + property real decimals: 0 + property real stepSize: 1 + property real maximumValue: 99 + property real minimumValue: 0 + + signal valueChanged(); + + SpinBox { + id: xspinner + width: root.spinboxWidth + anchors { left: parent.left } + value: root.vector.x + + decimals: root.decimals + stepSize: root.stepSize + maximumValue: root.maximumValue + minimumValue: root.minimumValue + onValueChanged: { + if (value !== vector.x) { + vector.x = value + root.valueChanged(); + } + } + } + + SpinBox { + id: yspinner + width: root.spinboxWidth + anchors { horizontalCenter: parent.horizontalCenter } + value: root.vector.y + + decimals: root.decimals + stepSize: root.stepSize + maximumValue: root.maximumValue + minimumValue: root.minimumValue + onValueChanged: { + if (value !== vector.y) { + vector.y = value + root.valueChanged(); + } + } + } + + SpinBox { + id: zspinner + width: root.spinboxWidth + anchors { right: parent.right; } + value: root.vector.z + + decimals: root.decimals + stepSize: root.stepSize + maximumValue: root.maximumValue + minimumValue: root.minimumValue + onValueChanged: { + if (value !== vector.z) { + vector.z = value + root.valueChanged(); + } + } + } +} + diff --git a/interface/resources/qml/hifi/models/S3Model.qml b/interface/resources/qml/hifi/models/S3Model.qml new file mode 100644 index 0000000000..565965c124 --- /dev/null +++ b/interface/resources/qml/hifi/models/S3Model.qml @@ -0,0 +1,41 @@ +import QtQuick 2.0 +import QtQuick.XmlListModel 2.0 + +//http://s3.amazonaws.com/hifi-public?prefix=models/attachments +/* + + + + models/attachments/guitar.fst + 2015-11-10T00:28:22.000Z + "236c00c4802ba9c2605cabd5601d138e" + 2992 + STANDARD + + +*/ + +// FIXME how to deal with truncated results? Store the marker? +XmlListModel { + id: xmlModel + property string prefix: "models/attachments/" + property string extension: "fst" + property string filter; + + readonly property string realPrefix: prefix.match('.*/$') ? prefix : (prefix + "/") + readonly property string nameRegex: realPrefix + (filter ? (".*" + filter) : "") + ".*\." + extension + readonly property string nameQuery: "Key/substring-before(substring-after(string(), '" + prefix + "'), '." + extension + "')" + readonly property string baseUrl: "http://s3.amazonaws.com/hifi-public" + + // FIXME need to urlencode prefix? + source: baseUrl + "?prefix=" + realPrefix + query: "/ListBucketResult/Contents[matches(Key, '" + nameRegex + "')]" + namespaceDeclarations: "declare default element namespace 'http://s3.amazonaws.com/doc/2006-03-01/';" + + XmlRole { name: "name"; query: nameQuery } + XmlRole { name: "size"; query: "Size/string()" } + XmlRole { name: "tag"; query: "ETag/string()" } + XmlRole { name: "modified"; query: "LastModified/string()" } + XmlRole { name: "key"; query: "Key/string()" } +} + diff --git a/interface/resources/qml/js/Utils.js b/interface/resources/qml/js/Utils.js index 417c8c1641..49f85fcc91 100644 --- a/interface/resources/qml/js/Utils.js +++ b/interface/resources/qml/js/Utils.js @@ -14,3 +14,17 @@ function randomPosition(min, max) { Math.random() * (max.x - min.x), Math.random() * (max.y - min.y)); } + +function formatSize(size) { + var suffixes = [ "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" ]; + var suffixIndex = 0 + while ((size / 1024.0) > 1.1) { + size /= 1024.0; + ++suffixIndex; + } + + size = Math.round(size*1000)/1000; + size = size.toLocaleString() + + return size + " " + suffixes[suffixIndex]; +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4629a8c08c..b3142702bb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1186,6 +1186,7 @@ void Application::initializeUi() { UpdateDialog::registerType(); qmlRegisterType("Hifi", 1, 0, "Preference"); + auto offscreenUi = DependencyManager::get(); offscreenUi->create(_offscreenContext->getContext()); offscreenUi->setProxyWindow(_window->windowHandle()); @@ -1842,6 +1843,10 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_X: if (isShifted && isMeta) { + auto offscreenUi = DependencyManager::get(); + offscreenUi->getRootContext()->engine()->clearComponentCache(); + offscreenUi->load("hifi/dialogs/AttachmentsDialog.qml"); + // OffscreenUi::information("Debugging", "Component cache cleared"); // placeholder for dialogs being converted to QML. } break; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 5fd69128eb..3933d705fc 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -1673,3 +1674,65 @@ glm::vec3 AvatarData::getAbsoluteJointTranslationInObjectFrame(int index) const assert(false); return glm::vec3(); } + +QVariant AttachmentData::toVariant() const { + QVariantMap result; + result["modelUrl"] = modelURL; + result["jointName"] = jointName; + result["translation"] = glmToQMap(translation); + result["rotation"] = glmToQMap(glm::degrees(safeEulerAngles(rotation))); + result["scale"] = scale; + result["soft"] = isSoft; + return result; +} + +glm::vec3 variantToVec3(const QVariant& var) { + auto map = var.toMap(); + glm::vec3 result; + result.x = map["x"].toFloat(); + result.y = map["y"].toFloat(); + result.z = map["z"].toFloat(); + return result; +} + +void AttachmentData::fromVariant(const QVariant& variant) { + auto map = variant.toMap(); + if (map.contains("modelUrl")) { + auto urlString = map["modelUrl"].toString(); + modelURL = urlString; + } + if (map.contains("jointName")) { + jointName = map["jointName"].toString(); + } + if (map.contains("translation")) { + translation = variantToVec3(map["translation"]); + } + if (map.contains("rotation")) { + rotation = glm::quat(glm::radians(variantToVec3(map["rotation"]))); + } + if (map.contains("scale")) { + scale = map["scale"].toFloat(); + } + if (map.contains("soft")) { + isSoft = map["soft"].toBool(); + } +} + +QVariantList AvatarData::getAttachmentsVariant() const { + QVariantList result; + for (const auto& attachment : getAttachmentData()) { + result.append(attachment.toVariant()); + } + return result; +} + +void AvatarData::setAttachmentsVariant(const QVariantList& variant) { + QVector newAttachments; + newAttachments.reserve(variant.size()); + for (const auto& attachmentVar : variant) { + AttachmentData attachment; + attachment.fromVariant(attachmentVar); + newAttachments.append(attachment); + } + setAttachmentData(newAttachments); +} diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 3b8214f226..eac1917533 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -277,6 +277,9 @@ public: Q_INVOKABLE void setBlendshape(QString name, float val) { _headData->setBlendshape(name, val); } + Q_INVOKABLE QVariantList getAttachmentsVariant() const; + Q_INVOKABLE void setAttachmentsVariant(const QVariantList& variant); + void setForceFaceTrackerConnected(bool connected) { _forceFaceTrackerConnected = connected; } // key state @@ -448,6 +451,9 @@ public: QJsonObject toJson() const; void fromJson(const QJsonObject& json); + + QVariant toVariant() const; + void fromVariant(const QVariant& variant); }; QDataStream& operator<<(QDataStream& out, const AttachmentData& attachment); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 485100da0a..3ea3175390 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -959,7 +959,7 @@ void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* p bool LimitedNodeList::getLocalServerPortFromSharedMemory(const QString key, quint16& localPort) { QSharedMemory sharedMem(key); if (!sharedMem.attach(QSharedMemory::ReadOnly)) { - qWarning() << "Could not attach to shared memory at key" << key; + qCWarning(networking) << "Could not attach to shared memory at key" << key; return false; } else { sharedMem.lock(); diff --git a/tests/ui/qml/main.qml b/tests/ui/qml/main.qml index c970cd711b..d20b580b5a 100644 --- a/tests/ui/qml/main.qml +++ b/tests/ui/qml/main.qml @@ -7,6 +7,7 @@ import "../../../interface/resources/qml" import "../../../interface/resources/qml/windows" import "../../../interface/resources/qml/dialogs" import "../../../interface/resources/qml/hifi" +import "../../../interface/resources/qml/hifi/dialogs" ApplicationWindow { id: appWindow @@ -196,4 +197,15 @@ ApplicationWindow { } */ } + + Action { + text: "Open Browser" + shortcut: "Ctrl+Shift+X" + onTriggered: { + builder.createObject(desktop); + } + property var builder: Component { + ModelBrowserDialog{} + } + } } From 2956557c5f50f8e5dd9b81ee4ed42629a54b8892 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 Jan 2016 14:41:22 -0800 Subject: [PATCH 093/145] Adding overlay compatible combo-box --- interface/resources/qml/controls/ComboBox.qml | 148 ++++++++++++++++++ .../hifi/dialogs/attachments/Attachment.qml | 3 +- 2 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 interface/resources/qml/controls/ComboBox.qml diff --git a/interface/resources/qml/controls/ComboBox.qml b/interface/resources/qml/controls/ComboBox.qml new file mode 100644 index 0000000000..e22bc8e664 --- /dev/null +++ b/interface/resources/qml/controls/ComboBox.qml @@ -0,0 +1,148 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +import "." as VrControls + +FocusScope { + id: root + property alias model: comboBox.model; + readonly property alias currentText: comboBox.currentText; + property alias currentIndex: comboBox.currentIndex; + implicitHeight: comboBox.height; + focus: true + + readonly property ComboBox control: comboBox + + Rectangle { + id: background + gradient: Gradient { + GradientStop {color: control.pressed ? "#bababa" : "#fefefe" ; position: 0} + GradientStop {color: control.pressed ? "#ccc" : "#e3e3e3" ; position: 1} + } + anchors.fill: parent + border.color: control.activeFocus ? "#47b" : "#999" + Rectangle { + anchors.fill: parent + radius: parent.radius + color: control.activeFocus ? "#47b" : "white" + opacity: control.hovered || control.activeFocus ? 0.1 : 0 + Behavior on opacity {NumberAnimation{ duration: 100 }} + } + } + + SystemPalette { id: palette } + + ComboBox { + id: comboBox + anchors.fill: parent + visible: false + } + + Text { + id: textField + anchors { left: parent.left; leftMargin: 2; right: dropIcon.left; verticalCenter: parent.verticalCenter } + text: comboBox.currentText + elide: Text.ElideRight + } + + Item { + id: dropIcon + anchors { right: parent.right; verticalCenter: parent.verticalCenter } + width: 20 + height: textField.height + VrControls.FontAwesome { + anchors.centerIn: parent; size: 16; + text: "\uf0d7" + } + } + + MouseArea { + anchors.fill: parent + onClicked: toggleList(); + } + + function toggleList() { + if (popup.visible) { + hideList(); + } else { + showList(); + } + } + + function showList() { + var r = desktop.mapFromItem(root, 0, 0, root.width, root.height); + listView.currentIndex = root.currentIndex + scrollView.x = r.x; + scrollView.y = r.y + r.height; + var bottom = scrollView.y + scrollView.height; + if (bottom > desktop.height) { + scrollView.y -= bottom - desktop.height + 8; + } + popup.visible = true; + popup.forceActiveFocus(); + } + + function hideList() { + popup.visible = false; + } + + FocusScope { + id: popup + parent: desktop + anchors.fill: parent + visible: false + focus: true + MouseArea { + anchors.fill: parent + onClicked: hideList(); + } + + function previousItem() { listView.currentIndex = (listView.currentIndex + listView.count - 1) % listView.count; } + function nextItem() { listView.currentIndex = (listView.currentIndex + listView.count + 1) % listView.count; } + function selectCurrentItem() { root.currentIndex = listView.currentIndex; hideList(); } + + Keys.onUpPressed: previousItem(); + Keys.onDownPressed: nextItem(); + Keys.onSpacePressed: selectCurrentItem(); + Keys.onRightPressed: selectCurrentItem(); + Keys.onReturnPressed: selectCurrentItem(); + Keys.onEscapePressed: hideList(); + + ScrollView { + id: scrollView + height: 480 + width: root.width + + ListView { + id: listView + height: textView.height * count + model: root.model + highlight: Rectangle{ + width: listView.currentItem ? listView.currentItem.width : 0 + height: listView.currentItem ? listView.currentItem.height : 0 + color: "red" + } + delegate: Rectangle { + width: root.width + height: popupText.implicitHeight * 1.4 + color: ListView.isCurrentItem ? palette.highlight : palette.base + Text { + anchors.verticalCenter: parent.verticalCenter + id: popupText + x: 3 + text: listView.model[index] + } + MouseArea { + id: popupHover + anchors.fill: parent; + hoverEnabled: true + onEntered: listView.currentIndex = index; + onClicked: popup.selectCurrentItem() + } + } + } + } + } + +} diff --git a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml index b45e10d755..31a1895e58 100644 --- a/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml +++ b/interface/resources/qml/hifi/dialogs/attachments/Attachment.qml @@ -2,6 +2,7 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import "../../../windows" +import "../../../controls" as VrControls import "." import ".." @@ -69,7 +70,7 @@ Item { text: "Joint:"; anchors.verticalCenter: jointChooser.verticalCenter; } - ComboBox { + VrControls.ComboBox { id: jointChooser; anchors { left: jointLabel.right; leftMargin: 8; right: parent.right } model: MyAvatar.jointNames From f53aaa1d64b3c92a39bfc24e885270232287f166 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 Jan 2016 15:54:03 -0800 Subject: [PATCH 094/145] Removing old attachment dialog, updating menu code --- .../qml/hifi/dialogs/AttachmentsDialog.qml | 1 + interface/src/Application.cpp | 3 +- interface/src/Menu.cpp | 13 +- interface/src/ui/AttachmentsDialog.cpp | 239 ------------------ interface/src/ui/AttachmentsDialog.h | 84 ------ interface/src/ui/DialogsManager.cpp | 10 - interface/src/ui/DialogsManager.h | 1 - 7 files changed, 10 insertions(+), 341 deletions(-) delete mode 100644 interface/src/ui/AttachmentsDialog.cpp delete mode 100644 interface/src/ui/AttachmentsDialog.h diff --git a/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml b/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml index 77771f65c4..1c70f06efd 100644 --- a/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml +++ b/interface/resources/qml/hifi/dialogs/AttachmentsDialog.qml @@ -8,6 +8,7 @@ import "attachments" Window { id: root title: "Edit Attachments" + objectName: "AttachmentsDialog" width: 600 height: 600 resizable: true diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b3142702bb..27f9d81ab2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1845,8 +1845,7 @@ void Application::keyPressEvent(QKeyEvent* event) { if (isShifted && isMeta) { auto offscreenUi = DependencyManager::get(); offscreenUi->getRootContext()->engine()->clearComponentCache(); - offscreenUi->load("hifi/dialogs/AttachmentsDialog.qml"); - // OffscreenUi::information("Debugging", "Component cache cleared"); + OffscreenUi::information("Debugging", "Component cache cleared"); // placeholder for dialogs being converted to QML. } break; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9cbb031a61..14c91dbda8 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -70,8 +70,8 @@ Menu::Menu() { } // File > Update -- FIXME: needs implementation - auto updateAction = addActionToQMenuAndActionHash(fileMenu, "Update"); - updateAction->setDisabled(true); + auto action = addActionToQMenuAndActionHash(fileMenu, "Update"); + action->setDisabled(true); // File > Help addActionToQMenuAndActionHash(fileMenu, MenuOption::Help, 0, qApp, SLOT(showHelp())); @@ -166,8 +166,11 @@ Menu::Menu() { QObject* avatar = avatarManager->getMyAvatar(); // Avatar > Attachments... - addActionToQMenuAndActionHash(avatarMenu, MenuOption::Attachments, 0, - dialogsManager.data(), SLOT(editAttachments())); + action = addActionToQMenuAndActionHash(avatarMenu, MenuOption::Attachments); + connect(action, &QAction::triggered, [] { + DependencyManager::get()->show(QString("hifi/dialogs/AttachmentsDialog.qml"), "AttachmentsDialog"); + }); + // Avatar > Size MenuWrapper* avatarSizeMenu = avatarMenu->addMenu("Size"); @@ -285,7 +288,7 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menus", 0, false, this, SLOT(toggleDeveloperMenus())); // Settings > General... - auto action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::Preferences, Qt::CTRL | Qt::Key_Comma, nullptr, nullptr, QAction::PreferencesRole); + action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::Preferences, Qt::CTRL | Qt::Key_Comma, nullptr, nullptr, QAction::PreferencesRole); connect(action, &QAction::triggered, [] { DependencyManager::get()->toggle(QString("hifi/dialogs/GeneralPreferencesDialog.qml"), "GeneralPreferencesDialog"); }); diff --git a/interface/src/ui/AttachmentsDialog.cpp b/interface/src/ui/AttachmentsDialog.cpp deleted file mode 100644 index d718b52d6d..0000000000 --- a/interface/src/ui/AttachmentsDialog.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// -// AttachmentsDialog.cpp -// interface/src/ui -// -// Created by Andrzej Kapolka on 5/4/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 -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "AttachmentsDialog.h" -#include "ModelsBrowser.h" - -AttachmentsDialog::AttachmentsDialog(QWidget* parent) : - QDialog(parent) { - - setWindowTitle("Edit Attachments"); - setAttribute(Qt::WA_DeleteOnClose); - - QVBoxLayout* layout = new QVBoxLayout(); - setLayout(layout); - - QScrollArea* area = new QScrollArea(); - layout->addWidget(area); - area->setWidgetResizable(true); - QWidget* container = new QWidget(); - container->setLayout(_attachments = new QVBoxLayout()); - container->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); - area->setWidget(container); - _attachments->addStretch(1); - - foreach (const AttachmentData& data, DependencyManager::get()->getMyAvatar()->getAttachmentData()) { - addAttachment(data); - } - - QPushButton* newAttachment = new QPushButton("New Attachment"); - connect(newAttachment, SIGNAL(clicked(bool)), SLOT(addAttachment())); - layout->addWidget(newAttachment); - - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok); - layout->addWidget(buttons); - connect(buttons, SIGNAL(accepted()), SLOT(deleteLater())); - _ok = buttons->button(QDialogButtonBox::Ok); - - setMinimumSize(600, 600); -} - -void AttachmentsDialog::setVisible(bool visible) { - QDialog::setVisible(visible); - - // un-default the OK button - if (visible) { - _ok->setDefault(false); - } -} - -void AttachmentsDialog::updateAttachmentData() { - QVector data; - for (int i = 0; i < _attachments->count() - 1; i++) { - data.append(static_cast(_attachments->itemAt(i)->widget())->getAttachmentData()); - } - DependencyManager::get()->getMyAvatar()->setAttachmentData(data); -} - -void AttachmentsDialog::addAttachment(const AttachmentData& data) { - _attachments->insertWidget(_attachments->count() - 1, new AttachmentPanel(this, data)); -} - -static QDoubleSpinBox* createTranslationBox(AttachmentPanel* panel, float value) { - QDoubleSpinBox* box = new QDoubleSpinBox(); - box->setSingleStep(0.01); - box->setMinimum(-FLT_MAX); - box->setMaximum(FLT_MAX); - box->setValue(value); - panel->connect(box, SIGNAL(valueChanged(double)), SLOT(updateAttachmentData())); - return box; -} - -static QDoubleSpinBox* createRotationBox(AttachmentPanel* panel, float value) { - QDoubleSpinBox* box = new QDoubleSpinBox(); - box->setMinimum(-180.0); - box->setMaximum(180.0); - box->setWrapping(true); - box->setValue(value); - panel->connect(box, SIGNAL(valueChanged(double)), SLOT(updateAttachmentData())); - return box; -} - -AttachmentPanel::AttachmentPanel(AttachmentsDialog* dialog, const AttachmentData& data) : - _dialog(dialog), - _applying(false) { - setFrameStyle(QFrame::StyledPanel); - - QFormLayout* layout = new QFormLayout(); - layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); - setLayout(layout); - - QHBoxLayout* urlBox = new QHBoxLayout(); - layout->addRow("Model URL:", urlBox); - urlBox->addWidget(_modelURL = new QLineEdit(data.modelURL.toString()), 1); - _modelURL->setText(data.modelURL.toString()); - connect(_modelURL, SIGNAL(editingFinished()), SLOT(modelURLChanged())); - QPushButton* chooseURL = new QPushButton("Choose"); - urlBox->addWidget(chooseURL); - connect(chooseURL, SIGNAL(clicked(bool)), SLOT(chooseModelURL())); - - layout->addRow("Joint:", _jointName = new QComboBox()); - QSharedPointer geometry = DependencyManager::get()->getMyAvatar()->getSkeletonModel().getGeometry(); - if (geometry && geometry->isLoaded()) { - foreach (const FBXJoint& joint, geometry->getFBXGeometry().joints) { - _jointName->addItem(joint.name); - } - } - _jointName->setCurrentText(data.jointName); - connect(_jointName, SIGNAL(currentIndexChanged(int)), SLOT(jointNameChanged())); - - QHBoxLayout* translationBox = new QHBoxLayout(); - translationBox->addWidget(_translationX = createTranslationBox(this, data.translation.x)); - translationBox->addWidget(_translationY = createTranslationBox(this, data.translation.y)); - translationBox->addWidget(_translationZ = createTranslationBox(this, data.translation.z)); - layout->addRow("Translation:", translationBox); - - QHBoxLayout* rotationBox = new QHBoxLayout(); - glm::vec3 eulers = glm::degrees(safeEulerAngles(data.rotation)); - rotationBox->addWidget(_rotationX = createRotationBox(this, eulers.x)); - rotationBox->addWidget(_rotationY = createRotationBox(this, eulers.y)); - rotationBox->addWidget(_rotationZ = createRotationBox(this, eulers.z)); - layout->addRow("Rotation:", rotationBox); - - layout->addRow("Scale:", _scale = new QDoubleSpinBox()); - _scale->setSingleStep(0.01); - _scale->setMaximum(FLT_MAX); - _scale->setValue(data.scale); - connect(_scale, SIGNAL(valueChanged(double)), SLOT(updateAttachmentData())); - - layout->addRow("Is Soft:", _isSoft = new QCheckBox()); - _isSoft->setChecked(data.isSoft); - connect(_isSoft, SIGNAL(stateChanged(int)), SLOT(updateAttachmentData())); - - QPushButton* remove = new QPushButton("Delete"); - layout->addRow(remove); - connect(remove, SIGNAL(clicked(bool)), SLOT(deleteLater())); - dialog->connect(remove, SIGNAL(clicked(bool)), SLOT(updateAttachmentData()), Qt::QueuedConnection); -} - -AttachmentData AttachmentPanel::getAttachmentData() const { - AttachmentData data; - data.modelURL = _modelURL->text(); - data.jointName = _jointName->currentText(); - data.translation = glm::vec3(_translationX->value(), _translationY->value(), _translationZ->value()); - data.rotation = glm::quat(glm::radians(glm::vec3(_rotationX->value(), _rotationY->value(), _rotationZ->value()))); - data.scale = _scale->value(); - data.isSoft = _isSoft->isChecked(); - return data; -} - -void AttachmentPanel::chooseModelURL() { - ModelsBrowser modelBrowser(FSTReader::ATTACHMENT_MODEL, this); - connect(&modelBrowser, SIGNAL(selected(QString)), SLOT(setModelURL(const QString&))); - modelBrowser.browse(); -} - -void AttachmentPanel::setModelURL(const QString& url) { - _modelURL->setText(url); - modelURLChanged(); -} - -void AttachmentPanel::modelURLChanged() { - // check for saved attachment data - if (_modelURL->text().isEmpty()) { - _dialog->updateAttachmentData(); - return; - } - AttachmentData attachment = DependencyManager::get()->getMyAvatar()->loadAttachmentData(_modelURL->text()); - if (attachment.isValid()) { - _applying = true; - _jointName->setCurrentText(attachment.jointName); - applyAttachmentData(attachment); - } - _dialog->updateAttachmentData(); -} - -void AttachmentPanel::jointNameChanged() { - if (_applying) { - return; - } - // check for saved attachment data specific to this joint - if (_modelURL->text().isEmpty()) { - _dialog->updateAttachmentData(); - return; - } - AttachmentData attachment = DependencyManager::get()->getMyAvatar()->loadAttachmentData( - _modelURL->text(), _jointName->currentText()); - if (attachment.isValid()) { - applyAttachmentData(attachment); - } - updateAttachmentData(); -} - -void AttachmentPanel::updateAttachmentData() { - if (_applying) { - return; - } - // save the attachment data under the model URL (if any) - if (!_modelURL->text().isEmpty()) { - DependencyManager::get()->getMyAvatar()->saveAttachmentData(getAttachmentData()); - } - _dialog->updateAttachmentData(); -} - -void AttachmentPanel::applyAttachmentData(const AttachmentData& attachment) { - _applying = true; - _translationX->setValue(attachment.translation.x); - _translationY->setValue(attachment.translation.y); - _translationZ->setValue(attachment.translation.z); - glm::vec3 eulers = glm::degrees(safeEulerAngles(attachment.rotation)); - _rotationX->setValue(eulers.x); - _rotationY->setValue(eulers.y); - _rotationZ->setValue(eulers.z); - _scale->setValue(attachment.scale); - _isSoft->setChecked(attachment.isSoft); - _applying = false; - _dialog->updateAttachmentData(); -} diff --git a/interface/src/ui/AttachmentsDialog.h b/interface/src/ui/AttachmentsDialog.h deleted file mode 100644 index 43ba5f8f3e..0000000000 --- a/interface/src/ui/AttachmentsDialog.h +++ /dev/null @@ -1,84 +0,0 @@ -// -// AttachmentsDialog.h -// interface/src/ui -// -// Created by Andrzej Kapolka on 5/4/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 -// - -#ifndef hifi_AttachmentsDialog_h -#define hifi_AttachmentsDialog_h - -#include -#include - -#include - -class QComboBox; -class QDoubleSpinner; -class QLineEdit; -class QVBoxLayout; - -/// Allows users to edit the avatar attachments. -class AttachmentsDialog : public QDialog { - Q_OBJECT - -public: - AttachmentsDialog(QWidget* parent = nullptr); - - virtual void setVisible(bool visible); - -public slots: - - void updateAttachmentData(); - -private slots: - - void addAttachment(const AttachmentData& data = AttachmentData()); - -private: - - QVBoxLayout* _attachments; - QPushButton* _ok; -}; - -/// A panel controlling a single attachment. -class AttachmentPanel : public QFrame { - Q_OBJECT - -public: - - AttachmentPanel(AttachmentsDialog* dialog, const AttachmentData& data = AttachmentData()); - - AttachmentData getAttachmentData() const; - -private slots: - - void chooseModelURL(); - void setModelURL(const QString& url); - void modelURLChanged(); - void jointNameChanged(); - void updateAttachmentData(); - -private: - - void applyAttachmentData(const AttachmentData& attachment); - - AttachmentsDialog* _dialog; - QLineEdit* _modelURL; - QComboBox* _jointName; - QDoubleSpinBox* _translationX; - QDoubleSpinBox* _translationY; - QDoubleSpinBox* _translationZ; - QDoubleSpinBox* _rotationX; - QDoubleSpinBox* _rotationY; - QDoubleSpinBox* _rotationZ; - QDoubleSpinBox* _scale; - QCheckBox* _isSoft; - bool _applying; -}; - -#endif // hifi_AttachmentsDialog_h diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index ef0ec5792f..41d7a0eb13 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -19,7 +19,6 @@ #include #include "AddressBarDialog.h" -#include "AttachmentsDialog.h" #include "BandwidthDialog.h" #include "CachesSizeDialog.h" #include "DiskCacheEditor.h" @@ -91,15 +90,6 @@ void DialogsManager::cachesSizeDialog() { _cachesSizeDialog->raise(); } -void DialogsManager::editAttachments() { - if (!_attachmentsDialog) { - maybeCreateDialog(_attachmentsDialog); - _attachmentsDialog->show(); - } else { - _attachmentsDialog->close(); - } -} - void DialogsManager::audioStatsDetails() { if (! _audioStatsDialog) { _audioStatsDialog = new AudioStatsDialog(qApp->getWindow()); diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 72a24e032c..b8fa22ec83 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -48,7 +48,6 @@ public slots: void showLoginDialog(); void octreeStatsDetails(); void cachesSizeDialog(); - void editAttachments(); void audioStatsDetails(); void bandwidthDetails(); void lodTools(); From a3b2dd2295b3709ae9461ce1eec5cd8eb23f2d7e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 27 Jan 2016 10:14:05 -0800 Subject: [PATCH 095/145] Add proper loop handling in injector --- libraries/audio/src/AudioInjector.cpp | 52 ++++++++++++++------------- libraries/audio/src/AudioInjector.h | 9 ++--- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index b203800703..fe6c1475b5 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -238,16 +238,19 @@ int64_t AudioInjector::injectNextFrame() { } } - int bytesToCopy = std::min((_options.stereo ? 2 : 1) * AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL, - _audioData.size() - _currentSendOffset); + int totalBytesLeftToCopy = (_options.stereo ? 2 : 1) * AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL; + if (!_options.loop) { + // If we aren't looping, let's make sure we don't read past the end + totalBytesLeftToCopy = std::min(totalBytesLeftToCopy, _audioData.size() - _currentSendOffset); + } // Measure the loudness of this frame _loudness = 0.0f; - for (int i = 0; i < bytesToCopy; i += sizeof(int16_t)) { - _loudness += abs(*reinterpret_cast(_audioData.data() + _currentSendOffset + i)) / + for (int i = 0; i < totalBytesLeftToCopy; i += sizeof(int16_t)) { + _loudness += abs(*reinterpret_cast(_audioData.data() + ((_currentSendOffset + i) % _audioData.size()))) / (AudioConstants::MAX_SAMPLE_VALUE / 2.0f); } - _loudness /= (float)(bytesToCopy / sizeof(int16_t)); + _loudness /= (float)(totalBytesLeftToCopy/ sizeof(int16_t)); _currentPacket->seek(0); @@ -264,8 +267,16 @@ int64_t AudioInjector::injectNextFrame() { _currentPacket->seek(audioDataOffset); - // copy the next NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL bytes to the packet - _currentPacket->write(_audioData.data() + _currentSendOffset, bytesToCopy); + while (totalBytesLeftToCopy > 0) { + int bytesToCopy = std::min(totalBytesLeftToCopy, _audioData.size() - _currentSendOffset); + + _currentPacket->write(_audioData.data() + _currentSendOffset, bytesToCopy); + _currentSendOffset += bytesToCopy; + totalBytesLeftToCopy -= bytesToCopy; + if (_currentSendOffset >= _audioData.size()) { + _currentSendOffset = 0; + } + } // set the correct size used for this packet _currentPacket->setPayloadSize(_currentPacket->pos()); @@ -280,21 +291,13 @@ int64_t AudioInjector::injectNextFrame() { _outgoingSequenceNumber++; } - _currentSendOffset += bytesToCopy; - - if (_currentSendOffset >= _audioData.size()) { - // we're at the end of the audio data to send - if (_options.loop) { - // we were asked to loop, set our send offset to 0 - _currentSendOffset = 0; - } else { - // we weren't to loop, say that we're done now - finish(); - return NEXT_FRAME_DELTA_ERROR_OR_FINISHED; - } + if (_currentSendOffset >= _audioData.size() && !_options.loop) { + finish(); + return NEXT_FRAME_DELTA_ERROR_OR_FINISHED; } - if (_currentSendOffset == bytesToCopy) { + if (!_hasSentFirstFrame) { + _hasSentFirstFrame = true; // ask AudioInjectorManager to call us right away again to // immediately send the first two frames so the mixer can start using the audio right away return NEXT_FRAME_DELTA_IMMEDIATELY; @@ -303,15 +306,14 @@ int64_t AudioInjector::injectNextFrame() { const int MAX_ALLOWED_FRAMES_TO_FALL_BEHIND = 7; int64_t currentTime = _frameTimer->nsecsElapsed() / 1000; auto currentFrameBasedOnElapsedTime = currentTime / AudioConstants::NETWORK_FRAME_USECS; - if (currentFrameBasedOnElapsedTime - _nextFrame > MAX_ALLOWED_FRAMES_TO_FALL_BEHIND) { // If we are falling behind by more frames than our threshold, let's skip the frames ahead - _nextFrame = currentFrameBasedOnElapsedTime - MAX_ALLOWED_FRAMES_TO_FALL_BEHIND; - } else { - ++_nextFrame; + qDebug() << "AudioInjector::injectNextFrame() skipping ahead, fell behind by " << (currentFrameBasedOnElapsedTime - _nextFrame) << " frames"; + _nextFrame = currentFrameBasedOnElapsedTime; + _currentSendOffset = _nextFrame * AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL * (_options.stereo ? 2 : 1) % _audioData.size(); } - int64_t playNextFrameAt = _nextFrame * AudioConstants::NETWORK_FRAME_USECS; + int64_t playNextFrameAt = ++_nextFrame * AudioConstants::NETWORK_FRAME_USECS; return std::max(INT64_C(0), playNextFrameAt - currentTime); } diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index 5155b87a74..acfbc2b04a 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -90,10 +90,11 @@ private: QByteArray _audioData; AudioInjectorOptions _options; State _state { State::NotFinished }; - bool _hasSetup = false; - bool _shouldStop = false; - float _loudness = 0.0f; - int _currentSendOffset = 0; + bool _hasSentFirstFrame { false }; + bool _hasSetup { false }; + bool _shouldStop { false }; + float _loudness { 0.0f }; + int _currentSendOffset { 0 }; std::unique_ptr _currentPacket { nullptr }; AbstractAudioInterface* _localAudioInterface { nullptr }; AudioInjectorLocalBuffer* _localBuffer { nullptr }; From 607f23618d93bdd21e5dfbfde39c9c6aac08a6cb Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 27 Jan 2016 10:36:44 -0800 Subject: [PATCH 096/145] Fix compiler warning for float->int conversion --- libraries/audio/src/AudioConstants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio/src/AudioConstants.h b/libraries/audio/src/AudioConstants.h index 91080017a5..6c12c6aa15 100644 --- a/libraries/audio/src/AudioConstants.h +++ b/libraries/audio/src/AudioConstants.h @@ -29,7 +29,7 @@ namespace AudioConstants { const int NETWORK_FRAME_SAMPLES_PER_CHANNEL = NETWORK_FRAME_BYTES_PER_CHANNEL / sizeof(AudioSample); const float NETWORK_FRAME_MSECS = (AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL / (float)AudioConstants::SAMPLE_RATE) * 1000.0f; - const int NETWORK_FRAME_USECS = floorf(NETWORK_FRAME_MSECS * 1000.0f); + const int NETWORK_FRAME_USECS = static_cast(NETWORK_FRAME_MSECS * 1000.0f); const int MIN_SAMPLE_VALUE = std::numeric_limits::min(); const int MAX_SAMPLE_VALUE = std::numeric_limits::max(); } From c771c925c8e0330e9cf8356a456ec6eed80203dc Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 27 Jan 2016 11:20:32 -0800 Subject: [PATCH 097/145] MyAvatar: copy body velocity + hmd follow velocity onto avatar This was inadvertently removed in a previous PR. https://github.com/highfidelity/hifi/pull/6895 Also, renamed Velocity stat to Speed. --- interface/resources/qml/Stats.qml | 2 +- interface/src/avatar/MyAvatar.cpp | 2 ++ interface/src/ui/Stats.cpp | 2 +- interface/src/ui/Stats.h | 4 ++-- libraries/physics/src/CharacterController.cpp | 8 ++++++++ libraries/physics/src/CharacterController.h | 1 + 6 files changed, 15 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 2155a11d91..35738c56b1 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -136,7 +136,7 @@ Item { Text { color: root.fontColor; font.pixelSize: root.fontSize - text: "Velocity: " + root.velocity.toFixed(1) + text: "Speed: " + root.speed.toFixed(1) } Text { color: root.fontColor; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e06dce2324..f0acd3f42a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1042,6 +1042,8 @@ void MyAvatar::harvestResultsFromPhysicsSimulation(float deltaTime) { nextAttitude(position, orientation); _bodySensorMatrix = _follow.postPhysicsUpdate(*this, _bodySensorMatrix); + setVelocity(_characterController.getLinearVelocity() + _characterController.getFollowVelocity()); + // now that physics has adjusted our position, we can update attachements. Avatar::simulateAttachments(deltaTime); } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index ae9e37b591..1ee26a865d 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -162,7 +162,7 @@ void Stats::updateStats(bool force) { MyAvatar* myAvatar = avatarManager->getMyAvatar(); glm::vec3 avatarPos = myAvatar->getPosition(); STAT_UPDATE(position, QVector3D(avatarPos.x, avatarPos.y, avatarPos.z)); - STAT_UPDATE_FLOAT(velocity, glm::length(myAvatar->getVelocity()), 0.1f); + STAT_UPDATE_FLOAT(speed, glm::length(myAvatar->getVelocity()), 0.1f); STAT_UPDATE_FLOAT(yaw, myAvatar->getBodyYaw(), 0.1f); if (_expanded || force) { SharedNodePointer avatarMixer = nodeList->soloNodeOfType(NodeType::AvatarMixer); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index fc01fe7f23..bebfbf6f70 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -47,7 +47,7 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, entitiesPing, 0) STATS_PROPERTY(int, assetPing, 0) STATS_PROPERTY(QVector3D, position, QVector3D(0, 0, 0) ) - STATS_PROPERTY(float, velocity, 0) + STATS_PROPERTY(float, speed, 0) STATS_PROPERTY(float, yaw, 0) STATS_PROPERTY(int, avatarMixerInKbps, 0) STATS_PROPERTY(int, avatarMixerInPps, 0) @@ -138,7 +138,7 @@ signals: void entitiesPingChanged(); void assetPingChanged(); void positionChanged(); - void velocityChanged(); + void speedChanged(); void yawChanged(); void avatarMixerInKbpsChanged(); void avatarMixerInPpsChanged(); diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 65432e2f65..a30feec150 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -390,6 +390,14 @@ glm::quat CharacterController::getFollowAngularDisplacement() const { return bulletToGLM(_followAngularDisplacement); } +glm::vec3 CharacterController::getFollowVelocity() const { + if (_followTime > 0.0f) { + return bulletToGLM(_followLinearDisplacement) / _followTime; + } else { + return glm::vec3(); + } +} + glm::vec3 CharacterController::getLinearVelocity() const { glm::vec3 velocity(0.0f); if (_rigidBody) { diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index 224632ea6b..c1c64a1a02 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -71,6 +71,7 @@ public: float getFollowTime() const { return _followTime; } glm::vec3 getFollowLinearDisplacement() const; glm::quat getFollowAngularDisplacement() const; + glm::vec3 getFollowVelocity() const; glm::vec3 getLinearVelocity() const; From 4de8e7a3c861fc21e15b903a5b732656d11be64a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 27 Jan 2016 13:47:09 -0800 Subject: [PATCH 098/145] Add audio resizing in injector --- libraries/audio/src/AudioInjector.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 661509c3d2..d863051b81 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -181,6 +181,15 @@ int64_t AudioInjector::injectNextFrame() { // make sure we actually have samples downloaded to inject if (_audioData.size()) { + auto sampleSize = (_options.stereo ? 2 : 1) * sizeof(AudioConstants::AudioSample); + auto numSamples = static_cast(_audioData.size() / sampleSize); + auto targetSize = numSamples * sampleSize; + if (targetSize != _audioData.size()) { + qDebug() << "Resizing audio that doesn't end at multiple of sample size, resizing from " + << _audioData.size() << " to " << targetSize; + _audioData.resize(targetSize); + } + _outgoingSequenceNumber = 0; _nextFrame = 0; From 7e5eec55da1db5ca64daa7c152e195a231f9b6d9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 27 Jan 2016 13:47:32 -0800 Subject: [PATCH 099/145] Fix non-looped injected audio possibly looping --- libraries/audio/src/AudioInjector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index d863051b81..ab0aa9d5c7 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -281,7 +281,7 @@ int64_t AudioInjector::injectNextFrame() { _currentPacket->write(_audioData.data() + _currentSendOffset, bytesToCopy); _currentSendOffset += bytesToCopy; totalBytesLeftToCopy -= bytesToCopy; - if (_currentSendOffset >= _audioData.size()) { + if (_options.loop && _currentSendOffset >= _audioData.size()) { _currentSendOffset = 0; } } From f2ea73d646808084f98060c6770319b75e0a4795 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 27 Jan 2016 14:12:03 -0800 Subject: [PATCH 100/145] don't adjust a time of '0 usecs since epoch' with clock skew in edit packets --- libraries/entities/src/EntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 24314e807d..b02fb9a054 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -763,7 +763,7 @@ void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, int clockSkew) // lastEdited quint64 lastEditedInLocalTime; memcpy(&lastEditedInLocalTime, dataAt, sizeof(lastEditedInLocalTime)); - quint64 lastEditedInServerTime = lastEditedInLocalTime + clockSkew; + quint64 lastEditedInServerTime = lastEditedInLocalTime > 0 ? lastEditedInLocalTime + clockSkew : 0; memcpy(dataAt, &lastEditedInServerTime, sizeof(lastEditedInServerTime)); #ifdef WANT_DEBUG qCDebug(entities, "EntityItem::adjustEditPacketForClockSkew()..."); From 2ec201b85e4a6de5b985b9e689d669ba18b918ec Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 27 Jan 2016 14:13:23 -0800 Subject: [PATCH 101/145] Fix conversion warning --- libraries/audio/src/AudioInjector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index ab0aa9d5c7..217b8b0d53 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -181,7 +181,7 @@ int64_t AudioInjector::injectNextFrame() { // make sure we actually have samples downloaded to inject if (_audioData.size()) { - auto sampleSize = (_options.stereo ? 2 : 1) * sizeof(AudioConstants::AudioSample); + int sampleSize = (_options.stereo ? 2 : 1) * sizeof(AudioConstants::AudioSample); auto numSamples = static_cast(_audioData.size() / sampleSize); auto targetSize = numSamples * sampleSize; if (targetSize != _audioData.size()) { From dc716461e3be559f23d2a6b253f407eda6d7bd49 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 27 Jan 2016 14:31:47 -0800 Subject: [PATCH 102/145] fix for a couple of resampling edge cases --- libraries/audio/src/Sound.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index 12f63e0a12..bbd6af5465 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -98,11 +98,23 @@ void Sound::downSample(const QByteArray& rawAudioByteArray) { int numSourceSamples = rawAudioByteArray.size() / sizeof(AudioConstants::AudioSample); - int numDestinationBytes = rawAudioByteArray.size() / sizeof(AudioConstants::AudioSample); - if (_isStereo && numSourceSamples % 2 != 0) { - numDestinationBytes += sizeof(AudioConstants::AudioSample); + if (_isStereo && numSourceSamples % 2 != 0){ + // in the unlikely case that we have stereo audio but we seem to be missing a sample + // (the sample for one channel is missing in a set of interleaved samples) + // then drop the odd sample + --numSourceSamples; } + int numDestinationSamples = numSourceSamples / 2.0f; + + if (_isStereo && numDestinationSamples % 2 != 0) { + // if this is stereo we need to make sure we produce stereo output + // which means we should have an even number of output samples + numDestinationSamples += 1; + } + + int numDestinationBytes = numDestinationSamples * sizeof(AudioConstants::AudioSample); + _byteArray.resize(numDestinationBytes); int16_t* sourceSamples = (int16_t*) rawAudioByteArray.data(); From 00715f1906d95d4a56450bb12b3c20c7c6316522 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 27 Jan 2016 10:14:37 -0800 Subject: [PATCH 103/145] apply "hips offset" to root of state graph (Somemtimes the hips are not the root. I'm looking at YOU blender!) --- libraries/animation/src/AnimInverseKinematics.cpp | 13 +++++++++++-- libraries/animation/src/AnimInverseKinematics.h | 9 +++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index e47a12960e..d7c604fff1 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -376,13 +376,13 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars ++constraintItr; } } else { - // shift the hips according to the offset from the previous frame + // shift the everything according to the _hipsOffset from the previous frame float offsetLength = glm::length(_hipsOffset); const float MIN_HIPS_OFFSET_LENGTH = 0.03f; if (offsetLength > MIN_HIPS_OFFSET_LENGTH) { // but only if offset is long enough float scaleFactor = ((offsetLength - MIN_HIPS_OFFSET_LENGTH) / offsetLength); - _relativePoses[_hipsIndex].trans = underPoses[_hipsIndex].trans + scaleFactor * _hipsOffset; + _relativePoses[_rootIndex].trans = underPoses[_rootIndex].trans + scaleFactor * _hipsOffset; } solveWithCyclicCoordinateDescent(targets); @@ -775,9 +775,18 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele initConstraints(); _headIndex = _skeleton->nameToJointIndex("Head"); _hipsIndex = _skeleton->nameToJointIndex("Hips"); + + // walk up the hierarchy until we find the root and cache its index + _rootIndex = _hipsIndex; + int parentIndex = _skeleton->getParentIndex(_hipsIndex); + while (parentIndex != -1) { + _rootIndex = parentIndex; + parentIndex = _skeleton->getParentIndex(_rootIndex); + } } else { clearConstraints(); _headIndex = -1; _hipsIndex = -1; + _rootIndex = -1; } } diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index 971d2d5ff1..52dd4b5863 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -79,13 +79,14 @@ protected: AnimPoseVec _relativePoses; // current relative poses // experimental data for moving hips during IK - int _headIndex = -1; - int _hipsIndex = -1; - glm::vec3 _hipsOffset = Vectors::ZERO; + glm::vec3 _hipsOffset { Vectors::ZERO }; + int _headIndex { -1 }; + int _hipsIndex { -1 }; + int _rootIndex { -1 }; // _maxTargetIndex is tracked to help optimize the recalculation of absolute poses // during the the cyclic coordinate descent algorithm - int _maxTargetIndex = 0; + int _maxTargetIndex { 0 }; }; #endif // hifi_AnimInverseKinematics_h From f67a20ee68522aec79fc306c5a066180855e2e3e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 27 Jan 2016 14:22:50 -0800 Subject: [PATCH 104/145] apply _hipsOffset in hips local-frame --- .../animation/src/AnimInverseKinematics.cpp | 26 ++++++++++++------- .../animation/src/AnimInverseKinematics.h | 2 +- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index d7c604fff1..897b5b3858 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -382,7 +382,20 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars if (offsetLength > MIN_HIPS_OFFSET_LENGTH) { // but only if offset is long enough float scaleFactor = ((offsetLength - MIN_HIPS_OFFSET_LENGTH) / offsetLength); - _relativePoses[_rootIndex].trans = underPoses[_rootIndex].trans + scaleFactor * _hipsOffset; + if (_hipsParentIndex == -1) { + // the hips are the root so _hipsOffset is in the correct frame + _relativePoses[_hipsIndex].trans = underPoses[_hipsIndex].trans + scaleFactor * _hipsOffset; + } else { + // the hips are NOT the root so we need to transform _hipsOffset into hips local-frame + glm::quat hipsFrameRotation = _relativePoses[_hipsParentIndex].rot; + int index = _skeleton->getParentIndex(_hipsParentIndex); + while (index != -1) { + hipsFrameRotation *= _relativePoses[index].rot; + index = _skeleton->getParentIndex(index); + } + _relativePoses[_hipsIndex].trans = underPoses[_hipsIndex].trans + + glm::inverse(glm::normalize(hipsFrameRotation)) * (scaleFactor * _hipsOffset); + } } solveWithCyclicCoordinateDescent(targets); @@ -776,17 +789,12 @@ void AnimInverseKinematics::setSkeletonInternal(AnimSkeleton::ConstPointer skele _headIndex = _skeleton->nameToJointIndex("Head"); _hipsIndex = _skeleton->nameToJointIndex("Hips"); - // walk up the hierarchy until we find the root and cache its index - _rootIndex = _hipsIndex; - int parentIndex = _skeleton->getParentIndex(_hipsIndex); - while (parentIndex != -1) { - _rootIndex = parentIndex; - parentIndex = _skeleton->getParentIndex(_rootIndex); - } + // also cache the _hipsParentIndex for later + _hipsParentIndex = _skeleton->getParentIndex(_hipsIndex); } else { clearConstraints(); _headIndex = -1; _hipsIndex = -1; - _rootIndex = -1; + _hipsParentIndex = -1; } } diff --git a/libraries/animation/src/AnimInverseKinematics.h b/libraries/animation/src/AnimInverseKinematics.h index 52dd4b5863..825577b1ae 100644 --- a/libraries/animation/src/AnimInverseKinematics.h +++ b/libraries/animation/src/AnimInverseKinematics.h @@ -82,7 +82,7 @@ protected: glm::vec3 _hipsOffset { Vectors::ZERO }; int _headIndex { -1 }; int _hipsIndex { -1 }; - int _rootIndex { -1 }; + int _hipsParentIndex { -1 }; // _maxTargetIndex is tracked to help optimize the recalculation of absolute poses // during the the cyclic coordinate descent algorithm From 1b45f5cc0c21f6997bd3e87aa86e67c4ef38908e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 27 Jan 2016 14:44:02 -0800 Subject: [PATCH 105/145] tweaks to neck and spine constraints --- libraries/animation/src/AnimInverseKinematics.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 897b5b3858..f9c8873779 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -246,7 +246,7 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vectorsetReferenceRotation(_defaultRelativePoses[i].rot); - const float MAX_SPINE_TWIST = PI / 8.0f; + const float MAX_SPINE_TWIST = PI / 12.0f; stConstraint->setTwistLimits(-MAX_SPINE_TWIST, MAX_SPINE_TWIST); std::vector minDots; @@ -658,11 +658,11 @@ void AnimInverseKinematics::initConstraints() { } else if (0 == baseName.compare("Neck", Qt::CaseInsensitive)) { SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); - const float MAX_NECK_TWIST = PI / 6.0f; + const float MAX_NECK_TWIST = PI / 9.0f; stConstraint->setTwistLimits(-MAX_NECK_TWIST, MAX_NECK_TWIST); std::vector minDots; - const float MAX_NECK_SWING = PI / 4.0f; + const float MAX_NECK_SWING = PI / 8.0f; minDots.push_back(cosf(MAX_NECK_SWING)); stConstraint->setSwingLimits(minDots); @@ -670,11 +670,11 @@ void AnimInverseKinematics::initConstraints() { } else if (0 == baseName.compare("Head", Qt::CaseInsensitive)) { SwingTwistConstraint* stConstraint = new SwingTwistConstraint(); stConstraint->setReferenceRotation(_defaultRelativePoses[i].rot); - const float MAX_HEAD_TWIST = PI / 8.0f; + const float MAX_HEAD_TWIST = PI / 9.0f; stConstraint->setTwistLimits(-MAX_HEAD_TWIST, MAX_HEAD_TWIST); std::vector minDots; - const float MAX_HEAD_SWING = PI / 6.0f; + const float MAX_HEAD_SWING = PI / 10.0f; minDots.push_back(cosf(MAX_HEAD_SWING)); stConstraint->setSwingLimits(minDots); From cd5e81de36d9fd43c4f687e25a1f775ead206022 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Wed, 27 Jan 2016 16:02:02 -0800 Subject: [PATCH 106/145] Validating href for edit.js --- examples/html/entityProperties.html | 2 +- libraries/entities/src/EntityItem.cpp | 8 ++++++++ libraries/entities/src/EntityItem.h | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 898f2bea6d..47790f8e0b 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -982,7 +982,7 @@
-
Href
+
Href - Hifi://address
diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 24314e807d..c67dc7212f 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -812,6 +812,14 @@ void EntityItem::setMass(float mass) { } } +void EntityItem::setHref(QString value) { + auto href = value.toLower(); + if (! (value.toLower().startsWith("hifi://")) ) { + return; + } + _href = value; +} + void EntityItem::simulate(const quint64& now) { if (_lastSimulated == 0) { _lastSimulated = now; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 67af53615d..c8bf62f83e 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -172,7 +172,7 @@ public: // Hyperlink related getters and setters QString getHref() const { return _href; } - void setHref(QString value) { _href = value; } + void setHref(QString value); QString getDescription() const { return _description; } void setDescription(QString value) { _description = value; } From 0a386cdde845cd3af3e2f6d925f48dd94f19c8aa Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 27 Jan 2016 16:09:42 -0800 Subject: [PATCH 107/145] remove trimFrames call from Sound --- libraries/audio/src/AudioEditBuffer.h | 112 -------------------------- libraries/audio/src/Sound.cpp | 23 ------ libraries/audio/src/Sound.h | 1 - 3 files changed, 136 deletions(-) delete mode 100644 libraries/audio/src/AudioEditBuffer.h diff --git a/libraries/audio/src/AudioEditBuffer.h b/libraries/audio/src/AudioEditBuffer.h deleted file mode 100644 index 66639f20bb..0000000000 --- a/libraries/audio/src/AudioEditBuffer.h +++ /dev/null @@ -1,112 +0,0 @@ -// -// AudioEditBuffer.h -// hifi -// -// Created by Craig Hansen-Sturm on 8/29/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 -// - -#ifndef hifi_AudioEditBuffer_h -#define hifi_AudioEditBuffer_h - -template< typename T > -class AudioEditBuffer : public AudioFrameBuffer { - -public: - - AudioEditBuffer(); - AudioEditBuffer(const uint32_t channelCount, const uint32_t frameCount); - ~AudioEditBuffer(); - - bool getZeroCrossing(uint32_t start, bool direction, float32_t epsilon, uint32_t& zero); - - void linearFade(uint32_t start, uint32_t stop, bool increasing); - void exponentialFade(uint32_t start, uint32_t stop, bool increasing); -}; - -template< typename T > -AudioEditBuffer::AudioEditBuffer() : - AudioFrameBuffer() { -} - -template< typename T > -AudioEditBuffer::AudioEditBuffer(const uint32_t channelCount, const uint32_t frameCount) : - AudioFrameBuffer(channelCount, frameCount) { -} - -template< typename T > - AudioEditBuffer::~AudioEditBuffer() { -} - -template< typename T > -inline bool AudioEditBuffer::getZeroCrossing(uint32_t start, bool direction, float32_t epsilon, uint32_t& zero) { - - zero = this->_frameCount; - - if (direction) { // scan from the left - if (start < this->_frameCount) { - for (uint32_t i = start; i < this->_frameCount; ++i) { - for (uint32_t j = 0; j < this->_channelCount; ++j) { - if (this->_frameBuffer[j][i] >= -epsilon && this->_frameBuffer[j][i] <= epsilon) { - zero = i; - return true; - } - } - } - } - } else { // scan from the right - if (start != 0 && start < this->_frameCount) { - for (uint32_t i = start; i != 0; --i) { - for (uint32_t j = 0; j < this->_channelCount; ++j) { - if (this->_frameBuffer[j][i] >= -epsilon && this->_frameBuffer[j][i] <= epsilon) { - zero = i; - return true; - } - } - } - } - } - - return false; -} - -template< typename T > -inline void AudioEditBuffer::linearFade(uint32_t start, uint32_t stop, bool increasing) { - - if (start >= stop || start > this->_frameCount || stop > this->_frameCount ) { - return; - } - - uint32_t count = stop - start; - float32_t delta; - float32_t gain; - - if (increasing) { // 0.0 to 1.0f in delta increments - delta = 1.0f / (float32_t)count; - gain = 0.0f; - } else { // 1.0f to 0.0f in delta increments - delta = -1.0f / (float32_t)count; - gain = 1.0f; - } - - for (uint32_t i = start; i < stop; ++i) { - for (uint32_t j = 0; j < this->_channelCount; ++j) { - this->_frameBuffer[j][i] *= gain; - } - gain += delta; - } -} - -template< typename T > -inline void AudioEditBuffer::exponentialFade(uint32_t start, uint32_t stop, bool increasing) { - // TBD -} - -typedef AudioEditBuffer< float32_t > AudioEditBufferFloat32; -typedef AudioEditBuffer< int32_t > AudioEditBufferSInt32; - -#endif // hifi_AudioEditBuffer_h - diff --git a/libraries/audio/src/Sound.cpp b/libraries/audio/src/Sound.cpp index bbd6af5465..ff80ba08a9 100644 --- a/libraries/audio/src/Sound.cpp +++ b/libraries/audio/src/Sound.cpp @@ -26,7 +26,6 @@ #include "AudioRingBuffer.h" #include "AudioFormat.h" #include "AudioBuffer.h" -#include "AudioEditBuffer.h" #include "AudioLogging.h" #include "Sound.h" @@ -69,7 +68,6 @@ void Sound::downloadFinished(const QByteArray& data) { interpretAsWav(rawAudioByteArray, outputAudioByteArray); downSample(outputAudioByteArray); - trimFrames(); } else if (fileName.endsWith(RAW_EXTENSION)) { // check if this was a stereo raw file // since it's raw the only way for us to know that is if the file was called .stereo.raw @@ -80,7 +78,6 @@ void Sound::downloadFinished(const QByteArray& data) { // Process as RAW file downSample(rawAudioByteArray); - trimFrames(); } else { qCDebug(audio) << "Unknown sound file type"; } @@ -141,26 +138,6 @@ void Sound::downSample(const QByteArray& rawAudioByteArray) { } } -void Sound::trimFrames() { - - const uint32_t inputFrameCount = _byteArray.size() / sizeof(int16_t); - const uint32_t trimCount = 1024; // number of leading and trailing frames to trim - - if (inputFrameCount <= (2 * trimCount)) { - return; - } - - int16_t* inputFrameData = (int16_t*)_byteArray.data(); - - AudioEditBufferFloat32 editBuffer(1, inputFrameCount); - editBuffer.copyFrames(1, inputFrameCount, inputFrameData, false /*copy in*/); - - editBuffer.linearFade(0, trimCount, true); - editBuffer.linearFade(inputFrameCount - trimCount, inputFrameCount, false); - - editBuffer.copyFrames(1, inputFrameCount, inputFrameData, true /*copy out*/); -} - // // Format description from https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ // diff --git a/libraries/audio/src/Sound.h b/libraries/audio/src/Sound.h index 91dbef8c6a..6baf691957 100644 --- a/libraries/audio/src/Sound.h +++ b/libraries/audio/src/Sound.h @@ -38,7 +38,6 @@ private: bool _isStereo; bool _isReady; - void trimFrames(); void downSample(const QByteArray& rawAudioByteArray); void interpretAsWav(const QByteArray& inputAudioByteArray, QByteArray& outputAudioByteArray); From 4e4627d03951fef18c802c56f84f961fde0f348d Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 26 Jan 2016 15:54:26 -0800 Subject: [PATCH 108/145] avatar-animation.json: Updated standard animations --- .../defaultAvatar_full/avatar-animation.json | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json index d510e7b966..637ed68455 100644 --- a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json +++ b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json @@ -420,7 +420,7 @@ "id": "idleStand", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle.fbx", "startFrame": 0.0, "endFrame": 90.0, "timeScale": 1.0, @@ -432,7 +432,7 @@ "id": "idleTalk", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/talk/talk.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/talk.fbx", "startFrame": 0.0, "endFrame": 801.0, "timeScale": 1.0, @@ -457,7 +457,7 @@ "id": "walkFwdShort", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_short_fwd.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_short_fwd.fbx", "startFrame": 0.0, "endFrame": 39.0, "timeScale": 1.0, @@ -469,7 +469,7 @@ "id": "walkFwdNormal", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_fwd.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_fwd.fbx", "startFrame": 0.0, "endFrame": 35.0, "timeScale": 1.0, @@ -481,7 +481,7 @@ "id": "walkFwdRun", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/run_fwd.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/run_fwd.fbx", "startFrame": 0.0, "endFrame": 21.0, "timeScale": 1.0, @@ -495,7 +495,7 @@ "id": "idleToWalkFwd", "type": "clip", "data": { - "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims/idle_to_walk.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle_to_walk.fbx", "startFrame": 1.0, "endFrame": 19.0, "timeScale": 1.0, @@ -518,7 +518,7 @@ "id": "walkBwdShort", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_short_bwd.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_short_bwd.fbx", "startFrame": 0.0, "endFrame": 38.0, "timeScale": 1.0, @@ -530,7 +530,7 @@ "id": "walkBwdNormal", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_bwd.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_bwd.fbx", "startFrame": 0.0, "endFrame": 36.0, "timeScale": 1.0, @@ -544,7 +544,7 @@ "id": "turnLeft", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_left.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/turn_left.fbx", "startFrame": 0.0, "endFrame": 28.0, "timeScale": 1.0, @@ -556,7 +556,7 @@ "id": "turnRight", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_right.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/turn_right.fbx", "startFrame": 0.0, "endFrame": 30.0, "timeScale": 1.0, @@ -579,7 +579,7 @@ "id": "strafeLeftShort", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_short_left.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_short_left.fbx", "startFrame": 0.0, "endFrame": 28.0, "timeScale": 1.0, @@ -591,7 +591,7 @@ "id": "strafeLeftNormal", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_left.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_left.fbx", "startFrame": 0.0, "endFrame": 30.0, "timeScale": 1.0, @@ -616,7 +616,7 @@ "id": "strafeRightShort", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_short_right.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_short_right.fbx", "startFrame": 0.0, "endFrame": 28.0, "timeScale": 1.0, @@ -628,7 +628,7 @@ "id": "strafeRightNormal", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_right.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_right.fbx", "startFrame": 0.0, "endFrame": 30.0, "timeScale": 1.0, @@ -642,7 +642,7 @@ "id": "awayIntro", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/kneel.fbx", "startFrame": 0.0, "endFrame": 83.0, "timeScale": 1.0, @@ -654,7 +654,7 @@ "id": "away", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/kneel.fbx", "startFrame": 83.0, "endFrame": 84.0, "timeScale": 1.0, @@ -666,7 +666,7 @@ "id": "awayOutro", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/kneel.fbx", "startFrame": 84.0, "endFrame": 167.0, "timeScale": 1.0, @@ -678,7 +678,7 @@ "id": "fly", "type": "clip", "data": { - "url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims/fly.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/fly.fbx", "startFrame": 1.0, "endFrame": 80.0, "timeScale": 1.0, @@ -700,7 +700,7 @@ "id": "userAnimA", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle.fbx", "startFrame": 0.0, "endFrame": 90.0, "timeScale": 1.0, @@ -712,7 +712,7 @@ "id": "userAnimB", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx", + "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle.fbx", "startFrame": 0.0, "endFrame": 90.0, "timeScale": 1.0, From af3d842e6096c3ecd9da8ea2964b5882852cb79e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 28 Jan 2016 15:22:42 +1300 Subject: [PATCH 109/145] Warn user if OpenGL version is too low (< 4.1) --- interface/src/OpenGLInfo.cpp | 60 ++++++++++++++++++++++++++++++++++++ interface/src/OpenGLInfo.h | 25 +++++++++++++++ interface/src/main.cpp | 13 ++++++++ 3 files changed, 98 insertions(+) create mode 100644 interface/src/OpenGLInfo.cpp create mode 100644 interface/src/OpenGLInfo.h diff --git a/interface/src/OpenGLInfo.cpp b/interface/src/OpenGLInfo.cpp new file mode 100644 index 0000000000..b61863c1bf --- /dev/null +++ b/interface/src/OpenGLInfo.cpp @@ -0,0 +1,60 @@ +// +// OpenGLInfo.cpp +// interface/src +// +// Created by David Rowe on 28 Jan 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 +// + +#include "OpenGLInfo.h" + +#include +#include + +#include "GLCanvas.h" + +OpenGLInfo::OpenGLInfo(int& argc, char** argv) : + QApplication(argc, argv) +{ +} + +bool OpenGLInfo::isValidVersion() { + bool valid = true; + + // Retrieve OpenGL version + GLCanvas* glCanvas = new GLCanvas(); + glCanvas->initializeGL(); + QString glVersion = QString((const char*)glGetString(GL_VERSION)); + delete glCanvas; + + // Compare against minimum + // The GL_VERSION string begins with a version number in one of these forms: + // - major_number.minor_number + // - major_number.minor_number.release_number + // Reference: https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glGetString.xml + const int MINIMUM_OPENGL_MAJOR_VERSION = 4; + const int MINIMUM_OPENGL_MINOR_VERSION = 1; + QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]")); + int majorNumber = versionParts[0].toInt(); + int minorNumber = versionParts[1].toInt(); + valid = (majorNumber > MINIMUM_OPENGL_MAJOR_VERSION + || (majorNumber == MINIMUM_OPENGL_MAJOR_VERSION && minorNumber >= MINIMUM_OPENGL_MINOR_VERSION)); + + // Prompt user if below minimum + if (!valid) { + QMessageBox messageBox; + messageBox.setWindowTitle("OpenGL Version Too Low"); + messageBox.setIcon(QMessageBox::Warning); + messageBox.setText(QString().sprintf("Your OpenGL version of %i.%i is lower than the minimum of %i.%i.", + majorNumber, minorNumber, MINIMUM_OPENGL_MAJOR_VERSION, MINIMUM_OPENGL_MINOR_VERSION)); + messageBox.setInformativeText("Press OK to exit; Ignore to continue."); + messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Ignore); + messageBox.setDefaultButton(QMessageBox::Ok); + valid = messageBox.exec() == QMessageBox::Ignore; + } + + return valid; +} diff --git a/interface/src/OpenGLInfo.h b/interface/src/OpenGLInfo.h new file mode 100644 index 0000000000..8df44c72b1 --- /dev/null +++ b/interface/src/OpenGLInfo.h @@ -0,0 +1,25 @@ +// +// OpenGLInfo.h +// interface/src +// +// Created by David Rowe on 28 Jan 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_OpenGLInfo_h +#define hifi_OpenGLInfo_h + +#include + +class OpenGLInfo : public QApplication { + +public: + OpenGLInfo(int& argc, char** argv); + + static bool isValidVersion(); +}; + +#endif // hifi_OpenGLInfo_h diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 15da88023b..db02994a19 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -22,6 +22,7 @@ #include "AddressManager.h" #include "Application.h" #include "InterfaceLogging.h" +#include "OpenGLInfo.h" #include "MainWindow.h" int main(int argc, const char* argv[]) { @@ -83,6 +84,17 @@ int main(int argc, const char* argv[]) { #endif } + // Check OpenGL version. + // This is done separately from the main Application so that start-up and shut-down logic within the main Application is + // not made more complicated than it already is. + { + OpenGLInfo openGLInfo(argc, const_cast(argv)); + if (!openGLInfo.isValidVersion()) { + qCDebug(interfaceapp, "Early exit due to OpenGL version."); + return 0; + } + } + QElapsedTimer startupTime; startupTime.start(); @@ -96,6 +108,7 @@ int main(int argc, const char* argv[]) { usecTimestampNowForceClockSkew(clockSkew); qCDebug(interfaceapp, "clockSkewOption=%s clockSkew=%d", clockSkewOption, clockSkew); } + // Oculus initialization MUST PRECEDE OpenGL context creation. // The nature of the Application constructor means this has to be either here, // or in the main window ctor, before GL startup. From d9651c6d4b5c824c243cf092475da1550a7851d9 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 Jan 2016 23:04:59 -0800 Subject: [PATCH 110/145] Allow user browser to work with marketplace --- interface/resources/qml/Browser.qml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml index 32515d82b7..382acc237c 100644 --- a/interface/resources/qml/Browser.qml +++ b/interface/resources/qml/Browser.qml @@ -108,7 +108,7 @@ Window { } } - WebEngineView { + WebView { id: webview url: "http://highfidelity.com" anchors.top: buttons.bottom @@ -124,6 +124,12 @@ Window { onIconChanged: { console.log("New icon: " + icon) } + + profile: WebEngineProfile { + id: webviewProfile + storageName: "qmlUserBrowser" + } + } } // item From 18d6a09dc9c3cf20ed5f15390bc336ed9aafc1be Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 Jan 2016 23:16:22 -0800 Subject: [PATCH 111/145] Better preferences dialog initial state --- interface/resources/qml/dialogs/PreferencesDialog.qml | 7 +++++++ interface/resources/qml/dialogs/preferences/Section.qml | 4 ++++ tests/ui/qmlscratch.pro | 1 + 3 files changed, 12 insertions(+) diff --git a/interface/resources/qml/dialogs/PreferencesDialog.qml b/interface/resources/qml/dialogs/PreferencesDialog.qml index bb3ce43fcd..8eee78719b 100644 --- a/interface/resources/qml/dialogs/PreferencesDialog.qml +++ b/interface/resources/qml/dialogs/PreferencesDialog.qml @@ -62,6 +62,13 @@ Window { sections.push(sectionBuilder.createObject(prefControls, { name: category })); } + + if (sections.length) { + sections[0].expanded = true; + if (sections.length === 1) { + sections[0].expandable = false + } + } } Flickable { diff --git a/interface/resources/qml/dialogs/preferences/Section.qml b/interface/resources/qml/dialogs/preferences/Section.qml index 4b2c92f867..2cf232864d 100644 --- a/interface/resources/qml/dialogs/preferences/Section.qml +++ b/interface/resources/qml/dialogs/preferences/Section.qml @@ -7,6 +7,7 @@ import "." Preference { id: root + property bool expandable: true property bool expanded: false property string name: "Header" property real spacing: 8 @@ -42,7 +43,10 @@ Preference { VrControls.FontAwesome { id: toggle + width: root.expandable ? height : 0 anchors { left: parent.left; top: parent.top; margins: root.spacing } + visible: root.expandable + enabled: root.expandable rotation: root.expanded ? 0 : -90 text: "\uf078" Behavior on rotation { PropertyAnimation {} } diff --git a/tests/ui/qmlscratch.pro b/tests/ui/qmlscratch.pro index 7a1b5ab652..a4e4b33957 100644 --- a/tests/ui/qmlscratch.pro +++ b/tests/ui/qmlscratch.pro @@ -20,6 +20,7 @@ DISTFILES += \ ../../interface/resources/qml/controls/*.qml \ ../../interface/resources/qml/dialogs/*.qml \ ../../interface/resources/qml/dialogs/fileDialog/*.qml \ + ../../interface/resources/qml/dialogs/preferences/*.qml \ ../../interface/resources/qml/desktop/*.qml \ ../../interface/resources/qml/menus/*.qml \ ../../interface/resources/qml/styles/*.qml \ From 04e6a5360a03d3ede5dbd39d32bae109839a315a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 10:29:21 -0800 Subject: [PATCH 112/145] Renaming preference dialog variable --- interface/resources/qml/dialogs/PreferencesDialog.qml | 2 +- interface/resources/qml/dialogs/preferences/Section.qml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/dialogs/PreferencesDialog.qml b/interface/resources/qml/dialogs/PreferencesDialog.qml index 8eee78719b..3b594153dc 100644 --- a/interface/resources/qml/dialogs/PreferencesDialog.qml +++ b/interface/resources/qml/dialogs/PreferencesDialog.qml @@ -66,7 +66,7 @@ Window { if (sections.length) { sections[0].expanded = true; if (sections.length === 1) { - sections[0].expandable = false + sections[0].collapsable = false } } } diff --git a/interface/resources/qml/dialogs/preferences/Section.qml b/interface/resources/qml/dialogs/preferences/Section.qml index 2cf232864d..b1e59430a9 100644 --- a/interface/resources/qml/dialogs/preferences/Section.qml +++ b/interface/resources/qml/dialogs/preferences/Section.qml @@ -7,7 +7,7 @@ import "." Preference { id: root - property bool expandable: true + property bool collapsable: true property bool expanded: false property string name: "Header" property real spacing: 8 @@ -43,10 +43,10 @@ Preference { VrControls.FontAwesome { id: toggle - width: root.expandable ? height : 0 + width: root.collapsable ? height : 0 anchors { left: parent.left; top: parent.top; margins: root.spacing } - visible: root.expandable - enabled: root.expandable + visible: root.collapsable + enabled: root.collapsable rotation: root.expanded ? 0 : -90 text: "\uf078" Behavior on rotation { PropertyAnimation {} } From 191e6090e7adaacfbb77eb332adc7bef97a24e79 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 28 Jan 2016 11:36:23 -0800 Subject: [PATCH 113/145] Moves zone props to top of entity props panel --- examples/html/entityProperties.html | 270 ++++++++++++++-------------- 1 file changed, 136 insertions(+), 134 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 898f2bea6d..86dbeebe9f 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -976,6 +976,142 @@
+ +
+ +
+ +
+ Stage Sun Model Enabled + + + +
+ +
+ +
+ +
+
Light Color
+
+
+
R
+
G
+
B
+
+
+ +
+
Light Intensity
+
+ +
+
+ +
+
Light Direction
+
+
Pitch
+
Yaw
+
Roll
+
+
+ +
+
Ambient Intensity
+
+ +
+
+ + +
+
Ambient URL
+
+ +
+
+ +
+ +
+ +
+
Stage Latitude
+
+ +
+
+
+
Stage Longitude
+
+ +
+
+
+
Stage Altitude
+
+ +
+
+ +
+ Automatically calculate stage hour and day from location and clock. + + + +
+ +
+
Stage Day
+
+ +
+
+
+
Stage Hour
+
+ +
+
+ +
+ +
+ +
+
Background Mode
+
+ +
+
+ + +
+ +
+ +
+
Skybox Color
+
+
+
R
+
G
+
B
+
+
+
+
Skybox URL
+
+ +
+
+ +
@@ -1440,139 +1576,5 @@
-
- -
- -
- Stage Sun Model Enabled - - - -
- -
- -
- -
-
Light Color
-
-
-
R
-
G
-
B
-
-
- -
-
Light Intensity
-
- -
-
- -
-
Light Direction
-
-
Pitch
-
Yaw
-
Roll
-
-
- -
-
Ambient Intensity
-
- -
-
- - -
-
Ambient URL
-
- -
-
- -
- -
- -
-
Stage Latitude
-
- -
-
-
-
Stage Longitude
-
- -
-
-
-
Stage Altitude
-
- -
-
- -
- Automatically calculate stage hour and day from location and clock. - - - -
- -
-
Stage Day
-
- -
-
-
-
Stage Hour
-
- -
-
- -
- -
- -
-
Background Mode
-
- -
-
- - -
- -
- -
-
Skybox Color
-
-
-
R
-
G
-
B
-
-
-
-
Skybox URL
-
- -
-
- From 9cb768bcbd748e6f1308ce511d3b1541b5491c6e Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 28 Jan 2016 11:42:51 -0800 Subject: [PATCH 114/145] document no debug heap trick --- BUILD_WIN.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/BUILD_WIN.md b/BUILD_WIN.md index 671fed5a97..25e20952ca 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -98,3 +98,7 @@ If you need to debug Interface, you can run interface from within Visual Studio * In the Solution Explorer, right click interface and click Set as StartUp Project * Set the "Working Directory" for the Interface debugging sessions to the Debug output directory so that your application can load resources. Do this: right click interface and click Properties, choose Debugging from Configuration Properties, set Working Directory to .\Debug * Now you can run and debug interface through Visual Studio + +For better performance when running debug builds, set the environment variable ```_NO_DEBUG_HEAP``` to ```1``` + +http://preshing.com/20110717/the-windows-heap-is-slow-when-launched-from-the-debugger/ From 3fff5868e8429d4b09da32244864cf21cb9c0088 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 28 Jan 2016 11:57:33 -0800 Subject: [PATCH 115/145] Fix syntax error --- examples/html/entityProperties.html | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 86dbeebe9f..28db85a2fd 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -976,8 +976,7 @@ - -
+
@@ -1110,7 +1109,6 @@
-
@@ -1574,7 +1572,6 @@
- - + - + \ No newline at end of file From 98453c085b5d966ecf752b388178b1f1475064f5 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 28 Jan 2016 12:08:21 -0800 Subject: [PATCH 116/145] Moved source URL up to top of entity properties panel --- examples/html/entityProperties.html | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 898f2bea6d..d8a157d5ca 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -976,6 +976,17 @@ +
+ +
+ +
+
Source URL
+
+ +
+
+
@@ -1311,18 +1322,6 @@
-
- -
- -
-
Source URL
-
- -
-
- -
From bf3a09cd00596c6134393365ed76ea8d9f826e8c Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 28 Jan 2016 12:14:20 -0800 Subject: [PATCH 117/145] Fixing the default value for the TOneMapping curve and cleaning the code into the ToneMappingEffect file --- .../render-utils/src/RenderDeferredTask.cpp | 15 +--------- .../render-utils/src/RenderDeferredTask.h | 28 ------------------ .../render-utils/src/ToneMappingEffect.cpp | 17 ++++++++++- .../render-utils/src/ToneMappingEffect.h | 29 ++++++++++++++++++- 4 files changed, 45 insertions(+), 44 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index eb46129777..d76d0a77de 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -27,6 +27,7 @@ #include "render/DrawStatus.h" #include "AmbientOcclusionEffect.h" #include "AntialiasingEffect.h" +#include "ToneMappingEffect.h" #include "RenderDeferredTask.h" @@ -67,20 +68,6 @@ void RenderDeferred::run(const SceneContextPointer& sceneContext, const RenderCo DependencyManager::get()->render(renderContext); } -void ToneMappingDeferred::configure(const Config& config) { - if (config.exposure >= 0.0f) { - _toneMappingEffect.setExposure(config.exposure); - } - - if (config.curve >= 0) { - _toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)config.curve); - } -} - -void ToneMappingDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - _toneMappingEffect.render(renderContext->args); -} - RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 414b019b31..8d773a9b21 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -16,8 +16,6 @@ #include "render/DrawTask.h" -#include "ToneMappingEffect.h" - class SetupDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); @@ -40,32 +38,6 @@ public: using JobModel = render::Job::Model; }; - -class ToneMappingConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(bool enabled MEMBER enabled) - Q_PROPERTY(float exposure MEMBER exposure NOTIFY dirty); - Q_PROPERTY(int curve MEMBER curve NOTIFY dirty); -public: - ToneMappingConfig() : render::Job::Config(true) {} - - float exposure{ 0.0f }; - int curve{ 3 }; -signals: - void dirty(); -}; - -class ToneMappingDeferred { -public: - using Config = ToneMappingConfig; - using JobModel = render::Job::Model; - - void configure(const Config& config); - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - - ToneMappingEffect _toneMappingEffect; -}; - class DrawConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int numDrawn READ getNumDrawn) diff --git a/libraries/render-utils/src/ToneMappingEffect.cpp b/libraries/render-utils/src/ToneMappingEffect.cpp index 55b7d41ab3..da11507965 100644 --- a/libraries/render-utils/src/ToneMappingEffect.cpp +++ b/libraries/render-utils/src/ToneMappingEffect.cpp @@ -145,4 +145,19 @@ void ToneMappingEffect::render(RenderArgs* args) { batch.setResourceTexture(ToneMappingEffect_LightingMapSlot, lightingBuffer); batch.draw(gpu::TRIANGLE_STRIP, 4); }); -} \ No newline at end of file +} + + +void ToneMappingDeferred::configure(const Config& config) { + if (config.exposure >= 0.0f) { + _toneMappingEffect.setExposure(config.exposure); + } + + if (config.curve >= 0) { + _toneMappingEffect.setToneCurve((ToneMappingEffect::ToneCurve)config.curve); + } +} + +void ToneMappingDeferred::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { + _toneMappingEffect.render(renderContext->args); +} diff --git a/libraries/render-utils/src/ToneMappingEffect.h b/libraries/render-utils/src/ToneMappingEffect.h index 20ee9024cf..f6747180a2 100644 --- a/libraries/render-utils/src/ToneMappingEffect.h +++ b/libraries/render-utils/src/ToneMappingEffect.h @@ -17,6 +17,8 @@ #include #include +#include + class RenderArgs; @@ -50,7 +52,7 @@ private: float _exposure = 0.0f; float _twoPowExposure = 1.0f; glm::vec2 spareA; - int _toneCurve = Filmic; + int _toneCurve = Gamma22; glm::vec3 spareB; Parameters() {} @@ -61,4 +63,29 @@ private: void init(); }; +class ToneMappingConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(bool enabled MEMBER enabled) + Q_PROPERTY(float exposure MEMBER exposure NOTIFY dirty); + Q_PROPERTY(int curve MEMBER curve NOTIFY dirty); +public: + ToneMappingConfig() : render::Job::Config(true) {} + + float exposure{ 0.0f }; + int curve{ 1 }; +signals: + void dirty(); +}; + +class ToneMappingDeferred { +public: + using Config = ToneMappingConfig; + using JobModel = render::Job::Model; + + void configure(const Config& config); + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + + ToneMappingEffect _toneMappingEffect; +}; + #endif // hifi_ToneMappingEffect_h From 62d5a45829222c981d804e910d8a78f577566abf Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 28 Jan 2016 12:20:09 -0800 Subject: [PATCH 118/145] Cleaner init --- libraries/render-utils/src/ToneMappingEffect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/ToneMappingEffect.h b/libraries/render-utils/src/ToneMappingEffect.h index f6747180a2..e9a4479dc9 100644 --- a/libraries/render-utils/src/ToneMappingEffect.h +++ b/libraries/render-utils/src/ToneMappingEffect.h @@ -72,7 +72,7 @@ public: ToneMappingConfig() : render::Job::Config(true) {} float exposure{ 0.0f }; - int curve{ 1 }; + int curve{ ToneMappingEffect::Gamma22 }; signals: void dirty(); }; From c41500f9d2a0bcd866f059d3cf95af7f1fd5044d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 12:21:44 -0800 Subject: [PATCH 119/145] Running scripts can now show script URL --- .../resources/qml/dialogs/RunningScripts.qml | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/dialogs/RunningScripts.qml b/interface/resources/qml/dialogs/RunningScripts.qml index eb56b59b66..5aec9ef3cf 100644 --- a/interface/resources/qml/dialogs/RunningScripts.qml +++ b/interface/resources/qml/dialogs/RunningScripts.qml @@ -123,26 +123,42 @@ Window { } ListView { + id: listView clip: true anchors { fill: parent; margins: 0 } model: runningScriptsModel delegate: Rectangle { + id: rectangle + clip: true radius: 3 anchors { left: parent.left; right: parent.right } - height: scriptName.height + 12 - color: index % 2 ? "#ddd" : "#eee" + height: scriptName.height + 12 + (ListView.isCurrentItem ? scriptName.height + 6 : 0) + color: ListView.isCurrentItem ? "#39f" : + index % 2 ? "#ddd" : "#eee" Text { - anchors { left: parent.left; leftMargin: 4; verticalCenter: parent.verticalCenter } id: scriptName + anchors { left: parent.left; leftMargin: 4; top: parent.top; topMargin:6 } text: name } + Text { + id: scriptUrl + anchors { left: scriptName.left; right: parent.right; rightMargin: 4; top: scriptName.bottom; topMargin: 6 } + text: url + elide: Text.ElideMiddle + } + + MouseArea { + anchors.fill: parent + onClicked: listView.currentIndex = index + } + Row { - anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenter: scriptName.verticalCenter anchors.right: parent.right anchors.rightMargin: 4 spacing: 4 From 79c6ed97399c3851f867d2018b5dfe9dcb5d0069 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 28 Jan 2016 12:22:36 -0800 Subject: [PATCH 120/145] add some debug for AudioInjector DOS case --- libraries/audio/src/AudioInjector.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 217b8b0d53..8eb032f8a8 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -295,7 +295,14 @@ int64_t AudioInjector::injectNextFrame() { if (audioMixer) { // send off this audio packet - nodeList->sendUnreliablePacket(*_currentPacket, *audioMixer); + auto bytesWritten = nodeList->sendUnreliablePacket(*_currentPacket, *audioMixer); + if (bytesWritten < 0) { + auto currentTime = _frameTimer->nsecsElapsed() / 1000; + qDebug() << this << "error sending audio injector packet. NF:" + << _nextFrame << "CT:" << currentTime + << "CF:" << currentTime / AudioConstants::NETWORK_FRAME_USECS; + } + _outgoingSequenceNumber++; } From ef451d40df3d2516cbda67d927c5825eda05c6b3 Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 28 Jan 2016 12:39:52 -0800 Subject: [PATCH 121/145] Cleaner... --- libraries/render-utils/src/ToneMappingEffect.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/ToneMappingEffect.h b/libraries/render-utils/src/ToneMappingEffect.h index e9a4479dc9..aa48494ca0 100644 --- a/libraries/render-utils/src/ToneMappingEffect.h +++ b/libraries/render-utils/src/ToneMappingEffect.h @@ -66,11 +66,15 @@ private: class ToneMappingConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(bool enabled MEMBER enabled) - Q_PROPERTY(float exposure MEMBER exposure NOTIFY dirty); - Q_PROPERTY(int curve MEMBER curve NOTIFY dirty); + Q_PROPERTY(float exposure MEMBER exposure WRITE setExposure); + Q_PROPERTY(int curve MEMBER curve WRITE setCurve); public: ToneMappingConfig() : render::Job::Config(true) {} + void setExposure(float newExposure) { exposure = std::max(0.0f, newExposure); emit dirty(); } + void setCurve(int newCurve) { curve = std::max((int)ToneMappingEffect::None, std::min((int)ToneMappingEffect::Filmic, newCurve)); emit dirty(); } + + float exposure{ 0.0f }; int curve{ ToneMappingEffect::Gamma22 }; signals: From 5863e340af253586217bf4ef18eae36205b3fa1e Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 28 Jan 2016 12:46:18 -0800 Subject: [PATCH 122/145] Cleaner... --- libraries/render-utils/src/ToneMappingEffect.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/ToneMappingEffect.h b/libraries/render-utils/src/ToneMappingEffect.h index aa48494ca0..3dd212c2dc 100644 --- a/libraries/render-utils/src/ToneMappingEffect.h +++ b/libraries/render-utils/src/ToneMappingEffect.h @@ -65,8 +65,8 @@ private: class ToneMappingConfig : public render::Job::Config { Q_OBJECT - Q_PROPERTY(bool enabled MEMBER enabled) - Q_PROPERTY(float exposure MEMBER exposure WRITE setExposure); + Q_PROPERTY(bool enabled MEMBER enabled) + Q_PROPERTY(float exposure MEMBER exposure WRITE setExposure); Q_PROPERTY(int curve MEMBER curve WRITE setCurve); public: ToneMappingConfig() : render::Job::Config(true) {} From c30109ec29130502083ce5f42fc60c88adfc8f1e Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Thu, 28 Jan 2016 13:21:48 -0800 Subject: [PATCH 123/145] trying to sync again --- examples/html/entityProperties.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index 28db85a2fd..848e16fae8 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -976,7 +976,7 @@ -
+
@@ -1116,7 +1116,7 @@
-
Href
+
Href - Hifi://address
From 8710029604e567fd73af44fecc235c963084c9c0 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 28 Jan 2016 14:12:52 -0800 Subject: [PATCH 124/145] Changed urls to http and updated hand poses. --- .../defaultAvatar_full/avatar-animation.json | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json index 637ed68455..b71bbc648b 100644 --- a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json +++ b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json @@ -145,7 +145,7 @@ "id": "rightHandGraspOpen", "type": "clip", "data": { - "url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/hand_anims/hydra_pose_open_right.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/hydra_pose_open_right.fbx", "startFrame": 0.0, "endFrame": 0.0, "timeScale": 1.0, @@ -157,7 +157,7 @@ "id": "rightHandGraspClosed", "type": "clip", "data": { - "url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/hand_anims/hydra_pose_closed_right.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/hydra_pose_closed_right.fbx", "startFrame": 0.0, "endFrame": 0.0, "timeScale": 1.0, @@ -205,7 +205,7 @@ "id": "leftHandGraspOpen", "type": "clip", "data": { - "url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/hand_anims/hydra_pose_open_left.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/hydra_pose_open_left.fbx", "startFrame": 0.0, "endFrame": 0.0, "timeScale": 1.0, @@ -217,7 +217,7 @@ "id": "leftHandGraspClosed", "type": "clip", "data": { - "url": "https://hifi-content.s3.amazonaws.com/ozan/dev/anim/hand_anims/hydra_pose_closed_left.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/hydra_pose_closed_left.fbx", "startFrame": 10.0, "endFrame": 10.0, "timeScale": 1.0, @@ -420,7 +420,7 @@ "id": "idleStand", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle.fbx", "startFrame": 0.0, "endFrame": 90.0, "timeScale": 1.0, @@ -432,7 +432,7 @@ "id": "idleTalk", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/talk.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/talk.fbx", "startFrame": 0.0, "endFrame": 801.0, "timeScale": 1.0, @@ -457,7 +457,7 @@ "id": "walkFwdShort", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_short_fwd.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_short_fwd.fbx", "startFrame": 0.0, "endFrame": 39.0, "timeScale": 1.0, @@ -469,7 +469,7 @@ "id": "walkFwdNormal", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_fwd.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_fwd.fbx", "startFrame": 0.0, "endFrame": 35.0, "timeScale": 1.0, @@ -481,7 +481,7 @@ "id": "walkFwdRun", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/run_fwd.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/run_fwd.fbx", "startFrame": 0.0, "endFrame": 21.0, "timeScale": 1.0, @@ -495,7 +495,7 @@ "id": "idleToWalkFwd", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle_to_walk.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle_to_walk.fbx", "startFrame": 1.0, "endFrame": 19.0, "timeScale": 1.0, @@ -518,7 +518,7 @@ "id": "walkBwdShort", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_short_bwd.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_short_bwd.fbx", "startFrame": 0.0, "endFrame": 38.0, "timeScale": 1.0, @@ -530,7 +530,7 @@ "id": "walkBwdNormal", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_bwd.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_bwd.fbx", "startFrame": 0.0, "endFrame": 36.0, "timeScale": 1.0, @@ -544,7 +544,7 @@ "id": "turnLeft", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/turn_left.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/turn_left.fbx", "startFrame": 0.0, "endFrame": 28.0, "timeScale": 1.0, @@ -556,7 +556,7 @@ "id": "turnRight", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/turn_right.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/turn_right.fbx", "startFrame": 0.0, "endFrame": 30.0, "timeScale": 1.0, @@ -579,7 +579,7 @@ "id": "strafeLeftShort", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_short_left.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_short_left.fbx", "startFrame": 0.0, "endFrame": 28.0, "timeScale": 1.0, @@ -591,7 +591,7 @@ "id": "strafeLeftNormal", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_left.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_left.fbx", "startFrame": 0.0, "endFrame": 30.0, "timeScale": 1.0, @@ -616,7 +616,7 @@ "id": "strafeRightShort", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_short_right.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_short_right.fbx", "startFrame": 0.0, "endFrame": 28.0, "timeScale": 1.0, @@ -628,7 +628,7 @@ "id": "strafeRightNormal", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_right.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_right.fbx", "startFrame": 0.0, "endFrame": 30.0, "timeScale": 1.0, @@ -642,7 +642,7 @@ "id": "awayIntro", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/kneel.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/kneel.fbx", "startFrame": 0.0, "endFrame": 83.0, "timeScale": 1.0, @@ -654,7 +654,7 @@ "id": "away", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/kneel.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/kneel.fbx", "startFrame": 83.0, "endFrame": 84.0, "timeScale": 1.0, @@ -666,7 +666,7 @@ "id": "awayOutro", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/kneel.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/kneel.fbx", "startFrame": 84.0, "endFrame": 167.0, "timeScale": 1.0, @@ -678,7 +678,7 @@ "id": "fly", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/fly.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/fly.fbx", "startFrame": 1.0, "endFrame": 80.0, "timeScale": 1.0, @@ -700,7 +700,7 @@ "id": "userAnimA", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle.fbx", "startFrame": 0.0, "endFrame": 90.0, "timeScale": 1.0, @@ -712,7 +712,7 @@ "id": "userAnimB", "type": "clip", "data": { - "url": "https://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle.fbx", + "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle.fbx", "startFrame": 0.0, "endFrame": 90.0, "timeScale": 1.0, From d743ea2c9be5b3f07f0aa3ad49906c5a00bde396 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 28 Jan 2016 14:20:10 -0800 Subject: [PATCH 125/145] Changed urls from s3-us-west-1 to hifi-content.s3 --- .../defaultAvatar_full/avatar-animation.json | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json index b71bbc648b..42ff64abc6 100644 --- a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json +++ b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json @@ -420,7 +420,7 @@ "id": "idleStand", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/idle.fbx", "startFrame": 0.0, "endFrame": 90.0, "timeScale": 1.0, @@ -432,7 +432,7 @@ "id": "idleTalk", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/talk.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/talk.fbx", "startFrame": 0.0, "endFrame": 801.0, "timeScale": 1.0, @@ -457,7 +457,7 @@ "id": "walkFwdShort", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_short_fwd.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/walk_short_fwd.fbx", "startFrame": 0.0, "endFrame": 39.0, "timeScale": 1.0, @@ -469,7 +469,7 @@ "id": "walkFwdNormal", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_fwd.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/walk_fwd.fbx", "startFrame": 0.0, "endFrame": 35.0, "timeScale": 1.0, @@ -481,7 +481,7 @@ "id": "walkFwdRun", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/run_fwd.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/run_fwd.fbx", "startFrame": 0.0, "endFrame": 21.0, "timeScale": 1.0, @@ -495,7 +495,7 @@ "id": "idleToWalkFwd", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle_to_walk.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/idle_to_walk.fbx", "startFrame": 1.0, "endFrame": 19.0, "timeScale": 1.0, @@ -518,7 +518,7 @@ "id": "walkBwdShort", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_short_bwd.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/walk_short_bwd.fbx", "startFrame": 0.0, "endFrame": 38.0, "timeScale": 1.0, @@ -530,7 +530,7 @@ "id": "walkBwdNormal", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/walk_bwd.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/walk_bwd.fbx", "startFrame": 0.0, "endFrame": 36.0, "timeScale": 1.0, @@ -544,7 +544,7 @@ "id": "turnLeft", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/turn_left.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/turn_left.fbx", "startFrame": 0.0, "endFrame": 28.0, "timeScale": 1.0, @@ -556,7 +556,7 @@ "id": "turnRight", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/turn_right.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/turn_right.fbx", "startFrame": 0.0, "endFrame": 30.0, "timeScale": 1.0, @@ -579,7 +579,7 @@ "id": "strafeLeftShort", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_short_left.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/side_step_short_left.fbx", "startFrame": 0.0, "endFrame": 28.0, "timeScale": 1.0, @@ -591,7 +591,7 @@ "id": "strafeLeftNormal", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_left.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/side_step_left.fbx", "startFrame": 0.0, "endFrame": 30.0, "timeScale": 1.0, @@ -616,7 +616,7 @@ "id": "strafeRightShort", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_short_right.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/side_step_short_right.fbx", "startFrame": 0.0, "endFrame": 28.0, "timeScale": 1.0, @@ -628,7 +628,7 @@ "id": "strafeRightNormal", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/side_step_right.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/side_step_right.fbx", "startFrame": 0.0, "endFrame": 30.0, "timeScale": 1.0, @@ -642,7 +642,7 @@ "id": "awayIntro", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/kneel.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/kneel.fbx", "startFrame": 0.0, "endFrame": 83.0, "timeScale": 1.0, @@ -654,7 +654,7 @@ "id": "away", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/kneel.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/kneel.fbx", "startFrame": 83.0, "endFrame": 84.0, "timeScale": 1.0, @@ -666,7 +666,7 @@ "id": "awayOutro", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/kneel.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/kneel.fbx", "startFrame": 84.0, "endFrame": 167.0, "timeScale": 1.0, @@ -678,7 +678,7 @@ "id": "fly", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/fly.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/fly.fbx", "startFrame": 1.0, "endFrame": 80.0, "timeScale": 1.0, @@ -700,7 +700,7 @@ "id": "userAnimA", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/idle.fbx", "startFrame": 0.0, "endFrame": 90.0, "timeScale": 1.0, @@ -712,7 +712,7 @@ "id": "userAnimB", "type": "clip", "data": { - "url": "http://s3-us-west-1.amazonaws.com/hifi-content/ozan/dev/anim/standard_anims_160127/idle.fbx", + "url": "http://hifi-content.s3.amazonaws.com/ozan/dev/anim/standard_anims_160127/idle.fbx", "startFrame": 0.0, "endFrame": 90.0, "timeScale": 1.0, From b7134c75c390a89b57616aaaf6ef0f97b020cbbb Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 29 Jan 2016 12:14:47 +1300 Subject: [PATCH 126/145] Rename OpenGLInfo to OpenGLVersionChecker --- .../src/{OpenGLInfo.cpp => OpenGLVersionChecker.cpp} | 8 ++++---- .../src/{OpenGLInfo.h => OpenGLVersionChecker.h} | 12 ++++++------ interface/src/main.cpp | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) rename interface/src/{OpenGLInfo.cpp => OpenGLVersionChecker.cpp} (91%) rename interface/src/{OpenGLInfo.h => OpenGLVersionChecker.h} (58%) diff --git a/interface/src/OpenGLInfo.cpp b/interface/src/OpenGLVersionChecker.cpp similarity index 91% rename from interface/src/OpenGLInfo.cpp rename to interface/src/OpenGLVersionChecker.cpp index b61863c1bf..d509d6aaab 100644 --- a/interface/src/OpenGLInfo.cpp +++ b/interface/src/OpenGLVersionChecker.cpp @@ -1,5 +1,5 @@ // -// OpenGLInfo.cpp +// OpenGLVersionChecker.cpp // interface/src // // Created by David Rowe on 28 Jan 2016. @@ -9,19 +9,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "OpenGLInfo.h" +#include "OpenGLVersionChecker.h" #include #include #include "GLCanvas.h" -OpenGLInfo::OpenGLInfo(int& argc, char** argv) : +OpenGLVersionChecker::OpenGLVersionChecker(int& argc, char** argv) : QApplication(argc, argv) { } -bool OpenGLInfo::isValidVersion() { +bool OpenGLVersionChecker::isValidVersion() { bool valid = true; // Retrieve OpenGL version diff --git a/interface/src/OpenGLInfo.h b/interface/src/OpenGLVersionChecker.h similarity index 58% rename from interface/src/OpenGLInfo.h rename to interface/src/OpenGLVersionChecker.h index 8df44c72b1..a46020031c 100644 --- a/interface/src/OpenGLInfo.h +++ b/interface/src/OpenGLVersionChecker.h @@ -1,5 +1,5 @@ // -// OpenGLInfo.h +// OpenGLVersionChecker.h // interface/src // // Created by David Rowe on 28 Jan 2016. @@ -9,17 +9,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_OpenGLInfo_h -#define hifi_OpenGLInfo_h +#ifndef hifi_OpenGLVersionChecker_h +#define hifi_OpenGLVersionChecker_h #include -class OpenGLInfo : public QApplication { +class OpenGLVersionChecker : public QApplication { public: - OpenGLInfo(int& argc, char** argv); + OpenGLVersionChecker(int& argc, char** argv); static bool isValidVersion(); }; -#endif // hifi_OpenGLInfo_h +#endif // hifi_OpenGLVersionChecker_h diff --git a/interface/src/main.cpp b/interface/src/main.cpp index db02994a19..745bf94b8c 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -22,7 +22,7 @@ #include "AddressManager.h" #include "Application.h" #include "InterfaceLogging.h" -#include "OpenGLInfo.h" +#include "OpenGLVersionChecker.h" #include "MainWindow.h" int main(int argc, const char* argv[]) { @@ -88,8 +88,8 @@ int main(int argc, const char* argv[]) { // This is done separately from the main Application so that start-up and shut-down logic within the main Application is // not made more complicated than it already is. { - OpenGLInfo openGLInfo(argc, const_cast(argv)); - if (!openGLInfo.isValidVersion()) { + OpenGLVersionChecker openGLVersionChecker(argc, const_cast(argv)); + if (!openGLVersionChecker.isValidVersion()) { qCDebug(interfaceapp, "Early exit due to OpenGL version."); return 0; } From 20205149745452043015078c2bdad78ee6722b5b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 29 Jan 2016 12:29:21 +1300 Subject: [PATCH 127/145] Move OpenGLVersionChecker to gl library --- interface/src/main.cpp | 2 +- .../gl/src/gl}/OpenGLVersionChecker.cpp | 10 +++++----- .../src => libraries/gl/src/gl}/OpenGLVersionChecker.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) rename {interface/src => libraries/gl/src/gl}/OpenGLVersionChecker.cpp (93%) rename {interface/src => libraries/gl/src/gl}/OpenGLVersionChecker.h (95%) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 745bf94b8c..a57e53b384 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -17,12 +17,12 @@ #include #include +#include #include #include "AddressManager.h" #include "Application.h" #include "InterfaceLogging.h" -#include "OpenGLVersionChecker.h" #include "MainWindow.h" int main(int argc, const char* argv[]) { diff --git a/interface/src/OpenGLVersionChecker.cpp b/libraries/gl/src/gl/OpenGLVersionChecker.cpp similarity index 93% rename from interface/src/OpenGLVersionChecker.cpp rename to libraries/gl/src/gl/OpenGLVersionChecker.cpp index d509d6aaab..f1a40bde8d 100644 --- a/interface/src/OpenGLVersionChecker.cpp +++ b/libraries/gl/src/gl/OpenGLVersionChecker.cpp @@ -1,6 +1,6 @@ // // OpenGLVersionChecker.cpp -// interface/src +// libraries/gl/src/gl // // Created by David Rowe on 28 Jan 2016. // Copyright 2016 High Fidelity, Inc. @@ -14,7 +14,7 @@ #include #include -#include "GLCanvas.h" +#include "GLWidget.h" OpenGLVersionChecker::OpenGLVersionChecker(int& argc, char** argv) : QApplication(argc, argv) @@ -25,10 +25,10 @@ bool OpenGLVersionChecker::isValidVersion() { bool valid = true; // Retrieve OpenGL version - GLCanvas* glCanvas = new GLCanvas(); - glCanvas->initializeGL(); + GLWidget* glWidget = new GLWidget(); + glWidget->initializeGL(); QString glVersion = QString((const char*)glGetString(GL_VERSION)); - delete glCanvas; + delete glWidget; // Compare against minimum // The GL_VERSION string begins with a version number in one of these forms: diff --git a/interface/src/OpenGLVersionChecker.h b/libraries/gl/src/gl/OpenGLVersionChecker.h similarity index 95% rename from interface/src/OpenGLVersionChecker.h rename to libraries/gl/src/gl/OpenGLVersionChecker.h index a46020031c..3e16c3a32d 100644 --- a/interface/src/OpenGLVersionChecker.h +++ b/libraries/gl/src/gl/OpenGLVersionChecker.h @@ -1,6 +1,6 @@ // // OpenGLVersionChecker.h -// interface/src +// libraries/gl/src/gl // // Created by David Rowe on 28 Jan 2016. // Copyright 2016 High Fidelity, Inc. From 311f1ac0e376409a9a7e6eda5262b6f976354bd0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 28 Jan 2016 15:37:45 -0800 Subject: [PATCH 128/145] fix for overflow on time of next frame --- libraries/audio/src/AudioConstants.h | 3 +++ libraries/audio/src/AudioInjector.cpp | 4 +++- libraries/audio/src/AudioInjector.h | 2 +- libraries/audio/src/AudioInjectorManager.cpp | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/audio/src/AudioConstants.h b/libraries/audio/src/AudioConstants.h index 6c12c6aa15..d5fd3f15e7 100644 --- a/libraries/audio/src/AudioConstants.h +++ b/libraries/audio/src/AudioConstants.h @@ -29,7 +29,10 @@ namespace AudioConstants { const int NETWORK_FRAME_SAMPLES_PER_CHANNEL = NETWORK_FRAME_BYTES_PER_CHANNEL / sizeof(AudioSample); const float NETWORK_FRAME_MSECS = (AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL / (float)AudioConstants::SAMPLE_RATE) * 1000.0f; + + // be careful with overflows when using this constant const int NETWORK_FRAME_USECS = static_cast(NETWORK_FRAME_MSECS * 1000.0f); + const int MIN_SAMPLE_VALUE = std::numeric_limits::min(); const int MAX_SAMPLE_VALUE = std::numeric_limits::max(); } diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 8eb032f8a8..5fd35bc37a 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -321,14 +321,16 @@ int64_t AudioInjector::injectNextFrame() { const int MAX_ALLOWED_FRAMES_TO_FALL_BEHIND = 7; int64_t currentTime = _frameTimer->nsecsElapsed() / 1000; auto currentFrameBasedOnElapsedTime = currentTime / AudioConstants::NETWORK_FRAME_USECS; + if (currentFrameBasedOnElapsedTime - _nextFrame > MAX_ALLOWED_FRAMES_TO_FALL_BEHIND) { // If we are falling behind by more frames than our threshold, let's skip the frames ahead - qDebug() << "AudioInjector::injectNextFrame() skipping ahead, fell behind by " << (currentFrameBasedOnElapsedTime - _nextFrame) << " frames"; + qDebug() << this << "injectNextFrame() skipping ahead, fell behind by " << (currentFrameBasedOnElapsedTime - _nextFrame) << " frames"; _nextFrame = currentFrameBasedOnElapsedTime; _currentSendOffset = _nextFrame * AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL * (_options.stereo ? 2 : 1) % _audioData.size(); } int64_t playNextFrameAt = ++_nextFrame * AudioConstants::NETWORK_FRAME_USECS; + return std::max(INT64_C(0), playNextFrameAt - currentTime); } diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index acfbc2b04a..79e2e645dd 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -99,7 +99,7 @@ private: AbstractAudioInterface* _localAudioInterface { nullptr }; AudioInjectorLocalBuffer* _localBuffer { nullptr }; - int _nextFrame { 0 }; + int64_t _nextFrame { 0 }; std::unique_ptr _frameTimer { nullptr }; quint16 _outgoingSequenceNumber { 0 }; diff --git a/libraries/audio/src/AudioInjectorManager.cpp b/libraries/audio/src/AudioInjectorManager.cpp index b91bddc553..2327bda0e7 100644 --- a/libraries/audio/src/AudioInjectorManager.cpp +++ b/libraries/audio/src/AudioInjectorManager.cpp @@ -87,7 +87,7 @@ void AudioInjectorManager::run() { if (!injector.isNull()) { // this is an injector that's ready to go, have it send a frame now auto nextCallDelta = injector->injectNextFrame(); - + if (nextCallDelta >= 0 && !injector->isFinished()) { // re-enqueue the injector with the correct timing _injectors.emplace(usecTimestampNow() + nextCallDelta, injector); From af1180aadb2840ef560996a609508cdbf3279dc7 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 15:47:42 -0800 Subject: [PATCH 129/145] Fix combobox in modal windows --- interface/resources/qml/controls/ComboBox.qml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/controls/ComboBox.qml b/interface/resources/qml/controls/ComboBox.qml index e22bc8e664..960ae8127a 100644 --- a/interface/resources/qml/controls/ComboBox.qml +++ b/interface/resources/qml/controls/ComboBox.qml @@ -91,8 +91,10 @@ FocusScope { id: popup parent: desktop anchors.fill: parent + z: desktop.zLevels.menu visible: false focus: true + MouseArea { anchors.fill: parent onClicked: hideList(); @@ -116,7 +118,7 @@ FocusScope { ListView { id: listView - height: textView.height * count + height: textField.height * count * 1.4 model: root.model highlight: Rectangle{ width: listView.currentItem ? listView.currentItem.width : 0 From 0c2805db7ed8b9f5be7e6ddf1d9071a35cc89de7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 28 Jan 2016 15:50:04 -0800 Subject: [PATCH 130/145] remove debug added to catch injector DOS --- libraries/audio/src/AudioInjector.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 5fd35bc37a..ea63df7f17 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -295,14 +295,7 @@ int64_t AudioInjector::injectNextFrame() { if (audioMixer) { // send off this audio packet - auto bytesWritten = nodeList->sendUnreliablePacket(*_currentPacket, *audioMixer); - if (bytesWritten < 0) { - auto currentTime = _frameTimer->nsecsElapsed() / 1000; - qDebug() << this << "error sending audio injector packet. NF:" - << _nextFrame << "CT:" << currentTime - << "CF:" << currentTime / AudioConstants::NETWORK_FRAME_USECS; - } - + nodeList->sendUnreliablePacket(*_currentPacket, *audioMixer); _outgoingSequenceNumber++; } From 1324525ecc363c40295ec57f88a8469de6aab8ad Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 15:50:57 -0800 Subject: [PATCH 131/145] Make file dialog compatible with QFileDialog::getOpenFile --- interface/resources/qml/desktop/Desktop.qml | 6 ++ .../resources/qml/dialogs/FileDialog.qml | 36 +++++++---- .../dialogs/fileDialog/FileTypeSelection.qml | 27 ++++++++ libraries/ui/src/OffscreenUi.cpp | 62 +++++++++++++++++++ libraries/ui/src/OffscreenUi.h | 2 +- 5 files changed, 121 insertions(+), 12 deletions(-) create mode 100644 interface/resources/qml/dialogs/fileDialog/FileTypeSelection.qml diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 8c4f73c200..b610dbf73c 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -257,6 +257,12 @@ FocusScope { return queryDialogBuilder.createObject(desktop, properties); } + Component { id: fileDialogBuilder; FileDialog { } } + function fileOpenDialog(properties) { + return fileDialogBuilder.createObject(desktop, properties); + } + + MenuMouseHandler { id: menuPopperUpper } function popupMenu(point) { menuPopperUpper.popup(desktop, rootMenu.items, point); diff --git a/interface/resources/qml/dialogs/FileDialog.qml b/interface/resources/qml/dialogs/FileDialog.qml index 9d2278f460..353e2df494 100644 --- a/interface/resources/qml/dialogs/FileDialog.qml +++ b/interface/resources/qml/dialogs/FileDialog.qml @@ -12,6 +12,27 @@ import "fileDialog" //FIXME implement shortcuts for favorite location ModalWindow { id: root + resizable: true + width: 640 + height: 480 + + Settings { + category: "FileDialog" + property alias width: root.width + property alias height: root.height + property alias x: root.x + property alias y: root.y + } + + + // Set from OffscreenUi::getOpenFile() + property alias caption: root.title; + // Set from OffscreenUi::getOpenFile() + property alias dir: model.folder; + // Set from OffscreenUi::getOpenFile() + property alias filter: selectionType.filtersString; + // Set from OffscreenUi::getOpenFile() + property int options; // <-- FIXME unused property bool selectDirectory: false; property bool showHidden: false; @@ -19,17 +40,11 @@ ModalWindow { property bool multiSelect: false; // FIXME implement property bool saveDialog: false; + property var helper: fileDialogHelper + property alias model: fileTableView.model signal selectedFile(var file); signal canceled(); - resizable: true - width: 640 - height: 480 - - property var helper: fileDialogHelper - property alias model: fileTableView.model - property alias filterModel: selectionType.model - property alias folder: model.folder Rectangle { anchors.fill: parent @@ -120,6 +135,7 @@ ModalWindow { onDoubleClicked: navigateToRow(row); model: FolderListModel { id: model + nameFilters: selectionType.currentFilter showDirsFirst: true showDotAndDotDot: false showFiles: !root.selectDirectory @@ -157,12 +173,10 @@ ModalWindow { readOnly: true } - ComboBox { + FileTypeSelection { id: selectionType anchors { bottom: buttonRow.top; bottomMargin: 8; right: parent.right; rightMargin: 8; left: buttonRow.left } visible: !selectDirectory - model: ListModel { ListElement { text: "All Files (*.*)"; filter: "*.*" } } -// onCurrentIndexChanged: model.nameFilters = [ filterModel.get(currentIndex).filter ] KeyNavigation.left: fileTableView KeyNavigation.right: openButton } diff --git a/interface/resources/qml/dialogs/fileDialog/FileTypeSelection.qml b/interface/resources/qml/dialogs/fileDialog/FileTypeSelection.qml new file mode 100644 index 0000000000..a3ab652e32 --- /dev/null +++ b/interface/resources/qml/dialogs/fileDialog/FileTypeSelection.qml @@ -0,0 +1,27 @@ +import QtQuick 2.5 + +import "../../controls" as VrControls + +VrControls.ComboBox { + id: root + property string filtersString: "All Files (*.*)"; + property var currentFilter: [ "*.*" ]; + + // Per http://doc.qt.io/qt-5/qfiledialog.html#getOpenFileName the string can contain + // multiple filters separated by semicolons + // ex: "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)" + model: filtersString.split(';;'); + + enabled: model.length > 1 + + onCurrentTextChanged: { + var globRegex = /\((.*)\)$/ + var globs = globRegex.exec(currentText); + if (!globs[1]) { + console.warn("Unable to parse filter " + currentText); + return; + } + currentFilter = globs[1].split(" "); + } +} + diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index d7d28bef84..f399cd95a1 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -412,4 +412,66 @@ void OffscreenUi::toggleMenu(const QPoint& screenPosition) { } +class FileDialogListener : public ModalDialogListener { + Q_OBJECT + + friend class OffscreenUi; + FileDialogListener(QQuickItem* messageBox) : ModalDialogListener(messageBox) { + if (_finished) { + return; + } + connect(_dialog, SIGNAL(selectedFile(QVariant)), this, SLOT(onSelectedFile(QVariant))); + } + +private slots: + void onSelectedFile(QVariant file) { + _result = file; + _finished = true; + disconnect(_dialog); + } +}; + +QString OffscreenUi::fileOpenDialog(const QString& caption, const QString& dir, const QString& filter, QString* selectedFilter, QFileDialog::Options options) { + if (QThread::currentThread() != thread()) { + QString result; + QMetaObject::invokeMethod(this, "fileOpenDialog", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QString, result), + Q_ARG(QString, caption), + Q_ARG(QString, dir), + Q_ARG(QString, filter), + Q_ARG(QString*, selectedFilter), + Q_ARG(QFileDialog::Options, options)); + return result; + } + + // FIXME support returning the selected filter... somehow? + QVariantMap map; + map.insert("caption", caption); + map.insert("dir", QUrl::fromLocalFile(dir)); + map.insert("filter", filter); + map.insert("options", static_cast(options)); + + QVariant buildDialogResult; + bool invokeResult = QMetaObject::invokeMethod(_desktop, "fileOpenDialog", + Q_RETURN_ARG(QVariant, buildDialogResult), + Q_ARG(QVariant, QVariant::fromValue(map))); + + if (!invokeResult) { + qWarning() << "Failed to create file open dialog"; + return QString(); + } + + QVariant result = FileDialogListener(qvariant_cast(buildDialogResult)).waitForResult(); + if (!result.isValid()) { + return QString(); + } + qDebug() << result.toString(); + return result.toUrl().toLocalFile(); +} + +QString OffscreenUi::getOpenFileName(void* ignored, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) { + return DependencyManager::get()->fileOpenDialog(caption, dir, filter, selectedFilter, options); +} + + #include "OffscreenUi.moc" diff --git a/libraries/ui/src/OffscreenUi.h b/libraries/ui/src/OffscreenUi.h index 73307b38f7..8ad6641e06 100644 --- a/libraries/ui/src/OffscreenUi.h +++ b/libraries/ui/src/OffscreenUi.h @@ -82,11 +82,11 @@ public: Q_INVOKABLE QMessageBox::StandardButton messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton); Q_INVOKABLE QVariant inputDialog(const QString& query, const QString& placeholderText = QString(), const QString& currentValue = QString()); + Q_INVOKABLE QString fileOpenDialog(const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0); // FIXME implement static QVariant query(const QString& query, const QString& placeholderText = QString(), const QString& currentValue = QString()); - // FIXME implement // Compatibility with QFileDialog::getOpenFileName static QString getOpenFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0); From db7e4eee8f15274191da80c3bb9b8aab3ad8ff42 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 15:52:11 -0800 Subject: [PATCH 132/145] Make Ctrl-O and 'Running Scripts->load file' follow the same code path --- .../resources/qml/dialogs/RunningScripts.qml | 60 ++++++++----------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/interface/resources/qml/dialogs/RunningScripts.qml b/interface/resources/qml/dialogs/RunningScripts.qml index 5aec9ef3cf..8b148c6bef 100644 --- a/interface/resources/qml/dialogs/RunningScripts.qml +++ b/interface/resources/qml/dialogs/RunningScripts.qml @@ -72,23 +72,6 @@ Window { scripts.stopAllScripts(); } - Component { - id: fileDialogBuilder - FileDialog { } - } - - function loadFromFile() { - var fileDialog = fileDialogBuilder.createObject(desktop, { filterModel: fileFilters }); - fileDialog.canceled.connect(function(){ - console.debug("Cancelled file open") - }) - - fileDialog.selectedFile.connect(function(file){ - console.debug("Selected " + file) - scripts.loadOneScript(file); - }) - } - Rectangle { color: "white" anchors.fill: parent @@ -201,31 +184,38 @@ Window { anchors.bottomMargin: 8 anchors.right: parent.right - // For some reason trigginer an API that enters - // an internal event loop directly from the button clicked - // trigger below causes the appliction to behave oddly. - // Most likely because the button onClicked handling is never - // completed until the function returns. - // FIXME find a better way of handling the input dialogs that - // doesn't trigger this. - Timer { - id: asyncAction - interval: 50 - repeat: false - running: false - onTriggered: ApplicationInterface.loadScriptURLDialog(); - } Button { text: "from URL"; - onClicked: { - focus = false; - asyncAction.running = true; + onClicked: fromUrlTimer.running = true; + + // For some reason trigginer an API that enters + // an internal event loop directly from the button clicked + // trigger below causes the appliction to behave oddly. + // Most likely because the button onClicked handling is never + // completed until the function returns. + // FIXME find a better way of handling the input dialogs that + // doesn't trigger this. + Timer { + id: fromUrlTimer + interval: 5 + repeat: false + running: false + onTriggered: ApplicationInterface.loadScriptURLDialog(); } } + Button { text: "from Disk" - onClicked: loadFromFile(); + onClicked: fromDiskTimer.running = true; + + Timer { + id: fromDiskTimer + interval: 5 + repeat: false + running: false + onTriggered: ApplicationInterface.loadDialog(); + } } } From aa03241dd9ba8a52899c3e7167816927d2f6d70c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 15:53:04 -0800 Subject: [PATCH 133/145] Make all load script dialogs QML and respect previous script location --- interface/src/Application.cpp | 21 ++++++++++++++----- interface/src/Application.h | 4 ++++ interface/src/ui/ScriptEditorWidget.cpp | 4 ++-- interface/src/ui/ScriptEditorWindow.cpp | 7 +++---- libraries/script-engine/src/ScriptEngines.cpp | 14 +------------ libraries/script-engine/src/ScriptEngines.h | 6 ------ 6 files changed, 26 insertions(+), 30 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8e0d46bc81..0bd0031740 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -416,7 +416,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : _aboutToQuit(false), _notifiedPacketVersionMismatchThisDomain(false), _maxOctreePPS(maxOctreePacketsPerSecond.get()), - _lastFaceTrackerUpdate(0) + _lastFaceTrackerUpdate(0), + _previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION) { thread()->setObjectName("Main Thread"); @@ -4501,14 +4502,24 @@ void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject } void Application::loadDialog() { - // To be migratd to QML - QString fileNameString = QFileDialog::getOpenFileName( - _glWidget, tr("Open Script"), "", tr("JavaScript Files (*.js)")); - if (!fileNameString.isEmpty()) { + auto scriptEngines = DependencyManager::get(); + QString fileNameString = OffscreenUi::getOpenFileName( + _glWidget, tr("Open Script"), getPreviousScriptLocation(), tr("JavaScript Files (*.js)")); + if (!fileNameString.isEmpty() && QFile(fileNameString).exists()) { + setPreviousScriptLocation(QFileInfo(fileNameString).absolutePath()); DependencyManager::get()->loadScript(fileNameString, true, false, false, true); // Don't load from cache } } +QString Application::getPreviousScriptLocation() { + QString result = _previousScriptLocation.get(); + return result; +} + +void Application::setPreviousScriptLocation(const QString& location) { + _previousScriptLocation.set(location); +} + void Application::loadScriptURLDialog() { auto newScript = OffscreenUi::getText(nullptr, "Open and Run Script", "Script URL"); if (!newScript.isEmpty()) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 71946497d5..e4bfba7492 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -103,6 +103,9 @@ public: void postLambdaEvent(std::function f) override; + QString getPreviousScriptLocation(); + void setPreviousScriptLocation(const QString& previousScriptLocation); + void initializeGL(); void initializeUi(); void paintGL(); @@ -431,6 +434,7 @@ private: Camera _mirrorCamera; // Cammera for mirror view QRect _mirrorViewRect; + Setting::Handle _previousScriptLocation; Setting::Handle _fieldOfView; float _scaleMirror; diff --git a/interface/src/ui/ScriptEditorWidget.cpp b/interface/src/ui/ScriptEditorWidget.cpp index a261c208d7..df66d1e3e1 100644 --- a/interface/src/ui/ScriptEditorWidget.cpp +++ b/interface/src/ui/ScriptEditorWidget.cpp @@ -191,10 +191,10 @@ bool ScriptEditorWidget::save() { bool ScriptEditorWidget::saveAs() { auto scriptEngines = DependencyManager::get(); QString fileName = QFileDialog::getSaveFileName(this, tr("Save script"), - scriptEngines->getPreviousScriptLocation(), + qApp->getPreviousScriptLocation(), tr("JavaScript Files (*.js)")); if (!fileName.isEmpty()) { - scriptEngines->setPreviousScriptLocation(fileName); + qApp->setPreviousScriptLocation(fileName); return saveFile(fileName); } else { return false; diff --git a/interface/src/ui/ScriptEditorWindow.cpp b/interface/src/ui/ScriptEditorWindow.cpp index 919c8b64d3..45a2f3f440 100644 --- a/interface/src/ui/ScriptEditorWindow.cpp +++ b/interface/src/ui/ScriptEditorWindow.cpp @@ -87,12 +87,11 @@ void ScriptEditorWindow::loadScriptMenu(const QString& scriptName) { } void ScriptEditorWindow::loadScriptClicked() { - auto scriptEngines = DependencyManager::get(); QString scriptName = QFileDialog::getOpenFileName(this, tr("Interface"), - scriptEngines->getPreviousScriptLocation(), + qApp->getPreviousScriptLocation(), tr("JavaScript Files (*.js)")); if (!scriptName.isEmpty()) { - scriptEngines->setPreviousScriptLocation(scriptName); + qApp->setPreviousScriptLocation(scriptName); addScriptEditorWidget("loading...")->loadFile(scriptName); updateButtons(); } @@ -100,7 +99,7 @@ void ScriptEditorWindow::loadScriptClicked() { void ScriptEditorWindow::loadMenuAboutToShow() { _loadMenu->clear(); - QStringList runningScripts = DependencyManager::get()->getRunningScripts();; + QStringList runningScripts = DependencyManager::get()->getRunningScripts(); if (runningScripts.count() > 0) { QSignalMapper* signalMapper = new QSignalMapper(this); foreach (const QString& runningScript, runningScripts) { diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 0a0b2de47e..6e8469a93f 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -34,8 +34,7 @@ ScriptsModel& getScriptsModel() { } ScriptEngines::ScriptEngines() - : _scriptsLocationHandle("scriptsLocation", DESKTOP_LOCATION), - _previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION) + : _scriptsLocationHandle("scriptsLocation", DESKTOP_LOCATION) { _scriptsModelFilter.setSourceModel(&_scriptsModel); _scriptsModelFilter.sort(0, Qt::AscendingOrder); @@ -445,14 +444,3 @@ void ScriptEngines::onScriptEngineError(const QString& scriptFilename) { qCDebug(scriptengine) << "Application::loadScript(), script failed to load..."; emit scriptLoadError(scriptFilename, ""); } - -QString ScriptEngines::getPreviousScriptLocation() const { - return _previousScriptLocation.get(); -} - -void ScriptEngines::setPreviousScriptLocation(const QString& previousScriptLocation) { - if (_previousScriptLocation.get() != previousScriptLocation) { - _previousScriptLocation.set(previousScriptLocation); - emit previousScriptLocationChanged(); - } -} diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 97afe9ac57..df60d6ff63 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -30,7 +30,6 @@ class ScriptEngines : public QObject, public Dependency { Q_PROPERTY(ScriptsModel* scriptsModel READ scriptsModel CONSTANT) Q_PROPERTY(ScriptsModelFilter* scriptsModelFilter READ scriptsModelFilter CONSTANT) - Q_PROPERTY(QString previousScriptLocation READ getPreviousScriptLocation WRITE setPreviousScriptLocation NOTIFY previousScriptLocationChanged) public: using ScriptInitializer = std::function; @@ -48,9 +47,6 @@ public: QStringList getRunningScripts(); ScriptEngine* getScriptEngine(const QString& scriptHash); - QString getPreviousScriptLocation() const; - void setPreviousScriptLocation(const QString& previousScriptLocation); - ScriptsModel* scriptsModel() { return &_scriptsModel; }; ScriptsModelFilter* scriptsModelFilter() { return &_scriptsModelFilter; }; @@ -73,7 +69,6 @@ signals: void scriptCountChanged(); void scriptsReloading(); void scriptLoadError(const QString& filename, const QString& error); - void previousScriptLocationChanged(); protected slots: void onScriptFinished(const QString& fileNameString, ScriptEngine* engine); @@ -97,7 +92,6 @@ protected: std::atomic _stoppingAllScripts { false }; std::list _scriptInitializers; mutable Setting::Handle _scriptsLocationHandle; - mutable Setting::Handle _previousScriptLocation; ScriptsModel _scriptsModel; ScriptsModelFilter _scriptsModelFilter; }; From 5b817ccc214cb3b30ca3d7ca161af8adfe3d35b0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 27 Jan 2016 15:47:06 -0800 Subject: [PATCH 134/145] Make all 2D overlays QML --- examples/libraries/overlayManager.js | 8 - examples/libraries/toolBars.js | 28 +-- .../resources/qml/TextOverlayElement.qml | 23 -- .../qml/hifi/overlays/ImageOverlay.qml | 78 ++++++ .../resources/qml/hifi/overlays/Overlay.qml | 30 +++ .../qml/hifi/overlays/RectangleOverlay.qml | 38 +++ .../qml/hifi/overlays/TextOverlay.qml | 63 +++++ interface/src/ui/overlays/ImageOverlay.cpp | 154 +----------- interface/src/ui/overlays/ImageOverlay.h | 34 +-- interface/src/ui/overlays/Overlay.h | 1 + interface/src/ui/overlays/Overlays.cpp | 5 +- interface/src/ui/overlays/QmlOverlay.cpp | 74 ++++++ interface/src/ui/overlays/QmlOverlay.h | 41 +++ .../src/ui/overlays/RectangleOverlay.cpp | 21 ++ interface/src/ui/overlays/RectangleOverlay.h | 27 ++ interface/src/ui/overlays/TextOverlay.cpp | 237 +----------------- interface/src/ui/overlays/TextOverlay.h | 50 +--- tests/ui/qmlscratch.pro | 3 +- 18 files changed, 421 insertions(+), 494 deletions(-) delete mode 100644 interface/resources/qml/TextOverlayElement.qml create mode 100644 interface/resources/qml/hifi/overlays/ImageOverlay.qml create mode 100644 interface/resources/qml/hifi/overlays/Overlay.qml create mode 100644 interface/resources/qml/hifi/overlays/RectangleOverlay.qml create mode 100644 interface/resources/qml/hifi/overlays/TextOverlay.qml create mode 100644 interface/src/ui/overlays/QmlOverlay.cpp create mode 100644 interface/src/ui/overlays/QmlOverlay.h create mode 100644 interface/src/ui/overlays/RectangleOverlay.cpp create mode 100644 interface/src/ui/overlays/RectangleOverlay.h diff --git a/examples/libraries/overlayManager.js b/examples/libraries/overlayManager.js index ce79214537..49398c5009 100644 --- a/examples/libraries/overlayManager.js +++ b/examples/libraries/overlayManager.js @@ -236,18 +236,10 @@ "dimensions" ]); - ImageOverlay = generateOverlayClass(Overlay2D, "image", [ - "subImage", "imageURL" - ]); - Image3DOverlay = generateOverlayClass(Billboard3DOverlay, "image3d", [ "url", "subImage" ]); - TextOverlay = generateOverlayClass(Overlay2D, "text", [ - "font", "text", "backgroundColor", "backgroundAlpha", "leftMargin", "topMargin" - ]); - Text3DOverlay = generateOverlayClass(Billboard3DOverlay, "text3d", [ "text", "backgroundColor", "backgroundAlpha", "lineHeight", "leftMargin", "topMargin", "rightMargin", "bottomMargin" diff --git a/examples/libraries/toolBars.js b/examples/libraries/toolBars.js index 7ab68cab1c..6c01580ea6 100644 --- a/examples/libraries/toolBars.js +++ b/examples/libraries/toolBars.js @@ -132,14 +132,15 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit this.y = y; this.width = 0; this.height = ToolBar.TITLE_BAR_HEIGHT; - this.back = this.back = Overlays.addOverlay("text", { - backgroundColor: { red: 255, green: 255, blue: 255 }, + this.backAlpha = 1.0; + this.back = Overlays.addOverlay("rectangle", { + color: { red: 255, green: 255, blue: 255 }, x: this.x, y: this.y, + radius: 4, width: this.width, height: this.height, - alpha: 1.0, - backgroundAlpha: 1.0, + alpha: this.backAlpha, visible: false }); this.spacing = []; @@ -246,10 +247,8 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit this.tools[tool].setAlpha(alpha); } if (this.back != null) { - Overlays.editOverlay(this.back, { - alpha: alpha, - backgroundAlpha: alpha - }); + this.backAlpha = alpha; + Overlays.editOverlay(this.back, { alpha: alpha }); } } else { this.tools[tool].setAlpha(alpha); @@ -258,9 +257,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit this.setBack = function(color, alpha) { if (color == null) { - Overlays.editOverlay(this.back, { - visible: false - }); + Overlays.editOverlay(this.back, { visible: false }); } else { Overlays.editOverlay(this.back, { width: this.width + @@ -268,8 +265,8 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit height: this.height + ((direction == ToolBar.VERTICAL) ? 1 : 2) * ToolBar.SPACING, visible: true, - backgroundColor: color, - backgroundAlpha: alpha + color: color, + alpha: alpha }); } } @@ -339,12 +336,9 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit that.hover = function (enable) { // Can be overriden or extended by clients. that.isHovering = enable; if (that.back) { - if (enable) { - that.oldAlpha = Overlays.getProperty(that.back, 'backgroundAlpha'); - } Overlays.editOverlay(this.back, { visible: enable, - backgroundAlpha: enable ? 0.5 : that.oldAlpha + alpha: enable ? 0.5 : that.backAlpha }); } }; diff --git a/interface/resources/qml/TextOverlayElement.qml b/interface/resources/qml/TextOverlayElement.qml deleted file mode 100644 index 0d9dd1eacc..0000000000 --- a/interface/resources/qml/TextOverlayElement.qml +++ /dev/null @@ -1,23 +0,0 @@ -import Hifi 1.0 -import QtQuick 2.3 -import QtQuick.Controls 1.2 - -TextOverlayElement { - id: root - Rectangle { - color: root.backgroundColor - anchors.fill: parent - Text { - x: root.leftMargin - y: root.topMargin - id: text - objectName: "textElement" - text: root.text - color: root.textColor - font.family: root.fontFamily - font.pixelSize: root.fontSize - lineHeightMode: Text.FixedHeight - lineHeight: root.lineHeight - } - } -} diff --git a/interface/resources/qml/hifi/overlays/ImageOverlay.qml b/interface/resources/qml/hifi/overlays/ImageOverlay.qml new file mode 100644 index 0000000000..b10b66f07c --- /dev/null +++ b/interface/resources/qml/hifi/overlays/ImageOverlay.qml @@ -0,0 +1,78 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 + +import "." + +Overlay { + id: root + + Image { + id: image + property bool scaleFix: true; + property real xOffset: 0 + property real yOffset: 0 + property real imageScale: 1.0 + property var resizer: Timer { + interval: 50 + repeat: false + running: false + onTriggered: { + var targetAspect = root.width / root.height; + var sourceAspect = image.sourceSize.width / image.sourceSize.height; + if (sourceAspect <= targetAspect) { + if (root.width === image.sourceSize.width) { + return; + } + image.imageScale = root.width / image.sourceSize.width; + } else if (sourceAspect > targetAspect){ + if (root.height === image.sourceSize.height) { + return; + } + image.imageScale = root.height / image.sourceSize.height; + } + image.sourceSize = Qt.size(image.sourceSize.width * image.imageScale, image.sourceSize.height * image.imageScale); + } + } + x: -1 * xOffset * imageScale + y: -1 * yOffset * imageScale + + onSourceSizeChanged: { + if (sourceSize.width !== 0 && sourceSize.height !== 0 && progress === 1.0 && scaleFix) { + scaleFix = false; + resizer.start(); + } + } + } + + function updateSubImage(subImage) { + var keys = Object.keys(subImage); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + var value = subImage[key]; + switch (key) { + case "x": image.xOffset = value; break; + case "y": image.yOffset = value; break; + } + } + } + + function updatePropertiesFromScript(properties) { + var keys = Object.keys(properties); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + var value = properties[key]; + switch (key) { + case "height": root.height = value; break; + case "width": root.width = value; break; + case "x": root.x = value; break; + case "y": root.y = value; break; + case "visible": root.visible = value; break; + case "alpha": root.opacity = value; break; + case "imageURL": image.source = value; break; + case "subImage": updateSubImage(value); break; + default: console.log("OVERLAY Unhandled image property " + key); + } + } + } +} + diff --git a/interface/resources/qml/hifi/overlays/Overlay.qml b/interface/resources/qml/hifi/overlays/Overlay.qml new file mode 100644 index 0000000000..80f3233b69 --- /dev/null +++ b/interface/resources/qml/hifi/overlays/Overlay.qml @@ -0,0 +1,30 @@ +import Hifi 1.0 +import QtQuick 2.3 +import QtQuick.Controls 1.2 + +Item { + id: root + clip: true + + property int dumpDepth: 0; + + + function dumpObject(object) { + var keys = Object.keys(object); + var tabsString = ""; + for (var j = 0; j < dumpDepth; ++j) { + tabsString = tabsString + "\t"; + } + + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + var value = object[key]; + console.log(tabsString + "OVERLAY Key " + key + " (" + typeof(value) + "): " + value); + if (typeof(value) === "object") { + ++dumpDepth; + dumpObject(value) + --dumpDepth; + } + } + } +} diff --git a/interface/resources/qml/hifi/overlays/RectangleOverlay.qml b/interface/resources/qml/hifi/overlays/RectangleOverlay.qml new file mode 100644 index 0000000000..0ea9b1a2a9 --- /dev/null +++ b/interface/resources/qml/hifi/overlays/RectangleOverlay.qml @@ -0,0 +1,38 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 + +import "." + +Overlay { + id: root + + Rectangle { + id: rectangle + anchors.fill: parent + color: "black" + } + + function updatePropertiesFromScript(properties) { + var keys = Object.keys(properties); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + var value = properties[key]; + console.log("OVERLAY rectangle property " + key + " set to value " + value); + switch (key) { + case "height": root.height = value; break; + case "width": root.width = value; break; + case "x": root.x = value; break; + case "y": root.y = value; break; + case "visible": root.visible = value; break; + case "alpha": rectangle.color.a = value; break; + case "color": rectangle.color = Qt.rgba(value.red, value.green, value.blue, rectangle.color.a); break; + case "borderAlpha": rectangle.border.color.a = value; break; + case "borderColor": rectangle.border.color = Qt.rgba(value.red, value.green, value.blue, rectangle.border.color.a); break; + case "borderWidth": rectangle.border.width = value; break; + case "radius": rectangle.radius = value; break; + default: console.log("OVERLAY Unhandled rectangle property " + key); + } + } + } +} + diff --git a/interface/resources/qml/hifi/overlays/TextOverlay.qml b/interface/resources/qml/hifi/overlays/TextOverlay.qml new file mode 100644 index 0000000000..21b4fddda9 --- /dev/null +++ b/interface/resources/qml/hifi/overlays/TextOverlay.qml @@ -0,0 +1,63 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 + +import "." + +Overlay { + id: root + clip: true + Rectangle { + id: background; + anchors.fill: parent + color: "#B2000000" + + Text { + id: textField; + anchors { fill: parent; bottomMargin: textField.anchors.topMargin; rightMargin: textField.anchors.leftMargin; } + objectName: "textElement" + color: "white" + lineHeightMode: Text.FixedHeight + font.family: "Helvetica" + font.pixelSize: 18 + lineHeight: 18 + } + } + + function updatePropertiesFromScript(properties) { + var keys = Object.keys(properties); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + var value = properties[key]; + switch (key) { + case "height": root.height = value; break; + case "width": root.width = value; break; + case "x": root.x = value; break; + case "y": root.y = value; break; + case "visible": root.visible = value; break; + case "alpha": textField.color.a = value; break; + case "margin": textField.anchors.margins = value; break; + case "leftMargin": textField.anchors.leftMargin = value; break; + case "topMargin": textField.anchors.topMargin = value; break; + case "color": + case "textColor": textField.color = Qt.rgba(value.red, value.green, value.blue, textField.color.a); break; + case "text": textField.text = value; break; + case "backgroundAlpha": + if ("object" === typeof(value)) { + console.log("OVERLAY Unexpected object for alpha"); + dumpObject(value) + } else { + background.color.a = value; break; + } + break + case "backgroundColor": background.color = Qt.rgba(value.red, value.green, value.blue, background.color.a); break; + case "font": if (typeof(value) === "Object") { + console.log("Font object"); + dumpObject(value) + } + break; + default: + console.log("OVERLAY text unhandled property " + key); + } + } + } +} diff --git a/interface/src/ui/overlays/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp index 8df62b9675..b273276dbf 100644 --- a/interface/src/ui/overlays/ImageOverlay.cpp +++ b/interface/src/ui/overlays/ImageOverlay.cpp @@ -17,159 +17,15 @@ QString const ImageOverlay::TYPE = "image"; +QUrl const ImageOverlay::URL = "hifi/overlays/ImageOverlay.qml"; -ImageOverlay::ImageOverlay() : - _imageURL(), - _renderImage(false), - _wantClipFromImage(false) -{ -} +ImageOverlay::ImageOverlay() + : QmlOverlay(URL) { } ImageOverlay::ImageOverlay(const ImageOverlay* imageOverlay) : - Overlay2D(imageOverlay), - _imageURL(imageOverlay->_imageURL), - _textureImage(imageOverlay->_textureImage), - _texture(imageOverlay->_texture), - _fromImage(imageOverlay->_fromImage), - _renderImage(imageOverlay->_renderImage), - _wantClipFromImage(imageOverlay->_wantClipFromImage) -{ -} + QmlOverlay(URL, imageOverlay) { } -// TODO: handle setting image multiple times, how do we manage releasing the bound texture? -void ImageOverlay::setImageURL(const QUrl& url) { - _imageURL = url; - if (url.isEmpty()) { - _isLoaded = true; - _renderImage = false; - _texture.clear(); - } else { - _isLoaded = false; - _renderImage = true; - } -} - -void ImageOverlay::render(RenderArgs* args) { - if (!_isLoaded && _renderImage) { - _isLoaded = true; - _texture = DependencyManager::get()->getTexture(_imageURL); - } - // If we are not visible or loaded, return. If we are trying to render an - // image but the texture hasn't loaded, return. - if (!_visible || !_isLoaded || (_renderImage && !_texture->isLoaded())) { - return; - } - - auto geometryCache = DependencyManager::get(); - gpu::Batch& batch = *args->_batch; - geometryCache->useSimpleDrawPipeline(batch); - if (_renderImage) { - batch.setResourceTexture(0, _texture->getGPUTexture()); - } else { - batch.setResourceTexture(0, args->_whiteTexture); - } - - const float MAX_COLOR = 255.0f; - xColor color = getColor(); - float alpha = getAlpha(); - glm::vec4 quadColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha); - - int left = _bounds.left(); - int right = _bounds.right() + 1; - int top = _bounds.top(); - int bottom = _bounds.bottom() + 1; - - glm::vec2 topLeft(left, top); - glm::vec2 bottomRight(right, bottom); - - batch.setModelTransform(Transform()); - - // if for some reason our image is not over 0 width or height, don't attempt to render the image - if (_renderImage) { - float imageWidth = _texture->getWidth(); - float imageHeight = _texture->getHeight(); - if (imageWidth > 0 && imageHeight > 0) { - QRect fromImage; - if (_wantClipFromImage) { - float scaleX = imageWidth / _texture->getOriginalWidth(); - float scaleY = imageHeight / _texture->getOriginalHeight(); - - fromImage.setX(scaleX * _fromImage.x()); - fromImage.setY(scaleY * _fromImage.y()); - fromImage.setWidth(scaleX * _fromImage.width()); - fromImage.setHeight(scaleY * _fromImage.height()); - } - else { - fromImage.setX(0); - fromImage.setY(0); - fromImage.setWidth(imageWidth); - fromImage.setHeight(imageHeight); - } - - float x = fromImage.x() / imageWidth; - float y = fromImage.y() / imageHeight; - float w = fromImage.width() / imageWidth; // ?? is this what we want? not sure - float h = fromImage.height() / imageHeight; - - glm::vec2 texCoordTopLeft(x, y); - glm::vec2 texCoordBottomRight(x + w, y + h); - glm::vec4 texcoordRect(texCoordTopLeft, w, h); - - DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor); - } else { - DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, quadColor); - } - } else { - DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, quadColor); - } -} - -void ImageOverlay::setProperties(const QScriptValue& properties) { - Overlay2D::setProperties(properties); - - QScriptValue subImageBounds = properties.property("subImage"); - if (subImageBounds.isValid()) { - QRect oldSubImageRect = _fromImage; - QRect subImageRect = _fromImage; - if (subImageBounds.property("x").isValid()) { - subImageRect.setX(subImageBounds.property("x").toVariant().toInt()); - } else { - subImageRect.setX(oldSubImageRect.x()); - } - if (subImageBounds.property("y").isValid()) { - subImageRect.setY(subImageBounds.property("y").toVariant().toInt()); - } else { - subImageRect.setY(oldSubImageRect.y()); - } - if (subImageBounds.property("width").isValid()) { - subImageRect.setWidth(subImageBounds.property("width").toVariant().toInt()); - } else { - subImageRect.setWidth(oldSubImageRect.width()); - } - if (subImageBounds.property("height").isValid()) { - subImageRect.setHeight(subImageBounds.property("height").toVariant().toInt()); - } else { - subImageRect.setHeight(oldSubImageRect.height()); - } - setClipFromSource(subImageRect); - } - - QScriptValue imageURL = properties.property("imageURL"); - if (imageURL.isValid()) { - setImageURL(imageURL.toVariant().toString()); - } -} - -QScriptValue ImageOverlay::getProperty(const QString& property) { - if (property == "subImage") { - return qRectToScriptValue(_scriptEngine, _fromImage); - } - if (property == "imageURL") { - return _imageURL.toString(); - } - - return Overlay2D::getProperty(property); -} ImageOverlay* ImageOverlay::createClone() const { return new ImageOverlay(this); } + diff --git a/interface/src/ui/overlays/ImageOverlay.h b/interface/src/ui/overlays/ImageOverlay.h index 5698a73732..224cb42045 100644 --- a/interface/src/ui/overlays/ImageOverlay.h +++ b/interface/src/ui/overlays/ImageOverlay.h @@ -11,48 +11,22 @@ #ifndef hifi_ImageOverlay_h #define hifi_ImageOverlay_h -// include this before QGLWidget, which includes an earlier version of OpenGL -#include -#include #include -#include +#include "QmlOverlay.h" -#include "Overlay2D.h" - -class ImageOverlay : public Overlay2D { +class ImageOverlay : public QmlOverlay { Q_OBJECT public: static QString const TYPE; virtual QString getType() const { return TYPE; } + static QUrl const URL; ImageOverlay(); ImageOverlay(const ImageOverlay* imageOverlay); - virtual void render(RenderArgs* args); - - // getters - const QRect& getClipFromSource() const { return _fromImage; } - const QUrl& getImageURL() const { return _imageURL; } - - // setters - void setClipFromSource(const QRect& bounds) { _fromImage = bounds; _wantClipFromImage = true; } - void setImageURL(const QUrl& url); - virtual void setProperties(const QScriptValue& properties); - virtual QScriptValue getProperty(const QString& property); - - virtual ImageOverlay* createClone() const; - -private: - - QUrl _imageURL; - QImage _textureImage; - - NetworkTexturePointer _texture; - QRect _fromImage; // where from in the image to sample - bool _renderImage; // is there an image associated with this overlay, or is it just a colored rectangle - bool _wantClipFromImage; + virtual ImageOverlay* createClone() const override; }; diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 9a19c71db6..4d3b5ae36f 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -39,6 +39,7 @@ public: virtual void render(RenderArgs* args) = 0; virtual AABox getBounds() const = 0; + virtual bool supportsGetProperty() const { return true; } virtual bool addToScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges); virtual void removeFromScene(Overlay::Pointer overlay, std::shared_ptr scene, render::PendingChanges& pendingChanges); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index f6e6851c38..10298b8f15 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -30,6 +30,7 @@ #include "Sphere3DOverlay.h" #include "Grid3DOverlay.h" #include "TextOverlay.h" +#include "RectangleOverlay.h" #include "Text3DOverlay.h" #include "Web3DOverlay.h" #include @@ -175,6 +176,8 @@ unsigned int Overlays::addOverlay(const QString& type, const QScriptValue& prope thisOverlay = std::make_shared(); } else if (type == Web3DOverlay::TYPE) { thisOverlay = std::make_shared(); + } else if (type == RectangleOverlay::TYPE) { + thisOverlay = std::make_shared(); } if (thisOverlay) { @@ -373,7 +376,7 @@ OverlayPropertyResult Overlays::getProperty(unsigned int id, const QString& prop OverlayPropertyResult result; Overlay::Pointer thisOverlay = getOverlay(id); QReadLocker lock(&_lock); - if (thisOverlay) { + if (thisOverlay && thisOverlay->supportsGetProperty()) { result.value = thisOverlay->getProperty(property); } return result; diff --git a/interface/src/ui/overlays/QmlOverlay.cpp b/interface/src/ui/overlays/QmlOverlay.cpp new file mode 100644 index 0000000000..e141d38f2b --- /dev/null +++ b/interface/src/ui/overlays/QmlOverlay.cpp @@ -0,0 +1,74 @@ +// +// Created by Bradley Austin Davis on 2016/01/27 +// Copyright 2013-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 +// + +#include "QmlOverlay.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Application.h" +#include "text/FontFamilies.h" + +QmlOverlay::QmlOverlay(const QUrl& url) { + buildQmlElement(url); +} + +QmlOverlay::QmlOverlay(const QUrl& url, const QmlOverlay* textOverlay) + : Overlay2D(textOverlay) { + buildQmlElement(url); +} + +void QmlOverlay::buildQmlElement(const QUrl& url) { + auto offscreenUi = DependencyManager::get(); + offscreenUi->returnFromUiThread([=] { + offscreenUi->load(url, [=](QQmlContext* context, QObject* object) { + _qmlElement = dynamic_cast(object); + }); + while (!_qmlElement) { + qApp->processEvents(); + } + return QVariant(); + }); +} + +QmlOverlay::~QmlOverlay() { + if (_qmlElement) { + _qmlElement->deleteLater(); + _qmlElement = nullptr; + } +} + +void QmlOverlay::setProperties(const QScriptValue& properties) { + Overlay2D::setProperties(properties); + auto bounds = _bounds; + DependencyManager::get()->executeOnUiThread([=] { + _qmlElement->setX(bounds.left()); + _qmlElement->setY(bounds.top()); + _qmlElement->setWidth(bounds.width()); + _qmlElement->setHeight(bounds.height()); + }); + QMetaObject::invokeMethod(_qmlElement, "updatePropertiesFromScript", Q_ARG(QVariant, properties.toVariant())); +} + +void QmlOverlay::render(RenderArgs* args) { + if (!_qmlElement) { + return; + } + + if (_visible != _qmlElement->isVisible()) { + _qmlElement->setVisible(_visible); + } +} diff --git a/interface/src/ui/overlays/QmlOverlay.h b/interface/src/ui/overlays/QmlOverlay.h new file mode 100644 index 0000000000..75f1a391a3 --- /dev/null +++ b/interface/src/ui/overlays/QmlOverlay.h @@ -0,0 +1,41 @@ +// +// Created by Bradley Austin Davis on 2016/01/27 +// Copyright 2013-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_QmlOverlay_h +#define hifi_QmlOverlay_h + +#include + +#include +#include "Overlay2D.h" + +class QQuickItem; + +class QmlOverlay : public Overlay2D { + Q_OBJECT + +public: + QmlOverlay(const QUrl& url); + QmlOverlay(const QUrl& url, const QmlOverlay* textOverlay); + ~QmlOverlay(); + + // Cannot fetch properties from QML based overlays due to race conditions + bool supportsGetProperty() const override { return false; } + + void setProperties(const QScriptValue& properties) override; + void render(RenderArgs* args) override; + +private: + void buildQmlElement(const QUrl& url); + +protected: + QQuickItem* _qmlElement{ nullptr }; +}; + + +#endif // hifi_QmlOverlay_h diff --git a/interface/src/ui/overlays/RectangleOverlay.cpp b/interface/src/ui/overlays/RectangleOverlay.cpp new file mode 100644 index 0000000000..6974fe3eff --- /dev/null +++ b/interface/src/ui/overlays/RectangleOverlay.cpp @@ -0,0 +1,21 @@ +// +// Created by Bradley Austin Davis on 2016/01/27 +// Copyright 2013-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 +// + +#include "RectangleOverlay.h" + +QString const RectangleOverlay::TYPE = "rectangle"; +QUrl const RectangleOverlay::URL = "hifi/overlays/RectangleOverlay.qml"; + +RectangleOverlay::RectangleOverlay() : QmlOverlay(URL) {} + +RectangleOverlay::RectangleOverlay(const RectangleOverlay* rectangleOverlay) + : QmlOverlay(URL, rectangleOverlay) { } + +RectangleOverlay* RectangleOverlay::createClone() const { + return new RectangleOverlay(this); +} diff --git a/interface/src/ui/overlays/RectangleOverlay.h b/interface/src/ui/overlays/RectangleOverlay.h new file mode 100644 index 0000000000..06e2fb228c --- /dev/null +++ b/interface/src/ui/overlays/RectangleOverlay.h @@ -0,0 +1,27 @@ +// +// Created by Bradley Austin Davis on 2016/01/27 +// Copyright 2013-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_RectangleOverlay_h +#define hifi_RectangleOverlay_h + +#include "QmlOverlay.h" + +class RectangleOverlay : public QmlOverlay { +public: + static QString const TYPE; + virtual QString getType() const { return TYPE; } + static QUrl const URL; + + RectangleOverlay(); + RectangleOverlay(const RectangleOverlay* RectangleOverlay); + + virtual RectangleOverlay* createClone() const; +}; + + +#endif // hifi_RectangleOverlay_h diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 6926e9b241..c1cbdc0502 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -24,216 +24,21 @@ #include "Application.h" #include "text/FontFamilies.h" -#define TEXT_OVERLAY_PROPERTY(type, name, initialValue) \ - Q_PROPERTY(type name READ name WRITE set##name NOTIFY name##Changed) \ -public: \ - type name() { return _##name; }; \ - void set##name(const type& name) { \ - if (name != _##name) { \ - _##name = name; \ - emit name##Changed(); \ - } \ - } \ -private: \ - type _##name{ initialValue }; - - -class TextOverlayElement : public QQuickItem { - Q_OBJECT - HIFI_QML_DECL -private: - TEXT_OVERLAY_PROPERTY(QString, text, "") - TEXT_OVERLAY_PROPERTY(QString, fontFamily, SANS_FONT_FAMILY) - TEXT_OVERLAY_PROPERTY(QString, textColor, "#ffffffff") - TEXT_OVERLAY_PROPERTY(QString, backgroundColor, "#B2000000") - TEXT_OVERLAY_PROPERTY(qreal, fontSize, 18) - TEXT_OVERLAY_PROPERTY(qreal, lineHeight, 18) - TEXT_OVERLAY_PROPERTY(qreal, leftMargin, 0) - TEXT_OVERLAY_PROPERTY(qreal, topMargin, 0) - -public: - TextOverlayElement(QQuickItem* parent = nullptr) : QQuickItem(parent) { - } - -signals: - void textChanged(); - void fontFamilyChanged(); - void fontSizeChanged(); - void lineHeightChanged(); - void leftMarginChanged(); - void topMarginChanged(); - void textColorChanged(); - void backgroundColorChanged(); -}; - -HIFI_QML_DEF(TextOverlayElement) - -QString toQmlColor(const glm::vec4& v) { - QString templat("#%1%2%3%4"); - return templat. - arg((int)(v.a * 255), 2, 16, QChar('0')). - arg((int)(v.r * 255), 2, 16, QChar('0')). - arg((int)(v.g * 255), 2, 16, QChar('0')). - arg((int)(v.b * 255), 2, 16, QChar('0')); -} - QString const TextOverlay::TYPE = "text"; +QUrl const TextOverlay::URL = "hifi/overlays/TextOverlay.qml"; -TextOverlay::TextOverlay() : - _backgroundColor(DEFAULT_BACKGROUND_COLOR), - _backgroundAlpha(DEFAULT_BACKGROUND_ALPHA), - _leftMargin(DEFAULT_MARGIN), - _topMargin(DEFAULT_MARGIN), - _fontSize(DEFAULT_FONTSIZE) -{ - qApp->postLambdaEvent([=] { - static std::once_flag once; - std::call_once(once, [] { - TextOverlayElement::registerType(); - }); - auto offscreenUi = DependencyManager::get(); - TextOverlayElement::show([=](QQmlContext* context, QObject* object) { - _qmlElement = static_cast(object); - }); - }); - while (!_qmlElement) { - QThread::msleep(1); - } +TextOverlay::TextOverlay() : QmlOverlay(URL) { } + +TextOverlay::TextOverlay(const TextOverlay* textOverlay) + : QmlOverlay(URL, textOverlay) { } -TextOverlay::TextOverlay(const TextOverlay* textOverlay) : - Overlay2D(textOverlay), - _text(textOverlay->_text), - _backgroundColor(textOverlay->_backgroundColor), - _backgroundAlpha(textOverlay->_backgroundAlpha), - _leftMargin(textOverlay->_leftMargin), - _topMargin(textOverlay->_topMargin), - _fontSize(textOverlay->_fontSize) -{ - qApp->postLambdaEvent([=] { - auto offscreenUi = DependencyManager::get(); - TextOverlayElement::show([this](QQmlContext* context, QObject* object) { - _qmlElement = static_cast(object); - }); - }); - while (!_qmlElement) { - QThread::msleep(1); - } -} - -TextOverlay::~TextOverlay() { - if (_qmlElement) { - _qmlElement->deleteLater(); - } -} - -xColor TextOverlay::getBackgroundColor() { - if (_colorPulse == 0.0f) { - return _backgroundColor; - } - - float pulseLevel = updatePulse(); - xColor result = _backgroundColor; - if (_colorPulse < 0.0f) { - result.red *= (1.0f - pulseLevel); - result.green *= (1.0f - pulseLevel); - result.blue *= (1.0f - pulseLevel); - } else { - result.red *= pulseLevel; - result.green *= pulseLevel; - result.blue *= pulseLevel; - } - return result; -} - -void TextOverlay::render(RenderArgs* args) { - if (!_qmlElement) { - return; - } - if (_visible != _qmlElement->isVisible()) { - _qmlElement->setVisible(_visible); - } -} - - -void TextOverlay::setProperties(const QScriptValue& properties) { - Overlay2D::setProperties(properties); - _qmlElement->setX(_bounds.left()); - _qmlElement->setY(_bounds.top()); - _qmlElement->setWidth(_bounds.width()); - _qmlElement->setHeight(_bounds.height()); - _qmlElement->settextColor(toQmlColor(vec4(toGlm(_color), _alpha))); - QScriptValue font = properties.property("font"); - if (font.isObject()) { - if (font.property("size").isValid()) { - setFontSize(font.property("size").toInt32()); - } - QFont font(_qmlElement->fontFamily()); - font.setPixelSize(_qmlElement->fontSize()); - QFontMetrics fm(font); - _qmlElement->setlineHeight(fm.lineSpacing() * 1.2); - } - - QScriptValue text = properties.property("text"); - if (text.isValid()) { - setText(text.toVariant().toString()); - } - - QScriptValue backgroundColor = properties.property("backgroundColor"); - if (backgroundColor.isValid()) { - QScriptValue red = backgroundColor.property("red"); - QScriptValue green = backgroundColor.property("green"); - QScriptValue blue = backgroundColor.property("blue"); - if (red.isValid() && green.isValid() && blue.isValid()) { - _backgroundColor.red = red.toVariant().toInt(); - _backgroundColor.green = green.toVariant().toInt(); - _backgroundColor.blue = blue.toVariant().toInt(); - } - } - - if (properties.property("backgroundAlpha").isValid()) { - _backgroundAlpha = properties.property("backgroundAlpha").toVariant().toFloat(); - } - _qmlElement->setbackgroundColor(toQmlColor(vec4(toGlm(_backgroundColor), _backgroundAlpha))); - - if (properties.property("leftMargin").isValid()) { - setLeftMargin(properties.property("leftMargin").toVariant().toInt()); - } - - if (properties.property("topMargin").isValid()) { - setTopMargin(properties.property("topMargin").toVariant().toInt()); - } -} +TextOverlay::~TextOverlay() { } TextOverlay* TextOverlay::createClone() const { return new TextOverlay(this); } -QScriptValue TextOverlay::getProperty(const QString& property) { - if (property == "font") { - QScriptValue font = _scriptEngine->newObject(); - font.setProperty("size", _fontSize); - return font; - } - if (property == "text") { - return _text; - } - if (property == "backgroundColor") { - return xColorToScriptValue(_scriptEngine, _backgroundColor); - } - if (property == "backgroundAlpha") { - return _backgroundAlpha; - } - if (property == "leftMargin") { - return _leftMargin; - } - if (property == "topMargin") { - return _topMargin; - } - - return Overlay2D::getProperty(property); -} - QSizeF TextOverlay::textSize(const QString& text) const { int lines = 1; foreach(QChar c, text) { @@ -241,31 +46,15 @@ QSizeF TextOverlay::textSize(const QString& text) const { ++lines; } } - QFont font(_qmlElement->fontFamily()); - font.setPixelSize(_qmlElement->fontSize()); + QFont font(SANS_FONT_FAMILY); + font.setPixelSize(18); QFontMetrics fm(font); - QSizeF result = QSizeF(fm.width(text), _qmlElement->lineHeight() * lines); + QSizeF result = QSizeF(fm.width(text), 18 * lines); return result; } -void TextOverlay::setFontSize(int fontSize) { - _fontSize = fontSize; - _qmlElement->setfontSize(fontSize); -} -void TextOverlay::setText(const QString& text) { - _text = text; - _qmlElement->settext(text); -} - -void TextOverlay::setLeftMargin(int margin) { - _leftMargin = margin; - _qmlElement->setleftMargin(margin); -} - -void TextOverlay::setTopMargin(int margin) { - _topMargin = margin; - _qmlElement->settopMargin(margin); -} - -#include "TextOverlay.moc" +void TextOverlay::setTopMargin(float margin) {} +void TextOverlay::setLeftMargin(float margin) {} +void TextOverlay::setFontSize(float size) {} +void TextOverlay::setText(const QString& text) {} diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h index a8e6967871..7c6e133ebd 100644 --- a/interface/src/ui/overlays/TextOverlay.h +++ b/interface/src/ui/overlays/TextOverlay.h @@ -11,59 +11,27 @@ #ifndef hifi_TextOverlay_h #define hifi_TextOverlay_h -#include +#include "QmlOverlay.h" -#include - -#include "Overlay2D.h" - -const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 }; -const float DEFAULT_BACKGROUND_ALPHA = 0.7f; -const int DEFAULT_MARGIN = 10; -const int DEFAULT_FONTSIZE = 12; -const int DEFAULT_FONT_WEIGHT = 50; - -class TextOverlayElement; - -class TextOverlay : public Overlay2D { - Q_OBJECT - +class TextOverlay : public QmlOverlay { public: static QString const TYPE; - virtual QString getType() const { return TYPE; } + QString getType() const override { return TYPE; } + static QUrl const URL; + TextOverlay(); TextOverlay(const TextOverlay* textOverlay); ~TextOverlay(); - virtual void render(RenderArgs* args); - // getters - const QString& getText() const { return _text; } - int getLeftMargin() const { return _leftMargin; } - int getTopMargin() const { return _topMargin; } - xColor getBackgroundColor(); - float getBackgroundAlpha() const { return _backgroundAlpha; } - - // setters + void setTopMargin(float margin); + void setLeftMargin(float margin); + void setFontSize(float size); void setText(const QString& text); - void setLeftMargin(int margin); - void setTopMargin(int margin); - void setFontSize(int fontSize); - virtual void setProperties(const QScriptValue& properties); - virtual TextOverlay* createClone() const; - virtual QScriptValue getProperty(const QString& property); + TextOverlay* createClone() const; QSizeF textSize(const QString& text) const; // Pixels - -private: - TextOverlayElement* _qmlElement{ nullptr }; - QString _text; - xColor _backgroundColor; - float _backgroundAlpha; - int _leftMargin; - int _topMargin; - int _fontSize; }; diff --git a/tests/ui/qmlscratch.pro b/tests/ui/qmlscratch.pro index a4e4b33957..d063e673fd 100644 --- a/tests/ui/qmlscratch.pro +++ b/tests/ui/qmlscratch.pro @@ -27,5 +27,6 @@ DISTFILES += \ ../../interface/resources/qml/windows/*.qml \ ../../interface/resources/qml/hifi/*.qml \ ../../interface/resources/qml/hifi/dialogs/*.qml \ - ../../interface/resources/qml/hifi/dialogs/preferences/*.qml + ../../interface/resources/qml/hifi/dialogs/preferences/*.qml \ + ../../interface/resources/qml/hifi/overlays/*.qml From 06071c649320b759e02baf3a483742ddbf86e61c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 27 Jan 2016 16:23:20 -0800 Subject: [PATCH 135/145] Fixing build errors --- interface/src/ui/overlays/ImageOverlay.cpp | 2 +- interface/src/ui/overlays/RectangleOverlay.cpp | 2 +- interface/src/ui/overlays/TextOverlay.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/overlays/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp index b273276dbf..4077fb0ab5 100644 --- a/interface/src/ui/overlays/ImageOverlay.cpp +++ b/interface/src/ui/overlays/ImageOverlay.cpp @@ -17,7 +17,7 @@ QString const ImageOverlay::TYPE = "image"; -QUrl const ImageOverlay::URL = "hifi/overlays/ImageOverlay.qml"; +QUrl const ImageOverlay::URL(QString("hifi/overlays/ImageOverlay.qml")); ImageOverlay::ImageOverlay() : QmlOverlay(URL) { } diff --git a/interface/src/ui/overlays/RectangleOverlay.cpp b/interface/src/ui/overlays/RectangleOverlay.cpp index 6974fe3eff..1487a4cb63 100644 --- a/interface/src/ui/overlays/RectangleOverlay.cpp +++ b/interface/src/ui/overlays/RectangleOverlay.cpp @@ -9,7 +9,7 @@ #include "RectangleOverlay.h" QString const RectangleOverlay::TYPE = "rectangle"; -QUrl const RectangleOverlay::URL = "hifi/overlays/RectangleOverlay.qml"; +QUrl const RectangleOverlay::URL(QString("hifi/overlays/RectangleOverlay.qml")); RectangleOverlay::RectangleOverlay() : QmlOverlay(URL) {} diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index c1cbdc0502..762d855a11 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -25,7 +25,7 @@ #include "text/FontFamilies.h" QString const TextOverlay::TYPE = "text"; -QUrl const TextOverlay::URL = "hifi/overlays/TextOverlay.qml"; +QUrl const TextOverlay::URL(QString("hifi/overlays/TextOverlay.qml")); TextOverlay::TextOverlay() : QmlOverlay(URL) { } From 72b264dcde0eb9f422fb0c6325b49dfdab88a354 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 27 Jan 2016 16:30:15 -0800 Subject: [PATCH 136/145] Ensure toolbar z-order is always below windows --- interface/resources/qml/desktop/Desktop.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index 8c4f73c200..9afae4a3c1 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -25,7 +25,7 @@ FocusScope { readonly property alias zLevels: zLevels QtObject { id: zLevels; - readonly property real normal: 0 + readonly property real normal: 1 // make windows always appear higher than QML overlays and other non-window controls. readonly property real top: 2000 readonly property real modal: 4000 readonly property real menu: 8000 From 6232a83f43e5e46beb2bd0d4467bef831bf635bd Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 29 Jan 2016 13:03:54 +1300 Subject: [PATCH 137/145] Specify minimum OpenGL version in gl library's config Note: Defines minimum OpenGL version as 4.1 in anticipation of Interface soon properly supporting both 4.1 and 4.3 on Windows. --- libraries/gl/src/gl/Config.h | 1 + libraries/gl/src/gl/OpenGLVersionChecker.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libraries/gl/src/gl/Config.h b/libraries/gl/src/gl/Config.h index fe693d8c65..2e42e85122 100644 --- a/libraries/gl/src/gl/Config.h +++ b/libraries/gl/src/gl/Config.h @@ -19,6 +19,7 @@ #define GPU_LEGACY 0 #define GPU_CORE_41 410 #define GPU_CORE_43 430 +#define GPU_CORE_MINIMUM GPU_CORE_41 #if defined(__APPLE__) diff --git a/libraries/gl/src/gl/OpenGLVersionChecker.cpp b/libraries/gl/src/gl/OpenGLVersionChecker.cpp index f1a40bde8d..761c27a302 100644 --- a/libraries/gl/src/gl/OpenGLVersionChecker.cpp +++ b/libraries/gl/src/gl/OpenGLVersionChecker.cpp @@ -14,6 +14,7 @@ #include #include +#include "Config.h" #include "GLWidget.h" OpenGLVersionChecker::OpenGLVersionChecker(int& argc, char** argv) : @@ -35,13 +36,13 @@ bool OpenGLVersionChecker::isValidVersion() { // - major_number.minor_number // - major_number.minor_number.release_number // Reference: https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glGetString.xml - const int MINIMUM_OPENGL_MAJOR_VERSION = 4; - const int MINIMUM_OPENGL_MINOR_VERSION = 1; QStringList versionParts = glVersion.split(QRegularExpression("[\\.\\s]")); int majorNumber = versionParts[0].toInt(); int minorNumber = versionParts[1].toInt(); - valid = (majorNumber > MINIMUM_OPENGL_MAJOR_VERSION - || (majorNumber == MINIMUM_OPENGL_MAJOR_VERSION && minorNumber >= MINIMUM_OPENGL_MINOR_VERSION)); + int minimumMajorNumber = GPU_CORE_MINIMUM / 100; + int minimumMinorNumber = (GPU_CORE_MINIMUM - minimumMajorNumber * 100) / 10; + valid = (majorNumber > minimumMajorNumber + || (majorNumber == minimumMajorNumber && minorNumber >= minimumMinorNumber)); // Prompt user if below minimum if (!valid) { @@ -49,7 +50,7 @@ bool OpenGLVersionChecker::isValidVersion() { messageBox.setWindowTitle("OpenGL Version Too Low"); messageBox.setIcon(QMessageBox::Warning); messageBox.setText(QString().sprintf("Your OpenGL version of %i.%i is lower than the minimum of %i.%i.", - majorNumber, minorNumber, MINIMUM_OPENGL_MAJOR_VERSION, MINIMUM_OPENGL_MINOR_VERSION)); + majorNumber, minorNumber, minimumMajorNumber, minimumMinorNumber)); messageBox.setInformativeText("Press OK to exit; Ignore to continue."); messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Ignore); messageBox.setDefaultButton(QMessageBox::Ok); From 8c19b95ea22867a69883e0c9466df668e5edfcad Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 16:36:28 -0800 Subject: [PATCH 138/145] Fix oversized text, invalid color handling --- .../qml/hifi/overlays/RectangleOverlay.qml | 4 ++-- .../qml/hifi/overlays/TextOverlay.qml | 23 ++++++------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/interface/resources/qml/hifi/overlays/RectangleOverlay.qml b/interface/resources/qml/hifi/overlays/RectangleOverlay.qml index 0ea9b1a2a9..fc4169103a 100644 --- a/interface/resources/qml/hifi/overlays/RectangleOverlay.qml +++ b/interface/resources/qml/hifi/overlays/RectangleOverlay.qml @@ -25,9 +25,9 @@ Overlay { case "y": root.y = value; break; case "visible": root.visible = value; break; case "alpha": rectangle.color.a = value; break; - case "color": rectangle.color = Qt.rgba(value.red, value.green, value.blue, rectangle.color.a); break; + case "color": rectangle.color = Qt.rgba(value.red / 255, value.green / 255, value.blue / 255, rectangle.color.a); break; case "borderAlpha": rectangle.border.color.a = value; break; - case "borderColor": rectangle.border.color = Qt.rgba(value.red, value.green, value.blue, rectangle.border.color.a); break; + case "borderColor": rectangle.border.color = Qt.rgba(value.red / 255, value.green / 255, value.blue / 255, rectangle.border.color.a); break; case "borderWidth": rectangle.border.width = value; break; case "radius": rectangle.radius = value; break; default: console.log("OVERLAY Unhandled rectangle property " + key); diff --git a/interface/resources/qml/hifi/overlays/TextOverlay.qml b/interface/resources/qml/hifi/overlays/TextOverlay.qml index 21b4fddda9..ba5cafdf64 100644 --- a/interface/resources/qml/hifi/overlays/TextOverlay.qml +++ b/interface/resources/qml/hifi/overlays/TextOverlay.qml @@ -23,6 +23,7 @@ Overlay { } } + function updatePropertiesFromScript(properties) { var keys = Object.keys(properties); for (var i = 0; i < keys.length; ++i) { @@ -38,23 +39,13 @@ Overlay { case "margin": textField.anchors.margins = value; break; case "leftMargin": textField.anchors.leftMargin = value; break; case "topMargin": textField.anchors.topMargin = value; break; - case "color": - case "textColor": textField.color = Qt.rgba(value.red, value.green, value.blue, textField.color.a); break; + case "color": // fall through + case "textColor": textField.color = Qt.rgba(value.red / 255, value.green / 255, value.blue / 255, textField.color.a); break; case "text": textField.text = value; break; - case "backgroundAlpha": - if ("object" === typeof(value)) { - console.log("OVERLAY Unexpected object for alpha"); - dumpObject(value) - } else { - background.color.a = value; break; - } - break - case "backgroundColor": background.color = Qt.rgba(value.red, value.green, value.blue, background.color.a); break; - case "font": if (typeof(value) === "Object") { - console.log("Font object"); - dumpObject(value) - } - break; + case "backgroundAlpha": background.color = Qt.rgba(background.color.r, background.color.g, background.color.b, value); break; + case "backgroundColor": background.color = Qt.rgba(value.red / 255, value.green / 255, value.blue / 255, background.color.a); break; + case "font": textField.font.pixelSize = value.size; break; + case "lineHeight": textField.lineHeight = value; break; default: console.log("OVERLAY text unhandled property " + key); } From 5b2e739ef3e3d184368af0209e6782c0270f330c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 16:39:40 -0800 Subject: [PATCH 139/145] Fixing warning --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0bd0031740..14e0ea2a6d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -406,6 +406,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : _entityClipboard(new EntityTree()), _lastQueriedTime(usecTimestampNow()), _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)), + _previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION), _fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES), _scaleMirror(1.0f), _rotateMirror(0.0f), @@ -416,8 +417,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : _aboutToQuit(false), _notifiedPacketVersionMismatchThisDomain(false), _maxOctreePPS(maxOctreePacketsPerSecond.get()), - _lastFaceTrackerUpdate(0), - _previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION) + _lastFaceTrackerUpdate(0) { thread()->setObjectName("Main Thread"); From ab56765ebd4cc297c6af21f0b0f457626126d1fc Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 17:52:22 -0800 Subject: [PATCH 140/145] Add titles to windows --- .../resources/qml/windows/DefaultFrame.qml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/windows/DefaultFrame.qml b/interface/resources/qml/windows/DefaultFrame.qml index fc54a1b1a2..505e653940 100644 --- a/interface/resources/qml/windows/DefaultFrame.qml +++ b/interface/resources/qml/windows/DefaultFrame.qml @@ -20,12 +20,8 @@ Frame { Row { id: controlsRow - anchors.right: parent.right - anchors.top: parent.top - anchors.rightMargin: iconSize - anchors.topMargin: iconSize / 2 + anchors { right: parent.right; top: parent.top; rightMargin: iconSize; topMargin: iconSize / 2; } spacing: iconSize / 4 - FontAwesome { visible: false text: "\uf08d" @@ -54,6 +50,18 @@ Frame { } } } + + Text { + id: titleText + anchors { left: parent.left; leftMargin: iconSize; right: controlsRow.left; rightMargin: iconSize; top: parent.top; topMargin: iconSize / 2; } + text: window.title + elide: Text.ElideRight + font.bold: true + color: window.focus ? "white" : "gray" + style: Text.Outline; + styleColor: "black" + } } + } From afd3ddf534612029cc5f5593a145ccf3676dc3f0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 21:17:05 -0800 Subject: [PATCH 141/145] Cleaning up message box --- .../resources/qml/dialogs/MessageDialog.qml | 148 +++--------------- .../messageDialog/MessageDialogButton.qml | 12 ++ tests/ui/qmlscratch.pro | 1 + 3 files changed, 33 insertions(+), 128 deletions(-) create mode 100644 interface/resources/qml/dialogs/messageDialog/MessageDialogButton.qml diff --git a/interface/resources/qml/dialogs/MessageDialog.qml b/interface/resources/qml/dialogs/MessageDialog.qml index 35efd4d0d1..ca00da1aa3 100644 --- a/interface/resources/qml/dialogs/MessageDialog.qml +++ b/interface/resources/qml/dialogs/MessageDialog.qml @@ -5,6 +5,7 @@ import QtQuick.Dialogs 1.2 as OriginalDialogs import "../controls" import "../styles" import "../windows" +import "messageDialog" // FIXME respect default button functionality ModalWindow { @@ -126,126 +127,23 @@ ModalWindow { onHeightChanged: d.resize(); onWidthChanged: d.resize(); layoutDirection: Qt.RightToLeft anchors { bottom: details.top; right: parent.right; margins: d.spacing * 2; bottomMargin: 0 } - Button { - id: okButton - text: qsTr("OK") - focus: root.defaultButton === OriginalDialogs.StandardButton.Ok - onClicked: root.click(OriginalDialogs.StandardButton.Ok) - visible: root.buttons & OriginalDialogs.StandardButton.Ok - - } - Button { - id: openButton - text: qsTr("Open") - focus: root.defaultButton === OriginalDialogs.StandardButton.Open - onClicked: root.click(OriginalDialogs.StandardButton.Open) - visible: root.buttons & OriginalDialogs.StandardButton.Open - } - Button { - id: saveButton - text: qsTr("Save") - focus: root.defaultButton === OriginalDialogs.StandardButton.Save - onClicked: root.click(OriginalDialogs.StandardButton.Save) - visible: root.buttons & OriginalDialogs.StandardButton.Save - } - Button { - id: saveAllButton - text: qsTr("Save All") - focus: root.defaultButton === OriginalDialogs.StandardButton.SaveAll - onClicked: root.click(OriginalDialogs.StandardButton.SaveAll) - visible: root.buttons & OriginalDialogs.StandardButton.SaveAll - } - Button { - id: retryButton - text: qsTr("Retry") - focus: root.defaultButton === OriginalDialogs.StandardButton.Retry - onClicked: root.click(OriginalDialogs.StandardButton.Retry) - visible: root.buttons & OriginalDialogs.StandardButton.Retry - } - Button { - id: ignoreButton - text: qsTr("Ignore") - focus: root.defaultButton === OriginalDialogs.StandardButton.Ignore - onClicked: root.click(OriginalDialogs.StandardButton.Ignore) - visible: root.buttons & OriginalDialogs.StandardButton.Ignore - } - Button { - id: applyButton - text: qsTr("Apply") - focus: root.defaultButton === OriginalDialogs.StandardButton.Apply - onClicked: root.click(OriginalDialogs.StandardButton.Apply) - visible: root.buttons & OriginalDialogs.StandardButton.Apply - } - Button { - id: yesButton - text: qsTr("Yes") - focus: root.defaultButton === OriginalDialogs.StandardButton.Yes - onClicked: root.click(OriginalDialogs.StandardButton.Yes) - visible: root.buttons & OriginalDialogs.StandardButton.Yes - } - Button { - id: yesAllButton - text: qsTr("Yes to All") - focus: root.defaultButton === OriginalDialogs.StandardButton.YesToAll - onClicked: root.click(OriginalDialogs.StandardButton.YesToAll) - visible: root.buttons & OriginalDialogs.StandardButton.YesToAll - } - Button { - id: noButton - text: qsTr("No") - focus: root.defaultButton === OriginalDialogs.StandardButton.No - onClicked: root.click(OriginalDialogs.StandardButton.No) - visible: root.buttons & OriginalDialogs.StandardButton.No - } - Button { - id: noAllButton - text: qsTr("No to All") - focus: root.defaultButton === OriginalDialogs.StandardButton.NoToAll - onClicked: root.click(OriginalDialogs.StandardButton.NoToAll) - visible: root.buttons & OriginalDialogs.StandardButton.NoToAll - } - Button { - id: discardButton - text: qsTr("Discard") - focus: root.defaultButton === OriginalDialogs.StandardButton.Discard - onClicked: root.click(OriginalDialogs.StandardButton.Discard) - visible: root.buttons & OriginalDialogs.StandardButton.Discard - } - Button { - id: resetButton - text: qsTr("Reset") - focus: root.defaultButton === OriginalDialogs.StandardButton.Reset - onClicked: root.click(OriginalDialogs.StandardButton.Reset) - visible: root.buttons & OriginalDialogs.StandardButton.Reset - } - Button { - id: restoreDefaultsButton - text: qsTr("Restore Defaults") - focus: root.defaultButton === OriginalDialogs.StandardButton.RestoreDefaults - onClicked: root.click(OriginalDialogs.StandardButton.RestoreDefaults) - visible: root.buttons & OriginalDialogs.StandardButton.RestoreDefaults - } - Button { - id: cancelButton - text: qsTr("Cancel") - focus: root.defaultButton === OriginalDialogs.StandardButton.Cancel - onClicked: root.click(OriginalDialogs.StandardButton.Cancel) - visible: root.buttons & OriginalDialogs.StandardButton.Cancel - } - Button { - id: abortButton - text: qsTr("Abort") - focus: root.defaultButton === OriginalDialogs.StandardButton.Abort - onClicked: root.click(OriginalDialogs.StandardButton.Abort) - visible: root.buttons & OriginalDialogs.StandardButton.Abort - } - Button { - id: closeButton - text: qsTr("Close") - focus: root.defaultButton === OriginalDialogs.StandardButton.Close - onClicked: root.click(OriginalDialogs.StandardButton.Close) - visible: root.buttons & OriginalDialogs.StandardButton.Close - } + MessageDialogButton { dialog: root; text: qsTr("OK"); button: OriginalDialogs.StandardButton.Ok; } + MessageDialogButton { dialog: root; text: qsTr("Open"); button: OriginalDialogs.StandardButton.Open; } + MessageDialogButton { dialog: root; text: qsTr("Save"); button: OriginalDialogs.StandardButton.Save; } + MessageDialogButton { dialog: root; text: qsTr("Save All"); button: OriginalDialogs.StandardButton.SaveAll; } + MessageDialogButton { dialog: root; text: qsTr("Retry"); button: OriginalDialogs.StandardButton.Retry; } + MessageDialogButton { dialog: root; text: qsTr("Ignore"); button: OriginalDialogs.StandardButton.Ignore; } + MessageDialogButton { dialog: root; text: qsTr("Apply"); button: OriginalDialogs.StandardButton.Apply; } + MessageDialogButton { dialog: root; text: qsTr("Yes"); button: OriginalDialogs.StandardButton.Yes; } + MessageDialogButton { dialog: root; text: qsTr("Yes to All"); button: OriginalDialogs.StandardButton.YesToAll; } + MessageDialogButton { dialog: root; text: qsTr("No"); button: OriginalDialogs.StandardButton.No; } + MessageDialogButton { dialog: root; text: qsTr("No to All"); button: OriginalDialogs.StandardButton.NoToAll; } + MessageDialogButton { dialog: root; text: qsTr("Discard"); button: OriginalDialogs.StandardButton.Discard; } + MessageDialogButton { dialog: root; text: qsTr("Reset"); button: OriginalDialogs.StandardButton.Reset; } + MessageDialogButton { dialog: root; text: qsTr("Restore Defaults"); button: OriginalDialogs.StandardButton.RestoreDefaults; } + MessageDialogButton { dialog: root; text: qsTr("Cancel"); button: OriginalDialogs.StandardButton.Cancel; } + MessageDialogButton { dialog: root; text: qsTr("Abort"); button: OriginalDialogs.StandardButton.Abort; } + MessageDialogButton { dialog: root; text: qsTr("Close"); button: OriginalDialogs.StandardButton.Close; } Button { id: moreButton text: qsTr("Show Details...") @@ -253,13 +151,7 @@ ModalWindow { } visible: detailedText && detailedText.length > 0 } - Button { - id: helpButton - text: qsTr("Help") - focus: root.defaultButton === OriginalDialogs.StandardButton.Help - onClicked: root.click(OriginalDialogs.StandardButton.Help) - visible: root.buttons & OriginalDialogs.StandardButton.Help - } + MessageDialogButton { dialog: root; text: qsTr("Help"); button: OriginalDialogs.StandardButton.Help; } } Item { @@ -328,7 +220,7 @@ ModalWindow { case Qt.Key_Enter: case Qt.Key_Return: event.accepted = true - root.click(OriginalDialogs.StandardButton.Ok) + root.click(root.defaultButton) break } } diff --git a/interface/resources/qml/dialogs/messageDialog/MessageDialogButton.qml b/interface/resources/qml/dialogs/messageDialog/MessageDialogButton.qml new file mode 100644 index 0000000000..2bcb3d1f29 --- /dev/null +++ b/interface/resources/qml/dialogs/messageDialog/MessageDialogButton.qml @@ -0,0 +1,12 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.2 +import QtQuick.Dialogs 1.2 + +Button { + property var dialog; + property int button: StandardButton.NoButton; + + focus: dialog.defaultButton === button + onClicked: dialog.click(button) + visible: dialog.buttons & button +} diff --git a/tests/ui/qmlscratch.pro b/tests/ui/qmlscratch.pro index a4e4b33957..68175382b0 100644 --- a/tests/ui/qmlscratch.pro +++ b/tests/ui/qmlscratch.pro @@ -21,6 +21,7 @@ DISTFILES += \ ../../interface/resources/qml/dialogs/*.qml \ ../../interface/resources/qml/dialogs/fileDialog/*.qml \ ../../interface/resources/qml/dialogs/preferences/*.qml \ + ../../interface/resources/qml/dialogs/messageDialog/*.qml \ ../../interface/resources/qml/desktop/*.qml \ ../../interface/resources/qml/menus/*.qml \ ../../interface/resources/qml/styles/*.qml \ From 35211b7475c2ad7089d0e2c472fbb7b419650fc3 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 21:18:14 -0800 Subject: [PATCH 142/145] Add titles to modal dialogs, move z-order debug display to bottom of window --- interface/resources/qml/windows/Frame.qml | 2 +- interface/resources/qml/windows/ModalFrame.qml | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/windows/Frame.qml b/interface/resources/qml/windows/Frame.qml index cbcf1a77f6..3cbc31fce6 100644 --- a/interface/resources/qml/windows/Frame.qml +++ b/interface/resources/qml/windows/Frame.qml @@ -25,7 +25,7 @@ Item { id: debugZ visible: DebugQML text: window ? "Z: " + window.z : "" - y: -height + y: window.height + 4 } function deltaSize(dx, dy) { diff --git a/interface/resources/qml/windows/ModalFrame.qml b/interface/resources/qml/windows/ModalFrame.qml index 135a27c647..09dbf04b5c 100644 --- a/interface/resources/qml/windows/ModalFrame.qml +++ b/interface/resources/qml/windows/ModalFrame.qml @@ -13,5 +13,16 @@ Frame { color: "#7f7f7f7f"; radius: 3; } + + Text { + y: -implicitHeight - iconSize / 2 + text: window.title + elide: Text.ElideRight + font.bold: true + color: window.focus ? "white" : "gray" + style: Text.Outline; + styleColor: "black" + } + } From c80193635bc694a7628b42a9c9d02ca96cacfa6d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 21:19:21 -0800 Subject: [PATCH 143/145] Update input dialog to support choice selection --- interface/resources/qml/desktop/Desktop.qml | 6 +- .../resources/qml/dialogs/QueryDialog.qml | 25 ++++- libraries/ui/src/OffscreenUi.cpp | 102 +++++++++++++----- libraries/ui/src/OffscreenUi.h | 22 ++-- 4 files changed, 115 insertions(+), 40 deletions(-) diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index b610dbf73c..5bef1cb516 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -252,9 +252,9 @@ FocusScope { return messageDialogBuilder.createObject(desktop, properties); } - Component { id: queryDialogBuilder; QueryDialog { } } - function queryBox(properties) { - return queryDialogBuilder.createObject(desktop, properties); + Component { id: inputDialogBuilder; QueryDialog { } } + function inputDialog(properties) { + return inputDialogBuilder.createObject(desktop, properties); } Component { id: fileDialogBuilder; FileDialog { } } diff --git a/interface/resources/qml/dialogs/QueryDialog.qml b/interface/resources/qml/dialogs/QueryDialog.qml index 52fde34271..159bb95b5d 100644 --- a/interface/resources/qml/dialogs/QueryDialog.qml +++ b/interface/resources/qml/dialogs/QueryDialog.qml @@ -16,9 +16,17 @@ ModalWindow { signal selected(var result); signal canceled(); - property alias result: textResult.text + property var items; + property alias label: mainTextContainer.text + property var result; + // FIXME not current honored + property var current; + + // For text boxes property alias placeholderText: textResult.placeholderText - property alias text: mainTextContainer.text + + // For combo boxes + property bool editable: true; Rectangle { clip: true @@ -55,10 +63,20 @@ ModalWindow { anchors { top: mainTextContainer.bottom; bottom: buttons.top; left: parent.left; right: parent.right; margins: d.spacing } // FIXME make a text field type that can be bound to a history for autocompletion TextField { - focus: true id: textResult + focus: items ? false : true + visible: items ? false : true anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter } } + + VrControls.ComboBox { + id: comboBox + focus: items ? true : false + visible: items ? true : false + anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter } + model: items ? items : [] + } + } Flow { @@ -86,6 +104,7 @@ ModalWindow { text: qsTr("OK") shortcut: Qt.Key_Return onTriggered: { + root.result = items ? comboBox.currentText : textResult.text root.selected(root.result); root.destroy(); } diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index f399cd95a1..8e52507243 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -199,19 +199,7 @@ private slots: } }; -QMessageBox::StandardButton OffscreenUi::messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { - if (QThread::currentThread() != thread()) { - QMessageBox::StandardButton result = QMessageBox::StandardButton::NoButton; - QMetaObject::invokeMethod(this, "messageBox", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(QMessageBox::StandardButton, result), - Q_ARG(QMessageBox::Icon, icon), - Q_ARG(QString, title), - Q_ARG(QString, text), - Q_ARG(QMessageBox::StandardButtons, buttons), - Q_ARG(QMessageBox::StandardButton, defaultButton)); - return result; - } - +QQuickItem* OffscreenUi::createMessageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { QVariantMap map; map.insert("title", title); map.insert("text", text); @@ -225,12 +213,34 @@ QMessageBox::StandardButton OffscreenUi::messageBox(QMessageBox::Icon icon, cons if (!invokeResult) { qWarning() << "Failed to create message box"; - return QMessageBox::StandardButton::NoButton; + return nullptr; + } + return qvariant_cast(result); +} + +QMessageBox::StandardButton OffscreenUi::waitForMessageBoxResult(QQuickItem* messageBox) { + if (!messageBox) { + return QMessageBox::NoButton; } - QMessageBox::StandardButton resultButton = MessageBoxListener(qvariant_cast(result)).waitForButtonResult(); - qDebug() << "Message box got a result of " << resultButton; - return resultButton; + return MessageBoxListener(messageBox).waitForButtonResult(); +} + + +QMessageBox::StandardButton OffscreenUi::messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) { + if (QThread::currentThread() != thread()) { + QMessageBox::StandardButton result = QMessageBox::StandardButton::NoButton; + QMetaObject::invokeMethod(this, "messageBox", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QMessageBox::StandardButton, result), + Q_ARG(QMessageBox::Icon, icon), + Q_ARG(QString, title), + Q_ARG(QString, text), + Q_ARG(QMessageBox::StandardButtons, buttons), + Q_ARG(QMessageBox::StandardButton, defaultButton)); + return result; + } + + return waitForMessageBoxResult(createMessageBox(icon, title, text, buttons, defaultButton)); } QMessageBox::StandardButton OffscreenUi::critical(const QString& title, const QString& text, @@ -273,6 +283,7 @@ private slots: // FIXME many input parameters currently ignored QString OffscreenUi::getText(void* ignored, const QString & title, const QString & label, QLineEdit::EchoMode mode, const QString & text, bool * ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints) { + if (ok) { *ok = false; } QVariant result = DependencyManager::get()->inputDialog(title, label, text).toString(); if (ok && result.isValid()) { *ok = true; @@ -280,35 +291,70 @@ QString OffscreenUi::getText(void* ignored, const QString & title, const QString return result.toString(); } +// FIXME many input parameters currently ignored +QString OffscreenUi::getItem(void *ignored, const QString & title, const QString & label, const QStringList & items, int current, bool editable, bool * ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints) { + if (ok) { + *ok = false; + } -QVariant OffscreenUi::inputDialog(const QString& query, const QString& placeholderText, const QString& currentValue) { + auto offscreenUi = DependencyManager::get(); + auto inputDialog = offscreenUi->createInputDialog(title, label, current); + if (!inputDialog) { + return QString(); + } + inputDialog->setProperty("items", items); + inputDialog->setProperty("editable", editable); + + QVariant result = offscreenUi->waitForInputDialogResult(inputDialog); + if (!result.isValid()) { + return QString(); + } + + if (ok) { + *ok = true; + } + return result.toString(); +} + +QVariant OffscreenUi::inputDialog(const QString& title, const QString& label, const QVariant& current) { if (QThread::currentThread() != thread()) { QVariant result; - QMetaObject::invokeMethod(this, "queryBox", Qt::BlockingQueuedConnection, + QMetaObject::invokeMethod(this, "inputDialog", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QVariant, result), - Q_ARG(QString, query), - Q_ARG(QString, placeholderText), - Q_ARG(QString, currentValue)); + Q_ARG(QString, title), + Q_ARG(QString, label), + Q_ARG(QVariant, current)); return result; } + return waitForInputDialogResult(createInputDialog(title, label, current)); +} + + +QQuickItem* OffscreenUi::createInputDialog(const QString& title, const QString& label, const QVariant& current) { QVariantMap map; - map.insert("text", query); - map.insert("placeholderText", placeholderText); - map.insert("result", currentValue); + map.insert("title", title); + map.insert("label", label); + map.insert("current", current); QVariant result; - bool invokeResult = QMetaObject::invokeMethod(_desktop, "queryBox", + bool invokeResult = QMetaObject::invokeMethod(_desktop, "inputDialog", Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, QVariant::fromValue(map))); if (!invokeResult) { qWarning() << "Failed to create message box"; - return QVariant(); + return nullptr; } - return InputDialogListener(qvariant_cast(result)).waitForResult(); + return qvariant_cast(result); } +QVariant OffscreenUi::waitForInputDialogResult(QQuickItem* inputDialog) { + if (!inputDialog) { + return QVariant(); + } + return InputDialogListener(inputDialog).waitForResult(); +} bool OffscreenUi::navigationFocused() { return offscreenFlags->isNavigationFocused(); diff --git a/libraries/ui/src/OffscreenUi.h b/libraries/ui/src/OffscreenUi.h index 8ad6641e06..ec5ba433cc 100644 --- a/libraries/ui/src/OffscreenUi.h +++ b/libraries/ui/src/OffscreenUi.h @@ -42,6 +42,13 @@ public: QQuickItem* getToolWindow(); + // Message box compatibility + Q_INVOKABLE QMessageBox::StandardButton messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton); + // Must be called from the main thread + QQuickItem* createMessageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton); + // Must be called from the main thread + QMessageBox::StandardButton waitForMessageBoxResult(QQuickItem* messageBox); + /// Same design as QMessageBox::critical(), will block, returns result static QMessageBox::StandardButton critical(void* ignored, const QString& title, const QString& text, QMessageBox::StandardButtons buttons = QMessageBox::Ok, @@ -80,18 +87,21 @@ public: QMessageBox::StandardButtons buttons = QMessageBox::Ok, QMessageBox::StandardButton defaultButton = QMessageBox::NoButton); - Q_INVOKABLE QMessageBox::StandardButton messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton); - Q_INVOKABLE QVariant inputDialog(const QString& query, const QString& placeholderText = QString(), const QString& currentValue = QString()); + // file dialog compatibility Q_INVOKABLE QString fileOpenDialog(const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0); - - // FIXME implement - static QVariant query(const QString& query, const QString& placeholderText = QString(), const QString& currentValue = QString()); - // Compatibility with QFileDialog::getOpenFileName static QString getOpenFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0); + + // input dialog compatibility + Q_INVOKABLE QVariant inputDialog(const QString& title, const QString& label = QString(), const QVariant& current = QVariant()); + QQuickItem* createInputDialog(const QString& title, const QString& label, const QVariant& current); + QVariant waitForInputDialogResult(QQuickItem* inputDialog); + // Compatibility with QInputDialog::getText static QString getText(void* ignored, const QString & title, const QString & label, QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(), bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone); + // Compatibility with QInputDialog::getItem + static QString getItem(void *ignored, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone); private: QQuickItem* _desktop { nullptr }; From 5b1971907c2a6cf438975a0698fc9a25f94ec182 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 28 Jan 2016 21:20:43 -0800 Subject: [PATCH 144/145] Move bookmarks to QML only dialogs --- interface/src/Bookmarks.cpp | 44 +++++++++++++++---------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/interface/src/Bookmarks.cpp b/interface/src/Bookmarks.cpp index 896a50acca..0a885493e3 100644 --- a/interface/src/Bookmarks.cpp +++ b/interface/src/Bookmarks.cpp @@ -20,12 +20,14 @@ #include #include +#include #include "MainWindow.h" #include "Menu.h" #include "InterfaceLogging.h" #include "Bookmarks.h" +#include Bookmarks::Bookmarks() { _bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + BOOKMARKS_FILENAME; @@ -104,18 +106,13 @@ void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) { } void Bookmarks::bookmarkLocation() { - QInputDialog bookmarkLocationDialog(qApp->getWindow()); - bookmarkLocationDialog.setWindowTitle("Bookmark Location"); - bookmarkLocationDialog.setLabelText("Name:"); - bookmarkLocationDialog.setInputMode(QInputDialog::TextInput); - bookmarkLocationDialog.resize(400, 200); - - if (bookmarkLocationDialog.exec() == QDialog::Rejected) { + bool ok = false; + auto bookmarkName = OffscreenUi::getText(nullptr, "Bookmark Location", "Name:", QLineEdit::Normal, QString(), &ok); + if (!ok) { return; } - QString bookmarkName = bookmarkLocationDialog.textValue().trimmed(); - bookmarkName = bookmarkName.replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " "); + bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " "); if (bookmarkName.length() == 0) { return; } @@ -125,13 +122,14 @@ void Bookmarks::bookmarkLocation() { Menu* menubar = Menu::getInstance(); if (contains(bookmarkName)) { - QMessageBox duplicateBookmarkMessage; - duplicateBookmarkMessage.setIcon(QMessageBox::Warning); - duplicateBookmarkMessage.setText("The bookmark name you entered already exists in your list."); - duplicateBookmarkMessage.setInformativeText("Would you like to overwrite it?"); - duplicateBookmarkMessage.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - duplicateBookmarkMessage.setDefaultButton(QMessageBox::Yes); - if (duplicateBookmarkMessage.exec() == QMessageBox::No) { + auto offscreenUi = DependencyManager::get(); + auto duplicateBookmarkMessage = offscreenUi->createMessageBox(QMessageBox::Warning, "Duplicate Bookmark", + "The bookmark name you entered already exists in your list.", + QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); + duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?"); + + auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage); + if (result != QMessageBox::Yes) { return; } removeLocationFromMenu(menubar, bookmarkName); @@ -157,19 +155,13 @@ void Bookmarks::deleteBookmark() { bookmarkList.append(menuItems[i]->text()); } - QInputDialog deleteBookmarkDialog(qApp->getWindow()); - deleteBookmarkDialog.setWindowTitle("Delete Bookmark"); - deleteBookmarkDialog.setLabelText("Select the bookmark to delete"); - deleteBookmarkDialog.resize(400, 400); - deleteBookmarkDialog.setOption(QInputDialog::UseListViewForComboBoxItems); - deleteBookmarkDialog.setComboBoxItems(bookmarkList); - deleteBookmarkDialog.setOkButtonText("Delete"); - - if (deleteBookmarkDialog.exec() == QDialog::Rejected) { + bool ok = false; + auto bookmarkName = OffscreenUi::getItem(nullptr, "Delete Bookmark", "Select the bookmark to delete", bookmarkList, 0, false, &ok); + if (!ok) { return; } - QString bookmarkName = deleteBookmarkDialog.textValue().trimmed(); + bookmarkName = bookmarkName.trimmed(); if (bookmarkName.length() == 0) { return; } From c4794dd0d551a82f4bdd09ed22f7e577be21b5b2 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 29 Jan 2016 13:41:43 -0800 Subject: [PATCH 145/145] Fix entity properties HTML --- examples/html/entityProperties.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index b9038ccacc..fc585a374e 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -1103,10 +1103,13 @@
B
+
Skybox URL
+
+