switch to stl wherever possible, use bitset instead of unsigned ints

This commit is contained in:
SamGondelman 2017-08-10 15:32:58 -07:00
parent 85c3f94976
commit d0d5ac8dd1
16 changed files with 268 additions and 201 deletions

View file

@ -13,7 +13,7 @@
#include "DependencyManager.h" #include "DependencyManager.h"
#include "avatar/AvatarManager.h" #include "avatar/AvatarManager.h"
JointRayPick::JointRayPick(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance, const bool enabled) : JointRayPick::JointRayPick(const std::string& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const RayPickFilter& filter, const float maxDistance, const bool enabled) :
RayPick(filter, maxDistance, enabled), RayPick(filter, maxDistance, enabled),
_jointName(jointName), _jointName(jointName),
_posOffset(posOffset), _posOffset(posOffset),
@ -23,7 +23,7 @@ JointRayPick::JointRayPick(const QString& jointName, const glm::vec3& posOffset,
const PickRay JointRayPick::getPickRay(bool& valid) const { const PickRay JointRayPick::getPickRay(bool& valid) const {
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar(); auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
int jointIndex = myAvatar->getJointIndex(_jointName); int jointIndex = myAvatar->getJointIndex(QString::fromStdString(_jointName));
bool useAvatarHead = _jointName == "Avatar"; bool useAvatarHead = _jointName == "Avatar";
const int INVALID_JOINT = -1; const int INVALID_JOINT = -1;
if (jointIndex != INVALID_JOINT || useAvatarHead) { if (jointIndex != INVALID_JOINT || useAvatarHead) {

View file

@ -13,17 +13,15 @@
#include "RayPick.h" #include "RayPick.h"
#include <QString>
class JointRayPick : public RayPick { class JointRayPick : public RayPick {
public: public:
JointRayPick(const QString& jointName, const glm::vec3& posOffset, const glm::vec3& dirOffset, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); 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);
const PickRay getPickRay(bool& valid) const override; const PickRay getPickRay(bool& valid) const override;
private: private:
QString _jointName; std::string _jointName;
glm::vec3 _posOffset; glm::vec3 _posOffset;
glm::vec3 _dirOffset; glm::vec3 _dirOffset;

View file

@ -13,7 +13,7 @@
#include "Application.h" #include "Application.h"
#include "avatar/AvatarManager.h" #include "avatar/AvatarManager.h"
LaserPointer::LaserPointer(const QVariantMap& rayProps, const QHash<QString, RenderState>& renderStates, QHash<QString, QPair<float, RenderState>>& defaultRenderStates, LaserPointer::LaserPointer(const QVariantMap& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) : const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) :
_renderingEnabled(enabled), _renderingEnabled(enabled),
_renderStates(renderStates), _renderStates(renderStates),
@ -24,14 +24,14 @@ LaserPointer::LaserPointer(const QVariantMap& rayProps, const QHash<QString, Ren
{ {
_rayPickUID = DependencyManager::get<RayPickManager>()->createRayPick(rayProps); _rayPickUID = DependencyManager::get<RayPickManager>()->createRayPick(rayProps);
for (QString& state : _renderStates.keys()) { for (auto& state : _renderStates) {
if (!enabled || state != _currentRenderState) { if (!enabled || state.first != _currentRenderState) {
disableRenderState(_renderStates[state]); disableRenderState(state.second);
} }
} }
for (QString& state : _defaultRenderStates.keys()) { for (auto& state : _defaultRenderStates) {
if (!enabled || state != _currentRenderState) { if (!enabled || state.first != _currentRenderState) {
disableRenderState(_defaultRenderStates[state].second); disableRenderState(state.second.second);
} }
} }
} }
@ -39,12 +39,12 @@ LaserPointer::LaserPointer(const QVariantMap& rayProps, const QHash<QString, Ren
LaserPointer::~LaserPointer() { LaserPointer::~LaserPointer() {
DependencyManager::get<RayPickManager>()->removeRayPick(_rayPickUID); DependencyManager::get<RayPickManager>()->removeRayPick(_rayPickUID);
for (RenderState& renderState : _renderStates) { for (auto& renderState : _renderStates) {
renderState.deleteOverlays();
}
for (QPair<float, RenderState>& renderState : _defaultRenderStates) {
renderState.second.deleteOverlays(); renderState.second.deleteOverlays();
} }
for (auto& renderState : _defaultRenderStates) {
renderState.second.second.deleteOverlays();
}
} }
void LaserPointer::enable() { void LaserPointer::enable() {
@ -55,29 +55,29 @@ void LaserPointer::enable() {
void LaserPointer::disable() { void LaserPointer::disable() {
DependencyManager::get<RayPickManager>()->disableRayPick(_rayPickUID); DependencyManager::get<RayPickManager>()->disableRayPick(_rayPickUID);
_renderingEnabled = false; _renderingEnabled = false;
if (!_currentRenderState.isEmpty()) { if (!_currentRenderState.empty()) {
if (_renderStates.contains(_currentRenderState)) { if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
disableRenderState(_renderStates[_currentRenderState]); disableRenderState(_renderStates[_currentRenderState]);
} }
if (_defaultRenderStates.contains(_currentRenderState)) { if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
disableRenderState(_defaultRenderStates[_currentRenderState].second); disableRenderState(_defaultRenderStates[_currentRenderState].second);
} }
} }
} }
void LaserPointer::setRenderState(const QString& state) { void LaserPointer::setRenderState(const std::string& state) {
if (!_currentRenderState.isEmpty() && state != _currentRenderState) { if (!_currentRenderState.empty() && state != _currentRenderState) {
if (_renderStates.contains(_currentRenderState)) { if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
disableRenderState(_renderStates[_currentRenderState]); disableRenderState(_renderStates[_currentRenderState]);
} }
if (_defaultRenderStates.contains(_currentRenderState)) { if (_defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
disableRenderState(_defaultRenderStates[_currentRenderState].second); disableRenderState(_defaultRenderStates[_currentRenderState].second);
} }
} }
_currentRenderState = state; _currentRenderState = state;
} }
void LaserPointer::editRenderState(const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { void LaserPointer::editRenderState(const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) {
updateRenderStateOverlay(_renderStates[state].getStartID(), startProps); updateRenderStateOverlay(_renderStates[state].getStartID(), startProps);
updateRenderStateOverlay(_renderStates[state].getPathID(), pathProps); updateRenderStateOverlay(_renderStates[state].getPathID(), pathProps);
updateRenderStateOverlay(_renderStates[state].getEndID(), endProps); updateRenderStateOverlay(_renderStates[state].getEndID(), endProps);
@ -181,13 +181,13 @@ void LaserPointer::disableRenderState(const RenderState& renderState) {
void LaserPointer::update() { void LaserPointer::update() {
RayPickResult prevRayPickResult = DependencyManager::get<RayPickManager>()->getPrevRayPickResult(_rayPickUID); RayPickResult prevRayPickResult = DependencyManager::get<RayPickManager>()->getPrevRayPickResult(_rayPickUID);
if (_renderingEnabled && !_currentRenderState.isEmpty() && _renderStates.contains(_currentRenderState) && prevRayPickResult.type != IntersectionType::NONE) { if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() && prevRayPickResult.type != IntersectionType::NONE) {
updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, prevRayPickResult.distance, prevRayPickResult.objectID, false); updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, prevRayPickResult.distance, prevRayPickResult.objectID, false);
disableRenderState(_defaultRenderStates[_currentRenderState].second); disableRenderState(_defaultRenderStates[_currentRenderState].second);
} else if (_renderingEnabled && !_currentRenderState.isEmpty() && _defaultRenderStates.contains(_currentRenderState)) { } else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
disableRenderState(_renderStates[_currentRenderState]); disableRenderState(_renderStates[_currentRenderState]);
updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), true); updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), true);
} else if (!_currentRenderState.isEmpty()) { } else if (!_currentRenderState.empty()) {
disableRenderState(_renderStates[_currentRenderState]); disableRenderState(_renderStates[_currentRenderState]);
disableRenderState(_defaultRenderStates[_currentRenderState].second); disableRenderState(_defaultRenderStates[_currentRenderState].second);
} }

View file

@ -48,7 +48,11 @@ private:
class LaserPointer { class LaserPointer {
public: public:
LaserPointer(const QVariantMap& rayProps, const QHash<QString, RenderState>& renderStates, QHash<QString, QPair<float, RenderState>>& defaultRenderStates,
typedef std::unordered_map<std::string, RenderState> RenderStateMap;
typedef std::unordered_map<std::string, std::pair<float, RenderState>> DefaultRenderStateMap;
LaserPointer(const QVariantMap& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled);
~LaserPointer(); ~LaserPointer();
@ -57,9 +61,9 @@ public:
void disable(); void disable();
const RayPickResult getPrevRayPickResult() { return DependencyManager::get<RayPickManager>()->getPrevRayPickResult(_rayPickUID); } const RayPickResult getPrevRayPickResult() { return DependencyManager::get<RayPickManager>()->getPrevRayPickResult(_rayPickUID); }
void setRenderState(const QString& state); 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. // 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 QString& 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);
void setIgnoreEntities(const QScriptValue& ignoreEntities) { DependencyManager::get<RayPickManager>()->setIgnoreEntities(_rayPickUID, ignoreEntities); } void setIgnoreEntities(const QScriptValue& ignoreEntities) { DependencyManager::get<RayPickManager>()->setIgnoreEntities(_rayPickUID, ignoreEntities); }
void setIncludeEntities(const QScriptValue& includeEntities) { DependencyManager::get<RayPickManager>()->setIncludeEntities(_rayPickUID, includeEntities); } void setIncludeEntities(const QScriptValue& includeEntities) { DependencyManager::get<RayPickManager>()->setIncludeEntities(_rayPickUID, includeEntities); }
@ -68,25 +72,26 @@ public:
void setIgnoreAvatars(const QScriptValue& ignoreAvatars) { DependencyManager::get<RayPickManager>()->setIgnoreAvatars(_rayPickUID, ignoreAvatars); } void setIgnoreAvatars(const QScriptValue& ignoreAvatars) { DependencyManager::get<RayPickManager>()->setIgnoreAvatars(_rayPickUID, ignoreAvatars); }
void setIncludeAvatars(const QScriptValue& includeAvatars) { DependencyManager::get<RayPickManager>()->setIncludeAvatars(_rayPickUID, includeAvatars); } void setIncludeAvatars(const QScriptValue& includeAvatars) { DependencyManager::get<RayPickManager>()->setIncludeAvatars(_rayPickUID, includeAvatars); }
void setLockEndUUID(QUuid objectID, const bool isOverlay) { _objectLockEnd = QPair<QUuid, bool>(objectID, isOverlay); } void setLockEndUUID(QUuid objectID, const bool isOverlay) { _objectLockEnd = std::pair<QUuid, bool>(objectID, isOverlay); }
void update(); void update();
private: private:
bool _renderingEnabled; bool _renderingEnabled;
QString _currentRenderState { "" }; std::string _currentRenderState { "" };
QHash<QString, RenderState> _renderStates; RenderStateMap _renderStates;
QHash<QString, QPair<float, RenderState>> _defaultRenderStates; DefaultRenderStateMap _defaultRenderStates;
bool _faceAvatar; bool _faceAvatar;
bool _centerEndY; bool _centerEndY;
bool _lockEnd; bool _lockEnd;
QPair<QUuid, bool> _objectLockEnd { QPair<QUuid, bool>(QUuid(), false)}; std::pair<QUuid, bool> _objectLockEnd { std::pair<QUuid, bool>(QUuid(), false)};
QUuid _rayPickUID; QUuid _rayPickUID;
void updateRenderStateOverlay(const OverlayID& id, const QVariant& props); void updateRenderStateOverlay(const OverlayID& id, const QVariant& props);
void updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const bool defaultState); void updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const bool defaultState);
void disableRenderState(const RenderState& renderState); void disableRenderState(const RenderState& renderState);
}; };
#endif // hifi_LaserPointer_h #endif // hifi_LaserPointer_h

View file

@ -11,85 +11,87 @@
#include "LaserPointerManager.h" #include "LaserPointerManager.h"
#include "RayPick.h" #include "RayPick.h"
QUuid LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const QHash<QString, RenderState>& renderStates, QHash<QString, QPair<float, RenderState>>& defaultRenderStates, QUuid LaserPointerManager::createLaserPointer(const QVariantMap& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates,
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) { const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled) {
std::shared_ptr<LaserPointer> laserPointer = std::make_shared<LaserPointer>(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled); std::shared_ptr<LaserPointer> laserPointer = std::make_shared<LaserPointer>(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, enabled);
if (!laserPointer->getRayUID().isNull()) { if (!laserPointer->getRayUID().isNull()) {
QWriteLocker lock(&_addLock); WriteLock lock(_addLock);
QUuid id = QUuid::createUuid(); QUuid id = QUuid::createUuid();
_laserPointersToAdd.enqueue(QPair<QUuid, std::shared_ptr<LaserPointer>>(id, laserPointer)); _laserPointersToAdd.push(std::pair<QUuid, std::shared_ptr<LaserPointer>>(id, laserPointer));
return id; return id;
} }
return QUuid(); return QUuid();
} }
void LaserPointerManager::removeLaserPointer(const QUuid uid) { void LaserPointerManager::removeLaserPointer(const QUuid uid) {
QWriteLocker lock(&_removeLock); WriteLock lock(_removeLock);
_laserPointersToRemove.enqueue(uid); _laserPointersToRemove.push(uid);
} }
void LaserPointerManager::enableLaserPointer(const QUuid uid) { void LaserPointerManager::enableLaserPointer(const QUuid uid) {
QReadLocker lock(&_containsLock); ReadLock lock(_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {
QWriteLocker laserLock(_laserPointerLocks[uid].get()); WriteLock laserLock(*_laserPointerLocks[uid]);
_laserPointers[uid]->enable(); _laserPointers[uid]->enable();
} }
} }
void LaserPointerManager::disableLaserPointer(const QUuid uid) { void LaserPointerManager::disableLaserPointer(const QUuid uid) {
QReadLocker lock(&_containsLock); ReadLock lock(_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {
QWriteLocker laserLock(_laserPointerLocks[uid].get()); WriteLock laserLock(*_laserPointerLocks[uid]);
_laserPointers[uid]->disable(); _laserPointers[uid]->disable();
} }
} }
void LaserPointerManager::setRenderState(QUuid uid, const QString & renderState) { void LaserPointerManager::setRenderState(QUuid uid, const std::string& renderState) {
QReadLocker lock(&_containsLock); ReadLock lock(_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {
QWriteLocker laserLock(_laserPointerLocks[uid].get()); WriteLock laserLock(*_laserPointerLocks[uid]);
_laserPointers[uid]->setRenderState(renderState); _laserPointers[uid]->setRenderState(renderState);
} }
} }
void LaserPointerManager::editRenderState(QUuid uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) { void LaserPointerManager::editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps) {
QReadLocker lock(&_containsLock); ReadLock lock(_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {
QWriteLocker laserLock(_laserPointerLocks[uid].get()); WriteLock laserLock(*_laserPointerLocks[uid]);
_laserPointers[uid]->editRenderState(state, startProps, pathProps, endProps); _laserPointers[uid]->editRenderState(state, startProps, pathProps, endProps);
} }
} }
const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid uid) { const RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid uid) {
QReadLocker lock(&_containsLock); ReadLock lock(_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {
QReadLocker laserLock(_laserPointerLocks[uid].get()); ReadLock laserLock(*_laserPointerLocks[uid]);
return _laserPointers[uid]->getPrevRayPickResult(); return _laserPointers[uid]->getPrevRayPickResult();
} }
return RayPickResult(); return RayPickResult();
} }
void LaserPointerManager::update() { void LaserPointerManager::update() {
for (QUuid uid : _laserPointers.keys()) { for (QUuid& uid : _laserPointers.keys()) {
// This only needs to be a read lock because update won't change any of the properties that can be modified from scripts // This only needs to be a read lock because update won't change any of the properties that can be modified from scripts
QReadLocker laserLock(_laserPointerLocks[uid].get()); ReadLock laserLock(*_laserPointerLocks[uid]);
_laserPointers[uid]->update(); _laserPointers[uid]->update();
} }
QWriteLocker containsLock(&_containsLock); WriteLock containsLock(_containsLock);
{ {
QWriteLocker lock(&_addLock); WriteLock lock(_addLock);
while (!_laserPointersToAdd.isEmpty()) { while (!_laserPointersToAdd.empty()) {
QPair<QUuid, std::shared_ptr<LaserPointer>> laserPointerToAdd = _laserPointersToAdd.dequeue(); std::pair<QUuid, std::shared_ptr<LaserPointer>> laserPointerToAdd = _laserPointersToAdd.front();
_laserPointersToAdd.pop();
_laserPointers[laserPointerToAdd.first] = laserPointerToAdd.second; _laserPointers[laserPointerToAdd.first] = laserPointerToAdd.second;
_laserPointerLocks[laserPointerToAdd.first] = std::make_shared<QReadWriteLock>(); _laserPointerLocks[laserPointerToAdd.first] = std::make_shared<std::shared_mutex>();
} }
} }
{ {
QWriteLocker lock(&_removeLock); WriteLock lock(_removeLock);
while (!_laserPointersToRemove.isEmpty()) { while (!_laserPointersToRemove.empty()) {
QUuid uid = _laserPointersToRemove.dequeue(); QUuid uid = _laserPointersToRemove.front();
_laserPointersToRemove.pop();
_laserPointers.remove(uid); _laserPointers.remove(uid);
_laserPointerLocks.remove(uid); _laserPointerLocks.remove(uid);
} }
@ -97,57 +99,57 @@ void LaserPointerManager::update() {
} }
void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { void LaserPointerManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
QReadLocker lock(&_containsLock); ReadLock lock(_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {
QWriteLocker laserLock(_laserPointerLocks[uid].get()); WriteLock laserLock(*_laserPointerLocks[uid]);
_laserPointers[uid]->setIgnoreEntities(ignoreEntities); _laserPointers[uid]->setIgnoreEntities(ignoreEntities);
} }
} }
void LaserPointerManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { void LaserPointerManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) {
QReadLocker lock(&_containsLock); ReadLock lock(_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {
QWriteLocker laserLock(_laserPointerLocks[uid].get()); WriteLock laserLock(*_laserPointerLocks[uid]);
_laserPointers[uid]->setIncludeEntities(includeEntities); _laserPointers[uid]->setIncludeEntities(includeEntities);
} }
} }
void LaserPointerManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { void LaserPointerManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) {
QReadLocker lock(&_containsLock); ReadLock lock(_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {
QWriteLocker laserLock(_laserPointerLocks[uid].get()); WriteLock laserLock(*_laserPointerLocks[uid]);
_laserPointers[uid]->setIgnoreOverlays(ignoreOverlays); _laserPointers[uid]->setIgnoreOverlays(ignoreOverlays);
} }
} }
void LaserPointerManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { void LaserPointerManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) {
QReadLocker lock(&_containsLock); ReadLock lock(_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {
QWriteLocker laserLock(_laserPointerLocks[uid].get()); WriteLock laserLock(*_laserPointerLocks[uid]);
_laserPointers[uid]->setIncludeOverlays(includeOverlays); _laserPointers[uid]->setIncludeOverlays(includeOverlays);
} }
} }
void LaserPointerManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { void LaserPointerManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) {
QReadLocker lock(&_containsLock); ReadLock lock(_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {
QWriteLocker laserLock(_laserPointerLocks[uid].get()); WriteLock laserLock(*_laserPointerLocks[uid]);
_laserPointers[uid]->setIgnoreAvatars(ignoreAvatars); _laserPointers[uid]->setIgnoreAvatars(ignoreAvatars);
} }
} }
void LaserPointerManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { void LaserPointerManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) {
QReadLocker lock(&_containsLock); ReadLock lock(_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {
QWriteLocker laserLock(_laserPointerLocks[uid].get()); WriteLock laserLock(*_laserPointerLocks[uid]);
_laserPointers[uid]->setIncludeAvatars(includeAvatars); _laserPointers[uid]->setIncludeAvatars(includeAvatars);
} }
} }
void LaserPointerManager::setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) { void LaserPointerManager::setLockEndUUID(QUuid uid, QUuid objectID, const bool isOverlay) {
QReadLocker lock(&_containsLock); ReadLock lock(_containsLock);
if (_laserPointers.contains(uid)) { if (_laserPointers.contains(uid)) {
QWriteLocker laserLock(_laserPointerLocks[uid].get()); WriteLock laserLock(*_laserPointerLocks[uid]);
_laserPointers[uid]->setLockEndUUID(objectID, isOverlay); _laserPointers[uid]->setLockEndUUID(objectID, isOverlay);
} }
} }

View file

@ -11,9 +11,8 @@
#ifndef hifi_LaserPointerManager_h #ifndef hifi_LaserPointerManager_h
#define hifi_LaserPointerManager_h #define hifi_LaserPointerManager_h
#include <QHash>
#include <QString>
#include <memory> #include <memory>
#include <shared_mutex>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "LaserPointer.h" #include "LaserPointer.h"
@ -23,13 +22,13 @@ class RayPickResult;
class LaserPointerManager { class LaserPointerManager {
public: public:
QUuid createLaserPointer(const QVariantMap& rayProps, const QHash<QString, RenderState>& renderStates, QHash<QString, QPair<float, RenderState>>& defaultRenderStates, QUuid createLaserPointer(const QVariantMap& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates,
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled); const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool enabled);
void removeLaserPointer(const QUuid uid); void removeLaserPointer(const QUuid uid);
void enableLaserPointer(const QUuid uid); void enableLaserPointer(const QUuid uid);
void disableLaserPointer(const QUuid uid); void disableLaserPointer(const QUuid uid);
void setRenderState(QUuid uid, const QString& renderState); void setRenderState(QUuid uid, const std::string& renderState);
void editRenderState(QUuid uid, const QString& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps); void editRenderState(QUuid uid, const std::string& state, const QVariant& startProps, const QVariant& pathProps, const QVariant& endProps);
const RayPickResult getPrevRayPickResult(const QUuid uid); const RayPickResult getPrevRayPickResult(const QUuid uid);
void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities); void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities);
@ -45,12 +44,15 @@ public:
private: private:
QHash<QUuid, std::shared_ptr<LaserPointer>> _laserPointers; QHash<QUuid, std::shared_ptr<LaserPointer>> _laserPointers;
QHash<QUuid, std::shared_ptr<QReadWriteLock>> _laserPointerLocks; QHash<QUuid, std::shared_ptr<std::shared_mutex>> _laserPointerLocks;
QReadWriteLock _addLock; std::shared_mutex _addLock;
QQueue<QPair<QUuid, std::shared_ptr<LaserPointer>>> _laserPointersToAdd; std::queue<std::pair<QUuid, std::shared_ptr<LaserPointer>>> _laserPointersToAdd;
QReadWriteLock _removeLock; std::shared_mutex _removeLock;
QQueue<QUuid> _laserPointersToRemove; std::queue<QUuid> _laserPointersToRemove;
QReadWriteLock _containsLock; std::shared_mutex _containsLock;
typedef std::lock_guard<std::shared_mutex> WriteLock;
typedef std::shared_lock<std::shared_mutex> ReadLock;
}; };

View file

@ -40,30 +40,30 @@ QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& propert
enabled = propertyMap["enabled"].toBool(); enabled = propertyMap["enabled"].toBool();
} }
QHash<QString, RenderState> renderStates; LaserPointer::RenderStateMap renderStates;
if (propertyMap["renderStates"].isValid()) { if (propertyMap["renderStates"].isValid()) {
QList<QVariant> renderStateVariants = propertyMap["renderStates"].toList(); QList<QVariant> renderStateVariants = propertyMap["renderStates"].toList();
for (QVariant& renderStateVariant : renderStateVariants) { for (QVariant& renderStateVariant : renderStateVariants) {
if (renderStateVariant.isValid()) { if (renderStateVariant.isValid()) {
QVariantMap renderStateMap = renderStateVariant.toMap(); QVariantMap renderStateMap = renderStateVariant.toMap();
if (renderStateMap["name"].isValid()) { if (renderStateMap["name"].isValid()) {
QString name = renderStateMap["name"].toString(); std::string name = renderStateMap["name"].toString().toStdString();
renderStates[name] = buildRenderState(renderStateMap); renderStates[name] = buildRenderState(renderStateMap);
} }
} }
} }
} }
QHash<QString, QPair<float, RenderState>> defaultRenderStates; LaserPointer::DefaultRenderStateMap defaultRenderStates;
if (propertyMap["defaultRenderStates"].isValid()) { if (propertyMap["defaultRenderStates"].isValid()) {
QList<QVariant> renderStateVariants = propertyMap["defaultRenderStates"].toList(); QList<QVariant> renderStateVariants = propertyMap["defaultRenderStates"].toList();
for (QVariant& renderStateVariant : renderStateVariants) { for (QVariant& renderStateVariant : renderStateVariants) {
if (renderStateVariant.isValid()) { if (renderStateVariant.isValid()) {
QVariantMap renderStateMap = renderStateVariant.toMap(); QVariantMap renderStateMap = renderStateVariant.toMap();
if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) { if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) {
QString name = renderStateMap["name"].toString(); std::string name = renderStateMap["name"].toString().toStdString();
float distance = renderStateMap["distance"].toFloat(); float distance = renderStateMap["distance"].toFloat();
defaultRenderStates[name] = QPair<float, RenderState>(distance, buildRenderState(renderStateMap)); defaultRenderStates[name] = std::pair<float, RenderState>(distance, buildRenderState(renderStateMap));
} }
} }
} }
@ -90,7 +90,7 @@ void LaserPointerScriptingInterface::editRenderState(QUuid uid, const QString& r
endProps = propMap["end"]; endProps = propMap["end"];
} }
qApp->getLaserPointerManager().editRenderState(uid, renderState, startProps, pathProps, endProps); qApp->getLaserPointerManager().editRenderState(uid, renderState.toStdString(), startProps, pathProps, endProps);
} }
const RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) { const RenderState LaserPointerScriptingInterface::buildRenderState(const QVariantMap& propMap) {

View file

@ -28,7 +28,7 @@ public slots:
Q_INVOKABLE void disableLaserPointer(QUuid uid) { qApp->getLaserPointerManager().disableLaserPointer(uid); } Q_INVOKABLE void disableLaserPointer(QUuid uid) { qApp->getLaserPointerManager().disableLaserPointer(uid); }
Q_INVOKABLE void removeLaserPointer(QUuid uid) { qApp->getLaserPointerManager().removeLaserPointer(uid); } Q_INVOKABLE void removeLaserPointer(QUuid uid) { qApp->getLaserPointerManager().removeLaserPointer(uid); }
Q_INVOKABLE void editRenderState(QUuid uid, const QString& renderState, const QVariant& properties); Q_INVOKABLE void editRenderState(QUuid uid, const QString& renderState, const QVariant& properties);
Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { qApp->getLaserPointerManager().setRenderState(uid, renderState); } Q_INVOKABLE void setRenderState(QUuid uid, const QString& renderState) { qApp->getLaserPointerManager().setRenderState(uid, renderState.toStdString()); }
Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); } Q_INVOKABLE RayPickResult getPrevRayPickResult(QUuid uid) { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { qApp->getLaserPointerManager().setIgnoreEntities(uid, ignoreEntities); } Q_INVOKABLE void setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { qApp->getLaserPointerManager().setIgnoreEntities(uid, ignoreEntities); }

View file

@ -14,7 +14,7 @@
#include "Application.h" #include "Application.h"
#include "display-plugins/CompositorHelper.h" #include "display-plugins/CompositorHelper.h"
MouseRayPick::MouseRayPick(const uint16_t filter, const float maxDistance, const bool enabled) : MouseRayPick::MouseRayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) :
RayPick(filter, maxDistance, enabled) RayPick(filter, maxDistance, enabled)
{ {
} }

View file

@ -16,7 +16,7 @@
class MouseRayPick : public RayPick { class MouseRayPick : public RayPick {
public: public:
MouseRayPick(const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); MouseRayPick(const RayPickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false);
const PickRay getPickRay(bool& valid) const override; const PickRay getPickRay(bool& valid) const override;
}; };

View file

@ -10,7 +10,7 @@
// //
#include "RayPick.h" #include "RayPick.h"
RayPick::RayPick(const uint16_t filter, const float maxDistance, const bool enabled) : RayPick::RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled) :
_filter(filter), _filter(filter),
_maxDistance(maxDistance), _maxDistance(maxDistance),
_enabled(enabled) _enabled(enabled)

View file

@ -17,17 +17,87 @@
#include "EntityItemID.h" #include "EntityItemID.h"
#include "ui/overlays/Overlay.h" #include "ui/overlays/Overlay.h"
class RayPickFilter {
public:
enum FlagBit {
PICK_NOTHING = 0,
PICK_ENTITIES,
PICK_OVERLAYS,
PICK_AVATARS,
PICK_HUD,
PICK_COURSE, // if not set, does precise intersection, otherwise, doesn't
PICK_INCLUDE_INVISIBLE, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements
PICK_INCLUDE_NONCOLLIDABLE, // if not set, will not intersect noncollidable elements, otherwise, intersects both collidable and noncollidable elements
// NOT YET IMPLEMENTED
PICK_ALL_INTERSECTIONS, // if not set, returns closest intersection, otherwise, returns list of all intersections
NUM_FLAGS, // Not a valid flag
};
typedef std::bitset<NUM_FLAGS> Flags;
// The key is the Flags
Flags _flags;
RayPickFilter() : _flags(PICK_NOTHING) {}
RayPickFilter(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 doesPickNothing() const { return _flags[PICK_NOTHING]; }
bool doesPickEntities() const { return _flags[PICK_ENTITIES]; }
bool doesPickOverlays() const { return _flags[PICK_OVERLAYS]; }
bool doesPickAvatars() const { return _flags[PICK_AVATARS]; }
bool doesPickHUD() const { return _flags[PICK_HUD]; }
bool doesPickCourse() const { return _flags[PICK_COURSE]; }
bool doesPickInvisible() const { return _flags[PICK_INCLUDE_INVISIBLE]; }
bool doesPickNonCollidable() const { return _flags[PICK_INCLUDE_NONCOLLIDABLE]; }
bool doesWantAllIntersections() const { return _flags[PICK_ALL_INTERSECTIONS]; }
// Helpers for RayPickManager
Flags getEntityFlags() const {
Flags toReturn(PICK_ENTITIES);
if (doesPickInvisible()) {
toReturn |= Flags(PICK_INCLUDE_INVISIBLE);
}
if (doesPickNonCollidable()) {
toReturn |= Flags(PICK_INCLUDE_NONCOLLIDABLE);
}
return toReturn;
}
Flags getOverlayFlags() const {
Flags toReturn(PICK_OVERLAYS);
if (doesPickInvisible()) {
toReturn |= Flags(PICK_INCLUDE_INVISIBLE);
}
if (doesPickNonCollidable()) {
toReturn |= Flags(PICK_INCLUDE_NONCOLLIDABLE);
}
return toReturn;
}
Flags getAvatarFlags() const { return Flags(PICK_AVATARS); }
Flags getHUDFlags() const { return Flags(PICK_HUD); }
static unsigned int getBitMask(FlagBit bit) { return 1 << bit; }
};
class RayPick { class RayPick {
public: public:
RayPick(const uint16_t filter, const float maxDistance, const bool enabled); RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled);
virtual const PickRay getPickRay(bool& valid) const = 0; virtual const PickRay getPickRay(bool& valid) const = 0;
void enable() { _enabled = true; } void enable() { _enabled = true; }
void disable() { _enabled = false; } void disable() { _enabled = false; }
const uint16_t& getFilter() { return _filter; } const RayPickFilter& getFilter() { return _filter; }
const float& getMaxDistance() { return _maxDistance; } const float& getMaxDistance() { return _maxDistance; }
const bool& isEnabled() { return _enabled; } const bool& isEnabled() { return _enabled; }
const RayPickResult& getPrevRayPickResult() { return _prevResult; } const RayPickResult& getPrevRayPickResult() { return _prevResult; }
@ -48,7 +118,7 @@ public:
void setIncludeAvatars(const QScriptValue& includeAvatars) { _includeAvatars = qVectorEntityItemIDFromScriptValue(includeAvatars); } void setIncludeAvatars(const QScriptValue& includeAvatars) { _includeAvatars = qVectorEntityItemIDFromScriptValue(includeAvatars); }
private: private:
uint16_t _filter; RayPickFilter _filter;
float _maxDistance; float _maxDistance;
bool _enabled; bool _enabled;
RayPickResult _prevResult; RayPickResult _prevResult;

View file

@ -10,8 +10,6 @@
// //
#include "RayPickManager.h" #include "RayPickManager.h"
#include "RayPick.h"
#include "Application.h" #include "Application.h"
#include "EntityScriptingInterface.h" #include "EntityScriptingInterface.h"
#include "ui/overlays/Overlays.h" #include "ui/overlays/Overlays.h"
@ -23,8 +21,8 @@
#include "StaticRayPick.h" #include "StaticRayPick.h"
#include "MouseRayPick.h" #include "MouseRayPick.h"
bool RayPickManager::checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, unsigned int mask) { bool RayPickManager::checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayPickFilter::Flags& mask) {
if (cache.contains(ray) && cache[ray].contains(mask)) { if (cache.contains(ray) && cache[ray].find(mask) != cache[ray].end()) {
if (cache[ray][mask].distance < res.distance) { if (cache[ray][mask].distance < res.distance) {
res = cache[ray][mask]; res = cache[ray][mask];
} }
@ -33,7 +31,7 @@ bool RayPickManager::checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& r
return false; return false;
} }
void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, unsigned int mask, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache) { void RayPickManager::cacheResult(const bool intersects, const RayPickResult& resTemp, const RayPickFilter::Flags& mask, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache) {
if (intersects) { if (intersects) {
cache[ray][mask] = resTemp; cache[ray][mask] = resTemp;
if (resTemp.distance < res.distance) { if (resTemp.distance < res.distance) {
@ -48,7 +46,7 @@ void RayPickManager::update() {
RayPickCache results; RayPickCache results;
for (auto& uid : _rayPicks.keys()) { for (auto& uid : _rayPicks.keys()) {
std::shared_ptr<RayPick> rayPick = _rayPicks[uid]; std::shared_ptr<RayPick> rayPick = _rayPicks[uid];
if (!rayPick->isEnabled() || rayPick->getFilter() == RayPickMask::PICK_NOTHING || rayPick->getMaxDistance() < 0.0f) { if (!rayPick->isEnabled() || rayPick->getFilter().doesPickNothing() || rayPick->getMaxDistance() < 0.0f) {
continue; continue;
} }
@ -62,12 +60,12 @@ void RayPickManager::update() {
QPair<glm::vec3, glm::vec3> rayKey = QPair<glm::vec3, glm::vec3>(ray.origin, ray.direction); QPair<glm::vec3, glm::vec3> rayKey = QPair<glm::vec3, glm::vec3>(ray.origin, ray.direction);
RayPickResult res; RayPickResult res;
if (rayPick->getFilter() & RayPickMask::PICK_ENTITIES) { if (rayPick->getFilter().doesPickEntities()) {
RayToEntityIntersectionResult entityRes; RayToEntityIntersectionResult entityRes;
bool fromCache = true; bool fromCache = true;
unsigned int invisible = rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE; bool invisible = rayPick->getFilter().doesPickInvisible();
unsigned int noncollidable = rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; bool noncollidable = rayPick->getFilter().doesPickNonCollidable();
unsigned int entityMask = RayPickMask::PICK_ENTITIES | invisible | noncollidable; RayPickFilter::Flags entityMask = rayPick->getFilter().getEntityFlags();
if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) { if (!checkAndCompareCachedResults(rayKey, results, res, entityMask)) {
entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersection(ray, true, rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !noncollidable); entityRes = DependencyManager::get<EntityScriptingInterface>()->findRayIntersection(ray, true, rayPick->getIncludeEntites(), rayPick->getIgnoreEntites(), !invisible, !noncollidable);
fromCache = false; fromCache = false;
@ -79,12 +77,12 @@ void RayPickManager::update() {
} }
} }
if (rayPick->getFilter() & RayPickMask::PICK_OVERLAYS) { if (rayPick->getFilter().doesPickOverlays()) {
RayToOverlayIntersectionResult overlayRes; RayToOverlayIntersectionResult overlayRes;
bool fromCache = true; bool fromCache = true;
unsigned int invisible = rayPick->getFilter() & RayPickMask::PICK_INCLUDE_INVISIBLE; bool invisible = rayPick->getFilter().doesPickInvisible();
unsigned int noncollidable = rayPick->getFilter() & RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; bool noncollidable = rayPick->getFilter().doesPickNonCollidable();
unsigned int overlayMask = RayPickMask::PICK_OVERLAYS | invisible | noncollidable; RayPickFilter::Flags overlayMask = rayPick->getFilter().getOverlayFlags();
if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) { if (!checkAndCompareCachedResults(rayKey, results, res, overlayMask)) {
overlayRes = qApp->getOverlays().findRayIntersection(ray, true, rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !noncollidable); overlayRes = qApp->getOverlays().findRayIntersection(ray, true, rayPick->getIncludeOverlays(), rayPick->getIgnoreOverlays(), !invisible, !noncollidable);
fromCache = false; fromCache = false;
@ -96,22 +94,24 @@ void RayPickManager::update() {
} }
} }
if (rayPick->getFilter() & RayPickMask::PICK_AVATARS) { if (rayPick->getFilter().doesPickAvatars()) {
if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_AVATARS)) { RayPickFilter::Flags avatarMask = rayPick->getFilter().getAvatarFlags();
if (!checkAndCompareCachedResults(rayKey, results, res, avatarMask)) {
RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersection(ray, rayPick->getIncludeAvatars(), rayPick->getIgnoreAvatars()); RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersection(ray, rayPick->getIncludeAvatars(), rayPick->getIgnoreAvatars());
cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection), RayPickMask::PICK_AVATARS, res, rayKey, results); cacheResult(avatarRes.intersects, RayPickResult(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection), avatarMask, res, rayKey, results);
} }
} }
// Can't intersect with HUD in desktop mode // Can't intersect with HUD in desktop mode
if (rayPick->getFilter() & RayPickMask::PICK_HUD && DependencyManager::get<HMDScriptingInterface>()->isHMDMode()) { if (rayPick->getFilter().doesPickHUD() && DependencyManager::get<HMDScriptingInterface>()->isHMDMode()) {
if (!checkAndCompareCachedResults(rayKey, results, res, RayPickMask::PICK_HUD)) { RayPickFilter::Flags hudMask = rayPick->getFilter().getHUDFlags();
if (!checkAndCompareCachedResults(rayKey, results, res, hudMask)) {
glm::vec3 hudRes = DependencyManager::get<HMDScriptingInterface>()->calculateRayUICollisionPoint(ray.origin, ray.direction); glm::vec3 hudRes = DependencyManager::get<HMDScriptingInterface>()->calculateRayUICollisionPoint(ray.origin, ray.direction);
cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes), RayPickMask::PICK_HUD, res, rayKey, results); cacheResult(true, RayPickResult(IntersectionType::HUD, 0, glm::distance(ray.origin, hudRes), hudRes), hudMask, res, rayKey, results);
} }
} }
QWriteLocker lock(_rayPickLocks[uid].get()); WriteLock lock(*_rayPickLocks[uid]);
if (rayPick->getMaxDistance() == 0.0f || (rayPick->getMaxDistance() > 0.0f && res.distance < rayPick->getMaxDistance())) { if (rayPick->getMaxDistance() == 0.0f || (rayPick->getMaxDistance() > 0.0f && res.distance < rayPick->getMaxDistance())) {
rayPick->setRayPickResult(res); rayPick->setRayPickResult(res);
} else { } else {
@ -119,20 +119,22 @@ void RayPickManager::update() {
} }
} }
QWriteLocker containsLock(&_containsLock); WriteLock containsLock(_containsLock);
{ {
QWriteLocker lock(&_addLock); WriteLock lock(_addLock);
while (!_rayPicksToAdd.isEmpty()) { while (!_rayPicksToAdd.empty()) {
QPair<QUuid, std::shared_ptr<RayPick>> rayPickToAdd = _rayPicksToAdd.dequeue(); std::pair<QUuid, std::shared_ptr<RayPick>> rayPickToAdd = _rayPicksToAdd.front();
_rayPicksToAdd.pop();
_rayPicks[rayPickToAdd.first] = rayPickToAdd.second; _rayPicks[rayPickToAdd.first] = rayPickToAdd.second;
_rayPickLocks[rayPickToAdd.first] = std::make_shared<QReadWriteLock>(); _rayPickLocks[rayPickToAdd.first] = std::make_shared<std::shared_mutex>();
} }
} }
{ {
QWriteLocker lock(&_removeLock); WriteLock lock(_removeLock);
while (!_rayPicksToRemove.isEmpty()) { while (!_rayPicksToRemove.empty()) {
QUuid uid = _rayPicksToRemove.dequeue(); QUuid uid = _rayPicksToRemove.front();
_rayPicksToRemove.pop();
_rayPicks.remove(uid); _rayPicks.remove(uid);
_rayPickLocks.remove(uid); _rayPickLocks.remove(uid);
} }
@ -145,9 +147,9 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) {
enabled = rayProps["enabled"].toBool(); enabled = rayProps["enabled"].toBool();
} }
uint16_t filter = 0; RayPickFilter filter = RayPickFilter();
if (rayProps["filter"].isValid()) { if (rayProps["filter"].isValid()) {
filter = rayProps["filter"].toUInt(); filter = RayPickFilter(rayProps["filter"].toUInt());
} }
float maxDistance = 0.0f; float maxDistance = 0.0f;
@ -156,7 +158,7 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) {
} }
if (rayProps["joint"].isValid()) { if (rayProps["joint"].isValid()) {
QString jointName = rayProps["joint"].toString(); std::string jointName = rayProps["joint"].toString().toStdString();
if (jointName != "Mouse") { if (jointName != "Mouse") {
// x = upward, y = forward, z = lateral // x = upward, y = forward, z = lateral
@ -170,14 +172,14 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) {
dirOffset = vec3FromVariant(rayProps["dirOffset"]); dirOffset = vec3FromVariant(rayProps["dirOffset"]);
} }
QWriteLocker lock(&_addLock); WriteLock lock(_addLock);
QUuid id = QUuid::createUuid(); QUuid id = QUuid::createUuid();
_rayPicksToAdd.enqueue(QPair<QUuid, std::shared_ptr<RayPick>>(id, std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled))); _rayPicksToAdd.push(std::pair<QUuid, std::shared_ptr<RayPick>>(id, std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled)));
return id; return id;
} else { } else {
QWriteLocker lock(&_addLock); WriteLock lock(_addLock);
QUuid id = QUuid::createUuid(); QUuid id = QUuid::createUuid();
_rayPicksToAdd.enqueue(QPair<QUuid, std::shared_ptr<RayPick>>(id, std::make_shared<MouseRayPick>(filter, maxDistance, enabled))); _rayPicksToAdd.push(std::pair<QUuid, std::shared_ptr<RayPick>>(id, std::make_shared<MouseRayPick>(filter, maxDistance, enabled)));
return id; return id;
} }
} else if (rayProps["position"].isValid()) { } else if (rayProps["position"].isValid()) {
@ -188,9 +190,9 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) {
direction = vec3FromVariant(rayProps["direction"]); direction = vec3FromVariant(rayProps["direction"]);
} }
QWriteLocker lock(&_addLock); WriteLock lock(_addLock);
QUuid id = QUuid::createUuid(); QUuid id = QUuid::createUuid();
_rayPicksToAdd.enqueue(QPair<QUuid, std::shared_ptr<RayPick>>(id, std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled))); _rayPicksToAdd.push(std::pair<QUuid, std::shared_ptr<RayPick>>(id, std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled)));
return id; return id;
} }
@ -198,28 +200,28 @@ QUuid RayPickManager::createRayPick(const QVariantMap& rayProps) {
} }
void RayPickManager::removeRayPick(const QUuid uid) { void RayPickManager::removeRayPick(const QUuid uid) {
QWriteLocker lock(&_removeLock); WriteLock lock(_removeLock);
_rayPicksToRemove.enqueue(uid); _rayPicksToRemove.push(uid);
} }
void RayPickManager::enableRayPick(const QUuid uid) { void RayPickManager::enableRayPick(const QUuid uid) {
QReadLocker containsLock(&_containsLock); ReadLock containsLock(_containsLock);
if (_rayPicks.contains(uid)) { if (_rayPicks.contains(uid)) {
QWriteLocker rayPickLock(_rayPickLocks[uid].get()); WriteLock rayPickLock(*_rayPickLocks[uid]);
_rayPicks[uid]->enable(); _rayPicks[uid]->enable();
} }
} }
void RayPickManager::disableRayPick(const QUuid uid) { void RayPickManager::disableRayPick(const QUuid uid) {
QReadLocker containsLock(&_containsLock); ReadLock containsLock(_containsLock);
if (_rayPicks.contains(uid)) { if (_rayPicks.contains(uid)) {
QWriteLocker rayPickLock(_rayPickLocks[uid].get()); WriteLock rayPickLock(*_rayPickLocks[uid]);
_rayPicks[uid]->disable(); _rayPicks[uid]->disable();
} }
} }
const PickRay RayPickManager::getPickRay(const QUuid uid) { const PickRay RayPickManager::getPickRay(const QUuid uid) {
QReadLocker containsLock(&_containsLock); ReadLock containsLock(_containsLock);
if (_rayPicks.contains(uid)) { if (_rayPicks.contains(uid)) {
bool valid; bool valid;
PickRay pickRay = _rayPicks[uid]->getPickRay(valid); PickRay pickRay = _rayPicks[uid]->getPickRay(valid);
@ -231,58 +233,58 @@ const PickRay RayPickManager::getPickRay(const QUuid uid) {
} }
const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) { const RayPickResult RayPickManager::getPrevRayPickResult(const QUuid uid) {
QReadLocker containsLock(&_containsLock); ReadLock containsLock(_containsLock);
if (_rayPicks.contains(uid)) { if (_rayPicks.contains(uid)) {
QReadLocker lock(_rayPickLocks[uid].get()); ReadLock lock(*_rayPickLocks[uid]);
return _rayPicks[uid]->getPrevRayPickResult(); return _rayPicks[uid]->getPrevRayPickResult();
} }
return RayPickResult(); return RayPickResult();
} }
void RayPickManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) { void RayPickManager::setIgnoreEntities(QUuid uid, const QScriptValue& ignoreEntities) {
QReadLocker containsLock(&_containsLock); ReadLock containsLock(_containsLock);
if (_rayPicks.contains(uid)) { if (_rayPicks.contains(uid)) {
QWriteLocker lock(_rayPickLocks[uid].get()); WriteLock lock(*_rayPickLocks[uid]);
_rayPicks[uid]->setIgnoreEntities(ignoreEntities); _rayPicks[uid]->setIgnoreEntities(ignoreEntities);
} }
} }
void RayPickManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) { void RayPickManager::setIncludeEntities(QUuid uid, const QScriptValue& includeEntities) {
QReadLocker containsLock(&_containsLock); ReadLock containsLock(_containsLock);
if (_rayPicks.contains(uid)) { if (_rayPicks.contains(uid)) {
QWriteLocker lock(_rayPickLocks[uid].get()); WriteLock lock(*_rayPickLocks[uid]);
_rayPicks[uid]->setIncludeEntities(includeEntities); _rayPicks[uid]->setIncludeEntities(includeEntities);
} }
} }
void RayPickManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) { void RayPickManager::setIgnoreOverlays(QUuid uid, const QScriptValue& ignoreOverlays) {
QReadLocker containsLock(&_containsLock); ReadLock containsLock(_containsLock);
if (_rayPicks.contains(uid)) { if (_rayPicks.contains(uid)) {
QWriteLocker lock(_rayPickLocks[uid].get()); WriteLock lock(*_rayPickLocks[uid]);
_rayPicks[uid]->setIgnoreOverlays(ignoreOverlays); _rayPicks[uid]->setIgnoreOverlays(ignoreOverlays);
} }
} }
void RayPickManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) { void RayPickManager::setIncludeOverlays(QUuid uid, const QScriptValue& includeOverlays) {
QReadLocker containsLock(&_containsLock); ReadLock containsLock(_containsLock);
if (_rayPicks.contains(uid)) { if (_rayPicks.contains(uid)) {
QWriteLocker lock(_rayPickLocks[uid].get()); WriteLock lock(*_rayPickLocks[uid]);
_rayPicks[uid]->setIncludeOverlays(includeOverlays); _rayPicks[uid]->setIncludeOverlays(includeOverlays);
} }
} }
void RayPickManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) { void RayPickManager::setIgnoreAvatars(QUuid uid, const QScriptValue& ignoreAvatars) {
QReadLocker containsLock(&_containsLock); ReadLock containsLock(_containsLock);
if (_rayPicks.contains(uid)) { if (_rayPicks.contains(uid)) {
QWriteLocker lock(_rayPickLocks[uid].get()); WriteLock lock(*_rayPickLocks[uid]);
_rayPicks[uid]->setIgnoreAvatars(ignoreAvatars); _rayPicks[uid]->setIgnoreAvatars(ignoreAvatars);
} }
} }
void RayPickManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) { void RayPickManager::setIncludeAvatars(QUuid uid, const QScriptValue& includeAvatars) {
QReadLocker containsLock(&_containsLock); ReadLock containsLock(_containsLock);
if (_rayPicks.contains(uid)) { if (_rayPicks.contains(uid)) {
QWriteLocker lock(_rayPickLocks[uid].get()); WriteLock lock(*_rayPickLocks[uid]);
_rayPicks[uid]->setIncludeAvatars(includeAvatars); _rayPicks[uid]->setIncludeAvatars(includeAvatars);
} }
} }

View file

@ -11,35 +11,20 @@
#ifndef hifi_RayPickManager_h #ifndef hifi_RayPickManager_h
#define hifi_RayPickManager_h #define hifi_RayPickManager_h
#include <QHash> #include "RayPick.h"
#include <QQueue>
#include <QReadWriteLock>
#include <memory> #include <memory>
#include <shared_mutex>
#include <QtCore/QObject> #include <QtCore/QObject>
#include "RegisteredMetaTypes.h" #include "RegisteredMetaTypes.h"
#include "DependencyManager.h" #include "DependencyManager.h"
class RayPick; #include <unordered_map>
#include <queue>
class RayPickResult; class RayPickResult;
enum RayPickMask {
PICK_NOTHING = 0,
PICK_ENTITIES = 1 << 0,
PICK_OVERLAYS = 1 << 1,
PICK_AVATARS = 1 << 2,
PICK_HUD = 1 << 3,
// NOT YET IMPLEMENTED
PICK_BOUNDING_BOX = 1 << 4, // if not set, picks again physics mesh (can't pick against graphics mesh, yet)
PICK_INCLUDE_INVISIBLE = 1 << 5, // if not set, will not intersect invisible elements, otherwise, intersects both visible and invisible elements
PICK_INCLUDE_NONCOLLIDABLE = 1 << 6, // if not set, will not intersect noncollidable elements, otherwise, intersects both collidable and noncollidable elements
// NOT YET IMPLEMENTED
PICK_ALL_INTERSECTIONS = 1 << 7 // if not set, returns closest intersection, otherwise, returns list of all intersections
};
class RayPickManager : public QObject, public Dependency { class RayPickManager : public QObject, public Dependency {
Q_OBJECT Q_OBJECT
Q_PROPERTY(unsigned int PICK_NOTHING READ PICK_NOTHING CONSTANT) Q_PROPERTY(unsigned int PICK_NOTHING READ PICK_NOTHING CONSTANT)
@ -78,34 +63,37 @@ public slots:
private: private:
QHash<QUuid, std::shared_ptr<RayPick>> _rayPicks; QHash<QUuid, std::shared_ptr<RayPick>> _rayPicks;
QHash<QUuid, std::shared_ptr<QReadWriteLock>> _rayPickLocks; QHash<QUuid, std::shared_ptr<std::shared_mutex>> _rayPickLocks;
QReadWriteLock _addLock; std::shared_mutex _addLock;
QQueue<QPair<QUuid, std::shared_ptr<RayPick>>> _rayPicksToAdd; std::queue<std::pair<QUuid, std::shared_ptr<RayPick>>> _rayPicksToAdd;
QReadWriteLock _removeLock; std::shared_mutex _removeLock;
QQueue<QUuid> _rayPicksToRemove; std::queue<QUuid> _rayPicksToRemove;
QReadWriteLock _containsLock; std::shared_mutex _containsLock;
typedef QHash<QPair<glm::vec3, glm::vec3>, QHash<unsigned int, RayPickResult>> RayPickCache; typedef QHash<QPair<glm::vec3, glm::vec3>, std::unordered_map<RayPickFilter::Flags, RayPickResult>> RayPickCache;
// Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer // Returns true if this ray exists in the cache, and if it does, update res if the cached result is closer
bool checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, unsigned int mask); bool checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayPickFilter::Flags& mask);
void cacheResult(const bool intersects, const RayPickResult& resTemp, unsigned int mask, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache); void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayPickFilter::Flags& mask, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache);
unsigned int PICK_NOTHING() { return RayPickMask::PICK_NOTHING; } unsigned int PICK_NOTHING() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_NOTHING); }
unsigned int PICK_ENTITIES() { return RayPickMask::PICK_ENTITIES; } unsigned int PICK_ENTITIES() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ENTITIES); }
unsigned int PICK_OVERLAYS() { return RayPickMask::PICK_OVERLAYS; } unsigned int PICK_OVERLAYS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_OVERLAYS); }
unsigned int PICK_AVATARS() { return RayPickMask::PICK_AVATARS; } unsigned int PICK_AVATARS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_AVATARS); }
unsigned int PICK_HUD() { return RayPickMask::PICK_HUD; } unsigned int PICK_HUD() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_HUD); }
unsigned int PICK_BOUNDING_BOX() { return RayPickMask::PICK_BOUNDING_BOX; } unsigned int PICK_BOUNDING_BOX() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_COURSE); }
unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickMask::PICK_INCLUDE_INVISIBLE; } unsigned int PICK_INCLUDE_INVISIBLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_INVISIBLE); }
unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickMask::PICK_INCLUDE_NONCOLLIDABLE; } unsigned int PICK_INCLUDE_NONCOLLIDABLE() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_INCLUDE_NONCOLLIDABLE); }
unsigned int PICK_ALL_INTERSECTIONS() { return RayPickMask::PICK_ALL_INTERSECTIONS; } unsigned int PICK_ALL_INTERSECTIONS() { return RayPickFilter::getBitMask(RayPickFilter::FlagBit::PICK_ALL_INTERSECTIONS); }
unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; } unsigned int INTERSECTED_NONE() { return IntersectionType::NONE; }
unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; } unsigned int INTERSECTED_ENTITY() { return IntersectionType::ENTITY; }
unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; } unsigned int INTERSECTED_OVERLAY() { return IntersectionType::OVERLAY; }
unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; } unsigned int INTERSECTED_AVATAR() { return IntersectionType::AVATAR; }
unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; } unsigned int INTERSECTED_HUD() { return IntersectionType::HUD; }
typedef std::lock_guard<std::shared_mutex> WriteLock;
typedef std::shared_lock<std::shared_mutex> ReadLock;
}; };
#endif // hifi_RayPickManager_h #endif // hifi_RayPickManager_h

View file

@ -10,7 +10,7 @@
// //
#include "StaticRayPick.h" #include "StaticRayPick.h"
StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance, const bool enabled) : StaticRayPick::StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance, const bool enabled) :
RayPick(filter, maxDistance, enabled), RayPick(filter, maxDistance, enabled),
_pickRay(position, direction) _pickRay(position, direction)
{ {

View file

@ -16,7 +16,7 @@
class StaticRayPick : public RayPick { class StaticRayPick : public RayPick {
public: public:
StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const uint16_t filter, const float maxDistance = 0.0f, const bool enabled = false); StaticRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, const float maxDistance = 0.0f, const bool enabled = false);
const PickRay getPickRay(bool& valid) const override; const PickRay getPickRay(bool& valid) const override;