From 596be8ec271139a94c9c6b40ddf5a38644a46065 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 17 Oct 2017 12:00:56 -0700 Subject: [PATCH 1/9] pickmanager wip --- interface/src/raypick/JointRayPick.cpp | 4 +- interface/src/raypick/JointRayPick.h | 6 +- interface/src/raypick/MouseRayPick.cpp | 5 +- interface/src/raypick/MouseRayPick.h | 6 +- interface/src/raypick/Pick.cpp | 10 + .../RayPick.h => interface/src/raypick/Pick.h | 135 ++++++++-- interface/src/raypick/PickManager.h | 244 ++++++++++++++++++ interface/src/raypick/RayPick.cpp | 39 +++ interface/src/raypick/RayPick.h | 35 +++ interface/src/raypick/RayPickManager.cpp | 192 +------------- interface/src/raypick/RayPickManager.h | 58 +---- .../src/raypick}/StaticRayPick.cpp | 4 +- .../src/raypick}/StaticRayPick.h | 4 +- .../pointers/src/pointers/rays/RayPick.cpp | 75 ------ libraries/shared/src/RegisteredMetaTypes.h | 15 ++ 15 files changed, 487 insertions(+), 345 deletions(-) create mode 100644 interface/src/raypick/Pick.cpp rename libraries/pointers/src/pointers/rays/RayPick.h => interface/src/raypick/Pick.h (51%) create mode 100644 interface/src/raypick/PickManager.h create mode 100644 interface/src/raypick/RayPick.cpp create mode 100644 interface/src/raypick/RayPick.h rename {libraries/pointers/src/pointers/rays => interface/src/raypick}/StaticRayPick.cpp (73%) rename {libraries/pointers/src/pointers/rays => interface/src/raypick}/StaticRayPick.h (75%) delete mode 100644 libraries/pointers/src/pointers/rays/RayPick.cpp diff --git a/interface/src/raypick/JointRayPick.cpp b/interface/src/raypick/JointRayPick.cpp index cf3f380ca0..d3991eac24 100644 --- a/interface/src/raypick/JointRayPick.cpp +++ b/interface/src/raypick/JointRayPick.cpp @@ -12,7 +12,7 @@ #include "avatar/AvatarManager.h" -JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled) : +JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, const float maxDistance, const bool enabled) : RayPick(filter, maxDistance, enabled), _jointName(jointName), _posOffset(posOffset), @@ -20,7 +20,7 @@ JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOff { } -const PickRay JointRayPick::getPickRay(bool& valid) const { +const PickRay JointRayPick::getMathematicalPick(bool& valid) const { auto myAvatar = DependencyManager::get()->getMyAvatar(); int jointIndex = myAvatar->getJointIndex(QString::fromStdString(_jointName)); bool useAvatarHead = _jointName == "Avatar"; diff --git a/interface/src/raypick/JointRayPick.h b/interface/src/raypick/JointRayPick.h index e3e5670e20..b2bffe83c4 100644 --- a/interface/src/raypick/JointRayPick.h +++ b/interface/src/raypick/JointRayPick.h @@ -11,14 +11,14 @@ #ifndef hifi_JointRayPick_h #define hifi_JointRayPick_h -#include +#include "RayPick.h" class JointRayPick : public RayPick { public: - JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); + JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); - const PickRay getPickRay(bool& valid) const override; + const PickRay getMathematicalPick(bool& valid) const override; private: std::string _jointName; diff --git a/interface/src/raypick/MouseRayPick.cpp b/interface/src/raypick/MouseRayPick.cpp index de59fde88d..27080f5857 100644 --- a/interface/src/raypick/MouseRayPick.cpp +++ b/interface/src/raypick/MouseRayPick.cpp @@ -10,16 +10,15 @@ // #include "MouseRayPick.h" -#include "DependencyManager.h" #include "Application.h" #include "display-plugins/CompositorHelper.h" -MouseRayPick::MouseRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) : +MouseRayPick::MouseRayPick(const PickFilter& filter, const float maxDistance, const bool enabled) : RayPick(filter, maxDistance, enabled) { } -const PickRay MouseRayPick::getPickRay(bool& valid) const { +const PickRay MouseRayPick::getMathematicalPick(bool& valid) const { QVariant position = qApp->getApplicationCompositor().getReticleInterface()->getPosition(); if (position.isValid()) { QVariantMap posMap = position.toMap(); diff --git a/interface/src/raypick/MouseRayPick.h b/interface/src/raypick/MouseRayPick.h index 47f9404f3a..c565a03db7 100644 --- a/interface/src/raypick/MouseRayPick.h +++ b/interface/src/raypick/MouseRayPick.h @@ -11,14 +11,14 @@ #ifndef hifi_MouseRayPick_h #define hifi_MouseRayPick_h -#include +#include "RayPick.h" class MouseRayPick : public RayPick { public: - MouseRayPick(const RayPickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); + MouseRayPick(const PickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); - const PickRay getPickRay(bool& valid) const override; + const PickRay getMathematicalPick(bool& valid) const override; }; #endif // hifi_MouseRayPick_h diff --git a/interface/src/raypick/Pick.cpp b/interface/src/raypick/Pick.cpp new file mode 100644 index 0000000000..030d2ef4b7 --- /dev/null +++ b/interface/src/raypick/Pick.cpp @@ -0,0 +1,10 @@ +// +// Created by Sam Gondelman 10/17/2017 +// 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 "Pick.h" + +const PickFilter PickFilter::NOTHING; \ No newline at end of file diff --git a/libraries/pointers/src/pointers/rays/RayPick.h b/interface/src/raypick/Pick.h similarity index 51% rename from libraries/pointers/src/pointers/rays/RayPick.h rename to interface/src/raypick/Pick.h index 5a53891dc6..561c336f3b 100644 --- a/libraries/pointers/src/pointers/rays/RayPick.h +++ b/interface/src/raypick/Pick.h @@ -1,12 +1,12 @@ // -// Created by Sam Gondelman 7/11/2017 +// Created by Sam Gondelman 10/17/2017 // 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_RayPick_h -#define hifi_RayPick_h +#ifndef hifi_Pick_h +#define hifi_Pick_h #include #include @@ -16,7 +16,10 @@ #include #include -class RayPickFilter { +#include "EntityScriptingInterface.h" +#include "ui/overlays/Overlays.h" + +class PickFilter { public: enum FlagBit { PICK_ENTITIES = 0, @@ -39,11 +42,11 @@ public: // The key is the Flags Flags _flags; - RayPickFilter() {} - RayPickFilter(const Flags& flags) : _flags(flags) {} + PickFilter() {} + PickFilter(const Flags& flags) : _flags(flags) {} - bool operator== (const RayPickFilter& rhs) const { return _flags == rhs._flags; } - bool operator!= (const RayPickFilter& rhs) const { return _flags != rhs._flags; } + bool operator== (const PickFilter& rhs) const { return _flags == rhs._flags; } + bool operator!= (const PickFilter& rhs) const { return _flags != rhs._flags; } void setFlag(FlagBit flag, bool value) { _flags[flag] = value; } @@ -91,29 +94,42 @@ public: static constexpr unsigned int getBitMask(FlagBit bit) { return 1 << bit; } - static const RayPickFilter NOTHING; + static const PickFilter NOTHING; }; -class RayPick : protected ReadWriteLockable { +template +class Pick : protected ReadWriteLockable { public: - using Pointer = std::shared_ptr; + using Pointer = std::shared_ptr>; - RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled); + Pick(const PickFilter& filter, const float maxDistance, const bool enabled); - virtual const PickRay getPickRay(bool& valid) const = 0; + virtual const T getMathematicalPick(bool& valid) const = 0; + virtual RayToEntityIntersectionResult getEntityIntersection(const T& pick, bool precisionPicking, + const QVector& entitiesToInclude, + const QVector& entitiesToIgnore, + bool visibleOnly, bool collidableOnly) = 0; + virtual RayToOverlayIntersectionResult getOverlayIntersection(const T& pick, bool precisionPicking, + const QVector& overlaysToInclude, + const QVector& overlaysToIgnore, + bool visibleOnly, bool collidableOnly) = 0; + virtual RayToAvatarIntersectionResult getAvatarIntersection(const T& pick, + const QVector& avatarsToInclude, + const QVector& avatarsToIgnore) = 0; + virtual glm::vec3 getHUDIntersection(const T& pick) = 0; void enable(bool enabled = true); void disable() { enable(false); } - RayPickFilter getFilter() const; + PickFilter getFilter() const; float getMaxDistance() const; bool isEnabled() const; - RayPickResult getPrevRayPickResult() const; + RayPickResult getPrevPickResult() const; void setPrecisionPicking(bool precisionPicking); - void setRayPickResult(const RayPickResult& rayPickResult); + void setPickResult(const RayPickResult& rayPickResult); QVector getIgnoreItems() const; QVector getIncludeItems() const; @@ -144,7 +160,7 @@ public: void setIncludeItems(const QVector& items); private: - RayPickFilter _filter; + PickFilter _filter; const float _maxDistance; bool _enabled; RayPickResult _prevResult; @@ -153,4 +169,87 @@ private: QVector _includeItems; }; -#endif // hifi_RayPick_h + +template +Pick::Pick(const PickFilter& filter, const float maxDistance, const bool enabled) : + _filter(filter), + _maxDistance(maxDistance), + _enabled(enabled) { +} + +template +void Pick::enable(bool enabled) { + withWriteLock([&] { + _enabled = enabled; + }); +} + +template +PickFilter Pick::getFilter() const { + return resultWithReadLock([&] { + return _filter; + }); +} + +template +float Pick::getMaxDistance() const { + return _maxDistance; +} + +template +bool Pick::isEnabled() const { + withReadLock([&]) { + return _enabled; + } +} + +template +void Pick::setPrecisionPicking(bool precisionPicking) { + withWriteLock([&] { + _filter.setFlag(PickFilter::PICK_COARSE, !precisionPicking); + }); +} + +template +void Pick::setPickResult(const RayPickResult& PickResult) { + withWriteLock([&] { + _prevResult = PickResult; + }); +} + +template +QVector Pick::getIgnoreItems() const { + withReadLock([&]) { + return _ignoreItems; + } +} + +template +QVector Pick::getIncludeItems() const { + withReadLock([&]) { + return _includeItems; + } +} + +template +RayPickResult Pick::getPrevPickResult() const { + return resultWithReadLock([&] { + return _prevResult; + }); +} + +template +void Pick::setIgnoreItems(const QVector& ignoreItems) { + withWriteLock([&] { + _ignoreItems = ignoreItems; + }); +} + +template +void Pick::setIncludeItems(const QVector& includeItems) { + withWriteLock([&] { + _includeItems = includeItems; + }); +} + +#endif // hifi_Pick_h diff --git a/interface/src/raypick/PickManager.h b/interface/src/raypick/PickManager.h new file mode 100644 index 0000000000..228631449f --- /dev/null +++ b/interface/src/raypick/PickManager.h @@ -0,0 +1,244 @@ +// +// PickManager.h +// interface/src/raypick +// +// Created by Sam Gondelman 10/16/2017 +// 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_PickManager_h +#define hifi_PickManager_h + +#include + +#include "Pick.h" + +typedef struct RayCacheKey { + PickFilter::Flags mask; + QVector include; + QVector ignore; + + bool operator==(const RayCacheKey& other) const { + return (mask == other.mask && include == other.include && ignore == other.ignore); + } +} RayCacheKey; + +namespace std { + template <> + struct hash { + size_t operator()(const RayCacheKey& k) const { + return ((hash()(k.mask) ^ (qHash(k.include) << 1)) >> 1) ^ (qHash(k.ignore) << 1); + } + }; +} + +// T is a mathematical representation of a Pick. +// For example: origin and direction for RayPick +template +class PickManager : protected ReadWriteLockable { + +public: + virtual void update(); + + RayPickResult getPrevPickResult(const QUuid& uid) const; + + void removePick(const QUuid& uid); + void enablePick(const QUuid& uid) const; + void disablePick(const QUuid& uid) const; + + void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const; + void setIgnoreItems(const QUuid& uid, const QVector& ignore) const; + void setIncludeItems(const QUuid& uid, const QVector& include) const; + +protected: + Pick::Pointer findPick(const QUuid& uid) const; + QHash::Pointer> _picks; + + typedef QHash> RayPickCache; + + // Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer + bool checkAndCompareCachedResults(T& pick, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key); + void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, T& pick, RayPickCache& cache); +}; + +template +RayPick::Pointer PickManager::findPick(const QUuid& uid) const { + return resultWithReadLock([&] { + if (_picks.contains(uid)) { + return _picks[uid]; + } + return RayPick::Pointer(); + }); +} + +template +bool PickManager::checkAndCompareCachedResults(T& pick, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key) { + if (cache.contains(pick) && cache[pick].find(key) != cache[pick].end()) { + if (cache[pick][key].distance < res.distance) { + res = cache[pick][key]; + } + return true; + } + return false; +} + +template +void PickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, T& pick, RayPickCache& cache) { + if (intersects) { + cache[pick][key] = resTemp; + if (resTemp.distance < res.distance) { + res = resTemp; + } + } else { + cache[pick][key] = RayPickResult(res.searchRay); + } +} + +template +void PickManager::update() { + RayPickCache results; + QHash::Pointer> cachedPicks; + withReadLock([&] { + cachedPicks = _picks; + }); + + for (const auto& uid : cachedPicks.keys()) { + Pick::Pointer pick = cachedPicks[uid]; + if (!pick->isEnabled() || pick->getFilter().doesPickNothing() || pick->getMaxDistance() < 0.0f) { + continue; + } + + T mathematicalPick; + + { + bool valid; + mathematicalPick = pick->getPickRay(valid); + if (!valid) { + continue; + } + } + + RayPickResult res = RayPickResult(mathematicalPick); + + if (pick->getFilter().doesPickEntities()) { + RayToEntityIntersectionResult entityRes; + bool fromCache = true; + bool invisible = pick->getFilter().doesPickInvisible(); + bool nonCollidable = pick->getFilter().doesPickNonCollidable(); + RayCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; + if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) { + entityRes = pick->getEntityIntersection(mathematicalPick, !pick->getFilter().doesPickCoarse(), + pick->getIncludeItemsAs(), pick->getIgnoreItemsAs(), !invisible, !nonCollidable); + fromCache = false; + } + + if (!fromCache) { + cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, mathematicalPick, entityRes.surfaceNormal), + entityKey, res, mathematicalPick, results); + } + } + + if (pick->getFilter().doesPickOverlays()) { + RayToOverlayIntersectionResult overlayRes; + bool fromCache = true; + bool invisible = pick->getFilter().doesPickInvisible(); + bool nonCollidable = pick->getFilter().doesPickNonCollidable(); + RayCacheKey overlayKey = { pick->getFilter().getOverlayFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; + if (!checkAndCompareCachedResults(mathematicalPick, results, res, overlayKey)) { + overlayRes = pick->getOverlayIntersection(mathematicalPick, !pick->getFilter().doesPickCoarse(), + pick->getIncludeItemsAs(), pick->getIgnoreItemsAs(), !invisible, !nonCollidable); + fromCache = false; + } + + if (!fromCache) { + cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, mathematicalPick, overlayRes.surfaceNormal), + overlayKey, res, mathematicalPick, results); + } + } + + if (pick->getFilter().doesPickAvatars()) { + RayCacheKey avatarKey = { pick->getFilter().getAvatarFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; + if (!checkAndCompareCachedResults(mathematicalPick, results, res, avatarKey)) { + RayToAvatarIntersectionResult avatarRes = pick->getAvatarIntersection(mathematicalPick, + pick->getIncludeItemsAs(), pick->getIgnoreItemsAs()); + cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, mathematicalPick), avatarKey, res, mathematicalPick, results); + } + } + + // Can't intersect with HUD in desktop mode + if (pick->getFilter().doesPickHUD() && DependencyManager::get()->isHMDMode()) { + RayCacheKey hudKey = { pick->getFilter().getHUDFlags(), QVector(), QVector() }; + if (!checkAndCompareCachedResults(mathematicalPick, results, res, hudKey)) { + glm::vec3 hudRes = pick->getHUDIntersection(mathematicalPick.origin, mathematicalPick.direction); + cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(mathematicalPick.origin, hudRes), hudRes, mathematicalPick), hudKey, res, mathematicalPick, results); + } + } + + if (pick->getMaxDistance() == 0.0f || (pick->getMaxDistance() > 0.0f && res.distance < pick->getMaxDistance())) { + pick->setPickResult(res); + } else { + pick->setPickResult(RayPickResult(mathematicalPick)); + } + } +} + +template +RayPickResult PickManager::getPrevPickResult(const QUuid& uid) const { + auto rayPick = findPick(uid); + if (rayPick) { + return rayPick->getPrevPickResult(); + } + return RayPickResult(); +} + +template +void PickManager::removePick(const QUuid& uid) { + withWriteLock([&] { + _picks.remove(uid); + }); +} + +template +void PickManager::enablePick(const QUuid& uid) const { + auto rayPick = findPick(uid); + if (rayPick) { + rayPick->enable(); + } +} + +template +void PickManager::disablePick(const QUuid& uid) const { + auto rayPick = findPick(uid); + if (rayPick) { + rayPick->disable(); + } +} + +template +void PickManager::setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { + auto rayPick = findPick(uid); + if (rayPick) { + rayPick->setPrecisionPicking(precisionPicking); + } +} + +template +void PickManager::setIgnoreItems(const QUuid& uid, const QVector& ignore) const { + auto rayPick = findPick(uid); + if (rayPick) { + rayPick->setIgnoreItems(ignore); + } +} + +template +void PickManager::setIncludeItems(const QUuid& uid, const QVector& include) const { + auto rayPick = findPick(uid); + if (rayPick) { + rayPick->setIncludeItems(include); + } +} + + +#endif // hifi_PickManager_h \ No newline at end of file diff --git a/interface/src/raypick/RayPick.cpp b/interface/src/raypick/RayPick.cpp new file mode 100644 index 0000000000..f12320ee35 --- /dev/null +++ b/interface/src/raypick/RayPick.cpp @@ -0,0 +1,39 @@ +// +// Created by Sam Gondelman 7/11/2017 +// 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 "RayPick.h" + +#include "Application.h" +#include "avatar/AvatarManager.h" +#include "scripting/HMDScriptingInterface.h" +#include "DependencyManager.h" + +RayToEntityIntersectionResult RayPick::getEntityIntersection(const PickRay& pick, bool precisionPicking, + const QVector& entitiesToInclude, + const QVector& entitiesToIgnore, + bool visibleOnly, bool collidableOnly) { + return DependencyManager::get()->findRayIntersectionVector(pick, precisionPicking, + entitiesToInclude, entitiesToIgnore, visibleOnly, collidableOnly); +} + +RayToOverlayIntersectionResult RayPick::getOverlayIntersection(const PickRay& pick, bool precisionPicking, + const QVector& overlaysToInclude, + const QVector& overlaysToIgnore, + bool visibleOnly, bool collidableOnly) { + return qApp->getOverlays().findRayIntersectionVector(pick, precisionPicking, + overlaysToInclude, overlaysToIgnore, visibleOnly, collidableOnly); +} + +RayToAvatarIntersectionResult RayPick::getAvatarIntersection(const PickRay& pick, + const QVector& avatarsToInclude, + const QVector& avatarsToIgnore) { + return DependencyManager::get()->findRayIntersectionVector(pick, avatarsToInclude, avatarsToIgnore); +} + +glm::vec3 RayPick::getHUDIntersection(const PickRay& pick) { + return DependencyManager::get()->calculateRayUICollisionPoint(pick.origin, pick.direction); +} \ No newline at end of file diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h new file mode 100644 index 0000000000..92778e74a2 --- /dev/null +++ b/interface/src/raypick/RayPick.h @@ -0,0 +1,35 @@ +// +// Created by Sam Gondelman 7/11/2017 +// 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_RayPick_h +#define hifi_RayPick_h + +#include "Pick.h" + +class EntityItemID; +class OverlayID; + +class RayPick : public Pick { + +public: + RayPick(const PickFilter& filter, const float maxDistance, const bool enabled) : Pick(filter, maxDistance, enabled) {} + + RayToEntityIntersectionResult getEntityIntersection(const PickRay& pick, bool precisionPicking, + const QVector& entitiesToInclude, + const QVector& entitiesToIgnore, + bool visibleOnly, bool collidableOnly) override; + RayToOverlayIntersectionResult getOverlayIntersection(const PickRay& pick, bool precisionPicking, + const QVector& overlaysToInclude, + const QVector& overlaysToIgnore, + bool visibleOnly, bool collidableOnly) override; + RayToAvatarIntersectionResult getAvatarIntersection(const PickRay& pick, + const QVector& avatarsToInclude, + const QVector& avatarsToIgnore) override; + glm::vec3 getHUDIntersection(const PickRay& pick) override; +}; + +#endif // hifi_RayPick_h diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index beb0075428..f4a45312bf 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -10,209 +10,33 @@ // #include "RayPickManager.h" -#include - -#include "Application.h" -#include "EntityScriptingInterface.h" -#include "ui/overlays/Overlays.h" -#include "avatar/AvatarManager.h" -#include "scripting/HMDScriptingInterface.h" -#include "DependencyManager.h" - +#include "StaticRayPick.h" #include "JointRayPick.h" #include "MouseRayPick.h" -bool RayPickManager::checkAndCompareCachedResults(QPair& ray, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key) { - if (cache.contains(ray) && cache[ray].find(key) != cache[ray].end()) { - if (cache[ray][key].distance < res.distance) { - res = cache[ray][key]; - } - return true; - } - return false; -} - -void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, QPair& ray, RayPickCache& cache) { - if (intersects) { - cache[ray][key] = resTemp; - if (resTemp.distance < res.distance) { - res = resTemp; - } - } else { - cache[ray][key] = RayPickResult(res.searchRay); - } -} - -void RayPickManager::update() { - RayPickCache results; - QHash cachedRayPicks; - withReadLock([&] { - cachedRayPicks = _rayPicks; - }); - - for (const auto& uid : cachedRayPicks.keys()) { - std::shared_ptr rayPick = cachedRayPicks[uid]; - if (!rayPick->isEnabled() || rayPick->getFilter().doesPickNothing() || rayPick->getMaxDistance() < 0.0f) { - continue; - } - - PickRay ray; - - { - bool valid; - ray = rayPick->getPickRay(valid); - if (!valid) { - continue; - } - } - - QPair rayKey = QPair(ray.origin, ray.direction); - RayPickResult res = RayPickResult(ray); - - if (rayPick->getFilter().doesPickEntities()) { - RayToEntityIntersectionResult entityRes; - bool fromCache = true; - bool invisible = rayPick->getFilter().doesPickInvisible(); - bool nonCollidable = rayPick->getFilter().doesPickNonCollidable(); - RayCacheKey entityKey = { rayPick->getFilter().getEntityFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() }; - if (!checkAndCompareCachedResults(rayKey, results, res, entityKey)) { - entityRes = DependencyManager::get()->findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(), - rayPick->getIncludeItemsAs(), rayPick->getIgnoreItemsAs(), !invisible, !nonCollidable); - fromCache = false; - } - - if (!fromCache) { - cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, ray, entityRes.surfaceNormal), - entityKey, res, rayKey, results); - } - } - - if (rayPick->getFilter().doesPickOverlays()) { - RayToOverlayIntersectionResult overlayRes; - bool fromCache = true; - bool invisible = rayPick->getFilter().doesPickInvisible(); - bool nonCollidable = rayPick->getFilter().doesPickNonCollidable(); - RayCacheKey overlayKey = { rayPick->getFilter().getOverlayFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() }; - if (!checkAndCompareCachedResults(rayKey, results, res, overlayKey)) { - overlayRes = qApp->getOverlays().findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(), - rayPick->getIncludeItemsAs(), rayPick->getIgnoreItemsAs(), !invisible, !nonCollidable); - fromCache = false; - } - - if (!fromCache) { - cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, ray, overlayRes.surfaceNormal), - overlayKey, res, rayKey, results); - } - } - - if (rayPick->getFilter().doesPickAvatars()) { - RayCacheKey avatarKey = { rayPick->getFilter().getAvatarFlags(), rayPick->getIncludeItems(), rayPick->getIgnoreItems() }; - if (!checkAndCompareCachedResults(rayKey, results, res, avatarKey)) { - RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersectionVector(ray, - rayPick->getIncludeItemsAs(), rayPick->getIgnoreItemsAs()); - cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, ray), avatarKey, res, rayKey, results); - } - } - - // Can't intersect with HUD in desktop mode - if (rayPick->getFilter().doesPickHUD() && DependencyManager::get()->isHMDMode()) { - RayPickFilter::Flags hudMask = rayPick->getFilter().getHUDFlags(); - RayCacheKey hudKey = { rayPick->getFilter().getHUDFlags() }; - if (!checkAndCompareCachedResults(rayKey, results, res, hudKey)) { - glm::vec3 hudRes = DependencyManager::get()->calculateRayUICollisionPoint(ray.origin, ray.direction); - cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes, ray), hudKey, res, rayKey, results); - } - } - - if (rayPick->getMaxDistance() == 0.0f || (rayPick->getMaxDistance() > 0.0f && res.distance < rayPick->getMaxDistance())) { - rayPick->setRayPickResult(res); - } else { - rayPick->setRayPickResult(RayPickResult(ray)); - } - } -} - -QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, float maxDistance, bool enabled) { +QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, float maxDistance, bool enabled) { auto newRayPick = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled); QUuid id = QUuid::createUuid(); withWriteLock([&] { - _rayPicks[id] = newRayPick; + _picks[id] = newRayPick; }); return id; } -QUuid RayPickManager::createRayPick(const RayPickFilter& filter, float maxDistance, bool enabled) { +QUuid RayPickManager::createRayPick(const PickFilter& filter, float maxDistance, bool enabled) { QUuid id = QUuid::createUuid(); auto newRayPick = std::make_shared(filter, maxDistance, enabled); withWriteLock([&] { - _rayPicks[id] = newRayPick; + _picks[id] = newRayPick; }); return id; } -QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, float maxDistance, bool enabled) { +QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, float maxDistance, bool enabled) { QUuid id = QUuid::createUuid(); auto newRayPick = std::make_shared(position, direction, filter, maxDistance, enabled); withWriteLock([&] { - _rayPicks[id] = newRayPick; + _picks[id] = newRayPick; }); return id; -} - -void RayPickManager::removeRayPick(const QUuid& uid) { - withWriteLock([&] { - _rayPicks.remove(uid); - }); -} - -RayPick::Pointer RayPickManager::findRayPick(const QUuid& uid) const { - return resultWithReadLock([&] { - if (_rayPicks.contains(uid)) { - return _rayPicks[uid]; - } - return RayPick::Pointer(); - }); -} - -void RayPickManager::enableRayPick(const QUuid& uid) const { - auto rayPick = findRayPick(uid); - if (rayPick) { - rayPick->enable(); - } -} - -void RayPickManager::disableRayPick(const QUuid& uid) const { - auto rayPick = findRayPick(uid); - if (rayPick) { - rayPick->disable(); - } -} - -RayPickResult RayPickManager::getPrevRayPickResult(const QUuid& uid) const { - auto rayPick = findRayPick(uid); - if (rayPick) { - return rayPick->getPrevRayPickResult(); - } - return RayPickResult(); -} - -void RayPickManager::setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { - auto rayPick = findRayPick(uid); - if (rayPick) { - rayPick->setPrecisionPicking(precisionPicking); - } -} - -void RayPickManager::setIgnoreItems(const QUuid& uid, const QVector& ignore) const { - auto rayPick = findRayPick(uid); - if (rayPick) { - rayPick->setIgnoreItems(ignore); - } -} - -void RayPickManager::setIncludeItems(const QUuid& uid, const QVector& include) const { - auto rayPick = findRayPick(uid); - if (rayPick) { - rayPick->setIncludeItems(include); - } -} +} \ No newline at end of file diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index fd2c6f4a6b..7673e402f4 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -11,64 +11,16 @@ #ifndef hifi_RayPickManager_h #define hifi_RayPickManager_h - -#include -#include -#include - -#include - -#include -#include - +#include "PickManager.h" class RayPickResult; -typedef struct RayCacheKey { - RayPickFilter::Flags mask; - QVector include; - QVector ignore; - - bool operator==(const RayCacheKey& other) const { - return (mask == other.mask && include == other.include && ignore == other.ignore); - } -} RayCacheKey; - -namespace std { - template <> - struct hash { - size_t operator()(const RayCacheKey& k) const { - return ((hash()(k.mask) ^ (qHash(k.include) << 1)) >> 1) ^ (qHash(k.ignore) << 1); - } - }; -} - -class RayPickManager : protected ReadWriteLockable { +class RayPickManager : public PickManager { public: - void update(); - - QUuid createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled); - QUuid createRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled); - QUuid createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled); - void removeRayPick(const QUuid& uid); - void enableRayPick(const QUuid& uid) const; - void disableRayPick(const QUuid& uid) const; - RayPickResult getPrevRayPickResult(const QUuid& uid) const; - - void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const; - void setIgnoreItems(const QUuid& uid, const QVector& ignore) const; - void setIncludeItems(const QUuid& uid, const QVector& include) const; - -private: - RayPick::Pointer findRayPick(const QUuid& uid) const; - QHash _rayPicks; - - typedef QHash, std::unordered_map> RayPickCache; - - // Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer - bool checkAndCompareCachedResults(QPair& ray, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key); - void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, QPair& ray, RayPickCache& cache); + QUuid createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, const float maxDistance, const bool enabled); + QUuid createRayPick(const PickFilter& filter, const float maxDistance, const bool enabled); + QUuid createRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, const float maxDistance, const bool enabled); }; #endif // hifi_RayPickManager_h \ No newline at end of file diff --git a/libraries/pointers/src/pointers/rays/StaticRayPick.cpp b/interface/src/raypick/StaticRayPick.cpp similarity index 73% rename from libraries/pointers/src/pointers/rays/StaticRayPick.cpp rename to interface/src/raypick/StaticRayPick.cpp index e507341021..5db054c2e4 100644 --- a/libraries/pointers/src/pointers/rays/StaticRayPick.cpp +++ b/interface/src/raypick/StaticRayPick.cpp @@ -7,13 +7,13 @@ // #include "StaticRayPick.h" -StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled) : +StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, const float maxDistance, const bool enabled) : RayPick(filter, maxDistance, enabled), _pickRay(position, direction) { } -const PickRay StaticRayPick::getPickRay(bool& valid) const { +const PickRay StaticRayPick::getMathematicalPick(bool& valid) const { valid = true; return _pickRay; } \ No newline at end of file diff --git a/libraries/pointers/src/pointers/rays/StaticRayPick.h b/interface/src/raypick/StaticRayPick.h similarity index 75% rename from libraries/pointers/src/pointers/rays/StaticRayPick.h rename to interface/src/raypick/StaticRayPick.h index de5ec234a5..c26ea386d6 100644 --- a/libraries/pointers/src/pointers/rays/StaticRayPick.h +++ b/interface/src/raypick/StaticRayPick.h @@ -13,9 +13,9 @@ class StaticRayPick : public RayPick { public: - StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); + StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); - const PickRay getPickRay(bool& valid) const override; + const PickRay getMathematicalPick(bool& valid) const override; private: PickRay _pickRay; diff --git a/libraries/pointers/src/pointers/rays/RayPick.cpp b/libraries/pointers/src/pointers/rays/RayPick.cpp deleted file mode 100644 index 36756cdb79..0000000000 --- a/libraries/pointers/src/pointers/rays/RayPick.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// Created by Sam Gondelman 7/11/2017 -// 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 "RayPick.h" - -const RayPickFilter RayPickFilter::NOTHING; - -RayPick::RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) : - _filter(filter), - _maxDistance(maxDistance), - _enabled(enabled) -{ -} - -void RayPick::enable(bool enabled) { - withWriteLock([&] { - _enabled = enabled; - }); -} - -RayPickFilter RayPick::getFilter() const { - return resultWithReadLock([&] { - return _filter; - }); -} - -float RayPick::getMaxDistance() const { - return _maxDistance; -} - -bool RayPick::isEnabled() const { - return _enabled; -} - -void RayPick::setPrecisionPicking(bool precisionPicking) { - withWriteLock([&]{ - _filter.setFlag(RayPickFilter::PICK_COARSE, !precisionPicking); - }); -} - -void RayPick::setRayPickResult(const RayPickResult& rayPickResult) { - withWriteLock([&] { - _prevResult = rayPickResult; - }); -} - -QVector RayPick::getIgnoreItems() const { - return _ignoreItems; -} - -QVector RayPick::getIncludeItems() const { - return _includeItems; -} - -RayPickResult RayPick::getPrevRayPickResult() const { - return resultWithReadLock([&] { - return _prevResult; - }); -} - -void RayPick::setIgnoreItems(const QVector& ignoreItems) { - withWriteLock([&] { - _ignoreItems = ignoreItems; - }); -} - -void RayPick::setIncludeItems(const QVector& includeItems) { - withWriteLock([&] { - _includeItems = includeItems; - }); -} diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 7b7d8d8f47..01b59f27e0 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -131,7 +131,22 @@ public: PickRay(const glm::vec3& origin, const glm::vec3 direction) : origin(origin), direction(direction) {} glm::vec3 origin; glm::vec3 direction; + + bool operator==(const PickRay& other) const { + return (origin == other.origin && direction == other.direction); + } }; +namespace std { + template <> + struct hash { + size_t operator()(const glm::vec3& a) const { + return ((hash()(a.x) ^ (hash()(a.y) << 1)) >> 1) ^ (hash()(a.z) << 1); + } + }; +} +uint qHash(const PickRay& a) { + return (uint)(std::hash()(a.origin) ^ (std::hash()(a.direction) << 1)); +} Q_DECLARE_METATYPE(PickRay) QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay); void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay); From 3ef7ebffba07e1c055c57499243505b1a483a3c4 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 17 Oct 2017 15:09:41 -0700 Subject: [PATCH 2/9] working generalized pickmanager --- interface/src/Application.cpp | 4 +- interface/src/raypick/LaserPointer.cpp | 8 +- interface/src/raypick/Pick.h | 16 ++-- interface/src/raypick/PickManager.h | 88 ++++++++++--------- .../src/raypick/RayPickScriptingInterface.cpp | 12 +-- .../src/raypick/RayPickScriptingInterface.h | 18 ++-- libraries/shared/src/RegisteredMetaTypes.h | 2 +- 7 files changed, 74 insertions(+), 74 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e5d5e696a1..b8d3168f10 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1819,11 +1819,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Setup the mouse ray pick and related operators DependencyManager::get()->setMouseRayPickID(_rayPickManager.createRayPick( - RayPickFilter(DependencyManager::get()->PICK_ENTITIES() | DependencyManager::get()->PICK_INCLUDE_NONCOLLIDABLE()), + PickFilter(DependencyManager::get()->PICK_ENTITIES() | DependencyManager::get()->PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true)); DependencyManager::get()->setMouseRayPickResultOperator([&](QUuid rayPickID) { RayToEntityIntersectionResult entityResult; - RayPickResult result = _rayPickManager.getPrevRayPickResult(rayPickID); + RayPickResult result = _rayPickManager.getPrevPickResult(rayPickID); entityResult.intersects = result.type != DependencyManager::get()->INTERSECTED_NONE(); if (entityResult.intersects) { entityResult.intersection = result.intersection; diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index a2f7c7a521..1c5073b9c9 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -39,7 +39,7 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende } LaserPointer::~LaserPointer() { - qApp->getRayPickManager().removeRayPick(_rayPickUID); + qApp->getRayPickManager().removePick(_rayPickUID); for (auto& renderState : _renderStates) { renderState.second.deleteOverlays(); @@ -50,14 +50,14 @@ LaserPointer::~LaserPointer() { } void LaserPointer::enable() { - qApp->getRayPickManager().enableRayPick(_rayPickUID); + qApp->getRayPickManager().enablePick(_rayPickUID); withWriteLock([&] { _renderingEnabled = true; }); } void LaserPointer::disable() { - qApp->getRayPickManager().disableRayPick(_rayPickUID); + qApp->getRayPickManager().disablePick(_rayPickUID); withWriteLock([&] { _renderingEnabled = false; if (!_currentRenderState.empty()) { @@ -198,7 +198,7 @@ void LaserPointer::disableRenderState(const RenderState& renderState) { void LaserPointer::update() { // This only needs to be a read lock because update won't change any of the properties that can be modified from scripts withReadLock([&] { - RayPickResult prevRayPickResult = qApp->getRayPickManager().getPrevRayPickResult(_rayPickUID); + RayPickResult prevRayPickResult = qApp->getRayPickManager().getPrevPickResult(_rayPickUID); if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() && (prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) { float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance; diff --git a/interface/src/raypick/Pick.h b/interface/src/raypick/Pick.h index 561c336f3b..c8d637bcb7 100644 --- a/interface/src/raypick/Pick.h +++ b/interface/src/raypick/Pick.h @@ -8,6 +8,7 @@ #ifndef hifi_Pick_h #define hifi_Pick_h +#include #include #include @@ -101,8 +102,6 @@ template class Pick : protected ReadWriteLockable { public: - using Pointer = std::shared_ptr>; - Pick(const PickFilter& filter, const float maxDistance, const bool enabled); virtual const T getMathematicalPick(bool& valid) const = 0; @@ -169,7 +168,6 @@ private: QVector _includeItems; }; - template Pick::Pick(const PickFilter& filter, const float maxDistance, const bool enabled) : _filter(filter), @@ -198,9 +196,9 @@ float Pick::getMaxDistance() const { template bool Pick::isEnabled() const { - withReadLock([&]) { + return resultWithReadLock([&] { return _enabled; - } + }); } template @@ -219,16 +217,16 @@ void Pick::setPickResult(const RayPickResult& PickResult) { template QVector Pick::getIgnoreItems() const { - withReadLock([&]) { + return resultWithReadLock>([&] { return _ignoreItems; - } + }); } template QVector Pick::getIncludeItems() const { - withReadLock([&]) { + return resultWithReadLock>([&] { return _includeItems; - } + }); } template diff --git a/interface/src/raypick/PickManager.h b/interface/src/raypick/PickManager.h index 228631449f..1c6093d2f0 100644 --- a/interface/src/raypick/PickManager.h +++ b/interface/src/raypick/PickManager.h @@ -13,29 +13,31 @@ #include +#include "scripting/HMDScriptingInterface.h" + #include "Pick.h" -typedef struct RayCacheKey { +typedef struct PickCacheKey { PickFilter::Flags mask; QVector include; QVector ignore; - bool operator==(const RayCacheKey& other) const { + bool operator==(const PickCacheKey& other) const { return (mask == other.mask && include == other.include && ignore == other.ignore); } -} RayCacheKey; +} PickCacheKey; namespace std { template <> - struct hash { - size_t operator()(const RayCacheKey& k) const { + struct hash { + size_t operator()(const PickCacheKey& k) const { return ((hash()(k.mask) ^ (qHash(k.include) << 1)) >> 1) ^ (qHash(k.ignore) << 1); } }; } // T is a mathematical representation of a Pick. -// For example: origin and direction for RayPick +// For example: PickRay for RayPick template class PickManager : protected ReadWriteLockable { @@ -53,28 +55,28 @@ public: void setIncludeItems(const QUuid& uid, const QVector& include) const; protected: - Pick::Pointer findPick(const QUuid& uid) const; - QHash::Pointer> _picks; + std::shared_ptr> findPick(const QUuid& uid) const; + QHash>> _picks; - typedef QHash> RayPickCache; + typedef QHash> PickCache; // Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer - bool checkAndCompareCachedResults(T& pick, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key); - void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, T& pick, RayPickCache& cache); + bool checkAndCompareCachedResults(T& pick, PickCache& cache, RayPickResult& res, const PickCacheKey& key); + void cacheResult(const bool intersects, const RayPickResult& resTemp, const PickCacheKey& key, RayPickResult& res, T& pick, PickCache& cache); }; template -RayPick::Pointer PickManager::findPick(const QUuid& uid) const { - return resultWithReadLock([&] { +std::shared_ptr> PickManager::findPick(const QUuid& uid) const { + return resultWithReadLock>>([&] { if (_picks.contains(uid)) { return _picks[uid]; } - return RayPick::Pointer(); + return std::shared_ptr>(); }); } template -bool PickManager::checkAndCompareCachedResults(T& pick, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key) { +bool PickManager::checkAndCompareCachedResults(T& pick, PickCache& cache, RayPickResult& res, const PickCacheKey& key) { if (cache.contains(pick) && cache[pick].find(key) != cache[pick].end()) { if (cache[pick][key].distance < res.distance) { res = cache[pick][key]; @@ -85,7 +87,7 @@ bool PickManager::checkAndCompareCachedResults(T& pick, RayPickCache& cache, } template -void PickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, T& pick, RayPickCache& cache) { +void PickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const PickCacheKey& key, RayPickResult& res, T& pick, PickCache& cache) { if (intersects) { cache[pick][key] = resTemp; if (resTemp.distance < res.distance) { @@ -98,14 +100,14 @@ void PickManager::cacheResult(const bool intersects, const RayPickResult& res template void PickManager::update() { - RayPickCache results; - QHash::Pointer> cachedPicks; + PickCache results; + QHash>> cachedPicks; withReadLock([&] { cachedPicks = _picks; }); for (const auto& uid : cachedPicks.keys()) { - Pick::Pointer pick = cachedPicks[uid]; + std::shared_ptr> pick = cachedPicks[uid]; if (!pick->isEnabled() || pick->getFilter().doesPickNothing() || pick->getMaxDistance() < 0.0f) { continue; } @@ -114,7 +116,7 @@ void PickManager::update() { { bool valid; - mathematicalPick = pick->getPickRay(valid); + mathematicalPick = pick->getMathematicalPick(valid); if (!valid) { continue; } @@ -127,7 +129,7 @@ void PickManager::update() { bool fromCache = true; bool invisible = pick->getFilter().doesPickInvisible(); bool nonCollidable = pick->getFilter().doesPickNonCollidable(); - RayCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; + PickCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) { entityRes = pick->getEntityIntersection(mathematicalPick, !pick->getFilter().doesPickCoarse(), pick->getIncludeItemsAs(), pick->getIgnoreItemsAs(), !invisible, !nonCollidable); @@ -145,7 +147,7 @@ void PickManager::update() { bool fromCache = true; bool invisible = pick->getFilter().doesPickInvisible(); bool nonCollidable = pick->getFilter().doesPickNonCollidable(); - RayCacheKey overlayKey = { pick->getFilter().getOverlayFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; + PickCacheKey overlayKey = { pick->getFilter().getOverlayFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, overlayKey)) { overlayRes = pick->getOverlayIntersection(mathematicalPick, !pick->getFilter().doesPickCoarse(), pick->getIncludeItemsAs(), pick->getIgnoreItemsAs(), !invisible, !nonCollidable); @@ -159,7 +161,7 @@ void PickManager::update() { } if (pick->getFilter().doesPickAvatars()) { - RayCacheKey avatarKey = { pick->getFilter().getAvatarFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; + PickCacheKey avatarKey = { pick->getFilter().getAvatarFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, avatarKey)) { RayToAvatarIntersectionResult avatarRes = pick->getAvatarIntersection(mathematicalPick, pick->getIncludeItemsAs(), pick->getIgnoreItemsAs()); @@ -169,9 +171,9 @@ void PickManager::update() { // Can't intersect with HUD in desktop mode if (pick->getFilter().doesPickHUD() && DependencyManager::get()->isHMDMode()) { - RayCacheKey hudKey = { pick->getFilter().getHUDFlags(), QVector(), QVector() }; + PickCacheKey hudKey = { pick->getFilter().getHUDFlags(), QVector(), QVector() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, hudKey)) { - glm::vec3 hudRes = pick->getHUDIntersection(mathematicalPick.origin, mathematicalPick.direction); + glm::vec3 hudRes = pick->getHUDIntersection(mathematicalPick); cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(mathematicalPick.origin, hudRes), hudRes, mathematicalPick), hudKey, res, mathematicalPick, results); } } @@ -186,9 +188,9 @@ void PickManager::update() { template RayPickResult PickManager::getPrevPickResult(const QUuid& uid) const { - auto rayPick = findPick(uid); - if (rayPick) { - return rayPick->getPrevPickResult(); + auto pick = findPick(uid); + if (pick) { + return pick->getPrevPickResult(); } return RayPickResult(); } @@ -202,41 +204,41 @@ void PickManager::removePick(const QUuid& uid) { template void PickManager::enablePick(const QUuid& uid) const { - auto rayPick = findPick(uid); - if (rayPick) { - rayPick->enable(); + auto pick = findPick(uid); + if (pick) { + pick->enable(); } } template void PickManager::disablePick(const QUuid& uid) const { - auto rayPick = findPick(uid); - if (rayPick) { - rayPick->disable(); + auto pick = findPick(uid); + if (pick) { + pick->disable(); } } template void PickManager::setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { - auto rayPick = findPick(uid); - if (rayPick) { - rayPick->setPrecisionPicking(precisionPicking); + auto pick = findPick(uid); + if (pick) { + pick->setPrecisionPicking(precisionPicking); } } template void PickManager::setIgnoreItems(const QUuid& uid, const QVector& ignore) const { - auto rayPick = findPick(uid); - if (rayPick) { - rayPick->setIgnoreItems(ignore); + auto pick = findPick(uid); + if (pick) { + pick->setIgnoreItems(ignore); } } template void PickManager::setIncludeItems(const QUuid& uid, const QVector& include) const { - auto rayPick = findPick(uid); - if (rayPick) { - rayPick->setIncludeItems(include); + auto pick = findPick(uid); + if (pick) { + pick->setIncludeItems(include); } } diff --git a/interface/src/raypick/RayPickScriptingInterface.cpp b/interface/src/raypick/RayPickScriptingInterface.cpp index 621ae9b738..380971b5e6 100644 --- a/interface/src/raypick/RayPickScriptingInterface.cpp +++ b/interface/src/raypick/RayPickScriptingInterface.cpp @@ -23,9 +23,9 @@ QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) { enabled = propMap["enabled"].toBool(); } - RayPickFilter filter = RayPickFilter(); + PickFilter filter = PickFilter(); if (propMap["filter"].isValid()) { - filter = RayPickFilter(propMap["filter"].toUInt()); + filter = PickFilter(propMap["filter"].toUInt()); } float maxDistance = 0.0f; @@ -67,19 +67,19 @@ QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) { } void RayPickScriptingInterface::enableRayPick(const QUuid& uid) { - qApp->getRayPickManager().enableRayPick(uid); + qApp->getRayPickManager().enablePick(uid); } void RayPickScriptingInterface::disableRayPick(const QUuid& uid) { - qApp->getRayPickManager().disableRayPick(uid); + qApp->getRayPickManager().disablePick(uid); } void RayPickScriptingInterface::removeRayPick(const QUuid& uid) { - qApp->getRayPickManager().removeRayPick(uid); + qApp->getRayPickManager().removePick(uid); } RayPickResult RayPickScriptingInterface::getPrevRayPickResult(const QUuid& uid) { - return qApp->getRayPickManager().getPrevRayPickResult(uid); + return qApp->getRayPickManager().getPrevPickResult(uid); } void RayPickScriptingInterface::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) { diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h index 099103e4c5..2153c4f3a5 100644 --- a/interface/src/raypick/RayPickScriptingInterface.h +++ b/interface/src/raypick/RayPickScriptingInterface.h @@ -15,7 +15,7 @@ #include #include -#include +#include "RayPick.h" class RayPickScriptingInterface : public QObject, public Dependency { Q_OBJECT @@ -47,14 +47,14 @@ public slots: Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities); unsigned int PICK_NOTHING() { return 0; } - unsigned int PICK_ENTITIES() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ENTITIES); } - unsigned int PICK_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); } - unsigned int PICK_AVATARS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_AVATARS); } - unsigned int PICK_HUD() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_HUD); } - unsigned int PICK_COARSE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_COARSE); } - unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); } - unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); } - unsigned int PICK_ALL_INTERSECTIONS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ALL_INTERSECTIONS); } + unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ENTITIES); } + unsigned int PICK_OVERLAYS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_OVERLAYS); } + unsigned int PICK_AVATARS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_AVATARS); } + unsigned int PICK_HUD() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_HUD); } + unsigned int PICK_COARSE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_COARSE); } + unsigned int PICK_INCLUDE_INVISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); } + unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); } + unsigned int PICK_ALL_INTERSECTIONS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ALL_INTERSECTIONS); } unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 01b59f27e0..c7b482a917 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -144,7 +144,7 @@ namespace std { } }; } -uint qHash(const PickRay& a) { +inline uint qHash(const PickRay& a) { return (uint)(std::hash()(a.origin) ^ (std::hash()(a.direction) << 1)); } Q_DECLARE_METATYPE(PickRay) From 8a5759df69f989e8e62ba0a1e05856dab5d74b42 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 17 Oct 2017 15:22:39 -0700 Subject: [PATCH 3/9] PickManager::addPick --- interface/src/raypick/PickManager.h | 11 +++++++++++ interface/src/raypick/RayPickManager.cpp | 21 +++------------------ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/interface/src/raypick/PickManager.h b/interface/src/raypick/PickManager.h index 1c6093d2f0..01cffaeb8e 100644 --- a/interface/src/raypick/PickManager.h +++ b/interface/src/raypick/PickManager.h @@ -38,6 +38,7 @@ namespace std { // T is a mathematical representation of a Pick. // For example: PickRay for RayPick +// TODO: add another template type to replace RayPickResult with a generalized PickResult template class PickManager : protected ReadWriteLockable { @@ -46,6 +47,7 @@ public: RayPickResult getPrevPickResult(const QUuid& uid) const; + QUuid addPick(const std::shared_ptr> pick); void removePick(const QUuid& uid); void enablePick(const QUuid& uid) const; void disablePick(const QUuid& uid) const; @@ -195,6 +197,15 @@ RayPickResult PickManager::getPrevPickResult(const QUuid& uid) const { return RayPickResult(); } +template +QUuid PickManager::addPick(const std::shared_ptr> pick) { + QUuid id = QUuid::createUuid(); + withWriteLock([&] { + _picks[id] = pick; + }); + return id; +} + template void PickManager::removePick(const QUuid& uid) { withWriteLock([&] { diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index f4a45312bf..e6b183133d 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -15,28 +15,13 @@ #include "MouseRayPick.h" QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, float maxDistance, bool enabled) { - auto newRayPick = std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled); - QUuid id = QUuid::createUuid(); - withWriteLock([&] { - _picks[id] = newRayPick; - }); - return id; + return addPick(std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); } QUuid RayPickManager::createRayPick(const PickFilter& filter, float maxDistance, bool enabled) { - QUuid id = QUuid::createUuid(); - auto newRayPick = std::make_shared(filter, maxDistance, enabled); - withWriteLock([&] { - _picks[id] = newRayPick; - }); - return id; + return addPick(std::make_shared(filter, maxDistance, enabled)); } QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, float maxDistance, bool enabled) { - QUuid id = QUuid::createUuid(); - auto newRayPick = std::make_shared(position, direction, filter, maxDistance, enabled); - withWriteLock([&] { - _picks[id] = newRayPick; - }); - return id; + return addPick(std::make_shared(position, direction, filter, maxDistance, enabled)); } \ No newline at end of file From 05f4883104d54d5e65eaaa9ac1cb5e4b051f2e2c Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 17 Oct 2017 16:15:54 -0700 Subject: [PATCH 4/9] get rid of valid --- interface/src/raypick/JointRayPick.cpp | 4 +--- interface/src/raypick/JointRayPick.h | 2 +- interface/src/raypick/MouseRayPick.cpp | 4 +--- interface/src/raypick/MouseRayPick.h | 2 +- interface/src/raypick/Pick.h | 2 +- interface/src/raypick/PickManager.h | 14 +++++--------- interface/src/raypick/StaticRayPick.cpp | 3 +-- interface/src/raypick/StaticRayPick.h | 2 +- libraries/shared/src/RegisteredMetaTypes.h | 15 +++++++++++---- 9 files changed, 23 insertions(+), 25 deletions(-) diff --git a/interface/src/raypick/JointRayPick.cpp b/interface/src/raypick/JointRayPick.cpp index d3991eac24..c2a7fb11e5 100644 --- a/interface/src/raypick/JointRayPick.cpp +++ b/interface/src/raypick/JointRayPick.cpp @@ -20,7 +20,7 @@ JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOff { } -const PickRay JointRayPick::getMathematicalPick(bool& valid) const { +const PickRay JointRayPick::getMathematicalPick() const { auto myAvatar = DependencyManager::get()->getMyAvatar(); int jointIndex = myAvatar->getJointIndex(QString::fromStdString(_jointName)); bool useAvatarHead = _jointName == "Avatar"; @@ -38,10 +38,8 @@ const PickRay JointRayPick::getMathematicalPick(bool& valid) const { pos = pos + (rot * (myAvatar->getSensorToWorldScale() * _posOffset)); glm::vec3 dir = rot * glm::normalize(_dirOffset); - valid = true; return PickRay(pos, dir); } - valid = false; return PickRay(); } diff --git a/interface/src/raypick/JointRayPick.h b/interface/src/raypick/JointRayPick.h index b2bffe83c4..ab44bf67c8 100644 --- a/interface/src/raypick/JointRayPick.h +++ b/interface/src/raypick/JointRayPick.h @@ -18,7 +18,7 @@ class JointRayPick : public RayPick { public: JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); - const PickRay getMathematicalPick(bool& valid) const override; + const PickRay getMathematicalPick() const override; private: std::string _jointName; diff --git a/interface/src/raypick/MouseRayPick.cpp b/interface/src/raypick/MouseRayPick.cpp index 27080f5857..f691dafc01 100644 --- a/interface/src/raypick/MouseRayPick.cpp +++ b/interface/src/raypick/MouseRayPick.cpp @@ -18,14 +18,12 @@ MouseRayPick::MouseRayPick(const PickFilter& filter, const float maxDistance, co { } -const PickRay MouseRayPick::getMathematicalPick(bool& valid) const { +const PickRay MouseRayPick::getMathematicalPick() const { QVariant position = qApp->getApplicationCompositor().getReticleInterface()->getPosition(); if (position.isValid()) { QVariantMap posMap = position.toMap(); - valid = true; return qApp->getCamera().computePickRay(posMap["x"].toFloat(), posMap["y"].toFloat()); } - valid = false; return PickRay(); } diff --git a/interface/src/raypick/MouseRayPick.h b/interface/src/raypick/MouseRayPick.h index c565a03db7..e9eb3ccabf 100644 --- a/interface/src/raypick/MouseRayPick.h +++ b/interface/src/raypick/MouseRayPick.h @@ -18,7 +18,7 @@ class MouseRayPick : public RayPick { public: MouseRayPick(const PickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); - const PickRay getMathematicalPick(bool& valid) const override; + const PickRay getMathematicalPick() const override; }; #endif // hifi_MouseRayPick_h diff --git a/interface/src/raypick/Pick.h b/interface/src/raypick/Pick.h index c8d637bcb7..161e9779ce 100644 --- a/interface/src/raypick/Pick.h +++ b/interface/src/raypick/Pick.h @@ -104,7 +104,7 @@ class Pick : protected ReadWriteLockable { public: Pick(const PickFilter& filter, const float maxDistance, const bool enabled); - virtual const T getMathematicalPick(bool& valid) const = 0; + virtual const T getMathematicalPick() const = 0; virtual RayToEntityIntersectionResult getEntityIntersection(const T& pick, bool precisionPicking, const QVector& entitiesToInclude, const QVector& entitiesToIgnore, diff --git a/interface/src/raypick/PickManager.h b/interface/src/raypick/PickManager.h index 01cffaeb8e..424be0aa4f 100644 --- a/interface/src/raypick/PickManager.h +++ b/interface/src/raypick/PickManager.h @@ -60,7 +60,7 @@ protected: std::shared_ptr> findPick(const QUuid& uid) const; QHash>> _picks; - typedef QHash> PickCache; + typedef std::unordered_map> PickCache; // Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer bool checkAndCompareCachedResults(T& pick, PickCache& cache, RayPickResult& res, const PickCacheKey& key); @@ -79,7 +79,7 @@ std::shared_ptr> PickManager::findPick(const QUuid& uid) const { template bool PickManager::checkAndCompareCachedResults(T& pick, PickCache& cache, RayPickResult& res, const PickCacheKey& key) { - if (cache.contains(pick) && cache[pick].find(key) != cache[pick].end()) { + if (cache.find(pick) != cache.end() && cache[pick].find(key) != cache[pick].end()) { if (cache[pick][key].distance < res.distance) { res = cache[pick][key]; } @@ -114,14 +114,10 @@ void PickManager::update() { continue; } - T mathematicalPick; + T mathematicalPick = pick->getMathematicalPick(); - { - bool valid; - mathematicalPick = pick->getMathematicalPick(valid); - if (!valid) { - continue; - } + if (!mathematicalPick) { + continue; } RayPickResult res = RayPickResult(mathematicalPick); diff --git a/interface/src/raypick/StaticRayPick.cpp b/interface/src/raypick/StaticRayPick.cpp index 5db054c2e4..f7803aade6 100644 --- a/interface/src/raypick/StaticRayPick.cpp +++ b/interface/src/raypick/StaticRayPick.cpp @@ -13,7 +13,6 @@ StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& directi { } -const PickRay StaticRayPick::getMathematicalPick(bool& valid) const { - valid = true; +const PickRay StaticRayPick::getMathematicalPick() const { return _pickRay; } \ No newline at end of file diff --git a/interface/src/raypick/StaticRayPick.h b/interface/src/raypick/StaticRayPick.h index c26ea386d6..6dc0a809ae 100644 --- a/interface/src/raypick/StaticRayPick.h +++ b/interface/src/raypick/StaticRayPick.h @@ -15,7 +15,7 @@ class StaticRayPick : public RayPick { public: StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false); - const PickRay getMathematicalPick(bool& valid) const override; + const PickRay getMathematicalPick() const override; private: PickRay _pickRay; diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index c7b482a917..45813bb294 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -127,11 +127,15 @@ void aaCubeFromScriptValue(const QScriptValue &object, AACube& aaCube); class PickRay { public: - PickRay() : origin(0.0f), direction(0.0f) { } + PickRay() : origin(NAN), direction(NAN) { } PickRay(const glm::vec3& origin, const glm::vec3 direction) : origin(origin), direction(direction) {} glm::vec3 origin; glm::vec3 direction; + operator bool() const { + auto isNan = glm::isnan(origin) || glm::isnan(direction); + return !isNan.x && !isNan.y && !isNan.z; + } bool operator==(const PickRay& other) const { return (origin == other.origin && direction == other.direction); } @@ -143,9 +147,12 @@ namespace std { return ((hash()(a.x) ^ (hash()(a.y) << 1)) >> 1) ^ (hash()(a.z) << 1); } }; -} -inline uint qHash(const PickRay& a) { - return (uint)(std::hash()(a.origin) ^ (std::hash()(a.direction) << 1)); + template <> + struct hash { + size_t operator()(const PickRay& a) const { + return (hash()(a.origin) ^ (hash()(a.direction) << 1)); + } + }; } Q_DECLARE_METATYPE(PickRay) QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay); From 640ad514bcfbe2745e5e9fa7f2d784c3aef6ded1 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 17 Oct 2017 16:26:55 -0700 Subject: [PATCH 5/9] updates based on austin's comments --- interface/src/Application.cpp | 4 +-- interface/src/raypick/Pick.h | 12 ++++---- interface/src/raypick/PickManager.h | 6 ++-- .../src/raypick/RayPickScriptingInterface.h | 28 +++++++++---------- libraries/shared/src/RegisteredMetaTypes.h | 3 +- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b8d3168f10..98fc3525bc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1819,12 +1819,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Setup the mouse ray pick and related operators DependencyManager::get()->setMouseRayPickID(_rayPickManager.createRayPick( - PickFilter(DependencyManager::get()->PICK_ENTITIES() | DependencyManager::get()->PICK_INCLUDE_NONCOLLIDABLE()), + PickFilter(RayPickScriptingInterface::PICK_ENTITIES() | RayPickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true)); DependencyManager::get()->setMouseRayPickResultOperator([&](QUuid rayPickID) { RayToEntityIntersectionResult entityResult; RayPickResult result = _rayPickManager.getPrevPickResult(rayPickID); - entityResult.intersects = result.type != DependencyManager::get()->INTERSECTED_NONE(); + entityResult.intersects = result.type != RayPickScriptingInterface::INTERSECTED_NONE(); if (entityResult.intersects) { entityResult.intersection = result.intersection; entityResult.distance = result.distance; diff --git a/interface/src/raypick/Pick.h b/interface/src/raypick/Pick.h index 161e9779ce..b4d9fa91b9 100644 --- a/interface/src/raypick/Pick.h +++ b/interface/src/raypick/Pick.h @@ -133,9 +133,9 @@ public: QVector getIgnoreItems() const; QVector getIncludeItems() const; - template - QVector getIgnoreItemsAs() const { - QVector result; + template + QVector getIgnoreItemsAs() const { + QVector result; withReadLock([&] { for (const auto& uid : _ignoreItems) { result.push_back(uid); @@ -144,9 +144,9 @@ public: return result; } - template - QVector getIncludeItemsAs() const { - QVector result; + template + QVector getIncludeItemsAs() const { + QVector result; withReadLock([&] { for (const auto& uid : _includeItems) { result.push_back(uid); diff --git a/interface/src/raypick/PickManager.h b/interface/src/raypick/PickManager.h index 424be0aa4f..3b991d130a 100644 --- a/interface/src/raypick/PickManager.h +++ b/interface/src/raypick/PickManager.h @@ -130,7 +130,7 @@ void PickManager::update() { PickCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) { entityRes = pick->getEntityIntersection(mathematicalPick, !pick->getFilter().doesPickCoarse(), - pick->getIncludeItemsAs(), pick->getIgnoreItemsAs(), !invisible, !nonCollidable); + pick->(template getIncludeItemsAs()), (template pick->getIgnoreItemsAs()), !invisible, !nonCollidable); fromCache = false; } @@ -148,7 +148,7 @@ void PickManager::update() { PickCacheKey overlayKey = { pick->getFilter().getOverlayFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, overlayKey)) { overlayRes = pick->getOverlayIntersection(mathematicalPick, !pick->getFilter().doesPickCoarse(), - pick->getIncludeItemsAs(), pick->getIgnoreItemsAs(), !invisible, !nonCollidable); + pick->(template getIncludeItemsAs()), pick->(template getIgnoreItemsAs()), !invisible, !nonCollidable); fromCache = false; } @@ -162,7 +162,7 @@ void PickManager::update() { PickCacheKey avatarKey = { pick->getFilter().getAvatarFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, avatarKey)) { RayToAvatarIntersectionResult avatarRes = pick->getAvatarIntersection(mathematicalPick, - pick->getIncludeItemsAs(), pick->getIgnoreItemsAs()); + pick->(template getIncludeItemsAs()), pick->(template getIgnoreItemsAs())); cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, mathematicalPick), avatarKey, res, mathematicalPick, results); } } diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h index 2153c4f3a5..b91483addf 100644 --- a/interface/src/raypick/RayPickScriptingInterface.h +++ b/interface/src/raypick/RayPickScriptingInterface.h @@ -46,20 +46,20 @@ public slots: Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities); Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities); - unsigned int PICK_NOTHING() { return 0; } - unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ENTITIES); } - unsigned int PICK_OVERLAYS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_OVERLAYS); } - unsigned int PICK_AVATARS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_AVATARS); } - unsigned int PICK_HUD() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_HUD); } - unsigned int PICK_COARSE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_COARSE); } - unsigned int PICK_INCLUDE_INVISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); } - unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); } - unsigned int PICK_ALL_INTERSECTIONS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ALL_INTERSECTIONS); } - unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } - unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } - unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } - unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } - unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } + static unsigned int PICK_NOTHING() { return 0; } + static unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ENTITIES); } + static unsigned int PICK_OVERLAYS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_OVERLAYS); } + static unsigned int PICK_AVATARS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_AVATARS); } + static unsigned int PICK_HUD() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_HUD); } + static unsigned int PICK_COARSE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_COARSE); } + static unsigned int PICK_INCLUDE_INVISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); } + static unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); } + static unsigned int PICK_ALL_INTERSECTIONS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ALL_INTERSECTIONS); } + static unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } + static unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } + static unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } + static unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } + static unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } }; #endif // hifi_RayPickScriptingInterface_h diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 45813bb294..8aeabce917 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -133,8 +133,7 @@ public: glm::vec3 direction; operator bool() const { - auto isNan = glm::isnan(origin) || glm::isnan(direction); - return !isNan.x && !isNan.y && !isNan.z; + return !(glm::any(glm::isnan(origin)) || glm::any(glm::isnan(direction))); } bool operator==(const PickRay& other) const { return (origin == other.origin && direction == other.direction); From 3572f7f5db9e989c0100817fabd77d0292eceb61 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 18 Oct 2017 18:43:56 -0700 Subject: [PATCH 6/9] non-templated pickresult wip --- interface/src/Application.cpp | 19 ++-- interface/src/raypick/LaserPointer.cpp | 16 ++-- interface/src/raypick/LaserPointer.h | 4 +- interface/src/raypick/LaserPointerManager.cpp | 4 +- interface/src/raypick/LaserPointerManager.h | 5 +- .../raypick/LaserPointerScriptingInterface.h | 2 +- interface/src/raypick/RayPick.cpp | 48 ++++++---- interface/src/raypick/RayPick.h | 70 ++++++++++++--- interface/src/raypick/RayPickManager.cpp | 3 - interface/src/raypick/RayPickManager.h | 8 +- .../src/raypick/RayPickScriptingInterface.cpp | 2 +- .../src/raypick/RayPickScriptingInterface.h | 30 +++---- .../pointers/src/pointers}/Pick.cpp | 0 .../pointers/src/pointers}/Pick.h | 68 +++++++++----- .../pointers/src/pointers}/PickManager.h | 90 +++++++------------ libraries/shared/src/RegisteredMetaTypes.cpp | 22 ----- libraries/shared/src/RegisteredMetaTypes.h | 32 ++----- 17 files changed, 217 insertions(+), 206 deletions(-) rename {interface/src/raypick => libraries/pointers/src/pointers}/Pick.cpp (100%) rename {interface/src/raypick => libraries/pointers/src/pointers}/Pick.h (78%) rename {interface/src/raypick => libraries/pointers/src/pointers}/PickManager.h (59%) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 98fc3525bc..49b150db79 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1823,14 +1823,17 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo 0.0f, true)); DependencyManager::get()->setMouseRayPickResultOperator([&](QUuid rayPickID) { RayToEntityIntersectionResult entityResult; - RayPickResult result = _rayPickManager.getPrevPickResult(rayPickID); - entityResult.intersects = result.type != RayPickScriptingInterface::INTERSECTED_NONE(); - if (entityResult.intersects) { - entityResult.intersection = result.intersection; - entityResult.distance = result.distance; - entityResult.surfaceNormal = result.surfaceNormal; - entityResult.entityID = result.objectID; - entityResult.entity = DependencyManager::get()->getTree()->findEntityByID(entityResult.entityID); + entityResult.intersects = false; + QVariantMap result = _rayPickManager.getPrevPickResult(rayPickID); + if (result["type"].isValid()) { + entityResult.intersects = result["type"] != RayPickScriptingInterface::INTERSECTED_NONE(); + if (entityResult.intersects) { + entityResult.intersection = vec3FromVariant(result["intersection"]); + entityResult.distance = result["distance"].toFloat(); + entityResult.surfaceNormal = vec3FromVariant(result["surfaceNormal"]); + entityResult.entityID = result["objectID"].toUuid(); + entityResult.entity = DependencyManager::get()->getTree()->findEntityByID(entityResult.entityID); + } } return entityResult; }); diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 32c781b58d..2f3fc13706 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -12,7 +12,6 @@ #include "Application.h" #include "avatar/AvatarManager.h" -#include "RayPickScriptingInterface.h" LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) : @@ -101,7 +100,7 @@ void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& } } -const RayPickResult LaserPointer::getPrevRayPickResult() { +const QVariantMap LaserPointer::getPrevRayPickResult() { return qApp->getRayPickManager().getPrevPickResult(_rayPickUID); } @@ -198,15 +197,18 @@ void LaserPointer::disableRenderState(const RenderState& renderState) { void LaserPointer::update() { // This only needs to be a read lock because update won't change any of the properties that can be modified from scripts withReadLock([&] { - RayPickResult prevRayPickResult = qApp->getRayPickManager().getPrevPickResult(_rayPickUID); + QVariantMap prevRayPickResult = qApp->getRayPickManager().getPrevPickResult(_rayPickUID); + IntersectionType type = IntersectionType(prevRayPickResult["type"].toInt()); + PickRay pickRay = PickRay(prevRayPickResult["searchRay"].toMap()); + QUuid uid = prevRayPickResult["objectID"].toUuid(); if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() && - (prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) { - float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance; - updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false); + (type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) { + float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult["distance"].toFloat(); + updateRenderState(_renderStates[_currentRenderState], type, distance, uid, pickRay, false); disableRenderState(_defaultRenderStates[_currentRenderState].second); } else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) { disableRenderState(_renderStates[_currentRenderState]); - updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), prevRayPickResult.searchRay, true); + updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), pickRay, true); } else if (!_currentRenderState.empty()) { disableRenderState(_renderStates[_currentRenderState]); disableRenderState(_defaultRenderStates[_currentRenderState].second); diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 20ea824f50..d6fcf20b9d 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -19,7 +19,7 @@ #include "ui/overlays/Overlay.h" -class RayPickResult; +#include "RayPickScriptingInterface.h" class RenderState { @@ -61,7 +61,7 @@ public: QUuid getRayUID() { return _rayPickUID; } void enable(); void disable(); - const RayPickResult getPrevRayPickResult(); + const QVariantMap getPrevRayPickResult(); void setRenderState(const std::string& state); // You cannot use editRenderState to change the overlay type of any part of the laser pointer. You can only edit the properties of the existing overlays. diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index f65a8a1a84..a300a418a7 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -67,12 +67,12 @@ void LaserPointerManager::editRenderState(const QUuid& uid, const std::string& s } } -const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid& uid) const { +const QVariantMap LaserPointerManager::getPrevRayPickResult(const QUuid& uid) const { auto laserPointer = find(uid); if (laserPointer) { return laserPointer->getPrevRayPickResult(); } - return RayPickResult(); + return QVariantMap(); } void LaserPointerManager::update() { diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index a4689cf16d..547f7cc785 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -18,9 +18,6 @@ #include "LaserPointer.h" -class RayPickResult; - - class LaserPointerManager : protected ReadWriteLockable { public: @@ -31,7 +28,7 @@ public: void disableLaserPointer(const QUuid& uid) const; void setRenderState(const QUuid& uid, const std::string& renderState) const; void editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const; - const RayPickResult getPrevRayPickResult(const QUuid& uid) const; + const QVariantMap getPrevRayPickResult(const QUuid& uid) const; void setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const; void setLaserLength(const QUuid& uid, const float laserLength) const; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 19262e6e5d..1e34016ab5 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -28,7 +28,7 @@ public slots: Q_INVOKABLE void removeLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().removeLaserPointer(uid); } Q_INVOKABLE void editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const; Q_INVOKABLE void setRenderState(const QUuid& uid, const QString& renderState) const { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); } - Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) const { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); } + Q_INVOKABLE QVariantMap getPrevRayPickResult(QUuid uid) const { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); } Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { qApp->getLaserPointerManager().setPrecisionPicking(uid, precisionPicking); } Q_INVOKABLE void setLaserLength(const QUuid& uid, float laserLength) const { qApp->getLaserPointerManager().setLaserLength(uid, laserLength); } diff --git a/interface/src/raypick/RayPick.cpp b/interface/src/raypick/RayPick.cpp index f12320ee35..4e1e0386f1 100644 --- a/interface/src/raypick/RayPick.cpp +++ b/interface/src/raypick/RayPick.cpp @@ -8,32 +8,44 @@ #include "RayPick.h" #include "Application.h" +#include "EntityScriptingInterface.h" +#include "ui/overlays/Overlays.h" #include "avatar/AvatarManager.h" #include "scripting/HMDScriptingInterface.h" #include "DependencyManager.h" -RayToEntityIntersectionResult RayPick::getEntityIntersection(const PickRay& pick, bool precisionPicking, - const QVector& entitiesToInclude, - const QVector& entitiesToIgnore, - bool visibleOnly, bool collidableOnly) { - return DependencyManager::get()->findRayIntersectionVector(pick, precisionPicking, - entitiesToInclude, entitiesToIgnore, visibleOnly, collidableOnly); +PickResultPointer RayPick::getEntityIntersection(const PickRay& pick) { + RayToEntityIntersectionResult entityRes = + DependencyManager::get()->findRayIntersectionVector(pick, !getFilter().doesPickCoarse(), + getIncludeItemsAs(), getIgnoreItemsAs(), !getFilter().doesPickInvisible(), !getFilter().doesPickNonCollidable()); + if (entityRes.intersects) { + return std::make_shared(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, pick, entityRes.surfaceNormal); + } else { + return std::make_shared(pick.toVariantMap()); + } } -RayToOverlayIntersectionResult RayPick::getOverlayIntersection(const PickRay& pick, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToIgnore, - bool visibleOnly, bool collidableOnly) { - return qApp->getOverlays().findRayIntersectionVector(pick, precisionPicking, - overlaysToInclude, overlaysToIgnore, visibleOnly, collidableOnly); +PickResultPointer RayPick::getOverlayIntersection(const PickRay& pick) { + RayToOverlayIntersectionResult overlayRes = + qApp->getOverlays().findRayIntersectionVector(pick, !getFilter().doesPickCoarse(), + getIncludeItemsAs(), getIgnoreItemsAs(), !getFilter().doesPickInvisible(), !getFilter().doesPickNonCollidable()); + if (overlayRes.intersects) { + return std::make_shared(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, pick, overlayRes.surfaceNormal); + } else { + return std::make_shared(pick.toVariantMap()); + } } -RayToAvatarIntersectionResult RayPick::getAvatarIntersection(const PickRay& pick, - const QVector& avatarsToInclude, - const QVector& avatarsToIgnore) { - return DependencyManager::get()->findRayIntersectionVector(pick, avatarsToInclude, avatarsToIgnore); +PickResultPointer RayPick::getAvatarIntersection(const PickRay& pick) { + RayToAvatarIntersectionResult avatarRes = DependencyManager::get()->findRayIntersectionVector(pick, getIncludeItemsAs(), getIgnoreItemsAs()); + if (avatarRes.intersects) { + return std::make_shared(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, pick); + } else { + return std::make_shared(pick.toVariantMap()); + } } -glm::vec3 RayPick::getHUDIntersection(const PickRay& pick) { - return DependencyManager::get()->calculateRayUICollisionPoint(pick.origin, pick.direction); +PickResultPointer RayPick::getHUDIntersection(const PickRay& pick) { + glm::vec3 hudRes = DependencyManager::get()->calculateRayUICollisionPoint(pick.origin, pick.direction); + return std::make_shared(IntersectionType::HUD, QUuid(), glm::distance(pick.origin, hudRes), hudRes, pick); } \ No newline at end of file diff --git a/interface/src/raypick/RayPick.h b/interface/src/raypick/RayPick.h index 92778e74a2..b5d7ea7c3e 100644 --- a/interface/src/raypick/RayPick.h +++ b/interface/src/raypick/RayPick.h @@ -8,28 +8,72 @@ #ifndef hifi_RayPick_h #define hifi_RayPick_h -#include "Pick.h" +#include +#include class EntityItemID; class OverlayID; +class RayPickResult : public PickResult { +public: + RayPickResult() {} + RayPickResult(const QVariantMap& pickVariant) : PickResult(pickVariant) {} + RayPickResult(const IntersectionType type, const QUuid& objectID, const float distance, const glm::vec3& intersection, const PickRay& searchRay, const glm::vec3& surfaceNormal = glm::vec3(NAN)) : + PickResult(searchRay.toVariantMap()), type(type), intersects(type != NONE), objectID(objectID), distance(distance), intersection(intersection), surfaceNormal(surfaceNormal) { + } + + RayPickResult(const RayPickResult& rayPickResult) : PickResult(rayPickResult.pickVariant) { + type = rayPickResult.type; + intersects = rayPickResult.intersects; + objectID = rayPickResult.objectID; + distance = rayPickResult.distance; + intersection = rayPickResult.intersection; + surfaceNormal = rayPickResult.surfaceNormal; + } + + IntersectionType type { NONE }; + bool intersects { false }; + QUuid objectID; + float distance { FLT_MAX }; + glm::vec3 intersection { NAN }; + glm::vec3 surfaceNormal { NAN }; + + virtual QVariantMap toVariantMap() const override { + QVariantMap toReturn; + toReturn["type"] = type; + toReturn["intersects"] = intersects; + toReturn["objectID"] = objectID; + toReturn["distance"] = distance; + toReturn["intersection"] = vec3toVariant(intersection); + toReturn["surfaceNormal"] = vec3toVariant(surfaceNormal); + toReturn["searchRay"] = PickResult::toVariantMap(); + return toReturn; + } + + bool doesIntersect() const override { return intersects; } + bool checkOrFilterAgainstMaxDistance(float maxDistance) override { return distance < maxDistance; } + + PickResultPointer compareAndProcessNewResult(const PickResultPointer newRes) override { + auto newRayRes = std::static_pointer_cast(newRes); + if (newRayRes->distance < distance) { + return std::make_shared(*newRayRes); + } else { + return std::make_shared(*this); + } + } + +}; + class RayPick : public Pick { public: RayPick(const PickFilter& filter, const float maxDistance, const bool enabled) : Pick(filter, maxDistance, enabled) {} - RayToEntityIntersectionResult getEntityIntersection(const PickRay& pick, bool precisionPicking, - const QVector& entitiesToInclude, - const QVector& entitiesToIgnore, - bool visibleOnly, bool collidableOnly) override; - RayToOverlayIntersectionResult getOverlayIntersection(const PickRay& pick, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToIgnore, - bool visibleOnly, bool collidableOnly) override; - RayToAvatarIntersectionResult getAvatarIntersection(const PickRay& pick, - const QVector& avatarsToInclude, - const QVector& avatarsToIgnore) override; - glm::vec3 getHUDIntersection(const PickRay& pick) override; + PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared(pickVariant); } + PickResultPointer getEntityIntersection(const PickRay& pick) override; + PickResultPointer getOverlayIntersection(const PickRay& pick) override; + PickResultPointer getAvatarIntersection(const PickRay& pick) override; + PickResultPointer getHUDIntersection(const PickRay& pick) override; }; #endif // hifi_RayPick_h diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp index e6b183133d..2e62c608d8 100644 --- a/interface/src/raypick/RayPickManager.cpp +++ b/interface/src/raypick/RayPickManager.cpp @@ -1,7 +1,4 @@ // -// RayPickManager.cpp -// interface/src/raypick -// // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. // diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h index 7673e402f4..7bc97c8526 100644 --- a/interface/src/raypick/RayPickManager.h +++ b/interface/src/raypick/RayPickManager.h @@ -1,7 +1,4 @@ // -// RayPickManager.h -// interface/src/raypick -// // Created by Sam Gondelman 7/11/2017 // Copyright 2017 High Fidelity, Inc. // @@ -11,9 +8,8 @@ #ifndef hifi_RayPickManager_h #define hifi_RayPickManager_h -#include "PickManager.h" - -class RayPickResult; +#include +#include "RegisteredMetaTypes.h" class RayPickManager : public PickManager { diff --git a/interface/src/raypick/RayPickScriptingInterface.cpp b/interface/src/raypick/RayPickScriptingInterface.cpp index 380971b5e6..11b6b2dfa3 100644 --- a/interface/src/raypick/RayPickScriptingInterface.cpp +++ b/interface/src/raypick/RayPickScriptingInterface.cpp @@ -78,7 +78,7 @@ void RayPickScriptingInterface::removeRayPick(const QUuid& uid) { qApp->getRayPickManager().removePick(uid); } -RayPickResult RayPickScriptingInterface::getPrevRayPickResult(const QUuid& uid) { +QVariantMap RayPickScriptingInterface::getPrevRayPickResult(const QUuid& uid) { return qApp->getRayPickManager().getPrevPickResult(uid); } diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h index b91483addf..ebfc3fb9fe 100644 --- a/interface/src/raypick/RayPickScriptingInterface.h +++ b/interface/src/raypick/RayPickScriptingInterface.h @@ -40,26 +40,26 @@ public slots: Q_INVOKABLE void enableRayPick(const QUuid& uid); Q_INVOKABLE void disableRayPick(const QUuid& uid); Q_INVOKABLE void removeRayPick(const QUuid& uid); - Q_INVOKABLE RayPickResult getPrevRayPickResult(const QUuid& uid); + Q_INVOKABLE QVariantMap getPrevRayPickResult(const QUuid& uid); Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, const bool precisionPicking); Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities); Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities); - static unsigned int PICK_NOTHING() { return 0; } - static unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ENTITIES); } - static unsigned int PICK_OVERLAYS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_OVERLAYS); } - static unsigned int PICK_AVATARS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_AVATARS); } - static unsigned int PICK_HUD() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_HUD); } - static unsigned int PICK_COARSE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_COARSE); } - static unsigned int PICK_INCLUDE_INVISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); } - static unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); } - static unsigned int PICK_ALL_INTERSECTIONS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ALL_INTERSECTIONS); } - static unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } - static unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } - static unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } - static unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } - static unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } + static constexpr unsigned int PICK_NOTHING() { return 0; } + static constexpr unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ENTITIES); } + static constexpr unsigned int PICK_OVERLAYS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_OVERLAYS); } + static constexpr unsigned int PICK_AVATARS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_AVATARS); } + static constexpr unsigned int PICK_HUD() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_HUD); } + static constexpr unsigned int PICK_COARSE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_COARSE); } + static constexpr unsigned int PICK_INCLUDE_INVISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); } + static constexpr unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); } + static constexpr unsigned int PICK_ALL_INTERSECTIONS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ALL_INTERSECTIONS); } + static constexpr unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } + static constexpr unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } + static constexpr unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } + static constexpr unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } + static constexpr unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } }; #endif // hifi_RayPickScriptingInterface_h diff --git a/interface/src/raypick/Pick.cpp b/libraries/pointers/src/pointers/Pick.cpp similarity index 100% rename from interface/src/raypick/Pick.cpp rename to libraries/pointers/src/pointers/Pick.cpp diff --git a/interface/src/raypick/Pick.h b/libraries/pointers/src/pointers/Pick.h similarity index 78% rename from interface/src/raypick/Pick.h rename to libraries/pointers/src/pointers/Pick.h index b4d9fa91b9..6e11506dd9 100644 --- a/interface/src/raypick/Pick.h +++ b/libraries/pointers/src/pointers/Pick.h @@ -13,12 +13,18 @@ #include #include +#include +#include -#include #include -#include "EntityScriptingInterface.h" -#include "ui/overlays/Overlays.h" +enum IntersectionType { + NONE = 0, + ENTITY, + OVERLAY, + AVATAR, + HUD +}; class PickFilter { public: @@ -98,6 +104,31 @@ public: static const PickFilter NOTHING; }; +class PickResult { +public: + PickResult() {} + PickResult(const QVariantMap& pickVariant) : pickVariant(pickVariant) {} + + virtual QVariantMap toVariantMap() const { + return pickVariant; + } + + virtual bool doesIntersect() const = 0; + + // for example: if we want the closest result, compare based on distance + // if we want all results, combine them + // must return a new pointer + virtual std::shared_ptr compareAndProcessNewResult(const std::shared_ptr newRes) = 0; + + // returns true if this result contains any valid results with distance < maxDistance + // can also filter out results with distance >= maxDistance + virtual bool checkOrFilterAgainstMaxDistance(float maxDistance) = 0; + + QVariantMap pickVariant; +}; + +using PickResultPointer = std::shared_ptr; + template class Pick : protected ReadWriteLockable { @@ -105,18 +136,11 @@ public: Pick(const PickFilter& filter, const float maxDistance, const bool enabled); virtual const T getMathematicalPick() const = 0; - virtual RayToEntityIntersectionResult getEntityIntersection(const T& pick, bool precisionPicking, - const QVector& entitiesToInclude, - const QVector& entitiesToIgnore, - bool visibleOnly, bool collidableOnly) = 0; - virtual RayToOverlayIntersectionResult getOverlayIntersection(const T& pick, bool precisionPicking, - const QVector& overlaysToInclude, - const QVector& overlaysToIgnore, - bool visibleOnly, bool collidableOnly) = 0; - virtual RayToAvatarIntersectionResult getAvatarIntersection(const T& pick, - const QVector& avatarsToInclude, - const QVector& avatarsToIgnore) = 0; - virtual glm::vec3 getHUDIntersection(const T& pick) = 0; + virtual PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const = 0; + virtual PickResultPointer getEntityIntersection(const T& pick) = 0; + virtual PickResultPointer getOverlayIntersection(const T& pick) = 0; + virtual PickResultPointer getAvatarIntersection(const T& pick) = 0; + virtual PickResultPointer getHUDIntersection(const T& pick) = 0; void enable(bool enabled = true); void disable() { enable(false); } @@ -124,11 +148,11 @@ public: PickFilter getFilter() const; float getMaxDistance() const; bool isEnabled() const; - RayPickResult getPrevPickResult() const; void setPrecisionPicking(bool precisionPicking); - void setPickResult(const RayPickResult& rayPickResult); + PickResultPointer getPrevPickResult() const; + void setPickResult(const PickResultPointer& pickResult); QVector getIgnoreItems() const; QVector getIncludeItems() const; @@ -162,7 +186,7 @@ private: PickFilter _filter; const float _maxDistance; bool _enabled; - RayPickResult _prevResult; + PickResultPointer _prevResult; QVector _ignoreItems; QVector _includeItems; @@ -209,9 +233,9 @@ void Pick::setPrecisionPicking(bool precisionPicking) { } template -void Pick::setPickResult(const RayPickResult& PickResult) { +void Pick::setPickResult(const PickResultPointer& pickResult) { withWriteLock([&] { - _prevResult = PickResult; + _prevResult = pickResult; }); } @@ -230,8 +254,8 @@ QVector Pick::getIncludeItems() const { } template -RayPickResult Pick::getPrevPickResult() const { - return resultWithReadLock([&] { +PickResultPointer Pick::getPrevPickResult() const { + return resultWithReadLock([&] { return _prevResult; }); } diff --git a/interface/src/raypick/PickManager.h b/libraries/pointers/src/pointers/PickManager.h similarity index 59% rename from interface/src/raypick/PickManager.h rename to libraries/pointers/src/pointers/PickManager.h index 3b991d130a..5441ff9b72 100644 --- a/interface/src/raypick/PickManager.h +++ b/libraries/pointers/src/pointers/PickManager.h @@ -1,7 +1,4 @@ // -// PickManager.h -// interface/src/raypick -// // Created by Sam Gondelman 10/16/2017 // Copyright 2017 High Fidelity, Inc. // @@ -36,16 +33,20 @@ namespace std { }; } -// T is a mathematical representation of a Pick. -// For example: PickRay for RayPick -// TODO: add another template type to replace RayPickResult with a generalized PickResult +// T is a mathematical representation of a Pick +// For example: RayPicks use T = PickRay +// T needs have the following functions defined: +// - operator bool() const +// - bool operator==(const T& other) const +// - QVariantMap toVariantMap() const +// - an std::hash size_t operator()(const T& a) const template class PickManager : protected ReadWriteLockable { public: virtual void update(); - RayPickResult getPrevPickResult(const QUuid& uid) const; + QVariantMap getPrevPickResult(const QUuid& uid) const; QUuid addPick(const std::shared_ptr> pick); void removePick(const QUuid& uid); @@ -60,11 +61,11 @@ protected: std::shared_ptr> findPick(const QUuid& uid) const; QHash>> _picks; - typedef std::unordered_map> PickCache; + typedef std::unordered_map> PickCache; - // Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer - bool checkAndCompareCachedResults(T& pick, PickCache& cache, RayPickResult& res, const PickCacheKey& key); - void cacheResult(const bool intersects, const RayPickResult& resTemp, const PickCacheKey& key, RayPickResult& res, T& pick, PickCache& cache); + // Returns true if this pick exists in the cache, and if it does, update res if the cached result is closer + bool checkAndCompareCachedResults(T& pick, PickCache& cache, PickResultPointer& res, const PickCacheKey& key); + void cacheResult(const bool intersects, const PickResultPointer& resTemp, const PickCacheKey& key, PickResultPointer& res, T& mathPick, PickCache& cache, const std::shared_ptr> pick); }; template @@ -78,25 +79,21 @@ std::shared_ptr> PickManager::findPick(const QUuid& uid) const { } template -bool PickManager::checkAndCompareCachedResults(T& pick, PickCache& cache, RayPickResult& res, const PickCacheKey& key) { +bool PickManager::checkAndCompareCachedResults(T& pick, PickCache& cache, PickResultPointer& res, const PickCacheKey& key) { if (cache.find(pick) != cache.end() && cache[pick].find(key) != cache[pick].end()) { - if (cache[pick][key].distance < res.distance) { - res = cache[pick][key]; - } + res = res->compareAndProcessNewResult(cache[pick][key]); return true; } return false; } template -void PickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const PickCacheKey& key, RayPickResult& res, T& pick, PickCache& cache) { +void PickManager::cacheResult(const bool intersects, const PickResultPointer& resTemp, const PickCacheKey& key, PickResultPointer& res, T& mathPick, PickCache& cache, const std::shared_ptr> pick) { if (intersects) { - cache[pick][key] = resTemp; - if (resTemp.distance < res.distance) { - res = resTemp; - } + cache[mathPick][key] = resTemp; + res = res->compareAndProcessNewResult(resTemp); } else { - cache[pick][key] = RayPickResult(res.searchRay); + cache[mathPick][key] = pick->getDefaultResult(mathPick.toVariantMap()); } } @@ -120,50 +117,29 @@ void PickManager::update() { continue; } - RayPickResult res = RayPickResult(mathematicalPick); + PickResultPointer res = pick->getDefaultResult(mathematicalPick.toVariantMap()); if (pick->getFilter().doesPickEntities()) { - RayToEntityIntersectionResult entityRes; - bool fromCache = true; - bool invisible = pick->getFilter().doesPickInvisible(); - bool nonCollidable = pick->getFilter().doesPickNonCollidable(); PickCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) { - entityRes = pick->getEntityIntersection(mathematicalPick, !pick->getFilter().doesPickCoarse(), - pick->(template getIncludeItemsAs()), (template pick->getIgnoreItemsAs()), !invisible, !nonCollidable); - fromCache = false; - } - - if (!fromCache) { - cacheResult(entityRes.intersects, RayPickResult(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, mathematicalPick, entityRes.surfaceNormal), - entityKey, res, mathematicalPick, results); + PickResultPointer entityRes = pick->getEntityIntersection(mathematicalPick); + cacheResult(entityRes->doesIntersect(), entityRes, entityKey, res, mathematicalPick, results, pick); } } if (pick->getFilter().doesPickOverlays()) { - RayToOverlayIntersectionResult overlayRes; - bool fromCache = true; - bool invisible = pick->getFilter().doesPickInvisible(); - bool nonCollidable = pick->getFilter().doesPickNonCollidable(); PickCacheKey overlayKey = { pick->getFilter().getOverlayFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, overlayKey)) { - overlayRes = pick->getOverlayIntersection(mathematicalPick, !pick->getFilter().doesPickCoarse(), - pick->(template getIncludeItemsAs()), pick->(template getIgnoreItemsAs()), !invisible, !nonCollidable); - fromCache = false; - } - - if (!fromCache) { - cacheResult(overlayRes.intersects, RayPickResult(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, mathematicalPick, overlayRes.surfaceNormal), - overlayKey, res, mathematicalPick, results); + PickResultPointer overlayRes = pick->getOverlayIntersection(mathematicalPick); + cacheResult(overlayRes->doesIntersect(), overlayRes, overlayKey, res, mathematicalPick, results, pick); } } if (pick->getFilter().doesPickAvatars()) { PickCacheKey avatarKey = { pick->getFilter().getAvatarFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, avatarKey)) { - RayToAvatarIntersectionResult avatarRes = pick->getAvatarIntersection(mathematicalPick, - pick->(template getIncludeItemsAs()), pick->(template getIgnoreItemsAs())); - cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, mathematicalPick), avatarKey, res, mathematicalPick, results); + PickResultPointer avatarRes = pick->getAvatarIntersection(mathematicalPick); + cacheResult(avatarRes->doesIntersect(), avatarRes, avatarKey, res, mathematicalPick, results, pick); } } @@ -171,26 +147,26 @@ void PickManager::update() { if (pick->getFilter().doesPickHUD() && DependencyManager::get()->isHMDMode()) { PickCacheKey hudKey = { pick->getFilter().getHUDFlags(), QVector(), QVector() }; if (!checkAndCompareCachedResults(mathematicalPick, results, res, hudKey)) { - glm::vec3 hudRes = pick->getHUDIntersection(mathematicalPick); - cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(mathematicalPick.origin, hudRes), hudRes, mathematicalPick), hudKey, res, mathematicalPick, results); + PickResultPointer hudRes = pick->getHUDIntersection(mathematicalPick); + cacheResult(true, hudRes, hudKey, res, mathematicalPick, results, pick); } } - if (pick->getMaxDistance() == 0.0f || (pick->getMaxDistance() > 0.0f && res.distance < pick->getMaxDistance())) { + if (pick->getMaxDistance() == 0.0f || (pick->getMaxDistance() > 0.0f && res->checkOrFilterAgainstMaxDistance(pick->getMaxDistance()))) { pick->setPickResult(res); } else { - pick->setPickResult(RayPickResult(mathematicalPick)); + pick->setPickResult(pick->getDefaultResult(mathematicalPick.toVariantMap())); } } } template -RayPickResult PickManager::getPrevPickResult(const QUuid& uid) const { +QVariantMap PickManager::getPrevPickResult(const QUuid& uid) const { auto pick = findPick(uid); - if (pick) { - return pick->getPrevPickResult(); + if (pick && pick->getPrevPickResult()) { + return pick->getPrevPickResult()->toVariantMap(); } - return RayPickResult(); + return QVariantMap(); } template diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 7d0df3ac78..b4d6ebaa7a 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -34,7 +34,6 @@ int vec2MetaTypeId = qRegisterMetaType(); int quatMetaTypeId = qRegisterMetaType(); int xColorMetaTypeId = qRegisterMetaType(); int pickRayMetaTypeId = qRegisterMetaType(); -int rayPickResultMetaTypeId = qRegisterMetaType(); int collisionMetaTypeId = qRegisterMetaType(); int qMapURLStringMetaTypeId = qRegisterMetaType>(); int socketErrorMetaTypeId = qRegisterMetaType(); @@ -57,7 +56,6 @@ void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, qColorToScriptValue, qColorFromScriptValue); qScriptRegisterMetaType(engine, qURLToScriptValue, qURLFromScriptValue); qScriptRegisterMetaType(engine, pickRayToScriptValue, pickRayFromScriptValue); - qScriptRegisterMetaType(engine, rayPickResultToScriptValue, rayPickResultFromScriptValue); qScriptRegisterMetaType(engine, collisionToScriptValue, collisionFromScriptValue); qScriptRegisterMetaType(engine, quuidToScriptValue, quuidFromScriptValue); qScriptRegisterMetaType(engine, qSizeFToScriptValue, qSizeFFromScriptValue); @@ -753,26 +751,6 @@ void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay) { } } -QScriptValue rayPickResultToScriptValue(QScriptEngine* engine, const RayPickResult& rayPickResult) { - QScriptValue obj = engine->newObject(); - obj.setProperty("type", rayPickResult.type); - QScriptValue objectID = quuidToScriptValue(engine, rayPickResult.objectID); - obj.setProperty("objectID", objectID); - obj.setProperty("distance", rayPickResult.distance); - QScriptValue intersection = vec3toScriptValue(engine, rayPickResult.intersection); - obj.setProperty("intersection", intersection); - obj.setProperty("intersects", rayPickResult.type != NONE); - QScriptValue searchRay = pickRayToScriptValue(engine, rayPickResult.searchRay); - obj.setProperty("searchRay", searchRay); - QScriptValue surfaceNormal = vec3toScriptValue(engine, rayPickResult.surfaceNormal); - obj.setProperty("surfaceNormal", surfaceNormal); - return obj; -} - -void rayPickResultFromScriptValue(const QScriptValue& object, RayPickResult& rayPickResult) { - // TODO: cannot currently accept RayPickResults from JS -} - QScriptValue collisionToScriptValue(QScriptEngine* engine, const Collision& collision) { QScriptValue obj = engine->newObject(); obj.setProperty("type", collision.type); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 8aeabce917..3d423d5205 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -128,6 +128,7 @@ void aaCubeFromScriptValue(const QScriptValue &object, AACube& aaCube); class PickRay { public: PickRay() : origin(NAN), direction(NAN) { } + PickRay(const QVariantMap& pickVariant) : origin(vec3FromVariant(pickVariant["origin"])), direction(vec3FromVariant(pickVariant["direction"])) {} PickRay(const glm::vec3& origin, const glm::vec3 direction) : origin(origin), direction(direction) {} glm::vec3 origin; glm::vec3 direction; @@ -138,6 +139,12 @@ public: bool operator==(const PickRay& other) const { return (origin == other.origin && direction == other.direction); } + QVariantMap toVariantMap() const { + QVariantMap pickRay; + pickRay["origin"] = vec3toVariant(origin); + pickRay["direction"] = vec3toVariant(direction); + return pickRay; + } }; namespace std { template <> @@ -157,31 +164,6 @@ Q_DECLARE_METATYPE(PickRay) QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay); void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay); -enum IntersectionType { - NONE = 0, - ENTITY, - OVERLAY, - AVATAR, - HUD -}; - -class RayPickResult { -public: - RayPickResult() {} - RayPickResult(const PickRay& searchRay) : searchRay(searchRay) {} - RayPickResult(const IntersectionType type, const QUuid& objectID, const float distance, const glm::vec3& intersection, const PickRay& searchRay, const glm::vec3& surfaceNormal = glm::vec3(NAN)) : - type(type), objectID(objectID), distance(distance), intersection(intersection), searchRay(searchRay), surfaceNormal(surfaceNormal) {} - IntersectionType type { NONE }; - QUuid objectID; - float distance { FLT_MAX }; - glm::vec3 intersection { NAN }; - PickRay searchRay; - glm::vec3 surfaceNormal { NAN }; -}; -Q_DECLARE_METATYPE(RayPickResult) -QScriptValue rayPickResultToScriptValue(QScriptEngine* engine, const RayPickResult& rayPickResult); -void rayPickResultFromScriptValue(const QScriptValue& object, RayPickResult& rayPickResult); - enum ContactEventType { CONTACT_EVENT_TYPE_START, CONTACT_EVENT_TYPE_CONTINUE, From d7745efc8e1a256f22aa5bf24a14799a2c2f83ef Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 19 Oct 2017 16:55:24 -0700 Subject: [PATCH 7/9] one global pickmanager --- interface/src/Application.cpp | 119 +++++----- interface/src/Application.h | 6 +- interface/src/raypick/LaserPointer.cpp | 16 +- .../LaserPointerScriptingInterface.cpp | 1 - .../raypick/LaserPointerScriptingInterface.h | 1 - interface/src/raypick/RayPickManager.cpp | 24 -- interface/src/raypick/RayPickManager.h | 22 -- .../src/raypick/RayPickScriptingInterface.cpp | 25 ++- libraries/pointers/src/pointers/Pick.cpp | 72 +++++- libraries/pointers/src/pointers/Pick.h | 102 +-------- .../src/pointers/PickCacheOptimizer.h | 127 +++++++++++ .../pointers/src/pointers/PickManager.cpp | 94 ++++++++ libraries/pointers/src/pointers/PickManager.h | 212 ++---------------- libraries/shared/src/RegisteredMetaTypes.h | 12 +- 14 files changed, 417 insertions(+), 416 deletions(-) delete mode 100644 interface/src/raypick/RayPickManager.cpp delete mode 100644 interface/src/raypick/RayPickManager.h create mode 100644 libraries/pointers/src/pointers/PickCacheOptimizer.h create mode 100644 libraries/pointers/src/pointers/PickManager.cpp diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 49b150db79..a727c58f86 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -195,6 +195,7 @@ #include #include +#include #include @@ -750,8 +751,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _notifiedPacketVersionMismatchThisDomain(false), _maxOctreePPS(maxOctreePacketsPerSecond.get()), _lastFaceTrackerUpdate(0), - _snapshotSound(nullptr) -{ + _snapshotSound(nullptr) { auto steamClient = PluginManager::getInstance()->getSteamClientPlugin(); setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); @@ -795,7 +795,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo installNativeEventFilter(&MyNativeEventFilter::getInstance()); #endif - + _logger = new FileLogger(this); qInstallMessageHandler(messageHandler); @@ -850,13 +850,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto audioIO = DependencyManager::get(); - audioIO->setPositionGetter([]{ + audioIO->setPositionGetter([] { auto avatarManager = DependencyManager::get(); auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr; return myAvatar ? myAvatar->getPositionForAudio() : Vectors::ZERO; }); - audioIO->setOrientationGetter([]{ + audioIO->setOrientationGetter([] { auto avatarManager = DependencyManager::get(); auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr; @@ -867,7 +867,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo audioIO->handleRecordedAudioInput(frame->data); }); - connect(audioIO.data(), &AudioClient::inputReceived, [](const QByteArray& audio){ + connect(audioIO.data(), &AudioClient::inputReceived, [](const QByteArray& audio) { static auto recorder = DependencyManager::get(); if (recorder->isRecording()) { static const recording::FrameType AUDIO_FRAME_TYPE = recording::Frame::registerFrameType(AudioConstants::getAudioFrameName()); @@ -956,14 +956,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto addressManager = DependencyManager::get(); // use our MyAvatar position and quat for address manager path - addressManager->setPositionGetter([this]{ return getMyAvatar()->getPosition(); }); - addressManager->setOrientationGetter([this]{ return getMyAvatar()->getOrientation(); }); + addressManager->setPositionGetter([this] { return getMyAvatar()->getPosition(); }); + addressManager->setOrientationGetter([this] { return getMyAvatar()->getOrientation(); }); connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle); connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress); connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateThreadPoolCount); - connect(this, &Application::activeDisplayPluginChanged, this, [](){ + connect(this, &Application::activeDisplayPluginChanged, this, []() { qApp->setProperty(hifi::properties::HMD, qApp->isHMDMode()); }); connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateSystemTabletMode); @@ -973,7 +973,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get().data(), &AddressManager::storeCurrentAddress); auto scriptEngines = DependencyManager::get().data(); - scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine){ + scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine) { registerScriptEngineWithApplicationServices(engine); }); @@ -989,7 +989,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo }, Qt::QueuedConnection); connect(scriptEngines, &ScriptEngines::scriptLoadError, - scriptEngines, [](const QString& filename, const QString& error){ + scriptEngines, [](const QString& filename, const QString& error) { OffscreenUi::asyncWarning(nullptr, "Error Loading Script", filename + " failed to load."); }, Qt::QueuedConnection); @@ -1101,7 +1101,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } // add firstRun flag from settings to launch event - Setting::Handle firstRun { Settings::firstRun, true }; + Setting::Handle firstRun{ Settings::firstRun, true }; // once the settings have been loaded, check if we need to flip the default for UserActivityLogger auto& userActivityLogger = UserActivityLogger::getInstance(); @@ -1202,42 +1202,42 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo static int lastKey = Qt::Key_unknown; bool navAxis = false; switch (actionEnum) { - case Action::UI_NAV_VERTICAL: - navAxis = true; - if (state > 0.0f) { - key = Qt::Key_Up; - } else if (state < 0.0f) { - key = Qt::Key_Down; - } - break; + case Action::UI_NAV_VERTICAL: + navAxis = true; + if (state > 0.0f) { + key = Qt::Key_Up; + } else if (state < 0.0f) { + key = Qt::Key_Down; + } + break; - case Action::UI_NAV_LATERAL: - navAxis = true; - if (state > 0.0f) { - key = Qt::Key_Right; - } else if (state < 0.0f) { - key = Qt::Key_Left; - } - break; + case Action::UI_NAV_LATERAL: + navAxis = true; + if (state > 0.0f) { + key = Qt::Key_Right; + } else if (state < 0.0f) { + key = Qt::Key_Left; + } + break; - case Action::UI_NAV_GROUP: - navAxis = true; - if (state > 0.0f) { - key = Qt::Key_Tab; - } else if (state < 0.0f) { - key = Qt::Key_Backtab; - } - break; + case Action::UI_NAV_GROUP: + navAxis = true; + if (state > 0.0f) { + key = Qt::Key_Tab; + } else if (state < 0.0f) { + key = Qt::Key_Backtab; + } + break; - case Action::UI_NAV_BACK: - key = Qt::Key_Escape; - break; + case Action::UI_NAV_BACK: + key = Qt::Key_Escape; + break; - case Action::UI_NAV_SELECT: - key = Qt::Key_Return; - break; - default: - break; + case Action::UI_NAV_SELECT: + key = Qt::Key_Return; + break; + default: + break; } auto window = tabletScriptingInterface->getTabletWindow(); @@ -1376,8 +1376,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo QTimer* settingsTimer = new QTimer(); - moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer]{ - connect(qApp, &Application::beforeAboutToQuit, [this, settingsTimer]{ + moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer] { + connect(qApp, &Application::beforeAboutToQuit, [this, settingsTimer] { // Disconnect the signal from the save settings QObject::disconnect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings); // Stop the settings timer @@ -1439,7 +1439,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Now that menu is initialized we can sync myAvatar with it's state. myAvatar->updateMotionBehaviorFromMenu(); -// FIXME spacemouse code still needs cleanup + // FIXME spacemouse code still needs cleanup #if 0 // the 3Dconnexion device wants to be initialized after a window is displayed. SpacemouseManager::getInstance().init(); @@ -1448,7 +1448,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // If the user clicks an an entity, we will check that it's an unlocked web entity, and if so, set the focus to it auto entityScriptingInterface = DependencyManager::get(); connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity, - [this](const EntityItemID& entityItemID, const PointerEvent& event) { + [this](const EntityItemID& entityItemID, const PointerEvent& event) { if (getEntities()->wantsKeyboardFocus(entityItemID)) { setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); setKeyboardFocusEntity(entityItemID); @@ -1663,8 +1663,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo totalServerOctreeElements += i->second.getTotalElements(); } - properties["local_octree_elements"] = (qint64) OctreeElement::getInternalNodeCount(); - properties["server_octree_elements"] = (qint64) totalServerOctreeElements; + properties["local_octree_elements"] = (qint64)OctreeElement::getInternalNodeCount(); + properties["server_octree_elements"] = (qint64)totalServerOctreeElements; properties["active_display_plugin"] = getActiveDisplayPlugin()->getName(); properties["using_hmd"] = isHMDMode(); @@ -1685,7 +1685,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (_autoSwitchDisplayModeSupportedHMDPlugin) { if (getActiveDisplayPlugin() != _autoSwitchDisplayModeSupportedHMDPlugin && !_autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) { - startHMDStandBySession(); + startHMDStandBySession(); } // Poll periodically to check whether the user has worn HMD or not. Switch Display mode accordingly. // If the user wears HMD then switch to VR mode. If the user removes HMD then switch to Desktop mode. @@ -1729,7 +1729,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(checkNearbyAvatarsTimer, &QTimer::timeout, this, [this]() { auto avatarManager = DependencyManager::get(); int nearbyAvatars = avatarManager->numberOfAvatarsInRange(avatarManager->getMyAvatar()->getPosition(), - NEARBY_AVATAR_RADIUS_METERS) - 1; + NEARBY_AVATAR_RADIUS_METERS) - 1; if (nearbyAvatars != lastCountOfNearbyAvatars) { lastCountOfNearbyAvatars = nearbyAvatars; UserActivityLogger::getInstance().logAction("nearby_avatars", { { "count", nearbyAvatars } }); @@ -1817,14 +1817,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged); + _pickManager.setShouldPickHUDOperator([&]() { return DependencyManager::get()->isHMDMode(); }); + // Setup the mouse ray pick and related operators - DependencyManager::get()->setMouseRayPickID(_rayPickManager.createRayPick( - PickFilter(RayPickScriptingInterface::PICK_ENTITIES() | RayPickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), - 0.0f, true)); + DependencyManager::get()->setMouseRayPickID(_pickManager.addPick(RAY, std::make_shared( + PickFilter(RayPickScriptingInterface::PICK_ENTITIES() | RayPickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true))); DependencyManager::get()->setMouseRayPickResultOperator([&](QUuid rayPickID) { RayToEntityIntersectionResult entityResult; entityResult.intersects = false; - QVariantMap result = _rayPickManager.getPrevPickResult(rayPickID); + QVariantMap result = _pickManager.getPrevPickResult(rayPickID); if (result["type"].isValid()) { entityResult.intersects = result["type"] != RayPickScriptingInterface::INTERSECTED_NONE(); if (entityResult.intersects) { @@ -1838,7 +1839,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return entityResult; }); DependencyManager::get()->setSetPrecisionPickingOperator([&](QUuid rayPickID, bool value) { - _rayPickManager.setPrecisionPicking(rayPickID, value); + _pickManager.setPrecisionPicking(rayPickID, value); }); qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); @@ -4910,8 +4911,8 @@ void Application::update(float deltaTime) { // TODO: break these out into distinct perfTimers when they prove interesting { - PROFILE_RANGE(app, "RayPickManager"); - _rayPickManager.update(); + PROFILE_RANGE(app, "PickManager"); + _pickManager.update(); } { diff --git a/interface/src/Application.h b/interface/src/Application.h index 772646f379..a70aaf93c7 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -70,7 +70,7 @@ #include "ui/overlays/Overlays.h" #include "UndoStackScriptingInterface.h" -#include "raypick/RayPickManager.h" +#include #include "raypick/LaserPointerManager.h" #include @@ -299,7 +299,7 @@ public: bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; } LaserPointerManager& getLaserPointerManager() { return _laserPointerManager; } - RayPickManager& getRayPickManager() { return _rayPickManager; } + PickManager& getPickManager() { return _pickManager; } signals: void svoImportRequested(const QString& url); @@ -713,7 +713,7 @@ private: bool _saveAvatarOverrideUrl { false }; QObject* _renderEventHandler{ nullptr }; - RayPickManager _rayPickManager; + PickManager _pickManager; LaserPointerManager _laserPointerManager; friend class RenderEventHandler; diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 2f3fc13706..0a8506ee28 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -38,7 +38,7 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende } LaserPointer::~LaserPointer() { - qApp->getRayPickManager().removePick(_rayPickUID); + qApp->getPickManager().removePick(_rayPickUID); for (auto& renderState : _renderStates) { renderState.second.deleteOverlays(); @@ -49,14 +49,14 @@ LaserPointer::~LaserPointer() { } void LaserPointer::enable() { - qApp->getRayPickManager().enablePick(_rayPickUID); + qApp->getPickManager().enablePick(_rayPickUID); withWriteLock([&] { _renderingEnabled = true; }); } void LaserPointer::disable() { - qApp->getRayPickManager().disablePick(_rayPickUID); + qApp->getPickManager().disablePick(_rayPickUID); withWriteLock([&] { _renderingEnabled = false; if (!_currentRenderState.empty()) { @@ -101,7 +101,7 @@ void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& } const QVariantMap LaserPointer::getPrevRayPickResult() { - return qApp->getRayPickManager().getPrevPickResult(_rayPickUID); + return qApp->getPickManager().getPrevPickResult(_rayPickUID); } void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState) { @@ -197,7 +197,7 @@ void LaserPointer::disableRenderState(const RenderState& renderState) { void LaserPointer::update() { // This only needs to be a read lock because update won't change any of the properties that can be modified from scripts withReadLock([&] { - QVariantMap prevRayPickResult = qApp->getRayPickManager().getPrevPickResult(_rayPickUID); + QVariantMap prevRayPickResult = qApp->getPickManager().getPrevPickResult(_rayPickUID); IntersectionType type = IntersectionType(prevRayPickResult["type"].toInt()); PickRay pickRay = PickRay(prevRayPickResult["searchRay"].toMap()); QUuid uid = prevRayPickResult["objectID"].toUuid(); @@ -217,7 +217,7 @@ void LaserPointer::update() { } void LaserPointer::setPrecisionPicking(const bool precisionPicking) { - qApp->getRayPickManager().setPrecisionPicking(_rayPickUID, precisionPicking); + qApp->getPickManager().setPrecisionPicking(_rayPickUID, precisionPicking); } void LaserPointer::setLaserLength(const float laserLength) { @@ -233,11 +233,11 @@ void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay) { } void LaserPointer::setIgnoreItems(const QVector& ignoreItems) const { - qApp->getRayPickManager().setIgnoreItems(_rayPickUID, ignoreItems); + qApp->getPickManager().setIgnoreItems(_rayPickUID, ignoreItems); } void LaserPointer::setIncludeItems(const QVector& includeItems) const { - qApp->getRayPickManager().setIncludeItems(_rayPickUID, includeItems); + qApp->getPickManager().setIncludeItems(_rayPickUID, includeItems); } RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID) : diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index 96839160fa..4ff917d8c5 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -14,7 +14,6 @@ #include #include -#include void LaserPointerScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) const { qApp->getLaserPointerManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems)); diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index 1e34016ab5..d51420a112 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -13,7 +13,6 @@ #include -#include "RegisteredMetaTypes.h" #include "DependencyManager.h" #include "Application.h" diff --git a/interface/src/raypick/RayPickManager.cpp b/interface/src/raypick/RayPickManager.cpp deleted file mode 100644 index 2e62c608d8..0000000000 --- a/interface/src/raypick/RayPickManager.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// Created by Sam Gondelman 7/11/2017 -// 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 "RayPickManager.h" - -#include "StaticRayPick.h" -#include "JointRayPick.h" -#include "MouseRayPick.h" - -QUuid RayPickManager::createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, float maxDistance, bool enabled) { - return addPick(std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); -} - -QUuid RayPickManager::createRayPick(const PickFilter& filter, float maxDistance, bool enabled) { - return addPick(std::make_shared(filter, maxDistance, enabled)); -} - -QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, float maxDistance, bool enabled) { - return addPick(std::make_shared(position, direction, filter, maxDistance, enabled)); -} \ No newline at end of file diff --git a/interface/src/raypick/RayPickManager.h b/interface/src/raypick/RayPickManager.h deleted file mode 100644 index 7bc97c8526..0000000000 --- a/interface/src/raypick/RayPickManager.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Created by Sam Gondelman 7/11/2017 -// 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_RayPickManager_h -#define hifi_RayPickManager_h - -#include -#include "RegisteredMetaTypes.h" - -class RayPickManager : public PickManager { - -public: - QUuid createRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const PickFilter& filter, const float maxDistance, const bool enabled); - QUuid createRayPick(const PickFilter& filter, const float maxDistance, const bool enabled); - QUuid createRayPick(const glm::vec3& position, const glm::vec3& direction, const PickFilter& filter, const float maxDistance, const bool enabled); -}; - -#endif // hifi_RayPickManager_h \ No newline at end of file diff --git a/interface/src/raypick/RayPickScriptingInterface.cpp b/interface/src/raypick/RayPickScriptingInterface.cpp index 11b6b2dfa3..de67fdde0f 100644 --- a/interface/src/raypick/RayPickScriptingInterface.cpp +++ b/interface/src/raypick/RayPickScriptingInterface.cpp @@ -15,6 +15,10 @@ #include "GLMHelpers.h" #include "Application.h" +#include "StaticRayPick.h" +#include "JointRayPick.h" +#include "MouseRayPick.h" + QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) { QVariantMap propMap = properties.toMap(); @@ -48,9 +52,10 @@ QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) { dirOffset = vec3FromVariant(propMap["dirOffset"]); } - return qApp->getRayPickManager().createRayPick(jointName, posOffset, dirOffset, filter, maxDistance, enabled); + return qApp->getPickManager().addPick(RAY, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); + } else { - return qApp->getRayPickManager().createRayPick(filter, maxDistance, enabled); + return qApp->getPickManager().addPick(RAY, std::make_shared(filter, maxDistance, enabled)); } } else if (propMap["position"].isValid()) { glm::vec3 position = vec3FromVariant(propMap["position"]); @@ -60,36 +65,36 @@ QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) { direction = vec3FromVariant(propMap["direction"]); } - return qApp->getRayPickManager().createRayPick(position, direction, filter, maxDistance, enabled); + return qApp->getPickManager().addPick(RAY, std::make_shared(position, direction, filter, maxDistance, enabled)); } return QUuid(); } void RayPickScriptingInterface::enableRayPick(const QUuid& uid) { - qApp->getRayPickManager().enablePick(uid); + qApp->getPickManager().enablePick(uid); } void RayPickScriptingInterface::disableRayPick(const QUuid& uid) { - qApp->getRayPickManager().disablePick(uid); + qApp->getPickManager().disablePick(uid); } void RayPickScriptingInterface::removeRayPick(const QUuid& uid) { - qApp->getRayPickManager().removePick(uid); + qApp->getPickManager().removePick(uid); } QVariantMap RayPickScriptingInterface::getPrevRayPickResult(const QUuid& uid) { - return qApp->getRayPickManager().getPrevPickResult(uid); + return qApp->getPickManager().getPrevPickResult(uid); } void RayPickScriptingInterface::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) { - qApp->getRayPickManager().setPrecisionPicking(uid, precisionPicking); + qApp->getPickManager().setPrecisionPicking(uid, precisionPicking); } void RayPickScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) { - qApp->getRayPickManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems)); + qApp->getPickManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems)); } void RayPickScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) { - qApp->getRayPickManager().setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems)); + qApp->getPickManager().setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems)); } diff --git a/libraries/pointers/src/pointers/Pick.cpp b/libraries/pointers/src/pointers/Pick.cpp index 030d2ef4b7..4e48bc906b 100644 --- a/libraries/pointers/src/pointers/Pick.cpp +++ b/libraries/pointers/src/pointers/Pick.cpp @@ -7,4 +7,74 @@ // #include "Pick.h" -const PickFilter PickFilter::NOTHING; \ No newline at end of file +const PickFilter PickFilter::NOTHING; + +PickQuery::PickQuery(const PickFilter& filter, const float maxDistance, const bool enabled) : + _filter(filter), + _maxDistance(maxDistance), + _enabled(enabled) { +} + +void PickQuery::enable(bool enabled) { + withWriteLock([&] { + _enabled = enabled; + }); +} + +PickFilter PickQuery::getFilter() const { + return resultWithReadLock([&] { + return _filter; + }); +} + +float PickQuery::getMaxDistance() const { + return _maxDistance; +} + +bool PickQuery::isEnabled() const { + return resultWithReadLock([&] { + return _enabled; + }); +} + +void PickQuery::setPrecisionPicking(bool precisionPicking) { + withWriteLock([&] { + _filter.setFlag(PickFilter::PICK_COARSE, !precisionPicking); + }); +} + +void PickQuery::setPickResult(const PickResultPointer& pickResult) { + withWriteLock([&] { + _prevResult = pickResult; + }); +} + +QVector PickQuery::getIgnoreItems() const { + return resultWithReadLock>([&] { + return _ignoreItems; + }); +} + +QVector PickQuery::getIncludeItems() const { + return resultWithReadLock>([&] { + return _includeItems; + }); +} + +PickResultPointer PickQuery::getPrevPickResult() const { + return resultWithReadLock([&] { + return _prevResult; + }); +} + +void PickQuery::setIgnoreItems(const QVector& ignoreItems) { + withWriteLock([&] { + _ignoreItems = ignoreItems; + }); +} + +void PickQuery::setIncludeItems(const QVector& includeItems) { + withWriteLock([&] { + _includeItems = includeItems; + }); +} \ No newline at end of file diff --git a/libraries/pointers/src/pointers/Pick.h b/libraries/pointers/src/pointers/Pick.h index 6e11506dd9..6ac0d6781e 100644 --- a/libraries/pointers/src/pointers/Pick.h +++ b/libraries/pointers/src/pointers/Pick.h @@ -129,18 +129,9 @@ public: using PickResultPointer = std::shared_ptr; -template -class Pick : protected ReadWriteLockable { - +class PickQuery : protected ReadWriteLockable { public: - Pick(const PickFilter& filter, const float maxDistance, const bool enabled); - - virtual const T getMathematicalPick() const = 0; - virtual PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const = 0; - virtual PickResultPointer getEntityIntersection(const T& pick) = 0; - virtual PickResultPointer getOverlayIntersection(const T& pick) = 0; - virtual PickResultPointer getAvatarIntersection(const T& pick) = 0; - virtual PickResultPointer getHUDIntersection(const T& pick) = 0; + PickQuery(const PickFilter& filter, const float maxDistance, const bool enabled); void enable(bool enabled = true); void disable() { enable(false); } @@ -193,85 +184,16 @@ private: }; template -Pick::Pick(const PickFilter& filter, const float maxDistance, const bool enabled) : - _filter(filter), - _maxDistance(maxDistance), - _enabled(enabled) { -} +class Pick : public PickQuery { +public: + Pick(const PickFilter& filter, const float maxDistance, const bool enabled) : PickQuery(filter, maxDistance, enabled) {} -template -void Pick::enable(bool enabled) { - withWriteLock([&] { - _enabled = enabled; - }); -} - -template -PickFilter Pick::getFilter() const { - return resultWithReadLock([&] { - return _filter; - }); -} - -template -float Pick::getMaxDistance() const { - return _maxDistance; -} - -template -bool Pick::isEnabled() const { - return resultWithReadLock([&] { - return _enabled; - }); -} - -template -void Pick::setPrecisionPicking(bool precisionPicking) { - withWriteLock([&] { - _filter.setFlag(PickFilter::PICK_COARSE, !precisionPicking); - }); -} - -template -void Pick::setPickResult(const PickResultPointer& pickResult) { - withWriteLock([&] { - _prevResult = pickResult; - }); -} - -template -QVector Pick::getIgnoreItems() const { - return resultWithReadLock>([&] { - return _ignoreItems; - }); -} - -template -QVector Pick::getIncludeItems() const { - return resultWithReadLock>([&] { - return _includeItems; - }); -} - -template -PickResultPointer Pick::getPrevPickResult() const { - return resultWithReadLock([&] { - return _prevResult; - }); -} - -template -void Pick::setIgnoreItems(const QVector& ignoreItems) { - withWriteLock([&] { - _ignoreItems = ignoreItems; - }); -} - -template -void Pick::setIncludeItems(const QVector& includeItems) { - withWriteLock([&] { - _includeItems = includeItems; - }); -} + virtual const T getMathematicalPick() const = 0; + virtual PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const = 0; + virtual PickResultPointer getEntityIntersection(const T& pick) = 0; + virtual PickResultPointer getOverlayIntersection(const T& pick) = 0; + virtual PickResultPointer getAvatarIntersection(const T& pick) = 0; + virtual PickResultPointer getHUDIntersection(const T& pick) = 0; +}; #endif // hifi_Pick_h diff --git a/libraries/pointers/src/pointers/PickCacheOptimizer.h b/libraries/pointers/src/pointers/PickCacheOptimizer.h new file mode 100644 index 0000000000..c4bf96ab51 --- /dev/null +++ b/libraries/pointers/src/pointers/PickCacheOptimizer.h @@ -0,0 +1,127 @@ +// +// Created by Sam Gondelman 10/16/2017 +// 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_PickCacheOptimizer_h +#define hifi_PickCacheOptimizer_h + +#include + +#include "Pick.h" + +typedef struct PickCacheKey { + PickFilter::Flags mask; + QVector include; + QVector ignore; + + bool operator==(const PickCacheKey& other) const { + return (mask == other.mask && include == other.include && ignore == other.ignore); + } +} PickCacheKey; + +namespace std { + template <> + struct hash { + size_t operator()(const PickCacheKey& k) const { + return ((hash()(k.mask) ^ (qHash(k.include) << 1)) >> 1) ^ (qHash(k.ignore) << 1); + } + }; +} + +// T is a mathematical representation of a Pick (a MathPick) +// For example: RayPicks use T = PickRay +template +class PickCacheOptimizer { + +public: + void update(QHash>& picks, bool shouldPickHUD); + +protected: + typedef std::unordered_map> PickCache; + + // Returns true if this pick exists in the cache, and if it does, update res if the cached result is closer + bool checkAndCompareCachedResults(T& pick, PickCache& cache, PickResultPointer& res, const PickCacheKey& key); + void cacheResult(const bool intersects, const PickResultPointer& resTemp, const PickCacheKey& key, PickResultPointer& res, T& mathPick, PickCache& cache, const std::shared_ptr> pick); +}; + +template +bool PickCacheOptimizer::checkAndCompareCachedResults(T& pick, PickCache& cache, PickResultPointer& res, const PickCacheKey& key) { + if (cache.find(pick) != cache.end() && cache[pick].find(key) != cache[pick].end()) { + res = res->compareAndProcessNewResult(cache[pick][key]); + return true; + } + return false; +} + +template +void PickCacheOptimizer::cacheResult(const bool intersects, const PickResultPointer& resTemp, const PickCacheKey& key, PickResultPointer& res, T& mathPick, PickCache& cache, const std::shared_ptr> pick) { + if (intersects) { + cache[mathPick][key] = resTemp; + res = res->compareAndProcessNewResult(resTemp); + } else { + cache[mathPick][key] = pick->getDefaultResult(mathPick.toVariantMap()); + } +} + +template +void PickCacheOptimizer::update(QHash>& picks, bool shouldPickHUD) { + PickCache results; + for (const auto& uid : picks.keys()) { + std::shared_ptr> pick = std::static_pointer_cast>(picks[uid]); + if (!pick->isEnabled() || pick->getFilter().doesPickNothing() || pick->getMaxDistance() < 0.0f) { + continue; + } + + T mathematicalPick = pick->getMathematicalPick(); + + if (!mathematicalPick) { + continue; + } + + PickResultPointer res = pick->getDefaultResult(mathematicalPick.toVariantMap()); + + if (pick->getFilter().doesPickEntities()) { + PickCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; + if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) { + PickResultPointer entityRes = pick->getEntityIntersection(mathematicalPick); + cacheResult(entityRes->doesIntersect(), entityRes, entityKey, res, mathematicalPick, results, pick); + } + } + + if (pick->getFilter().doesPickOverlays()) { + PickCacheKey overlayKey = { pick->getFilter().getOverlayFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; + if (!checkAndCompareCachedResults(mathematicalPick, results, res, overlayKey)) { + PickResultPointer overlayRes = pick->getOverlayIntersection(mathematicalPick); + cacheResult(overlayRes->doesIntersect(), overlayRes, overlayKey, res, mathematicalPick, results, pick); + } + } + + if (pick->getFilter().doesPickAvatars()) { + PickCacheKey avatarKey = { pick->getFilter().getAvatarFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; + if (!checkAndCompareCachedResults(mathematicalPick, results, res, avatarKey)) { + PickResultPointer avatarRes = pick->getAvatarIntersection(mathematicalPick); + cacheResult(avatarRes->doesIntersect(), avatarRes, avatarKey, res, mathematicalPick, results, pick); + } + } + + // Can't intersect with HUD in desktop mode + if (pick->getFilter().doesPickHUD() && shouldPickHUD) { + PickCacheKey hudKey = { pick->getFilter().getHUDFlags(), QVector(), QVector() }; + if (!checkAndCompareCachedResults(mathematicalPick, results, res, hudKey)) { + PickResultPointer hudRes = pick->getHUDIntersection(mathematicalPick); + cacheResult(true, hudRes, hudKey, res, mathematicalPick, results, pick); + } + } + + if (pick->getMaxDistance() == 0.0f || (pick->getMaxDistance() > 0.0f && res->checkOrFilterAgainstMaxDistance(pick->getMaxDistance()))) { + pick->setPickResult(res); + } else { + pick->setPickResult(pick->getDefaultResult(mathematicalPick.toVariantMap())); + } + } +} + +#endif // hifi_PickCacheOptimizer_h \ No newline at end of file diff --git a/libraries/pointers/src/pointers/PickManager.cpp b/libraries/pointers/src/pointers/PickManager.cpp new file mode 100644 index 0000000000..d6c2f44212 --- /dev/null +++ b/libraries/pointers/src/pointers/PickManager.cpp @@ -0,0 +1,94 @@ +// +// Created by Sam Gondelman 10/19/2017 +// 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 "PickManager.h" + +PickManager::PickManager() { + setShouldPickHUDOperator([]() { return false; }); +} + +QUuid PickManager::addPick(PickType type, const std::shared_ptr pick) { + QUuid id = QUuid::createUuid(); + withWriteLock([&] { + _picks[type][id] = pick; + _typeMap[id] = type; + }); + return id; +} + +std::shared_ptr PickManager::findPick(const QUuid& uid) const { + return resultWithReadLock>([&] { + auto type = _typeMap.find(uid); + if (type != _typeMap.end()) { + return _picks[type.value()][uid]; + } + return std::shared_ptr(); + }); +} + +void PickManager::removePick(const QUuid& uid) { + withWriteLock([&] { + auto type = _typeMap.find(uid); + if (type != _typeMap.end()) { + _picks[type.value()].remove(uid); + _typeMap.remove(uid); + } + }); +} + +QVariantMap PickManager::getPrevPickResult(const QUuid& uid) const { + auto pick = findPick(uid); + if (pick && pick->getPrevPickResult()) { + return pick->getPrevPickResult()->toVariantMap(); + } + return QVariantMap(); +} + +void PickManager::enablePick(const QUuid& uid) const { + auto pick = findPick(uid); + if (pick) { + pick->enable(); + } +} + +void PickManager::disablePick(const QUuid& uid) const { + auto pick = findPick(uid); + if (pick) { + pick->disable(); + } +} + +void PickManager::setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { + auto pick = findPick(uid); + if (pick) { + pick->setPrecisionPicking(precisionPicking); + } +} + +void PickManager::setIgnoreItems(const QUuid& uid, const QVector& ignore) const { + auto pick = findPick(uid); + if (pick) { + pick->setIgnoreItems(ignore); + } +} + +void PickManager::setIncludeItems(const QUuid& uid, const QVector& include) const { + auto pick = findPick(uid); + if (pick) { + pick->setIncludeItems(include); + } +} + +void PickManager::update() { + QHash>> cachedPicks; + withReadLock([&] { + cachedPicks = _picks; + }); + + bool shouldPickHUD = _shouldPickHUDOperator(); + _rayPickCacheOptimizer.update(cachedPicks[RAY], shouldPickHUD); +} \ No newline at end of file diff --git a/libraries/pointers/src/pointers/PickManager.h b/libraries/pointers/src/pointers/PickManager.h index 5441ff9b72..9b2f19a63a 100644 --- a/libraries/pointers/src/pointers/PickManager.h +++ b/libraries/pointers/src/pointers/PickManager.h @@ -10,220 +10,44 @@ #include -#include "scripting/HMDScriptingInterface.h" +#include "RegisteredMetaTypes.h" #include "Pick.h" +#include "PickCacheOptimizer.h" -typedef struct PickCacheKey { - PickFilter::Flags mask; - QVector include; - QVector ignore; +enum PickType { + RAY = 0, + STYLUS +}; - bool operator==(const PickCacheKey& other) const { - return (mask == other.mask && include == other.include && ignore == other.ignore); - } -} PickCacheKey; - -namespace std { - template <> - struct hash { - size_t operator()(const PickCacheKey& k) const { - return ((hash()(k.mask) ^ (qHash(k.include) << 1)) >> 1) ^ (qHash(k.ignore) << 1); - } - }; -} - -// T is a mathematical representation of a Pick -// For example: RayPicks use T = PickRay -// T needs have the following functions defined: -// - operator bool() const -// - bool operator==(const T& other) const -// - QVariantMap toVariantMap() const -// - an std::hash size_t operator()(const T& a) const -template class PickManager : protected ReadWriteLockable { public: - virtual void update(); + PickManager(); - QVariantMap getPrevPickResult(const QUuid& uid) const; + void update(); - QUuid addPick(const std::shared_ptr> pick); + QUuid addPick(PickType type, const std::shared_ptr pick); void removePick(const QUuid& uid); void enablePick(const QUuid& uid) const; void disablePick(const QUuid& uid) const; + QVariantMap getPrevPickResult(const QUuid& uid) const; + void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const; void setIgnoreItems(const QUuid& uid, const QVector& ignore) const; void setIncludeItems(const QUuid& uid, const QVector& include) const; + void setShouldPickHUDOperator(std::function shouldPickHUDOperator) { _shouldPickHUDOperator = shouldPickHUDOperator; } + protected: - std::shared_ptr> findPick(const QUuid& uid) const; - QHash>> _picks; + std::function _shouldPickHUDOperator; - typedef std::unordered_map> PickCache; + std::shared_ptr findPick(const QUuid& uid) const; + QHash>> _picks; + QHash _typeMap; - // Returns true if this pick exists in the cache, and if it does, update res if the cached result is closer - bool checkAndCompareCachedResults(T& pick, PickCache& cache, PickResultPointer& res, const PickCacheKey& key); - void cacheResult(const bool intersects, const PickResultPointer& resTemp, const PickCacheKey& key, PickResultPointer& res, T& mathPick, PickCache& cache, const std::shared_ptr> pick); + PickCacheOptimizer _rayPickCacheOptimizer; }; -template -std::shared_ptr> PickManager::findPick(const QUuid& uid) const { - return resultWithReadLock>>([&] { - if (_picks.contains(uid)) { - return _picks[uid]; - } - return std::shared_ptr>(); - }); -} - -template -bool PickManager::checkAndCompareCachedResults(T& pick, PickCache& cache, PickResultPointer& res, const PickCacheKey& key) { - if (cache.find(pick) != cache.end() && cache[pick].find(key) != cache[pick].end()) { - res = res->compareAndProcessNewResult(cache[pick][key]); - return true; - } - return false; -} - -template -void PickManager::cacheResult(const bool intersects, const PickResultPointer& resTemp, const PickCacheKey& key, PickResultPointer& res, T& mathPick, PickCache& cache, const std::shared_ptr> pick) { - if (intersects) { - cache[mathPick][key] = resTemp; - res = res->compareAndProcessNewResult(resTemp); - } else { - cache[mathPick][key] = pick->getDefaultResult(mathPick.toVariantMap()); - } -} - -template -void PickManager::update() { - PickCache results; - QHash>> cachedPicks; - withReadLock([&] { - cachedPicks = _picks; - }); - - for (const auto& uid : cachedPicks.keys()) { - std::shared_ptr> pick = cachedPicks[uid]; - if (!pick->isEnabled() || pick->getFilter().doesPickNothing() || pick->getMaxDistance() < 0.0f) { - continue; - } - - T mathematicalPick = pick->getMathematicalPick(); - - if (!mathematicalPick) { - continue; - } - - PickResultPointer res = pick->getDefaultResult(mathematicalPick.toVariantMap()); - - if (pick->getFilter().doesPickEntities()) { - PickCacheKey entityKey = { pick->getFilter().getEntityFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; - if (!checkAndCompareCachedResults(mathematicalPick, results, res, entityKey)) { - PickResultPointer entityRes = pick->getEntityIntersection(mathematicalPick); - cacheResult(entityRes->doesIntersect(), entityRes, entityKey, res, mathematicalPick, results, pick); - } - } - - if (pick->getFilter().doesPickOverlays()) { - PickCacheKey overlayKey = { pick->getFilter().getOverlayFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; - if (!checkAndCompareCachedResults(mathematicalPick, results, res, overlayKey)) { - PickResultPointer overlayRes = pick->getOverlayIntersection(mathematicalPick); - cacheResult(overlayRes->doesIntersect(), overlayRes, overlayKey, res, mathematicalPick, results, pick); - } - } - - if (pick->getFilter().doesPickAvatars()) { - PickCacheKey avatarKey = { pick->getFilter().getAvatarFlags(), pick->getIncludeItems(), pick->getIgnoreItems() }; - if (!checkAndCompareCachedResults(mathematicalPick, results, res, avatarKey)) { - PickResultPointer avatarRes = pick->getAvatarIntersection(mathematicalPick); - cacheResult(avatarRes->doesIntersect(), avatarRes, avatarKey, res, mathematicalPick, results, pick); - } - } - - // Can't intersect with HUD in desktop mode - if (pick->getFilter().doesPickHUD() && DependencyManager::get()->isHMDMode()) { - PickCacheKey hudKey = { pick->getFilter().getHUDFlags(), QVector(), QVector() }; - if (!checkAndCompareCachedResults(mathematicalPick, results, res, hudKey)) { - PickResultPointer hudRes = pick->getHUDIntersection(mathematicalPick); - cacheResult(true, hudRes, hudKey, res, mathematicalPick, results, pick); - } - } - - if (pick->getMaxDistance() == 0.0f || (pick->getMaxDistance() > 0.0f && res->checkOrFilterAgainstMaxDistance(pick->getMaxDistance()))) { - pick->setPickResult(res); - } else { - pick->setPickResult(pick->getDefaultResult(mathematicalPick.toVariantMap())); - } - } -} - -template -QVariantMap PickManager::getPrevPickResult(const QUuid& uid) const { - auto pick = findPick(uid); - if (pick && pick->getPrevPickResult()) { - return pick->getPrevPickResult()->toVariantMap(); - } - return QVariantMap(); -} - -template -QUuid PickManager::addPick(const std::shared_ptr> pick) { - QUuid id = QUuid::createUuid(); - withWriteLock([&] { - _picks[id] = pick; - }); - return id; -} - -template -void PickManager::removePick(const QUuid& uid) { - withWriteLock([&] { - _picks.remove(uid); - }); -} - -template -void PickManager::enablePick(const QUuid& uid) const { - auto pick = findPick(uid); - if (pick) { - pick->enable(); - } -} - -template -void PickManager::disablePick(const QUuid& uid) const { - auto pick = findPick(uid); - if (pick) { - pick->disable(); - } -} - -template -void PickManager::setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { - auto pick = findPick(uid); - if (pick) { - pick->setPrecisionPicking(precisionPicking); - } -} - -template -void PickManager::setIgnoreItems(const QUuid& uid, const QVector& ignore) const { - auto pick = findPick(uid); - if (pick) { - pick->setIgnoreItems(ignore); - } -} - -template -void PickManager::setIncludeItems(const QUuid& uid, const QVector& include) const { - auto pick = findPick(uid); - if (pick) { - pick->setIncludeItems(include); - } -} - - #endif // hifi_PickManager_h \ No newline at end of file diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 3d423d5205..a716c9231e 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -125,7 +125,13 @@ QVector qVectorQUuidFromScriptValue(const QScriptValue& array); QScriptValue aaCubeToScriptValue(QScriptEngine* engine, const AACube& aaCube); void aaCubeFromScriptValue(const QScriptValue &object, AACube& aaCube); -class PickRay { +// MathPicks also have to overide operator== for their type +class MathPick { + virtual operator bool() const = 0; + virtual QVariantMap toVariantMap() const = 0; +}; + +class PickRay : public MathPick { public: PickRay() : origin(NAN), direction(NAN) { } PickRay(const QVariantMap& pickVariant) : origin(vec3FromVariant(pickVariant["origin"])), direction(vec3FromVariant(pickVariant["direction"])) {} @@ -133,13 +139,13 @@ public: glm::vec3 origin; glm::vec3 direction; - operator bool() const { + operator bool() const override { return !(glm::any(glm::isnan(origin)) || glm::any(glm::isnan(direction))); } bool operator==(const PickRay& other) const { return (origin == other.origin && direction == other.direction); } - QVariantMap toVariantMap() const { + QVariantMap toVariantMap() const override { QVariantMap pickRay; pickRay["origin"] = vec3toVariant(origin); pickRay["direction"] = vec3toVariant(direction); From 24ce09f91413122d6d92570b4abc75cad44a8223 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 20 Oct 2017 11:19:14 -0700 Subject: [PATCH 8/9] generalized pointer, laserpointermanager -> pointermanager --- interface/src/Application.cpp | 119 ++++++++--------- interface/src/Application.h | 9 -- interface/src/raypick/LaserPointer.cpp | 38 ++---- interface/src/raypick/LaserPointer.h | 33 ++--- interface/src/raypick/LaserPointerManager.cpp | 121 ------------------ interface/src/raypick/LaserPointerManager.h | 47 ------- .../LaserPointerScriptingInterface.cpp | 10 +- .../raypick/LaserPointerScriptingInterface.h | 20 +-- .../src/raypick/RayPickScriptingInterface.cpp | 23 ++-- libraries/pointers/src/pointers/PickManager.h | 4 +- libraries/pointers/src/pointers/Pointer.cpp | 39 ++++++ libraries/pointers/src/pointers/Pointer.h | 46 +++++++ .../pointers/src/pointers/PointerManager.cpp | 113 +++++++++++++++- .../pointers/src/pointers/PointerManager.h | 32 ++++- 14 files changed, 341 insertions(+), 313 deletions(-) delete mode 100644 interface/src/raypick/LaserPointerManager.cpp delete mode 100644 interface/src/raypick/LaserPointerManager.h create mode 100644 libraries/pointers/src/pointers/Pointer.cpp create mode 100644 libraries/pointers/src/pointers/Pointer.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a727c58f86..3476700904 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -193,6 +193,8 @@ #include #include +#include +#include #include #include #include @@ -690,6 +692,8 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); + DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -751,7 +755,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _notifiedPacketVersionMismatchThisDomain(false), _maxOctreePPS(maxOctreePacketsPerSecond.get()), _lastFaceTrackerUpdate(0), - _snapshotSound(nullptr) { + _snapshotSound(nullptr) +{ auto steamClient = PluginManager::getInstance()->getSteamClientPlugin(); setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); @@ -850,13 +855,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto audioIO = DependencyManager::get(); - audioIO->setPositionGetter([] { + audioIO->setPositionGetter([]{ auto avatarManager = DependencyManager::get(); auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr; return myAvatar ? myAvatar->getPositionForAudio() : Vectors::ZERO; }); - audioIO->setOrientationGetter([] { + audioIO->setOrientationGetter([]{ auto avatarManager = DependencyManager::get(); auto myAvatar = avatarManager ? avatarManager->getMyAvatar() : nullptr; @@ -867,7 +872,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo audioIO->handleRecordedAudioInput(frame->data); }); - connect(audioIO.data(), &AudioClient::inputReceived, [](const QByteArray& audio) { + connect(audioIO.data(), &AudioClient::inputReceived, [](const QByteArray& audio){ static auto recorder = DependencyManager::get(); if (recorder->isRecording()) { static const recording::FrameType AUDIO_FRAME_TYPE = recording::Frame::registerFrameType(AudioConstants::getAudioFrameName()); @@ -956,14 +961,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto addressManager = DependencyManager::get(); // use our MyAvatar position and quat for address manager path - addressManager->setPositionGetter([this] { return getMyAvatar()->getPosition(); }); - addressManager->setOrientationGetter([this] { return getMyAvatar()->getOrientation(); }); + addressManager->setPositionGetter([this]{ return getMyAvatar()->getPosition(); }); + addressManager->setOrientationGetter([this]{ return getMyAvatar()->getOrientation(); }); connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle); connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress); connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateThreadPoolCount); - connect(this, &Application::activeDisplayPluginChanged, this, []() { + connect(this, &Application::activeDisplayPluginChanged, this, [](){ qApp->setProperty(hifi::properties::HMD, qApp->isHMDMode()); }); connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateSystemTabletMode); @@ -973,7 +978,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get().data(), &AddressManager::storeCurrentAddress); auto scriptEngines = DependencyManager::get().data(); - scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine) { + scriptEngines->registerScriptInitializer([this](ScriptEnginePointer engine){ registerScriptEngineWithApplicationServices(engine); }); @@ -989,7 +994,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo }, Qt::QueuedConnection); connect(scriptEngines, &ScriptEngines::scriptLoadError, - scriptEngines, [](const QString& filename, const QString& error) { + scriptEngines, [](const QString& filename, const QString& error){ OffscreenUi::asyncWarning(nullptr, "Error Loading Script", filename + " failed to load."); }, Qt::QueuedConnection); @@ -1101,7 +1106,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } // add firstRun flag from settings to launch event - Setting::Handle firstRun{ Settings::firstRun, true }; + Setting::Handle firstRun { Settings::firstRun, true }; // once the settings have been loaded, check if we need to flip the default for UserActivityLogger auto& userActivityLogger = UserActivityLogger::getInstance(); @@ -1202,42 +1207,42 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo static int lastKey = Qt::Key_unknown; bool navAxis = false; switch (actionEnum) { - case Action::UI_NAV_VERTICAL: - navAxis = true; - if (state > 0.0f) { - key = Qt::Key_Up; - } else if (state < 0.0f) { - key = Qt::Key_Down; - } - break; + case Action::UI_NAV_VERTICAL: + navAxis = true; + if (state > 0.0f) { + key = Qt::Key_Up; + } else if (state < 0.0f) { + key = Qt::Key_Down; + } + break; - case Action::UI_NAV_LATERAL: - navAxis = true; - if (state > 0.0f) { - key = Qt::Key_Right; - } else if (state < 0.0f) { - key = Qt::Key_Left; - } - break; + case Action::UI_NAV_LATERAL: + navAxis = true; + if (state > 0.0f) { + key = Qt::Key_Right; + } else if (state < 0.0f) { + key = Qt::Key_Left; + } + break; - case Action::UI_NAV_GROUP: - navAxis = true; - if (state > 0.0f) { - key = Qt::Key_Tab; - } else if (state < 0.0f) { - key = Qt::Key_Backtab; - } - break; + case Action::UI_NAV_GROUP: + navAxis = true; + if (state > 0.0f) { + key = Qt::Key_Tab; + } else if (state < 0.0f) { + key = Qt::Key_Backtab; + } + break; - case Action::UI_NAV_BACK: - key = Qt::Key_Escape; - break; + case Action::UI_NAV_BACK: + key = Qt::Key_Escape; + break; - case Action::UI_NAV_SELECT: - key = Qt::Key_Return; - break; - default: - break; + case Action::UI_NAV_SELECT: + key = Qt::Key_Return; + break; + default: + break; } auto window = tabletScriptingInterface->getTabletWindow(); @@ -1376,8 +1381,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo QTimer* settingsTimer = new QTimer(); - moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer] { - connect(qApp, &Application::beforeAboutToQuit, [this, settingsTimer] { + moveToNewNamedThread(settingsTimer, "Settings Thread", [this, settingsTimer]{ + connect(qApp, &Application::beforeAboutToQuit, [this, settingsTimer]{ // Disconnect the signal from the save settings QObject::disconnect(settingsTimer, &QTimer::timeout, this, &Application::saveSettings); // Stop the settings timer @@ -1439,7 +1444,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Now that menu is initialized we can sync myAvatar with it's state. myAvatar->updateMotionBehaviorFromMenu(); - // FIXME spacemouse code still needs cleanup +// FIXME spacemouse code still needs cleanup #if 0 // the 3Dconnexion device wants to be initialized after a window is displayed. SpacemouseManager::getInstance().init(); @@ -1448,7 +1453,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // If the user clicks an an entity, we will check that it's an unlocked web entity, and if so, set the focus to it auto entityScriptingInterface = DependencyManager::get(); connect(entityScriptingInterface.data(), &EntityScriptingInterface::clickDownOnEntity, - [this](const EntityItemID& entityItemID, const PointerEvent& event) { + [this](const EntityItemID& entityItemID, const PointerEvent& event) { if (getEntities()->wantsKeyboardFocus(entityItemID)) { setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID); setKeyboardFocusEntity(entityItemID); @@ -1663,8 +1668,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo totalServerOctreeElements += i->second.getTotalElements(); } - properties["local_octree_elements"] = (qint64)OctreeElement::getInternalNodeCount(); - properties["server_octree_elements"] = (qint64)totalServerOctreeElements; + properties["local_octree_elements"] = (qint64) OctreeElement::getInternalNodeCount(); + properties["server_octree_elements"] = (qint64) totalServerOctreeElements; properties["active_display_plugin"] = getActiveDisplayPlugin()->getName(); properties["using_hmd"] = isHMDMode(); @@ -1685,7 +1690,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (_autoSwitchDisplayModeSupportedHMDPlugin) { if (getActiveDisplayPlugin() != _autoSwitchDisplayModeSupportedHMDPlugin && !_autoSwitchDisplayModeSupportedHMDPlugin->isSessionActive()) { - startHMDStandBySession(); + startHMDStandBySession(); } // Poll periodically to check whether the user has worn HMD or not. Switch Display mode accordingly. // If the user wears HMD then switch to VR mode. If the user removes HMD then switch to Desktop mode. @@ -1729,7 +1734,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(checkNearbyAvatarsTimer, &QTimer::timeout, this, [this]() { auto avatarManager = DependencyManager::get(); int nearbyAvatars = avatarManager->numberOfAvatarsInRange(avatarManager->getMyAvatar()->getPosition(), - NEARBY_AVATAR_RADIUS_METERS) - 1; + NEARBY_AVATAR_RADIUS_METERS) - 1; if (nearbyAvatars != lastCountOfNearbyAvatars) { lastCountOfNearbyAvatars = nearbyAvatars; UserActivityLogger::getInstance().logAction("nearby_avatars", { { "count", nearbyAvatars } }); @@ -1817,15 +1822,15 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged); - _pickManager.setShouldPickHUDOperator([&]() { return DependencyManager::get()->isHMDMode(); }); + DependencyManager::get()->setShouldPickHUDOperator([&]() { return DependencyManager::get()->isHMDMode(); }); // Setup the mouse ray pick and related operators - DependencyManager::get()->setMouseRayPickID(_pickManager.addPick(RAY, std::make_shared( + DependencyManager::get()->setMouseRayPickID(DependencyManager::get()->addPick(RAY, std::make_shared( PickFilter(RayPickScriptingInterface::PICK_ENTITIES() | RayPickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true))); DependencyManager::get()->setMouseRayPickResultOperator([&](QUuid rayPickID) { RayToEntityIntersectionResult entityResult; entityResult.intersects = false; - QVariantMap result = _pickManager.getPrevPickResult(rayPickID); + QVariantMap result = DependencyManager::get()->getPrevPickResult(rayPickID); if (result["type"].isValid()) { entityResult.intersects = result["type"] != RayPickScriptingInterface::INTERSECTED_NONE(); if (entityResult.intersects) { @@ -1839,7 +1844,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo return entityResult; }); DependencyManager::get()->setSetPrecisionPickingOperator([&](QUuid rayPickID, bool value) { - _pickManager.setPrecisionPicking(rayPickID, value); + DependencyManager::get()->setPrecisionPicking(rayPickID, value); }); qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); @@ -4912,12 +4917,12 @@ void Application::update(float deltaTime) { // TODO: break these out into distinct perfTimers when they prove interesting { PROFILE_RANGE(app, "PickManager"); - _pickManager.update(); + DependencyManager::get()->update(); } { - PROFILE_RANGE(app, "LaserPointerManager"); - _laserPointerManager.update(); + PROFILE_RANGE(app, "PointerManager"); + DependencyManager::get()->update(); } { diff --git a/interface/src/Application.h b/interface/src/Application.h index a70aaf93c7..7075745a39 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -70,9 +70,6 @@ #include "ui/overlays/Overlays.h" #include "UndoStackScriptingInterface.h" -#include -#include "raypick/LaserPointerManager.h" - #include #include #include @@ -298,9 +295,6 @@ public: QUrl getAvatarOverrideUrl() { return _avatarOverrideUrl; } bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; } - LaserPointerManager& getLaserPointerManager() { return _laserPointerManager; } - PickManager& getPickManager() { return _pickManager; } - signals: void svoImportRequested(const QString& url); @@ -713,9 +707,6 @@ private: bool _saveAvatarOverrideUrl { false }; QObject* _renderEventHandler{ nullptr }; - PickManager _pickManager; - LaserPointerManager _laserPointerManager; - friend class RenderEventHandler; }; #endif // hifi_Application_h diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 0a8506ee28..3100a18dde 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -13,18 +13,20 @@ #include "Application.h" #include "avatar/AvatarManager.h" +#include +#include +#include "RayPickScriptingInterface.h" + LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) : + Pointer(DependencyManager::get()->createRayPick(rayProps)), _renderingEnabled(enabled), _renderStates(renderStates), _defaultRenderStates(defaultRenderStates), _faceAvatar(faceAvatar), _centerEndY(centerEndY), - _lockEnd(lockEnd), - _rayPickUID(DependencyManager::get()->createRayPick(rayProps)) + _lockEnd(lockEnd) { - - for (auto& state : _renderStates) { if (!enabled || state.first != _currentRenderState) { disableRenderState(state.second); @@ -38,8 +40,6 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende } LaserPointer::~LaserPointer() { - qApp->getPickManager().removePick(_rayPickUID); - for (auto& renderState : _renderStates) { renderState.second.deleteOverlays(); } @@ -49,14 +49,14 @@ LaserPointer::~LaserPointer() { } void LaserPointer::enable() { - qApp->getPickManager().enablePick(_rayPickUID); + Pointer::enable(); withWriteLock([&] { _renderingEnabled = true; }); } void LaserPointer::disable() { - qApp->getPickManager().disablePick(_rayPickUID); + Pointer::disable(); withWriteLock([&] { _renderingEnabled = false; if (!_currentRenderState.empty()) { @@ -100,10 +100,6 @@ void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant& } } -const QVariantMap LaserPointer::getPrevRayPickResult() { - return qApp->getPickManager().getPrevPickResult(_rayPickUID); -} - void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState) { if (!renderState.getStartID().isNull()) { QVariantMap startProps; @@ -197,7 +193,7 @@ void LaserPointer::disableRenderState(const RenderState& renderState) { void LaserPointer::update() { // This only needs to be a read lock because update won't change any of the properties that can be modified from scripts withReadLock([&] { - QVariantMap prevRayPickResult = qApp->getPickManager().getPrevPickResult(_rayPickUID); + QVariantMap prevRayPickResult = DependencyManager::get()->getPrevPickResult(_pickUID); IntersectionType type = IntersectionType(prevRayPickResult["type"].toInt()); PickRay pickRay = PickRay(prevRayPickResult["searchRay"].toMap()); QUuid uid = prevRayPickResult["objectID"].toUuid(); @@ -216,13 +212,9 @@ void LaserPointer::update() { }); } -void LaserPointer::setPrecisionPicking(const bool precisionPicking) { - qApp->getPickManager().setPrecisionPicking(_rayPickUID, precisionPicking); -} - -void LaserPointer::setLaserLength(const float laserLength) { +void LaserPointer::setLength(const float length) { withWriteLock([&] { - _laserLength = laserLength; + _laserLength = length; }); } @@ -232,14 +224,6 @@ void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay) { }); } -void LaserPointer::setIgnoreItems(const QVector& ignoreItems) const { - qApp->getPickManager().setIgnoreItems(_rayPickUID, ignoreItems); -} - -void LaserPointer::setIncludeItems(const QVector& includeItems) const { - qApp->getPickManager().setIncludeItems(_rayPickUID, includeItems); -} - RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID) : _startID(startID), _pathID(pathID), _endID(endID) { diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index d6fcf20b9d..a0fd1b2417 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -14,12 +14,10 @@ #include #include -#include -#include - #include "ui/overlays/Overlay.h" -#include "RayPickScriptingInterface.h" +#include +#include class RenderState { @@ -45,12 +43,9 @@ private: bool _endIgnoreRays; }; - -class LaserPointer : public ReadWriteLockable { +class LaserPointer : public Pointer { public: - using Pointer = std::shared_ptr; - typedef std::unordered_map RenderStateMap; typedef std::unordered_map> DefaultRenderStateMap; @@ -58,23 +53,17 @@ public: const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); ~LaserPointer(); - QUuid getRayUID() { return _rayPickUID; } - void enable(); - void disable(); - const QVariantMap getPrevRayPickResult(); + void enable() override; + void disable() override; - void setRenderState(const std::string& state); + void setRenderState(const std::string& state) override; // You cannot use editRenderState to change the overlay type of any part of the laser pointer. You can only edit the properties of the existing overlays. - void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); + void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) override; - void setPrecisionPicking(const bool precisionPicking); - void setLaserLength(const float laserLength); - void setLockEndUUID(QUuid objectID, const bool isOverlay); + void setLength(const float length) override; + void setLockEndUUID(QUuid objectID, const bool isOverlay) override; - void setIgnoreItems(const QVector& ignoreItems) const; - void setIncludeItems(const QVector& includeItems) const; - - void update(); + void update() override; private: bool _renderingEnabled; @@ -87,8 +76,6 @@ private: bool _lockEnd; std::pair _objectLockEnd { std::pair(QUuid(), false)}; - const QUuid _rayPickUID; - void updateRenderStateOverlay(const OverlayID& id, const QVariant& props); void updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState); void disableRenderState(const RenderState& renderState); diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp deleted file mode 100644 index a300a418a7..0000000000 --- a/interface/src/raypick/LaserPointerManager.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// -// LaserPointerManager.cpp -// interface/src/raypick -// -// Created by Sam Gondelman 7/11/2017 -// 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 "LaserPointerManager.h" - -QUuid LaserPointerManager::createLaserPointer(const QVariant& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates, - const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { - QUuid result; - std::shared_ptr laserPointer = std::make_shared(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); - if (!laserPointer->getRayUID().isNull()) { - result = QUuid::createUuid(); - withWriteLock([&] { _laserPointers[result] = laserPointer; }); - } - return result; -} - - -LaserPointer::Pointer LaserPointerManager::find(const QUuid& uid) const { - return resultWithReadLock([&] { - auto itr = _laserPointers.find(uid); - if (itr != _laserPointers.end()) { - return *itr; - } - return LaserPointer::Pointer(); - }); -} - - -void LaserPointerManager::removeLaserPointer(const QUuid& uid) { - withWriteLock([&] { - _laserPointers.remove(uid); - }); -} - -void LaserPointerManager::enableLaserPointer(const QUuid& uid) const { - auto laserPointer = find(uid); - if (laserPointer) { - laserPointer->enable(); - } -} - -void LaserPointerManager::disableLaserPointer(const QUuid& uid) const { - auto laserPointer = find(uid); - if (laserPointer) { - laserPointer->disable(); - } -} - -void LaserPointerManager::setRenderState(const QUuid& uid, const std::string& renderState) const { - auto laserPointer = find(uid); - if (laserPointer) { - laserPointer->setRenderState(renderState); - } -} - -void LaserPointerManager::editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const { - auto laserPointer = find(uid); - if (laserPointer) { - laserPointer->editRenderState(state, startProps, pathProps, endProps); - } -} - -const QVariantMap LaserPointerManager::getPrevRayPickResult(const QUuid& uid) const { - auto laserPointer = find(uid); - if (laserPointer) { - return laserPointer->getPrevRayPickResult(); - } - return QVariantMap(); -} - -void LaserPointerManager::update() { - auto cachedLaserPointers = resultWithReadLock>>([&] { - return _laserPointers.values(); - }); - - for (const auto& laserPointer : cachedLaserPointers) { - laserPointer->update(); - } -} - -void LaserPointerManager::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const { - auto laserPointer = find(uid); - if (laserPointer) { - laserPointer->setPrecisionPicking(precisionPicking); - } -} - -void LaserPointerManager::setLaserLength(const QUuid& uid, const float laserLength) const { - auto laserPointer = find(uid); - if (laserPointer) { - laserPointer->setLaserLength(laserLength); - } -} - -void LaserPointerManager::setIgnoreItems(const QUuid& uid, const QVector& ignoreEntities) const { - auto laserPointer = find(uid); - if (laserPointer) { - laserPointer->setIgnoreItems(ignoreEntities); - } -} - -void LaserPointerManager::setIncludeItems(const QUuid& uid, const QVector& includeEntities) const { - auto laserPointer = find(uid); - if (laserPointer) { - laserPointer->setIncludeItems(includeEntities); - } -} - -void LaserPointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const { - auto laserPointer = find(uid); - if (laserPointer) { - laserPointer->setLockEndUUID(objectID, isOverlay); - } -} diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h deleted file mode 100644 index 547f7cc785..0000000000 --- a/interface/src/raypick/LaserPointerManager.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// LaserPointerManager.h -// interface/src/raypick -// -// Created by Sam Gondelman 7/11/2017 -// 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_LaserPointerManager_h -#define hifi_LaserPointerManager_h - -#include -#include - -#include - -#include "LaserPointer.h" - -class LaserPointerManager : protected ReadWriteLockable { - -public: - QUuid createLaserPointer(const QVariant& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates, - const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); - void removeLaserPointer(const QUuid& uid); - void enableLaserPointer(const QUuid& uid) const; - void disableLaserPointer(const QUuid& uid) const; - void setRenderState(const QUuid& uid, const std::string& renderState) const; - void editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const; - const QVariantMap getPrevRayPickResult(const QUuid& uid) const; - - void setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const; - void setLaserLength(const QUuid& uid, const float laserLength) const; - 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 update(); - -private: - LaserPointer::Pointer find(const QUuid& uid) const; - QHash> _laserPointers; -}; - -#endif // hifi_LaserPointerManager_h diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index 4ff917d8c5..779f9ff605 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -15,11 +15,13 @@ #include +#include "Application.h" + void LaserPointerScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) const { - qApp->getLaserPointerManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems)); + DependencyManager::get()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems)); } void LaserPointerScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) const { - qApp->getLaserPointerManager().setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems)); + DependencyManager::get()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems)); } QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) const { @@ -74,7 +76,7 @@ QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& propert } } - return qApp->getLaserPointerManager().createLaserPointer(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); + return DependencyManager::get()->addPointer(std::make_shared(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled)); } void LaserPointerScriptingInterface::editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const { @@ -95,7 +97,7 @@ void LaserPointerScriptingInterface::editRenderState(const QUuid& uid, const QSt endProps = propMap["end"]; } - qApp->getLaserPointerManager().editRenderState(uid, renderState.toStdString(), startProps, pathProps, endProps); + DependencyManager::get()->editRenderState(uid, renderState.toStdString(), startProps, pathProps, endProps); } RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) { diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index d51420a112..b2e46f66d6 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -14,7 +14,9 @@ #include #include "DependencyManager.h" -#include "Application.h" +#include + +#include "LaserPointer.h" class LaserPointerScriptingInterface : public QObject, public Dependency { Q_OBJECT @@ -22,19 +24,19 @@ class LaserPointerScriptingInterface : public QObject, public Dependency { public slots: Q_INVOKABLE QUuid createLaserPointer(const QVariant& properties) const; - Q_INVOKABLE void enableLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().enableLaserPointer(uid); } - Q_INVOKABLE void disableLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().disableLaserPointer(uid); } - Q_INVOKABLE void removeLaserPointer(const QUuid& uid) const { qApp->getLaserPointerManager().removeLaserPointer(uid); } + Q_INVOKABLE void enableLaserPointer(const QUuid& uid) const { DependencyManager::get()->enablePointer(uid); } + Q_INVOKABLE void disableLaserPointer(const QUuid& uid) const { DependencyManager::get()->disablePointer(uid); } + Q_INVOKABLE void removeLaserPointer(const QUuid& uid) const { DependencyManager::get()->removePointer(uid); } Q_INVOKABLE void editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const; - Q_INVOKABLE void setRenderState(const QUuid& uid, const QString& renderState) const { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); } - Q_INVOKABLE QVariantMap getPrevRayPickResult(QUuid uid) const { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); } + Q_INVOKABLE void setRenderState(const QUuid& uid, const QString& renderState) const { DependencyManager::get()->setRenderState(uid, renderState.toStdString()); } + Q_INVOKABLE QVariantMap getPrevRayPickResult(QUuid uid) const { return DependencyManager::get()->getPrevRayPickResult(uid); } - Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { qApp->getLaserPointerManager().setPrecisionPicking(uid, precisionPicking); } - Q_INVOKABLE void setLaserLength(const QUuid& uid, float laserLength) const { qApp->getLaserPointerManager().setLaserLength(uid, laserLength); } + Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { DependencyManager::get()->setPrecisionPicking(uid, precisionPicking); } + Q_INVOKABLE void setLaserLength(const QUuid& uid, float laserLength) const { DependencyManager::get()->setLength(uid, laserLength); } 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 { DependencyManager::get()->setLockEndUUID(uid, objectID, isOverlay); } private: static RenderState buildRenderState(const QVariantMap& propMap); diff --git a/interface/src/raypick/RayPickScriptingInterface.cpp b/interface/src/raypick/RayPickScriptingInterface.cpp index de67fdde0f..8913138c36 100644 --- a/interface/src/raypick/RayPickScriptingInterface.cpp +++ b/interface/src/raypick/RayPickScriptingInterface.cpp @@ -13,7 +13,8 @@ #include #include "GLMHelpers.h" -#include "Application.h" + +#include #include "StaticRayPick.h" #include "JointRayPick.h" @@ -52,10 +53,10 @@ QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) { dirOffset = vec3FromVariant(propMap["dirOffset"]); } - return qApp->getPickManager().addPick(RAY, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); + return DependencyManager::get()->addPick(RAY, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); } else { - return qApp->getPickManager().addPick(RAY, std::make_shared(filter, maxDistance, enabled)); + return DependencyManager::get()->addPick(RAY, std::make_shared(filter, maxDistance, enabled)); } } else if (propMap["position"].isValid()) { glm::vec3 position = vec3FromVariant(propMap["position"]); @@ -65,36 +66,36 @@ QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) { direction = vec3FromVariant(propMap["direction"]); } - return qApp->getPickManager().addPick(RAY, std::make_shared(position, direction, filter, maxDistance, enabled)); + return DependencyManager::get()->addPick(RAY, std::make_shared(position, direction, filter, maxDistance, enabled)); } return QUuid(); } void RayPickScriptingInterface::enableRayPick(const QUuid& uid) { - qApp->getPickManager().enablePick(uid); + DependencyManager::get()->enablePick(uid); } void RayPickScriptingInterface::disableRayPick(const QUuid& uid) { - qApp->getPickManager().disablePick(uid); + DependencyManager::get()->disablePick(uid); } void RayPickScriptingInterface::removeRayPick(const QUuid& uid) { - qApp->getPickManager().removePick(uid); + DependencyManager::get()->removePick(uid); } QVariantMap RayPickScriptingInterface::getPrevRayPickResult(const QUuid& uid) { - return qApp->getPickManager().getPrevPickResult(uid); + return DependencyManager::get()->getPrevPickResult(uid); } void RayPickScriptingInterface::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) { - qApp->getPickManager().setPrecisionPicking(uid, precisionPicking); + DependencyManager::get()->setPrecisionPicking(uid, precisionPicking); } void RayPickScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) { - qApp->getPickManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems)); + DependencyManager::get()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems)); } void RayPickScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) { - qApp->getPickManager().setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems)); + DependencyManager::get()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems)); } diff --git a/libraries/pointers/src/pointers/PickManager.h b/libraries/pointers/src/pointers/PickManager.h index 9b2f19a63a..07c8d914f3 100644 --- a/libraries/pointers/src/pointers/PickManager.h +++ b/libraries/pointers/src/pointers/PickManager.h @@ -10,6 +10,7 @@ #include +#include #include "RegisteredMetaTypes.h" #include "Pick.h" @@ -20,7 +21,8 @@ enum PickType { STYLUS }; -class PickManager : protected ReadWriteLockable { +class PickManager : public Dependency, protected ReadWriteLockable { + SINGLETON_DEPENDENCY public: PickManager(); diff --git a/libraries/pointers/src/pointers/Pointer.cpp b/libraries/pointers/src/pointers/Pointer.cpp new file mode 100644 index 0000000000..6ba8c6072c --- /dev/null +++ b/libraries/pointers/src/pointers/Pointer.cpp @@ -0,0 +1,39 @@ +// +// Created by Sam Gondelman 10/19/2017 +// 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 "Pointer.h" + +#include +#include "PickManager.h" + +Pointer::~Pointer() { + DependencyManager::get()->removePick(_pickUID); +} + +void Pointer::enable() { + DependencyManager::get()->enablePick(_pickUID); +} + +void Pointer::disable() { + DependencyManager::get()->disablePick(_pickUID); +} + +const QVariantMap Pointer::getPrevPickResult() { + return DependencyManager::get()->getPrevPickResult(_pickUID); +} + +void Pointer::setPrecisionPicking(const bool precisionPicking) { + DependencyManager::get()->setPrecisionPicking(_pickUID, precisionPicking); +} + +void Pointer::setIgnoreItems(const QVector& ignoreItems) const { + DependencyManager::get()->setIgnoreItems(_pickUID, ignoreItems); +} + +void Pointer::setIncludeItems(const QVector& includeItems) const { + DependencyManager::get()->setIncludeItems(_pickUID, includeItems); +} \ No newline at end of file diff --git a/libraries/pointers/src/pointers/Pointer.h b/libraries/pointers/src/pointers/Pointer.h new file mode 100644 index 0000000000..4a105f8a92 --- /dev/null +++ b/libraries/pointers/src/pointers/Pointer.h @@ -0,0 +1,46 @@ +// +// Created by Sam Gondelman 10/17/2017 +// 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_Pointer_h +#define hifi_Pointer_h + +#include +#include +#include + +#include + +class Pointer : protected ReadWriteLockable { +public: + Pointer(const QUuid& uid) : _pickUID(uid) {} + + virtual ~Pointer(); + + virtual void enable(); + virtual void disable(); + virtual const QVariantMap getPrevPickResult(); + + virtual void setRenderState(const std::string& state) = 0; + virtual void editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) = 0; + + virtual void setPrecisionPicking(const bool precisionPicking); + virtual void setIgnoreItems(const QVector& ignoreItems) const; + virtual void setIncludeItems(const QVector& includeItems) const; + + // Pointers can choose to implement these + virtual void setLength(const float length) {} + virtual void setLockEndUUID(QUuid objectID, const bool isOverlay) {} + + virtual void update() = 0; + + QUuid getRayUID() { return _pickUID; } + +protected: + const QUuid _pickUID; +}; + +#endif // hifi_Pick_h diff --git a/libraries/pointers/src/pointers/PointerManager.cpp b/libraries/pointers/src/pointers/PointerManager.cpp index 63bd983420..f2c2756d6f 100644 --- a/libraries/pointers/src/pointers/PointerManager.cpp +++ b/libraries/pointers/src/pointers/PointerManager.cpp @@ -1,6 +1,115 @@ +// +// Created by Bradley Austin Davis on 2017/10/16 +// 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 +// + #include "PointerManager.h" -PointerManager::PointerManager() { - +std::shared_ptr PointerManager::find(const QUuid& uid) const { + return resultWithReadLock>([&] { + auto itr = _pointers.find(uid); + if (itr != _pointers.end()) { + return *itr; + } + return std::shared_ptr(); + }); } +QUuid PointerManager::addPointer(std::shared_ptr pointer) { + QUuid result; + if (!pointer->getRayUID().isNull()) { + result = QUuid::createUuid(); + withWriteLock([&] { _pointers[result] = pointer; }); + } + return result; +} + +void PointerManager::removePointer(const QUuid& uid) { + withWriteLock([&] { + _pointers.remove(uid); + }); +} + +void PointerManager::enablePointer(const QUuid& uid) const { + auto pointer = find(uid); + if (pointer) { + pointer->enable(); + } +} + +void PointerManager::disablePointer(const QUuid& uid) const { + auto pointer = find(uid); + if (pointer) { + pointer->disable(); + } +} + +void PointerManager::setRenderState(const QUuid& uid, const std::string& renderState) const { + auto pointer = find(uid); + if (pointer) { + pointer->setRenderState(renderState); + } +} + +void PointerManager::editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const { + auto pointer = find(uid); + if (pointer) { + pointer->editRenderState(state, startProps, pathProps, endProps); + } +} + +const QVariantMap PointerManager::getPrevRayPickResult(const QUuid& uid) const { + auto pointer = find(uid); + if (pointer) { + return pointer->getPrevPickResult(); + } + return QVariantMap(); +} + +void PointerManager::update() { + auto cachedPointers = resultWithReadLock>>([&] { + return _pointers.values(); + }); + + for (const auto& pointer : cachedPointers) { + pointer->update(); + } +} + +void PointerManager::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const { + auto pointer = find(uid); + if (pointer) { + pointer->setPrecisionPicking(precisionPicking); + } +} + +void PointerManager::setIgnoreItems(const QUuid& uid, const QVector& ignoreEntities) const { + auto pointer = find(uid); + if (pointer) { + pointer->setIgnoreItems(ignoreEntities); + } +} + +void PointerManager::setIncludeItems(const QUuid& uid, const QVector& includeEntities) const { + auto pointer = find(uid); + if (pointer) { + pointer->setIncludeItems(includeEntities); + } +} + +void PointerManager::setLength(const QUuid& uid, const float length) const { + auto pointer = find(uid); + if (pointer) { + pointer->setLength(length); + } +} + +void PointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const { + auto pointer = find(uid); + if (pointer) { + pointer->setLockEndUUID(objectID, isOverlay); + } +} diff --git a/libraries/pointers/src/pointers/PointerManager.h b/libraries/pointers/src/pointers/PointerManager.h index 16f854bff5..1841e66f7b 100644 --- a/libraries/pointers/src/pointers/PointerManager.h +++ b/libraries/pointers/src/pointers/PointerManager.h @@ -11,11 +11,39 @@ #include #include -class PointerManager : public QObject, public Dependency { +#include +#include + +#include + +#include "Pointer.h" + +class PointerManager : public QObject, public Dependency, protected ReadWriteLockable{ Q_OBJECT SINGLETON_DEPENDENCY public: - PointerManager(); + PointerManager() {} + + QUuid addPointer(std::shared_ptr pointer); + void removePointer(const QUuid& uid); + void enablePointer(const QUuid& uid) const; + void disablePointer(const QUuid& uid) const; + void setRenderState(const QUuid& uid, const std::string& renderState) const; + void editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const; + const QVariantMap getPrevRayPickResult(const QUuid& uid) const; + + void setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const; + void setIgnoreItems(const QUuid& uid, const QVector& ignoreEntities) const; + void setIncludeItems(const QUuid& uid, const QVector& includeEntities) const; + + void setLength(const QUuid& uid, const float length) const; + void setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const; + + void update(); + +private: + std::shared_ptr find(const QUuid& uid) const; + QHash> _pointers; signals: void triggerBegin(const QUuid& id, const PointerEvent& pointerEvent); From fb969964f3663131c88925a2571427a590d46fe4 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 20 Oct 2017 14:37:10 -0700 Subject: [PATCH 9/9] generalized scripting interfaces --- interface/src/Application.cpp | 12 +- .../LaserPointerScriptingInterface.cpp | 105 +------------ .../raypick/LaserPointerScriptingInterface.h | 7 +- .../src/raypick/PickScriptingInterface.cpp | 107 ++++++++++++++ .../src/raypick/PickScriptingInterface.h | 65 ++++++++ .../src/raypick/PointerScriptingInterface.cpp | 139 ++++++++++++++++++ .../src/raypick/PointerScriptingInterface.h | 46 ++++++ .../src/raypick/RayPickScriptingInterface.cpp | 50 +------ .../src/raypick/RayPickScriptingInterface.h | 31 +--- libraries/pointers/src/pointers/Pick.h | 7 + .../pointers/src/pointers/PickManager.cpp | 6 +- libraries/pointers/src/pointers/PickManager.h | 11 +- .../pointers/src/pointers/PointerManager.cpp | 2 +- .../pointers/src/pointers/PointerManager.h | 2 +- .../controllers/controllerDispatcher.js | 12 +- .../controllerModules/farActionGrabEntity.js | 8 +- .../controllerModules/farTrigger.js | 2 +- .../controllerModules/hudOverlayPointer.js | 2 +- .../controllerModules/inEditMode.js | 6 +- .../controllerModules/overlayLaserInput.js | 4 +- .../controllers/controllerModules/teleport.js | 10 +- .../controllerModules/webEntityLaserInput.js | 4 +- scripts/system/controllers/grab.js | 8 +- scripts/system/libraries/touchEventUtils.js | 2 +- 24 files changed, 417 insertions(+), 231 deletions(-) create mode 100644 interface/src/raypick/PickScriptingInterface.cpp create mode 100644 interface/src/raypick/PickScriptingInterface.h create mode 100644 interface/src/raypick/PointerScriptingInterface.cpp create mode 100644 interface/src/raypick/PointerScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3476700904..26e659e118 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -197,6 +197,8 @@ #include #include #include +#include +#include #include #include @@ -696,6 +698,8 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); + DependencyManager::set(); return previousSessionCrashed; } @@ -1825,14 +1829,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo DependencyManager::get()->setShouldPickHUDOperator([&]() { return DependencyManager::get()->isHMDMode(); }); // Setup the mouse ray pick and related operators - DependencyManager::get()->setMouseRayPickID(DependencyManager::get()->addPick(RAY, std::make_shared( - PickFilter(RayPickScriptingInterface::PICK_ENTITIES() | RayPickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true))); + DependencyManager::get()->setMouseRayPickID(DependencyManager::get()->addPick(PickQuery::Ray, std::make_shared( + PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true))); DependencyManager::get()->setMouseRayPickResultOperator([&](QUuid rayPickID) { RayToEntityIntersectionResult entityResult; entityResult.intersects = false; QVariantMap result = DependencyManager::get()->getPrevPickResult(rayPickID); if (result["type"].isValid()) { - entityResult.intersects = result["type"] != RayPickScriptingInterface::INTERSECTED_NONE(); + entityResult.intersects = result["type"] != PickScriptingInterface::INTERSECTED_NONE(); if (entityResult.intersects) { entityResult.intersection = vec3FromVariant(result["intersection"]); entityResult.distance = result["distance"].toFloat(); @@ -5798,6 +5802,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerGlobalObject("RayPick", DependencyManager::get().data()); scriptEngine->registerGlobalObject("LaserPointers", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("Picks", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("Pointers", DependencyManager::get().data()); // Caches scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get().data()); diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index 779f9ff605..8f8f9d921a 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -15,6 +15,7 @@ #include +#include "PointerScriptingInterface.h" #include "Application.h" void LaserPointerScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) const { @@ -25,109 +26,9 @@ void LaserPointerScriptingInterface::setIncludeItems(const QUuid& uid, const QSc } QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& properties) const { - QVariantMap propertyMap = properties.toMap(); - - bool faceAvatar = false; - if (propertyMap["faceAvatar"].isValid()) { - faceAvatar = propertyMap["faceAvatar"].toBool(); - } - - bool centerEndY = true; - if (propertyMap["centerEndY"].isValid()) { - centerEndY = propertyMap["centerEndY"].toBool(); - } - - bool lockEnd = false; - if (propertyMap["lockEnd"].isValid()) { - lockEnd = propertyMap["lockEnd"].toBool(); - } - - bool enabled = false; - if (propertyMap["enabled"].isValid()) { - enabled = propertyMap["enabled"].toBool(); - } - - LaserPointer::RenderStateMap renderStates; - if (propertyMap["renderStates"].isValid()) { - QList renderStateVariants = propertyMap["renderStates"].toList(); - for (QVariant& renderStateVariant : renderStateVariants) { - if (renderStateVariant.isValid()) { - QVariantMap renderStateMap = renderStateVariant.toMap(); - if (renderStateMap["name"].isValid()) { - std::string name = renderStateMap["name"].toString().toStdString(); - renderStates[name] = buildRenderState(renderStateMap); - } - } - } - } - - LaserPointer::DefaultRenderStateMap defaultRenderStates; - if (propertyMap["defaultRenderStates"].isValid()) { - QList renderStateVariants = propertyMap["defaultRenderStates"].toList(); - for (QVariant& renderStateVariant : renderStateVariants) { - if (renderStateVariant.isValid()) { - QVariantMap renderStateMap = renderStateVariant.toMap(); - if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) { - std::string name = renderStateMap["name"].toString().toStdString(); - float distance = renderStateMap["distance"].toFloat(); - defaultRenderStates[name] = std::pair(distance, buildRenderState(renderStateMap)); - } - } - } - } - - return DependencyManager::get()->addPointer(std::make_shared(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled)); + return DependencyManager::get()->createLaserPointer(properties); } void LaserPointerScriptingInterface::editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const { - QVariantMap propMap = properties.toMap(); - - QVariant startProps; - if (propMap["start"].isValid()) { - startProps = propMap["start"]; - } - - QVariant pathProps; - if (propMap["path"].isValid()) { - pathProps = propMap["path"]; - } - - QVariant endProps; - if (propMap["end"].isValid()) { - endProps = propMap["end"]; - } - - DependencyManager::get()->editRenderState(uid, renderState.toStdString(), startProps, pathProps, endProps); -} - -RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) { - QUuid startID; - if (propMap["start"].isValid()) { - QVariantMap startMap = propMap["start"].toMap(); - if (startMap["type"].isValid()) { - startMap.remove("visible"); - startID = qApp->getOverlays().addOverlay(startMap["type"].toString(), startMap); - } - } - - QUuid pathID; - if (propMap["path"].isValid()) { - QVariantMap pathMap = propMap["path"].toMap(); - // right now paths must be line3ds - if (pathMap["type"].isValid() && pathMap["type"].toString() == "line3d") { - pathMap.remove("visible"); - pathID = qApp->getOverlays().addOverlay(pathMap["type"].toString(), pathMap); - } - } - - QUuid endID; - if (propMap["end"].isValid()) { - QVariantMap endMap = propMap["end"].toMap(); - if (endMap["type"].isValid()) { - endMap.remove("visible"); - endID = qApp->getOverlays().addOverlay(endMap["type"].toString(), endMap); - } - } - - return RenderState(startID, pathID, endID); + DependencyManager::get()->editRenderState(uid, renderState, properties); } \ No newline at end of file diff --git a/interface/src/raypick/LaserPointerScriptingInterface.h b/interface/src/raypick/LaserPointerScriptingInterface.h index b2e46f66d6..1116da1528 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.h +++ b/interface/src/raypick/LaserPointerScriptingInterface.h @@ -16,8 +16,6 @@ #include "DependencyManager.h" #include -#include "LaserPointer.h" - class LaserPointerScriptingInterface : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -29,7 +27,7 @@ public slots: Q_INVOKABLE void removeLaserPointer(const QUuid& uid) const { DependencyManager::get()->removePointer(uid); } Q_INVOKABLE void editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const; Q_INVOKABLE void setRenderState(const QUuid& uid, const QString& renderState) const { DependencyManager::get()->setRenderState(uid, renderState.toStdString()); } - Q_INVOKABLE QVariantMap getPrevRayPickResult(QUuid uid) const { return DependencyManager::get()->getPrevRayPickResult(uid); } + Q_INVOKABLE QVariantMap getPrevRayPickResult(QUuid uid) const { return DependencyManager::get()->getPrevPickResult(uid); } Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { DependencyManager::get()->setPrecisionPicking(uid, precisionPicking); } Q_INVOKABLE void setLaserLength(const QUuid& uid, float laserLength) const { DependencyManager::get()->setLength(uid, laserLength); } @@ -38,9 +36,6 @@ public slots: Q_INVOKABLE void setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay) const { DependencyManager::get()->setLockEndUUID(uid, objectID, isOverlay); } -private: - static RenderState buildRenderState(const QVariantMap& propMap); - }; #endif // hifi_LaserPointerScriptingInterface_h diff --git a/interface/src/raypick/PickScriptingInterface.cpp b/interface/src/raypick/PickScriptingInterface.cpp new file mode 100644 index 0000000000..99f7ac2515 --- /dev/null +++ b/interface/src/raypick/PickScriptingInterface.cpp @@ -0,0 +1,107 @@ +// +// Created by Sam Gondelman 10/20/2017 +// 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 "PickScriptingInterface.h" + +#include +#include "GLMHelpers.h" + +#include + +#include "StaticRayPick.h" +#include "JointRayPick.h" +#include "MouseRayPick.h" + +QUuid PickScriptingInterface::createPick(const PickQuery::PickType type, const QVariant& properties) { + switch (type) { + case PickQuery::PickType::Ray: + return createRayPick(properties); + default: + return QUuid(); + } +} + +QUuid PickScriptingInterface::createRayPick(const QVariant& properties) { + QVariantMap propMap = properties.toMap(); + + bool enabled = false; + if (propMap["enabled"].isValid()) { + enabled = propMap["enabled"].toBool(); + } + + PickFilter filter = PickFilter(); + if (propMap["filter"].isValid()) { + filter = PickFilter(propMap["filter"].toUInt()); + } + + float maxDistance = 0.0f; + if (propMap["maxDistance"].isValid()) { + maxDistance = propMap["maxDistance"].toFloat(); + } + + if (propMap["joint"].isValid()) { + std::string jointName = propMap["joint"].toString().toStdString(); + + if (jointName != "Mouse") { + // x = upward, y = forward, z = lateral + glm::vec3 posOffset = Vectors::ZERO; + if (propMap["posOffset"].isValid()) { + posOffset = vec3FromVariant(propMap["posOffset"]); + } + + glm::vec3 dirOffset = Vectors::UP; + if (propMap["dirOffset"].isValid()) { + dirOffset = vec3FromVariant(propMap["dirOffset"]); + } + + return DependencyManager::get()->addPick(PickQuery::Ray, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); + + } else { + return DependencyManager::get()->addPick(PickQuery::Ray, std::make_shared(filter, maxDistance, enabled)); + } + } else if (propMap["position"].isValid()) { + glm::vec3 position = vec3FromVariant(propMap["position"]); + + glm::vec3 direction = -Vectors::UP; + if (propMap["direction"].isValid()) { + direction = vec3FromVariant(propMap["direction"]); + } + + return DependencyManager::get()->addPick(PickQuery::Ray, std::make_shared(position, direction, filter, maxDistance, enabled)); + } + + return QUuid(); +} + +void PickScriptingInterface::enablePick(const QUuid& uid) { + DependencyManager::get()->enablePick(uid); +} + +void PickScriptingInterface::disablePick(const QUuid& uid) { + DependencyManager::get()->disablePick(uid); +} + +void PickScriptingInterface::removePick(const QUuid& uid) { + DependencyManager::get()->removePick(uid); +} + +QVariantMap PickScriptingInterface::getPrevPickResult(const QUuid& uid) { + return DependencyManager::get()->getPrevPickResult(uid); +} + +void PickScriptingInterface::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) { + DependencyManager::get()->setPrecisionPicking(uid, precisionPicking); +} + +void PickScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) { + DependencyManager::get()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems)); +} + +void PickScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) { + DependencyManager::get()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems)); +} diff --git a/interface/src/raypick/PickScriptingInterface.h b/interface/src/raypick/PickScriptingInterface.h new file mode 100644 index 0000000000..462b64dbd1 --- /dev/null +++ b/interface/src/raypick/PickScriptingInterface.h @@ -0,0 +1,65 @@ +// +// Created by Sam Gondelman 10/20/2017 +// 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_PickScriptingInterface_h +#define hifi_PickScriptingInterface_h + +#include + +#include +#include +#include + +class PickScriptingInterface : public QObject, public Dependency { + Q_OBJECT + Q_PROPERTY(unsigned int PICK_NOTHING READ PICK_NOTHING CONSTANT) + Q_PROPERTY(unsigned int PICK_ENTITIES READ PICK_ENTITIES CONSTANT) + Q_PROPERTY(unsigned int PICK_OVERLAYS READ PICK_OVERLAYS CONSTANT) + Q_PROPERTY(unsigned int PICK_AVATARS READ PICK_AVATARS CONSTANT) + Q_PROPERTY(unsigned int PICK_HUD READ PICK_HUD CONSTANT) + Q_PROPERTY(unsigned int PICK_COARSE READ PICK_COARSE CONSTANT) + Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ PICK_INCLUDE_INVISIBLE CONSTANT) + Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ PICK_INCLUDE_NONCOLLIDABLE CONSTANT) + Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_NONE READ INTERSECTED_NONE CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ INTERSECTED_ENTITY CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ INTERSECTED_OVERLAY CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ INTERSECTED_AVATAR CONSTANT) + Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT) + SINGLETON_DEPENDENCY + +public: + QUuid createRayPick(const QVariant& properties); + +public slots: + Q_INVOKABLE QUuid createPick(const PickQuery::PickType type, const QVariant& properties); + Q_INVOKABLE void enablePick(const QUuid& uid); + Q_INVOKABLE void disablePick(const QUuid& uid); + Q_INVOKABLE void removePick(const QUuid& uid); + Q_INVOKABLE QVariantMap getPrevPickResult(const QUuid& uid); + + Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, const bool precisionPicking); + Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities); + Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities); + + static constexpr unsigned int PICK_NOTHING() { return 0; } + static constexpr unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ENTITIES); } + static constexpr unsigned int PICK_OVERLAYS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_OVERLAYS); } + static constexpr unsigned int PICK_AVATARS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_AVATARS); } + static constexpr unsigned int PICK_HUD() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_HUD); } + static constexpr unsigned int PICK_COARSE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_COARSE); } + static constexpr unsigned int PICK_INCLUDE_INVISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); } + static constexpr unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); } + static constexpr unsigned int PICK_ALL_INTERSECTIONS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ALL_INTERSECTIONS); } + static constexpr unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } + static constexpr unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } + static constexpr unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } + static constexpr unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } + static constexpr unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } +}; + +#endif // hifi_PickScriptingInterface_h \ No newline at end of file diff --git a/interface/src/raypick/PointerScriptingInterface.cpp b/interface/src/raypick/PointerScriptingInterface.cpp new file mode 100644 index 0000000000..4e5d5f414f --- /dev/null +++ b/interface/src/raypick/PointerScriptingInterface.cpp @@ -0,0 +1,139 @@ +// +// Created by Sam Gondelman 10/20/2017 +// 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 "PointerScriptingInterface.h" + +#include + +#include + +#include "Application.h" + +void PointerScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) const { + DependencyManager::get()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems)); +} +void PointerScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) const { + DependencyManager::get()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems)); +} + +QUuid PointerScriptingInterface::createPointer(const PickQuery::PickType type, const QVariant& properties) const { + switch (type) { + case PickQuery::PickType::Ray: + return createLaserPointer(properties); + default: + return QUuid(); + } +} + +QUuid PointerScriptingInterface::createLaserPointer(const QVariant& properties) const { + QVariantMap propertyMap = properties.toMap(); + + bool faceAvatar = false; + if (propertyMap["faceAvatar"].isValid()) { + faceAvatar = propertyMap["faceAvatar"].toBool(); + } + + bool centerEndY = true; + if (propertyMap["centerEndY"].isValid()) { + centerEndY = propertyMap["centerEndY"].toBool(); + } + + bool lockEnd = false; + if (propertyMap["lockEnd"].isValid()) { + lockEnd = propertyMap["lockEnd"].toBool(); + } + + bool enabled = false; + if (propertyMap["enabled"].isValid()) { + enabled = propertyMap["enabled"].toBool(); + } + + LaserPointer::RenderStateMap renderStates; + if (propertyMap["renderStates"].isValid()) { + QList renderStateVariants = propertyMap["renderStates"].toList(); + for (QVariant& renderStateVariant : renderStateVariants) { + if (renderStateVariant.isValid()) { + QVariantMap renderStateMap = renderStateVariant.toMap(); + if (renderStateMap["name"].isValid()) { + std::string name = renderStateMap["name"].toString().toStdString(); + renderStates[name] = buildRenderState(renderStateMap); + } + } + } + } + + LaserPointer::DefaultRenderStateMap defaultRenderStates; + if (propertyMap["defaultRenderStates"].isValid()) { + QList renderStateVariants = propertyMap["defaultRenderStates"].toList(); + for (QVariant& renderStateVariant : renderStateVariants) { + if (renderStateVariant.isValid()) { + QVariantMap renderStateMap = renderStateVariant.toMap(); + if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) { + std::string name = renderStateMap["name"].toString().toStdString(); + float distance = renderStateMap["distance"].toFloat(); + defaultRenderStates[name] = std::pair(distance, buildRenderState(renderStateMap)); + } + } + } + } + + return DependencyManager::get()->addPointer(std::make_shared(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled)); +} + +void PointerScriptingInterface::editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const { + QVariantMap propMap = properties.toMap(); + + QVariant startProps; + if (propMap["start"].isValid()) { + startProps = propMap["start"]; + } + + QVariant pathProps; + if (propMap["path"].isValid()) { + pathProps = propMap["path"]; + } + + QVariant endProps; + if (propMap["end"].isValid()) { + endProps = propMap["end"]; + } + + DependencyManager::get()->editRenderState(uid, renderState.toStdString(), startProps, pathProps, endProps); +} + +RenderState PointerScriptingInterface::buildRenderState(const QVariantMap& propMap) { + QUuid startID; + if (propMap["start"].isValid()) { + QVariantMap startMap = propMap["start"].toMap(); + if (startMap["type"].isValid()) { + startMap.remove("visible"); + startID = qApp->getOverlays().addOverlay(startMap["type"].toString(), startMap); + } + } + + QUuid pathID; + if (propMap["path"].isValid()) { + QVariantMap pathMap = propMap["path"].toMap(); + // right now paths must be line3ds + if (pathMap["type"].isValid() && pathMap["type"].toString() == "line3d") { + pathMap.remove("visible"); + pathID = qApp->getOverlays().addOverlay(pathMap["type"].toString(), pathMap); + } + } + + QUuid endID; + if (propMap["end"].isValid()) { + QVariantMap endMap = propMap["end"].toMap(); + if (endMap["type"].isValid()) { + endMap.remove("visible"); + endID = qApp->getOverlays().addOverlay(endMap["type"].toString(), endMap); + } + } + + return RenderState(startID, pathID, endID); +} \ No newline at end of file diff --git a/interface/src/raypick/PointerScriptingInterface.h b/interface/src/raypick/PointerScriptingInterface.h new file mode 100644 index 0000000000..8a3a316d9e --- /dev/null +++ b/interface/src/raypick/PointerScriptingInterface.h @@ -0,0 +1,46 @@ +// +// Created by Sam Gondelman 10/20/2017 +// 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_PointerScriptingInterface_h +#define hifi_PointerScriptingInterface_h + +#include + +#include "DependencyManager.h" +#include + +#include "LaserPointer.h" + +class PointerScriptingInterface : public QObject, public Dependency { + Q_OBJECT + SINGLETON_DEPENDENCY + +public: + QUuid createLaserPointer(const QVariant& properties) const; + +public slots: + Q_INVOKABLE QUuid createPointer(const PickQuery::PickType type, const QVariant& properties) const; + Q_INVOKABLE void enablePointer(const QUuid& uid) const { DependencyManager::get()->enablePointer(uid); } + Q_INVOKABLE void disablePointer(const QUuid& uid) const { DependencyManager::get()->disablePointer(uid); } + Q_INVOKABLE void removePointer(const QUuid& uid) const { DependencyManager::get()->removePointer(uid); } + Q_INVOKABLE void editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const; + Q_INVOKABLE void setRenderState(const QUuid& uid, const QString& renderState) const { DependencyManager::get()->setRenderState(uid, renderState.toStdString()); } + Q_INVOKABLE QVariantMap getPrevPickResult(QUuid uid) const { return DependencyManager::get()->getPrevPickResult(uid); } + + Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { DependencyManager::get()->setPrecisionPicking(uid, precisionPicking); } + Q_INVOKABLE void setLaserLength(const QUuid& uid, float laserLength) const { DependencyManager::get()->setLength(uid, laserLength); } + 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 { DependencyManager::get()->setLockEndUUID(uid, objectID, isOverlay); } + +private: + static RenderState buildRenderState(const QVariantMap& propMap); + +}; + +#endif // hifi_PointerScriptingInterface_h diff --git a/interface/src/raypick/RayPickScriptingInterface.cpp b/interface/src/raypick/RayPickScriptingInterface.cpp index 8913138c36..92bf3ec521 100644 --- a/interface/src/raypick/RayPickScriptingInterface.cpp +++ b/interface/src/raypick/RayPickScriptingInterface.cpp @@ -21,55 +21,7 @@ #include "MouseRayPick.h" QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) { - QVariantMap propMap = properties.toMap(); - - bool enabled = false; - if (propMap["enabled"].isValid()) { - enabled = propMap["enabled"].toBool(); - } - - PickFilter filter = PickFilter(); - if (propMap["filter"].isValid()) { - filter = PickFilter(propMap["filter"].toUInt()); - } - - float maxDistance = 0.0f; - if (propMap["maxDistance"].isValid()) { - maxDistance = propMap["maxDistance"].toFloat(); - } - - if (propMap["joint"].isValid()) { - std::string jointName = propMap["joint"].toString().toStdString(); - - if (jointName != "Mouse") { - // x = upward, y = forward, z = lateral - glm::vec3 posOffset = Vectors::ZERO; - if (propMap["posOffset"].isValid()) { - posOffset = vec3FromVariant(propMap["posOffset"]); - } - - glm::vec3 dirOffset = Vectors::UP; - if (propMap["dirOffset"].isValid()) { - dirOffset = vec3FromVariant(propMap["dirOffset"]); - } - - return DependencyManager::get()->addPick(RAY, std::make_shared(jointName, posOffset, dirOffset, filter, maxDistance, enabled)); - - } else { - return DependencyManager::get()->addPick(RAY, std::make_shared(filter, maxDistance, enabled)); - } - } else if (propMap["position"].isValid()) { - glm::vec3 position = vec3FromVariant(propMap["position"]); - - glm::vec3 direction = -Vectors::UP; - if (propMap["direction"].isValid()) { - direction = vec3FromVariant(propMap["direction"]); - } - - return DependencyManager::get()->addPick(RAY, std::make_shared(position, direction, filter, maxDistance, enabled)); - } - - return QUuid(); + return DependencyManager::get()->createRayPick(properties); } void RayPickScriptingInterface::enableRayPick(const QUuid& uid) { diff --git a/interface/src/raypick/RayPickScriptingInterface.h b/interface/src/raypick/RayPickScriptingInterface.h index ebfc3fb9fe..ed837afe49 100644 --- a/interface/src/raypick/RayPickScriptingInterface.h +++ b/interface/src/raypick/RayPickScriptingInterface.h @@ -17,22 +17,10 @@ #include #include "RayPick.h" +#include "PickScriptingInterface.h" + class RayPickScriptingInterface : public QObject, public Dependency { Q_OBJECT - Q_PROPERTY(unsigned int PICK_NOTHING READ PICK_NOTHING CONSTANT) - Q_PROPERTY(unsigned int PICK_ENTITIES READ PICK_ENTITIES CONSTANT) - Q_PROPERTY(unsigned int PICK_OVERLAYS READ PICK_OVERLAYS CONSTANT) - Q_PROPERTY(unsigned int PICK_AVATARS READ PICK_AVATARS CONSTANT) - Q_PROPERTY(unsigned int PICK_HUD READ PICK_HUD CONSTANT) - Q_PROPERTY(unsigned int PICK_COARSE READ PICK_COARSE CONSTANT) - Q_PROPERTY(unsigned int PICK_INCLUDE_INVISIBLE READ PICK_INCLUDE_INVISIBLE CONSTANT) - Q_PROPERTY(unsigned int PICK_INCLUDE_NONCOLLIDABLE READ PICK_INCLUDE_NONCOLLIDABLE CONSTANT) - Q_PROPERTY(unsigned int PICK_ALL_INTERSECTIONS READ PICK_ALL_INTERSECTIONS CONSTANT) - Q_PROPERTY(unsigned int INTERSECTED_NONE READ INTERSECTED_NONE CONSTANT) - Q_PROPERTY(unsigned int INTERSECTED_ENTITY READ INTERSECTED_ENTITY CONSTANT) - Q_PROPERTY(unsigned int INTERSECTED_OVERLAY READ INTERSECTED_OVERLAY CONSTANT) - Q_PROPERTY(unsigned int INTERSECTED_AVATAR READ INTERSECTED_AVATAR CONSTANT) - Q_PROPERTY(unsigned int INTERSECTED_HUD READ INTERSECTED_HUD CONSTANT) SINGLETON_DEPENDENCY public slots: @@ -45,21 +33,6 @@ public slots: Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, const bool precisionPicking); Q_INVOKABLE void setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreEntities); Q_INVOKABLE void setIncludeItems(const QUuid& uid, const QScriptValue& includeEntities); - - static constexpr unsigned int PICK_NOTHING() { return 0; } - static constexpr unsigned int PICK_ENTITIES() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ENTITIES); } - static constexpr unsigned int PICK_OVERLAYS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_OVERLAYS); } - static constexpr unsigned int PICK_AVATARS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_AVATARS); } - static constexpr unsigned int PICK_HUD() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_HUD); } - static constexpr unsigned int PICK_COARSE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_COARSE); } - static constexpr unsigned int PICK_INCLUDE_INVISIBLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); } - static constexpr unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); } - static constexpr unsigned int PICK_ALL_INTERSECTIONS() { return PickFilter::getBitMask(PickFilter::FlagBit::PICK_ALL_INTERSECTIONS); } - static constexpr unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } - static constexpr unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } - static constexpr unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } - static constexpr unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } - static constexpr unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } }; #endif // hifi_RayPickScriptingInterface_h diff --git a/libraries/pointers/src/pointers/Pick.h b/libraries/pointers/src/pointers/Pick.h index 6ac0d6781e..5dcaba2bb8 100644 --- a/libraries/pointers/src/pointers/Pick.h +++ b/libraries/pointers/src/pointers/Pick.h @@ -130,9 +130,16 @@ public: using PickResultPointer = std::shared_ptr; class PickQuery : protected ReadWriteLockable { + Q_GADGET public: PickQuery(const PickFilter& filter, const float maxDistance, const bool enabled); + enum PickType { + Ray = 0, + Stylus + }; + Q_ENUM(PickType) + void enable(bool enabled = true); void disable() { enable(false); } diff --git a/libraries/pointers/src/pointers/PickManager.cpp b/libraries/pointers/src/pointers/PickManager.cpp index d6c2f44212..571f9f04cd 100644 --- a/libraries/pointers/src/pointers/PickManager.cpp +++ b/libraries/pointers/src/pointers/PickManager.cpp @@ -11,7 +11,7 @@ PickManager::PickManager() { setShouldPickHUDOperator([]() { return false; }); } -QUuid PickManager::addPick(PickType type, const std::shared_ptr pick) { +QUuid PickManager::addPick(PickQuery::PickType type, const std::shared_ptr pick) { QUuid id = QUuid::createUuid(); withWriteLock([&] { _picks[type][id] = pick; @@ -84,11 +84,11 @@ void PickManager::setIncludeItems(const QUuid& uid, const QVector& includ } void PickManager::update() { - QHash>> cachedPicks; + QHash>> cachedPicks; withReadLock([&] { cachedPicks = _picks; }); bool shouldPickHUD = _shouldPickHUDOperator(); - _rayPickCacheOptimizer.update(cachedPicks[RAY], shouldPickHUD); + _rayPickCacheOptimizer.update(cachedPicks[PickQuery::Ray], shouldPickHUD); } \ No newline at end of file diff --git a/libraries/pointers/src/pointers/PickManager.h b/libraries/pointers/src/pointers/PickManager.h index 07c8d914f3..f09f44621a 100644 --- a/libraries/pointers/src/pointers/PickManager.h +++ b/libraries/pointers/src/pointers/PickManager.h @@ -16,11 +16,6 @@ #include "Pick.h" #include "PickCacheOptimizer.h" -enum PickType { - RAY = 0, - STYLUS -}; - class PickManager : public Dependency, protected ReadWriteLockable { SINGLETON_DEPENDENCY @@ -29,7 +24,7 @@ public: void update(); - QUuid addPick(PickType type, const std::shared_ptr pick); + QUuid addPick(PickQuery::PickType type, const std::shared_ptr pick); void removePick(const QUuid& uid); void enablePick(const QUuid& uid) const; void disablePick(const QUuid& uid) const; @@ -46,8 +41,8 @@ protected: std::function _shouldPickHUDOperator; std::shared_ptr findPick(const QUuid& uid) const; - QHash>> _picks; - QHash _typeMap; + QHash>> _picks; + QHash _typeMap; PickCacheOptimizer _rayPickCacheOptimizer; }; diff --git a/libraries/pointers/src/pointers/PointerManager.cpp b/libraries/pointers/src/pointers/PointerManager.cpp index f2c2756d6f..a475ba4d83 100644 --- a/libraries/pointers/src/pointers/PointerManager.cpp +++ b/libraries/pointers/src/pointers/PointerManager.cpp @@ -61,7 +61,7 @@ void PointerManager::editRenderState(const QUuid& uid, const std::string& state, } } -const QVariantMap PointerManager::getPrevRayPickResult(const QUuid& uid) const { +const QVariantMap PointerManager::getPrevPickResult(const QUuid& uid) const { auto pointer = find(uid); if (pointer) { return pointer->getPrevPickResult(); diff --git a/libraries/pointers/src/pointers/PointerManager.h b/libraries/pointers/src/pointers/PointerManager.h index 1841e66f7b..db08199949 100644 --- a/libraries/pointers/src/pointers/PointerManager.h +++ b/libraries/pointers/src/pointers/PointerManager.h @@ -30,7 +30,7 @@ public: void disablePointer(const QUuid& uid) const; void setRenderState(const QUuid& uid, const std::string& renderState) const; void editRenderState(const QUuid& uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) const; - const QVariantMap getPrevRayPickResult(const QUuid& uid) const; + const QVariantMap getPrevPickResult(const QUuid& uid) const; void setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const; void setIgnoreItems(const QUuid& uid, const QVector& ignoreEntities) const; diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 2deef5f9fa..3bc423450e 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -252,7 +252,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); length: 1000 }; - if (rayPicks[h].type === RayPick.INTERSECTED_ENTITY) { + if (rayPicks[h].type === Picks.INTERSECTED_ENTITY) { // XXX check to make sure this one isn't already in nearbyEntityProperties? if (rayPicks[h].distance < NEAR_GRAB_PICK_RADIUS * sensorScaleFactor) { var nearEntityID = rayPicks[h].objectID; @@ -390,35 +390,35 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); this.leftControllerRayPick = RayPick.createRayPick({ joint: "_CONTROLLER_LEFTHAND", - filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + filter: Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS, enabled: true, maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true) }); this.leftControllerHudRayPick = RayPick.createRayPick({ joint: "_CONTROLLER_LEFTHAND", - filter: RayPick.PICK_HUD, + filter: Picks.PICK_HUD, enabled: true, maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true) }); this.rightControllerRayPick = RayPick.createRayPick({ joint: "_CONTROLLER_RIGHTHAND", - filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + filter: Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS, enabled: true, maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true) }); this.rightControllerHudRayPick = RayPick.createRayPick({ joint: "_CONTROLLER_RIGHTHAND", - filter: RayPick.PICK_HUD, + filter: Picks.PICK_HUD, enabled: true, maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true) }); this.mouseRayPick = RayPick.createRayPick({ joint: "Mouse", - filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + filter: Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS, enabled: true }); diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index 2ef7b1efeb..79a7b70bae 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -376,8 +376,8 @@ Script.include("/~/system/libraries/controllers.js"); var entityType = entityProperty.type; var hudRayPick = controllerData.hudRayPicks[this.hand]; var point2d = this.calculateNewReticlePosition(hudRayPick.intersection); - if ((intersection.type === RayPick.INTERSECTED_ENTITY && entityType === "Web") || - intersection.type === RayPick.INTERSECTED_OVERLAY || Window.isPointOnDesktopWindow(point2d)) { + if ((intersection.type === Picks.INTERSECTED_ENTITY && entityType === "Web") || + intersection.type === Picks.INTERSECTED_OVERLAY || Window.isPointOnDesktopWindow(point2d)) { return true; } return false; @@ -497,7 +497,7 @@ Script.include("/~/system/libraries/controllers.js"); } var rayPickInfo = controllerData.rayPicks[this.hand]; - if (rayPickInfo.type === RayPick.INTERSECTED_ENTITY) { + if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) { if (controllerData.triggerClicks[this.hand]) { var entityID = rayPickInfo.objectID; var targetProps = Entities.getEntityProperties(entityID, [ @@ -581,7 +581,7 @@ Script.include("/~/system/libraries/controllers.js"); this.fullEnd = fullEnd; this.laserPointer = LaserPointers.createLaserPointer({ joint: (this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", - filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + filter: Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS, maxDistance: PICK_MAX_DISTANCE, posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, diff --git a/scripts/system/controllers/controllerModules/farTrigger.js b/scripts/system/controllers/controllerModules/farTrigger.js index a683044e6e..7975889bc8 100644 --- a/scripts/system/controllers/controllerModules/farTrigger.js +++ b/scripts/system/controllers/controllerModules/farTrigger.js @@ -196,7 +196,7 @@ Script.include("/~/system/libraries/controllers.js"); this.fullEnd = fullEnd; this.laserPointer = LaserPointers.createLaserPointer({ joint: (this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", - filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + filter: Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS, maxDistance: PICK_MAX_DISTANCE, posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, diff --git a/scripts/system/controllers/controllerModules/hudOverlayPointer.js b/scripts/system/controllers/controllerModules/hudOverlayPointer.js index fe1dedefb8..d579ce2611 100644 --- a/scripts/system/controllers/controllerModules/hudOverlayPointer.js +++ b/scripts/system/controllers/controllerModules/hudOverlayPointer.js @@ -216,7 +216,7 @@ this.fullEnd = fullEnd; this.laserPointer = LaserPointers.createLaserPointer({ joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND", - filter: RayPick.PICK_HUD, + filter: Picks.PICK_HUD, maxDistance: PICK_MAX_DISTANCE, posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index 5049185827..34247b1d9d 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -153,12 +153,12 @@ Script.include("/~/system/libraries/utils.js"); this.sendPickData = function(controllerData) { if (controllerData.triggerClicks[this.hand] && !this.triggerClicked) { var intersection = controllerData.rayPicks[this.hand]; - if (intersection.type === RayPick.INTERSECTED_ENTITY) { + if (intersection.type === Picks.INTERSECTED_ENTITY) { Messages.sendLocalMessage("entityToolUpdates", JSON.stringify({ method: "selectEntity", entityID: intersection.objectID })); - } else if (intersection.type === RayPick.INTERSECTED_OVERLAY) { + } else if (intersection.type === Picks.INTERSECTED_OVERLAY) { Messages.sendLocalMessage("entityToolUpdates", JSON.stringify({ method: "selectOverlay", overlayID: intersection.objectID @@ -243,7 +243,7 @@ Script.include("/~/system/libraries/utils.js"); this.laserPointer = LaserPointers.createLaserPointer({ joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND", - filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + filter: Picks.PICK_ENTITIES | Picks.PICK_OVERLAYS, maxDistance: PICK_MAX_DISTANCE, posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, diff --git a/scripts/system/controllers/controllerModules/overlayLaserInput.js b/scripts/system/controllers/controllerModules/overlayLaserInput.js index 7c86a01c5d..0747985c7b 100644 --- a/scripts/system/controllers/controllerModules/overlayLaserInput.js +++ b/scripts/system/controllers/controllerModules/overlayLaserInput.js @@ -301,7 +301,7 @@ Script.include("/~/system/libraries/controllers.js"); this.shouldExit = function(controllerData) { var intersection = controllerData.rayPicks[this.hand]; - var offOverlay = (intersection.type !== RayPick.INTERSECTED_OVERLAY); + var offOverlay = (intersection.type !== Picks.INTERSECTED_OVERLAY); var triggerOff = (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE); if (triggerOff) { this.deleteContextOverlay(); @@ -375,7 +375,7 @@ Script.include("/~/system/libraries/controllers.js"); this.fullEnd = fullEnd; this.laserPointer = LaserPointers.createLaserPointer({ joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND", - filter: RayPick.PICK_OVERLAYS, + filter: Picks.PICK_OVERLAYS, maxDistance: PICK_MAX_DISTANCE, posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js index 86ad9c56ca..1fb867675e 100644 --- a/scripts/system/controllers/controllerModules/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -149,7 +149,7 @@ Script.include("/~/system/libraries/controllers.js"); this.teleportRayHandVisible = LaserPointers.createLaserPointer({ joint: (_this.hand === RIGHT_HAND) ? "RightHand" : "LeftHand", - filter: RayPick.PICK_ENTITIES, + filter: Picks.PICK_ENTITIES, faceAvatar: true, centerEndY: false, renderStates: teleportRenderStates, @@ -157,14 +157,14 @@ Script.include("/~/system/libraries/controllers.js"); }); this.teleportRayHandInvisible = LaserPointers.createLaserPointer({ joint: (_this.hand === RIGHT_HAND) ? "RightHand" : "LeftHand", - filter: RayPick.PICK_ENTITIES | RayPick.PICK_INCLUDE_INVISIBLE, + filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE, faceAvatar: true, centerEndY: false, renderStates: teleportRenderStates }); this.teleportRayHeadVisible = LaserPointers.createLaserPointer({ joint: "Avatar", - filter: RayPick.PICK_ENTITIES, + filter: Picks.PICK_ENTITIES, faceAvatar: true, centerEndY: false, renderStates: teleportRenderStates, @@ -172,7 +172,7 @@ Script.include("/~/system/libraries/controllers.js"); }); this.teleportRayHeadInvisible = LaserPointers.createLaserPointer({ joint: "Avatar", - filter: RayPick.PICK_ENTITIES | RayPick.PICK_INCLUDE_INVISIBLE, + filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE, faceAvatar: true, centerEndY: false, renderStates: teleportRenderStates @@ -397,7 +397,7 @@ Script.include("/~/system/libraries/controllers.js"); // you can't teleport there. var MAX_ANGLE_FROM_UP_TO_TELEPORT = 70; function getTeleportTargetType(result) { - if (result.type === RayPick.INTERSECTED_NONE) { + if (result.type === Picks.INTERSECTED_NONE) { return TARGET.NONE; } diff --git a/scripts/system/controllers/controllerModules/webEntityLaserInput.js b/scripts/system/controllers/controllerModules/webEntityLaserInput.js index 339f248547..0076e1c865 100644 --- a/scripts/system/controllers/controllerModules/webEntityLaserInput.js +++ b/scripts/system/controllers/controllerModules/webEntityLaserInput.js @@ -386,7 +386,7 @@ Script.include("/~/system/libraries/controllers.js"); var entityProperty = Entities.getEntityProperties(intersection.objectID); var entityType = entityProperty.type; - if ((intersection.type === RayPick.INTERSECTED_ENTITY && entityType === "Web")) { + if ((intersection.type === Picks.INTERSECTED_ENTITY && entityType === "Web")) { return true; } return false; @@ -454,7 +454,7 @@ Script.include("/~/system/libraries/controllers.js"); this.laserPointer = LaserPointers.createLaserPointer({ joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND", - filter: RayPick.PICK_ENTITIES, + filter: Picks.PICK_ENTITIES, maxDistance: PICK_MAX_DISTANCE, posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index a1846e7ad7..7e575e38b0 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -260,14 +260,14 @@ function Grabber() { this.mouseRayOverlays = RayPick.createRayPick({ joint: "Mouse", - filter: RayPick.PICK_OVERLAYS, + filter: Picks.PICK_OVERLAYS, enabled: true }); RayPick.setIncludeItems(this.mouseRayOverlays, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]); var renderStates = [{name: "grabbed", end: beacon}]; this.mouseRayEntities = LaserPointers.createLaserPointer({ joint: "Mouse", - filter: RayPick.PICK_ENTITIES, + filter: Picks.PICK_ENTITIES, faceAvatar: true, enabled: true, renderStates: renderStates @@ -321,12 +321,12 @@ Grabber.prototype.pressEvent = function(event) { } var overlayResult = RayPick.getPrevRayPickResult(this.mouseRayOverlays); - if (overlayResult.type != RayPick.INTERSECTED_NONE) { + if (overlayResult.type != Picks.INTERSECTED_NONE) { return; } var pickResults = LaserPointers.getPrevRayPickResult(this.mouseRayEntities); - if (pickResults.type == RayPick.INTERSECTED_NONE) { + if (pickResults.type == Picks.INTERSECTED_NONE) { LaserPointers.setRenderState(this.mouseRayEntities, ""); return; } diff --git a/scripts/system/libraries/touchEventUtils.js b/scripts/system/libraries/touchEventUtils.js index fbd56e16ae..7d19181c2a 100644 --- a/scripts/system/libraries/touchEventUtils.js +++ b/scripts/system/libraries/touchEventUtils.js @@ -130,7 +130,7 @@ function sendTouchMoveEventToTouchTarget(hand, touchTarget) { } function composeTouchTargetFromIntersection(intersection) { - var isEntity = (intersection.type === RayPick.INTERSECTED_ENTITY); + var isEntity = (intersection.type === Picks.INTERSECTED_ENTITY); var objectID = intersection.objectID; var worldPos = intersection.intersection; var props = null;