From 328fc29bc595faa62ef1ae69604d6fabebca7ece Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 1 Nov 2017 17:01:19 +1300 Subject: [PATCH 01/21] Fix serverScripts not being able to see entities in parent/child tree --- .../src/entities/EntityTreeSendThread.cpp | 14 +++++++++----- .../src/entities/EntityTreeSendThread.h | 3 ++- libraries/entities/src/DiffTraversal.cpp | 5 +++-- libraries/entities/src/DiffTraversal.h | 3 ++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index 03014bae6a..e96a9dc667 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -96,7 +96,7 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O nodeData->copyCurrentViewFrustum(viewFrustum); EntityTreeElementPointer root = std::dynamic_pointer_cast(_myServer->getOctree()->getRoot()); int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST); - startNewTraversal(viewFrustum, root, lodLevelOffset, nodeData->getUsesFrustum()); + startNewTraversal(viewFrustum, root, lodLevelOffset, nodeData->getUsesFrustum(), isFullScene); // When the viewFrustum changed the sort order may be incorrect, so we re-sort // and also use the opportunity to cull anything no longer in view @@ -175,7 +175,7 @@ bool EntityTreeSendThread::addAncestorsToExtraFlaggedEntities(const QUuid& filte return parentWasNew || ancestorsWereNew; } - // since we didn't have a parent niether of our parents or ancestors could be new additions + // since we didn't have a parent, neither of our parents or ancestors could be new additions return false; } @@ -204,8 +204,10 @@ bool EntityTreeSendThread::addDescendantsToExtraFlaggedEntities(const QUuid& fil return hasNewChild || hasNewDescendants; } -void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum) { - DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset, usesViewFrustum); +void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root, int32_t lodLevelOffset, + bool usesViewFrustum, bool isFullScene) { + + DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset, usesViewFrustum, isFullScene); // there are three types of traversal: // // (1) FirstTime = at login --> find everything in view @@ -423,12 +425,14 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream uint64_t sendTime = usecTimestampNow(); auto nodeData = static_cast(params.nodeData); nodeData->stats.encodeStarted(); + auto entityNodeData = static_cast(_node.toStrongRef()->getLinkedData()); while(!_sendQueue.empty()) { PrioritizedEntity queuedItem = _sendQueue.top(); EntityItemPointer entity = queuedItem.getEntity(); if (entity) { // Only send entities that match the jsonFilters, but keep track of everything we've tried to send so we don't try to send it again - if (entity->matchesJSONFilters(jsonFilters)) { + if (entity->matchesJSONFilters(jsonFilters) || entityNodeData->isEntityFlaggedAsExtra(entity->getID())) { + entityNodeData->insertSentFilteredEntity(entity->getID()); OctreeElement::AppendState appendEntityState = entity->appendEntityData(&_packetData, params, _extraEncodeData); if (appendEntityState != OctreeElement::COMPLETED) { diff --git a/assignment-client/src/entities/EntityTreeSendThread.h b/assignment-client/src/entities/EntityTreeSendThread.h index 49901491ff..1781de9890 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.h +++ b/assignment-client/src/entities/EntityTreeSendThread.h @@ -38,7 +38,8 @@ private: bool addAncestorsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData); bool addDescendantsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData); - void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum); + void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, + bool usesViewFrustum, bool isFullScene); bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override; void preDistributionProcessing() override; diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp index 2f9423daa3..9b16ee90bf 100644 --- a/libraries/entities/src/DiffTraversal.cpp +++ b/libraries/entities/src/DiffTraversal.cpp @@ -142,7 +142,8 @@ DiffTraversal::DiffTraversal() { _path.reserve(MIN_PATH_DEPTH); } -DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum) { +DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, + int32_t lodLevelOffset, bool usesViewFrustum, bool isFullScene) { assert(root); // there are three types of traversal: // @@ -163,7 +164,7 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFr Type type; // If usesViewFrustum changes, treat it as a First traversal - if (_completedView.startTime == 0 || _currentView.usesViewFrustum != _completedView.usesViewFrustum) { + if (_completedView.startTime == 0 || _currentView.usesViewFrustum != _completedView.usesViewFrustum || isFullScene) { type = Type::First; _currentView.viewFrustum = viewFrustum; _currentView.lodScaleFactor = lodScaleFactor; diff --git a/libraries/entities/src/DiffTraversal.h b/libraries/entities/src/DiffTraversal.h index c26e48ae5f..becf322fd5 100644 --- a/libraries/entities/src/DiffTraversal.h +++ b/libraries/entities/src/DiffTraversal.h @@ -57,7 +57,8 @@ public: DiffTraversal(); - Type prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum); + Type prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, + bool usesViewFrustum, bool isFullScene); const ViewFrustum& getCurrentView() const { return _currentView.viewFrustum; } const ViewFrustum& getCompletedView() const { return _completedView.viewFrustum; } From da63e85699c62271145962f7a1b1d95ab87a70f4 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 1 Nov 2017 09:17:04 -0700 Subject: [PATCH 02/21] Bug 8270 fixed --- libraries/animation/src/AnimClip.h | 1 + libraries/animation/src/Rig.cpp | 21 +++++++++++++++++++ libraries/animation/src/Rig.h | 2 ++ .../src/avatars-renderer/Avatar.cpp | 12 +++++++++++ .../src/avatars-renderer/Avatar.h | 3 +++ 5 files changed, 39 insertions(+) diff --git a/libraries/animation/src/AnimClip.h b/libraries/animation/src/AnimClip.h index c7e7ebf3ee..7121cff356 100644 --- a/libraries/animation/src/AnimClip.h +++ b/libraries/animation/src/AnimClip.h @@ -54,6 +54,7 @@ public: void setMirrorFlag(bool mirrorFlag) { _mirrorFlag = mirrorFlag; } void loadURL(const QString& url); + const QString& getURL() { return _url; } protected: virtual void setCurrentFrameInternal(float frame) override; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 0f2bce5ca4..8293cb91f4 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -144,6 +144,27 @@ QStringList Rig::getAnimationRoles() const { } } +QVector> Rig::getAnimationClips() const { + QVector> list; + if (_animNode) { + _animNode->traverse([&](AnimNode::Pointer node) { + // only report clip nodes as valid roles. + auto clipNode = std::dynamic_pointer_cast(node); + if (clipNode) { + // filter out the userAnims, they are for internal use only. + if (!clipNode->getID().startsWith("userAnim")) { + list.append(clipNode); + } + } + return true; + }); + return list; + } + else { + return list; + } +} + void Rig::overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame) { if (_animNode) { AnimNode::Pointer node = _animNode->findByName(role); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 18d49c5f1e..9290b41513 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -21,6 +21,7 @@ #include #include +#include "AnimClip.h" #include "AnimNode.h" #include "AnimNodeLoader.h" #include "SimpleMovingAverage.h" @@ -107,6 +108,7 @@ public: QStringList getAnimationRoles() const; void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame); void restoreRoleAnimation(const QString& role); + QVector> getAnimationClips() const; void initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset); void reset(const FBXGeometry& geometry); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 142e57c9e5..0d2e730a1a 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -139,6 +139,7 @@ Avatar::~Avatar() { void Avatar::init() { getHead()->init(); _skeletonModel->init(); + connect(&_skeletonModel->getRig(), &Rig::onLoadComplete, this, &Avatar::restoreAnimations); _initialized = true; } @@ -198,6 +199,16 @@ void Avatar::setTargetScale(float targetScale) { } } +void Avatar::restoreAnimations() { + for (int i = 0; i < _animationCache.size(); i++) { + auto clip = _animationCache[i]; + const float REFERENCE_FRAMES_PER_SECOND = 30.0f; + float fps = REFERENCE_FRAMES_PER_SECOND / clip->getTimeScale(); + qDebug() << clip->getID() << " " << clip->getURL() << " " << fps << " " << clip->getLoopFlag() << " " << clip->getStartFrame() << " " << clip->getEndFrame(); + _skeletonModel->getRig().overrideRoleAnimation(clip->getID(), clip->getURL(), fps, clip->getLoopFlag(), clip->getStartFrame(), clip->getEndFrame()); + } +} + void Avatar::updateAvatarEntities() { PerformanceTimer perfTimer("attachments"); // - if queueEditEntityMessage sees clientOnly flag it does _myAvatar->updateAvatarEntity() @@ -1177,6 +1188,7 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { } void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { + _animationCache = _skeletonModel->getRig().getAnimationClips(); AvatarData::setSkeletonModelURL(skeletonModelURL); if (QThread::currentThread() == thread()) { _skeletonModel->setURL(_skeletonModelURL); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index a5ec307c50..09e1451aa9 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -274,6 +274,7 @@ public slots: glm::vec3 getRightPalmPosition() const; glm::quat getRightPalmRotation() const; + void restoreAnimations(); void setModelURLFinished(bool success); protected: @@ -377,6 +378,8 @@ private: float _displayNameTargetAlpha { 1.0f }; float _displayNameAlpha { 1.0f }; + + QVector> _animationCache; }; #endif // hifi_Avatar_h From 67552d2b7de3ae8ec71db3bb3563d77a2b82da5d Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 1 Nov 2017 17:39:37 -0700 Subject: [PATCH 03/21] Change stencil mask used with Haze. --- libraries/render-utils/src/DrawHaze.cpp | 2 +- libraries/render-utils/src/StencilMaskPass.cpp | 5 +++++ libraries/render-utils/src/StencilMaskPass.h | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index 7cf07d8f33..dba35cbb3c 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -140,7 +140,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu gpu::StatePointer state = gpu::StatePointer(new gpu::State()); // Mask out haze on the tablet - PrepareStencil::testNoAA(*state); + PrepareStencil::testMaskNoAA(*state); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), HazeEffect_ParamsSlot)); diff --git a/libraries/render-utils/src/StencilMaskPass.cpp b/libraries/render-utils/src/StencilMaskPass.cpp index 0e0d8b56b3..f9305d8268 100644 --- a/libraries/render-utils/src/StencilMaskPass.cpp +++ b/libraries/render-utils/src/StencilMaskPass.cpp @@ -128,6 +128,11 @@ void PrepareStencil::testNoAA(gpu::State& state) { gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } +void PrepareStencil::testMaskNoAA(gpu::State& state) { + state.setStencilTest(true, 0x00, gpu::State::StencilTest(0, STENCIL_MASK | STENCIL_NO_AA, gpu::EQUAL, + gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); +} + // Pass if this area WAS marked as BACKGROUND // (see: model/src/Skybox.cpp, procedural/src/ProceduralSkybox.cpp) void PrepareStencil::testBackground(gpu::State& state) { diff --git a/libraries/render-utils/src/StencilMaskPass.h b/libraries/render-utils/src/StencilMaskPass.h index ddbf4a7ac0..18ec104ff5 100644 --- a/libraries/render-utils/src/StencilMaskPass.h +++ b/libraries/render-utils/src/StencilMaskPass.h @@ -49,8 +49,9 @@ public: static void drawMask(gpu::State& state); static void drawBackground(gpu::State& state); - static void testNoAA(gpu::State& state); static void testMask(gpu::State& state); + static void testNoAA(gpu::State& state); + static void testMaskNoAA(gpu::State& state); static void testBackground(gpu::State& state); static void testShape(gpu::State& state); static void testMaskDrawShape(gpu::State& state); From 6a2dc38fdd402e42b648a74b2254387f85ae1665 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 1 Nov 2017 19:38:37 -0700 Subject: [PATCH 04/21] restoring previous roles --- libraries/animation/src/Rig.cpp | 30 +++++-------------- libraries/animation/src/Rig.h | 17 +++++++++-- .../src/avatars-renderer/Avatar.cpp | 12 -------- .../src/avatars-renderer/Avatar.h | 4 +-- 4 files changed, 24 insertions(+), 39 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 8293cb91f4..e16afc65c2 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -144,27 +144,6 @@ QStringList Rig::getAnimationRoles() const { } } -QVector> Rig::getAnimationClips() const { - QVector> list; - if (_animNode) { - _animNode->traverse([&](AnimNode::Pointer node) { - // only report clip nodes as valid roles. - auto clipNode = std::dynamic_pointer_cast(node); - if (clipNode) { - // filter out the userAnims, they are for internal use only. - if (!clipNode->getID().startsWith("userAnim")) { - list.append(clipNode); - } - } - return true; - }); - return list; - } - else { - return list; - } -} - void Rig::overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame) { if (_animNode) { AnimNode::Pointer node = _animNode->findByName(role); @@ -173,6 +152,7 @@ void Rig::overrideRoleAnimation(const QString& role, const QString& url, float f const float REFERENCE_FRAMES_PER_SECOND = 30.0f; float timeScale = fps / REFERENCE_FRAMES_PER_SECOND; auto clipNode = std::make_shared(role, url, firstFrame, lastFrame, timeScale, loop, false); + _roleAnimState[role] = { role, url, fps, loop, firstFrame, lastFrame }; AnimNode::Pointer parent = node->getParent(); parent->replaceChild(node, clipNode); } else { @@ -1659,8 +1639,14 @@ void Rig::initAnimGraph(const QUrl& url) { _userAnimState = { UserAnimState::None, "", 30.0f, false, 0.0f, 0.0f }; overrideAnimation(origState.url, origState.fps, origState.loop, origState.firstFrame, origState.lastFrame); } + // restore the role animations we had before reset. + for (auto ite = _roleAnimState.begin(); ite != _roleAnimState.end(); ite++) { + auto role = ite->first; + auto roleState = _roleAnimState[role]; + overrideRoleAnimation(roleState.role, roleState.url, roleState.fps, roleState.loop, roleState.firstFrame, roleState.lastFrame); + } _animLoading = false; - + emit onLoadComplete(); }); connect(_animLoader.get(), &AnimNodeLoader::error, [url](int error, QString str) { diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 9290b41513..a63d5eb0a5 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -21,7 +21,6 @@ #include #include -#include "AnimClip.h" #include "AnimNode.h" #include "AnimNodeLoader.h" #include "SimpleMovingAverage.h" @@ -108,7 +107,7 @@ public: QStringList getAnimationRoles() const; void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame); void restoreRoleAnimation(const QString& role); - QVector> getAnimationClips() const; + //QVector> getAnimationClips() const; void initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset); void reset(const FBXGeometry& geometry); @@ -337,8 +336,22 @@ protected: float firstFrame; float lastFrame; }; + + struct RoleAnimState { + RoleAnimState() {} + RoleAnimState(const QString& roleId, const QString& urlIn, float fpsIn, bool loopIn, float firstFrameIn, float lastFrameIn) : + role(roleId), url(urlIn), fps(fpsIn), loop(loopIn), firstFrame(firstFrameIn), lastFrame(lastFrameIn) {} + + QString role; + QString url; + float fps; + bool loop; + float firstFrame; + float lastFrame; + }; UserAnimState _userAnimState; + std::map _roleAnimState; float _leftHandOverlayAlpha { 0.0f }; float _rightHandOverlayAlpha { 0.0f }; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 0d2e730a1a..142e57c9e5 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -139,7 +139,6 @@ Avatar::~Avatar() { void Avatar::init() { getHead()->init(); _skeletonModel->init(); - connect(&_skeletonModel->getRig(), &Rig::onLoadComplete, this, &Avatar::restoreAnimations); _initialized = true; } @@ -199,16 +198,6 @@ void Avatar::setTargetScale(float targetScale) { } } -void Avatar::restoreAnimations() { - for (int i = 0; i < _animationCache.size(); i++) { - auto clip = _animationCache[i]; - const float REFERENCE_FRAMES_PER_SECOND = 30.0f; - float fps = REFERENCE_FRAMES_PER_SECOND / clip->getTimeScale(); - qDebug() << clip->getID() << " " << clip->getURL() << " " << fps << " " << clip->getLoopFlag() << " " << clip->getStartFrame() << " " << clip->getEndFrame(); - _skeletonModel->getRig().overrideRoleAnimation(clip->getID(), clip->getURL(), fps, clip->getLoopFlag(), clip->getStartFrame(), clip->getEndFrame()); - } -} - void Avatar::updateAvatarEntities() { PerformanceTimer perfTimer("attachments"); // - if queueEditEntityMessage sees clientOnly flag it does _myAvatar->updateAvatarEntity() @@ -1188,7 +1177,6 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { } void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { - _animationCache = _skeletonModel->getRig().getAnimationClips(); AvatarData::setSkeletonModelURL(skeletonModelURL); if (QThread::currentThread() == thread()) { _skeletonModel->setURL(_skeletonModelURL); diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 09e1451aa9..a06ba0fb82 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -274,7 +274,7 @@ public slots: glm::vec3 getRightPalmPosition() const; glm::quat getRightPalmRotation() const; - void restoreAnimations(); + //void restoreAnimations(); void setModelURLFinished(bool success); protected: @@ -378,8 +378,6 @@ private: float _displayNameTargetAlpha { 1.0f }; float _displayNameAlpha { 1.0f }; - - QVector> _animationCache; }; #endif // hifi_Avatar_h From e201e82ec26aa0ce28b63a1bf36b6c0828e9e6fd Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 1 Nov 2017 19:45:56 -0700 Subject: [PATCH 05/21] formatting --- libraries/animation/src/AnimClip.h | 1 - libraries/animation/src/Rig.cpp | 2 +- libraries/avatars-renderer/src/avatars-renderer/Avatar.h | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/animation/src/AnimClip.h b/libraries/animation/src/AnimClip.h index 7121cff356..c7e7ebf3ee 100644 --- a/libraries/animation/src/AnimClip.h +++ b/libraries/animation/src/AnimClip.h @@ -54,7 +54,6 @@ public: void setMirrorFlag(bool mirrorFlag) { _mirrorFlag = mirrorFlag; } void loadURL(const QString& url); - const QString& getURL() { return _url; } protected: virtual void setCurrentFrameInternal(float frame) override; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index e16afc65c2..9df12de540 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1646,7 +1646,7 @@ void Rig::initAnimGraph(const QUrl& url) { overrideRoleAnimation(roleState.role, roleState.url, roleState.fps, roleState.loop, roleState.firstFrame, roleState.lastFrame); } _animLoading = false; - + emit onLoadComplete(); }); connect(_animLoader.get(), &AnimNodeLoader::error, [url](int error, QString str) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index a06ba0fb82..a5ec307c50 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -274,7 +274,6 @@ public slots: glm::vec3 getRightPalmPosition() const; glm::quat getRightPalmRotation() const; - //void restoreAnimations(); void setModelURLFinished(bool success); protected: From 9e0e1ab5a54c85f3721a629aee5e2e9e67e3dae4 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 1 Nov 2017 19:56:16 -0700 Subject: [PATCH 06/21] erase comment --- libraries/animation/src/Rig.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index a63d5eb0a5..8ca701ec2d 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -107,7 +107,6 @@ public: QStringList getAnimationRoles() const; void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame); void restoreRoleAnimation(const QString& role); - //QVector> getAnimationClips() const; void initJointStates(const FBXGeometry& geometry, const glm::mat4& modelOffset); void reset(const FBXGeometry& geometry); From 2e6c849b63f55f453c08a9da64271dfcbbc1857c Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Wed, 1 Nov 2017 20:31:44 -0700 Subject: [PATCH 07/21] Added comment. --- libraries/render-utils/src/StencilMaskPass.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/render-utils/src/StencilMaskPass.cpp b/libraries/render-utils/src/StencilMaskPass.cpp index f9305d8268..79833795e9 100644 --- a/libraries/render-utils/src/StencilMaskPass.cpp +++ b/libraries/render-utils/src/StencilMaskPass.cpp @@ -128,6 +128,7 @@ void PrepareStencil::testNoAA(gpu::State& state) { gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } +// Pass if this area has been marked as MASK or NO_AA void PrepareStencil::testMaskNoAA(gpu::State& state) { state.setStencilTest(true, 0x00, gpu::State::StencilTest(0, STENCIL_MASK | STENCIL_NO_AA, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); From 81509b3e92e4a13b3129a97a6ef71e5fcc15869e Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 2 Nov 2017 10:34:57 -0700 Subject: [PATCH 08/21] coding standard --- libraries/animation/src/Rig.cpp | 7 +++---- libraries/animation/src/Rig.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 9df12de540..acf7bf81d8 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -152,7 +152,7 @@ void Rig::overrideRoleAnimation(const QString& role, const QString& url, float f const float REFERENCE_FRAMES_PER_SECOND = 30.0f; float timeScale = fps / REFERENCE_FRAMES_PER_SECOND; auto clipNode = std::make_shared(role, url, firstFrame, lastFrame, timeScale, loop, false); - _roleAnimState[role] = { role, url, fps, loop, firstFrame, lastFrame }; + _roleAnimStates[role] = { role, url, fps, loop, firstFrame, lastFrame }; AnimNode::Pointer parent = node->getParent(); parent->replaceChild(node, clipNode); } else { @@ -1640,9 +1640,8 @@ void Rig::initAnimGraph(const QUrl& url) { overrideAnimation(origState.url, origState.fps, origState.loop, origState.firstFrame, origState.lastFrame); } // restore the role animations we had before reset. - for (auto ite = _roleAnimState.begin(); ite != _roleAnimState.end(); ite++) { - auto role = ite->first; - auto roleState = _roleAnimState[role]; + for (auto& roleAnimState : _roleAnimStates) { + auto roleState = roleAnimState.second; overrideRoleAnimation(roleState.role, roleState.url, roleState.fps, roleState.loop, roleState.firstFrame, roleState.lastFrame); } _animLoading = false; diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 8ca701ec2d..e9cc444bd4 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -350,7 +350,7 @@ protected: }; UserAnimState _userAnimState; - std::map _roleAnimState; + std::map _roleAnimStates; float _leftHandOverlayAlpha { 0.0f }; float _rightHandOverlayAlpha { 0.0f }; From d8191e3bd2122f8e45f1ce70d2c4fce98a9f5503 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Thu, 2 Nov 2017 12:45:18 -0700 Subject: [PATCH 09/21] Fixed Mask test. --- libraries/render-utils/src/DrawHaze.cpp | 2 +- libraries/render-utils/src/StencilMaskPass.cpp | 10 ++-------- libraries/render-utils/src/StencilMaskPass.h | 1 - 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index dba35cbb3c..f694a93033 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -140,7 +140,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu gpu::StatePointer state = gpu::StatePointer(new gpu::State()); // Mask out haze on the tablet - PrepareStencil::testMaskNoAA(*state); + PrepareStencil::testMask(*state); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), HazeEffect_ParamsSlot)); diff --git a/libraries/render-utils/src/StencilMaskPass.cpp b/libraries/render-utils/src/StencilMaskPass.cpp index 79833795e9..f71111b64e 100644 --- a/libraries/render-utils/src/StencilMaskPass.cpp +++ b/libraries/render-utils/src/StencilMaskPass.cpp @@ -116,9 +116,9 @@ void PrepareStencil::drawBackground(gpu::State& state) { gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_KEEP)); } -// Pass if this area has NOT been marked as MASK +// Pass if this area has NOT been marked as MASK or anything containing MASK void PrepareStencil::testMask(gpu::State& state) { - state.setStencilTest(true, 0x00, gpu::State::StencilTest(STENCIL_MASK, 0xFF, gpu::NOT_EQUAL, + state.setStencilTest(true, 0x00, gpu::State::StencilTest(STENCIL_MASK, STENCIL_MASK, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } @@ -128,12 +128,6 @@ void PrepareStencil::testNoAA(gpu::State& state) { gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); } -// Pass if this area has been marked as MASK or NO_AA -void PrepareStencil::testMaskNoAA(gpu::State& state) { - state.setStencilTest(true, 0x00, gpu::State::StencilTest(0, STENCIL_MASK | STENCIL_NO_AA, gpu::EQUAL, - gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); -} - // Pass if this area WAS marked as BACKGROUND // (see: model/src/Skybox.cpp, procedural/src/ProceduralSkybox.cpp) void PrepareStencil::testBackground(gpu::State& state) { diff --git a/libraries/render-utils/src/StencilMaskPass.h b/libraries/render-utils/src/StencilMaskPass.h index 18ec104ff5..fc258b607a 100644 --- a/libraries/render-utils/src/StencilMaskPass.h +++ b/libraries/render-utils/src/StencilMaskPass.h @@ -51,7 +51,6 @@ public: static void drawBackground(gpu::State& state); static void testMask(gpu::State& state); static void testNoAA(gpu::State& state); - static void testMaskNoAA(gpu::State& state); static void testBackground(gpu::State& state); static void testShape(gpu::State& state); static void testMaskDrawShape(gpu::State& state); From 539cf35f30970c031ea0ccc48aa8cadf206b2fd3 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 3 Nov 2017 17:14:27 -0700 Subject: [PATCH 10/21] saving work --- interface/src/raypick/LaserPointer.cpp | 2 +- interface/src/raypick/LaserPointer.h | 2 +- .../controllerModules/farActionGrabEntity.js | 44 ++++++++++++++++++- .../libraries/controllerDispatcherUtils.js | 29 ++++++++++++ 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 75b43a251b..9da8ff34ac 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -233,7 +233,7 @@ void LaserPointer::setLaserLength(const float laserLength) { }); } -void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay) { +void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offset) { withWriteLock([&] { _objectLockEnd = std::pair(objectID, isOverlay); }); diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index f2350c7199..a80f9d447d 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -74,7 +74,7 @@ public: void setPrecisionPicking(const bool precisionPicking); void setLaserLength(const float laserLength); - void setLockEndUUID(QUuid objectID, const bool isOverlay); + void setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offset = glm::mat4()); void setIgnoreItems(const QVector& ignoreItems) const; void setIncludeItems(const QVector& includeItems) const; diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index e34855d521..e63d7c7c35 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -19,6 +19,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); +Script.include("/~/system/libraries/Xform.hs"); (function() { var PICK_WITH_HAND_RAY = true; @@ -113,10 +114,42 @@ Script.include("/~/system/libraries/controllers.js"); ]; var MARGIN = 25; + + function TargetObject(entityID) { + this.entityID = entityID; + this.entityProps = null; + this.parentID = null; + this.parentProps = []; + this.childrenProps = []; + this.parentsCollisionStatus = []; + this.childrenCollisionStatus = []; + this.madeDynamic = null; + this.parentEntityProps = null; + + this.makeDynamic = function() { + }; + + this.saveCollisionStatus = function() { + }; + + this.restoreEntitiesProperties = function() { + }; + + this.getTargetEntity = function() { + var parentPropsLength = this.parentProps.length; + if (parentPropsLength !== 0) { + return this.parentProps[parentPropsLength].id; + } + return this.entityID; + }; + } + function FarActionGrabEntity(hand) { this.hand = hand; this.grabbedThingID = null; + this.targetObject = null; this.actionID = null; // action this script created... + this.entityToLockOnto = null; this.entityWithContextOverlay = false; this.contextOverlayTimer = false; this.previousCollisionStatus = false; @@ -158,7 +191,8 @@ Script.include("/~/system/libraries/controllers.js"); LaserPointers.enableLaserPointer(laserPointerID); LaserPointers.setRenderState(laserPointerID, mode); if (this.distanceHolding || this.distanceRotating) { - LaserPointers.setLockEndUUID(laserPointerID, this.grabbedThingID, this.grabbedIsOverlay); + // calculate offset + LaserPointers.setLockEndUUID(laserPointerID, this.entityToLockOnto, this.grabbedIsOverlay); } else { LaserPointers.setLockEndUUID(laserPointerID, null, false); } @@ -351,6 +385,7 @@ Script.include("/~/system/libraries/controllers.js"); } this.actionID = null; this.grabbedThingID = null; + this.entityToLockOnto = null; }; this.updateRecommendedArea = function() { @@ -497,17 +532,24 @@ Script.include("/~/system/libraries/controllers.js"); if (rayPickInfo.type === RayPick.INTERSECTED_ENTITY) { if (controllerData.triggerClicks[this.hand]) { var entityID = rayPickInfo.objectID; + this.entityToLockOnto = entityID; var targetProps = Entities.getEntityProperties(entityID, [ "dynamic", "shapeType", "position", "rotation", "dimensions", "density", "userData", "locked", "type" ]); + this.targetObject = new TargetObject(entityID); if (entityID !== this.entityWithContextOverlay) { this.destroyContextOverlay(); } if (entityIsGrabbable(targetProps)) { + var groupRootProps = findGroupParent(controllerData, targetProps); + if (entityIsGrabbable(groupRootProps)) { + targetProps = groupRootProps; + entityID = targetProps.id; + } if (!entityIsDistanceGrabbable(targetProps)) { targetProps.dynamic = true; this.previousCollisionStatus = targetProps.collisionless; diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index cd3f1a711f..148530c5ec 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -35,12 +35,14 @@ propsArePhysical:true, controllerDispatcherPluginsNeedSort:true, projectOntoXYPlane:true, + getChildrenProps:true, projectOntoEntityXYPlane:true, projectOntoOverlayXYPlane:true, entityHasActions:true, ensureDynamic:true, findGroupParent:true, BUMPER_ON_VALUE:true, + getEntityParents:true, findHandChildEntities:true, TEAR_AWAY_DISTANCE:true, TEAR_AWAY_COUNT:true, @@ -306,6 +308,33 @@ findGroupParent = function (controllerData, targetProps) { return targetProps; }; +getChildrenProps = function(entityID) { + var childrenProps = []; + var childrenIDs = Entities.getChildrenIDs(entityID); + for (var index = 0; index < childrenIDs.length; index++) { + var childProps = Entities.getEntityProperties(childrenIDs[index]); + childrenProps.push(childProps); + } + return childrenProps; +}; + +getEntityParents = function(targetProps) { + var parentProperties = []; + while (targetProps.parentID && + targetProps.parentID !== Uuid.NULL && + Entities.getNestableType(targetProps.parentID) == "entity") { + var parentProps = Entities.getEntityProperties(targetProps.parentID, DISPATCHER_PROPERTIES); + if (!parentProps) { + break; + } + parentProps.id = targetProps.parentID; + targetProps = parentProps; + parentProperties.push(parentProps); + } + + return parentProperties; +}; + findHandChildEntities = function(hand) { // find children of avatar's hand joint From 4a5f52155c8d60a0e7e52a56805691a01ab7c8f5 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 5 Nov 2017 14:33:30 +1300 Subject: [PATCH 11/21] Pin node pointer --- assignment-client/src/entities/EntityTreeSendThread.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index e96a9dc667..f5f8450de7 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -425,7 +425,8 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream uint64_t sendTime = usecTimestampNow(); auto nodeData = static_cast(params.nodeData); nodeData->stats.encodeStarted(); - auto entityNodeData = static_cast(_node.toStrongRef()->getLinkedData()); + auto entityNode = _node.toStrongRef(); + auto entityNodeData = static_cast(entityNode->getLinkedData()); while(!_sendQueue.empty()) { PrioritizedEntity queuedItem = _sendQueue.top(); EntityItemPointer entity = queuedItem.getEntity(); From a76b7855b5d29b887af4784fc538d33a0365272c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 5 Nov 2017 15:03:43 +1300 Subject: [PATCH 12/21] Record only explicitly filtered-in entities for flagging extras --- assignment-client/src/entities/EntityTreeSendThread.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index f5f8450de7..a259dacecd 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -432,8 +432,12 @@ bool EntityTreeSendThread::traverseTreeAndBuildNextPacketPayload(EncodeBitstream EntityItemPointer entity = queuedItem.getEntity(); if (entity) { // Only send entities that match the jsonFilters, but keep track of everything we've tried to send so we don't try to send it again - if (entity->matchesJSONFilters(jsonFilters) || entityNodeData->isEntityFlaggedAsExtra(entity->getID())) { - entityNodeData->insertSentFilteredEntity(entity->getID()); + bool entityMatchesFilters = entity->matchesJSONFilters(jsonFilters); + if (entityMatchesFilters || entityNodeData->isEntityFlaggedAsExtra(entity->getID())) { + if (!jsonFilters.isEmpty() && entityMatchesFilters) { + // Record explicitly filtered-in entity so that extra entities can be flagged. + entityNodeData->insertSentFilteredEntity(entity->getID()); + } OctreeElement::AppendState appendEntityState = entity->appendEntityData(&_packetData, params, _extraEncodeData); if (appendEntityState != OctreeElement::COMPLETED) { From 05275afb4fe034461354cf1f8e0ebd3ba70969a6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 5 Nov 2017 15:48:02 +1300 Subject: [PATCH 13/21] Resending full scene is not necessary after all --- assignment-client/src/entities/EntityTreeSendThread.cpp | 6 +++--- assignment-client/src/entities/EntityTreeSendThread.h | 2 +- libraries/entities/src/DiffTraversal.cpp | 4 ++-- libraries/entities/src/DiffTraversal.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/entities/EntityTreeSendThread.cpp b/assignment-client/src/entities/EntityTreeSendThread.cpp index a259dacecd..11e4d533fb 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.cpp +++ b/assignment-client/src/entities/EntityTreeSendThread.cpp @@ -96,7 +96,7 @@ void EntityTreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, O nodeData->copyCurrentViewFrustum(viewFrustum); EntityTreeElementPointer root = std::dynamic_pointer_cast(_myServer->getOctree()->getRoot()); int32_t lodLevelOffset = nodeData->getBoundaryLevelAdjust() + (viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST); - startNewTraversal(viewFrustum, root, lodLevelOffset, nodeData->getUsesFrustum(), isFullScene); + startNewTraversal(viewFrustum, root, lodLevelOffset, nodeData->getUsesFrustum()); // When the viewFrustum changed the sort order may be incorrect, so we re-sort // and also use the opportunity to cull anything no longer in view @@ -205,9 +205,9 @@ bool EntityTreeSendThread::addDescendantsToExtraFlaggedEntities(const QUuid& fil } void EntityTreeSendThread::startNewTraversal(const ViewFrustum& view, EntityTreeElementPointer root, int32_t lodLevelOffset, - bool usesViewFrustum, bool isFullScene) { + bool usesViewFrustum) { - DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset, usesViewFrustum, isFullScene); + DiffTraversal::Type type = _traversal.prepareNewTraversal(view, root, lodLevelOffset, usesViewFrustum); // there are three types of traversal: // // (1) FirstTime = at login --> find everything in view diff --git a/assignment-client/src/entities/EntityTreeSendThread.h b/assignment-client/src/entities/EntityTreeSendThread.h index 1781de9890..a96a18494d 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.h +++ b/assignment-client/src/entities/EntityTreeSendThread.h @@ -39,7 +39,7 @@ private: bool addDescendantsToExtraFlaggedEntities(const QUuid& filteredEntityID, EntityItem& entityItem, EntityNodeData& nodeData); void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, - bool usesViewFrustum, bool isFullScene); + bool usesViewFrustum); bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override; void preDistributionProcessing() override; diff --git a/libraries/entities/src/DiffTraversal.cpp b/libraries/entities/src/DiffTraversal.cpp index 9b16ee90bf..764c420197 100644 --- a/libraries/entities/src/DiffTraversal.cpp +++ b/libraries/entities/src/DiffTraversal.cpp @@ -143,7 +143,7 @@ DiffTraversal::DiffTraversal() { } DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, - int32_t lodLevelOffset, bool usesViewFrustum, bool isFullScene) { + int32_t lodLevelOffset, bool usesViewFrustum) { assert(root); // there are three types of traversal: // @@ -164,7 +164,7 @@ DiffTraversal::Type DiffTraversal::prepareNewTraversal(const ViewFrustum& viewFr Type type; // If usesViewFrustum changes, treat it as a First traversal - if (_completedView.startTime == 0 || _currentView.usesViewFrustum != _completedView.usesViewFrustum || isFullScene) { + if (_completedView.startTime == 0 || _currentView.usesViewFrustum != _completedView.usesViewFrustum) { type = Type::First; _currentView.viewFrustum = viewFrustum; _currentView.lodScaleFactor = lodScaleFactor; diff --git a/libraries/entities/src/DiffTraversal.h b/libraries/entities/src/DiffTraversal.h index becf322fd5..eb7168356e 100644 --- a/libraries/entities/src/DiffTraversal.h +++ b/libraries/entities/src/DiffTraversal.h @@ -58,7 +58,7 @@ public: DiffTraversal(); Type prepareNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, - bool usesViewFrustum, bool isFullScene); + bool usesViewFrustum); const ViewFrustum& getCurrentView() const { return _currentView.viewFrustum; } const ViewFrustum& getCompletedView() const { return _completedView.viewFrustum; } From e2ca3c6de04e6662f83ff80f550871220bd8afb8 Mon Sep 17 00:00:00 2001 From: Midnight Date: Sun, 5 Nov 2017 13:39:26 -0700 Subject: [PATCH 14/21] Fix lib file path Changed the include to what should be the correct file path. it does not exist in the controllers folder. --- scripts/system/libraries/cloneEntityUtils.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/system/libraries/cloneEntityUtils.js b/scripts/system/libraries/cloneEntityUtils.js index 777504b16d..63b161eb80 100644 --- a/scripts/system/libraries/cloneEntityUtils.js +++ b/scripts/system/libraries/cloneEntityUtils.js @@ -8,8 +8,7 @@ /* global entityIsCloneable:true, getGrabbableData:true, cloneEntity:true, propsAreCloneDynamic:true, Script, propsAreCloneDynamic:true, Entities*/ -Script.include("/~/system/controllers/controllerDispatcherUtils.js"); - +Script.include("/~/system/libraries/controllerDispatcherUtils.js"); // Object assign polyfill if (typeof Object.assign !== 'function') { From 3b15897b123e40d6faa1dab4edb46bc36f77fd04 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 6 Nov 2017 15:21:20 -0800 Subject: [PATCH 15/21] fixed farGrab parent grabbing and laser LockEndUUID --- interface/src/raypick/LaserPointer.cpp | 11 +- interface/src/raypick/LaserPointer.h | 3 +- interface/src/raypick/LaserPointerManager.cpp | 4 +- interface/src/raypick/LaserPointerManager.h | 2 +- .../raypick/LaserPointerScriptingInterface.h | 2 +- .../controllerModules/farActionGrabEntity.js | 107 +++++++++++------- .../libraries/controllerDispatcherUtils.js | 10 -- 7 files changed, 78 insertions(+), 61 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 9da8ff34ac..0d691911c8 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -25,7 +25,7 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende _distanceScaleEnd(distanceScaleEnd), _rayPickUID(DependencyManager::get()->createRayPick(rayProps)) { - + _offsetMat = glm::mat4(); for (auto& state : _renderStates) { if (!enabled || state.first != _currentRenderState) { @@ -134,8 +134,10 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter registrationPoint = glm::vec3(0.5f); } else { EntityItemProperties props = DependencyManager::get()->getEntityProperties(_objectLockEnd.first); - pos = props.getPosition(); - rot = props.getRotation(); + glm::mat4 entityMat = createMatFromQuatAndPos(props.getRotation(), props.getPosition()); + glm::mat4 finalPosAndRotMat = entityMat * _offsetMat; + pos = extractTranslation(finalPosAndRotMat); + rot = glmExtractRotation(finalPosAndRotMat); dim = props.getDimensions(); registrationPoint = props.getRegistrationPoint(); } @@ -233,9 +235,10 @@ void LaserPointer::setLaserLength(const float laserLength) { }); } -void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offset) { +void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offsetMat) { withWriteLock([&] { _objectLockEnd = std::pair(objectID, isOverlay); + _offsetMat = offsetMat; }); } diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index a80f9d447d..40a7d93356 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -74,7 +74,7 @@ public: void setPrecisionPicking(const bool precisionPicking); void setLaserLength(const float laserLength); - void setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offset = glm::mat4()); + void setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offsetMat = glm::mat4()); void setIgnoreItems(const QVector& ignoreItems) const; void setIncludeItems(const QVector& includeItems) const; @@ -91,6 +91,7 @@ private: bool _centerEndY; bool _lockEnd; bool _distanceScaleEnd; + glm::mat4 _offsetMat; std::pair _objectLockEnd { std::pair(QUuid(), false)}; const QUuid _rayPickUID; diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 9d58cc2587..45420d1488 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -113,9 +113,9 @@ void LaserPointerManager::setIncludeItems(const QUuid& uid, const QVector } } -void LaserPointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const { +void LaserPointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay, const glm::mat4& offsetMat) const { auto laserPointer = find(uid); if (laserPointer) { - laserPointer->setLockEndUUID(objectID, isOverlay); + laserPointer->setLockEndUUID(objectID, isOverlay, offsetMat); } } diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index e302318483..25089a291a 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -39,7 +39,7 @@ public: void setIgnoreItems(const QUuid& uid, const QVector& ignoreEntities) const; void setIncludeItems(const QUuid& uid, const QVector& includeEntities) const; - void setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const; + void setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const; void update(); diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 19262e6e5d..986c53e24f 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -35,7 +35,7 @@ public slots: Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities) const; Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities) const; - Q_INVOKABLE void setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay) const { qApp->getLaserPointerManager().setLockEndUUID(uid, objectID, isOverlay); } + Q_INVOKABLE void setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const { qApp->getLaserPointerManager().setLockEndUUID(uid, objectID, isOverlay, offsetMat); } private: static RenderState buildRenderState(const QVariantMap& propMap); diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index e63d7c7c35..7d9a6dc1b5 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -13,13 +13,13 @@ makeDispatcherModuleParameters, MSECS_PER_SEC, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic, - getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI + getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI, Xform, getEntityParents */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); -Script.include("/~/system/libraries/Xform.hs"); +Script.include("/~/system/libraries/Xform.js"); (function() { var PICK_WITH_HAND_RAY = true; @@ -115,32 +115,53 @@ Script.include("/~/system/libraries/Xform.hs"); var MARGIN = 25; - function TargetObject(entityID) { + function TargetObject(entityID, entityProps) { this.entityID = entityID; - this.entityProps = null; - this.parentID = null; - this.parentProps = []; - this.childrenProps = []; - this.parentsCollisionStatus = []; - this.childrenCollisionStatus = []; + this.entityProps = entityProps; + this.targetEntityID = null; + this.targetEntityProps = null; + this.previousCollisionStatus = null; this.madeDynamic = null; - this.parentEntityProps = null; this.makeDynamic = function() { + if (this.targetEntityID) { + var newProps = { + dynamic: true, + collisionless: true + }; + this.previousCollisionStatus = this.targetEntityProps.collisionless; + Entities.editEntity(this.targetEntityID, newProps); + this.madeDynamic = true; + } }; - this.saveCollisionStatus = function() { - }; - - this.restoreEntitiesProperties = function() { + this.restoreTargetEntityOriginalProps = function() { + if (this.madeDynamic) { + var props = {}; + props.dynamic = false; + props.collisionless = this.previousCollisionStatus; + var zeroVector = {x: 0, y: 0, z:0}; + props.localVelocity = zeroVector; + props.localRotation = zeroVector; + Entities.editEntity(this.targetEntityID, props); + } }; this.getTargetEntity = function() { var parentPropsLength = this.parentProps.length; if (parentPropsLength !== 0) { - return this.parentProps[parentPropsLength].id; + var targetEntity = { + id: this.parentProps[parentPropsLength - 1].id, + props: this.parentProps[parentPropsLength - 1]}; + this.targetEntityID = targetEntity.id; + this.targetEntityProps = targetEntity.props; + return targetEntity; } - return this.entityID; + this.targetEntityID = this.entityID; + this.targetEntityProps = this.entityProps; + return { + id: this.entityID, + props: this.entityProps}; }; } @@ -153,11 +174,11 @@ Script.include("/~/system/libraries/Xform.hs"); this.entityWithContextOverlay = false; this.contextOverlayTimer = false; this.previousCollisionStatus = false; + this.locked = false; this.reticleMinX = MARGIN; this.reticleMaxX; this.reticleMinY = MARGIN; this.reticleMaxY; - this.madeDynamic = false; var ACTION_TTL = 15; // seconds @@ -191,10 +212,25 @@ Script.include("/~/system/libraries/Xform.hs"); LaserPointers.enableLaserPointer(laserPointerID); LaserPointers.setRenderState(laserPointerID, mode); if (this.distanceHolding || this.distanceRotating) { - // calculate offset - LaserPointers.setLockEndUUID(laserPointerID, this.entityToLockOnto, this.grabbedIsOverlay); + if (!this.locked) { + // calculate offset + var targetProps = Entities.getEntityProperties(this.targetObject.entityID, [ + "position", + "rotation" + ]); + var zeroVector = { x: 0, y: 0, z:0, w: 0 }; + var intersection = controllerData.rayPicks[this.hand].intersection; + var intersectionMat = new Xform(zeroVector, intersection); + var modelMat = new Xform(targetProps.rotation, targetProps.position); + var modelMatInv = modelMat.inv(); + var xformMat = Xform.mul(modelMatInv, intersectionMat); + var offsetMat = Mat4.createFromRotAndTrans(xformMat.rot, xformMat.pos); + LaserPointers.setLockEndUUID(laserPointerID, this.targetObject.entityID, this.grabbedIsOverlay, offsetMat); + this.locked = true; + } } else { LaserPointers.setLockEndUUID(laserPointerID, null, false); + this.locked = false; } }; @@ -373,22 +409,15 @@ Script.include("/~/system/libraries/Xform.hs"); var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.grabbedThingID, "releaseGrab", args); - - if (this.madeDynamic) { - var props = {}; - props.dynamic = false; - props.collisionless = this.previousCollisionStatus; - props.localVelocity = {x: 0, y: 0, z: 0}; - props.localRotation = {x: 0, y: 0, z: 0}; - Entities.editEntity(this.grabbedThingID, props); - this.madeDynamic = false; + if (this.targetObject) { + this.targetObject.restoreTargetEntityOriginalProps(); } this.actionID = null; this.grabbedThingID = null; - this.entityToLockOnto = null; + this.targetObject = null; }; - this.updateRecommendedArea = function() { + this.updateRecommendedArea = function() { var dims = Controller.getViewportDimensions(); this.reticleMaxX = dims.x - MARGIN; this.reticleMaxY = dims.y - MARGIN; @@ -532,30 +561,24 @@ Script.include("/~/system/libraries/Xform.hs"); if (rayPickInfo.type === RayPick.INTERSECTED_ENTITY) { if (controllerData.triggerClicks[this.hand]) { var entityID = rayPickInfo.objectID; - this.entityToLockOnto = entityID; var targetProps = Entities.getEntityProperties(entityID, [ "dynamic", "shapeType", "position", "rotation", "dimensions", "density", "userData", "locked", "type" ]); - this.targetObject = new TargetObject(entityID); + this.targetObject = new TargetObject(entityID, targetProps); + this.targetObject.parentProps = getEntityParents(targetProps); if (entityID !== this.entityWithContextOverlay) { this.destroyContextOverlay(); } + var targetEntity = this.targetObject.getTargetEntity(); + entityID = targetEntity.id; + targetProps = targetEntity.props; if (entityIsGrabbable(targetProps)) { - var groupRootProps = findGroupParent(controllerData, targetProps); - if (entityIsGrabbable(groupRootProps)) { - targetProps = groupRootProps; - entityID = targetProps.id; - } if (!entityIsDistanceGrabbable(targetProps)) { - targetProps.dynamic = true; - this.previousCollisionStatus = targetProps.collisionless; - targetProps.collisionless = true; - Entities.editEntity(entityID, targetProps); - this.madeDynamic = true; + this.targetObject.makeDynamic(); } if (!this.distanceRotating) { diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 148530c5ec..fb6de0e683 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -308,16 +308,6 @@ findGroupParent = function (controllerData, targetProps) { return targetProps; }; -getChildrenProps = function(entityID) { - var childrenProps = []; - var childrenIDs = Entities.getChildrenIDs(entityID); - for (var index = 0; index < childrenIDs.length; index++) { - var childProps = Entities.getEntityProperties(childrenIDs[index]); - childrenProps.push(childProps); - } - return childrenProps; -}; - getEntityParents = function(targetProps) { var parentProperties = []; while (targetProps.parentID && From 41c6261b74d0d591a908fa31f255e07354eef803 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 6 Nov 2017 16:04:33 -0800 Subject: [PATCH 16/21] LaserPointer: made _objectLockEnd into a struct --- interface/src/raypick/LaserPointer.cpp | 23 ++++++++++++----------- interface/src/raypick/LaserPointer.h | 8 +++++++- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 0d691911c8..f3d74d18a5 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -119,23 +119,23 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter qApp->getOverlays().editOverlay(renderState.getStartID(), startProps); } glm::vec3 endVec; - if (((defaultState || !_lockEnd) && _objectLockEnd.first.isNull()) || type == IntersectionType::HUD) { + if (((defaultState || !_lockEnd) && _lockEndObject.id.isNull()) || type == IntersectionType::HUD) { endVec = pickRay.origin + pickRay.direction * distance; } else { - if (!_objectLockEnd.first.isNull()) { + if (!_lockEndObject.id.isNull()) { glm::vec3 pos; glm::quat rot; glm::vec3 dim; glm::vec3 registrationPoint; - if (_objectLockEnd.second) { - pos = vec3FromVariant(qApp->getOverlays().getProperty(_objectLockEnd.first, "position").value); - rot = quatFromVariant(qApp->getOverlays().getProperty(_objectLockEnd.first, "rotation").value); - dim = vec3FromVariant(qApp->getOverlays().getProperty(_objectLockEnd.first, "dimensions").value); + if (_lockEndObject.isOverlay) { + pos = vec3FromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "position").value); + rot = quatFromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "rotation").value); + dim = vec3FromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "dimensions").value); registrationPoint = glm::vec3(0.5f); } else { - EntityItemProperties props = DependencyManager::get()->getEntityProperties(_objectLockEnd.first); + EntityItemProperties props = DependencyManager::get()->getEntityProperties(_lockEndObject.id); glm::mat4 entityMat = createMatFromQuatAndPos(props.getRotation(), props.getPosition()); - glm::mat4 finalPosAndRotMat = entityMat * _offsetMat; + glm::mat4 finalPosAndRotMat = entityMat * _lockEndObject.offsetMat; pos = extractTranslation(finalPosAndRotMat); rot = glmExtractRotation(finalPosAndRotMat); dim = props.getDimensions(); @@ -211,7 +211,7 @@ void LaserPointer::update() { withReadLock([&] { RayPickResult prevRayPickResult = qApp->getRayPickManager().getPrevRayPickResult(_rayPickUID); if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() && - (prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) { + (prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_lockEndObject.id.isNull())) { float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance; updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false); disableRenderState(_defaultRenderStates[_currentRenderState].second); @@ -237,8 +237,9 @@ void LaserPointer::setLaserLength(const float laserLength) { void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offsetMat) { withWriteLock([&] { - _objectLockEnd = std::pair(objectID, isOverlay); - _offsetMat = offsetMat; + _lockEndObject.id = objectID; + _lockEndObject.isOverlay; + _lockEndObject.offsetMat = offsetMat; }); } diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 40a7d93356..2171698cc5 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -21,6 +21,12 @@ class RayPickResult; +struct LockEndObject { + QUuid id {QUuid()}; + bool isOverlay {false}; + glm::mat4 offsetMat {glm::mat4()}; +}; + class RenderState { public: @@ -91,8 +97,8 @@ private: bool _centerEndY; bool _lockEnd; bool _distanceScaleEnd; + LockEndObject _lockEndObject; glm::mat4 _offsetMat; - std::pair _objectLockEnd { std::pair(QUuid(), false)}; const QUuid _rayPickUID; From 646e5455ac8c4eee8454da1c3fa498196e50e67c Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 6 Nov 2017 16:05:44 -0800 Subject: [PATCH 17/21] forgot to remove unused variable --- interface/src/raypick/LaserPointer.h | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 2171698cc5..32ef189d76 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -98,7 +98,6 @@ private: bool _lockEnd; bool _distanceScaleEnd; LockEndObject _lockEndObject; - glm::mat4 _offsetMat; const QUuid _rayPickUID; From 067ed2ffe064126065852ec83cd56306421e206d Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 6 Nov 2017 16:09:31 -0800 Subject: [PATCH 18/21] apply coding standard --- interface/src/raypick/LaserPointer.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 32ef189d76..896752a96e 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -22,9 +22,9 @@ class RayPickResult; struct LockEndObject { - QUuid id {QUuid()}; - bool isOverlay {false}; - glm::mat4 offsetMat {glm::mat4()}; + QUuid id { QUuid() }; + bool isOverlay { false }; + glm::mat4 offsetMat { glm::mat4() }; }; class RenderState { From c9d67f762bbcd1db95b73faf7f624fd3c8eacd39 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Mon, 6 Nov 2017 16:20:16 -0800 Subject: [PATCH 19/21] made requested changes --- interface/src/raypick/LaserPointer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index f3d74d18a5..32dd74279b 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -25,7 +25,6 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende _distanceScaleEnd(distanceScaleEnd), _rayPickUID(DependencyManager::get()->createRayPick(rayProps)) { - _offsetMat = glm::mat4(); for (auto& state : _renderStates) { if (!enabled || state.first != _currentRenderState) { @@ -238,7 +237,7 @@ void LaserPointer::setLaserLength(const float laserLength) { void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay, const glm::mat4& offsetMat) { withWriteLock([&] { _lockEndObject.id = objectID; - _lockEndObject.isOverlay; + _lockEndObject.isOverlay = isOverlay; _lockEndObject.offsetMat = offsetMat; }); } From 60319e8d53a3605dc5cefc0f70e275357eacf364 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 7 Nov 2017 13:35:31 +1300 Subject: [PATCH 20/21] Don't move or rotate entities if Alt or Meta keys are pressed --- scripts/system/controllers/grab.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index a1846e7ad7..eaa15ee3b1 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -315,6 +315,10 @@ Grabber.prototype.pressEvent = function(event) { return; } + if (event.isAlt || event.isMeta) { + return; + } + if (Overlays.getOverlayAtPoint(Reticle.position) > 0) { // the mouse is pointing at an overlay; don't look for entities underneath the overlay. return; From fadbf09cdd659569b4f8df988a9e23a48571c111 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 7 Nov 2017 18:10:10 +1300 Subject: [PATCH 21/21] Avoid potentially slow entity list refresh upon deleting entities --- scripts/system/edit.js | 13 +++++++++++-- scripts/system/html/js/entityList.js | 7 ++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index e76a02b6f5..ba84ffd716 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -1333,7 +1333,7 @@ function sortSelectedEntities(selected) { return sortedEntities; } -function recursiveDelete(entities, childrenList) { +function recursiveDelete(entities, childrenList, deletedIDs) { var entitiesLength = entities.length; for (var i = 0; i < entitiesLength; i++) { var entityID = entities[i]; @@ -1346,6 +1346,7 @@ function recursiveDelete(entities, childrenList) { properties: initialProperties, children: grandchildrenList }); + deletedIDs.push(entityID); Entities.deleteEntity(entityID); } } @@ -1413,6 +1414,8 @@ function parentSelectedEntities() { } function deleteSelectedEntities() { if (SelectionManager.hasSelection()) { + var deletedIDs = []; + selectedParticleEntityID = null; particleExplorerTool.destroyWebView(); SelectionManager.saveProperties(); @@ -1423,16 +1426,22 @@ function deleteSelectedEntities() { var initialProperties = SelectionManager.savedProperties[entityID]; var children = Entities.getChildrenIDs(entityID); var childList = []; - recursiveDelete(children, childList); + recursiveDelete(children, childList, deletedIDs); savedProperties.push({ entityID: entityID, properties: initialProperties, children: childList }); + deletedIDs.push(entityID); Entities.deleteEntity(entityID); } SelectionManager.clearSelections(); pushCommandForSelections([], savedProperties); + + entityListTool.webView.emitScriptEvent(JSON.stringify({ + type: "deleted", + ids: deletedIDs + })); } } diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index ea79750154..7b25e66c67 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -286,7 +286,6 @@ function loaded() { } elDelete.onclick = function() { EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' })); - refreshEntities(); } document.addEventListener("keydown", function (keyDownEvent) { @@ -362,6 +361,12 @@ function loaded() { updateSelectedEntities(data.selectedIDs); resize(); } + } else if (data.type === "deleted") { + for (i = 0, length = data.ids.length; i < length; i++) { + delete entities[data.ids[i]]; + entityList.remove("id", data.ids[i]); + } + refreshFooter(); } }); setTimeout(refreshEntities, 1000);