From 5da43257f70ce701e09fb54e4d760357d9173969 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Fri, 23 Jun 2017 10:52:23 -0700 Subject: [PATCH 01/47] Fix for eye direction when no look at targets are present. --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b9e3b48903..c138230893 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4180,7 +4180,7 @@ void Application::updateMyAvatarLookAtPosition() { lookAtSpot = transformPoint(worldHeadMat, glm::vec3(0.0f, 0.0f, TREE_SCALE)); } else { lookAtSpot = myAvatar->getHead()->getEyePosition() + - (myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, TREE_SCALE)); + (myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE)); } } From b1b26bc8a52094f9d6dae502718f896e0072d41e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 25 Jun 2017 02:34:58 -0700 Subject: [PATCH 02/47] Fix toolbar button mouse click when they were added via the tablet scripting interface --- libraries/ui/src/ui/TabletScriptingInterface.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 8b3dc342e2..1e426dd8f0 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -623,7 +623,8 @@ TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) { auto toolbarProxy = DependencyManager::get()->getSystemToolbarProxy(); if (toolbarProxy) { // copy properties from tablet button proxy to toolbar button proxy. - toolbarProxy->addButton(tabletButtonProxy->getProperties()); + auto toolbarButtonProxy = toolbarProxy->addButton(tabletButtonProxy->getProperties()); + tabletButtonProxy->setToolbarButtonProxy(toolbarButtonProxy); } } return tabletButtonProxy.data(); From e5f5d3835cdfb13ed9fe3fadbb86d1faa7c808dd Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Mon, 26 Jun 2017 08:08:52 -0700 Subject: [PATCH 03/47] Fix reverbTest script --- scripts/developer/utilities/tools/reverbTest.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/developer/utilities/tools/reverbTest.js b/scripts/developer/utilities/tools/reverbTest.js index a7a6bad9d7..8d83140ecd 100644 --- a/scripts/developer/utilities/tools/reverbTest.js +++ b/scripts/developer/utilities/tools/reverbTest.js @@ -35,8 +35,8 @@ var audioOptions = new AudioEffectOptions({ wetDryMix: 50, }); -AudioDevice.setReverbOptions(audioOptions); -AudioDevice.setReverb(true); +Audio.setReverbOptions(audioOptions); +Audio.setReverb(true); print("Reverb is ON."); var panel = new Panel(10, 160); @@ -66,7 +66,7 @@ var parameters = [ ] function setter(name) { - return function(value) { audioOptions[name] = value; AudioDevice.setReverbOptions(audioOptions); } + return function(value) { audioOptions[name] = value; Audio.setReverbOptions(audioOptions); } } function getter(name) { @@ -89,7 +89,7 @@ Controller.mouseReleaseEvent.connect(function(event) { return panel.mouseRelease function scriptEnding() { panel.destroy(); - AudioDevice.setReverb(false); + Audio.setReverb(false); print("Reverb is OFF."); } Script.scriptEnding.connect(scriptEnding); From 2260c0965c55c8e15ef3477ca385d65dc7a9f26b Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Mon, 26 Jun 2017 08:28:29 -0700 Subject: [PATCH 04/47] Fix halfDuplex script --- scripts/tutorials/halfDuplex.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/scripts/tutorials/halfDuplex.js b/scripts/tutorials/halfDuplex.js index e1ed132233..d4a993ae06 100644 --- a/scripts/tutorials/halfDuplex.js +++ b/scripts/tutorials/halfDuplex.js @@ -20,7 +20,7 @@ var averageLoudness = 0.0; var AVERAGING_TIME = 0.9; var LOUDNESS_THRESHOLD = 100; -var HYSTERESIS_GAP = 1.41; // 3db gap +var HYSTERESIS_GAP = 1.41; // 3dB gap var MICROPHONE_DISPLAY_NAME = "Microphone"; var debug = false; @@ -54,17 +54,13 @@ Script.update.connect(function () { print("Muted!"); } isMuted = true; - if (!AudioDevice.getMuted()) { - AudioDevice.toggleMute(); - } + Audio.muted = true; } else if (isMuted && (averageLoudness < LOUDNESS_THRESHOLD)) { if (debug) { print("UnMuted!"); } isMuted = false; - if (AudioDevice.getMuted()) { - AudioDevice.toggleMute(); - } + Audio.muted = false; } }); From d7416434bf9c869e26a96c5503252665ca98bc84 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 26 Jun 2017 11:38:24 -0700 Subject: [PATCH 05/47] added tool to visualize avatar-animation.json using graphviz. --- tools/avatar-json-to-dot.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tools/avatar-json-to-dot.js diff --git a/tools/avatar-json-to-dot.js b/tools/avatar-json-to-dot.js new file mode 100644 index 0000000000..fcd75a99c1 --- /dev/null +++ b/tools/avatar-json-to-dot.js @@ -0,0 +1,27 @@ +// usage: +// node avatar-json-to-dot.js /path/to/avatar-animaton.json > out.dot +// +// Then if you have graphviz installed you can run the following command to generate a png. +// dot -Tpng out.dot > out.png + +var fs = require('fs'); +var filename = process.argv[2]; + +function dumpNodes(node) { + node.children.forEach(function (child) { + console.log(' ' + node.id + ' -> ' + child.id + ';'); + dumpNodes(child); + }); +} + +fs.readFile(filename, 'utf8', function (err, data) { + if (err) { + console.log('error opening ' + filename + ', err = ' + err); + } else { + var graph = JSON.parse(data); + console.log('digraph graphname {'); + console.log(' rankdir = "LR";'); + dumpNodes(graph.root); + console.log('}'); + } +}); From 8602d57a577c8344962bffd4d2a11a272ac17561 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 26 Jun 2017 14:09:10 -0700 Subject: [PATCH 06/47] Eliminated to wiggle while pucks are enabled. * Added new anim node AnimDefaultPose * AnimNodeLoader was changed to support the addition of the AnimDefaultPose node * Edited default avatar-animation.json to insert an AnimOverlay and AnimDefaultPose between the IK node and the rest of the "underPose". * Rig uses this to fade in default pose for the toes when the hip/feet puck are active. This effectively deadens the toe animations, without effecting the hand animations. * Also, the rig was changed to use the LimitCenter solution when the feet are enabled but the hips are not. --- .../resources/avatar/avatar-animation.json | 21 ++++------- libraries/animation/src/AnimDefaultPose.cpp | 34 ++++++++++++++++++ libraries/animation/src/AnimDefaultPose.h | 36 +++++++++++++++++++ libraries/animation/src/AnimNode.h | 1 + libraries/animation/src/AnimNodeLoader.cpp | 13 ++++++- libraries/animation/src/AnimOverlay.cpp | 15 ++++++++ libraries/animation/src/AnimOverlay.h | 2 ++ libraries/animation/src/Rig.cpp | 20 +++++++++-- 8 files changed, 124 insertions(+), 18 deletions(-) create mode 100644 libraries/animation/src/AnimDefaultPose.cpp create mode 100644 libraries/animation/src/AnimDefaultPose.h diff --git a/interface/resources/avatar/avatar-animation.json b/interface/resources/avatar/avatar-animation.json index 018987b58b..a493d8e9af 100644 --- a/interface/resources/avatar/avatar-animation.json +++ b/interface/resources/avatar/avatar-animation.json @@ -150,28 +150,19 @@ "children": [] }, { - "id": "hipsManipulatorOverlay", + "id": "defaultPoseOverlay", "type": "overlay", "data": { "alpha": 0.0, - "boneSet": "hipsOnly" + "alphaVar": "defaultPoseOverlayAlpha", + "boneSet": "fullBody", + "boneSetVar": "defaultPoseOverlayBoneSet" }, "children": [ { - "id": "hipsManipulator", - "type": "manipulator", + "id": "defaultPose", + "type": "defaultPose", "data": { - "alpha": 0.0, - "alphaVar": "hipsManipulatorAlpha", - "joints": [ - { - "jointName": "Hips", - "rotationType": "absolute", - "translationType": "absolute", - "rotationVar": "hipsManipulatorRotation", - "translationVar": "hipsManipulatorPosition" - } - ] }, "children": [] }, diff --git a/libraries/animation/src/AnimDefaultPose.cpp b/libraries/animation/src/AnimDefaultPose.cpp new file mode 100644 index 0000000000..70bcbe7c21 --- /dev/null +++ b/libraries/animation/src/AnimDefaultPose.cpp @@ -0,0 +1,34 @@ +// +// AnimDefaultPose.cpp +// +// Created by Anthony J. Thibault on 6/26/17. +// Copyright (c) 2017 High Fidelity, Inc. All rights reserved. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "AnimDefaultPose.h" + +AnimDefaultPose::AnimDefaultPose(const QString& id) : + AnimNode(AnimNode::Type::DefaultPose, id) +{ + +} + +AnimDefaultPose::~AnimDefaultPose() { + +} + +const AnimPoseVec& AnimDefaultPose::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) { + if (_skeleton) { + _poses = _skeleton->getRelativeDefaultPoses(); + } else { + _poses.clear(); + } + return _poses; +} + +const AnimPoseVec& AnimDefaultPose::getPosesInternal() const { + return _poses; +} diff --git a/libraries/animation/src/AnimDefaultPose.h b/libraries/animation/src/AnimDefaultPose.h new file mode 100644 index 0000000000..eefefac7af --- /dev/null +++ b/libraries/animation/src/AnimDefaultPose.h @@ -0,0 +1,36 @@ +// +// AnimDefaultPose.h +// +// Created by Anthony J. Thibault on 6/26/17. +// Copyright (c) 2017 High Fidelity, Inc. All rights reserved. +// +// 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_AnimDefaultPose_h +#define hifi_AnimDefaultPose_h + +#include +#include "AnimNode.h" + +// Always returns the default pose of the current skeleton. + +class AnimDefaultPose : public AnimNode { +public: + AnimDefaultPose(const QString& id); + virtual ~AnimDefaultPose() override; + + virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) override; +protected: + // for AnimDebugDraw rendering + virtual const AnimPoseVec& getPosesInternal() const override; + + AnimPoseVec _poses; + + // no copies + AnimDefaultPose(const AnimDefaultPose&) = delete; + AnimDefaultPose& operator=(const AnimDefaultPose&) = delete; +}; + +#endif // hifi_AnimDefaultPose_h diff --git a/libraries/animation/src/AnimNode.h b/libraries/animation/src/AnimNode.h index 10db38f42e..6d9d35b19b 100644 --- a/libraries/animation/src/AnimNode.h +++ b/libraries/animation/src/AnimNode.h @@ -44,6 +44,7 @@ public: StateMachine, Manipulator, InverseKinematics, + DefaultPose, NumTypes }; using Pointer = std::shared_ptr; diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index 2a1978127d..33f3d72756 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -23,6 +23,7 @@ #include "AnimStateMachine.h" #include "AnimManipulator.h" #include "AnimInverseKinematics.h" +#include "AnimDefaultPose.h" using NodeLoaderFunc = AnimNode::Pointer (*)(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); using NodeProcessFunc = bool (*)(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); @@ -35,6 +36,7 @@ static AnimNode::Pointer loadOverlayNode(const QJsonObject& jsonObj, const QStri static AnimNode::Pointer loadStateMachineNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); static AnimNode::Pointer loadManipulatorNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); static AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); +static AnimNode::Pointer loadDefaultPoseNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); // called after children have been loaded // returns node on success, nullptr on failure. @@ -50,6 +52,7 @@ static const char* animNodeTypeToString(AnimNode::Type type) { case AnimNode::Type::StateMachine: return "stateMachine"; case AnimNode::Type::Manipulator: return "manipulator"; case AnimNode::Type::InverseKinematics: return "inverseKinematics"; + case AnimNode::Type::DefaultPose: return "defaultPose"; case AnimNode::Type::NumTypes: return nullptr; }; return nullptr; @@ -109,6 +112,7 @@ static NodeLoaderFunc animNodeTypeToLoaderFunc(AnimNode::Type type) { case AnimNode::Type::StateMachine: return loadStateMachineNode; case AnimNode::Type::Manipulator: return loadManipulatorNode; case AnimNode::Type::InverseKinematics: return loadInverseKinematicsNode; + case AnimNode::Type::DefaultPose: return loadDefaultPoseNode; case AnimNode::Type::NumTypes: return nullptr; }; return nullptr; @@ -123,6 +127,7 @@ static NodeProcessFunc animNodeTypeToProcessFunc(AnimNode::Type type) { case AnimNode::Type::StateMachine: return processStateMachineNode; case AnimNode::Type::Manipulator: return processDoNothing; case AnimNode::Type::InverseKinematics: return processDoNothing; + case AnimNode::Type::DefaultPose: return processDoNothing; case AnimNode::Type::NumTypes: return nullptr; }; return nullptr; @@ -347,7 +352,8 @@ static const char* boneSetStrings[AnimOverlay::NumBoneSets] = { "empty", "leftHand", "rightHand", - "hipsOnly" + "hipsOnly", + "bothFeet" }; static AnimOverlay::BoneSet stringToBoneSetEnum(const QString& str) { @@ -517,6 +523,11 @@ AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QS return node; } +static AnimNode::Pointer loadDefaultPoseNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { + auto node = std::make_shared(id); + return node; +} + void buildChildMap(std::map& map, AnimNode::Pointer node) { for (int i = 0; i < (int)node->getChildCount(); ++i) { map.insert(std::pair(node->getChild(i)->getID(), i)); diff --git a/libraries/animation/src/AnimOverlay.cpp b/libraries/animation/src/AnimOverlay.cpp index e086413dde..10594af20a 100644 --- a/libraries/animation/src/AnimOverlay.cpp +++ b/libraries/animation/src/AnimOverlay.cpp @@ -35,6 +35,7 @@ void AnimOverlay::buildBoneSet(BoneSet boneSet) { case LeftHandBoneSet: buildLeftHandBoneSet(); break; case RightHandBoneSet: buildRightHandBoneSet(); break; case HipsOnlyBoneSet: buildHipsOnlyBoneSet(); break; + case BothFeetBoneSet: buildBothFeetBoneSet(); break; default: case EmptyBoneSet: buildEmptyBoneSet(); break; } @@ -196,6 +197,20 @@ void AnimOverlay::buildHipsOnlyBoneSet() { _boneSetVec[hipsJoint] = 1.0f; } +void AnimOverlay::buildBothFeetBoneSet() { + assert(_skeleton); + buildEmptyBoneSet(); + int rightFoot = _skeleton->nameToJointIndex("RightFoot"); + for_each_child_joint(_skeleton, rightFoot, [&](int i) { + _boneSetVec[i] = 1.0f; + }); + int leftFoot = _skeleton->nameToJointIndex("LeftFoot"); + for_each_child_joint(_skeleton, leftFoot, [&](int i) { + _boneSetVec[i] = 1.0f; + }); +} + + // for AnimDebugDraw rendering const AnimPoseVec& AnimOverlay::getPosesInternal() const { return _poses; diff --git a/libraries/animation/src/AnimOverlay.h b/libraries/animation/src/AnimOverlay.h index ed9439feb7..8b6e1529fc 100644 --- a/libraries/animation/src/AnimOverlay.h +++ b/libraries/animation/src/AnimOverlay.h @@ -38,6 +38,7 @@ public: LeftHandBoneSet, RightHandBoneSet, HipsOnlyBoneSet, + BothFeetBoneSet, NumBoneSets }; @@ -77,6 +78,7 @@ public: void buildLeftHandBoneSet(); void buildRightHandBoneSet(); void buildHipsOnlyBoneSet(); + void buildBothFeetBoneSet(); // no copies AnimOverlay(const AnimOverlay&) = delete; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 3f63f226e7..3d04b0b26f 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -27,6 +27,7 @@ #include "AnimationLogging.h" #include "AnimClip.h" #include "AnimInverseKinematics.h" +#include "AnimOverlay.h" #include "AnimSkeleton.h" #include "AnimUtil.h" #include "IKTarget.h" @@ -1459,13 +1460,28 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo updateFeet(leftFootEnabled, rightFootEnabled, params.controllerPoses[ControllerType_LeftFoot], params.controllerPoses[ControllerType_RightFoot]); - if (hipsEnabled) { + // if the hips or the feet are being controlled. + if (hipsEnabled || rightFootEnabled || leftFootEnabled) { + // for more predictable IK solve from the center of the joint limits, not from the underpose _animVars.set("solutionSource", (int)AnimInverseKinematics::SolutionSource::RelaxToLimitCenterPoses); + + // replace the feet animation with the default pose, this is to prevent unexpected toe wiggling. + _animVars.set("defaultPoseOverlayAlpha", 1.0f); + _animVars.set("defaultPoseOverlayBoneSet", (int)AnimOverlay::BothFeetBoneSet); + } else { + // augment the IK with the underPose. + _animVars.set("solutionSource", (int)AnimInverseKinematics::SolutionSource::RelaxToUnderPoses); + + // feet should follow source animation + _animVars.unset("defaultPoseOverlayAlpha"); + _animVars.unset("defaultPoseOverlayBoneSet"); + } + + if (hipsEnabled) { _animVars.set("hipsType", (int)IKTarget::Type::RotationAndPosition); _animVars.set("hipsPosition", params.controllerPoses[ControllerType_Hips].trans()); _animVars.set("hipsRotation", params.controllerPoses[ControllerType_Hips].rot()); } else { - _animVars.set("solutionSource", (int)AnimInverseKinematics::SolutionSource::RelaxToUnderPoses); _animVars.set("hipsType", (int)IKTarget::Type::Unknown); } From bf7da71eafcbe89124c220e0be166e6c96bed940 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 26 Jun 2017 15:07:22 -0700 Subject: [PATCH 07/47] use QEventLoop and a timer for a less CPU using sleep + event-processing --- libraries/script-engine/src/ScriptEngine.cpp | 29 +++++++++----------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index d9b41bb55d..017124af1c 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1067,24 +1067,21 @@ void ScriptEngine::run() { // on shutdown and stop... so we want to loop and sleep until we've spent our time in // purgatory, constantly checking to see if our script was asked to end bool processedEvents = false; - while (!_isFinished && clock::now() < sleepUntil) { - - { - PROFILE_RANGE(script, "processEvents-sleep"); - QCoreApplication::processEvents(); // before we sleep again, give events a chance to process + if (!_isFinished) { + PROFILE_RANGE(script, "processEvents-sleep"); + std::chrono::milliseconds sleepFor = + std::chrono::duration_cast(sleepUntil - clock::now()); + if (sleepFor > std::chrono::milliseconds(0)) { + QEventLoop loop; + QTimer timer; + timer.setSingleShot(true); + connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + timer.start(sleepFor); + loop.exec(); + } else { + QCoreApplication::processEvents(); } processedEvents = true; - - // If after processing events, we're past due, exit asap - if (clock::now() >= sleepUntil) { - break; - } - - // We only want to sleep a small amount so that any pending events (like timers or invokeMethod events) - // will be able to process quickly. - static const int SMALL_SLEEP_AMOUNT = 100; - auto smallSleepUntil = clock::now() + static_cast(SMALL_SLEEP_AMOUNT); - std::this_thread::sleep_until(smallSleepUntil); } PROFILE_RANGE(script, "ScriptMainLoop"); From 4f672f93d20ed87aec24b57f3fd37c3a6d2e76d8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 26 Jun 2017 16:03:39 -0700 Subject: [PATCH 08/47] avoid cast that isn't always available --- libraries/script-engine/src/ScriptEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 017124af1c..81b815a34b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1076,7 +1076,7 @@ void ScriptEngine::run() { QTimer timer; timer.setSingleShot(true); connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); - timer.start(sleepFor); + timer.start(sleepFor.count()); loop.exec(); } else { QCoreApplication::processEvents(); From 2814c945821edc60f14d692df69812896407e9c2 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 26 Jun 2017 17:43:51 -0700 Subject: [PATCH 09/47] Hips should no longer waggle when feet are active --- libraries/animation/src/AnimInverseKinematics.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 3e948a4f5b..5d98357ea3 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -870,9 +870,9 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars float scaleFactor = ((offsetLength - MIN_HIPS_OFFSET_LENGTH) / offsetLength); glm::vec3 hipsOffset = scaleFactor * _hipsOffset; if (_hipsParentIndex == -1) { - _relativePoses[_hipsIndex].trans() = underPoses[_hipsIndex].trans() + hipsOffset; + _relativePoses[_hipsIndex].trans() = _relativePoses[_hipsIndex].trans() + hipsOffset; } else { - auto absHipsPose = _skeleton->getAbsolutePose(_hipsIndex, underPoses); + auto absHipsPose = _skeleton->getAbsolutePose(_hipsIndex, _relativePoses); absHipsPose.trans() += hipsOffset; _relativePoses[_hipsIndex] = _skeleton->getAbsolutePose(_hipsParentIndex, _relativePoses).inverse() * absHipsPose; } @@ -1732,6 +1732,10 @@ void AnimInverseKinematics::initRelativePosesFromSolutionSource(SolutionSource s break; case SolutionSource::RelaxToLimitCenterPoses: blendToPoses(_limitCenterPoses, underPoses, RELAX_BLEND_FACTOR); + // special case for hips: copy over hips pose whether or not IK is enabled. + if (_hipsIndex >= 0 && _hipsIndex < _relativePoses.size()) { + _relativePoses[_hipsIndex] = _limitCenterPoses[_hipsIndex]; + } break; case SolutionSource::PreviousSolution: // do nothing... _relativePoses is already the previous solution From d4122cff5ad20cf5b9db00d62f2e72c3cc9b4a61 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 27 Jun 2017 11:29:08 -0700 Subject: [PATCH 10/47] warning fix --- libraries/animation/src/AnimInverseKinematics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 5d98357ea3..d7076a443e 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -1733,7 +1733,7 @@ void AnimInverseKinematics::initRelativePosesFromSolutionSource(SolutionSource s case SolutionSource::RelaxToLimitCenterPoses: blendToPoses(_limitCenterPoses, underPoses, RELAX_BLEND_FACTOR); // special case for hips: copy over hips pose whether or not IK is enabled. - if (_hipsIndex >= 0 && _hipsIndex < _relativePoses.size()) { + if (_hipsIndex >= 0 && _hipsIndex < (int)_relativePoses.size()) { _relativePoses[_hipsIndex] = _limitCenterPoses[_hipsIndex]; } break; From dcdf07191b87f2bcaf4ee6ace7a9dd4b90fb2e69 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Tue, 27 Jun 2017 11:29:44 -0700 Subject: [PATCH 11/47] Fast acosf() using polynomial approximation --- libraries/shared/src/AudioHelpers.h | 42 +++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/libraries/shared/src/AudioHelpers.h b/libraries/shared/src/AudioHelpers.h index b43764ef5d..d75733e678 100644 --- a/libraries/shared/src/AudioHelpers.h +++ b/libraries/shared/src/AudioHelpers.h @@ -66,6 +66,48 @@ static inline float fastExp2f(float x) { return x * xi.f; } +// +// on x86 architecture, assume that SSE2 is present +// +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__x86_64__) + +#include +// inline sqrtss, without requiring /fp:fast +static inline float fastSqrtf(float x) { + return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(x))); +} + +#else + +static inline float fastSqrtf(float x) { + return sqrtf(x); +} + +#endif + +// +// for -1 <= x <= 1, returns acos(x) +// otherwise, returns NaN +// +// abs |error| < 7e-5, smooth +// +static inline float fastAcosf(float x) { + + union { float f; int32_t i; } xi = { x }; + + int32_t sign = xi.i & 0x80000000; + xi.i ^= sign; // fabs(x) + + // compute sqrt(1-x) in parallel + float r = fastSqrtf(1.0f - xi.f); + + // polynomial for acos(x)/sqrt(1-x) over x=[0,1] + xi.f = ((-0.0198439236f * xi.f + 0.0762021306f) * xi.f + -0.212940971f) * xi.f + 1.57079633f; + + xi.f *= r; + return (sign ? 3.141592654f - xi.f : xi.f); +} + // // Quantize a non-negative gain value to the nearest 0.5dB, and pack to a byte. // From 241231c00ceb173cb3139fe78b5db60fde4b8872 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Tue, 27 Jun 2017 22:14:58 +0200 Subject: [PATCH 12/47] file lists works, but not initial yet --- .../qml/dialogs/TabletFileDialog.qml | 50 ++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/dialogs/TabletFileDialog.qml b/interface/resources/qml/dialogs/TabletFileDialog.qml index 5e33663436..f77cc7c78a 100644 --- a/interface/resources/qml/dialogs/TabletFileDialog.qml +++ b/interface/resources/qml/dialogs/TabletFileDialog.qml @@ -25,11 +25,14 @@ import "fileDialog" //FIXME implement shortcuts for favorite location TabletModalWindow { id: root + anchors.fill: parent width: parent.width height: parent.height HifiConstants { id: hifi } + property var filesModel: ListModel { } + Settings { category: "FileDialog" property alias width: root.width @@ -250,7 +253,9 @@ TabletModalWindow { } currentSelectionUrl = helper.pathToUrl(fileTableView.model.get(row).filePath); - currentSelectionIsFolder = fileTableView.model.isFolder(row); + currentSelectionIsFolder = fileTableView.model !== filesModel ? + fileTableView.model.isFolder(row) : + fileTableModel.isFolder(row); if (root.selectDirectory || !currentSelectionIsFolder) { currentSelection.text = capitalizeDrive(helper.urlToPath(currentSelectionUrl)); } else { @@ -288,7 +293,7 @@ TabletModalWindow { } onFolderChanged: { - fileTableModel.update(); // Update once the data from the folder change is available. + refreshTimer.start() } function getItem(index, field) { @@ -328,7 +333,20 @@ TabletModalWindow { } } - ListModel { + Timer { + id: refreshTimer + interval: 100 + repeat: false + running: false + onTriggered: fileTableModel.update() + } + + Component { + id: filesModelBuilder + ListModel { } + } + + QtObject { id: fileTableModel // FolderListModel has a couple of problems: @@ -380,7 +398,11 @@ TabletModalWindow { if (row === -1) { return false; } - return get(row).fileIsDir; + return filesModel.get(row).fileIsDir; + } + + function get(row) { + return filesModel.get(row) } function update() { @@ -398,7 +420,8 @@ TabletModalWindow { rows = 0, i; - clear(); + console.log("dialog.qml updating") + var newFilesModel = filesModelBuilder.createObject(root); comparisonFunction = sortOrder === Qt.AscendingOrder ? function(a, b) { return a < b; } @@ -420,7 +443,7 @@ TabletModalWindow { while (lower < upper) { middle = Math.floor((lower + upper) / 2); var lessThan; - if (comparisonFunction(sortValue, get(middle)[sortField])) { + if (comparisonFunction(sortValue, newFilesModel.get(middle)[sortField])) { lessThan = true; upper = middle; } else { @@ -429,7 +452,7 @@ TabletModalWindow { } } - insert(lower, { + newFilesModel.insert(lower, { fileName: fileName, fileModified: (fileIsDir ? new Date(0) : model.getItem(i, "fileModified")), fileSize: model.getItem(i, "fileSize"), @@ -440,6 +463,7 @@ TabletModalWindow { rows++; } + filesModel = newFilesModel; d.clearSelection(); } @@ -467,7 +491,7 @@ TabletModalWindow { sortIndicatorOrder: Qt.AscendingOrder sortIndicatorVisible: true - model: fileTableModel + model: filesModel function updateSort() { model.sortOrder = sortIndicatorOrder; @@ -559,11 +583,12 @@ TabletModalWindow { } function navigateToCurrentRow() { + var currentModel = fileTableView.model !== filesModel ? fileTableView.model : fileTableModel var row = fileTableView.currentRow - var isFolder = model.isFolder(row); - var file = model.get(row).filePath; + var isFolder = currentModel.isFolder(row); + var file = currentModel.get(row).filePath; if (isFolder) { - fileTableView.model.folder = helper.pathToUrl(file); + currentModel.folder = helper.pathToUrl(file); } else { okAction.trigger(); } @@ -578,7 +603,8 @@ TabletModalWindow { var newPrefix = prefix + event.text.toLowerCase(); var matchedIndex = -1; for (var i = 0; i < model.count; ++i) { - var name = model.get(i).fileName.toLowerCase(); + var name = model !== filesModel ? model.get(i).fileName.toLowerCase() : + filesModel.get(i).fileName.toLowerCase(); if (0 === name.indexOf(newPrefix)) { matchedIndex = i; break; From ad970c9f5c8ec1712ecd7974f83086df4d8a3bcb Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Tue, 27 Jun 2017 13:45:18 -0700 Subject: [PATCH 13/47] fast compute of HRTF azimuth --- assignment-client/src/audio/AudioMixerSlave.cpp | 17 +++++++++++------ libraries/audio-client/src/AudioClient.cpp | 17 ++++++++++------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index 2d800c3561..14b4fdea68 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -545,7 +545,6 @@ float computeAzimuth(const AvatarAudioStream& listeningNodeStream, const Positio const glm::vec3& relativePosition) { glm::quat inverseOrientation = glm::inverse(listeningNodeStream.getOrientation()); - // Compute sample delay for the two ears to create phase panning glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; // project the rotated source position vector onto the XZ plane @@ -553,11 +552,17 @@ float computeAzimuth(const AvatarAudioStream& listeningNodeStream, const Positio const float SOURCE_DISTANCE_THRESHOLD = 1e-30f; - if (glm::length2(rotatedSourcePosition) > SOURCE_DISTANCE_THRESHOLD) { + float rotatedSourcePositionLength2 = glm::length2(rotatedSourcePosition); + if (rotatedSourcePositionLength2 > SOURCE_DISTANCE_THRESHOLD) { + // produce an oriented angle about the y-axis - return glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), glm::normalize(rotatedSourcePosition), glm::vec3(0.0f, -1.0f, 0.0f)); - } else { - // there is no distance between listener and source - return no azimuth - return 0; + // return glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), glm::normalize(rotatedSourcePosition), glm::vec3(0.0f, -1.0f, 0.0f)); + glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2)); + float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); + return (direction.x < 0.0f) ? -angle : angle; + + } else { + // no azimuth if they are in same spot + return 0.0f; } } diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index fc54a04a5e..27e70e5f01 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -48,6 +48,7 @@ #include "AudioClientLogging.h" #include "AudioLogging.h" +#include "AudioHelpers.h" #include "AudioClient.h" @@ -1688,23 +1689,25 @@ int AudioClient::calculateNumberOfFrameSamples(int numBytes) const { } float AudioClient::azimuthForSource(const glm::vec3& relativePosition) { - // copied from AudioMixer, more or less glm::quat inverseOrientation = glm::inverse(_orientationGetter()); - // compute sample delay for the 2 ears to create phase panning glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; - // project the rotated source position vector onto x-y plane + // project the rotated source position vector onto the XZ plane rotatedSourcePosition.y = 0.0f; static const float SOURCE_DISTANCE_THRESHOLD = 1e-30f; - if (glm::length2(rotatedSourcePosition) > SOURCE_DISTANCE_THRESHOLD) { + float rotatedSourcePositionLength2 = glm::length2(rotatedSourcePosition); + if (rotatedSourcePositionLength2 > SOURCE_DISTANCE_THRESHOLD) { // produce an oriented angle about the y-axis - return glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), glm::normalize(rotatedSourcePosition), glm::vec3(0.0f, -1.0f, 0.0f)); - } else { - + // return glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), glm::normalize(rotatedSourcePosition), glm::vec3(0.0f, -1.0f, 0.0f)); + glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2)); + float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); + return (direction.x < 0.0f) ? -angle : angle; + + } else { // no azimuth if they are in same spot return 0.0f; } From a00cd425668ac30b92bc3fe8c612da25c3a94830 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Tue, 27 Jun 2017 14:01:28 -0700 Subject: [PATCH 14/47] fast compute of HRTF gain --- assignment-client/src/audio/AudioMixerSlave.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index 14b4fdea68..9cfc659c14 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -497,13 +497,14 @@ float computeGain(const AvatarAudioStream& listeningNodeStream, const Positional // avatar: apply fixed off-axis attenuation to make them quieter as they turn away } else if (!isEcho && (streamToAdd.getType() == PositionalAudioStream::Microphone)) { glm::vec3 rotatedListenerPosition = glm::inverse(streamToAdd.getOrientation()) * relativePosition; - float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), - glm::normalize(rotatedListenerPosition)); + + // float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), glm::normalize(rotatedListenerPosition)); + glm::vec3 direction = glm::normalize(rotatedListenerPosition); + float angleOfDelivery = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); const float MAX_OFF_AXIS_ATTENUATION = 0.2f; const float OFF_AXIS_ATTENUATION_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f; - float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + - (angleOfDelivery * (OFF_AXIS_ATTENUATION_STEP / PI_OVER_TWO)); + float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + (angleOfDelivery * (OFF_AXIS_ATTENUATION_STEP / PI_OVER_TWO)); gain *= offAxisCoefficient; } From 827fa98baaa68448882b1780399410a81a2f7729 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 26 Jun 2017 23:18:21 -0700 Subject: [PATCH 15/47] Fix toolbar button activation states --- scripts/system/audio.js | 12 ++++-------- scripts/system/help.js | 3 ++- scripts/system/marketplaces/marketplaces.js | 12 ++---------- scripts/system/menu.js | 9 ++------- scripts/system/pal.js | 16 ++++++---------- scripts/system/snapshot.js | 10 +++------- 6 files changed, 19 insertions(+), 43 deletions(-) diff --git a/scripts/system/audio.js b/scripts/system/audio.js index cb9589ae9e..0a3471fa81 100644 --- a/scripts/system/audio.js +++ b/scripts/system/audio.js @@ -15,6 +15,7 @@ var TABLET_BUTTON_NAME = "AUDIO"; var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png"; +var AUDIO_QML_SOURCE = "../audio/Audio.qml"; var MUTE_ICONS = { icon: "icons/tablet-icons/mic-mute-i.svg", @@ -34,7 +35,6 @@ function onMuteToggled() { } } -var shouldActivateButton = false; var onAudioScreen = false; function onClicked() { @@ -44,18 +44,14 @@ function onClicked() { } else { var entity = HMD.tabletID; Entities.editEntity(entity, { textures: JSON.stringify({ "tex.close": HOME_BUTTON_TEXTURE }) }); - shouldActivateButton = true; - shouldActivateButton = true; - tablet.loadQMLSource("../audio/Audio.qml"); - onAudioScreen = true; + tablet.loadQMLSource(AUDIO_QML_SOURCE); } } function onScreenChanged(type, url) { + onAudioScreen = (type === "QML" && url === AUDIO_QML_SOURCE); // for toolbar mode: change button to active when window is first openend, false otherwise. - button.editProperties({isActive: shouldActivateButton}); - shouldActivateButton = false; - onAudioScreen = false; + button.editProperties({isActive: onAudioScreen}); } var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); diff --git a/scripts/system/help.js b/scripts/system/help.js index a335b2ef9c..1265a5597b 100644 --- a/scripts/system/help.js +++ b/scripts/system/help.js @@ -40,7 +40,8 @@ } function onScreenChanged(type, url) { - onHelpScreen = false; + onHelpScreen = type === "Web" && url.startsWith("../../../html/tabletHelp.html"); + button.editProperties({ isActive: onHelpScreen }); } button.clicked.connect(onClicked); diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 4d26bcadb6..3be8143830 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -52,17 +52,11 @@ function onMessageBoxClosed(id, button) { Window.messageBoxClosed.connect(onMessageBoxClosed); -var shouldActivateButton = false; var onMarketplaceScreen = false; function showMarketplace() { UserActivityLogger.openedMarketplace(); - - shouldActivateButton = true; - tablet.gotoWebScreen(MARKETPLACE_URL_INITIAL, MARKETPLACES_INJECT_SCRIPT_URL); - onMarketplaceScreen = true; - tablet.webEventReceived.connect(function (message) { if (message === GOTO_DIRECTORY) { @@ -122,7 +116,6 @@ function onClick() { if (onMarketplaceScreen) { // for toolbar-mode: go back to home screen, this will close the window. tablet.gotoHomeScreen(); - onMarketplaceScreen = false; } else { var entity = HMD.tabletID; Entities.editEntity(entity, {textures: JSON.stringify({"tex.close": HOME_BUTTON_TEXTURE})}); @@ -131,10 +124,9 @@ function onClick() { } function onScreenChanged(type, url) { + onMarketplaceScreen = type === "Web" && url === MARKETPLACE_URL_INITIAL // for toolbar mode: change button to active when window is first openend, false otherwise. - marketplaceButton.editProperties({isActive: shouldActivateButton}); - shouldActivateButton = false; - onMarketplaceScreen = false; + marketplaceButton.editProperties({isActive: onMarketplaceScreen}); } marketplaceButton.clicked.connect(onClick); diff --git a/scripts/system/menu.js b/scripts/system/menu.js index 4ad5958144..c7a44d3e48 100644 --- a/scripts/system/menu.js +++ b/scripts/system/menu.js @@ -21,7 +21,6 @@ var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet- sortOrder: 3 }); - var shouldActivateButton = false; var onMenuScreen = false; function onClicked() { @@ -31,17 +30,13 @@ var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet- } else { var entity = HMD.tabletID; Entities.editEntity(entity, {textures: JSON.stringify({"tex.close": HOME_BUTTON_TEXTURE})}); - shouldActivateButton = true; tablet.gotoMenuScreen(); - onMenuScreen = true; } } function onScreenChanged(type, url) { - // for toolbar mode: change button to active when window is first openend, false otherwise. - button.editProperties({isActive: shouldActivateButton}); - shouldActivateButton = false; - onMenuScreen = false; + onMenuScreen = type === "Menu"; + button.editProperties({isActive: onMenuScreen}); } button.clicked.connect(onClicked); diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 0500c13f9b..f7ea4b8f8a 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -40,7 +40,7 @@ var HOVER_TEXTURES = { var UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6}; var SELECTED_COLOR = {red: 0xF3, green: 0x91, blue: 0x29}; var HOVER_COLOR = {red: 0xD0, green: 0xD0, blue: 0xD0}; // almost white for now - +var PAL_QML_SOURCE = "../Pal.qml"; var conserveResources = true; Script.include("/~/system/libraries/controllers.js"); @@ -726,17 +726,14 @@ function tabletVisibilityChanged() { } var onPalScreen = false; -var shouldActivateButton = false; function onTabletButtonClicked() { if (onPalScreen) { // for toolbar-mode: go back to home screen, this will close the window. tablet.gotoHomeScreen(); } else { - shouldActivateButton = true; - tablet.loadQMLSource("../Pal.qml"); + tablet.loadQMLSource(PAL_QML_SOURCE); tablet.tabletShownChanged.connect(tabletVisibilityChanged); - onPalScreen = true; Users.requestsDomainListData = true; populateNearbyUserList(); isWired = true; @@ -764,14 +761,13 @@ function wireEventBridge(on) { } function onTabletScreenChanged(type, url) { - wireEventBridge(shouldActivateButton); + onPalScreen = (type === "QML" && url === PAL_QML_SOURCE); + wireEventBridge(onPalScreen); // for toolbar mode: change button to active when window is first openend, false otherwise. - button.editProperties({isActive: shouldActivateButton}); - shouldActivateButton = false; - onPalScreen = false; + button.editProperties({isActive: onPalScreen}); // disable sphere overlays when not on pal screen. - if (type !== "QML" || url !== "../Pal.qml") { + if (!onPalScreen) { off(); } } diff --git a/scripts/system/snapshot.js b/scripts/system/snapshot.js index 6321c17ded..c60e3a67f7 100644 --- a/scripts/system/snapshot.js +++ b/scripts/system/snapshot.js @@ -377,18 +377,15 @@ function fillImageDataFromPrevious() { var SNAPSHOT_REVIEW_URL = Script.resolvePath("html/SnapshotReview.html"); var isInSnapshotReview = false; -var shouldActivateButton = false; function onButtonClicked() { if (isInSnapshotReview){ // for toolbar-mode: go back to home screen, this will close the window. tablet.gotoHomeScreen(); } else { - shouldActivateButton = true; fillImageDataFromPrevious(); tablet.gotoWebScreen(SNAPSHOT_REVIEW_URL); tablet.webEventReceived.connect(onMessage); HMD.openTablet(); - isInSnapshotReview = true; } } @@ -662,11 +659,10 @@ function maybeDeleteSnapshotStories() { storyIDsToMaybeDelete = []; } function onTabletScreenChanged(type, url) { - button.editProperties({ isActive: shouldActivateButton }); - shouldActivateButton = false; - if (isInSnapshotReview) { + isInSnapshotReview = (type === "Web" && url === SNAPSHOT_REVIEW_URL); + button.editProperties({ isActive: isInSnapshotReview }); + if (!isInSnapshotReview) { tablet.webEventReceived.disconnect(onMessage); - isInSnapshotReview = false; } } function onUsernameChanged() { From 6d0b853668e08249a6baea6da67aef46bdadd97b Mon Sep 17 00:00:00 2001 From: Patrick Manalich Date: Tue, 27 Jun 2017 14:34:01 -0700 Subject: [PATCH 16/47] Comment structure changes for compacting --- interface/src/SecondaryCamera.cpp | 2 +- scripts/system/spectatorCamera.js | 245 +++++++++--------------------- 2 files changed, 77 insertions(+), 170 deletions(-) diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index f6ee8caa61..1b8f8a4577 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -39,7 +39,7 @@ void SecondaryCameraRenderTaskConfig::resetSizeSpectatorCamera(int width, int he resetSize(width, height); } -class BeginSecondaryCameraFrame { // Changes renderContext for our framebuffer and and view. +class BeginSecondaryCameraFrame { // Changes renderContext for our framebuffer and view. glm::vec3 _position{}; glm::quat _orientation{}; float _vFoV{}; diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 5ea9ab3fae..ca5752dd2c 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -1,7 +1,4 @@ "use strict"; -/*jslint vars:true, plusplus:true, forin:true*/ -/*global Tablet, Script, */ -/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ // // spectatorCamera.js // @@ -14,45 +11,39 @@ (function () { // BEGIN LOCAL_SCOPE - // // FUNCTION VAR DECLARATIONS - // var sendToQml, addOrRemoveButton, onTabletScreenChanged, fromQml, onTabletButtonClicked, wireEventBridge, startup, shutdown, registerButtonMappings; - // // Function Name: inFrontOf() // // Description: - // Spectator camera utility functions and variables. - // + // -Returns the position in front of the given "position" argument, where the forward vector is based off + // the "orientation" argument and the amount in front is based off the "distance" argument. function inFrontOf(distance, position, orientation) { return Vec3.sum(position || MyAvatar.position, Vec3.multiply(distance, Quat.getForward(orientation || MyAvatar.orientation))); } - // + + // Function Name: updateRenderFromCamera() // - // Relevant Variables: - // spectatorFrameRenderConfig: The render configuration of the spectator camera - // render job. Controls size. - // beginSpectatorFrameRenderConfig: The render configuration of the spectator camera - // render job. Controls position and orientation. - // viewFinderOverlay: The in-world overlay that displays the spectator camera's view. - // camera: The in-world entity that corresponds to the spectator camera. - // cameraIsDynamic: "false" for now while we figure out why dynamic, parented overlays - // drift with respect to their parent - // lastCameraPosition: Holds the last known camera position - // lastCameraRotation: Holds the last known camera rotation - // - // Arguments: - // None - // // Description: - // The update function for the spectator camera. Modifies the camera's position - // and orientation. + // -The update function for the spectator camera. Modifies the camera's position + // and orientation. // + // Relevant Variables: + // -spectatorFrameRenderConfig: The render configuration of the spectator camera + // render job. Controls size. + // -beginSpectatorFrameRenderConfig: The render configuration of the spectator camera + // render job. Controls position and orientation. + // -viewFinderOverlay: The in-world overlay that displays the spectator camera's view. + // -camera: The in-world entity that corresponds to the spectator camera. + // -cameraIsDynamic: "false" for now while we figure out why dynamic, parented overlays + // drift with respect to their parent. + // -lastCameraPosition: Holds the last known camera position. + // -lastCameraRotation: Holds the last known camera rotation. var spectatorFrameRenderConfig = Render.getConfig("SecondaryCameraFrame"); var beginSpectatorFrameRenderConfig = Render.getConfig("BeginSecondaryCamera"); var viewFinderOverlay = false; @@ -72,37 +63,34 @@ } } - // // Function Name: spectatorCameraOn() - // - // Relevant Variables: - // isUpdateRenderWired: Bool storing whether or not the camera's update - // function is wired. - // vFoV: The vertical field of view of the spectator camera - // nearClipPlaneDistance: The near clip plane distance of the spectator camera (aka "camera") - // farClipPlaneDistance: The far clip plane distance of the spectator camera - // cameraRotation: The rotation of the spectator camera - // cameraPosition: The position of the spectator camera - // glassPaneWidth: The width of the glass pane above the spectator camera that holds the viewFinderOverlay - // viewFinderOverlayDim: The x, y, and z dimensions of the viewFinderOverlay - // - // Arguments: - // None // // Description: - // Call this function to set up the spectator camera and - // spawn the camera entity. + // -Call this function to set up the spectator camera and + // spawn the camera entity. // + // Relevant Variables: + // -isUpdateRenderWired: Bool storing whether or not the camera's update + // function is wired. + // -vFoV: The vertical field of view of the spectator camera. + // -nearClipPlaneDistance: The near clip plane distance of the spectator camera (aka "camera"). + // -farClipPlaneDistance: The far clip plane distance of the spectator camera. + // -cameraRotation: The rotation of the spectator camera. + // -cameraPosition: The position of the spectator camera. + // -glassPaneWidth: The width of the glass pane above the spectator camera that holds the viewFinderOverlay. + // -viewFinderOverlayDim: The x, y, and z dimensions of the viewFinderOverlay. + // -camera: The camera model which is grabbable. + // -viewFinderOverlay: The preview of what the spectator camera is viewing, placed inside the glass pane. var isUpdateRenderWired = false; var vFoV = 45.0; var nearClipPlaneDistance = 0.1; var farClipPlaneDistance = 100.0; var cameraRotation; var cameraPosition; - //The negative y dimension for viewFinderOverlay is necessary for now due to the way Image3DOverlay - // draws textures, but should be looked into at some point. Also the z dimension shouldn't affect - // the overlay since it is an Image3DOverlay so it is set to 0 var glassPaneWidth = 0.16; + // The negative y dimension for viewFinderOverlay is necessary for now due to the way Image3DOverlay + // draws textures, but should be looked into at some point. Also the z dimension shouldn't affect + // the overlay since it is an Image3DOverlay so it is set to 0. var viewFinderOverlayDim = { x: glassPaneWidth, y: -glassPaneWidth, z: 0 }; function spectatorCameraOn() { // Sets the special texture size based on the window it is displayed in, which doesn't include the menu bar @@ -126,7 +114,6 @@ "type": "Model", "userData": "{\"grabbableKey\":{\"grabbable\":true}}" }, true); - // This image3d overlay acts as the camera's preview screen. viewFinderOverlay = Overlays.addOverlay("image3d", { url: "resource://spectatorCameraFrame", emissive: true, @@ -139,19 +126,11 @@ setDisplay(monitorShowsCameraView); } - // // Function Name: spectatorCameraOff() - // - // Relevant Variables: - // None - // - // Arguments: - // None // // Description: - // Call this function to shut down the spectator camera and - // destroy the camera entity. - // + // -Call this function to shut down the spectator camera and + // destroy the camera entity. function spectatorCameraOff() { spectatorFrameRenderConfig.enabled = beginSpectatorFrameRenderConfig.enabled = false; if (isUpdateRenderWired) { @@ -169,22 +148,18 @@ setDisplay(monitorShowsCameraView); } - // // Function Name: addOrRemoveButton() // - // Relevant Variables: - // button: The tablet button. - // buttonName: The name of the button. - // tablet: The tablet instance to be modified. - // showInDesktop: Set to "true" to show the "SPECTATOR" app in desktop mode - // - // Arguments: - // isShuttingDown: Set to "true" if you're calling this function upon script shutdown - // isHMDMode: "true" if user is in HMD; false otherwise - // // Description: - // Used to add or remove the "SPECTATOR" app button from the HUD/tablet + // -Used to add or remove the "SPECTATOR" app button from the HUD/tablet. Set the "isShuttingDown" argument + // to true if you're calling this function upon script shutdown. Set the "isHMDmode" to true if the user is + // in HMD; otherwise set to false. // + // Relevant Variables: + // -button: The tablet button. + // -buttonName: The name of the button. + // -tablet: The tablet instance to be modified. + // -showInDesktop: Set to "true" to show the "SPECTATOR" app in desktop mode. var button = false; var buttonName = "SPECTATOR"; var tablet = null; @@ -208,18 +183,10 @@ } } - // // Function Name: startup() // - // Relevant Variables: - // None - // - // Arguments: - // None - // // Description: - // startup() will be called when the script is loaded. - // + // -startup() will be called when the script is loaded. function startup() { tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); addOrRemoveButton(false, HMD.active); @@ -233,18 +200,14 @@ registerButtonMappings(); } - // // Function Name: wireEventBridge() // - // Relevant Variables: - // hasEventBridge: true/false depending on whether we've already connected the event bridge - // - // Arguments: - // on: Enable or disable the event bridge - // // Description: - // Used to connect/disconnect the script's response to the tablet's "fromQml" signal. + // -Used to connect/disconnect the script's response to the tablet's "fromQml" signal. Set the "on" argument to enable or + // disable to event bridge. // + // Relevant Variables: + // -hasEventBridge: true/false depending on whether we've already connected the event bridge. var hasEventBridge = false; function wireEventBridge(on) { if (on) { @@ -285,22 +248,18 @@ } } - // // Function Name: resizeViewFinderOverlay() // - // Relevant Variables: - // glassPaneRatio: The aspect ratio of the glass pane, currently set as a 16:9 aspect ratio (change if model changes) - // verticalScale: The amount the viewFinderOverlay should be scaled if the window size is vertical - // squareScale: The amount the viewFinderOverlay should be scaled if the window size is not vertical but is more square than the - // glass pane's aspect ratio - // - // Arguments: - // geometryChanged: The signal argument that gives information on how the window changed, including x, y, width, and height - // // Description: - // A function called when the window is moved/resized, which changes the viewFinderOverlay's texture and dimensions to be - // appropriately altered to fit inside the glass pane while not distorting the texture + // -A function called when the window is moved/resized, which changes the viewFinderOverlay's texture and dimensions to be + // appropriately altered to fit inside the glass pane while not distorting the texture. The "geometryChanged" argument gives information + // on how the window changed, including x, y, width, and height. // + // Relevant Variables: + // -glassPaneRatio: The aspect ratio of the glass pane, currently set as a 16:9 aspect ratio (change if model changes). + // -verticalScale: The amount the viewFinderOverlay should be scaled if the window size is vertical. + // -squareScale: The amount the viewFinderOverlay should be scaled if the window size is not vertical but is more square than the + // glass pane's aspect ratio. function resizeViewFinderOverlay(geometryChanged) { var glassPaneRatio = 16 / 9; var verticalScale = 1 / glassPaneRatio; @@ -315,7 +274,7 @@ } // The only way I found to update the viewFinderOverlay without turning the spectator camera on and off is to delete and recreate the - // overlay, which is inefficient but resizing the window shouldn't be performed often + // overlay, which is inefficient but resizing the window shouldn't be performed often Overlays.deleteOverlay(viewFinderOverlay); viewFinderOverlay = Overlays.addOverlay("image3d", { url: "resource://spectatorCameraFrame", @@ -348,20 +307,15 @@ Settings.setValue('spectatorCamera/switchViewFromController', setting); } - // // Function Name: registerButtonMappings() // - // Relevant Variables: - // controllerMappingName: The name of the controller mapping - // controllerMapping: The controller mapping itself - // controllerType: "OculusTouch", "Vive", "Other" - // - // Arguments: - // None - // // Description: - // Updates controller button mappings for Spectator Camera. + // -Updates controller button mappings for Spectator Camera. // + // Relevant Variables: + // -controllerMappingName: The name of the controller mapping. + // -controllerMapping: The controller mapping itself. + // -controllerType: "OculusTouch", "Vive", "Other". var controllerMappingName; var controllerMapping; var controllerType = "Other"; @@ -394,20 +348,15 @@ sendToQml({ method: 'updateControllerMappingCheckbox', setting: switchViewFromController, controller: controllerType }); } - // // Function Name: onTabletButtonClicked() // - // Relevant Variables: - // onSpectatorCameraScreen: true/false depending on whether we're looking at the spectator camera app - // shouldActivateButton: true/false depending on whether we should show the button as white or gray the - // next time we edit the button's properties - // - // Arguments: - // None - // // Description: - // Fired when the Spectator Camera app button is pressed. + // -Fired when the Spectator Camera app button is pressed. // + // Relevant Variables: + // -onSpectatorCameraScreen: true/false depending on whether we're looking at the spectator camera app. + // -shouldActivateButton: true/false depending on whether we should show the button as white or gray the + // next time we edit the button's properties. var onSpectatorCameraScreen = false; var shouldActivateButton = false; function onTabletButtonClicked() { @@ -425,19 +374,11 @@ } } - // // Function Name: onTabletScreenChanged() // - // Relevant Variables: - // None - // - // Arguments: - // type: "Home", "Web", "Menu", "QML", "Closed" - // url: Only valid for Web and QML. - // // Description: - // Called when the TabletScriptingInterface::screenChanged() signal is emitted. - // + // -Called when the TabletScriptingInterface::screenChanged() signal is emitted. The "type" argument can be either the string + // value of "Home", "Web", "Menu", "QML", or "Closed". The "url" argument is only valid for Web and QML. function onTabletScreenChanged(type, url) { wireEventBridge(shouldActivateButton); // for toolbar mode: change button to active when window is first openend, false otherwise. @@ -448,36 +389,20 @@ onSpectatorCameraScreen = false; } - // // Function Name: sendToQml() // - // Relevant Variables: - // None - // - // Arguments: - // message: The message to send to the SpectatorCamera QML. - // Messages are in format "{method, params}", like json-rpc. See also fromQml(). - // // Description: - // Use this function to send a message to the QML (i.e. to change appearances). - // + // -Use this function to send a message to the QML (i.e. to change appearances). The "message" argument is what is sent to + // SpectatorCamera QML in the format "{method, params}", like json-rpc. See also fromQml(). function sendToQml(message) { tablet.sendToQml(message); } - // // Function Name: fromQml() // - // Relevant Variables: - // None - // - // Arguments: - // message: The message sent from the SpectatorCamera QML. - // Messages are in format "{method, params}", like json-rpc. See also sendToQml(). - // // Description: - // Called when a message is received from SpectatorCamera.qml. - // + // -Called when a message is received from SpectatorCamera.qml. The "message" argument is what is sent from the SpectatorCamera QML + // in the format "{method, params}", like json-rpc. See also sendToQml(). function fromQml(message) { switch (message.method) { case 'spectatorCameraOn': @@ -497,18 +422,10 @@ } } - // // Function Name: onHMDChanged() - // - // Relevant Variables: - // None - // - // Arguments: - // isHMDMode: "true" if HMD is on; "false" otherwise // // Description: - // Called from C++ when HMD mode is changed - // + // -Called from C++ when HMD mode is changed. The argument "isHMDMode" should be true if HMD is on; false otherwise. function onHMDChanged(isHMDMode) { setDisplay(monitorShowsCameraView); addOrRemoveButton(false, isHMDMode); @@ -517,18 +434,10 @@ } } - // // Function Name: shutdown() - // - // Relevant Variables: - // None - // - // Arguments: - // None // // Description: - // shutdown() will be called when the script ends (i.e. is stopped). - // + // -shutdown() will be called when the script ends (i.e. is stopped). function shutdown() { spectatorCameraOff(); Window.domainChanged.disconnect(spectatorCameraOff); @@ -540,9 +449,7 @@ controllerMapping.disable(); } - // // These functions will be called when the script is loaded. - // startup(); Script.scriptEnding.connect(shutdown); From 994117b524eb0ad16a55a95393238bafbca185e6 Mon Sep 17 00:00:00 2001 From: Patrick Manalich Date: Tue, 27 Jun 2017 15:08:37 -0700 Subject: [PATCH 17/47] Small comment change to clarify configurations --- scripts/system/spectatorCamera.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index ca5752dd2c..7b60c14575 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -25,8 +25,6 @@ Vec3.multiply(distance, Quat.getForward(orientation || MyAvatar.orientation))); } - - // Function Name: updateRenderFromCamera() // // Description: @@ -35,9 +33,10 @@ // // Relevant Variables: // -spectatorFrameRenderConfig: The render configuration of the spectator camera - // render job. Controls size. + // render job. It controls the rendered texture size of the spectator camera. // -beginSpectatorFrameRenderConfig: The render configuration of the spectator camera - // render job. Controls position and orientation. + // render job. It controls the orientation and position of the secondary camera whose viewport is rendered to + // the texture. // -viewFinderOverlay: The in-world overlay that displays the spectator camera's view. // -camera: The in-world entity that corresponds to the spectator camera. // -cameraIsDynamic: "false" for now while we figure out why dynamic, parented overlays From 1392297da9b2ee5ff22ad90de50bec6c9dcb461a Mon Sep 17 00:00:00 2001 From: Patrick Manalich Date: Tue, 27 Jun 2017 16:50:44 -0700 Subject: [PATCH 18/47] Messing around, howard please refer the commit before this one --- scripts/system/spectatorCamera.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 7b60c14575..6b867d4abc 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -48,6 +48,7 @@ var viewFinderOverlay = false; var camera = false; var cameraIsDynamic = false; + var attachedToggle = false; var lastCameraPosition = false; var lastCameraRotation = false; function updateRenderFromCamera() { @@ -123,6 +124,30 @@ dimensions: viewFinderOverlayDim }); setDisplay(monitorShowsCameraView); + + attachedToggle = Entities.addEntity({ + "color": { + "blue": 0, + "green": 0, + "red": 255 + }, + parentID: camera, + localPosition: { x: 0.1, y: 0, z: -0.05 }, + localRotation: { w: 0.70708787441253662, x: 0, y: 0, z: 0.70708787441253662 }, + "dimensions": { + "x": 0.03, + "y": 0.03, + "z": 0.03 + }, + "queryAACube": { + "scale": 0.052, + "x": -0.026, + "y": -0.026, + "z": -0.026 + }, + "shape": "Cylinder", + "type": "Shape" + }, true); } // Function Name: spectatorCameraOff() @@ -142,8 +167,12 @@ if (viewFinderOverlay) { Overlays.deleteOverlay(viewFinderOverlay); } + if (attachedToggle) { + Entities.deleteEntity(attachedToggle); + } camera = false; viewFinderOverlay = false; + attachedToggle = false; setDisplay(monitorShowsCameraView); } @@ -196,6 +225,7 @@ HMD.displayModeChanged.connect(onHMDChanged); viewFinderOverlay = false; camera = false; + attachedToggle = false; registerButtonMappings(); } From 617e927695bab6bf91adb4522f19768f8e5fd7fc Mon Sep 17 00:00:00 2001 From: Patrick Manalich Date: Tue, 27 Jun 2017 17:13:39 -0700 Subject: [PATCH 19/47] rotation changed to localRotation --- scripts/system/spectatorCamera.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 5ea9ab3fae..685df66ba2 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -132,7 +132,7 @@ emissive: true, parentID: camera, alpha: 1, - rotation: cameraRotation, + localRotation: { x: 0, y: 0, z: 0 }, localPosition: { x: 0.007, y: 0.15, z: -0.005 }, dimensions: viewFinderOverlayDim }); @@ -322,7 +322,7 @@ emissive: true, parentID: camera, alpha: 1, - rotation: cameraRotation, + localRotation: { x: 0, y: 0, z: 0 }, localPosition: { x: 0.007, y: 0.15, z: -0.005 }, dimensions: viewFinderOverlayDim }); From 9417a176a17d5d7e899be8563199c5fac69dcd07 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Tue, 27 Jun 2017 18:10:54 -0700 Subject: [PATCH 20/47] make scripts tree show scripts in directory passed in with --scripts --- interface/src/Application.cpp | 12 ++++++------ interface/src/main.cpp | 10 ++++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9052f082dc..72e14656f3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -915,11 +915,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _saveAvatarOverrideUrl = true; } - QString defaultScriptsLocation = getCmdOption(argc, constArgv, "--scripts"); - if (!defaultScriptsLocation.isEmpty()) { - PathUtils::defaultScriptsLocation(defaultScriptsLocation); - } - _glWidget = new GLCanvas(); getApplicationCompositor().setRenderingWidget(_glWidget); _window->setCentralWidget(_glWidget); @@ -1186,7 +1181,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // do this as late as possible so that all required subsystems are initialized // If we've overridden the default scripts location, just load default scripts // otherwise, load 'em all - if (!defaultScriptsLocation.isEmpty()) { + + // we just want to see if --scripts was set, we've already parsed it and done + // the change in PathUtils. Rather than pass that in the constructor, lets just + // look (this could be debated) + QDir defaultScriptsLocation(getCmdOption(argc, constArgv, "--scripts")); + if (!defaultScriptsLocation.exists()) { scriptEngines->loadDefaultScripts(); scriptEngines->defaultScriptsLocationOverridden(true); } else { diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 67e248506f..ac1b6d5010 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -73,12 +73,14 @@ int main(int argc, const char* argv[]) { QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath"); QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run"); QCommandLineOption overrideAppLocalDataPathOption("cache", "set test cache ", "dir"); + QCommandLineOption overrideScriptsPathOption("scripts", "set scripts ", "path"); parser.addOption(urlOption); parser.addOption(noUpdaterOption); parser.addOption(checkMinSpecOption); parser.addOption(runServerOption); parser.addOption(serverContentPathOption); parser.addOption(overrideAppLocalDataPathOption); + parser.addOption(overrideScriptsPathOption); parser.addOption(allowMultipleInstancesOption); parser.parse(arguments); @@ -99,6 +101,14 @@ int main(int argc, const char* argv[]) { if (allowMultipleInstances) { instanceMightBeRunning = false; } + + if (parser.isSet(overrideScriptsPathOption)) { + QDir scriptsPath(parser.value(overrideScriptsPathOption)); + if (scriptsPath.exists()) { + PathUtils::defaultScriptsLocation(scriptsPath.path()); + } + } + if (parser.isSet(overrideAppLocalDataPathOption)) { // get dir to use for cache QString cacheDir = parser.value(overrideAppLocalDataPathOption); From 8130a91b8c403fd1e78936b2834954c446717717 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 21 Jun 2017 12:43:48 -0700 Subject: [PATCH 21/47] Cleanup entity dependencies --- interface/src/Application.cpp | 5 +- libraries/animation/src/AnimationCache.cpp | 35 ------ libraries/animation/src/AnimationCache.h | 21 ---- .../src/EntityTreeRenderer.cpp | 34 +----- .../src/EntityTreeRenderer.h | 5 +- .../src/RenderableEntityItem.h | 5 + .../src/RenderableModelEntityItem.cpp | 60 +++++++--- .../src/RenderableModelEntityItem.h | 18 ++- .../src/RenderablePolyVoxEntityItem.cpp | 8 +- .../src/RenderablePolyVoxEntityItem.h | 8 +- libraries/entities/CMakeLists.txt | 8 +- .../entities/src/AnimationPropertyGroup.cpp | 4 +- .../entities/src/AnimationPropertyGroup.h | 2 +- libraries/entities/src/EntityItem.cpp | 23 +--- libraries/entities/src/EntityItem.h | 7 +- libraries/entities/src/EntityItemID.cpp | 2 +- .../entities/src/EntityItemProperties.cpp | 1 + libraries/entities/src/EntityItemProperties.h | 1 + .../entities/src/EntityScriptingInterface.cpp | 13 --- libraries/entities/src/EntityTree.cpp | 14 ++- libraries/entities/src/EntityTree.h | 18 --- libraries/entities/src/EntityTreeElement.cpp | 5 +- .../entities/src/KeyLightPropertyGroup.cpp | 5 +- libraries/entities/src/ModelEntityItem.cpp | 25 ---- libraries/entities/src/ModelEntityItem.h | 11 -- .../src/model-networking/MeshFace.cpp | 44 ------- .../src/model-networking/MeshFace.h | 43 ------- .../src/model-networking/MeshProxy.cpp | 48 -------- .../src/model-networking/MeshProxy.h | 52 --------- .../src/model-networking/SimpleMeshProxy.cpp | 27 +++++ .../src/model-networking/SimpleMeshProxy.h | 36 ++++++ libraries/model/src/model/Forward.h | 19 +++ .../src/ModelScriptingInterface.cpp | 12 +- .../src/ModelScriptingInterface.h | 12 +- libraries/shared/src/GLMHelpers.h | 1 + libraries/shared/src/RegisteredMetaTypes.cpp | 109 +++++++++++++++++- libraries/shared/src/RegisteredMetaTypes.h | 70 +++++++++++ .../src/shared/types}/AnimationLoop.cpp | 10 +- .../src/shared/types}/AnimationLoop.h | 7 +- tests/render-perf/src/main.cpp | 1 + 40 files changed, 391 insertions(+), 438 deletions(-) delete mode 100644 libraries/model-networking/src/model-networking/MeshFace.cpp delete mode 100644 libraries/model-networking/src/model-networking/MeshFace.h delete mode 100644 libraries/model-networking/src/model-networking/MeshProxy.cpp delete mode 100644 libraries/model-networking/src/model-networking/MeshProxy.h create mode 100644 libraries/model-networking/src/model-networking/SimpleMeshProxy.cpp create mode 100644 libraries/model-networking/src/model-networking/SimpleMeshProxy.h create mode 100644 libraries/model/src/model/Forward.h rename libraries/{animation/src => shared/src/shared/types}/AnimationLoop.cpp (95%) rename libraries/{animation/src => shared/src/shared/types}/AnimationLoop.h (93%) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9052f082dc..c6741ee7e4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4094,7 +4094,10 @@ void Application::init() { EntityTreePointer tree = getEntities()->getTree(); if (auto entity = tree->findEntityByEntityItemID(id)) { auto sound = DependencyManager::get()->getSound(newURL); - entity->setCollisionSound(sound); + auto renderable = entity->getRenderableInterface(); + if (renderable) { + renderable->setCollisionSound(sound); + } } }, Qt::QueuedConnection); connect(getMyAvatar().get(), &MyAvatar::newCollisionSoundURL, this, [this](QUrl newURL) { diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index 6594482085..7d4c0f4e92 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -144,38 +144,3 @@ void Animation::animationParseError(int error, QString str) { finishedLoading(false); } -AnimationDetails::AnimationDetails() : - role(), url(), fps(0.0f), priority(0.0f), loop(false), hold(false), - startAutomatically(false), firstFrame(0.0f), lastFrame(0.0f), running(false), currentFrame(0.0f) -{ -} - -AnimationDetails::AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop, - bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame) : - role(role), url(url), fps(fps), priority(priority), loop(loop), hold(hold), - startAutomatically(startAutomatically), firstFrame(firstFrame), lastFrame(lastFrame), - running(running), currentFrame(currentFrame) -{ -} - - -QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& details) { - QScriptValue obj = engine->newObject(); - obj.setProperty("role", details.role); - obj.setProperty("url", details.url.toString()); - obj.setProperty("fps", details.fps); - obj.setProperty("priority", details.priority); - obj.setProperty("loop", details.loop); - obj.setProperty("hold", details.hold); - obj.setProperty("startAutomatically", details.startAutomatically); - obj.setProperty("firstFrame", details.firstFrame); - obj.setProperty("lastFrame", details.lastFrame); - obj.setProperty("running", details.running); - obj.setProperty("currentFrame", details.currentFrame); - return obj; -} - -void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& details) { - // nothing for now... -} - diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 0e6a94c1b8..490bb7dcd8 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -107,26 +107,5 @@ private: QByteArray _data; }; -class AnimationDetails { -public: - AnimationDetails(); - AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop, - bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame); - - QString role; - QUrl url; - float fps; - float priority; - bool loop; - bool hold; - bool startAutomatically; - float firstFrame; - float lastFrame; - bool running; - float currentFrame; -}; -Q_DECLARE_METATYPE(AnimationDetails); -QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& event); -void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& event); #endif // hifi_AnimationCache_h diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index ffaac3bf3e..c02bde2244 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -163,7 +163,6 @@ void EntityTreeRenderer::reloadEntityScripts() { void EntityTreeRenderer::init() { OctreeProcessor::init(); EntityTreePointer entityTree = std::static_pointer_cast(_tree); - entityTree->setFBXService(this); if (_wantScripts) { resetEntitiesScriptEngine(); @@ -188,7 +187,6 @@ void EntityTreeRenderer::shutdown() { void EntityTreeRenderer::setTree(OctreePointer newTree) { OctreeProcessor::setTree(newTree); - std::static_pointer_cast(_tree)->setFBXService(this); } void EntityTreeRenderer::update() { @@ -373,31 +371,6 @@ bool EntityTreeRenderer::applyLayeredZones() { return true; } -const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(EntityItemPointer entityItem) { - const FBXGeometry* result = NULL; - - if (entityItem->getType() == EntityTypes::Model) { - std::shared_ptr modelEntityItem = - std::dynamic_pointer_cast(entityItem); - assert(modelEntityItem); // we need this!!! - ModelPointer model = modelEntityItem->getModel(getSharedFromThis()); - if (model && model->isLoaded()) { - result = &model->getFBXGeometry(); - } - } - return result; -} - -ModelPointer EntityTreeRenderer::getModelForEntityItem(EntityItemPointer entityItem) { - ModelPointer result = nullptr; - if (entityItem->getType() == EntityTypes::Model) { - std::shared_ptr modelEntityItem = - std::dynamic_pointer_cast(entityItem); - result = modelEntityItem->getModel(getSharedFromThis()); - } - return result; -} - void EntityTreeRenderer::processEraseMessage(ReceivedMessage& message, const SharedNodePointer& sourceNode) { std::static_pointer_cast(_tree)->processEraseMessage(message, sourceNode); } @@ -889,7 +862,12 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, bool void EntityTreeRenderer::playEntityCollisionSound(EntityItemPointer entity, const Collision& collision) { assert((bool)entity); - SharedSoundPointer collisionSound = entity->getCollisionSound(); + auto renderable = entity->getRenderableInterface(); + if (!renderable) { + return; + } + + SharedSoundPointer collisionSound = renderable->getCollisionSound(); if (!collisionSound) { return; } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 5dcbd1aeb9..f4909a2036 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -39,7 +39,7 @@ using ModelWeakPointer = std::weak_ptr; using CalculateEntityLoadingPriority = std::function; // Generic client side Octree renderer class. -class EntityTreeRenderer : public OctreeProcessor, public EntityItemFBXService, public Dependency { +class EntityTreeRenderer : public OctreeProcessor, public Dependency { Q_OBJECT public: EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState, @@ -68,9 +68,6 @@ public: virtual void init() override; - virtual const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) override; - virtual ModelPointer getModelForEntityItem(EntityItemPointer entityItem) override; - /// clears the tree virtual void clear() override; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 244a850d67..c848b10f6a 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -14,6 +14,7 @@ #include #include +#include #include "AbstractViewStateInterface.h" #include "EntitiesRendererLogging.h" @@ -40,7 +41,11 @@ public: virtual void render(RenderArgs* args) {}; virtual bool addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) = 0; virtual void removeFromScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) = 0; + const SharedSoundPointer& getCollisionSound() { return _collisionSound; } + void setCollisionSound(const SharedSoundPointer& sound) { _collisionSound = sound; } virtual RenderableEntityInterface* getRenderableInterface() { return nullptr; } +private: + SharedSoundPointer _collisionSound; }; class RenderableEntityItemProxy { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index f343fdb155..b8e869e4d9 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -69,11 +69,9 @@ void RenderableModelEntityItem::setModelURL(const QString& url) { void RenderableModelEntityItem::loader() { _needsModelReload = true; - auto renderer = DependencyManager::get(); - assert(renderer); { PerformanceTimer perfTimer("getModel"); - getModel(renderer); + getModel(); } } @@ -390,8 +388,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { if (!_model || _needsModelReload) { // TODO: this getModel() appears to be about 3% of model render time. We should optimize PerformanceTimer perfTimer("getModel"); - auto renderer = qSharedPointerCast(args->_renderData); - getModel(renderer); + getModel(); // Remap textures immediately after loading to avoid flicker remapTextures(); @@ -483,7 +480,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { auto& currentURL = getParsedModelURL(); if (currentURL != _model->getURL()) { // Defer setting the url to the render thread - getModel(_myRenderer); + getModel(); } } } @@ -492,16 +489,11 @@ ModelPointer RenderableModelEntityItem::getModelNotSafe() { return _model; } -ModelPointer RenderableModelEntityItem::getModel(QSharedPointer renderer) { - if (!renderer) { - return nullptr; - } - +ModelPointer RenderableModelEntityItem::getModel() { // make sure our renderer is setup if (!_myRenderer) { - _myRenderer = renderer; + _myRenderer = DependencyManager::get(); } - assert(_myRenderer == renderer); // you should only ever render on one renderer if (!_myRenderer || QThread::currentThread() != _myRenderer->thread()) { return _model; @@ -513,7 +505,7 @@ ModelPointer RenderableModelEntityItem::getModel(QSharedPointerallocateModel(getModelURL(), renderer->getEntityLoadingPriority(*this), this); + _model = _myRenderer->allocateModel(getModelURL(), _myRenderer->getEntityLoadingPriority(*this), this); _needsInitialSimulation = true; // If we need to change URLs, update it *after rendering* (to avoid access violations) } else if (QUrl(getModelURL()) != _model->getURL()) { @@ -587,6 +579,22 @@ EntityItemProperties RenderableModelEntityItem::getProperties(EntityPropertyFlag properties.setRenderInfoHasTransparent(_model->getRenderInfoHasTransparent()); } + + const FBXGeometry* geometry = NULL; + const_cast(this)->getModel(); + if (_model && _model->isLoaded()) { + geometry = &_model->getFBXGeometry(); + } + + // TODO: improve naturalDimensions in the future, + // for now we've added this hack for setting natural dimensions of models + if (geometry) { + Extents meshExtents = geometry->getUnscaledMeshExtents(); + properties.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum); + properties.calculateNaturalPosition(meshExtents.minimum, meshExtents.maximum); + } + + return properties; } @@ -1255,3 +1263,27 @@ QStringList RenderableModelEntityItem::getJointNames() const { } return result; } + +void RenderableModelEntityItem::mapJoints(const QStringList& modelJointNames) { + // if we don't have animation, or we're already joint mapped then bail early + if (!hasAnimation() || jointsMapped()) { + return; + } + + if (!_animation || _animation->getURL().toString() != getAnimationURL()) { + _animation = DependencyManager::get()->getAnimation(getAnimationURL()); + } + + if (_animation && _animation->isLoaded()) { + QStringList animationJointNames = _animation->getJointNames(); + + if (modelJointNames.size() > 0 && animationJointNames.size() > 0) { + _jointMapping.resize(modelJointNames.size()); + for (int i = 0; i < modelJointNames.size(); i++) { + _jointMapping[i] = animationJointNames.indexOf(modelJointNames[i]); + } + _jointMappingCompleted = true; + _jointMappingURL = _animationProperties.getURL(); + } + } +} diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 2bbb51b3f0..2d240c01a6 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -16,6 +16,7 @@ #include #include +#include class Model; class EntityTreeRenderer; @@ -53,7 +54,7 @@ public: bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const override; - ModelPointer getModel(QSharedPointer renderer); + ModelPointer getModel(); ModelPointer getModelNotSafe(); virtual bool needsToCallUpdate() const override; @@ -106,6 +107,15 @@ public: // Transparency is handled in ModelMeshPartPayload bool isTransparent() override { return false; } + void mapJoints(const QStringList& modelJointNames); + bool jointsMapped() const { + return _jointMappingURL == getAnimationURL() && _jointMappingCompleted; + } + + AnimationPointer getAnimation() const { + return _animation; + } + private: QVariantMap parseTexturesToMap(QString textures); void remapTextures(); @@ -131,6 +141,12 @@ private: bool _needsJointSimulation { false }; bool _showCollisionGeometry { false }; const void* _collisionMeshKey { nullptr }; + + // used on client side + bool _jointMappingCompleted { false }; + QVector _jointMapping; // domain is index into model-joints, range is index into animation-joints + QString _jointMappingURL; + AnimationPointer _animation; }; #endif // hifi_RenderableModelEntityItem_h diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 6cda472d96..88a5d2b873 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -9,11 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + +#include "RenderablePolyVoxEntityItem.h" + #include #include #include #include #include +#include #include "ModelScriptingInterface.h" #if defined(__GNUC__) && !defined(__clang__) @@ -52,7 +56,6 @@ #include "EntityTreeRenderer.h" #include "polyvox_vert.h" #include "polyvox_frag.h" -#include "RenderablePolyVoxEntityItem.h" #include "EntityEditPacketSender.h" #include "PhysicalEntitySimulation.h" @@ -1626,6 +1629,7 @@ void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) { scene->enqueueTransaction(transaction); } + bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) { if (!updateDependents()) { return false; @@ -1645,7 +1649,7 @@ bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) { } else { success = true; // the mesh will be in voxel-space. transform it into object-space - meshProxy = new MeshProxy( + meshProxy = new SimpleMeshProxy( _mesh->map([=](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); }, [=](glm::vec3 normal){ return glm::normalize(glm::vec3(transform * glm::vec4(normal, 0.0f))); }, [&](uint32_t index){ return index; })); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 174d6338d3..45625ada6d 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -12,17 +12,19 @@ #ifndef hifi_RenderablePolyVoxEntityItem_h #define hifi_RenderablePolyVoxEntityItem_h -#include #include +#include + #include #include +#include +#include #include +#include -#include "PolyVoxEntityItem.h" #include "RenderableEntityItem.h" -#include "gpu/Context.h" class PolyVoxPayload { public: diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index ddb5fbaf73..19341ec3e2 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,9 +1,3 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) -link_hifi_libraries(avatars shared audio octree model model-networking fbx networking animation) -include_hifi_library_headers(networking) -include_hifi_library_headers(gpu) - -target_bullet() - -include_hifi_library_headers(render) +link_hifi_libraries(shared networking octree avatars) diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index f6d08ad8b9..848d4352a7 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -9,12 +9,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "AnimationPropertyGroup.h" + #include #include -#include -#include "AnimationPropertyGroup.h" #include "EntityItemProperties.h" #include "EntityItemPropertiesMacros.h" diff --git a/libraries/entities/src/AnimationPropertyGroup.h b/libraries/entities/src/AnimationPropertyGroup.h index c6d386d2ef..c0086b41b3 100644 --- a/libraries/entities/src/AnimationPropertyGroup.h +++ b/libraries/entities/src/AnimationPropertyGroup.h @@ -19,7 +19,7 @@ #include -#include "AnimationLoop.h" +#include // for Animation, AnimationCache, and AnimationPointer classes #include "EntityItemPropertiesMacros.h" #include "PropertyGroup.h" diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 17de15e32b..23ce097cc2 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -23,8 +23,8 @@ #include #include #include // usecTimestampNow() -#include #include +#include #include "EntityScriptingInterface.h" #include "EntitiesLogging.h" @@ -988,21 +988,6 @@ void EntityItem::setCollisionSoundURL(const QString& value) { } } -SharedSoundPointer EntityItem::getCollisionSound() { - SharedSoundPointer result; - withReadLock([&] { - result = _collisionSound; - }); - - if (!result) { - result = DependencyManager::get()->getSound(_collisionSoundURL); - withWriteLock([&] { - _collisionSound = result; - }); - } - return result; -} - void EntityItem::simulate(const quint64& now) { if (getLastSimulated() == 0) { setLastSimulated(now); @@ -2650,12 +2635,6 @@ QString EntityItem::getCollisionSoundURL() const { return result; } -void EntityItem::setCollisionSound(SharedSoundPointer sound) { - withWriteLock([&] { - _collisionSound = sound; - }); -} - glm::vec3 EntityItem::getRegistrationPoint() const { glm::vec3 result; withReadLock([&] { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 0318c72991..92c83651aa 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -19,14 +19,13 @@ #include -#include // for Animation, AnimationCache, and AnimationPointer classes +#include // for Animation, AnimationCache, and AnimationPointer classes #include // for EncodeBitstreamParams class #include // for OctreeElement::AppendState #include #include #include #include -#include #include #include @@ -260,9 +259,6 @@ public: QString getCollisionSoundURL() const; void setCollisionSoundURL(const QString& value); - SharedSoundPointer getCollisionSound(); - void setCollisionSound(SharedSoundPointer sound); - glm::vec3 getRegistrationPoint() const; /// registration point as ratio of entity /// registration point as ratio of entity @@ -526,7 +522,6 @@ protected: quint64 _loadedScriptTimestamp { ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP + 1 }; QString _collisionSoundURL; - SharedSoundPointer _collisionSound; glm::vec3 _registrationPoint; float _angularDamping; bool _visible; diff --git a/libraries/entities/src/EntityItemID.cpp b/libraries/entities/src/EntityItemID.cpp index 5f07019db4..3b4ca1cea0 100644 --- a/libraries/entities/src/EntityItemID.cpp +++ b/libraries/entities/src/EntityItemID.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "EntityItemID.h" #include #include @@ -17,7 +18,6 @@ #include #include "RegisteredMetaTypes.h" -#include "EntityItemID.h" int entityItemIDTypeID = qRegisterMetaType(); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 1ed020e592..a207902789 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "EntitiesLogging.h" #include "EntityItem.h" diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 590298e102..b526ac663c 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -15,6 +15,7 @@ #include #include +#include #include #include diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 90dc6893b4..7351d49dff 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include "EntitiesLogging.h" #include "EntityDynamicFactoryInterface.h" @@ -298,18 +297,6 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit } results = entity->getProperties(desiredProperties); - - // TODO: improve naturalDimensions in the future, - // for now we've added this hack for setting natural dimensions of models - if (entity->getType() == EntityTypes::Model) { - const FBXGeometry* geometry = _entityTree->getGeometryForEntity(entity); - if (geometry) { - Extents meshExtents = geometry->getUnscaledMeshExtents(); - results.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum); - results.calculateNaturalPosition(meshExtents.minimum, meshExtents.maximum); - } - } - } }); } diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 11694c4cea..4773f45af7 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -9,11 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include +#include "EntityTree.h" +#include +#include + #include -#include "EntityTree.h" +#include +#include + #include "EntitySimulation.h" #include "VariantMapToScriptValue.h" @@ -55,9 +59,7 @@ public: EntityTree::EntityTree(bool shouldReaverage) : - Octree(shouldReaverage), - _fbxService(NULL), - _simulation(NULL) + Octree(shouldReaverage) { resetClientEditStats(); } diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 8e3c9f5412..24e6c364b1 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -41,13 +41,6 @@ public: virtual void entityCreated(const EntityItem& newEntity, const SharedNodePointer& senderNode) = 0; }; -class EntityItemFBXService { -public: - virtual const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) = 0; - virtual ModelPointer getModelForEntityItem(EntityItemPointer entityItem) = 0; -}; - - class SendEntitiesOperationArgs { public: glm::vec3 root; @@ -189,15 +182,6 @@ public: int processEraseMessage(ReceivedMessage& message, const SharedNodePointer& sourceNode); int processEraseMessageDetails(const QByteArray& buffer, const SharedNodePointer& sourceNode); - EntityItemFBXService* getFBXService() const { return _fbxService; } - void setFBXService(EntityItemFBXService* service) { _fbxService = service; } - const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) { - return _fbxService ? _fbxService->getGeometryForEntity(entityItem) : NULL; - } - ModelPointer getModelForEntityItem(EntityItemPointer entityItem) { - return _fbxService ? _fbxService->getModelForEntityItem(entityItem) : NULL; - } - EntityTreeElementPointer getContainingElement(const EntityItemID& entityItemID) /*const*/; void setContainingElement(const EntityItemID& entityItemID, EntityTreeElementPointer element); void debugDumpMap(); @@ -325,8 +309,6 @@ protected: _deletedEntityItemIDs << id; } - EntityItemFBXService* _fbxService; - mutable QReadWriteLock _entityToElementLock; QHash _entityToElementMap; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 0dc42717f5..cce7ee006f 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -9,17 +9,18 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "EntityTreeElement.h" + #include -#include #include #include +#include #include "EntitiesLogging.h" #include "EntityNodeData.h" #include "EntityItemProperties.h" #include "EntityTree.h" -#include "EntityTreeElement.h" #include "EntityTypes.h" EntityTreeElement::EntityTreeElement(unsigned char* octalCode) : OctreeElement() { diff --git a/libraries/entities/src/KeyLightPropertyGroup.cpp b/libraries/entities/src/KeyLightPropertyGroup.cpp index 1011094266..f0d059af67 100644 --- a/libraries/entities/src/KeyLightPropertyGroup.cpp +++ b/libraries/entities/src/KeyLightPropertyGroup.cpp @@ -9,12 +9,11 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "KeyLightPropertyGroup.h" + #include #include -#include - -#include "KeyLightPropertyGroup.h" #include "EntityItemProperties.h" #include "EntityItemPropertiesMacros.h" diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 89213459fa..b5e759d2d8 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -37,7 +37,6 @@ ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID) : EntityItem( _animationLoop.setResetOnRunning(false); _type = EntityTypes::Model; - _jointMappingCompleted = false; _lastKnownCurrentFrame = -1; _color[0] = _color[1] = _color[2] = 0; } @@ -204,30 +203,6 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit } -void ModelEntityItem::mapJoints(const QStringList& modelJointNames) { - // if we don't have animation, or we're already joint mapped then bail early - if (!hasAnimation() || jointsMapped()) { - return; - } - - if (!_animation || _animation->getURL().toString() != getAnimationURL()) { - _animation = DependencyManager::get()->getAnimation(getAnimationURL()); - } - - if (_animation && _animation->isLoaded()) { - QStringList animationJointNames = _animation->getJointNames(); - - if (modelJointNames.size() > 0 && animationJointNames.size() > 0) { - _jointMapping.resize(modelJointNames.size()); - for (int i = 0; i < modelJointNames.size(); i++) { - _jointMapping[i] = animationJointNames.indexOf(modelJointNames[i]); - } - _jointMappingCompleted = true; - _jointMappingURL = _animationProperties.getURL(); - } - } -} - bool ModelEntityItem::isAnimatingSomething() const { return getAnimationIsPlaying() && getAnimationFPS() != 0.0f && diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 5076a43892..0c6132e211 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -12,8 +12,6 @@ #ifndef hifi_ModelEntityItem_h #define hifi_ModelEntityItem_h -#include - #include "EntityItem.h" #include "AnimationPropertyGroup.h" @@ -103,10 +101,7 @@ public: void setAnimationLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); } float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } - void mapJoints(const QStringList& modelJointNames); - bool jointsMapped() const { return _jointMappingURL == getAnimationURL() && _jointMappingCompleted; } - AnimationPointer getAnimation() const { return _animation; } bool getAnimationIsPlaying() const { return _animationLoop.getRunning(); } float getAnimationCurrentFrame() const { return _animationLoop.getCurrentFrame(); } float getAnimationFPS() const { return _animationLoop.getFPS(); } @@ -158,7 +153,6 @@ protected: QUrl _parsedModelURL; QString _compoundShapeURL; - AnimationPointer _animation; AnimationPropertyGroup _animationProperties; AnimationLoop _animationLoop; @@ -166,11 +160,6 @@ protected: QString _textures; ShapeType _shapeType = SHAPE_TYPE_NONE; - - // used on client side - bool _jointMappingCompleted; - QVector _jointMapping; // domain is index into model-joints, range is index into animation-joints - QString _jointMappingURL; }; #endif // hifi_ModelEntityItem_h diff --git a/libraries/model-networking/src/model-networking/MeshFace.cpp b/libraries/model-networking/src/model-networking/MeshFace.cpp deleted file mode 100644 index 8092d36aa3..0000000000 --- a/libraries/model-networking/src/model-networking/MeshFace.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// MeshFace.cpp -// libraries/model/src/model/ -// -// Created by Seth Alves on 2017-3-23 -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include "MeshFace.h" - - -QScriptValue meshFaceToScriptValue(QScriptEngine* engine, const MeshFace &meshFace) { - QScriptValue obj = engine->newObject(); - obj.setProperty("vertices", qVectorIntToScriptValue(engine, meshFace.vertexIndices)); - return obj; -} - -void meshFaceFromScriptValue(const QScriptValue &object, MeshFace& meshFaceResult) { - qVectorIntFromScriptValue(object.property("vertices"), meshFaceResult.vertexIndices); -} - -QScriptValue qVectorMeshFaceToScriptValue(QScriptEngine* engine, const QVector& vector) { - QScriptValue array = engine->newArray(); - for (int i = 0; i < vector.size(); i++) { - array.setProperty(i, meshFaceToScriptValue(engine, vector.at(i))); - } - return array; -} - -void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector& result) { - int length = array.property("length").toInteger(); - result.clear(); - - for (int i = 0; i < length; i++) { - MeshFace meshFace = MeshFace(); - meshFaceFromScriptValue(array.property(i), meshFace); - result << meshFace; - } -} diff --git a/libraries/model-networking/src/model-networking/MeshFace.h b/libraries/model-networking/src/model-networking/MeshFace.h deleted file mode 100644 index 3b81b372c3..0000000000 --- a/libraries/model-networking/src/model-networking/MeshFace.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// MeshFace.h -// libraries/model/src/model/ -// -// Created by Seth Alves on 2017-3-23 -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_MeshFace_h -#define hifi_MeshFace_h - -#include -#include -#include - -#include - -using MeshPointer = std::shared_ptr; - -class MeshFace { - -public: - MeshFace() {} - ~MeshFace() {} - - QVector vertexIndices; - // TODO -- material... -}; - -Q_DECLARE_METATYPE(MeshFace) -Q_DECLARE_METATYPE(QVector) - -QScriptValue meshFaceToScriptValue(QScriptEngine* engine, const MeshFace &meshFace); -void meshFaceFromScriptValue(const QScriptValue &object, MeshFace& meshFaceResult); -QScriptValue qVectorMeshFaceToScriptValue(QScriptEngine* engine, const QVector& vector); -void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector& result); - - - -#endif // hifi_MeshFace_h diff --git a/libraries/model-networking/src/model-networking/MeshProxy.cpp b/libraries/model-networking/src/model-networking/MeshProxy.cpp deleted file mode 100644 index 1b6fa43c82..0000000000 --- a/libraries/model-networking/src/model-networking/MeshProxy.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// MeshProxy.cpp -// libraries/model/src/model/ -// -// Created by Seth Alves on 2017-3-22. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "MeshProxy.h" - - -QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) { - return engine->newQObject(in, QScriptEngine::QtOwnership, - QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects); -} - -void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) { - out = qobject_cast(value.toQObject()); -} - -QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in) { - // QScriptValueList result; - QScriptValue result = engine->newArray(); - int i = 0; - foreach (MeshProxy* const meshProxy, in) { - result.setProperty(i++, meshToScriptValue(engine, meshProxy)); - } - return result; -} - -void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out) { - QScriptValueIterator itr(value); - - qDebug() << "in meshesFromScriptValue, value.length =" << value.property("length").toInt32(); - - while(itr.hasNext()) { - itr.next(); - MeshProxy* meshProxy = qscriptvalue_cast(itr.value()); - if (meshProxy) { - out.append(meshProxy); - } else { - qDebug() << "null meshProxy"; - } - } -} diff --git a/libraries/model-networking/src/model-networking/MeshProxy.h b/libraries/model-networking/src/model-networking/MeshProxy.h deleted file mode 100644 index c5b25b7895..0000000000 --- a/libraries/model-networking/src/model-networking/MeshProxy.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// MeshProxy.h -// libraries/model/src/model/ -// -// Created by Seth Alves on 2017-1-27. -// Copyright 2017 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_MeshProxy_h -#define hifi_MeshProxy_h - -#include -#include -#include - -#include - -using MeshPointer = std::shared_ptr; - -class MeshProxy : public QObject { - Q_OBJECT - -public: - MeshProxy(MeshPointer mesh) : _mesh(mesh) {} - ~MeshProxy() {} - - MeshPointer getMeshPointer() const { return _mesh; } - - Q_INVOKABLE int getNumVertices() const { return (int)_mesh->getNumVertices(); } - Q_INVOKABLE glm::vec3 getPos3(int index) const { return _mesh->getPos3(index); } - - -protected: - MeshPointer _mesh; -}; - -Q_DECLARE_METATYPE(MeshProxy*); - -class MeshProxyList : public QList {}; // typedef and using fight with the Qt macros/templates, do this instead -Q_DECLARE_METATYPE(MeshProxyList); - - -QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in); -void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out); - -QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in); -void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out); - -#endif // hifi_MeshProxy_h diff --git a/libraries/model-networking/src/model-networking/SimpleMeshProxy.cpp b/libraries/model-networking/src/model-networking/SimpleMeshProxy.cpp new file mode 100644 index 0000000000..40b30154bf --- /dev/null +++ b/libraries/model-networking/src/model-networking/SimpleMeshProxy.cpp @@ -0,0 +1,27 @@ +// +// MeshProxy.cpp +// libraries/model/src/model/ +// +// Created by Seth Alves on 2017-3-22. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "SimpleMeshProxy.h" + +#include + +MeshPointer SimpleMeshProxy::getMeshPointer() const { + return _mesh; +} + +int SimpleMeshProxy::getNumVertices() const { + return (int)_mesh->getNumVertices(); +} + +glm::vec3 SimpleMeshProxy::getPos3(int index) const { + return _mesh->getPos3(index); +} + diff --git a/libraries/model-networking/src/model-networking/SimpleMeshProxy.h b/libraries/model-networking/src/model-networking/SimpleMeshProxy.h new file mode 100644 index 0000000000..b82e501673 --- /dev/null +++ b/libraries/model-networking/src/model-networking/SimpleMeshProxy.h @@ -0,0 +1,36 @@ +// +// MeshProxy.h +// libraries/model/src/model/ +// +// Created by Seth Alves on 2017-1-27. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_SimpleMeshProxy_h +#define hifi_SimpleMeshProxy_h + +#include +#include +#include + +#include + +class SimpleMeshProxy : public MeshProxy { +public: + SimpleMeshProxy(const MeshPointer& mesh) : _mesh(mesh) { } + + MeshPointer getMeshPointer() const override; + + int getNumVertices() const override; + + glm::vec3 getPos3(int index) const override; + + +protected: + const MeshPointer _mesh; +}; + +#endif // hifi_SimpleMeshProxy_h diff --git a/libraries/model/src/model/Forward.h b/libraries/model/src/model/Forward.h new file mode 100644 index 0000000000..362eabb454 --- /dev/null +++ b/libraries/model/src/model/Forward.h @@ -0,0 +1,19 @@ +// +// Geometry.h +// libraries/model/src/model +// +// Created by Sam Gateau on 12/5/2014. +// 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_model_Forward_h +#define hifi_model_Forward_h + +namespace model { + class Mesh; + using MeshPointer = std::shared_ptr; +} + +#endif diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp index f56312568e..762d9ffb29 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -9,17 +9,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "ModelScriptingInterface.h" #include #include #include -#include +#include #include "ScriptEngine.h" #include "ScriptEngineLogging.h" -#include "ModelScriptingInterface.h" #include "OBJWriter.h" ModelScriptingInterface::ModelScriptingInterface(QObject* parent) : QObject(parent) { - _modelScriptEngine = qobject_cast(parent); + _modelScriptEngine = qobject_cast(parent); qScriptRegisterSequenceMetaType>(_modelScriptEngine); qScriptRegisterMetaType(_modelScriptEngine, meshFaceToScriptValue, meshFaceFromScriptValue); @@ -118,7 +118,7 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { (gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL)); - MeshProxy* resultProxy = new MeshProxy(result); + MeshProxy* resultProxy = new SimpleMeshProxy(result); return meshToScriptValue(_modelScriptEngine, resultProxy); } @@ -134,7 +134,7 @@ QScriptValue ModelScriptingInterface::transformMesh(glm::mat4 transform, MeshPro model::MeshPointer result = mesh->map([&](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); }, [&](glm::vec3 normal){ return glm::vec3(transform * glm::vec4(normal, 0.0f)); }, [&](uint32_t index){ return index; }); - MeshProxy* resultProxy = new MeshProxy(result); + MeshProxy* resultProxy = new SimpleMeshProxy(result); return meshToScriptValue(_modelScriptEngine, resultProxy); } @@ -188,6 +188,6 @@ QScriptValue ModelScriptingInterface::newMesh(const QVector& vertices - MeshProxy* meshProxy = new MeshProxy(mesh); + MeshProxy* meshProxy = new SimpleMeshProxy(mesh); return meshToScriptValue(_modelScriptEngine, meshProxy); } diff --git a/libraries/script-engine/src/ModelScriptingInterface.h b/libraries/script-engine/src/ModelScriptingInterface.h index d899f532d8..ba23623acf 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.h +++ b/libraries/script-engine/src/ModelScriptingInterface.h @@ -9,19 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - #ifndef hifi_ModelScriptingInterface_h #define hifi_ModelScriptingInterface_h #include -#include -#include -#include -#include -#include -using MeshPointer = std::shared_ptr; -class ScriptEngine; +#include +class QScriptEngine; class ModelScriptingInterface : public QObject { Q_OBJECT @@ -37,7 +31,7 @@ public: const QVector& faces); private: - ScriptEngine* _modelScriptEngine { nullptr }; + QScriptEngine* _modelScriptEngine { nullptr }; }; #endif // hifi_ModelScriptingInterface_h diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index ef92552d1f..3386ea2c22 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -17,6 +17,7 @@ #include #include #include +#include // Bring the most commonly used GLM types into the default namespace using glm::ivec2; diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 70067b93f3..1e5fe23458 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -9,6 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "RegisteredMetaTypes.h" + +#include + #include #include #include @@ -17,10 +21,9 @@ #include #include #include -#include -#include - -#include "RegisteredMetaTypes.h" +#include +#include +#include int vec4MetaTypeId = qRegisterMetaType(); int vec3MetaTypeId = qRegisterMetaType(); @@ -796,3 +799,101 @@ void qSizeFFromScriptValue(const QScriptValue& object, QSizeF& qSizeF) { qSizeF.setWidth(object.property("width").toVariant().toFloat()); qSizeF.setHeight(object.property("height").toVariant().toFloat()); } + +AnimationDetails::AnimationDetails() : + role(), url(), fps(0.0f), priority(0.0f), loop(false), hold(false), + startAutomatically(false), firstFrame(0.0f), lastFrame(0.0f), running(false), currentFrame(0.0f) { +} + +AnimationDetails::AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop, + bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame) : + role(role), url(url), fps(fps), priority(priority), loop(loop), hold(hold), + startAutomatically(startAutomatically), firstFrame(firstFrame), lastFrame(lastFrame), + running(running), currentFrame(currentFrame) { +} + + +QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& details) { + QScriptValue obj = engine->newObject(); + obj.setProperty("role", details.role); + obj.setProperty("url", details.url.toString()); + obj.setProperty("fps", details.fps); + obj.setProperty("priority", details.priority); + obj.setProperty("loop", details.loop); + obj.setProperty("hold", details.hold); + obj.setProperty("startAutomatically", details.startAutomatically); + obj.setProperty("firstFrame", details.firstFrame); + obj.setProperty("lastFrame", details.lastFrame); + obj.setProperty("running", details.running); + obj.setProperty("currentFrame", details.currentFrame); + return obj; +} + +void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& details) { + // nothing for now... +} + +QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) { + return engine->newQObject(in, QScriptEngine::QtOwnership, + QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects); +} + +void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) { + out = qobject_cast(value.toQObject()); +} + +QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in) { + // QScriptValueList result; + QScriptValue result = engine->newArray(); + int i = 0; + foreach(MeshProxy* const meshProxy, in) { + result.setProperty(i++, meshToScriptValue(engine, meshProxy)); + } + return result; +} + +void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out) { + QScriptValueIterator itr(value); + + qDebug() << "in meshesFromScriptValue, value.length =" << value.property("length").toInt32(); + + while (itr.hasNext()) { + itr.next(); + MeshProxy* meshProxy = qscriptvalue_cast(itr.value()); + if (meshProxy) { + out.append(meshProxy); + } else { + qDebug() << "null meshProxy"; + } + } +} + + +QScriptValue meshFaceToScriptValue(QScriptEngine* engine, const MeshFace &meshFace) { + QScriptValue obj = engine->newObject(); + obj.setProperty("vertices", qVectorIntToScriptValue(engine, meshFace.vertexIndices)); + return obj; +} + +void meshFaceFromScriptValue(const QScriptValue &object, MeshFace& meshFaceResult) { + qVectorIntFromScriptValue(object.property("vertices"), meshFaceResult.vertexIndices); +} + +QScriptValue qVectorMeshFaceToScriptValue(QScriptEngine* engine, const QVector& vector) { + QScriptValue array = engine->newArray(); + for (int i = 0; i < vector.size(); i++) { + array.setProperty(i, meshFaceToScriptValue(engine, vector.at(i))); + } + return array; +} + +void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector& result) { + int length = array.property("length").toInteger(); + result.clear(); + + for (int i = 0; i < length; i++) { + MeshFace meshFace = MeshFace(); + meshFaceFromScriptValue(array.property(i), meshFace); + result << meshFace; + } +} diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 8a15f62eed..dd37cb3410 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -167,4 +168,73 @@ void quuidFromScriptValue(const QScriptValue& object, QUuid& uuid); QScriptValue qSizeFToScriptValue(QScriptEngine* engine, const QSizeF& qSizeF); void qSizeFFromScriptValue(const QScriptValue& object, QSizeF& qSizeF); +class AnimationDetails { +public: + AnimationDetails(); + AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop, + bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame); + + QString role; + QUrl url; + float fps; + float priority; + bool loop; + bool hold; + bool startAutomatically; + float firstFrame; + float lastFrame; + bool running; + float currentFrame; +}; +Q_DECLARE_METATYPE(AnimationDetails); +QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& event); +void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& event); + +namespace model { + class Mesh; +} + +using MeshPointer = std::shared_ptr; + + +class MeshProxy : public QObject { + Q_OBJECT + +public: + virtual MeshPointer getMeshPointer() const = 0; + Q_INVOKABLE virtual int getNumVertices() const = 0; + Q_INVOKABLE virtual glm::vec3 getPos3(int index) const = 0; +}; + +Q_DECLARE_METATYPE(MeshProxy*); + +class MeshProxyList : public QList {}; // typedef and using fight with the Qt macros/templates, do this instead +Q_DECLARE_METATYPE(MeshProxyList); + + +QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in); +void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out); + +QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in); +void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out); + +class MeshFace { + +public: + MeshFace() {} + ~MeshFace() {} + + QVector vertexIndices; + // TODO -- material... +}; + +Q_DECLARE_METATYPE(MeshFace) +Q_DECLARE_METATYPE(QVector) + +QScriptValue meshFaceToScriptValue(QScriptEngine* engine, const MeshFace &meshFace); +void meshFaceFromScriptValue(const QScriptValue &object, MeshFace& meshFaceResult); +QScriptValue qVectorMeshFaceToScriptValue(QScriptEngine* engine, const QVector& vector); +void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector& result); + + #endif // hifi_RegisteredMetaTypes_h diff --git a/libraries/animation/src/AnimationLoop.cpp b/libraries/shared/src/shared/types/AnimationLoop.cpp similarity index 95% rename from libraries/animation/src/AnimationLoop.cpp rename to libraries/shared/src/shared/types/AnimationLoop.cpp index 3d7bca863f..f77bd8bb2a 100644 --- a/libraries/animation/src/AnimationLoop.cpp +++ b/libraries/shared/src/shared/types/AnimationLoop.cpp @@ -9,11 +9,13 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include - -#include "AnimationCache.h" #include "AnimationLoop.h" +#include "../../NumericalConstants.h" +#include "../../SharedUtil.h" +#include "../../GLMHelpers.h" +#include "../../RegisteredMetaTypes.h" + const float AnimationLoop::MAXIMUM_POSSIBLE_FRAME = 100000.0f; AnimationLoop::AnimationLoop() : @@ -62,7 +64,7 @@ AnimationLoop::AnimationLoop(float fps, bool loop, bool hold, bool startAutomati { } -void AnimationLoop::simulateAtTime(quint64 now) { +void AnimationLoop::simulateAtTime(uint64_t now) { float deltaTime = (float)(now - _lastSimulated) / (float)USECS_PER_SECOND; _lastSimulated = now; simulate(deltaTime); diff --git a/libraries/animation/src/AnimationLoop.h b/libraries/shared/src/shared/types/AnimationLoop.h similarity index 93% rename from libraries/animation/src/AnimationLoop.h rename to libraries/shared/src/shared/types/AnimationLoop.h index 6adfbf35e2..33434209e7 100644 --- a/libraries/animation/src/AnimationLoop.h +++ b/libraries/shared/src/shared/types/AnimationLoop.h @@ -14,6 +14,9 @@ class AnimationDetails; +#include +#include + class AnimationLoop { public: static const float MAXIMUM_POSSIBLE_FRAME; @@ -58,7 +61,7 @@ public: void stop() { setRunning(false); } void simulate(float deltaTime); /// call this with deltaTime if you as the caller are managing the delta time between calls - void simulateAtTime(quint64 now); /// call this with "now" if you want the animationLoop to handle delta times + void simulateAtTime(uint64_t now); /// call this with "now" if you want the animationLoop to handle delta times private: float _fps; @@ -71,7 +74,7 @@ private: float _currentFrame; float _maxFrameIndexHint; bool _resetOnRunning; - quint64 _lastSimulated; + uint64_t _lastSimulated; }; #endif // hifi_AnimationLoop_h diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 52592cd202..552dc3d270 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -47,6 +47,7 @@ #include #include +#include #include #include #include From 28d727153b4418c277b2d4cbf75584cddf4d233f Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 27 Jun 2017 19:22:07 -0700 Subject: [PATCH 22/47] PR feedback --- .../src/RenderableModelEntityItem.cpp | 13 ++++--------- .../src/model-networking/SimpleMeshProxy.cpp | 4 ++-- .../src/model-networking/SimpleMeshProxy.h | 4 ++-- libraries/model/src/model/Forward.h | 6 +++--- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index b8e869e4d9..0547c60364 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -580,21 +580,16 @@ EntityItemProperties RenderableModelEntityItem::getProperties(EntityPropertyFlag } - const FBXGeometry* geometry = NULL; - const_cast(this)->getModel(); if (_model && _model->isLoaded()) { - geometry = &_model->getFBXGeometry(); - } - - // TODO: improve naturalDimensions in the future, - // for now we've added this hack for setting natural dimensions of models - if (geometry) { - Extents meshExtents = geometry->getUnscaledMeshExtents(); + // TODO: improve naturalDimensions in the future, + // for now we've added this hack for setting natural dimensions of models + Extents meshExtents = _model->getFBXGeometry().getUnscaledMeshExtents(); properties.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum); properties.calculateNaturalPosition(meshExtents.minimum, meshExtents.maximum); } + return properties; } diff --git a/libraries/model-networking/src/model-networking/SimpleMeshProxy.cpp b/libraries/model-networking/src/model-networking/SimpleMeshProxy.cpp index 40b30154bf..b44ea1ff56 100644 --- a/libraries/model-networking/src/model-networking/SimpleMeshProxy.cpp +++ b/libraries/model-networking/src/model-networking/SimpleMeshProxy.cpp @@ -1,6 +1,6 @@ // -// MeshProxy.cpp -// libraries/model/src/model/ +// SimpleMeshProxy.cpp +// libraries/model-networking/src/model-networking/ // // Created by Seth Alves on 2017-3-22. // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/model-networking/src/model-networking/SimpleMeshProxy.h b/libraries/model-networking/src/model-networking/SimpleMeshProxy.h index b82e501673..24c3fca27e 100644 --- a/libraries/model-networking/src/model-networking/SimpleMeshProxy.h +++ b/libraries/model-networking/src/model-networking/SimpleMeshProxy.h @@ -1,6 +1,6 @@ // -// MeshProxy.h -// libraries/model/src/model/ +// SimpleMeshProxy.h +// libraries/model-networking/src/model-networking/ // // Created by Seth Alves on 2017-1-27. // Copyright 2017 High Fidelity, Inc. diff --git a/libraries/model/src/model/Forward.h b/libraries/model/src/model/Forward.h index 362eabb454..90f55fa64f 100644 --- a/libraries/model/src/model/Forward.h +++ b/libraries/model/src/model/Forward.h @@ -1,9 +1,9 @@ // -// Geometry.h +// Forward.h // libraries/model/src/model // -// Created by Sam Gateau on 12/5/2014. -// Copyright 2014 High Fidelity, Inc. +// Created by Bradley Austin Davis on 2017/06/21 +// Copyright 2013-2017 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html From 37e5454421c4f924fb035540a0ff9b949af49b16 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 28 Jun 2017 15:12:20 +0200 Subject: [PATCH 23/47] Fix lighting issues identified with 2nd rendering pipeline --- interface/src/SecondaryCamera.cpp | 2 ++ libraries/gpu-gl/src/gpu/gl/GLBackend.cpp | 11 ++++++++++- libraries/gpu-gl/src/gpu/gl/GLBackend.h | 9 +++++++++ libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp | 8 +++++++- libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp | 2 +- libraries/gpu/src/gpu/Batch.cpp | 7 +++++++ libraries/gpu/src/gpu/Batch.h | 6 ++++++ libraries/render-utils/src/DeferredFrameTransform.cpp | 2 +- libraries/render-utils/src/RenderDeferredTask.cpp | 2 +- libraries/render-utils/src/SurfaceGeometryPass.cpp | 2 +- libraries/render/src/render/Args.h | 2 ++ libraries/render/src/render/BlurTask.cpp | 4 ++-- 12 files changed, 49 insertions(+), 8 deletions(-) diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index f6ee8caa61..f59d2fcc7a 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -79,6 +79,7 @@ public: gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.disableContextStereo(); + batch.disableContextViewCorrection(); }); auto srcViewFrustum = args->getViewFrustum(); @@ -112,6 +113,7 @@ public: gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.restoreContextStereo(); + batch.restoreContextViewCorrection(); }); } }; diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index 3441407f62..11e67811b6 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -114,7 +114,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::gl::GLBackend::do_getQuery), (&::gpu::gl::GLBackend::do_resetStages), - + + (&::gpu::gl::GLBackend::do_disableContextViewCorrection), + (&::gpu::gl::GLBackend::do_restoreContextViewCorrection), (&::gpu::gl::GLBackend::do_disableContextStereo), (&::gpu::gl::GLBackend::do_restoreContextStereo), @@ -374,6 +376,13 @@ void GLBackend::do_resetStages(const Batch& batch, size_t paramOffset) { resetStages(); } +void GLBackend::do_disableContextViewCorrection(const Batch& batch, size_t paramOffset) { + _transform._viewCorrectionEnabled = false; +} + +void GLBackend::do_restoreContextViewCorrection(const Batch& batch, size_t paramOffset) { + _transform._viewCorrectionEnabled = true; +} void GLBackend::do_disableContextStereo(const Batch& batch, size_t paramOffset) { diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.h b/libraries/gpu-gl/src/gpu/gl/GLBackend.h index 96217555e1..88aecda617 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.h @@ -143,6 +143,10 @@ public: // Reset stages virtual void do_resetStages(const Batch& batch, size_t paramOffset) final; + + virtual void do_disableContextViewCorrection(const Batch& batch, size_t paramOffset) final; + virtual void do_restoreContextViewCorrection(const Batch& batch, size_t paramOffset) final; + virtual void do_disableContextStereo(const Batch& batch, size_t paramOffset) final; virtual void do_restoreContextStereo(const Batch& batch, size_t paramOffset) final; @@ -333,6 +337,8 @@ protected: bool _skybox { false }; Transform _view; CameraCorrection _correction; + bool _viewCorrectionEnabled{ true }; + Mat4 _projection; Vec4i _viewport { 0, 0, 1, 1 }; @@ -400,6 +406,7 @@ protected: bool _invalidProgram { false }; BufferView _cameraCorrectionBuffer { gpu::BufferView(std::make_shared(sizeof(CameraCorrection), nullptr )) }; + BufferView _cameraCorrectionBufferIdentity { gpu::BufferView(std::make_shared(sizeof(CameraCorrection), nullptr )) }; State::Data _stateCache{ State::DEFAULT }; State::Signature _stateSignatureCache { 0 }; @@ -409,6 +416,8 @@ protected: PipelineStageState() { _cameraCorrectionBuffer.edit() = CameraCorrection(); + _cameraCorrectionBufferIdentity.edit() = CameraCorrection(); + _cameraCorrectionBufferIdentity._buffer->flush(); } } _pipeline; diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp index 2d71e8ed78..7ef64343ea 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp @@ -77,8 +77,14 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) { if (_pipeline._invalidProgram) { glUseProgram(_pipeline._program); if (_pipeline._cameraCorrectionLocation != -1) { - auto cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBuffer._buffer); + gl::GLBuffer* cameraCorrectionBuffer = nullptr; + if (_transform._viewCorrectionEnabled) { + cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBuffer._buffer); + } else { + cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBufferIdentity._buffer); + } glBindBufferRange(GL_UNIFORM_BUFFER, _pipeline._cameraCorrectionLocation, cameraCorrectionBuffer->_id, 0, sizeof(CameraCorrection)); + } (void) CHECK_GL_ERROR(); _pipeline._invalidProgram = false; diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp index 01f055e0d9..f286a5cca9 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp @@ -102,7 +102,7 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo if (_invalidView) { // Apply the correction - if (_viewIsCamera && _correction.correction != glm::mat4()) { + if (_viewIsCamera && (_viewCorrectionEnabled && _correction.correction != glm::mat4())) { // FIXME should I switch to using the camera correction buffer in Transform.slf and leave this out? Transform result; _view.mult(result, _view, _correction.correction); diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 15c0dfce49..c432e19368 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -390,6 +390,13 @@ void Batch::resetStages() { ADD_COMMAND(resetStages); } +void Batch::disableContextViewCorrection() { + ADD_COMMAND(disableContextViewCorrection); +} + +void Batch::restoreContextViewCorrection() { + ADD_COMMAND(restoreContextViewCorrection); +} void Batch::disableContextStereo() { ADD_COMMAND(disableContextStereo); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 27c9402131..77d22258b2 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -217,6 +217,9 @@ public: // Reset the stage caches and states void resetStages(); + void disableContextViewCorrection(); + void restoreContextViewCorrection(); + void disableContextStereo(); void restoreContextStereo(); @@ -304,6 +307,9 @@ public: COMMAND_resetStages, + COMMAND_disableContextViewCorrection, + COMMAND_restoreContextViewCorrection, + COMMAND_disableContextStereo, COMMAND_restoreContextStereo, diff --git a/libraries/render-utils/src/DeferredFrameTransform.cpp b/libraries/render-utils/src/DeferredFrameTransform.cpp index b1166437db..baf523312c 100644 --- a/libraries/render-utils/src/DeferredFrameTransform.cpp +++ b/libraries/render-utils/src/DeferredFrameTransform.cpp @@ -39,7 +39,7 @@ void DeferredFrameTransform::update(RenderArgs* args) { args->getViewFrustum().evalProjectionMatrix(frameTransformBuffer.projectionMono); // Running in stero ? - bool isStereo = args->_context->isStereo(); + bool isStereo = args->isStereo(); if (!isStereo) { frameTransformBuffer.projection[0] = frameTransformBuffer.projectionMono; frameTransformBuffer.stereoInfo = glm::vec4(0.0f, (float)args->_viewport.z, 0.0f, 0.0f); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index b49a066bf7..20c999019b 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -406,7 +406,7 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer batch.setFramebuffer(blitFbo); if (renderArgs->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - if (renderArgs->_context->isStereo()) { + if (renderArgs->isStereo()) { gpu::Vec4i srcRectLeft; srcRectLeft.z = width / 2; srcRectLeft.w = height; diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp index 1941766353..c4eea7ce7f 100644 --- a/libraries/render-utils/src/SurfaceGeometryPass.cpp +++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp @@ -459,7 +459,7 @@ void SurfaceGeometryPass::run(const render::RenderContextPointer& renderContext, auto diffuseVPipeline = _diffusePass.getBlurVPipeline(); auto diffuseHPipeline = _diffusePass.getBlurHPipeline(); - _diffusePass.getParameters()->setWidthHeight(curvatureViewport.z, curvatureViewport.w, args->_context->isStereo()); + _diffusePass.getParameters()->setWidthHeight(curvatureViewport.z, curvatureViewport.w, args->isStereo()); glm::ivec2 textureSize(curvatureTexture->getDimensions()); _diffusePass.getParameters()->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, curvatureViewport)); _diffusePass.getParameters()->setDepthPerspective(args->getViewFrustum().getProjection()[1][1]); diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index a75488ce7a..c2e03d4f46 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -99,6 +99,8 @@ namespace render { void pushViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustums.push(viewFrustum); } void popViewFrustum() { _viewFrustums.pop(); } + bool isStereo() const { return _displayMode != MONO; } + std::shared_ptr _context; std::shared_ptr _blitFramebuffer; std::shared_ptr _pipeline; diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp index 0a6b3d16fc..73a8e0a0dd 100644 --- a/libraries/render/src/render/BlurTask.cpp +++ b/libraries/render/src/render/BlurTask.cpp @@ -217,7 +217,7 @@ void BlurGaussian::run(const RenderContextPointer& renderContext, const gpu::Fra auto blurVPipeline = getBlurVPipeline(); auto blurHPipeline = getBlurHPipeline(); - _parameters->setWidthHeight(args->_viewport.z, args->_viewport.w, args->_context->isStereo()); + _parameters->setWidthHeight(args->_viewport.z, args->_viewport.w, args->isStereo()); glm::ivec2 textureSize(blurringResources.sourceTexture->getDimensions()); _parameters->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, args->_viewport)); @@ -330,7 +330,7 @@ void BlurGaussianDepthAware::run(const RenderContextPointer& renderContext, cons auto sourceViewport = args->_viewport; - _parameters->setWidthHeight(sourceViewport.z, sourceViewport.w, args->_context->isStereo()); + _parameters->setWidthHeight(sourceViewport.z, sourceViewport.w, args->isStereo()); glm::ivec2 textureSize(blurringResources.sourceTexture->getDimensions()); _parameters->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, sourceViewport)); _parameters->setDepthPerspective(args->getViewFrustum().getProjection()[1][1]); From 93963b32577737dfc469e7bd80f7dfd64f0f03e9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 28 Jun 2017 15:44:17 +0200 Subject: [PATCH 24/47] Apply the projection and deferred transform fixes found while working on spectator camera --- interface/src/SecondaryCamera.cpp | 2 ++ libraries/gpu-gl/src/gpu/gl/GLBackend.cpp | 11 ++++++++++- libraries/gpu-gl/src/gpu/gl/GLBackend.h | 9 +++++++++ libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp | 8 +++++++- libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp | 2 +- libraries/gpu/src/gpu/Batch.cpp | 7 +++++++ libraries/gpu/src/gpu/Batch.h | 6 ++++++ libraries/render-utils/src/DeferredFrameTransform.cpp | 2 +- libraries/render-utils/src/RenderDeferredTask.cpp | 2 +- libraries/render-utils/src/SurfaceGeometryPass.cpp | 2 +- libraries/render/src/render/Args.h | 2 ++ libraries/render/src/render/BlurTask.cpp | 4 ++-- 12 files changed, 49 insertions(+), 8 deletions(-) diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index f6ee8caa61..f59d2fcc7a 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -79,6 +79,7 @@ public: gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.disableContextStereo(); + batch.disableContextViewCorrection(); }); auto srcViewFrustum = args->getViewFrustum(); @@ -112,6 +113,7 @@ public: gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.restoreContextStereo(); + batch.restoreContextViewCorrection(); }); } }; diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index 3441407f62..11e67811b6 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -114,7 +114,9 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::gl::GLBackend::do_getQuery), (&::gpu::gl::GLBackend::do_resetStages), - + + (&::gpu::gl::GLBackend::do_disableContextViewCorrection), + (&::gpu::gl::GLBackend::do_restoreContextViewCorrection), (&::gpu::gl::GLBackend::do_disableContextStereo), (&::gpu::gl::GLBackend::do_restoreContextStereo), @@ -374,6 +376,13 @@ void GLBackend::do_resetStages(const Batch& batch, size_t paramOffset) { resetStages(); } +void GLBackend::do_disableContextViewCorrection(const Batch& batch, size_t paramOffset) { + _transform._viewCorrectionEnabled = false; +} + +void GLBackend::do_restoreContextViewCorrection(const Batch& batch, size_t paramOffset) { + _transform._viewCorrectionEnabled = true; +} void GLBackend::do_disableContextStereo(const Batch& batch, size_t paramOffset) { diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.h b/libraries/gpu-gl/src/gpu/gl/GLBackend.h index 96217555e1..88aecda617 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.h @@ -143,6 +143,10 @@ public: // Reset stages virtual void do_resetStages(const Batch& batch, size_t paramOffset) final; + + virtual void do_disableContextViewCorrection(const Batch& batch, size_t paramOffset) final; + virtual void do_restoreContextViewCorrection(const Batch& batch, size_t paramOffset) final; + virtual void do_disableContextStereo(const Batch& batch, size_t paramOffset) final; virtual void do_restoreContextStereo(const Batch& batch, size_t paramOffset) final; @@ -333,6 +337,8 @@ protected: bool _skybox { false }; Transform _view; CameraCorrection _correction; + bool _viewCorrectionEnabled{ true }; + Mat4 _projection; Vec4i _viewport { 0, 0, 1, 1 }; @@ -400,6 +406,7 @@ protected: bool _invalidProgram { false }; BufferView _cameraCorrectionBuffer { gpu::BufferView(std::make_shared(sizeof(CameraCorrection), nullptr )) }; + BufferView _cameraCorrectionBufferIdentity { gpu::BufferView(std::make_shared(sizeof(CameraCorrection), nullptr )) }; State::Data _stateCache{ State::DEFAULT }; State::Signature _stateSignatureCache { 0 }; @@ -409,6 +416,8 @@ protected: PipelineStageState() { _cameraCorrectionBuffer.edit() = CameraCorrection(); + _cameraCorrectionBufferIdentity.edit() = CameraCorrection(); + _cameraCorrectionBufferIdentity._buffer->flush(); } } _pipeline; diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp index 2d71e8ed78..7ef64343ea 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendPipeline.cpp @@ -77,8 +77,14 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) { if (_pipeline._invalidProgram) { glUseProgram(_pipeline._program); if (_pipeline._cameraCorrectionLocation != -1) { - auto cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBuffer._buffer); + gl::GLBuffer* cameraCorrectionBuffer = nullptr; + if (_transform._viewCorrectionEnabled) { + cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBuffer._buffer); + } else { + cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBufferIdentity._buffer); + } glBindBufferRange(GL_UNIFORM_BUFFER, _pipeline._cameraCorrectionLocation, cameraCorrectionBuffer->_id, 0, sizeof(CameraCorrection)); + } (void) CHECK_GL_ERROR(); _pipeline._invalidProgram = false; diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp index 01f055e0d9..f286a5cca9 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackendTransform.cpp @@ -102,7 +102,7 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo if (_invalidView) { // Apply the correction - if (_viewIsCamera && _correction.correction != glm::mat4()) { + if (_viewIsCamera && (_viewCorrectionEnabled && _correction.correction != glm::mat4())) { // FIXME should I switch to using the camera correction buffer in Transform.slf and leave this out? Transform result; _view.mult(result, _view, _correction.correction); diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 15c0dfce49..c432e19368 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -390,6 +390,13 @@ void Batch::resetStages() { ADD_COMMAND(resetStages); } +void Batch::disableContextViewCorrection() { + ADD_COMMAND(disableContextViewCorrection); +} + +void Batch::restoreContextViewCorrection() { + ADD_COMMAND(restoreContextViewCorrection); +} void Batch::disableContextStereo() { ADD_COMMAND(disableContextStereo); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 27c9402131..77d22258b2 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -217,6 +217,9 @@ public: // Reset the stage caches and states void resetStages(); + void disableContextViewCorrection(); + void restoreContextViewCorrection(); + void disableContextStereo(); void restoreContextStereo(); @@ -304,6 +307,9 @@ public: COMMAND_resetStages, + COMMAND_disableContextViewCorrection, + COMMAND_restoreContextViewCorrection, + COMMAND_disableContextStereo, COMMAND_restoreContextStereo, diff --git a/libraries/render-utils/src/DeferredFrameTransform.cpp b/libraries/render-utils/src/DeferredFrameTransform.cpp index b1166437db..baf523312c 100644 --- a/libraries/render-utils/src/DeferredFrameTransform.cpp +++ b/libraries/render-utils/src/DeferredFrameTransform.cpp @@ -39,7 +39,7 @@ void DeferredFrameTransform::update(RenderArgs* args) { args->getViewFrustum().evalProjectionMatrix(frameTransformBuffer.projectionMono); // Running in stero ? - bool isStereo = args->_context->isStereo(); + bool isStereo = args->isStereo(); if (!isStereo) { frameTransformBuffer.projection[0] = frameTransformBuffer.projectionMono; frameTransformBuffer.stereoInfo = glm::vec4(0.0f, (float)args->_viewport.z, 0.0f, 0.0f); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index b49a066bf7..20c999019b 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -406,7 +406,7 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer batch.setFramebuffer(blitFbo); if (renderArgs->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { - if (renderArgs->_context->isStereo()) { + if (renderArgs->isStereo()) { gpu::Vec4i srcRectLeft; srcRectLeft.z = width / 2; srcRectLeft.w = height; diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp index 1941766353..c4eea7ce7f 100644 --- a/libraries/render-utils/src/SurfaceGeometryPass.cpp +++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp @@ -459,7 +459,7 @@ void SurfaceGeometryPass::run(const render::RenderContextPointer& renderContext, auto diffuseVPipeline = _diffusePass.getBlurVPipeline(); auto diffuseHPipeline = _diffusePass.getBlurHPipeline(); - _diffusePass.getParameters()->setWidthHeight(curvatureViewport.z, curvatureViewport.w, args->_context->isStereo()); + _diffusePass.getParameters()->setWidthHeight(curvatureViewport.z, curvatureViewport.w, args->isStereo()); glm::ivec2 textureSize(curvatureTexture->getDimensions()); _diffusePass.getParameters()->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, curvatureViewport)); _diffusePass.getParameters()->setDepthPerspective(args->getViewFrustum().getProjection()[1][1]); diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index a75488ce7a..c2e03d4f46 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -99,6 +99,8 @@ namespace render { void pushViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustums.push(viewFrustum); } void popViewFrustum() { _viewFrustums.pop(); } + bool isStereo() const { return _displayMode != MONO; } + std::shared_ptr _context; std::shared_ptr _blitFramebuffer; std::shared_ptr _pipeline; diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp index 0a6b3d16fc..73a8e0a0dd 100644 --- a/libraries/render/src/render/BlurTask.cpp +++ b/libraries/render/src/render/BlurTask.cpp @@ -217,7 +217,7 @@ void BlurGaussian::run(const RenderContextPointer& renderContext, const gpu::Fra auto blurVPipeline = getBlurVPipeline(); auto blurHPipeline = getBlurHPipeline(); - _parameters->setWidthHeight(args->_viewport.z, args->_viewport.w, args->_context->isStereo()); + _parameters->setWidthHeight(args->_viewport.z, args->_viewport.w, args->isStereo()); glm::ivec2 textureSize(blurringResources.sourceTexture->getDimensions()); _parameters->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, args->_viewport)); @@ -330,7 +330,7 @@ void BlurGaussianDepthAware::run(const RenderContextPointer& renderContext, cons auto sourceViewport = args->_viewport; - _parameters->setWidthHeight(sourceViewport.z, sourceViewport.w, args->_context->isStereo()); + _parameters->setWidthHeight(sourceViewport.z, sourceViewport.w, args->isStereo()); glm::ivec2 textureSize(blurringResources.sourceTexture->getDimensions()); _parameters->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, sourceViewport)); _parameters->setDepthPerspective(args->getViewFrustum().getProjection()[1][1]); From d3282a4ed06d203c74b9f9fb0272f57aa18a929e Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Wed, 28 Jun 2017 15:56:35 +0200 Subject: [PATCH 25/47] Cleanup --- .../resources/qml/dialogs/TabletFileDialog.qml | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/dialogs/TabletFileDialog.qml b/interface/resources/qml/dialogs/TabletFileDialog.qml index f77cc7c78a..9e1d0a9f5a 100644 --- a/interface/resources/qml/dialogs/TabletFileDialog.qml +++ b/interface/resources/qml/dialogs/TabletFileDialog.qml @@ -293,7 +293,7 @@ TabletModalWindow { } onFolderChanged: { - refreshTimer.start() + fileTableModel.update() } function getItem(index, field) { @@ -333,14 +333,6 @@ TabletModalWindow { } } - Timer { - id: refreshTimer - interval: 100 - repeat: false - running: false - onTriggered: fileTableModel.update() - } - Component { id: filesModelBuilder ListModel { } @@ -377,17 +369,16 @@ TabletModalWindow { } onFolderChanged: { + if (folder === rootFolder) { model = driveListModel; helper.monitorDirectory(""); update(); } else { var needsUpdate = model === driveListModel && folder === folderListModel.folder; - model = folderListModel; folderListModel.folder = folder; helper.monitorDirectory(helper.urlToPath(folder)); - if (needsUpdate) { update(); } @@ -420,7 +411,6 @@ TabletModalWindow { rows = 0, i; - console.log("dialog.qml updating") var newFilesModel = filesModelBuilder.createObject(root); comparisonFunction = sortOrder === Qt.AscendingOrder From 51b44d90213e823280233088f8b5d6c84a0a73a1 Mon Sep 17 00:00:00 2001 From: Vladyslav Stelmakhovskyi Date: Wed, 28 Jun 2017 16:36:25 +0200 Subject: [PATCH 26/47] Implement same for HMD mode --- .../resources/qml/dialogs/FileDialog.qml | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/interface/resources/qml/dialogs/FileDialog.qml b/interface/resources/qml/dialogs/FileDialog.qml index 0886a25949..106e067968 100644 --- a/interface/resources/qml/dialogs/FileDialog.qml +++ b/interface/resources/qml/dialogs/FileDialog.qml @@ -34,6 +34,8 @@ ModalWindow { HifiConstants { id: hifi } + property var filesModel: ListModel { } + Settings { category: "FileDialog" property alias width: root.width @@ -253,7 +255,9 @@ ModalWindow { } currentSelectionUrl = helper.pathToUrl(fileTableView.model.get(row).filePath); - currentSelectionIsFolder = fileTableView.model.isFolder(row); + currentSelectionIsFolder = fileTableView.model !== filesModel ? + fileTableView.model.isFolder(row) : + fileTableModel.isFolder(row); if (root.selectDirectory || !currentSelectionIsFolder) { currentSelection.text = capitalizeDrive(helper.urlToPath(currentSelectionUrl)); } else { @@ -331,7 +335,12 @@ ModalWindow { } } - ListModel { + Component { + id: filesModelBuilder + ListModel { } + } + + QtObject { id: fileTableModel // FolderListModel has a couple of problems: @@ -383,7 +392,11 @@ ModalWindow { if (row === -1) { return false; } - return get(row).fileIsDir; + return filesModel.get(row).fileIsDir; + } + + function get(row) { + return filesModel.get(row) } function update() { @@ -401,7 +414,7 @@ ModalWindow { rows = 0, i; - clear(); + var newFilesModel = filesModelBuilder.createObject(root); comparisonFunction = sortOrder === Qt.AscendingOrder ? function(a, b) { return a < b; } @@ -423,7 +436,7 @@ ModalWindow { while (lower < upper) { middle = Math.floor((lower + upper) / 2); var lessThan; - if (comparisonFunction(sortValue, get(middle)[sortField])) { + if (comparisonFunction(sortValue, newFilesModel.get(middle)[sortField])) { lessThan = true; upper = middle; } else { @@ -432,7 +445,7 @@ ModalWindow { } } - insert(lower, { + newFilesModel.insert(lower, { fileName: fileName, fileModified: (fileIsDir ? new Date(0) : model.getItem(i, "fileModified")), fileSize: model.getItem(i, "fileSize"), @@ -443,6 +456,7 @@ ModalWindow { rows++; } + filesModel = newFilesModel; d.clearSelection(); } @@ -469,7 +483,7 @@ ModalWindow { sortIndicatorOrder: Qt.AscendingOrder sortIndicatorVisible: true - model: fileTableModel + model: filesModel function updateSort() { model.sortOrder = sortIndicatorOrder; @@ -561,11 +575,12 @@ ModalWindow { } function navigateToCurrentRow() { + var currentModel = fileTableView.model !== filesModel ? fileTableView.model : fileTableModel var row = fileTableView.currentRow - var isFolder = model.isFolder(row); - var file = model.get(row).filePath; + var isFolder = currentModel.isFolder(row); + var file = currentModel.get(row).filePath; if (isFolder) { - fileTableView.model.folder = helper.pathToUrl(file); + currentModel.folder = helper.pathToUrl(file); } else { okAction.trigger(); } @@ -580,7 +595,8 @@ ModalWindow { var newPrefix = prefix + event.text.toLowerCase(); var matchedIndex = -1; for (var i = 0; i < model.count; ++i) { - var name = model.get(i).fileName.toLowerCase(); + var name = model !== filesModel ? model.get(i).fileName.toLowerCase() : + filesModel.get(i).fileName.toLowerCase(); if (0 === name.indexOf(newPrefix)) { matchedIndex = i; break; From f6ba264de67ff3bbc31441f19588b96ce020078b Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 28 Jun 2017 16:22:28 +0100 Subject: [PATCH 27/47] avatar recording fix --- libraries/avatars/src/AvatarData.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 1147b8a811..5023bd7ae5 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1978,7 +1978,7 @@ JointData jointDataFromJsonValue(const QJsonValue& json) { result.rotation = quatFromJsonValue(array[0]); result.rotationSet = true; result.translation = vec3FromJsonValue(array[1]); - result.translationSet = false; + result.translationSet = true; } return result; } @@ -2146,12 +2146,9 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) { QVector jointArray; QJsonArray jointArrayJson = json[JSON_AVATAR_JOINT_ARRAY].toArray(); jointArray.reserve(jointArrayJson.size()); - int i = 0; for (const auto& jointJson : jointArrayJson) { auto joint = jointDataFromJsonValue(jointJson); jointArray.push_back(joint); - setJointData(i, joint.rotation, joint.translation); - i++; } setRawJointData(jointArray); } From 0acbdc7755e925e7ba498583ca0252e1a04a10db Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 28 Jun 2017 10:18:54 -0700 Subject: [PATCH 28/47] CR fix: use predefined PI --- libraries/shared/src/AudioHelpers.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/AudioHelpers.h b/libraries/shared/src/AudioHelpers.h index d75733e678..1dcc11af0c 100644 --- a/libraries/shared/src/AudioHelpers.h +++ b/libraries/shared/src/AudioHelpers.h @@ -14,6 +14,8 @@ #include +#include + const int IEEE754_MANT_BITS = 23; const int IEEE754_EXPN_BIAS = 127; @@ -105,7 +107,7 @@ static inline float fastAcosf(float x) { xi.f = ((-0.0198439236f * xi.f + 0.0762021306f) * xi.f + -0.212940971f) * xi.f + 1.57079633f; xi.f *= r; - return (sign ? 3.141592654f - xi.f : xi.f); + return (sign ? PI - xi.f : xi.f); } // From fedbc28da45bf28fe8d0008a92d40f0dd41637a2 Mon Sep 17 00:00:00 2001 From: Patrick Manalich Date: Wed, 28 Jun 2017 10:47:34 -0700 Subject: [PATCH 29/47] Rotation quaternion fix --- scripts/system/spectatorCamera.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 685df66ba2..b3cc17ad74 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -132,7 +132,7 @@ emissive: true, parentID: camera, alpha: 1, - localRotation: { x: 0, y: 0, z: 0 }, + localRotation: { w: 1, x: 0, y: 0, z: 0 }, localPosition: { x: 0.007, y: 0.15, z: -0.005 }, dimensions: viewFinderOverlayDim }); @@ -322,7 +322,7 @@ emissive: true, parentID: camera, alpha: 1, - localRotation: { x: 0, y: 0, z: 0 }, + localRotation: { w: 1, x: 0, y: 0, z: 0 }, localPosition: { x: 0.007, y: 0.15, z: -0.005 }, dimensions: viewFinderOverlayDim }); From 2f3109e4beb86222227fcd89d53211626184407e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 28 Jun 2017 11:00:05 -0700 Subject: [PATCH 30/47] move the location of Q_DECLARE_METATYPE(std::function) so that the server-script AC can see it --- libraries/shared/src/RegisteredMetaTypes.cpp | 2 ++ libraries/shared/src/RegisteredMetaTypes.h | 2 ++ libraries/ui/src/ui/OffscreenQmlSurface.cpp | 6 ------ 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 1e5fe23458..b30637c83f 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -37,6 +37,8 @@ int pickRayMetaTypeId = qRegisterMetaType(); int collisionMetaTypeId = qRegisterMetaType(); int qMapURLStringMetaTypeId = qRegisterMetaType>(); int socketErrorMetaTypeId = qRegisterMetaType(); +int voidLambdaType = qRegisterMetaType>(); +int variantLambdaType = qRegisterMetaType>(); void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, mat4toScriptValue, mat4FromScriptValue); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index dd37cb3410..123c769a96 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -34,6 +34,8 @@ Q_DECLARE_METATYPE(xColor) Q_DECLARE_METATYPE(QVector) Q_DECLARE_METATYPE(QVector) Q_DECLARE_METATYPE(AACube) +Q_DECLARE_METATYPE(std::function); +Q_DECLARE_METATYPE(std::function); void registerMetaTypes(QScriptEngine* engine); diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index f0006cb399..648bdad1bf 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -886,12 +886,6 @@ QQmlContext* OffscreenQmlSurface::getSurfaceContext() { return _qmlContext; } -Q_DECLARE_METATYPE(std::function); -auto VoidLambdaType = qRegisterMetaType>(); -Q_DECLARE_METATYPE(std::function); -auto VariantLambdaType = qRegisterMetaType>(); - - void OffscreenQmlSurface::executeOnUiThread(std::function function, bool blocking ) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "executeOnUiThread", blocking ? Qt::BlockingQueuedConnection : Qt::QueuedConnection, From 252d100a5eb7eb9a3614b2e1acb007832db690d9 Mon Sep 17 00:00:00 2001 From: Patrick Manalich Date: Wed, 28 Jun 2017 11:31:40 -0700 Subject: [PATCH 31/47] Function updateOverlay() made so we don't repeat code --- scripts/system/spectatorCamera.js | 40 ++++++++++++++----------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index b3cc17ad74..97fadb7e6f 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -127,15 +127,7 @@ "userData": "{\"grabbableKey\":{\"grabbable\":true}}" }, true); // This image3d overlay acts as the camera's preview screen. - viewFinderOverlay = Overlays.addOverlay("image3d", { - url: "resource://spectatorCameraFrame", - emissive: true, - parentID: camera, - alpha: 1, - localRotation: { w: 1, x: 0, y: 0, z: 0 }, - localPosition: { x: 0.007, y: 0.15, z: -0.005 }, - dimensions: viewFinderOverlayDim - }); + updateOverlay(); setDisplay(monitorShowsCameraView); } @@ -284,6 +276,22 @@ setMonitorShowsCameraViewAndSendToQml(!monitorShowsCameraView); } } + function updateOverlay() { + // The only way I found to update the viewFinderOverlay without turning the spectator camera on and off is to delete and recreate the + // overlay, which is inefficient but resizing the window shouldn't be performed often + if (viewFinderOverlay) { + Overlays.deleteOverlay(viewFinderOverlay); + } + viewFinderOverlay = Overlays.addOverlay("image3d", { + url: "resource://spectatorCameraFrame", + emissive: true, + parentID: camera, + alpha: 1, + localRotation: { w: 1, x: 0, y: 0, z: 0 }, + localPosition: { x: 0.007, y: 0.15, z: -0.005 }, + dimensions: viewFinderOverlayDim + }); + } // // Function Name: resizeViewFinderOverlay() @@ -313,19 +321,7 @@ } else { //horizontal window size viewFinderOverlayDim = { x: glassPaneWidth, y: -glassPaneWidth, z: 0 }; } - - // The only way I found to update the viewFinderOverlay without turning the spectator camera on and off is to delete and recreate the - // overlay, which is inefficient but resizing the window shouldn't be performed often - Overlays.deleteOverlay(viewFinderOverlay); - viewFinderOverlay = Overlays.addOverlay("image3d", { - url: "resource://spectatorCameraFrame", - emissive: true, - parentID: camera, - alpha: 1, - localRotation: { w: 1, x: 0, y: 0, z: 0 }, - localPosition: { x: 0.007, y: 0.15, z: -0.005 }, - dimensions: viewFinderOverlayDim - }); + updateOverlay(); spectatorFrameRenderConfig.resetSizeSpectatorCamera(geometryChanged.width, geometryChanged.height); setDisplay(monitorShowsCameraView); } From 0dbb7a71f3831b69b86b8960e4e6b07cdd1d9143 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 28 Jun 2017 11:32:24 -0700 Subject: [PATCH 32/47] CR fix: comments instead of ref code --- libraries/audio-client/src/AudioClient.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 27e70e5f01..43af7afdef 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1702,9 +1702,8 @@ float AudioClient::azimuthForSource(const glm::vec3& relativePosition) { if (rotatedSourcePositionLength2 > SOURCE_DISTANCE_THRESHOLD) { // produce an oriented angle about the y-axis - // return glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), glm::normalize(rotatedSourcePosition), glm::vec3(0.0f, -1.0f, 0.0f)); glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2)); - float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); + float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward" return (direction.x < 0.0f) ? -angle : angle; } else { From a7a049434d733c3b3a8ed112697ce7a9c4824781 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Wed, 28 Jun 2017 11:32:41 -0700 Subject: [PATCH 33/47] CR fix: comments instead of ref code --- assignment-client/src/audio/AudioMixerSlave.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index 9cfc659c14..ed63bbc298 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -498,9 +498,9 @@ float computeGain(const AvatarAudioStream& listeningNodeStream, const Positional } else if (!isEcho && (streamToAdd.getType() == PositionalAudioStream::Microphone)) { glm::vec3 rotatedListenerPosition = glm::inverse(streamToAdd.getOrientation()) * relativePosition; - // float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), glm::normalize(rotatedListenerPosition)); + // source directivity is based on angle of emission, in local coordinates glm::vec3 direction = glm::normalize(rotatedListenerPosition); - float angleOfDelivery = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); + float angleOfDelivery = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward" const float MAX_OFF_AXIS_ATTENUATION = 0.2f; const float OFF_AXIS_ATTENUATION_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f; @@ -557,9 +557,8 @@ float computeAzimuth(const AvatarAudioStream& listeningNodeStream, const Positio if (rotatedSourcePositionLength2 > SOURCE_DISTANCE_THRESHOLD) { // produce an oriented angle about the y-axis - // return glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), glm::normalize(rotatedSourcePosition), glm::vec3(0.0f, -1.0f, 0.0f)); glm::vec3 direction = rotatedSourcePosition * (1.0f / fastSqrtf(rotatedSourcePositionLength2)); - float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); + float angle = fastAcosf(glm::clamp(-direction.z, -1.0f, 1.0f)); // UNIT_NEG_Z is "forward" return (direction.x < 0.0f) ? -angle : angle; } else { From 9bcaa6d2566bde83fb2a8febeaf0724add76600c Mon Sep 17 00:00:00 2001 From: Patrick Manalich Date: Wed, 28 Jun 2017 12:10:16 -0700 Subject: [PATCH 34/47] Revert "Messing around, howard please refer the commit before this one" This reverts commit 1392297da9b2ee5ff22ad90de50bec6c9dcb461a. --- scripts/system/spectatorCamera.js | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 6b867d4abc..7b60c14575 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -48,7 +48,6 @@ var viewFinderOverlay = false; var camera = false; var cameraIsDynamic = false; - var attachedToggle = false; var lastCameraPosition = false; var lastCameraRotation = false; function updateRenderFromCamera() { @@ -124,30 +123,6 @@ dimensions: viewFinderOverlayDim }); setDisplay(monitorShowsCameraView); - - attachedToggle = Entities.addEntity({ - "color": { - "blue": 0, - "green": 0, - "red": 255 - }, - parentID: camera, - localPosition: { x: 0.1, y: 0, z: -0.05 }, - localRotation: { w: 0.70708787441253662, x: 0, y: 0, z: 0.70708787441253662 }, - "dimensions": { - "x": 0.03, - "y": 0.03, - "z": 0.03 - }, - "queryAACube": { - "scale": 0.052, - "x": -0.026, - "y": -0.026, - "z": -0.026 - }, - "shape": "Cylinder", - "type": "Shape" - }, true); } // Function Name: spectatorCameraOff() @@ -167,12 +142,8 @@ if (viewFinderOverlay) { Overlays.deleteOverlay(viewFinderOverlay); } - if (attachedToggle) { - Entities.deleteEntity(attachedToggle); - } camera = false; viewFinderOverlay = false; - attachedToggle = false; setDisplay(monitorShowsCameraView); } @@ -225,7 +196,6 @@ HMD.displayModeChanged.connect(onHMDChanged); viewFinderOverlay = false; camera = false; - attachedToggle = false; registerButtonMappings(); } From 99ebd743e6bdf9f3ea223b1417d9b45cdb22d7da Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 27 Jun 2017 17:09:59 -0700 Subject: [PATCH 35/47] First steps --- scripts/system/spectatorCamera.js | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 97fadb7e6f..434ecaa033 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -58,18 +58,10 @@ var viewFinderOverlay = false; var camera = false; var cameraIsDynamic = false; - var lastCameraPosition = false; - var lastCameraRotation = false; function updateRenderFromCamera() { var cameraData = Entities.getEntityProperties(camera, ['position', 'rotation']); - if (JSON.stringify(lastCameraRotation) !== JSON.stringify(cameraData.rotation)) { - lastCameraRotation = cameraData.rotation; - beginSpectatorFrameRenderConfig.orientation = lastCameraRotation; - } - if (JSON.stringify(lastCameraPosition) !== JSON.stringify(cameraData.position)) { - lastCameraPosition = cameraData.position; - beginSpectatorFrameRenderConfig.position = Vec3.sum(inFrontOf(0.17, lastCameraPosition, lastCameraRotation), {x: 0, y: 0.02, z: 0}); - } + beginSpectatorFrameRenderConfig.orientation = cameraData.rotation; + beginSpectatorFrameRenderConfig.position = Vec3.sum(inFrontOf(0.17, cameraData.position, lastCameraRotation), {x: 0, y: 0.02, z: 0}); } // @@ -104,6 +96,7 @@ // the overlay since it is an Image3DOverlay so it is set to 0 var glassPaneWidth = 0.16; var viewFinderOverlayDim = { x: glassPaneWidth, y: -glassPaneWidth, z: 0 }; + var cameraUpdateInterval; function spectatorCameraOn() { // Sets the special texture size based on the window it is displayed in, which doesn't include the menu bar spectatorFrameRenderConfig.resetSizeSpectatorCamera(Window.innerWidth, Window.innerHeight); @@ -112,7 +105,7 @@ beginSpectatorFrameRenderConfig.nearClipPlaneDistance = nearClipPlaneDistance; beginSpectatorFrameRenderConfig.farClipPlaneDistance = farClipPlaneDistance; cameraRotation = MyAvatar.orientation, cameraPosition = inFrontOf(1, Vec3.sum(MyAvatar.position, { x: 0, y: 0.3, z: 0 })); - Script.update.connect(updateRenderFromCamera); + cameraUpdateInterval = Script.setInterval(updateRenderFromCamera, 10); isUpdateRenderWired = true; camera = Entities.addEntity({ "angularDamping": 0.98000001907348633, @@ -147,7 +140,7 @@ function spectatorCameraOff() { spectatorFrameRenderConfig.enabled = beginSpectatorFrameRenderConfig.enabled = false; if (isUpdateRenderWired) { - Script.update.disconnect(updateRenderFromCamera); + Script.clearInterval(cameraUpdateInterval); isUpdateRenderWired = false; } if (camera) { From c54a7a713c47d7df9efe6d2c513ecb7366458553 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 28 Jun 2017 11:33:18 -0700 Subject: [PATCH 36/47] New registration point; attempt to fix button interactions --- scripts/system/spectatorCamera.js | 119 ++++++++++++++++-------------- 1 file changed, 65 insertions(+), 54 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 434ecaa033..72e062338d 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -43,8 +43,6 @@ // camera: The in-world entity that corresponds to the spectator camera. // cameraIsDynamic: "false" for now while we figure out why dynamic, parented overlays // drift with respect to their parent - // lastCameraPosition: Holds the last known camera position - // lastCameraRotation: Holds the last known camera rotation // // Arguments: // None @@ -61,7 +59,7 @@ function updateRenderFromCamera() { var cameraData = Entities.getEntityProperties(camera, ['position', 'rotation']); beginSpectatorFrameRenderConfig.orientation = cameraData.rotation; - beginSpectatorFrameRenderConfig.position = Vec3.sum(inFrontOf(0.17, cameraData.position, lastCameraRotation), {x: 0, y: 0.02, z: 0}); + beginSpectatorFrameRenderConfig.position = cameraData.position; } // @@ -77,6 +75,7 @@ // cameraPosition: The position of the spectator camera // glassPaneWidth: The width of the glass pane above the spectator camera that holds the viewFinderOverlay // viewFinderOverlayDim: The x, y, and z dimensions of the viewFinderOverlay + // cameraUpdateInterval: Used when setting Script.setInterval() // // Arguments: // None @@ -105,14 +104,20 @@ beginSpectatorFrameRenderConfig.nearClipPlaneDistance = nearClipPlaneDistance; beginSpectatorFrameRenderConfig.farClipPlaneDistance = farClipPlaneDistance; cameraRotation = MyAvatar.orientation, cameraPosition = inFrontOf(1, Vec3.sum(MyAvatar.position, { x: 0, y: 0.3, z: 0 })); - cameraUpdateInterval = Script.setInterval(updateRenderFromCamera, 10); + cameraUpdateInterval = Script.setInterval(updateRenderFromCamera, 11); // Update every 11ms (90.9hz) isUpdateRenderWired = true; camera = Entities.addEntity({ - "angularDamping": 0.98000001907348633, - "collisionsWillMove": 0, - "damping": 0.98000001907348633, + "angularDamping": 1, + "damping": 1, + "collidesWith": "static,dynamic,kinematic,", + "collisionMask": 7, "dynamic": cameraIsDynamic, - "modelURL": "http://hifi-content.s3.amazonaws.com/alan/dev/spectator-camera.fbx?1", + "modelURL": "http://hifi-content.s3.amazonaws.com/alan/dev/spectator-camera.fbx?7", + "registrationPoint": { + "x": 0.53, + "y": 0.545, + "z": 0.2 + }, "rotation": cameraRotation, "position": cameraPosition, "shapeType": "simple-compound", @@ -160,7 +165,6 @@ // Relevant Variables: // button: The tablet button. // buttonName: The name of the button. - // tablet: The tablet instance to be modified. // showInDesktop: Set to "true" to show the "SPECTATOR" app in desktop mode // // Arguments: @@ -172,24 +176,25 @@ // var button = false; var buttonName = "SPECTATOR"; - var tablet = null; var showSpectatorInDesktop = true; function addOrRemoveButton(isShuttingDown, isHMDMode) { - if (!button) { - if ((isHMDMode || showSpectatorInDesktop) && !isShuttingDown) { - button = tablet.addButton({ - text: buttonName - }); - button.clicked.connect(onTabletButtonClicked); + if (tablet) { + if (!button) { + if ((isHMDMode || showSpectatorInDesktop) && !isShuttingDown) { + button = tablet.addButton({ + text: buttonName + }); + button.clicked.connect(onTabletButtonClicked); + } + } else if (button) { + if ((!showSpectatorInDesktop || isShuttingDown)) { + button.clicked.disconnect(onTabletButtonClicked); + tablet.removeButton(button); + button = false; + } + } else { + print("ERROR adding/removing Spectator button!"); } - } else if (button) { - if ((!showSpectatorInDesktop || isShuttingDown) && !isHMDMode) { - button.clicked.disconnect(onTabletButtonClicked); - tablet.removeButton(button); - button = false; - } - } else { - print("ERROR adding/removing Spectator button!"); } } @@ -197,7 +202,7 @@ // Function Name: startup() // // Relevant Variables: - // None + // tablet: The tablet instance to be modified. // // Arguments: // None @@ -205,6 +210,7 @@ // Description: // startup() will be called when the script is loaded. // + var tablet = null; function startup() { tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); addOrRemoveButton(false, HMD.active); @@ -232,15 +238,17 @@ // var hasEventBridge = false; function wireEventBridge(on) { - if (on) { - if (!hasEventBridge) { - tablet.fromQml.connect(fromQml); - hasEventBridge = true; - } - } else { - if (hasEventBridge) { - tablet.fromQml.disconnect(fromQml); - hasEventBridge = false; + if (tablet) { + if (on) { + if (!hasEventBridge) { + tablet.fromQml.connect(fromQml); + hasEventBridge = true; + } + } else { + if (hasEventBridge) { + tablet.fromQml.disconnect(fromQml); + hasEventBridge = false; + } } } } @@ -281,7 +289,7 @@ parentID: camera, alpha: 1, localRotation: { w: 1, x: 0, y: 0, z: 0 }, - localPosition: { x: 0.007, y: 0.15, z: -0.005 }, + localPosition: { x: 0, y: 0.13, z: 0.112 }, dimensions: viewFinderOverlayDim }); } @@ -387,9 +395,8 @@ // Function Name: onTabletButtonClicked() // // Relevant Variables: + // SPECTATOR_CAMERA_QML_SOURCE: The path to the SpectatorCamera QML // onSpectatorCameraScreen: true/false depending on whether we're looking at the spectator camera app - // shouldActivateButton: true/false depending on whether we should show the button as white or gray the - // next time we edit the button's properties // // Arguments: // None @@ -397,20 +404,20 @@ // Description: // Fired when the Spectator Camera app button is pressed. // + var SPECTATOR_CAMERA_QML_SOURCE = "../SpectatorCamera.qml"; var onSpectatorCameraScreen = false; - var shouldActivateButton = false; function onTabletButtonClicked() { - if (onSpectatorCameraScreen) { - // for toolbar-mode: go back to home screen, this will close the window. - tablet.gotoHomeScreen(); - } else { - shouldActivateButton = true; - tablet.loadQMLSource("../SpectatorCamera.qml"); - onSpectatorCameraScreen = true; - sendToQml({ method: 'updateSpectatorCameraCheckbox', params: !!camera }); - sendToQml({ method: 'updateMonitorShowsSwitch', params: monitorShowsCameraView }); - sendToQml({ method: 'updateControllerMappingCheckbox', setting: switchViewFromController, controller: controllerType }); - Menu.setIsOptionChecked("Disable Preview", false); + if (tablet) { + if (onSpectatorCameraScreen) { + // for toolbar-mode: go back to home screen, this will close the window. + tablet.gotoHomeScreen(); + } else { + tablet.loadQMLSource(SPECTATOR_CAMERA_QML_SOURCE); + sendToQml({ method: 'updateSpectatorCameraCheckbox', params: !!camera }); + sendToQml({ method: 'updateMonitorShowsSwitch', params: monitorShowsCameraView }); + sendToQml({ method: 'updateControllerMappingCheckbox', setting: switchViewFromController, controller: controllerType }); + Menu.setIsOptionChecked("Disable Preview", false); + } } } @@ -428,13 +435,12 @@ // Called when the TabletScriptingInterface::screenChanged() signal is emitted. // function onTabletScreenChanged(type, url) { - wireEventBridge(shouldActivateButton); + onSpectatorCameraScreen = (type === "QML" && url === SPECTATOR_CAMERA_QML_SOURCE); + wireEventBridge(onSpectatorCameraScreen); // for toolbar mode: change button to active when window is first openend, false otherwise. if (button) { - button.editProperties({ isActive: shouldActivateButton }); + button.editProperties({ isActive: onSpectatorCameraScreen }); } - shouldActivateButton = false; - onSpectatorCameraScreen = false; } // @@ -523,7 +529,12 @@ Window.domainChanged.disconnect(spectatorCameraOff); Window.geometryChanged.disconnect(resizeViewFinderOverlay); addOrRemoveButton(true, HMD.active); - tablet.screenChanged.disconnect(onTabletScreenChanged); + if (tablet) { + tablet.screenChanged.disconnect(onTabletScreenChanged); + if (onSpectatorCameraScreen) { + tablet.gotoHomeScreen(); + } + } HMD.displayModeChanged.disconnect(onHMDChanged); Controller.keyPressEvent.disconnect(keyPressEvent); controllerMapping.disable(); From 3e7b1b5696ef5590604334d278814449ec168ded Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 28 Jun 2017 12:44:34 -0700 Subject: [PATCH 37/47] Slightly update registration point --- scripts/system/spectatorCamera.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 72e062338d..cf4df65e54 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -116,7 +116,7 @@ "registrationPoint": { "x": 0.53, "y": 0.545, - "z": 0.2 + "z": 0.16 }, "rotation": cameraRotation, "position": cameraPosition, @@ -289,7 +289,7 @@ parentID: camera, alpha: 1, localRotation: { w: 1, x: 0, y: 0, z: 0 }, - localPosition: { x: 0, y: 0.13, z: 0.112 }, + localPosition: { x: 0, y: 0.13, z: 0.126 }, dimensions: viewFinderOverlayDim }); } From 39ae28bfcfed8548cc7f713f4cff2f9c7b968ac0 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 28 Jun 2017 12:54:40 -0700 Subject: [PATCH 38/47] CR feedback --- scripts/system/spectatorCamera.js | 63 +++++++++++++++---------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index cf4df65e54..0f2adb664f 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -66,8 +66,6 @@ // Function Name: spectatorCameraOn() // // Relevant Variables: - // isUpdateRenderWired: Bool storing whether or not the camera's update - // function is wired. // vFoV: The vertical field of view of the spectator camera // nearClipPlaneDistance: The near clip plane distance of the spectator camera (aka "camera") // farClipPlaneDistance: The far clip plane distance of the spectator camera @@ -76,6 +74,7 @@ // glassPaneWidth: The width of the glass pane above the spectator camera that holds the viewFinderOverlay // viewFinderOverlayDim: The x, y, and z dimensions of the viewFinderOverlay // cameraUpdateInterval: Used when setting Script.setInterval() + // CAMERA_UPDATE_INTERVAL_MS: Defines the time between calls to updateRenderFromCamera() // // Arguments: // None @@ -84,7 +83,6 @@ // Call this function to set up the spectator camera and // spawn the camera entity. // - var isUpdateRenderWired = false; var vFoV = 45.0; var nearClipPlaneDistance = 0.1; var farClipPlaneDistance = 100.0; @@ -96,6 +94,7 @@ var glassPaneWidth = 0.16; var viewFinderOverlayDim = { x: glassPaneWidth, y: -glassPaneWidth, z: 0 }; var cameraUpdateInterval; + var CAMERA_UPDATE_INTERVAL_MS = 11; // Result of (1000 (ms/s)) / (90 (hz)) rounded down function spectatorCameraOn() { // Sets the special texture size based on the window it is displayed in, which doesn't include the menu bar spectatorFrameRenderConfig.resetSizeSpectatorCamera(Window.innerWidth, Window.innerHeight); @@ -105,7 +104,6 @@ beginSpectatorFrameRenderConfig.farClipPlaneDistance = farClipPlaneDistance; cameraRotation = MyAvatar.orientation, cameraPosition = inFrontOf(1, Vec3.sum(MyAvatar.position, { x: 0, y: 0.3, z: 0 })); cameraUpdateInterval = Script.setInterval(updateRenderFromCamera, 11); // Update every 11ms (90.9hz) - isUpdateRenderWired = true; camera = Entities.addEntity({ "angularDamping": 1, "damping": 1, @@ -144,10 +142,7 @@ // function spectatorCameraOff() { spectatorFrameRenderConfig.enabled = beginSpectatorFrameRenderConfig.enabled = false; - if (isUpdateRenderWired) { - Script.clearInterval(cameraUpdateInterval); - isUpdateRenderWired = false; - } + cameraUpdateInterval = Script.clearInterval(cameraUpdateInterval); if (camera) { Entities.deleteEntity(camera); } @@ -238,24 +233,26 @@ // var hasEventBridge = false; function wireEventBridge(on) { - if (tablet) { - if (on) { - if (!hasEventBridge) { - tablet.fromQml.connect(fromQml); - hasEventBridge = true; - } - } else { - if (hasEventBridge) { - tablet.fromQml.disconnect(fromQml); - hasEventBridge = false; - } + if (!tablet) { + print("Warning in wireEventBridge(): 'tablet' undefined!"); + return; + } + if (on) { + if (!hasEventBridge) { + tablet.fromQml.connect(fromQml); + hasEventBridge = true; + } + } else { + if (hasEventBridge) { + tablet.fromQml.disconnect(fromQml); + hasEventBridge = false; } } } function setDisplay(showCameraView) { - // It would be fancy if (showCameraView && !isUpdateRenderWired) would show instructions, but that's out of scope for now. - var url = (showCameraView && isUpdateRenderWired) ? "resource://spectatorCameraFrame" : ""; + // It would be fancy if (showCameraView && !cameraUpdateInterval) would show instructions, but that's out of scope for now. + var url = (showCameraView && cameraUpdateInterval) ? "resource://spectatorCameraFrame" : ""; Window.setDisplayTexture(url); } const MONITOR_SHOWS_CAMERA_VIEW_DEFAULT = false; @@ -407,17 +404,19 @@ var SPECTATOR_CAMERA_QML_SOURCE = "../SpectatorCamera.qml"; var onSpectatorCameraScreen = false; function onTabletButtonClicked() { - if (tablet) { - if (onSpectatorCameraScreen) { - // for toolbar-mode: go back to home screen, this will close the window. - tablet.gotoHomeScreen(); - } else { - tablet.loadQMLSource(SPECTATOR_CAMERA_QML_SOURCE); - sendToQml({ method: 'updateSpectatorCameraCheckbox', params: !!camera }); - sendToQml({ method: 'updateMonitorShowsSwitch', params: monitorShowsCameraView }); - sendToQml({ method: 'updateControllerMappingCheckbox', setting: switchViewFromController, controller: controllerType }); - Menu.setIsOptionChecked("Disable Preview", false); - } + if (!tablet) { + print("Warning in onTabletButtonClicked(): 'tablet' undefined!"); + return; + } + if (onSpectatorCameraScreen) { + // for toolbar-mode: go back to home screen, this will close the window. + tablet.gotoHomeScreen(); + } else { + tablet.loadQMLSource(SPECTATOR_CAMERA_QML_SOURCE); + sendToQml({ method: 'updateSpectatorCameraCheckbox', params: !!camera }); + sendToQml({ method: 'updateMonitorShowsSwitch', params: monitorShowsCameraView }); + sendToQml({ method: 'updateControllerMappingCheckbox', setting: switchViewFromController, controller: controllerType }); + Menu.setIsOptionChecked("Disable Preview", false); } } From 1bebe8aede48888d776693780cfc22175947d35e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 28 Jun 2017 13:49:05 -0700 Subject: [PATCH 39/47] Whoops! Missed an if() --- scripts/system/spectatorCamera.js | 34 ++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 0f2adb664f..92d45b9838 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -173,23 +173,25 @@ var buttonName = "SPECTATOR"; var showSpectatorInDesktop = true; function addOrRemoveButton(isShuttingDown, isHMDMode) { - if (tablet) { - if (!button) { - if ((isHMDMode || showSpectatorInDesktop) && !isShuttingDown) { - button = tablet.addButton({ - text: buttonName - }); - button.clicked.connect(onTabletButtonClicked); - } - } else if (button) { - if ((!showSpectatorInDesktop || isShuttingDown)) { - button.clicked.disconnect(onTabletButtonClicked); - tablet.removeButton(button); - button = false; - } - } else { - print("ERROR adding/removing Spectator button!"); + if (!tablet) { + print("Warning in addOrRemoveButton(): 'tablet' undefined!"); + return; + } + if (!button) { + if ((isHMDMode || showSpectatorInDesktop) && !isShuttingDown) { + button = tablet.addButton({ + text: buttonName + }); + button.clicked.connect(onTabletButtonClicked); } + } else if (button) { + if ((!showSpectatorInDesktop || isShuttingDown)) { + button.clicked.disconnect(onTabletButtonClicked); + tablet.removeButton(button); + button = false; + } + } else { + print("ERROR adding/removing Spectator button!"); } } From 48de8011b28c8241dd00626640871c62c6b00f98 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 28 Jun 2017 14:15:29 -0700 Subject: [PATCH 40/47] cr feedback --- interface/src/Application.cpp | 3 ++- interface/src/Application.h | 1 + interface/src/main.cpp | 6 ++++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 72e14656f3..a36b9ace93 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1185,7 +1185,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // we just want to see if --scripts was set, we've already parsed it and done // the change in PathUtils. Rather than pass that in the constructor, lets just // look (this could be debated) - QDir defaultScriptsLocation(getCmdOption(argc, constArgv, "--scripts")); + QString scriptsSwitch = QString("--").append(SCRIPTS_SWITCH); + QDir defaultScriptsLocation(getCmdOption(argc, constArgv, scriptsSwitch.toStdString().c_str())); if (!defaultScriptsLocation.exists()) { scriptEngines->loadDefaultScripts(); scriptEngines->defaultScriptsLocationOverridden(true); diff --git a/interface/src/Application.h b/interface/src/Application.h index a7aded006b..c26b3b215e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -95,6 +95,7 @@ static const UINT UWM_SHOW_APPLICATION = #endif static const QString RUNNING_MARKER_FILENAME = "Interface.running"; +static const QString SCRIPTS_SWITCH = "scripts"; class Application; #if defined(qApp) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index ac1b6d5010..ebe6ebc7b5 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -73,7 +73,7 @@ int main(int argc, const char* argv[]) { QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath"); QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run"); QCommandLineOption overrideAppLocalDataPathOption("cache", "set test cache ", "dir"); - QCommandLineOption overrideScriptsPathOption("scripts", "set scripts ", "path"); + QCommandLineOption overrideScriptsPathOption(SCRIPTS_SWITCH, "set scripts ", "path"); parser.addOption(urlOption); parser.addOption(noUpdaterOption); parser.addOption(checkMinSpecOption); @@ -101,7 +101,9 @@ int main(int argc, const char* argv[]) { if (allowMultipleInstances) { instanceMightBeRunning = false; } - + // this needs to be done here in main, as the mechanism for setting the + // scripts directory appears not to work. See the bug report + // https://highfidelity.fogbugz.com/f/cases/5759/Issues-changing-scripts-directory-in-ScriptsEngine if (parser.isSet(overrideScriptsPathOption)) { QDir scriptsPath(parser.value(overrideScriptsPathOption)); if (scriptsPath.exists()) { From 794495c197e1e99a380117cc6cef104455819b6d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 28 Jun 2017 14:18:14 -0700 Subject: [PATCH 41/47] make ResourceManager be owned by DependencyManager --- assignment-client/src/Agent.cpp | 7 ++-- .../src/entities/EntityServer.cpp | 2 +- .../src/scripts/EntityScriptServer.cpp | 7 ++-- interface/src/Application.cpp | 6 ++-- interface/src/assets/ATPAssetMigrator.cpp | 3 +- interface/src/main.cpp | 2 +- .../src/scripting/TestScriptingInterface.cpp | 2 +- .../src/EntityTreeRenderer.cpp | 2 +- libraries/entities/src/EntityEditFilters.cpp | 2 +- libraries/fbx/src/OBJReader.cpp | 4 +-- .../src/model-networking/TextureCache.cpp | 4 +-- libraries/networking/src/AtpReply.cpp | 2 +- libraries/networking/src/ResourceCache.cpp | 2 +- libraries/networking/src/ResourceManager.cpp | 24 ++++++------- libraries/networking/src/ResourceManager.h | 34 ++++++++++++------- .../src/ResourceScriptingInterface.cpp | 2 +- libraries/octree/src/Octree.cpp | 3 +- .../procedural/src/procedural/Procedural.cpp | 2 +- .../src/FileScriptingInterface.cpp | 2 +- libraries/script-engine/src/ScriptCache.cpp | 8 ++--- libraries/script-engine/src/ScriptEngine.cpp | 2 +- tests/render-perf/src/main.cpp | 7 ++-- tests/render-texture-load/src/main.cpp | 4 +-- 23 files changed, 68 insertions(+), 65 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 260a6d6825..f336f1dad5 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -62,8 +62,6 @@ Agent::Agent(ReceivedMessage& message) : _entityEditSender.setPacketsPerSecond(DEFAULT_ENTITY_PPS_PER_SCRIPT); DependencyManager::get()->setPacketSender(&_entityEditSender); - ResourceManager::init(); - DependencyManager::registerInheritance(); DependencyManager::set(); @@ -81,6 +79,7 @@ Agent::Agent(ReceivedMessage& message) : DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); @@ -199,7 +198,7 @@ void Agent::requestScript() { return; } - auto request = ResourceManager::createResourceRequest(this, scriptURL); + auto request = DependencyManager::get()->createResourceRequest(this, scriptURL); if (!request) { qWarning() << "Could not create ResourceRequest for Agent script at" << scriptURL.toString(); @@ -779,7 +778,7 @@ void Agent::aboutToFinish() { // our entity tree is going to go away so tell that to the EntityScriptingInterface DependencyManager::get()->setEntityTree(nullptr); - ResourceManager::cleanup(); + DependencyManager::get()->cleanup(); // cleanup the AudioInjectorManager (and any still running injectors) DependencyManager::destroy(); diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index dc0a2add3a..afcbcf4f1e 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -31,9 +31,9 @@ EntityServer::EntityServer(ReceivedMessage& message) : OctreeServer(message), _entitySimulation(NULL) { - ResourceManager::init(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerListenerForTypes({ PacketType::EntityAdd, PacketType::EntityEdit, PacketType::EntityErase, PacketType::EntityPhysics }, diff --git a/assignment-client/src/scripts/EntityScriptServer.cpp b/assignment-client/src/scripts/EntityScriptServer.cpp index 1b226ab642..489478ff9a 100644 --- a/assignment-client/src/scripts/EntityScriptServer.cpp +++ b/assignment-client/src/scripts/EntityScriptServer.cpp @@ -54,7 +54,7 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig DependencyManager::get()->setPacketSender(&_entityEditSender); - ResourceManager::init(); + DependencyManager::set(); DependencyManager::registerInheritance(); @@ -67,7 +67,6 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig DependencyManager::set(); DependencyManager::set(ScriptEngine::ENTITY_SERVER_SCRIPT); - auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase }, this, "handleOctreePacket"); @@ -493,7 +492,7 @@ void EntityScriptServer::checkAndCallPreload(const EntityItemID& entityID, bool if (entity && (reload || notRunning || details.scriptText != entity->getServerScripts())) { QString scriptUrl = entity->getServerScripts(); if (!scriptUrl.isEmpty()) { - scriptUrl = ResourceManager::normalizeURL(scriptUrl); + scriptUrl = DependencyManager::get()->normalizeURL(scriptUrl); qCDebug(entity_script_server) << "Loading entity server script" << scriptUrl << "for" << entityID; _entitiesScriptEngine->loadEntityScript(entityID, scriptUrl, reload); } @@ -551,7 +550,7 @@ void EntityScriptServer::aboutToFinish() { // our entity tree is going to go away so tell that to the EntityScriptingInterface DependencyManager::get()->setEntityTree(nullptr); - ResourceManager::cleanup(); + DependencyManager::get()->cleanup(); // cleanup the AudioInjectorManager (and any still running injectors) DependencyManager::destroy(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c6741ee7e4..118d99997a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -582,6 +582,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); return previousSessionCrashed; } @@ -776,7 +777,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(this, &Application::activeDisplayPluginChanged, reinterpret_cast(audioScriptingInterface.data()), &scripting::Audio::onContextChanged); - ResourceManager::init(); // Make sure we don't time out during slow operations at startup updateHeartbeat(); @@ -1880,7 +1880,7 @@ Application::~Application() { DependencyManager::destroy(); DependencyManager::destroy(); - ResourceManager::cleanup(); + DependencyManager::get()->cleanup(); // remove the NodeList from the DependencyManager DependencyManager::destroy(); @@ -5940,7 +5940,7 @@ void Application::addAssetToWorldFromURL(QString url) { addAssetToWorldInfo(filename, "Downloading model file " + filename + "."); - auto request = ResourceManager::createResourceRequest(nullptr, QUrl(url)); + auto request = DependencyManager::get()->createResourceRequest(nullptr, QUrl(url)); connect(request, &ResourceRequest::finished, this, &Application::addAssetToWorldFromURLRequestFinished); request->send(); } diff --git a/interface/src/assets/ATPAssetMigrator.cpp b/interface/src/assets/ATPAssetMigrator.cpp index e0e9d5a73a..667c2587b0 100644 --- a/interface/src/assets/ATPAssetMigrator.cpp +++ b/interface/src/assets/ATPAssetMigrator.cpp @@ -106,7 +106,8 @@ void ATPAssetMigrator::loadEntityServerFile() { jsonValue = entityObject; } else if (wantsToMigrateResource(migrationURL)) { - auto request = ResourceManager::createResourceRequest(this, migrationURL); + auto request = + DependencyManager::get()->createResourceRequest(this, migrationURL); if (request) { qCDebug(asset_migrator) << "Requesting" << migrationURL << "for ATP asset migration"; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 67e248506f..88493f9944 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -106,7 +106,7 @@ int main(int argc, const char* argv[]) { // tell everyone to use the right cache location // // this handles data8 and prepared - ResourceManager::setCacheDir(cacheDir); + DependencyManager::get()->setCacheDir(cacheDir); // this does the ktx_cache PathUtils::getAppLocalDataPath(cacheDir); diff --git a/interface/src/scripting/TestScriptingInterface.cpp b/interface/src/scripting/TestScriptingInterface.cpp index b8892fae7e..84c742d0ab 100644 --- a/interface/src/scripting/TestScriptingInterface.cpp +++ b/interface/src/scripting/TestScriptingInterface.cpp @@ -62,7 +62,7 @@ bool TestScriptingInterface::loadTestScene(QString scene) { static const QString TEST_SCRIPTS_ROOT = TEST_ROOT + "scripts/"; static const QString TEST_SCENES_ROOT = TEST_ROOT + "scenes/"; return DependencyManager::get()->returnFromUiThread([scene]()->QVariant { - ResourceManager::setUrlPrefixOverride("atp:/", TEST_BINARY_ROOT + scene + ".atp/"); + DependencyManager::get()->setUrlPrefixOverride("atp:/", TEST_BINARY_ROOT + scene + ".atp/"); auto tree = qApp->getEntities()->getTree(); auto treeIsClient = tree->getIsClient(); // Force the tree to accept the load regardless of permissions diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index c02bde2244..1684c06512 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -853,7 +853,7 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, bool entity->scriptHasUnloaded(); } if (shouldLoad) { - scriptUrl = ResourceManager::normalizeURL(scriptUrl); + scriptUrl = DependencyManager::get()->normalizeURL(scriptUrl); _entitiesScriptEngine->loadEntityScript(entityID, scriptUrl, reload); entity->scriptHasPreloaded(); } diff --git a/libraries/entities/src/EntityEditFilters.cpp b/libraries/entities/src/EntityEditFilters.cpp index d62495d95e..5359ebd31b 100644 --- a/libraries/entities/src/EntityEditFilters.cpp +++ b/libraries/entities/src/EntityEditFilters.cpp @@ -132,7 +132,7 @@ void EntityEditFilters::addFilter(EntityItemID entityID, QString filterURL) { _filterDataMap.insert(entityID, filterData); _lock.unlock(); - auto scriptRequest = ResourceManager::createResourceRequest(this, scriptURL); + auto scriptRequest = DependencyManager::get()->createResourceRequest(this, scriptURL); if (!scriptRequest) { qWarning() << "Could not create ResourceRequest for Entity Edit filter script at" << scriptURL.toString(); scriptRequestFinished(entityID); diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 1445d14d84..417901b9ab 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -202,7 +202,7 @@ bool OBJReader::isValidTexture(const QByteArray &filename) { } QUrl candidateUrl = _url.resolved(QUrl(filename)); - return ResourceManager::resourceExists(candidateUrl); + return DependencyManager::get()->resourceExists(candidateUrl); } void OBJReader::parseMaterialLibrary(QIODevice* device) { @@ -267,7 +267,7 @@ void OBJReader::parseMaterialLibrary(QIODevice* device) { } std::tuple requestData(QUrl& url) { - auto request = ResourceManager::createResourceRequest(nullptr, url); + auto request = DependencyManager::get()->createResourceRequest(nullptr, url); if (!request) { return std::make_tuple(false, QByteArray()); diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index ed1715219a..5c8f59f20f 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -384,7 +384,7 @@ void NetworkTexture::makeRequest() { // Add a fragment to the base url so we can identify the section of the ktx being requested when debugging // The actual requested url is _activeUrl and will not contain the fragment _url.setFragment("head"); - _ktxHeaderRequest = ResourceManager::createResourceRequest(this, _activeUrl); + _ktxHeaderRequest = DependencyManager::get()->createResourceRequest(this, _activeUrl); if (!_ktxHeaderRequest) { qCDebug(networking).noquote() << "Failed to get request for" << _url.toDisplayString(); @@ -454,7 +454,7 @@ void NetworkTexture::startMipRangeRequest(uint16_t low, uint16_t high) { bool isHighMipRequest = low == NULL_MIP_LEVEL && high == NULL_MIP_LEVEL; - _ktxMipRequest = ResourceManager::createResourceRequest(this, _activeUrl); + _ktxMipRequest = DependencyManager::get()->createResourceRequest(this, _activeUrl); if (!_ktxMipRequest) { qCWarning(networking).noquote() << "Failed to get request for" << _url.toDisplayString(); diff --git a/libraries/networking/src/AtpReply.cpp b/libraries/networking/src/AtpReply.cpp index 4440995ee0..6417478005 100644 --- a/libraries/networking/src/AtpReply.cpp +++ b/libraries/networking/src/AtpReply.cpp @@ -13,7 +13,7 @@ #include "AtpReply.h" AtpReply::AtpReply(const QUrl& url, QObject* parent) : - _resourceRequest(ResourceManager::createResourceRequest(parent, url)) { + _resourceRequest(DependencyManager::get()->createResourceRequest(parent, url)) { setOperation(QNetworkAccessManager::GetOperation); connect(_resourceRequest, &AssetResourceRequest::progress, this, &AtpReply::downloadProgress); diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 88ea68780b..f07514cd85 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -672,7 +672,7 @@ void Resource::makeRequest() { PROFILE_ASYNC_BEGIN(resource, "Resource:" + getType(), QString::number(_requestID), { { "url", _url.toString() }, { "activeURL", _activeUrl.toString() } }); - _request = ResourceManager::createResourceRequest(this, _activeUrl); + _request = DependencyManager::get()->createResourceRequest(this, _activeUrl); if (!_request) { qCDebug(networking).noquote() << "Failed to get request for" << _url.toDisplayString(); diff --git a/libraries/networking/src/ResourceManager.cpp b/libraries/networking/src/ResourceManager.cpp index e4357ca507..e9fe2f1ec1 100644 --- a/libraries/networking/src/ResourceManager.cpp +++ b/libraries/networking/src/ResourceManager.cpp @@ -24,10 +24,16 @@ #include "NetworkAccessManager.h" #include "NetworkLogging.h" -QThread ResourceManager::_thread; -ResourceManager::PrefixMap ResourceManager::_prefixMap; -QMutex ResourceManager::_prefixMapLock; -QString ResourceManager::_cacheDir; + +ResourceManager::ResourceManager() { + _thread.setObjectName("Resource Manager Thread"); + + auto assetClient = DependencyManager::set(_cacheDir); + assetClient->moveToThread(&_thread); + QObject::connect(&_thread, &QThread::started, assetClient.data(), &AssetClient::init); + + _thread.start(); +} void ResourceManager::setUrlPrefixOverride(const QString& prefix, const QString& replacement) { QMutexLocker locker(&_prefixMapLock); @@ -75,16 +81,6 @@ QUrl ResourceManager::normalizeURL(const QUrl& originalUrl) { return url; } -void ResourceManager::init() { - _thread.setObjectName("Resource Manager Thread"); - - auto assetClient = DependencyManager::set(_cacheDir); - assetClient->moveToThread(&_thread); - QObject::connect(&_thread, &QThread::started, assetClient.data(), &AssetClient::init); - - _thread.start(); -} - void ResourceManager::cleanup() { // cleanup the AssetClient thread DependencyManager::destroy(); diff --git a/libraries/networking/src/ResourceManager.h b/libraries/networking/src/ResourceManager.h index 699573ddd6..4e7cd3d92d 100644 --- a/libraries/networking/src/ResourceManager.h +++ b/libraries/networking/src/ResourceManager.h @@ -14,7 +14,11 @@ #include +#include #include +#include + +#include #include "ResourceRequest.h" @@ -24,34 +28,38 @@ const QString URL_SCHEME_HTTPS = "https"; const QString URL_SCHEME_FTP = "ftp"; const QString URL_SCHEME_ATP = "atp"; -class ResourceManager { +class ResourceManager: public QObject, public Dependency { + Q_OBJECT + SINGLETON_DEPENDENCY + public: + ResourceManager(); - static void setUrlPrefixOverride(const QString& prefix, const QString& replacement); - static QString normalizeURL(const QString& urlString); - static QUrl normalizeURL(const QUrl& url); + void setUrlPrefixOverride(const QString& prefix, const QString& replacement); + QString normalizeURL(const QString& urlString); + QUrl normalizeURL(const QUrl& url); - static ResourceRequest* createResourceRequest(QObject* parent, const QUrl& url); + ResourceRequest* createResourceRequest(QObject* parent, const QUrl& url); - static void init(); - static void cleanup(); + void init(); + void cleanup(); // Blocking call to check if a resource exists. This function uses a QEventLoop internally // to return to the calling thread so that events can still be processed. - static bool resourceExists(const QUrl& url); + bool resourceExists(const QUrl& url); // adjust where we persist the cache - static void setCacheDir(const QString& cacheDir); + void setCacheDir(const QString& cacheDir); private: - static QThread _thread; + QThread _thread; using PrefixMap = std::map; - static PrefixMap _prefixMap; - static QMutex _prefixMapLock; + PrefixMap _prefixMap; + QMutex _prefixMapLock; - static QString _cacheDir; + QString _cacheDir; }; #endif diff --git a/libraries/networking/src/ResourceScriptingInterface.cpp b/libraries/networking/src/ResourceScriptingInterface.cpp index 38be49049c..3227d44de1 100644 --- a/libraries/networking/src/ResourceScriptingInterface.cpp +++ b/libraries/networking/src/ResourceScriptingInterface.cpp @@ -11,5 +11,5 @@ #include "ResourceManager.h" void ResourceScriptingInterface::overrideUrlPrefix(const QString& prefix, const QString& replacement) { - ResourceManager::setUrlPrefixOverride(prefix, replacement); + DependencyManager::get()->setUrlPrefixOverride(prefix, replacement); } diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 180f25f106..2e93f3515f 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -1668,7 +1668,8 @@ bool Octree::readJSONFromGzippedFile(QString qFileName) { } bool Octree::readFromURL(const QString& urlString) { - auto request = std::unique_ptr(ResourceManager::createResourceRequest(this, urlString)); + auto request = + std::unique_ptr(DependencyManager::get()->createResourceRequest(this, urlString)); if (!request) { return false; diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index e4ce3c691a..c38e562672 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -103,7 +103,7 @@ bool Procedural::parseVersion(const QJsonValue& version) { } bool Procedural::parseShader(const QUrl& shaderPath) { - auto shaderUrl = ResourceManager::normalizeURL(shaderPath); + auto shaderUrl = DependencyManager::get()->normalizeURL(shaderPath); if (!shaderUrl.isValid()) { if (!shaderUrl.isEmpty()) { diff --git a/libraries/script-engine/src/FileScriptingInterface.cpp b/libraries/script-engine/src/FileScriptingInterface.cpp index 2f5cc2bc88..30d0a3a201 100644 --- a/libraries/script-engine/src/FileScriptingInterface.cpp +++ b/libraries/script-engine/src/FileScriptingInterface.cpp @@ -85,7 +85,7 @@ QString FileScriptingInterface::convertUrlToPath(QUrl url) { // this function is not in use void FileScriptingInterface::downloadZip(QString path, const QString link) { QUrl url = QUrl(link); - auto request = ResourceManager::createResourceRequest(nullptr, url); + auto request = DependencyManager::get()->createResourceRequest(nullptr, url); connect(request, &ResourceRequest::finished, this, [this, path]{ unzipFile(path, ""); // so intellisense isn't mad }); diff --git a/libraries/script-engine/src/ScriptCache.cpp b/libraries/script-engine/src/ScriptCache.cpp index 601ca6bc95..dba2db0458 100644 --- a/libraries/script-engine/src/ScriptCache.cpp +++ b/libraries/script-engine/src/ScriptCache.cpp @@ -57,7 +57,7 @@ void ScriptCache::clearATPScriptsFromCache() { } void ScriptCache::deleteScript(const QUrl& unnormalizedURL) { - QUrl url = ResourceManager::normalizeURL(unnormalizedURL); + QUrl url = DependencyManager::get()->normalizeURL(unnormalizedURL); Lock lock(_containerLock); if (_scriptCache.contains(url)) { qCDebug(scriptengine) << "Delete script from cache:" << url.toString(); @@ -70,7 +70,7 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable qCDebug(scriptengine) << "ScriptCache::getScriptContents() on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; #endif QUrl unnormalizedURL(scriptOrURL); - QUrl url = ResourceManager::normalizeURL(unnormalizedURL); + QUrl url = DependencyManager::get()->normalizeURL(unnormalizedURL); // attempt to determine if this is a URL to a script, or if this is actually a script itself (which is valid in the // entityScript use case) @@ -109,7 +109,7 @@ void ScriptCache::getScriptContents(const QString& scriptOrURL, contentAvailable #ifdef THREAD_DEBUGGING qCDebug(scriptengine) << "about to call: ResourceManager::createResourceRequest(this, url); on thread [" << QThread::currentThread() << "] expected thread [" << thread() << "]"; #endif - auto request = ResourceManager::createResourceRequest(nullptr, url); + auto request = DependencyManager::get()->createResourceRequest(nullptr, url); Q_ASSERT(request); request->setCacheEnabled(!forceDownload); connect(request, &ResourceRequest::finished, this, [=]{ scriptContentAvailable(maxRetries); }); @@ -166,7 +166,7 @@ void ScriptCache::scriptContentAvailable(int maxRetries) { qCDebug(scriptengine) << QString("Retrying script request [%1 / %2]: %3") .arg(attempt).arg(maxRetries).arg(url.toString()); - auto request = ResourceManager::createResourceRequest(nullptr, url); + auto request = DependencyManager::get()->createResourceRequest(nullptr, url); Q_ASSERT(request); // We've already made a request, so the cache must be disabled or it wasn't there, so enabling diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 48f8b07a4a..11bb044d72 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1762,7 +1762,7 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac QList urls; for (QString includeFile : includeFiles) { - QString file = ResourceManager::normalizeURL(includeFile); + QString file = DependencyManager::get()->normalizeURL(includeFile); QUrl thisURL; bool isStandardLibrary = false; if (file.startsWith("/~/")) { diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 552dc3d270..50f92ec3b9 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -494,6 +494,7 @@ public: DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); } QTestWindow() { @@ -520,8 +521,6 @@ public: _entitySimulation = simpleSimulation; } - ResourceManager::init(); - setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); _size = QSize(800, 600); _renderThread._size = _size; @@ -575,7 +574,7 @@ public: DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); - ResourceManager::cleanup(); + DependencyManager::get()->cleanup(); // remove the NodeList from the DependencyManager DependencyManager::destroy(); } @@ -998,7 +997,7 @@ private: QFileInfo atpPathInfo(atpPath); if (atpPathInfo.exists()) { QString atpUrl = QUrl::fromLocalFile(atpPath).toString(); - ResourceManager::setUrlPrefixOverride("atp:/", atpUrl + "/"); + DependencyManager::get()->setUrlPrefixOverride("atp:/", atpUrl + "/"); } _octree->clear(); _octree->getTree()->readFromURL(fileName); diff --git a/tests/render-texture-load/src/main.cpp b/tests/render-texture-load/src/main.cpp index f426cd8024..5920e04558 100644 --- a/tests/render-texture-load/src/main.cpp +++ b/tests/render-texture-load/src/main.cpp @@ -289,6 +289,7 @@ public: DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); } struct TextureLoad { @@ -329,7 +330,6 @@ public: installEventFilter(this); QThreadPool::globalInstance()->setMaxThreadCount(2); QThread::currentThread()->setPriority(QThread::HighestPriority); - ResourceManager::init(); setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); _size = QSize(800, 600); _renderThread._size = _size; @@ -369,7 +369,7 @@ public: DependencyManager::destroy(); DependencyManager::destroy(); DependencyManager::destroy(); - ResourceManager::cleanup(); + DependencyManager::get()->cleanup(); } protected: From 9f8a6c63cca316ab75a350d7640723b6a74378f6 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 28 Jun 2017 14:44:26 -0700 Subject: [PATCH 42/47] Fixup after merge --- scripts/system/spectatorCamera.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index d4d387b1b7..1fa2f78fcb 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -162,7 +162,7 @@ button.clicked.connect(onTabletButtonClicked); } } else if (button) { - if ((!showSpectatorInDesktop || isShuttingDown) && !isHMDMode) { + if (!showSpectatorInDesktop || isShuttingDown) { button.clicked.disconnect(onTabletButtonClicked); tablet.removeButton(button); button = false; From 218b32e9fba14350f55eb56932e1bae0204619d9 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 28 Jun 2017 15:12:57 -0700 Subject: [PATCH 43/47] Fix cameraUpdateInterval --- scripts/system/spectatorCamera.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 1fa2f78fcb..5154322daa 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -123,7 +123,10 @@ // destroy the camera entity. function spectatorCameraOff() { spectatorFrameRenderConfig.enabled = beginSpectatorFrameRenderConfig.enabled = false; - cameraUpdateInterval = Script.clearInterval(cameraUpdateInterval); + if (cameraUpdateInterval) { + Script.clearInterval(cameraUpdateInterval); + cameraUpdateInterval = false; + } if (camera) { Entities.deleteEntity(camera); } From 93679f7c3be1899fbe5ae534ff5fd50b3ad79bc1 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 29 Jun 2017 00:52:51 +0200 Subject: [PATCH 44/47] move the ResourceManager init back to where it was, to prevent problems --- assignment-client/src/Agent.cpp | 3 ++- assignment-client/src/entities/EntityServer.cpp | 2 +- tests/render-perf/src/main.cpp | 3 ++- tests/render-texture-load/src/main.cpp | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index f336f1dad5..8aec5adb1f 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -62,6 +62,8 @@ Agent::Agent(ReceivedMessage& message) : _entityEditSender.setPacketsPerSecond(DEFAULT_ENTITY_PPS_PER_SCRIPT); DependencyManager::get()->setPacketSender(&_entityEditSender); + DependencyManager::set(); + DependencyManager::registerInheritance(); DependencyManager::set(); @@ -79,7 +81,6 @@ Agent::Agent(ReceivedMessage& message) : DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index afcbcf4f1e..ac686e2e0a 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -31,9 +31,9 @@ EntityServer::EntityServer(ReceivedMessage& message) : OctreeServer(message), _entitySimulation(NULL) { + DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerListenerForTypes({ PacketType::EntityAdd, PacketType::EntityEdit, PacketType::EntityErase, PacketType::EntityPhysics }, diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 50f92ec3b9..61608f12aa 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -494,7 +494,6 @@ public: DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); } QTestWindow() { @@ -520,6 +519,8 @@ public: _octree->getTree()->setSimulation(simpleSimulation); _entitySimulation = simpleSimulation; } + + DependencyManager::set(); setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); _size = QSize(800, 600); diff --git a/tests/render-texture-load/src/main.cpp b/tests/render-texture-load/src/main.cpp index 5920e04558..d85fcd6a32 100644 --- a/tests/render-texture-load/src/main.cpp +++ b/tests/render-texture-load/src/main.cpp @@ -289,7 +289,6 @@ public: DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); } struct TextureLoad { @@ -329,7 +328,8 @@ public: installEventFilter(this); QThreadPool::globalInstance()->setMaxThreadCount(2); - QThread::currentThread()->setPriority(QThread::HighestPriority); + QThread::currentThread()->setPriority(QThread::HighestPriority); + DependencyManager::set(); setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); _size = QSize(800, 600); _renderThread._size = _size; From d5289d357b9e67ed53ef884a0d51e35edb1b8c48 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 29 Jun 2017 01:01:59 +0200 Subject: [PATCH 45/47] I need to setup my code-editor, spaces. --- tests/render-perf/src/main.cpp | 2 +- tests/render-texture-load/src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 61608f12aa..9c4e3ae870 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -519,7 +519,7 @@ public: _octree->getTree()->setSimulation(simpleSimulation); _entitySimulation = simpleSimulation; } - + DependencyManager::set(); setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); diff --git a/tests/render-texture-load/src/main.cpp b/tests/render-texture-load/src/main.cpp index d85fcd6a32..67b80d9ba8 100644 --- a/tests/render-texture-load/src/main.cpp +++ b/tests/render-texture-load/src/main.cpp @@ -328,7 +328,7 @@ public: installEventFilter(this); QThreadPool::globalInstance()->setMaxThreadCount(2); - QThread::currentThread()->setPriority(QThread::HighestPriority); + QThread::currentThread()->setPriority(QThread::HighestPriority); DependencyManager::set(); setFlags(Qt::MSWindowsOwnDC | Qt::Window | Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint); _size = QSize(800, 600); From 5f123018a4109c0cf43458293fdf59bffdeab8bf Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Thu, 29 Jun 2017 10:38:33 -0700 Subject: [PATCH 46/47] Update DomainMetadata.cpp --- domain-server/src/DomainMetadata.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index c19cefa397..eee5673af3 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -171,7 +171,7 @@ void DomainMetadata::maybeUpdateUsers() { if (linkedData) { auto nodeData = static_cast(linkedData); - if (!nodeData->wasAssigned()) { + if (!nodeData->wasAssigned() && node->getType() == NodeType::Agent) { ++numConnected; if (nodeData->getUsername().isEmpty()) { From 3c9291062d7546d14693974ba99f841d0b778a02 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 30 Jun 2017 11:31:48 -0700 Subject: [PATCH 47/47] Clarify setDisplayTexture cases, also fixing crash bug --- scripts/system/spectatorCamera.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 5154322daa..4df168fde4 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -223,9 +223,19 @@ } } + // Function Name: setDisplay() + // + // Description: + // -There are two bool variables that determine what the "url" argument to "setDisplayTexture(url)" should be: + // Camera on/off switch, and the "Monitor Shows" on/off switch. + // This results in four possible cases for the argument. Those four cases are: + // 1. Camera is off; "Monitor Shows" is "HMD Preview": "url" is "" + // 2. Camera is off; "Monitor Shows" is "Camera View": "url" is "" + // 3. Camera is on; "Monitor Shows" is "HMD Preview": "url" is "" + // 4. Camera is on; "Monitor Shows" is "Camera View": "url" is "resource://spectatorCameraFrame" function setDisplay(showCameraView) { - // It would be fancy if (showCameraView && !cameraUpdateInterval) would show instructions, but that's out of scope for now. - var url = (showCameraView && cameraUpdateInterval) ? "resource://spectatorCameraFrame" : ""; + // It would be fancy if the app would show instructions when (url === ""), but that's out of scope for now. + var url = (camera && showCameraView && cameraUpdateInterval) ? "resource://spectatorCameraFrame" : ""; Window.setDisplayTexture(url); } const MONITOR_SHOWS_CAMERA_VIEW_DEFAULT = false;