mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 07:47:30 +02:00
laserpointers generate pointerevents
This commit is contained in:
parent
befe583c5e
commit
cf34fe3345
20 changed files with 375 additions and 56 deletions
|
@ -5919,6 +5919,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
||||||
|
|
||||||
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
|
qScriptRegisterMetaType(scriptEngine.data(), OverlayIDtoScriptValue, OverlayIDfromScriptValue);
|
||||||
|
|
||||||
|
DependencyManager::get<PickScriptingInterface>()->registerMetaTypes(scriptEngine.data());
|
||||||
|
|
||||||
// connect this script engines printedMessage signal to the global ScriptEngines these various messages
|
// connect this script engines printedMessage signal to the global ScriptEngines these various messages
|
||||||
connect(scriptEngine.data(), &ScriptEngine::printedMessage,
|
connect(scriptEngine.data(), &ScriptEngine::printedMessage,
|
||||||
DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onPrintedMessage);
|
DependencyManager::get<ScriptEngines>().data(), &ScriptEngines::onPrintedMessage);
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
#include <pointers/PickManager.h>
|
#include <pointers/PickManager.h>
|
||||||
#include "PickScriptingInterface.h"
|
#include "PickScriptingInterface.h"
|
||||||
|
|
||||||
LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
|
LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, const PointerTriggers& triggers,
|
||||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled) :
|
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled) :
|
||||||
Pointer(DependencyManager::get<PickScriptingInterface>()->createRayPick(rayProps)),
|
Pointer(DependencyManager::get<PickScriptingInterface>()->createRayPick(rayProps), enabled),
|
||||||
_renderingEnabled(enabled),
|
_triggers(triggers),
|
||||||
_renderStates(renderStates),
|
_renderStates(renderStates),
|
||||||
_defaultRenderStates(defaultRenderStates),
|
_defaultRenderStates(defaultRenderStates),
|
||||||
_faceAvatar(faceAvatar),
|
_faceAvatar(faceAvatar),
|
||||||
|
@ -49,17 +49,9 @@ LaserPointer::~LaserPointer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LaserPointer::enable() {
|
|
||||||
Pointer::enable();
|
|
||||||
withWriteLock([&] {
|
|
||||||
_renderingEnabled = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void LaserPointer::disable() {
|
void LaserPointer::disable() {
|
||||||
Pointer::disable();
|
Parent::disable();
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
_renderingEnabled = false;
|
|
||||||
if (!_currentRenderState.empty()) {
|
if (!_currentRenderState.empty()) {
|
||||||
if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
|
if (_renderStates.find(_currentRenderState) != _renderStates.end()) {
|
||||||
disableRenderState(_renderStates[_currentRenderState]);
|
disableRenderState(_renderStates[_currentRenderState]);
|
||||||
|
@ -199,26 +191,37 @@ void LaserPointer::disableRenderState(const RenderState& renderState) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LaserPointer::update() {
|
void LaserPointer::updateVisuals(const QVariantMap& prevRayPickResult) {
|
||||||
// This only needs to be a read lock because update won't change any of the properties that can be modified from scripts
|
IntersectionType type = IntersectionType(prevRayPickResult["type"].toInt());
|
||||||
withReadLock([&] {
|
PickRay pickRay = PickRay(prevRayPickResult["searchRay"].toMap());
|
||||||
QVariantMap prevRayPickResult = DependencyManager::get<PickManager>()->getPrevPickResult(_pickUID);
|
QUuid uid = prevRayPickResult["objectID"].toUuid();
|
||||||
IntersectionType type = IntersectionType(prevRayPickResult["type"].toInt());
|
if (_enabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() &&
|
||||||
PickRay pickRay = PickRay(prevRayPickResult["searchRay"].toMap());
|
(type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) {
|
||||||
QUuid uid = prevRayPickResult["objectID"].toUuid();
|
float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult["distance"].toFloat();
|
||||||
if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() &&
|
updateRenderState(_renderStates[_currentRenderState], type, distance, uid, pickRay, false);
|
||||||
(type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) {
|
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||||
float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult["distance"].toFloat();
|
} else if (_enabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
||||||
updateRenderState(_renderStates[_currentRenderState], type, distance, uid, pickRay, false);
|
disableRenderState(_renderStates[_currentRenderState]);
|
||||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), pickRay, true);
|
||||||
} else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) {
|
} else if (!_currentRenderState.empty()) {
|
||||||
disableRenderState(_renderStates[_currentRenderState]);
|
disableRenderState(_renderStates[_currentRenderState]);
|
||||||
updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), pickRay, true);
|
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
||||||
} else if (!_currentRenderState.empty()) {
|
}
|
||||||
disableRenderState(_renderStates[_currentRenderState]);
|
}
|
||||||
disableRenderState(_defaultRenderStates[_currentRenderState].second);
|
|
||||||
|
Pointer::PickedObject LaserPointer::getHoveredObject(const QVariantMap& pickResult) {
|
||||||
|
return Pointer::PickedObject(pickResult["objectID"].toUuid(), IntersectionType(pickResult["type"].toUInt()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Pointer::Buttons LaserPointer::getPressedButtons() {
|
||||||
|
std::unordered_set<std::string> toReturn;
|
||||||
|
for (const PointerTrigger& trigger : _triggers) {
|
||||||
|
// TODO: right now, LaserPointers don't support axes, only on/off buttons
|
||||||
|
if (trigger.getEndpoint()->peek() >= 1.0f) {
|
||||||
|
toReturn.insert(trigger.getButton());
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LaserPointer::setLength(const float length) {
|
void LaserPointer::setLength(const float length) {
|
||||||
|
@ -290,4 +293,53 @@ RenderState LaserPointer::buildRenderState(const QVariantMap& propMap) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return RenderState(startID, pathID, endID);
|
return RenderState(startID, pathID, endID);
|
||||||
|
}
|
||||||
|
|
||||||
|
PointerEvent LaserPointer::buildPointerEvent(const QUuid& uid, const QVariantMap& pickResult) const {
|
||||||
|
uint32_t id = 0;
|
||||||
|
glm::vec3 intersection = vec3FromVariant(pickResult["intersection"]);
|
||||||
|
glm::vec3 surfaceNormal = vec3FromVariant(pickResult["surfaceNormal"]);
|
||||||
|
glm::vec3 direction = -surfaceNormal;
|
||||||
|
IntersectionType type = IntersectionType(pickResult["type"].toUInt());
|
||||||
|
glm::vec2 pos2D;
|
||||||
|
if (type == ENTITY) {
|
||||||
|
pos2D = projectOntoEntityXYPlane(uid, intersection);
|
||||||
|
} else if (type == OVERLAY) {
|
||||||
|
pos2D = projectOntoOverlayXYPlane(uid, intersection);
|
||||||
|
}
|
||||||
|
return PointerEvent(PointerEvent::Move, id, pos2D, intersection, surfaceNormal, direction, PointerEvent::NoButtons);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec2 LaserPointer::projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint) const {
|
||||||
|
glm::quat invRot = glm::inverse(rotation);
|
||||||
|
glm::vec3 localPos = invRot * (worldPos - position);
|
||||||
|
glm::vec3 invDimensions = glm::vec3(1.0f / dimensions.x, 1.0f / dimensions.y, 1.0f / dimensions.z);
|
||||||
|
|
||||||
|
glm::vec3 normalizedPos = (localPos * invDimensions) + registrationPoint;
|
||||||
|
return glm::vec2(normalizedPos.x * dimensions.x, (1.0f - normalizedPos.y) * dimensions.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec2 LaserPointer::projectOntoOverlayXYPlane(const QUuid& overlayID, const glm::vec3& worldPos) const {
|
||||||
|
glm::vec3 position = vec3FromVariant(qApp->getOverlays().getProperty(overlayID, "position").value);
|
||||||
|
glm::quat rotation = quatFromVariant(qApp->getOverlays().getProperty(overlayID, "rotation").value);
|
||||||
|
glm::vec3 dimensions;
|
||||||
|
|
||||||
|
float dpi = qApp->getOverlays().getProperty(overlayID, "dpi").value.toFloat();
|
||||||
|
if (dpi > 0) {
|
||||||
|
// Calculate physical dimensions for web3d overlay from resolution and dpi; "dimensions" property is used as a scale.
|
||||||
|
glm::vec3 resolution = glm::vec3(vec2FromVariant(qApp->getOverlays().getProperty(overlayID, "resolution").value), 1);
|
||||||
|
glm::vec3 scale = glm::vec3(vec2FromVariant(qApp->getOverlays().getProperty(overlayID, "dimensions").value), 0.01f);
|
||||||
|
const float INCHES_TO_METERS = 1.0f / 39.3701f;
|
||||||
|
dimensions = (resolution * INCHES_TO_METERS / dpi) * scale;
|
||||||
|
} else {
|
||||||
|
dimensions = glm::vec3(vec2FromVariant(qApp->getOverlays().getProperty(overlayID, "dimensions").value), 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
const glm::vec3 DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f);
|
||||||
|
return projectOntoXYPlane(worldPos, position, rotation, dimensions, DEFAULT_REGISTRATION_POINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec2 LaserPointer::projectOntoEntityXYPlane(const QUuid& entity, const glm::vec3& worldPos) const {
|
||||||
|
auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entity);
|
||||||
|
return projectOntoXYPlane(worldPos, props.getPosition(), props.getRotation(), props.getDimensions(), props.getRegistrationPoint());
|
||||||
}
|
}
|
|
@ -49,16 +49,15 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
class LaserPointer : public Pointer {
|
class LaserPointer : public Pointer {
|
||||||
|
using Parent = Pointer;
|
||||||
public:
|
public:
|
||||||
typedef std::unordered_map<std::string, RenderState> RenderStateMap;
|
typedef std::unordered_map<std::string, RenderState> RenderStateMap;
|
||||||
typedef std::unordered_map<std::string, std::pair<float, RenderState>> DefaultRenderStateMap;
|
typedef std::unordered_map<std::string, std::pair<float, RenderState>> DefaultRenderStateMap;
|
||||||
|
|
||||||
LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates,
|
LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, const PointerTriggers& triggers,
|
||||||
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled);
|
const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled);
|
||||||
~LaserPointer();
|
~LaserPointer();
|
||||||
|
|
||||||
void enable() override;
|
|
||||||
void disable() override;
|
void disable() override;
|
||||||
|
|
||||||
void setRenderState(const std::string& state) override;
|
void setRenderState(const std::string& state) override;
|
||||||
|
@ -68,12 +67,18 @@ public:
|
||||||
void setLength(const float length) override;
|
void setLength(const float length) override;
|
||||||
void setLockEndUUID(QUuid objectID, const bool isOverlay) override;
|
void setLockEndUUID(QUuid objectID, const bool isOverlay) override;
|
||||||
|
|
||||||
void update() override;
|
void updateVisuals(const QVariantMap& prevRayPickResult) override;
|
||||||
|
|
||||||
|
PickedObject getHoveredObject(const QVariantMap& pickResult) override;
|
||||||
|
Pointer::Buttons getPressedButtons() override;
|
||||||
|
|
||||||
static RenderState buildRenderState(const QVariantMap& propMap);
|
static RenderState buildRenderState(const QVariantMap& propMap);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PointerEvent buildPointerEvent(const QUuid& uid, const QVariantMap& pickResult) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _renderingEnabled;
|
PointerTriggers _triggers;
|
||||||
float _laserLength { 0.0f };
|
float _laserLength { 0.0f };
|
||||||
std::string _currentRenderState { "" };
|
std::string _currentRenderState { "" };
|
||||||
RenderStateMap _renderStates;
|
RenderStateMap _renderStates;
|
||||||
|
@ -88,6 +93,10 @@ private:
|
||||||
void updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState);
|
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);
|
void disableRenderState(const RenderState& renderState);
|
||||||
|
|
||||||
|
glm::vec2 projectOntoEntityXYPlane(const QUuid& entity, const glm::vec3& worldPos) const;
|
||||||
|
glm::vec2 projectOntoOverlayXYPlane(const QUuid& overlayID, const glm::vec3& worldPos) const;
|
||||||
|
glm::vec2 projectOntoXYPlane(const glm::vec3& worldPos, const glm::vec3& position, const glm::quat& rotation, const glm::vec3& dimensions, const glm::vec3& registrationPoint) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_LaserPointer_h
|
#endif // hifi_LaserPointer_h
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
#include "JointRayPick.h"
|
#include "JointRayPick.h"
|
||||||
#include "MouseRayPick.h"
|
#include "MouseRayPick.h"
|
||||||
|
|
||||||
|
#include <pointers/Pick.h>
|
||||||
|
#include <ScriptEngine.h>
|
||||||
|
|
||||||
QUuid PickScriptingInterface::createPick(const PickQuery::PickType type, const QVariant& properties) {
|
QUuid PickScriptingInterface::createPick(const PickQuery::PickType type, const QVariant& properties) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PickQuery::PickType::Ray:
|
case PickQuery::PickType::Ray:
|
||||||
|
@ -105,3 +108,22 @@ void PickScriptingInterface::setIgnoreItems(const QUuid& uid, const QScriptValue
|
||||||
void PickScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) {
|
void PickScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptValue& includeItems) {
|
||||||
DependencyManager::get<PickManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
DependencyManager::get<PickManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QScriptValue pickTypesToScriptValue(QScriptEngine* engine, const PickQuery::PickType& pickType) {
|
||||||
|
return pickType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pickTypesFromScriptValue(const QScriptValue& object, PickQuery::PickType& pickType) {
|
||||||
|
pickType = static_cast<PickQuery::PickType>(object.toUInt16());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PickScriptingInterface::registerMetaTypes(QScriptEngine* engine) {
|
||||||
|
QScriptValue pickTypes = engine->newObject();
|
||||||
|
auto metaEnum = QMetaEnum::fromType<PickQuery::PickType>();
|
||||||
|
for (int i = 0; i < PickQuery::PickType::NUM_PICK_TYPES; ++i) {
|
||||||
|
pickTypes.setProperty(metaEnum.key(i), metaEnum.value(i));
|
||||||
|
}
|
||||||
|
engine->globalObject().setProperty("PickType", pickTypes);
|
||||||
|
|
||||||
|
qScriptRegisterMetaType(engine, pickTypesToScriptValue, pickTypesFromScriptValue);
|
||||||
|
}
|
|
@ -35,6 +35,8 @@ class PickScriptingInterface : public QObject, public Dependency {
|
||||||
public:
|
public:
|
||||||
QUuid createRayPick(const QVariant& properties);
|
QUuid createRayPick(const QVariant& properties);
|
||||||
|
|
||||||
|
void registerMetaTypes(QScriptEngine* engine);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
Q_INVOKABLE QUuid createPick(const PickQuery::PickType type, const QVariant& properties);
|
Q_INVOKABLE QUuid createPick(const PickQuery::PickType type, const QVariant& properties);
|
||||||
Q_INVOKABLE void enablePick(const QUuid& uid);
|
Q_INVOKABLE void enablePick(const QUuid& uid);
|
||||||
|
|
|
@ -21,7 +21,7 @@ void PointerScriptingInterface::setIncludeItems(const QUuid& uid, const QScriptV
|
||||||
DependencyManager::get<PointerManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
DependencyManager::get<PointerManager>()->setIncludeItems(uid, qVectorQUuidFromScriptValue(includeItems));
|
||||||
}
|
}
|
||||||
|
|
||||||
QUuid PointerScriptingInterface::createPointer(const PickQuery::PickType type, const QVariant& properties) const {
|
QUuid PointerScriptingInterface::createPointer(const PickQuery::PickType& type, const QVariant& properties) const {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PickQuery::PickType::Ray:
|
case PickQuery::PickType::Ray:
|
||||||
return createLaserPointer(properties);
|
return createLaserPointer(properties);
|
||||||
|
@ -61,7 +61,7 @@ QUuid PointerScriptingInterface::createLaserPointer(const QVariant& properties)
|
||||||
LaserPointer::RenderStateMap renderStates;
|
LaserPointer::RenderStateMap renderStates;
|
||||||
if (propertyMap["renderStates"].isValid()) {
|
if (propertyMap["renderStates"].isValid()) {
|
||||||
QList<QVariant> renderStateVariants = propertyMap["renderStates"].toList();
|
QList<QVariant> renderStateVariants = propertyMap["renderStates"].toList();
|
||||||
for (QVariant& renderStateVariant : renderStateVariants) {
|
for (const QVariant& renderStateVariant : renderStateVariants) {
|
||||||
if (renderStateVariant.isValid()) {
|
if (renderStateVariant.isValid()) {
|
||||||
QVariantMap renderStateMap = renderStateVariant.toMap();
|
QVariantMap renderStateMap = renderStateVariant.toMap();
|
||||||
if (renderStateMap["name"].isValid()) {
|
if (renderStateMap["name"].isValid()) {
|
||||||
|
@ -75,7 +75,7 @@ QUuid PointerScriptingInterface::createLaserPointer(const QVariant& properties)
|
||||||
LaserPointer::DefaultRenderStateMap defaultRenderStates;
|
LaserPointer::DefaultRenderStateMap defaultRenderStates;
|
||||||
if (propertyMap["defaultRenderStates"].isValid()) {
|
if (propertyMap["defaultRenderStates"].isValid()) {
|
||||||
QList<QVariant> renderStateVariants = propertyMap["defaultRenderStates"].toList();
|
QList<QVariant> renderStateVariants = propertyMap["defaultRenderStates"].toList();
|
||||||
for (QVariant& renderStateVariant : renderStateVariants) {
|
for (const QVariant& renderStateVariant : renderStateVariants) {
|
||||||
if (renderStateVariant.isValid()) {
|
if (renderStateVariant.isValid()) {
|
||||||
QVariantMap renderStateMap = renderStateVariant.toMap();
|
QVariantMap renderStateMap = renderStateVariant.toMap();
|
||||||
if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) {
|
if (renderStateMap["name"].isValid() && renderStateMap["distance"].isValid()) {
|
||||||
|
@ -87,7 +87,26 @@ QUuid PointerScriptingInterface::createLaserPointer(const QVariant& properties)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<LaserPointer>(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, distanceScaleEnd, enabled));
|
PointerTriggers triggers;
|
||||||
|
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||||
|
if (propertyMap["triggers"].isValid()) {
|
||||||
|
QList<QVariant> triggerVariants = propertyMap["triggers"].toList();
|
||||||
|
for (const QVariant& triggerVariant : triggerVariants) {
|
||||||
|
if (triggerVariant.isValid()) {
|
||||||
|
QVariantMap triggerMap = triggerVariant.toMap();
|
||||||
|
if (triggerMap["action"].isValid() && triggerMap["button"].isValid()) {
|
||||||
|
controller::Endpoint::Pointer endpoint = userInputMapper->endpointFor(controller::Input(triggerMap["action"].toUInt()));
|
||||||
|
if (endpoint) {
|
||||||
|
std::string button = triggerMap["button"].toString().toStdString();
|
||||||
|
triggers.emplace_back(endpoint, button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<LaserPointer>(properties, renderStates, defaultRenderStates, triggers,
|
||||||
|
faceAvatar, centerEndY, lockEnd, distanceScaleEnd, enabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PointerScriptingInterface::editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const {
|
void PointerScriptingInterface::editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const {
|
||||||
|
|
|
@ -22,13 +22,13 @@ public:
|
||||||
QUuid createLaserPointer(const QVariant& properties) const;
|
QUuid createLaserPointer(const QVariant& properties) const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
Q_INVOKABLE QUuid createPointer(const PickQuery::PickType type, const QVariant& properties) const;
|
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 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 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 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 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 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 QVariantMap getPrevPickResult(const 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 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 setLaserLength(const QUuid& uid, float laserLength) const { DependencyManager::get<PointerManager>()->setLength(uid, laserLength); }
|
||||||
|
@ -37,6 +37,14 @@ public slots:
|
||||||
|
|
||||||
Q_INVOKABLE void setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay) const { DependencyManager::get<PointerManager>()->setLockEndUUID(uid, objectID, isOverlay); }
|
Q_INVOKABLE void setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay) const { DependencyManager::get<PointerManager>()->setLockEndUUID(uid, objectID, isOverlay); }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void triggerBegin(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
void triggerContinue(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
void triggerEnd(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
void hoverBegin(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
void hoverContinue(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
void hoverEnd(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_PointerScriptingInterface_h
|
#endif // hifi_PointerScriptingInterface_h
|
||||||
|
|
|
@ -37,10 +37,22 @@
|
||||||
#include "Web3DOverlay.h"
|
#include "Web3DOverlay.h"
|
||||||
#include <QtQuick/QQuickWindow>
|
#include <QtQuick/QQuickWindow>
|
||||||
|
|
||||||
|
#include <pointers/PointerManager.h>
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays")
|
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays")
|
||||||
|
|
||||||
extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false);
|
extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false);
|
||||||
|
|
||||||
|
Overlays::Overlays() {
|
||||||
|
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||||
|
connect(pointerManager.data(), &PointerManager::hoverBeginOverlay, this, &Overlays::hoverEnterOverlay);
|
||||||
|
connect(pointerManager.data(), &PointerManager::hoverContinueOverlay, this, &Overlays::hoverOverOverlay);
|
||||||
|
connect(pointerManager.data(), &PointerManager::hoverEndOverlay, this, &Overlays::hoverLeaveOverlay);
|
||||||
|
connect(pointerManager.data(), &PointerManager::triggerBeginOverlay, this, &Overlays::mousePressOnOverlay);
|
||||||
|
connect(pointerManager.data(), &PointerManager::triggerContinueOverlay, this, &Overlays::mouseMoveOnOverlay);
|
||||||
|
connect(pointerManager.data(), &PointerManager::triggerEndOverlay, this, &Overlays::mouseReleaseOnOverlay);
|
||||||
|
}
|
||||||
|
|
||||||
void Overlays::cleanupAllOverlays() {
|
void Overlays::cleanupAllOverlays() {
|
||||||
QMap<OverlayID, Overlay::Pointer> overlaysHUD;
|
QMap<OverlayID, Overlay::Pointer> overlaysHUD;
|
||||||
QMap<OverlayID, Overlay::Pointer> overlaysWorld;
|
QMap<OverlayID, Overlay::Pointer> overlaysWorld;
|
||||||
|
|
|
@ -85,7 +85,7 @@ class Overlays : public QObject {
|
||||||
Q_PROPERTY(OverlayID keyboardFocusOverlay READ getKeyboardFocusOverlay WRITE setKeyboardFocusOverlay)
|
Q_PROPERTY(OverlayID keyboardFocusOverlay READ getKeyboardFocusOverlay WRITE setKeyboardFocusOverlay)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Overlays() {};
|
Overlays();
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void update(float deltatime);
|
void update(float deltatime);
|
||||||
|
|
|
@ -129,6 +129,8 @@ namespace controller {
|
||||||
template <typename F>
|
template <typename F>
|
||||||
void withLock(F&& f) { Locker locker(_lock); f(); }
|
void withLock(F&& f) { Locker locker(_lock); f(); }
|
||||||
|
|
||||||
|
EndpointPointer endpointFor(const Input& endpoint) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void actionEvent(int action, float state);
|
void actionEvent(int action, float state);
|
||||||
void inputEvent(int input, float state);
|
void inputEvent(int input, float state);
|
||||||
|
@ -161,7 +163,6 @@ namespace controller {
|
||||||
void disableMapping(const MappingPointer& mapping);
|
void disableMapping(const MappingPointer& mapping);
|
||||||
EndpointPointer endpointFor(const QJSValue& endpoint);
|
EndpointPointer endpointFor(const QJSValue& endpoint);
|
||||||
EndpointPointer endpointFor(const QScriptValue& endpoint);
|
EndpointPointer endpointFor(const QScriptValue& endpoint);
|
||||||
EndpointPointer endpointFor(const Input& endpoint) const;
|
|
||||||
EndpointPointer compositeEndpointFor(EndpointPointer first, EndpointPointer second);
|
EndpointPointer compositeEndpointFor(EndpointPointer first, EndpointPointer second);
|
||||||
ConditionalPointer conditionalFor(const QJSValue& endpoint);
|
ConditionalPointer conditionalFor(const QJSValue& endpoint);
|
||||||
ConditionalPointer conditionalFor(const QScriptValue& endpoint);
|
ConditionalPointer conditionalFor(const QScriptValue& endpoint);
|
||||||
|
|
|
@ -12,6 +12,8 @@ include_hifi_library_headers(animation)
|
||||||
include_hifi_library_headers(fbx)
|
include_hifi_library_headers(fbx)
|
||||||
include_hifi_library_headers(entities)
|
include_hifi_library_headers(entities)
|
||||||
include_hifi_library_headers(avatars)
|
include_hifi_library_headers(avatars)
|
||||||
|
include_hifi_library_headers(pointers)
|
||||||
|
include_hifi_library_headers(controllers)
|
||||||
|
|
||||||
target_bullet()
|
target_bullet()
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
#include "EntitiesRendererLogging.h"
|
#include "EntitiesRendererLogging.h"
|
||||||
#include "RenderableEntityItem.h"
|
#include "RenderableEntityItem.h"
|
||||||
|
|
||||||
|
#include <pointers/PointerManager.h>
|
||||||
|
|
||||||
size_t std::hash<EntityItemID>::operator()(const EntityItemID& id) const { return qHash(id); }
|
size_t std::hash<EntityItemID>::operator()(const EntityItemID& id) const { return qHash(id); }
|
||||||
std::function<bool()> EntityTreeRenderer::_entitiesShouldFadeFunction;
|
std::function<bool()> EntityTreeRenderer::_entitiesShouldFadeFunction;
|
||||||
|
|
||||||
|
@ -55,6 +57,14 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
||||||
EntityRenderer::initEntityRenderers();
|
EntityRenderer::initEntityRenderers();
|
||||||
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
|
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
|
||||||
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID;
|
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID;
|
||||||
|
|
||||||
|
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||||
|
connect(pointerManager.data(), &PointerManager::hoverBeginEntity, this, &EntityTreeRenderer::hoverEnterEntity);
|
||||||
|
connect(pointerManager.data(), &PointerManager::hoverContinueEntity, this, &EntityTreeRenderer::hoverOverEntity);
|
||||||
|
connect(pointerManager.data(), &PointerManager::hoverEndEntity, this, &EntityTreeRenderer::hoverLeaveEntity);
|
||||||
|
connect(pointerManager.data(), &PointerManager::triggerBeginEntity, this, &EntityTreeRenderer::mousePressOnEntity);
|
||||||
|
connect(pointerManager.data(), &PointerManager::triggerContinueEntity, this, &EntityTreeRenderer::mouseMoveOnEntity);
|
||||||
|
connect(pointerManager.data(), &PointerManager::triggerEndEntity, this, &EntityTreeRenderer::mouseReleaseOnEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityTreeRenderer::~EntityTreeRenderer() {
|
EntityTreeRenderer::~EntityTreeRenderer() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
set(TARGET_NAME pointers)
|
set(TARGET_NAME pointers)
|
||||||
setup_hifi_library()
|
setup_hifi_library()
|
||||||
GroupSources(src)
|
GroupSources(src)
|
||||||
link_hifi_libraries(shared)
|
link_hifi_libraries(shared controllers)
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
const PickFilter PickFilter::NOTHING;
|
const PickFilter PickFilter::NOTHING;
|
||||||
|
|
||||||
|
int pickTypeMetaTypeId = qRegisterMetaType<PickQuery::PickType>("PickType");
|
||||||
|
|
||||||
PickQuery::PickQuery(const PickFilter& filter, const float maxDistance, const bool enabled) :
|
PickQuery::PickQuery(const PickFilter& filter, const float maxDistance, const bool enabled) :
|
||||||
_filter(filter),
|
_filter(filter),
|
||||||
_maxDistance(maxDistance),
|
_maxDistance(maxDistance),
|
||||||
|
|
|
@ -136,7 +136,9 @@ public:
|
||||||
|
|
||||||
enum PickType {
|
enum PickType {
|
||||||
Ray = 0,
|
Ray = 0,
|
||||||
Stylus
|
Stylus,
|
||||||
|
|
||||||
|
NUM_PICK_TYPES
|
||||||
};
|
};
|
||||||
Q_ENUM(PickType)
|
Q_ENUM(PickType)
|
||||||
|
|
||||||
|
@ -189,6 +191,7 @@ private:
|
||||||
QVector<QUuid> _ignoreItems;
|
QVector<QUuid> _ignoreItems;
|
||||||
QVector<QUuid> _includeItems;
|
QVector<QUuid> _includeItems;
|
||||||
};
|
};
|
||||||
|
Q_DECLARE_METATYPE(PickQuery::PickType)
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Pick : public PickQuery {
|
class Pick : public PickQuery {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
#include "PickManager.h"
|
#include "PickManager.h"
|
||||||
|
#include "PointerManager.h"
|
||||||
|
|
||||||
Pointer::~Pointer() {
|
Pointer::~Pointer() {
|
||||||
DependencyManager::get<PickManager>()->removePick(_pickUID);
|
DependencyManager::get<PickManager>()->removePick(_pickUID);
|
||||||
|
@ -16,10 +17,16 @@ Pointer::~Pointer() {
|
||||||
|
|
||||||
void Pointer::enable() {
|
void Pointer::enable() {
|
||||||
DependencyManager::get<PickManager>()->enablePick(_pickUID);
|
DependencyManager::get<PickManager>()->enablePick(_pickUID);
|
||||||
|
withWriteLock([&] {
|
||||||
|
_enabled = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pointer::disable() {
|
void Pointer::disable() {
|
||||||
DependencyManager::get<PickManager>()->disablePick(_pickUID);
|
DependencyManager::get<PickManager>()->disablePick(_pickUID);
|
||||||
|
withWriteLock([&] {
|
||||||
|
_enabled = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVariantMap Pointer::getPrevPickResult() {
|
const QVariantMap Pointer::getPrevPickResult() {
|
||||||
|
@ -36,4 +43,118 @@ void Pointer::setIgnoreItems(const QVector<QUuid>& ignoreItems) const {
|
||||||
|
|
||||||
void Pointer::setIncludeItems(const QVector<QUuid>& includeItems) const {
|
void Pointer::setIncludeItems(const QVector<QUuid>& includeItems) const {
|
||||||
DependencyManager::get<PickManager>()->setIncludeItems(_pickUID, includeItems);
|
DependencyManager::get<PickManager>()->setIncludeItems(_pickUID, includeItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pointer::update() {
|
||||||
|
// This only needs to be a read lock because update won't change any of the properties that can be modified from scripts
|
||||||
|
withReadLock([&] {
|
||||||
|
QVariantMap pickResult = getPrevPickResult();
|
||||||
|
updateVisuals(pickResult);
|
||||||
|
generatePointerEvents(pickResult);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pointer::generatePointerEvents(const QVariantMap& pickResult) {
|
||||||
|
// TODO: avatars/HUD?
|
||||||
|
auto pointerManager = DependencyManager::get<PointerManager>();
|
||||||
|
|
||||||
|
// Hover events
|
||||||
|
Pointer::PickedObject hoveredObject = getHoveredObject(pickResult);
|
||||||
|
PointerEvent hoveredEvent = buildPointerEvent(hoveredObject.objectID, pickResult);
|
||||||
|
hoveredEvent.setType(PointerEvent::Move);
|
||||||
|
hoveredEvent.setButton(PointerEvent::NoButtons);
|
||||||
|
if (_enabled) {
|
||||||
|
if (hoveredObject.type == OVERLAY) {
|
||||||
|
if (_prevHoveredObject.type == OVERLAY) {
|
||||||
|
if (hoveredObject.objectID == _prevHoveredObject.objectID) {
|
||||||
|
emit pointerManager->hoverContinueOverlay(hoveredObject.objectID, hoveredEvent);
|
||||||
|
} else {
|
||||||
|
PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject.objectID, pickResult);
|
||||||
|
emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, prevHoveredEvent);
|
||||||
|
emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent);
|
||||||
|
if (_prevHoveredObject.type == ENTITY) {
|
||||||
|
emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this is basically repeated code. is there a way to clean it up?
|
||||||
|
if (hoveredObject.type == ENTITY) {
|
||||||
|
if (_prevHoveredObject.type == ENTITY) {
|
||||||
|
if (hoveredObject.objectID == _prevHoveredObject.objectID) {
|
||||||
|
emit pointerManager->hoverContinueEntity(hoveredObject.objectID, hoveredEvent);
|
||||||
|
} else {
|
||||||
|
PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject.objectID, pickResult);
|
||||||
|
emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, prevHoveredEvent);
|
||||||
|
emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent);
|
||||||
|
if (_prevHoveredObject.type == OVERLAY) {
|
||||||
|
emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger events
|
||||||
|
Buttons buttons;
|
||||||
|
Buttons newButtons;
|
||||||
|
Buttons sameButtons;
|
||||||
|
// NOTE: After this loop: _prevButtons = buttons that were removed
|
||||||
|
// If !_enabled, release all buttons
|
||||||
|
if (_enabled) {
|
||||||
|
buttons = getPressedButtons();
|
||||||
|
for (const std::string& button : buttons) {
|
||||||
|
if (_prevButtons.find(button) == _prevButtons.end()) {
|
||||||
|
newButtons.insert(button);
|
||||||
|
} else {
|
||||||
|
sameButtons.insert(button);
|
||||||
|
_prevButtons.erase(button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger begin
|
||||||
|
for (const std::string& button : newButtons) {
|
||||||
|
hoveredEvent.setType(PointerEvent::Press);
|
||||||
|
hoveredEvent.setButton(PointerEvent::PrimaryButton);
|
||||||
|
if (hoveredObject.type == ENTITY) {
|
||||||
|
emit pointerManager->triggerBeginEntity(hoveredObject.objectID, hoveredEvent);
|
||||||
|
} else if (hoveredObject.type == OVERLAY) {
|
||||||
|
emit pointerManager->triggerBeginOverlay(hoveredObject.objectID, hoveredEvent);
|
||||||
|
}
|
||||||
|
_triggeredObjects[button] = hoveredObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger continue
|
||||||
|
for (const std::string& button : sameButtons) {
|
||||||
|
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button].objectID, pickResult);
|
||||||
|
triggeredEvent.setType(PointerEvent::Move);
|
||||||
|
triggeredEvent.setButton(PointerEvent::PrimaryButton);
|
||||||
|
if (_triggeredObjects[button].type == ENTITY) {
|
||||||
|
emit pointerManager->triggerContinueEntity(_triggeredObjects[button].objectID, triggeredEvent);
|
||||||
|
} else if (_triggeredObjects[button].type == OVERLAY) {
|
||||||
|
emit pointerManager->triggerContinueOverlay(_triggeredObjects[button].objectID, triggeredEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger end
|
||||||
|
for (const std::string& button : _prevButtons) {
|
||||||
|
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button].objectID, pickResult);
|
||||||
|
triggeredEvent.setType(PointerEvent::Release);
|
||||||
|
triggeredEvent.setButton(PointerEvent::PrimaryButton);
|
||||||
|
if (_triggeredObjects[button].type == ENTITY) {
|
||||||
|
emit pointerManager->triggerEndEntity(_triggeredObjects[button].objectID, triggeredEvent);
|
||||||
|
} else if (_triggeredObjects[button].type == OVERLAY) {
|
||||||
|
emit pointerManager->triggerEndOverlay(_triggeredObjects[button].objectID, triggeredEvent);
|
||||||
|
}
|
||||||
|
_triggeredObjects.erase(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
_prevHoveredObject = hoveredObject;
|
||||||
|
_prevButtons = buttons;
|
||||||
}
|
}
|
|
@ -8,15 +8,37 @@
|
||||||
#ifndef hifi_Pointer_h
|
#ifndef hifi_Pointer_h
|
||||||
#define hifi_Pointer_h
|
#define hifi_Pointer_h
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <QtCore/QUuid>
|
#include <QtCore/QUuid>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
#include <shared/ReadWriteLockable.h>
|
#include <shared/ReadWriteLockable.h>
|
||||||
|
|
||||||
|
#include <controllers/impl/Endpoint.h>
|
||||||
|
#include "PointerEvent.h"
|
||||||
|
|
||||||
|
#include "Pick.h"
|
||||||
|
|
||||||
|
class PointerTrigger {
|
||||||
|
public:
|
||||||
|
PointerTrigger(controller::Endpoint::Pointer endpoint, const std::string& button) : _endpoint(endpoint), _button(button) {}
|
||||||
|
|
||||||
|
controller::Endpoint::Pointer getEndpoint() const { return _endpoint; }
|
||||||
|
const std::string& getButton() const { return _button; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
controller::Endpoint::Pointer _endpoint;
|
||||||
|
std::string _button { "" };
|
||||||
|
};
|
||||||
|
|
||||||
|
using PointerTriggers = std::vector<PointerTrigger>;
|
||||||
|
|
||||||
class Pointer : protected ReadWriteLockable {
|
class Pointer : protected ReadWriteLockable {
|
||||||
public:
|
public:
|
||||||
Pointer(const QUuid& uid) : _pickUID(uid) {}
|
Pointer(const QUuid& uid, bool enabled) : _pickUID(uid), _enabled(enabled) {}
|
||||||
|
|
||||||
virtual ~Pointer();
|
virtual ~Pointer();
|
||||||
|
|
||||||
|
@ -35,12 +57,35 @@ public:
|
||||||
virtual void setLength(const float length) {}
|
virtual void setLength(const float length) {}
|
||||||
virtual void setLockEndUUID(QUuid objectID, const bool isOverlay) {}
|
virtual void setLockEndUUID(QUuid objectID, const bool isOverlay) {}
|
||||||
|
|
||||||
virtual void update() = 0;
|
void update();
|
||||||
|
virtual void updateVisuals(const QVariantMap& pickResult) = 0;
|
||||||
|
void generatePointerEvents(const QVariantMap& pickResult);
|
||||||
|
|
||||||
|
struct PickedObject {
|
||||||
|
PickedObject() {}
|
||||||
|
PickedObject(const QUuid& objectID, IntersectionType type) : objectID(objectID), type(type) {}
|
||||||
|
|
||||||
|
QUuid objectID;
|
||||||
|
IntersectionType type;
|
||||||
|
} typedef PickedObject;
|
||||||
|
|
||||||
|
using Buttons = std::unordered_set<std::string>;
|
||||||
|
|
||||||
|
virtual PickedObject getHoveredObject(const QVariantMap& pickResult) = 0;
|
||||||
|
virtual Buttons getPressedButtons() = 0;
|
||||||
|
|
||||||
QUuid getRayUID() { return _pickUID; }
|
QUuid getRayUID() { return _pickUID; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool _enabled;
|
||||||
const QUuid _pickUID;
|
const QUuid _pickUID;
|
||||||
|
|
||||||
|
virtual PointerEvent buildPointerEvent(const QUuid& uid, const QVariantMap& pickResult) const = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PickedObject _prevHoveredObject;
|
||||||
|
Buttons _prevButtons;
|
||||||
|
std::unordered_map<std::string, PickedObject> _triggeredObjects;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_Pick_h
|
#endif // hifi_Pick_h
|
||||||
|
|
|
@ -45,13 +45,19 @@ private:
|
||||||
QHash<QUuid, std::shared_ptr<Pointer>> _pointers;
|
QHash<QUuid, std::shared_ptr<Pointer>> _pointers;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void triggerBegin(const QUuid& id, const PointerEvent& pointerEvent);
|
void triggerBeginOverlay(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
void triggerContinue(const QUuid& id, const PointerEvent& pointerEvent);
|
void triggerContinueOverlay(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
void triggerEnd(const QUuid& id, const PointerEvent& pointerEvent);
|
void triggerEndOverlay(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
void hoverBeginOverlay(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
void hoverContinueOverlay(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
void hoverEndOverlay(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
|
||||||
void hoverEnter(const QUuid& id, const PointerEvent& pointerEvent);
|
void triggerBeginEntity(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
void hoverOver(const QUuid& id, const PointerEvent& pointerEvent);
|
void triggerContinueEntity(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
void hoverLeave(const QUuid& id, const PointerEvent& pointerEvent);
|
void triggerEndEntity(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
void hoverBeginEntity(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
void hoverContinueEntity(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
|
void hoverEndEntity(const QUuid& id, const PointerEvent& pointerEvent);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_pointers_PointerManager_h
|
#endif // hifi_pointers_PointerManager_h
|
||||||
|
|
|
@ -39,7 +39,7 @@ public:
|
||||||
PointerEvent(EventType type, uint32_t id,
|
PointerEvent(EventType type, uint32_t id,
|
||||||
const glm::vec2& pos2D, const glm::vec3& pos3D,
|
const glm::vec2& pos2D, const glm::vec3& pos3D,
|
||||||
const glm::vec3& normal, const glm::vec3& direction,
|
const glm::vec3& normal, const glm::vec3& direction,
|
||||||
Button button, uint32_t buttons, Qt::KeyboardModifiers keyboardModifiers);
|
Button button, uint32_t buttons = NoButtons, Qt::KeyboardModifiers keyboardModifiers = Qt::KeyboardModifier::NoModifier);
|
||||||
|
|
||||||
static QScriptValue toScriptValue(QScriptEngine* engine, const PointerEvent& event);
|
static QScriptValue toScriptValue(QScriptEngine* engine, const PointerEvent& event);
|
||||||
static void fromScriptValue(const QScriptValue& object, PointerEvent& event);
|
static void fromScriptValue(const QScriptValue& object, PointerEvent& event);
|
||||||
|
@ -56,6 +56,9 @@ public:
|
||||||
uint32_t getButtons() const { return _buttons; }
|
uint32_t getButtons() const { return _buttons; }
|
||||||
Qt::KeyboardModifiers getKeyboardModifiers() const { return _keyboardModifiers; }
|
Qt::KeyboardModifiers getKeyboardModifiers() const { return _keyboardModifiers; }
|
||||||
|
|
||||||
|
void setType(EventType type) { _type = type; }
|
||||||
|
void setButton(Button button) { _button = button; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EventType _type;
|
EventType _type;
|
||||||
uint32_t _id; // used to identify the pointer. (left vs right hand, for example)
|
uint32_t _id; // used to identify the pointer. (left vs right hand, for example)
|
||||||
|
|
|
@ -32,7 +32,7 @@ var DEFAULT_SCRIPTS_COMBINED = [
|
||||||
"system/tablet-ui/tabletUI.js"
|
"system/tablet-ui/tabletUI.js"
|
||||||
];
|
];
|
||||||
var DEFAULT_SCRIPTS_SEPARATE = [
|
var DEFAULT_SCRIPTS_SEPARATE = [
|
||||||
"system/controllers/controllerScripts.js"
|
//"system/controllers/controllerScripts.js"
|
||||||
// "system/chat.js"
|
// "system/chat.js"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue