mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
merge from master
This commit is contained in:
commit
a44e8efb99
46 changed files with 1311 additions and 967 deletions
|
@ -194,8 +194,13 @@
|
|||
#include <EntityScriptClient.h>
|
||||
#include <ModelScriptingInterface.h>
|
||||
|
||||
#include <pointers/PickManager.h>
|
||||
#include <pointers/PointerManager.h>
|
||||
#include <raypick/RayPickScriptingInterface.h>
|
||||
#include <raypick/LaserPointerScriptingInterface.h>
|
||||
#include <raypick/PickScriptingInterface.h>
|
||||
#include <raypick/PointerScriptingInterface.h>
|
||||
#include <raypick/MouseRayPick.h>
|
||||
|
||||
#include <FadeEffect.h>
|
||||
|
||||
|
@ -698,8 +703,12 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
|
||||
DependencyManager::set<FadeEffect>();
|
||||
|
||||
DependencyManager::set<PickManager>();
|
||||
DependencyManager::set<PointerManager>();
|
||||
DependencyManager::set<LaserPointerScriptingInterface>();
|
||||
DependencyManager::set<RayPickScriptingInterface>();
|
||||
DependencyManager::set<PointerScriptingInterface>();
|
||||
DependencyManager::set<PickScriptingInterface>();
|
||||
|
||||
return previousSessionCrashed;
|
||||
}
|
||||
|
@ -1800,25 +1809,29 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
connect(&_myCamera, &Camera::modeUpdated, this, &Application::cameraModeChanged);
|
||||
|
||||
DependencyManager::get<PickManager>()->setShouldPickHUDOperator([&]() { return DependencyManager::get<HMDScriptingInterface>()->isHMDMode(); });
|
||||
|
||||
// Setup the mouse ray pick and related operators
|
||||
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(_rayPickManager.createRayPick(
|
||||
RayPickFilter(DependencyManager::get<RayPickScriptingInterface>()->PICK_ENTITIES() | DependencyManager::get<RayPickScriptingInterface>()->PICK_INCLUDE_NONCOLLIDABLE()),
|
||||
0.0f, true));
|
||||
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickID(DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<MouseRayPick>(
|
||||
PickFilter(PickScriptingInterface::PICK_ENTITIES() | PickScriptingInterface::PICK_INCLUDE_NONCOLLIDABLE()), 0.0f, true)));
|
||||
DependencyManager::get<EntityTreeRenderer>()->setMouseRayPickResultOperator([&](QUuid rayPickID) {
|
||||
RayToEntityIntersectionResult entityResult;
|
||||
RayPickResult result = _rayPickManager.getPrevRayPickResult(rayPickID);
|
||||
entityResult.intersects = result.type != DependencyManager::get<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<EntityTreeRenderer>()->getTree()->findEntityByID(entityResult.entityID);
|
||||
entityResult.intersects = false;
|
||||
QVariantMap result = DependencyManager::get<PickManager>()->getPrevPickResult(rayPickID);
|
||||
if (result["type"].isValid()) {
|
||||
entityResult.intersects = result["type"] != PickScriptingInterface::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<EntityTreeRenderer>()->getTree()->findEntityByID(entityResult.entityID);
|
||||
}
|
||||
}
|
||||
return entityResult;
|
||||
});
|
||||
DependencyManager::get<EntityTreeRenderer>()->setSetPrecisionPickingOperator([&](QUuid rayPickID, bool value) {
|
||||
_rayPickManager.setPrecisionPicking(rayPickID, value);
|
||||
DependencyManager::get<PickManager>()->setPrecisionPicking(rayPickID, value);
|
||||
});
|
||||
|
||||
// Preload Tablet sounds
|
||||
|
@ -4936,13 +4949,13 @@ 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");
|
||||
DependencyManager::get<PickManager>()->update();
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE(app, "LaserPointerManager");
|
||||
_laserPointerManager.update();
|
||||
PROFILE_RANGE(app, "PointerManager");
|
||||
DependencyManager::get<PointerManager>()->update();
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -5821,6 +5834,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
|||
|
||||
scriptEngine->registerGlobalObject("RayPick", DependencyManager::get<RayPickScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("LaserPointers", DependencyManager::get<LaserPointerScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("Picks", DependencyManager::get<PickScriptingInterface>().data());
|
||||
scriptEngine->registerGlobalObject("Pointers", DependencyManager::get<PointerScriptingInterface>().data());
|
||||
|
||||
// Caches
|
||||
scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCache>().data());
|
||||
|
|
|
@ -70,9 +70,6 @@
|
|||
#include "ui/overlays/Overlays.h"
|
||||
#include "UndoStackScriptingInterface.h"
|
||||
|
||||
#include "raypick/RayPickManager.h"
|
||||
#include "raypick/LaserPointerManager.h"
|
||||
|
||||
#include <procedural/ProceduralSkybox.h>
|
||||
#include <model/Skybox.h>
|
||||
#include <ModelScriptingInterface.h>
|
||||
|
@ -286,9 +283,6 @@ public:
|
|||
QUrl getAvatarOverrideUrl() { return _avatarOverrideUrl; }
|
||||
bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; }
|
||||
|
||||
LaserPointerManager& getLaserPointerManager() { return _laserPointerManager; }
|
||||
RayPickManager& getRayPickManager() { return _rayPickManager; }
|
||||
|
||||
signals:
|
||||
void svoImportRequested(const QString& url);
|
||||
|
||||
|
@ -702,9 +696,6 @@ private:
|
|||
bool _saveAvatarOverrideUrl { false };
|
||||
QObject* _renderEventHandler{ nullptr };
|
||||
|
||||
RayPickManager _rayPickManager;
|
||||
LaserPointerManager _laserPointerManager;
|
||||
|
||||
friend class RenderEventHandler;
|
||||
|
||||
std::atomic<bool> _pendingIdleEvent { false };
|
||||
|
|
|
@ -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() const {
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
int jointIndex = myAvatar->getJointIndex(QString::fromStdString(_jointName));
|
||||
bool useAvatarHead = _jointName == "Avatar";
|
||||
|
@ -38,10 +38,8 @@ const PickRay JointRayPick::getPickRay(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();
|
||||
}
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
#ifndef hifi_JointRayPick_h
|
||||
#define hifi_JointRayPick_h
|
||||
|
||||
#include <pointers/rays/RayPick.h>
|
||||
#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() const override;
|
||||
|
||||
private:
|
||||
std::string _jointName;
|
||||
|
|
|
@ -12,21 +12,22 @@
|
|||
|
||||
#include "Application.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "RayPickScriptingInterface.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <pointers/PickManager.h>
|
||||
#include "PickScriptingInterface.h"
|
||||
|
||||
LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
|
||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled) :
|
||||
Pointer(DependencyManager::get<PickScriptingInterface>()->createRayPick(rayProps)),
|
||||
_renderingEnabled(enabled),
|
||||
_renderStates(renderStates),
|
||||
_defaultRenderStates(defaultRenderStates),
|
||||
_faceAvatar(faceAvatar),
|
||||
_centerEndY(centerEndY),
|
||||
_lockEnd(lockEnd),
|
||||
_distanceScaleEnd(distanceScaleEnd),
|
||||
_rayPickUID(DependencyManager::get<RayPickScriptingInterface>()->createRayPick(rayProps))
|
||||
_distanceScaleEnd(distanceScaleEnd)
|
||||
{
|
||||
|
||||
|
||||
for (auto& state : _renderStates) {
|
||||
if (!enabled || state.first != _currentRenderState) {
|
||||
disableRenderState(state.second);
|
||||
|
@ -40,8 +41,6 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende
|
|||
}
|
||||
|
||||
LaserPointer::~LaserPointer() {
|
||||
qApp->getRayPickManager().removeRayPick(_rayPickUID);
|
||||
|
||||
for (auto& renderState : _renderStates) {
|
||||
renderState.second.deleteOverlays();
|
||||
}
|
||||
|
@ -51,14 +50,14 @@ LaserPointer::~LaserPointer() {
|
|||
}
|
||||
|
||||
void LaserPointer::enable() {
|
||||
qApp->getRayPickManager().enableRayPick(_rayPickUID);
|
||||
Pointer::enable();
|
||||
withWriteLock([&] {
|
||||
_renderingEnabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::disable() {
|
||||
qApp->getRayPickManager().disableRayPick(_rayPickUID);
|
||||
Pointer::disable();
|
||||
withWriteLock([&] {
|
||||
_renderingEnabled = false;
|
||||
if (!_currentRenderState.empty()) {
|
||||
|
@ -106,10 +105,6 @@ void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant&
|
|||
}
|
||||
}
|
||||
|
||||
const RayPickResult LaserPointer::getPrevRayPickResult() {
|
||||
return qApp->getRayPickManager().getPrevRayPickResult(_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;
|
||||
|
@ -207,15 +202,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().getPrevRayPickResult(_rayPickUID);
|
||||
QVariantMap prevRayPickResult = DependencyManager::get<PickManager>()->getPrevPickResult(_pickUID);
|
||||
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);
|
||||
|
@ -223,13 +221,9 @@ void LaserPointer::update() {
|
|||
});
|
||||
}
|
||||
|
||||
void LaserPointer::setPrecisionPicking(const bool precisionPicking) {
|
||||
qApp->getRayPickManager().setPrecisionPicking(_rayPickUID, precisionPicking);
|
||||
}
|
||||
|
||||
void LaserPointer::setLaserLength(const float laserLength) {
|
||||
void LaserPointer::setLength(const float length) {
|
||||
withWriteLock([&] {
|
||||
_laserLength = laserLength;
|
||||
_laserLength = length;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -239,14 +233,6 @@ void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay) {
|
|||
});
|
||||
}
|
||||
|
||||
void LaserPointer::setIgnoreItems(const QVector<QUuid>& ignoreItems) const {
|
||||
qApp->getRayPickManager().setIgnoreItems(_rayPickUID, ignoreItems);
|
||||
}
|
||||
|
||||
void LaserPointer::setIncludeItems(const QVector<QUuid>& includeItems) const {
|
||||
qApp->getRayPickManager().setIncludeItems(_rayPickUID, includeItems);
|
||||
}
|
||||
|
||||
RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, const OverlayID& endID) :
|
||||
_startID(startID), _pathID(pathID), _endID(endID)
|
||||
{
|
||||
|
@ -273,3 +259,35 @@ void RenderState::deleteOverlays() {
|
|||
qApp->getOverlays().deleteOverlay(_endID);
|
||||
}
|
||||
}
|
||||
|
||||
RenderState LaserPointer::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);
|
||||
}
|
|
@ -14,12 +14,10 @@
|
|||
#include <QString>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
#include "ui/overlays/Overlay.h"
|
||||
|
||||
class RayPickResult;
|
||||
#include <pointers/Pointer.h>
|
||||
#include <pointers/Pick.h>
|
||||
|
||||
class RenderState {
|
||||
|
||||
|
@ -50,12 +48,9 @@ private:
|
|||
glm::vec3 _endDim;
|
||||
};
|
||||
|
||||
|
||||
class LaserPointer : public ReadWriteLockable {
|
||||
class LaserPointer : public Pointer {
|
||||
|
||||
public:
|
||||
using Pointer = std::shared_ptr<LaserPointer>;
|
||||
|
||||
typedef std::unordered_map<std::string, RenderState> RenderStateMap;
|
||||
typedef std::unordered_map<std::string, std::pair<float, RenderState>> DefaultRenderStateMap;
|
||||
|
||||
|
@ -63,23 +58,19 @@ public:
|
|||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled);
|
||||
~LaserPointer();
|
||||
|
||||
QUuid getRayUID() { return _rayPickUID; }
|
||||
void enable();
|
||||
void disable();
|
||||
const RayPickResult 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<QUuid>& ignoreItems) const;
|
||||
void setIncludeItems(const QVector<QUuid>& includeItems) const;
|
||||
void update() override;
|
||||
|
||||
void update();
|
||||
static RenderState buildRenderState(const QVariantMap& propMap);
|
||||
|
||||
private:
|
||||
bool _renderingEnabled;
|
||||
|
@ -93,8 +84,6 @@ private:
|
|||
bool _distanceScaleEnd;
|
||||
std::pair<QUuid, bool> _objectLockEnd { std::pair<QUuid, bool>(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);
|
||||
|
|
|
@ -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 distanceScaleEnd, const bool enabled) {
|
||||
QUuid result;
|
||||
std::shared_ptr<LaserPointer> laserPointer = std::make_shared<LaserPointer>(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, distanceScaleEnd, enabled);
|
||||
if (!laserPointer->getRayUID().isNull()) {
|
||||
result = QUuid::createUuid();
|
||||
withWriteLock([&] { _laserPointers[result] = laserPointer; });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
LaserPointer::Pointer LaserPointerManager::find(const QUuid& uid) const {
|
||||
return resultWithReadLock<LaserPointer::Pointer>([&] {
|
||||
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 RayPickResult LaserPointerManager::getPrevRayPickResult(const QUuid& uid) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
return laserPointer->getPrevRayPickResult();
|
||||
}
|
||||
return RayPickResult();
|
||||
}
|
||||
|
||||
void LaserPointerManager::update() {
|
||||
auto cachedLaserPointers = resultWithReadLock<QList<std::shared_ptr<LaserPointer>>>([&] {
|
||||
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<QUuid>& ignoreEntities) const {
|
||||
auto laserPointer = find(uid);
|
||||
if (laserPointer) {
|
||||
laserPointer->setIgnoreItems(ignoreEntities);
|
||||
}
|
||||
}
|
||||
|
||||
void LaserPointerManager::setIncludeItems(const QUuid& uid, const QVector<QUuid>& 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);
|
||||
}
|
||||
}
|
|
@ -1,51 +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 <memory>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
#include "LaserPointer.h"
|
||||
|
||||
class RayPickResult;
|
||||
|
||||
|
||||
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 distanceScaleEnd, 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 RayPickResult 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<QUuid>& ignoreEntities) const;
|
||||
void setIncludeItems(const QUuid& uid, const QVector<QUuid>& 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<QUuid, std::shared_ptr<LaserPointer>> _laserPointers;
|
||||
};
|
||||
|
||||
#endif // hifi_LaserPointerManager_h
|
|
@ -11,127 +11,20 @@
|
|||
|
||||
#include "LaserPointerScriptingInterface.h"
|
||||
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
#include <GLMHelpers.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include "RegisteredMetaTypes.h"
|
||||
#include "PointerScriptingInterface.h"
|
||||
|
||||
void LaserPointerScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) const {
|
||||
qApp->getLaserPointerManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
|
||||
DependencyManager::get<PointerManager>()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
|
||||
}
|
||||
void LaserPointerScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) const {
|
||||
qApp->getLaserPointerManager().setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
||||
DependencyManager::get<PointerManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
||||
}
|
||||
|
||||
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 distanceScaleEnd = false;
|
||||
if (propertyMap["distanceScaleEnd"].isValid()) {
|
||||
distanceScaleEnd = propertyMap["distanceScaleEnd"].toBool();
|
||||
}
|
||||
|
||||
bool enabled = false;
|
||||
if (propertyMap["enabled"].isValid()) {
|
||||
enabled = propertyMap["enabled"].toBool();
|
||||
}
|
||||
|
||||
LaserPointer::RenderStateMap renderStates;
|
||||
if (propertyMap["renderStates"].isValid()) {
|
||||
QList<QVariant> 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<QVariant> 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<float, RenderState>(distance, buildRenderState(renderStateMap));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return qApp->getLaserPointerManager().createLaserPointer(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, distanceScaleEnd, enabled);
|
||||
return DependencyManager::get<PointerScriptingInterface>()->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"];
|
||||
}
|
||||
|
||||
qApp->getLaserPointerManager().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<PointerScriptingInterface>()->editRenderState(uid, renderState, properties);
|
||||
}
|
|
@ -13,9 +13,8 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "RegisteredMetaTypes.h"
|
||||
#include "DependencyManager.h"
|
||||
#include "Application.h"
|
||||
#include <pointers/PointerManager.h>
|
||||
|
||||
class LaserPointerScriptingInterface : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
@ -23,22 +22,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<PointerManager>()->enablePointer(uid); }
|
||||
Q_INVOKABLE void disableLaserPointer(const QUuid& uid) const { DependencyManager::get<PointerManager>()->disablePointer(uid); }
|
||||
Q_INVOKABLE void removeLaserPointer(const QUuid& uid) const { DependencyManager::get<PointerManager>()->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 RayPickResult getPrevRayPickResult(QUuid uid) const { return qApp->getLaserPointerManager().getPrevRayPickResult(uid); }
|
||||
Q_INVOKABLE void setRenderState(const QUuid& uid, const QString& renderState) const { DependencyManager::get<PointerManager>()->setRenderState(uid, renderState.toStdString()); }
|
||||
Q_INVOKABLE QVariantMap getPrevRayPickResult(QUuid uid) const { return DependencyManager::get<PointerManager>()->getPrevPickResult(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<PointerManager>()->setPrecisionPicking(uid, precisionPicking); }
|
||||
Q_INVOKABLE void setLaserLength(const QUuid& uid, float laserLength) const { DependencyManager::get<PointerManager>()->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); }
|
||||
|
||||
private:
|
||||
static RenderState buildRenderState(const QVariantMap& propMap);
|
||||
Q_INVOKABLE void setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay) const { DependencyManager::get<PointerManager>()->setLockEndUUID(uid, objectID, isOverlay); }
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -10,23 +10,20 @@
|
|||
//
|
||||
#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() 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();
|
||||
}
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
#ifndef hifi_MouseRayPick_h
|
||||
#define hifi_MouseRayPick_h
|
||||
|
||||
#include <pointers/rays/RayPick.h>
|
||||
#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() const override;
|
||||
};
|
||||
|
||||
#endif // hifi_MouseRayPick_h
|
||||
|
|
107
interface/src/raypick/PickScriptingInterface.cpp
Normal file
107
interface/src/raypick/PickScriptingInterface.cpp
Normal file
|
@ -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 <QVariant>
|
||||
#include "GLMHelpers.h"
|
||||
|
||||
#include <pointers/PickManager.h>
|
||||
|
||||
#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<PickManager>()->addPick(PickQuery::Ray, std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled));
|
||||
|
||||
} else {
|
||||
return DependencyManager::get<PickManager>()->addPick(PickQuery::Ray, std::make_shared<MouseRayPick>(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<PickManager>()->addPick(PickQuery::Ray, std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled));
|
||||
}
|
||||
|
||||
return QUuid();
|
||||
}
|
||||
|
||||
void PickScriptingInterface::enablePick(const QUuid& uid) {
|
||||
DependencyManager::get<PickManager>()->enablePick(uid);
|
||||
}
|
||||
|
||||
void PickScriptingInterface::disablePick(const QUuid& uid) {
|
||||
DependencyManager::get<PickManager>()->disablePick(uid);
|
||||
}
|
||||
|
||||
void PickScriptingInterface::removePick(const QUuid& uid) {
|
||||
DependencyManager::get<PickManager>()->removePick(uid);
|
||||
}
|
||||
|
||||
QVariantMap PickScriptingInterface::getPrevPickResult(const QUuid& uid) {
|
||||
return DependencyManager::get<PickManager>()->getPrevPickResult(uid);
|
||||
}
|
||||
|
||||
void PickScriptingInterface::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) {
|
||||
DependencyManager::get<PickManager>()->setPrecisionPicking(uid, precisionPicking);
|
||||
}
|
||||
|
||||
void PickScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) {
|
||||
DependencyManager::get<PickManager>()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
|
||||
}
|
||||
|
||||
void PickScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) {
|
||||
DependencyManager::get<PickManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
||||
}
|
65
interface/src/raypick/PickScriptingInterface.h
Normal file
65
interface/src/raypick/PickScriptingInterface.h
Normal file
|
@ -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 <QtCore/QObject>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <pointers/Pick.h>
|
||||
|
||||
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
|
112
interface/src/raypick/PointerScriptingInterface.cpp
Normal file
112
interface/src/raypick/PointerScriptingInterface.cpp
Normal file
|
@ -0,0 +1,112 @@
|
|||
//
|
||||
// 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 <QtCore/QVariant>
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "LaserPointer.h"
|
||||
|
||||
void PointerScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) const {
|
||||
DependencyManager::get<PointerManager>()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
|
||||
}
|
||||
void PointerScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) const {
|
||||
DependencyManager::get<PointerManager>()->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 distanceScaleEnd = false;
|
||||
if (propertyMap["distanceScaleEnd"].isValid()) {
|
||||
distanceScaleEnd = propertyMap["distanceScaleEnd"].toBool();
|
||||
}
|
||||
|
||||
bool enabled = false;
|
||||
if (propertyMap["enabled"].isValid()) {
|
||||
enabled = propertyMap["enabled"].toBool();
|
||||
}
|
||||
|
||||
LaserPointer::RenderStateMap renderStates;
|
||||
if (propertyMap["renderStates"].isValid()) {
|
||||
QList<QVariant> 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] = LaserPointer::buildRenderState(renderStateMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaserPointer::DefaultRenderStateMap defaultRenderStates;
|
||||
if (propertyMap["defaultRenderStates"].isValid()) {
|
||||
QList<QVariant> 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<float, RenderState>(distance, LaserPointer::buildRenderState(renderStateMap));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<LaserPointer>(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, distanceScaleEnd, 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<PointerManager>()->editRenderState(uid, renderState.toStdString(), startProps, pathProps, endProps);
|
||||
}
|
42
interface/src/raypick/PointerScriptingInterface.h
Normal file
42
interface/src/raypick/PointerScriptingInterface.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// 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 <QtCore/QObject>
|
||||
|
||||
#include "DependencyManager.h"
|
||||
#include <pointers/PointerManager.h>
|
||||
#include <pointers/Pick.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<PointerManager>()->enablePointer(uid); }
|
||||
Q_INVOKABLE void disablePointer(const QUuid& uid) const { DependencyManager::get<PointerManager>()->disablePointer(uid); }
|
||||
Q_INVOKABLE void removePointer(const QUuid& uid) const { DependencyManager::get<PointerManager>()->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<PointerManager>()->setRenderState(uid, renderState.toStdString()); }
|
||||
Q_INVOKABLE QVariantMap getPrevPickResult(QUuid uid) const { return DependencyManager::get<PointerManager>()->getPrevPickResult(uid); }
|
||||
|
||||
Q_INVOKABLE void setPrecisionPicking(const QUuid& uid, bool precisionPicking) const { DependencyManager::get<PointerManager>()->setPrecisionPicking(uid, precisionPicking); }
|
||||
Q_INVOKABLE void setLaserLength(const QUuid& uid, float laserLength) const { DependencyManager::get<PointerManager>()->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<PointerManager>()->setLockEndUUID(uid, objectID, isOverlay); }
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_PointerScriptingInterface_h
|
51
interface/src/raypick/RayPick.cpp
Normal file
51
interface/src/raypick/RayPick.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// 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 "EntityScriptingInterface.h"
|
||||
#include "ui/overlays/Overlays.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "DependencyManager.h"
|
||||
|
||||
PickResultPointer RayPick::getEntityIntersection(const PickRay& pick) {
|
||||
RayToEntityIntersectionResult entityRes =
|
||||
DependencyManager::get<EntityScriptingInterface>()->findRayIntersectionVector(pick, !getFilter().doesPickCoarse(),
|
||||
getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>(), !getFilter().doesPickInvisible(), !getFilter().doesPickNonCollidable());
|
||||
if (entityRes.intersects) {
|
||||
return std::make_shared<RayPickResult>(IntersectionType::ENTITY, entityRes.entityID, entityRes.distance, entityRes.intersection, pick, entityRes.surfaceNormal);
|
||||
} else {
|
||||
return std::make_shared<RayPickResult>(pick.toVariantMap());
|
||||
}
|
||||
}
|
||||
|
||||
PickResultPointer RayPick::getOverlayIntersection(const PickRay& pick) {
|
||||
RayToOverlayIntersectionResult overlayRes =
|
||||
qApp->getOverlays().findRayIntersectionVector(pick, !getFilter().doesPickCoarse(),
|
||||
getIncludeItemsAs<OverlayID>(), getIgnoreItemsAs<OverlayID>(), !getFilter().doesPickInvisible(), !getFilter().doesPickNonCollidable());
|
||||
if (overlayRes.intersects) {
|
||||
return std::make_shared<RayPickResult>(IntersectionType::OVERLAY, overlayRes.overlayID, overlayRes.distance, overlayRes.intersection, pick, overlayRes.surfaceNormal);
|
||||
} else {
|
||||
return std::make_shared<RayPickResult>(pick.toVariantMap());
|
||||
}
|
||||
}
|
||||
|
||||
PickResultPointer RayPick::getAvatarIntersection(const PickRay& pick) {
|
||||
RayToAvatarIntersectionResult avatarRes = DependencyManager::get<AvatarManager>()->findRayIntersectionVector(pick, getIncludeItemsAs<EntityItemID>(), getIgnoreItemsAs<EntityItemID>());
|
||||
if (avatarRes.intersects) {
|
||||
return std::make_shared<RayPickResult>(IntersectionType::AVATAR, avatarRes.avatarID, avatarRes.distance, avatarRes.intersection, pick);
|
||||
} else {
|
||||
return std::make_shared<RayPickResult>(pick.toVariantMap());
|
||||
}
|
||||
}
|
||||
|
||||
PickResultPointer RayPick::getHUDIntersection(const PickRay& pick) {
|
||||
glm::vec3 hudRes = DependencyManager::get<HMDScriptingInterface>()->calculateRayUICollisionPoint(pick.origin, pick.direction);
|
||||
return std::make_shared<RayPickResult>(IntersectionType::HUD, QUuid(), glm::distance(pick.origin, hudRes), hudRes, pick);
|
||||
}
|
79
interface/src/raypick/RayPick.h
Normal file
79
interface/src/raypick/RayPick.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
//
|
||||
// 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 <RegisteredMetaTypes.h>
|
||||
#include <pointers/Pick.h>
|
||||
|
||||
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<RayPickResult>(newRes);
|
||||
if (newRayRes->distance < distance) {
|
||||
return std::make_shared<RayPickResult>(*newRayRes);
|
||||
} else {
|
||||
return std::make_shared<RayPickResult>(*this);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class RayPick : public Pick<PickRay> {
|
||||
|
||||
public:
|
||||
RayPick(const PickFilter& filter, const float maxDistance, const bool enabled) : Pick(filter, maxDistance, enabled) {}
|
||||
|
||||
PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const override { return std::make_shared<RayPickResult>(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
|
|
@ -1,217 +0,0 @@
|
|||
//
|
||||
// RayPickManager.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 "RayPickManager.h"
|
||||
|
||||
#include <pointers/rays/StaticRayPick.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "EntityScriptingInterface.h"
|
||||
#include "ui/overlays/Overlays.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "DependencyManager.h"
|
||||
|
||||
#include "JointRayPick.h"
|
||||
#include "MouseRayPick.h"
|
||||
|
||||
bool RayPickManager::checkAndCompareCachedResults(QPair<glm::vec3, glm::vec3>& 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<glm::vec3, glm::vec3>& 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<QUuid, RayPick::Pointer> cachedRayPicks;
|
||||
withReadLock([&] {
|
||||
cachedRayPicks = _rayPicks;
|
||||
});
|
||||
|
||||
for (const auto& uid : cachedRayPicks.keys()) {
|
||||
std::shared_ptr<RayPick> 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<glm::vec3, glm::vec3> rayKey = QPair<glm::vec3, glm::vec3>(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<EntityScriptingInterface>()->findRayIntersectionVector(ray, !rayPick->getFilter().doesPickCoarse(),
|
||||
rayPick->getIncludeItemsAs<EntityItemID>(), rayPick->getIgnoreItemsAs<EntityItemID>(), !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<OverlayID>(), rayPick->getIgnoreItemsAs<OverlayID>(), !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<AvatarManager>()->findRayIntersectionVector(ray,
|
||||
rayPick->getIncludeItemsAs<EntityItemID>(), rayPick->getIgnoreItemsAs<EntityItemID>());
|
||||
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<HMDScriptingInterface>()->isHMDMode()) {
|
||||
RayCacheKey hudKey = { rayPick->getFilter().getHUDFlags(), QVector<QUuid>(), QVector<QUuid>() };
|
||||
if (!checkAndCompareCachedResults(rayKey, results, res, hudKey)) {
|
||||
glm::vec3 hudRes = DependencyManager::get<HMDScriptingInterface>()->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) {
|
||||
auto newRayPick = std::make_shared<JointRayPick>(jointName, posOffset, dirOffset, filter, maxDistance, enabled);
|
||||
QUuid id = QUuid::createUuid();
|
||||
withWriteLock([&] {
|
||||
_rayPicks[id] = newRayPick;
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
QUuid RayPickManager::createRayPick(const RayPickFilter& filter, float maxDistance, bool enabled) {
|
||||
QUuid id = QUuid::createUuid();
|
||||
auto newRayPick = std::make_shared<MouseRayPick>(filter, maxDistance, enabled);
|
||||
withWriteLock([&] {
|
||||
_rayPicks[id] = newRayPick;
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
QUuid RayPickManager::createRayPick(const glm::vec3& position, const glm::vec3& direction, const RayPickFilter& filter, float maxDistance, bool enabled) {
|
||||
QUuid id = QUuid::createUuid();
|
||||
auto newRayPick = std::make_shared<StaticRayPick>(position, direction, filter, maxDistance, enabled);
|
||||
withWriteLock([&] {
|
||||
_rayPicks[id] = newRayPick;
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
void RayPickManager::removeRayPick(const QUuid& uid) {
|
||||
withWriteLock([&] {
|
||||
_rayPicks.remove(uid);
|
||||
});
|
||||
}
|
||||
|
||||
RayPick::Pointer RayPickManager::findRayPick(const QUuid& uid) const {
|
||||
return resultWithReadLock<RayPick::Pointer>([&] {
|
||||
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<QUuid>& ignore) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
rayPick->setIgnoreItems(ignore);
|
||||
}
|
||||
}
|
||||
|
||||
void RayPickManager::setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const {
|
||||
auto rayPick = findRayPick(uid);
|
||||
if (rayPick) {
|
||||
rayPick->setIncludeItems(include);
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
//
|
||||
// RayPickManager.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_RayPickManager_h
|
||||
#define hifi_RayPickManager_h
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <pointers/rays/RayPick.h>
|
||||
|
||||
|
||||
class RayPickResult;
|
||||
|
||||
typedef struct RayCacheKey {
|
||||
RayPickFilter::Flags mask;
|
||||
QVector<QUuid> include;
|
||||
QVector<QUuid> ignore;
|
||||
|
||||
bool operator==(const RayCacheKey& other) const {
|
||||
return (mask == other.mask && include == other.include && ignore == other.ignore);
|
||||
}
|
||||
} RayCacheKey;
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<RayCacheKey> {
|
||||
size_t operator()(const RayCacheKey& k) const {
|
||||
return ((hash<RayPickFilter::Flags>()(k.mask) ^ (qHash(k.include) << 1)) >> 1) ^ (qHash(k.ignore) << 1);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class RayPickManager : protected ReadWriteLockable {
|
||||
|
||||
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<QUuid>& ignore) const;
|
||||
void setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const;
|
||||
|
||||
private:
|
||||
RayPick::Pointer findRayPick(const QUuid& uid) const;
|
||||
QHash<QUuid, RayPick::Pointer> _rayPicks;
|
||||
|
||||
typedef QHash<QPair<glm::vec3, glm::vec3>, std::unordered_map<RayCacheKey, RayPickResult>> 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<glm::vec3, glm::vec3>& ray, RayPickCache& cache, RayPickResult& res, const RayCacheKey& key);
|
||||
void cacheResult(const bool intersects, const RayPickResult& resTemp, const RayCacheKey& key, RayPickResult& res, QPair<glm::vec3, glm::vec3>& ray, RayPickCache& cache);
|
||||
};
|
||||
|
||||
#endif // hifi_RayPickManager_h
|
|
@ -13,83 +13,42 @@
|
|||
|
||||
#include <QVariant>
|
||||
#include "GLMHelpers.h"
|
||||
#include "Application.h"
|
||||
|
||||
#include "PickScriptingInterface.h"
|
||||
#include <pointers/PickManager.h>
|
||||
|
||||
#include "StaticRayPick.h"
|
||||
#include "JointRayPick.h"
|
||||
#include "MouseRayPick.h"
|
||||
|
||||
QUuid RayPickScriptingInterface::createRayPick(const QVariant& properties) {
|
||||
QVariantMap propMap = properties.toMap();
|
||||
|
||||
bool enabled = false;
|
||||
if (propMap["enabled"].isValid()) {
|
||||
enabled = propMap["enabled"].toBool();
|
||||
}
|
||||
|
||||
RayPickFilter filter = RayPickFilter();
|
||||
if (propMap["filter"].isValid()) {
|
||||
filter = RayPickFilter(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 qApp->getRayPickManager().createRayPick(jointName, posOffset, dirOffset, filter, maxDistance, enabled);
|
||||
} else {
|
||||
return qApp->getRayPickManager().createRayPick(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 qApp->getRayPickManager().createRayPick(position, direction, filter, maxDistance, enabled);
|
||||
}
|
||||
|
||||
return QUuid();
|
||||
return DependencyManager::get<PickScriptingInterface>()->createRayPick(properties);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::enableRayPick(const QUuid& uid) {
|
||||
qApp->getRayPickManager().enableRayPick(uid);
|
||||
DependencyManager::get<PickManager>()->enablePick(uid);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::disableRayPick(const QUuid& uid) {
|
||||
qApp->getRayPickManager().disableRayPick(uid);
|
||||
DependencyManager::get<PickManager>()->disablePick(uid);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::removeRayPick(const QUuid& uid) {
|
||||
qApp->getRayPickManager().removeRayPick(uid);
|
||||
DependencyManager::get<PickManager>()->removePick(uid);
|
||||
}
|
||||
|
||||
RayPickResult RayPickScriptingInterface::getPrevRayPickResult(const QUuid& uid) {
|
||||
return qApp->getRayPickManager().getPrevRayPickResult(uid);
|
||||
QVariantMap RayPickScriptingInterface::getPrevRayPickResult(const QUuid& uid) {
|
||||
return DependencyManager::get<PickManager>()->getPrevPickResult(uid);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) {
|
||||
qApp->getRayPickManager().setPrecisionPicking(uid, precisionPicking);
|
||||
DependencyManager::get<PickManager>()->setPrecisionPicking(uid, precisionPicking);
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue& ignoreItems) {
|
||||
qApp->getRayPickManager().setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
|
||||
DependencyManager::get<PickManager>()->setIgnoreItems(uid, qVectorQUuidFromScriptValue(ignoreItems));
|
||||
}
|
||||
|
||||
void RayPickScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) {
|
||||
qApp->getRayPickManager().setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
||||
DependencyManager::get<PickManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
||||
}
|
||||
|
|
|
@ -13,26 +13,11 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include "RegisteredMetaTypes.h"
|
||||
#include <DependencyManager.h>
|
||||
#include <pointers/rays/RayPick.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:
|
||||
|
@ -40,26 +25,11 @@ 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);
|
||||
|
||||
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 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; }
|
||||
};
|
||||
|
||||
#endif // hifi_RayPickScriptingInterface_h
|
||||
|
|
|
@ -7,13 +7,12 @@
|
|||
//
|
||||
#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 {
|
||||
valid = true;
|
||||
const PickRay StaticRayPick::getMathematicalPick() const {
|
||||
return _pickRay;
|
||||
}
|
|
@ -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() const override;
|
||||
|
||||
private:
|
||||
PickRay _pickRay;
|
80
libraries/pointers/src/pointers/Pick.cpp
Normal file
80
libraries/pointers/src/pointers/Pick.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// 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;
|
||||
|
||||
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<PickFilter>([&] {
|
||||
return _filter;
|
||||
});
|
||||
}
|
||||
|
||||
float PickQuery::getMaxDistance() const {
|
||||
return _maxDistance;
|
||||
}
|
||||
|
||||
bool PickQuery::isEnabled() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _enabled;
|
||||
});
|
||||
}
|
||||
|
||||
void PickQuery::setPrecisionPicking(bool precisionPicking) {
|
||||
withWriteLock([&] {
|
||||
_filter.setFlag(PickFilter::PICK_COARSE, !precisionPicking);
|
||||
});
|
||||
}
|
||||
|
||||
void PickQuery::setPickResult(const PickResultPointer& pickResult) {
|
||||
withWriteLock([&] {
|
||||
_prevResult = pickResult;
|
||||
});
|
||||
}
|
||||
|
||||
QVector<QUuid> PickQuery::getIgnoreItems() const {
|
||||
return resultWithReadLock<QVector<QUuid>>([&] {
|
||||
return _ignoreItems;
|
||||
});
|
||||
}
|
||||
|
||||
QVector<QUuid> PickQuery::getIncludeItems() const {
|
||||
return resultWithReadLock<QVector<QUuid>>([&] {
|
||||
return _includeItems;
|
||||
});
|
||||
}
|
||||
|
||||
PickResultPointer PickQuery::getPrevPickResult() const {
|
||||
return resultWithReadLock<PickResultPointer>([&] {
|
||||
return _prevResult;
|
||||
});
|
||||
}
|
||||
|
||||
void PickQuery::setIgnoreItems(const QVector<QUuid>& ignoreItems) {
|
||||
withWriteLock([&] {
|
||||
_ignoreItems = ignoreItems;
|
||||
});
|
||||
}
|
||||
|
||||
void PickQuery::setIncludeItems(const QVector<QUuid>& includeItems) {
|
||||
withWriteLock([&] {
|
||||
_includeItems = includeItems;
|
||||
});
|
||||
}
|
|
@ -1,22 +1,32 @@
|
|||
//
|
||||
// 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 <memory>
|
||||
#include <stdint.h>
|
||||
#include <bitset>
|
||||
|
||||
#include <QtCore/QUuid>
|
||||
#include <QVector>
|
||||
#include <QVariant>
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
class RayPickFilter {
|
||||
enum IntersectionType {
|
||||
NONE = 0,
|
||||
ENTITY,
|
||||
OVERLAY,
|
||||
AVATAR,
|
||||
HUD
|
||||
};
|
||||
|
||||
class PickFilter {
|
||||
public:
|
||||
enum FlagBit {
|
||||
PICK_ENTITIES = 0,
|
||||
|
@ -39,11 +49,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,36 +101,63 @@ public:
|
|||
|
||||
static constexpr unsigned int getBitMask(FlagBit bit) { return 1 << bit; }
|
||||
|
||||
static const RayPickFilter NOTHING;
|
||||
static const PickFilter NOTHING;
|
||||
};
|
||||
|
||||
class RayPick : protected ReadWriteLockable {
|
||||
|
||||
class PickResult {
|
||||
public:
|
||||
using Pointer = std::shared_ptr<RayPick>;
|
||||
PickResult() {}
|
||||
PickResult(const QVariantMap& pickVariant) : pickVariant(pickVariant) {}
|
||||
|
||||
RayPick(const RayPickFilter& filter, const float maxDistance, const bool enabled);
|
||||
virtual QVariantMap toVariantMap() const {
|
||||
return pickVariant;
|
||||
}
|
||||
|
||||
virtual const PickRay getPickRay(bool& valid) const = 0;
|
||||
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<PickResult> compareAndProcessNewResult(const std::shared_ptr<PickResult> 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<PickResult>;
|
||||
|
||||
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); }
|
||||
|
||||
RayPickFilter getFilter() const;
|
||||
PickFilter getFilter() const;
|
||||
float getMaxDistance() const;
|
||||
bool isEnabled() const;
|
||||
RayPickResult getPrevRayPickResult() const;
|
||||
|
||||
void setPrecisionPicking(bool precisionPicking);
|
||||
|
||||
void setRayPickResult(const RayPickResult& rayPickResult);
|
||||
PickResultPointer getPrevPickResult() const;
|
||||
void setPickResult(const PickResultPointer& pickResult);
|
||||
|
||||
QVector<QUuid> getIgnoreItems() const;
|
||||
QVector<QUuid> getIncludeItems() const;
|
||||
|
||||
template <typename T>
|
||||
QVector<T> getIgnoreItemsAs() const {
|
||||
QVector<T> result;
|
||||
template <typename S>
|
||||
QVector<S> getIgnoreItemsAs() const {
|
||||
QVector<S> result;
|
||||
withReadLock([&] {
|
||||
for (const auto& uid : _ignoreItems) {
|
||||
result.push_back(uid);
|
||||
|
@ -129,9 +166,9 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
QVector<T> getIncludeItemsAs() const {
|
||||
QVector<T> result;
|
||||
template <typename S>
|
||||
QVector<S> getIncludeItemsAs() const {
|
||||
QVector<S> result;
|
||||
withReadLock([&] {
|
||||
for (const auto& uid : _includeItems) {
|
||||
result.push_back(uid);
|
||||
|
@ -144,13 +181,26 @@ public:
|
|||
void setIncludeItems(const QVector<QUuid>& items);
|
||||
|
||||
private:
|
||||
RayPickFilter _filter;
|
||||
PickFilter _filter;
|
||||
const float _maxDistance;
|
||||
bool _enabled;
|
||||
RayPickResult _prevResult;
|
||||
PickResultPointer _prevResult;
|
||||
|
||||
QVector<QUuid> _ignoreItems;
|
||||
QVector<QUuid> _includeItems;
|
||||
};
|
||||
|
||||
#endif // hifi_RayPick_h
|
||||
template<typename T>
|
||||
class Pick : public PickQuery {
|
||||
public:
|
||||
Pick(const PickFilter& filter, const float maxDistance, const bool enabled) : PickQuery(filter, maxDistance, 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;
|
||||
};
|
||||
|
||||
#endif // hifi_Pick_h
|
127
libraries/pointers/src/pointers/PickCacheOptimizer.h
Normal file
127
libraries/pointers/src/pointers/PickCacheOptimizer.h
Normal file
|
@ -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 <unordered_map>
|
||||
|
||||
#include "Pick.h"
|
||||
|
||||
typedef struct PickCacheKey {
|
||||
PickFilter::Flags mask;
|
||||
QVector<QUuid> include;
|
||||
QVector<QUuid> ignore;
|
||||
|
||||
bool operator==(const PickCacheKey& other) const {
|
||||
return (mask == other.mask && include == other.include && ignore == other.ignore);
|
||||
}
|
||||
} PickCacheKey;
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<PickCacheKey> {
|
||||
size_t operator()(const PickCacheKey& k) const {
|
||||
return ((hash<PickFilter::Flags>()(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<typename T>
|
||||
class PickCacheOptimizer {
|
||||
|
||||
public:
|
||||
void update(QHash<QUuid, std::shared_ptr<PickQuery>>& picks, bool shouldPickHUD);
|
||||
|
||||
protected:
|
||||
typedef std::unordered_map<T, std::unordered_map<PickCacheKey, PickResultPointer>> 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<T>> pick);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool PickCacheOptimizer<T>::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<typename T>
|
||||
void PickCacheOptimizer<T>::cacheResult(const bool intersects, const PickResultPointer& resTemp, const PickCacheKey& key, PickResultPointer& res, T& mathPick, PickCache& cache, const std::shared_ptr<Pick<T>> pick) {
|
||||
if (intersects) {
|
||||
cache[mathPick][key] = resTemp;
|
||||
res = res->compareAndProcessNewResult(resTemp);
|
||||
} else {
|
||||
cache[mathPick][key] = pick->getDefaultResult(mathPick.toVariantMap());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void PickCacheOptimizer<T>::update(QHash<QUuid, std::shared_ptr<PickQuery>>& picks, bool shouldPickHUD) {
|
||||
PickCache results;
|
||||
for (const auto& uid : picks.keys()) {
|
||||
std::shared_ptr<Pick<T>> pick = std::static_pointer_cast<Pick<T>>(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<QUuid>(), QVector<QUuid>() };
|
||||
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
|
94
libraries/pointers/src/pointers/PickManager.cpp
Normal file
94
libraries/pointers/src/pointers/PickManager.cpp
Normal file
|
@ -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(PickQuery::PickType type, const std::shared_ptr<PickQuery> pick) {
|
||||
QUuid id = QUuid::createUuid();
|
||||
withWriteLock([&] {
|
||||
_picks[type][id] = pick;
|
||||
_typeMap[id] = type;
|
||||
});
|
||||
return id;
|
||||
}
|
||||
|
||||
std::shared_ptr<PickQuery> PickManager::findPick(const QUuid& uid) const {
|
||||
return resultWithReadLock<std::shared_ptr<PickQuery>>([&] {
|
||||
auto type = _typeMap.find(uid);
|
||||
if (type != _typeMap.end()) {
|
||||
return _picks[type.value()][uid];
|
||||
}
|
||||
return std::shared_ptr<PickQuery>();
|
||||
});
|
||||
}
|
||||
|
||||
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<QUuid>& ignore) const {
|
||||
auto pick = findPick(uid);
|
||||
if (pick) {
|
||||
pick->setIgnoreItems(ignore);
|
||||
}
|
||||
}
|
||||
|
||||
void PickManager::setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const {
|
||||
auto pick = findPick(uid);
|
||||
if (pick) {
|
||||
pick->setIncludeItems(include);
|
||||
}
|
||||
}
|
||||
|
||||
void PickManager::update() {
|
||||
QHash<PickQuery::PickType, QHash<QUuid, std::shared_ptr<PickQuery>>> cachedPicks;
|
||||
withReadLock([&] {
|
||||
cachedPicks = _picks;
|
||||
});
|
||||
|
||||
bool shouldPickHUD = _shouldPickHUDOperator();
|
||||
_rayPickCacheOptimizer.update(cachedPicks[PickQuery::Ray], shouldPickHUD);
|
||||
}
|
48
libraries/pointers/src/pointers/PickManager.h
Normal file
48
libraries/pointers/src/pointers/PickManager.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// 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 <DependencyManager.h>
|
||||
#include "RegisteredMetaTypes.h"
|
||||
|
||||
#include "Pick.h"
|
||||
#include "PickCacheOptimizer.h"
|
||||
|
||||
class PickManager : public Dependency, protected ReadWriteLockable {
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
PickManager();
|
||||
|
||||
void update();
|
||||
|
||||
QUuid addPick(PickQuery::PickType type, const std::shared_ptr<PickQuery> 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<QUuid>& ignore) const;
|
||||
void setIncludeItems(const QUuid& uid, const QVector<QUuid>& include) const;
|
||||
|
||||
void setShouldPickHUDOperator(std::function<bool()> shouldPickHUDOperator) { _shouldPickHUDOperator = shouldPickHUDOperator; }
|
||||
|
||||
protected:
|
||||
std::function<bool()> _shouldPickHUDOperator;
|
||||
|
||||
std::shared_ptr<PickQuery> findPick(const QUuid& uid) const;
|
||||
QHash<PickQuery::PickType, QHash<QUuid, std::shared_ptr<PickQuery>>> _picks;
|
||||
QHash<QUuid, PickQuery::PickType> _typeMap;
|
||||
|
||||
PickCacheOptimizer<PickRay> _rayPickCacheOptimizer;
|
||||
};
|
||||
|
||||
#endif // hifi_PickManager_h
|
39
libraries/pointers/src/pointers/Pointer.cpp
Normal file
39
libraries/pointers/src/pointers/Pointer.cpp
Normal file
|
@ -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 <DependencyManager.h>
|
||||
#include "PickManager.h"
|
||||
|
||||
Pointer::~Pointer() {
|
||||
DependencyManager::get<PickManager>()->removePick(_pickUID);
|
||||
}
|
||||
|
||||
void Pointer::enable() {
|
||||
DependencyManager::get<PickManager>()->enablePick(_pickUID);
|
||||
}
|
||||
|
||||
void Pointer::disable() {
|
||||
DependencyManager::get<PickManager>()->disablePick(_pickUID);
|
||||
}
|
||||
|
||||
const QVariantMap Pointer::getPrevPickResult() {
|
||||
return DependencyManager::get<PickManager>()->getPrevPickResult(_pickUID);
|
||||
}
|
||||
|
||||
void Pointer::setPrecisionPicking(const bool precisionPicking) {
|
||||
DependencyManager::get<PickManager>()->setPrecisionPicking(_pickUID, precisionPicking);
|
||||
}
|
||||
|
||||
void Pointer::setIgnoreItems(const QVector<QUuid>& ignoreItems) const {
|
||||
DependencyManager::get<PickManager>()->setIgnoreItems(_pickUID, ignoreItems);
|
||||
}
|
||||
|
||||
void Pointer::setIncludeItems(const QVector<QUuid>& includeItems) const {
|
||||
DependencyManager::get<PickManager>()->setIncludeItems(_pickUID, includeItems);
|
||||
}
|
46
libraries/pointers/src/pointers/Pointer.h
Normal file
46
libraries/pointers/src/pointers/Pointer.h
Normal file
|
@ -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 <QtCore/QUuid>
|
||||
#include <QVector>
|
||||
#include <QVariant>
|
||||
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
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<QUuid>& ignoreItems) const;
|
||||
virtual void setIncludeItems(const QVector<QUuid>& 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
|
|
@ -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<Pointer> PointerManager::find(const QUuid& uid) const {
|
||||
return resultWithReadLock<std::shared_ptr<Pointer>>([&] {
|
||||
auto itr = _pointers.find(uid);
|
||||
if (itr != _pointers.end()) {
|
||||
return *itr;
|
||||
}
|
||||
return std::shared_ptr<Pointer>();
|
||||
});
|
||||
}
|
||||
|
||||
QUuid PointerManager::addPointer(std::shared_ptr<Pointer> 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::getPrevPickResult(const QUuid& uid) const {
|
||||
auto pointer = find(uid);
|
||||
if (pointer) {
|
||||
return pointer->getPrevPickResult();
|
||||
}
|
||||
return QVariantMap();
|
||||
}
|
||||
|
||||
void PointerManager::update() {
|
||||
auto cachedPointers = resultWithReadLock<QList<std::shared_ptr<Pointer>>>([&] {
|
||||
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<QUuid>& ignoreEntities) const {
|
||||
auto pointer = find(uid);
|
||||
if (pointer) {
|
||||
pointer->setIgnoreItems(ignoreEntities);
|
||||
}
|
||||
}
|
||||
|
||||
void PointerManager::setIncludeItems(const QUuid& uid, const QVector<QUuid>& 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,11 +11,38 @@
|
|||
#include <DependencyManager.h>
|
||||
#include <PointerEvent.h>
|
||||
|
||||
class PointerManager : public QObject, public Dependency {
|
||||
#include <memory>
|
||||
|
||||
#include <shared/ReadWriteLockable.h>
|
||||
|
||||
#include "Pointer.h"
|
||||
|
||||
class PointerManager : public QObject, public Dependency, protected ReadWriteLockable {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
public:
|
||||
PointerManager();
|
||||
PointerManager() {}
|
||||
|
||||
QUuid addPointer(std::shared_ptr<Pointer> 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 getPrevPickResult(const QUuid& uid) const;
|
||||
|
||||
void setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const;
|
||||
void setIgnoreItems(const QUuid& uid, const QVector<QUuid>& ignoreEntities) const;
|
||||
void setIncludeItems(const QUuid& uid, const QVector<QUuid>& 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<Pointer> find(const QUuid& uid) const;
|
||||
QHash<QUuid, std::shared_ptr<Pointer>> _pointers;
|
||||
|
||||
signals:
|
||||
void triggerBegin(const QUuid& id, const PointerEvent& pointerEvent);
|
||||
|
|
|
@ -1,81 +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<RayPickFilter>([&] {
|
||||
return _filter;
|
||||
});
|
||||
}
|
||||
|
||||
float RayPick::getMaxDistance() const {
|
||||
return _maxDistance;
|
||||
}
|
||||
|
||||
bool RayPick::isEnabled() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _enabled;
|
||||
});
|
||||
}
|
||||
|
||||
void RayPick::setPrecisionPicking(bool precisionPicking) {
|
||||
withWriteLock([&]{
|
||||
_filter.setFlag(RayPickFilter::PICK_COARSE, !precisionPicking);
|
||||
});
|
||||
}
|
||||
|
||||
void RayPick::setRayPickResult(const RayPickResult& rayPickResult) {
|
||||
withWriteLock([&] {
|
||||
_prevResult = rayPickResult;
|
||||
});
|
||||
}
|
||||
|
||||
QVector<QUuid> RayPick::getIgnoreItems() const {
|
||||
return resultWithReadLock<QVector<QUuid>>([&] {
|
||||
return _ignoreItems;
|
||||
});
|
||||
}
|
||||
|
||||
QVector<QUuid> RayPick::getIncludeItems() const {
|
||||
return resultWithReadLock<QVector<QUuid>>([&] {
|
||||
return _includeItems;
|
||||
});
|
||||
}
|
||||
|
||||
RayPickResult RayPick::getPrevRayPickResult() const {
|
||||
return resultWithReadLock<RayPickResult>([&] {
|
||||
return _prevResult;
|
||||
});
|
||||
}
|
||||
|
||||
void RayPick::setIgnoreItems(const QVector<QUuid>& ignoreItems) {
|
||||
withWriteLock([&] {
|
||||
_ignoreItems = ignoreItems;
|
||||
});
|
||||
}
|
||||
|
||||
void RayPick::setIncludeItems(const QVector<QUuid>& includeItems) {
|
||||
withWriteLock([&] {
|
||||
_includeItems = includeItems;
|
||||
});
|
||||
}
|
|
@ -34,7 +34,6 @@ int vec2MetaTypeId = qRegisterMetaType<glm::vec2>();
|
|||
int quatMetaTypeId = qRegisterMetaType<glm::quat>();
|
||||
int xColorMetaTypeId = qRegisterMetaType<xColor>();
|
||||
int pickRayMetaTypeId = qRegisterMetaType<PickRay>();
|
||||
int rayPickResultMetaTypeId = qRegisterMetaType<RayPickResult>();
|
||||
int collisionMetaTypeId = qRegisterMetaType<Collision>();
|
||||
int qMapURLStringMetaTypeId = qRegisterMetaType<QMap<QUrl,QString>>();
|
||||
int socketErrorMetaTypeId = qRegisterMetaType<QAbstractSocket::SocketError>();
|
||||
|
@ -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);
|
||||
|
|
|
@ -125,42 +125,51 @@ QVector<QUuid> 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(0.0f), direction(0.0f) { }
|
||||
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;
|
||||
|
||||
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 override {
|
||||
QVariantMap pickRay;
|
||||
pickRay["origin"] = vec3toVariant(origin);
|
||||
pickRay["direction"] = vec3toVariant(direction);
|
||||
return pickRay;
|
||||
}
|
||||
};
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<glm::vec3> {
|
||||
size_t operator()(const glm::vec3& a) const {
|
||||
return ((hash<float>()(a.x) ^ (hash<float>()(a.y) << 1)) >> 1) ^ (hash<float>()(a.z) << 1);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct hash<PickRay> {
|
||||
size_t operator()(const PickRay& a) const {
|
||||
return (hash<glm::vec3>()(a.origin) ^ (hash<glm::vec3>()(a.direction) << 1));
|
||||
}
|
||||
};
|
||||
}
|
||||
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,
|
||||
|
|
|
@ -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
|
||||
});
|
||||
|
||||
|
|
|
@ -373,8 +373,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;
|
||||
|
@ -494,7 +494,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, [
|
||||
|
@ -578,7 +578,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
|
||||
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,
|
||||
|
|
|
@ -184,7 +184,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
|
||||
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,
|
||||
|
|
|
@ -207,7 +207,7 @@
|
|||
|
||||
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,
|
||||
|
|
|
@ -146,12 +146,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
|
||||
|
@ -232,7 +232,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,
|
||||
|
|
|
@ -294,7 +294,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();
|
||||
|
@ -366,7 +366,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
|
||||
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,
|
||||
|
|
|
@ -151,7 +151,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,
|
||||
|
@ -159,14 +159,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,
|
||||
|
@ -174,7 +174,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
|
||||
|
@ -399,7 +399,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -379,7 +379,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;
|
||||
|
@ -447,7 +447,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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue