mirror of
https://github.com/lubosz/overte.git
synced 2025-04-10 08:57:12 +02:00
control hovering, preset buttons for clicking, constness, scroll off
surface
This commit is contained in:
parent
7951826e49
commit
e9a5acda06
7 changed files with 100 additions and 43 deletions
|
@ -17,9 +17,9 @@
|
|||
#include <pointers/PickManager.h>
|
||||
#include "PickScriptingInterface.h"
|
||||
|
||||
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) :
|
||||
Pointer(DependencyManager::get<PickScriptingInterface>()->createRayPick(rayProps), enabled),
|
||||
LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, bool hover,
|
||||
const PointerTriggers& triggers, bool faceAvatar, bool centerEndY, bool lockEnd, bool distanceScaleEnd, bool enabled) :
|
||||
Pointer(DependencyManager::get<PickScriptingInterface>()->createRayPick(rayProps), enabled, hover),
|
||||
_triggers(triggers),
|
||||
_renderStates(renderStates),
|
||||
_defaultRenderStates(defaultRenderStates),
|
||||
|
@ -83,7 +83,7 @@ void LaserPointer::updateRenderStateOverlay(const OverlayID& id, const QVariant&
|
|||
}
|
||||
}
|
||||
|
||||
void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, const float distance, const QUuid& objectID, const PickRay& pickRay, const bool defaultState) {
|
||||
void LaserPointer::updateRenderState(const RenderState& renderState, const IntersectionType type, float distance, const QUuid& objectID, const PickRay& pickRay, bool defaultState) {
|
||||
if (!renderState.getStartID().isNull()) {
|
||||
QVariantMap startProps;
|
||||
startProps.insert("position", vec3toVariant(pickRay.origin));
|
||||
|
@ -210,13 +210,13 @@ Pointer::Buttons LaserPointer::getPressedButtons() {
|
|||
return toReturn;
|
||||
}
|
||||
|
||||
void LaserPointer::setLength(const float length) {
|
||||
void LaserPointer::setLength(float length) {
|
||||
withWriteLock([&] {
|
||||
_laserLength = length;
|
||||
});
|
||||
}
|
||||
|
||||
void LaserPointer::setLockEndUUID(QUuid objectID, const bool isOverlay) {
|
||||
void LaserPointer::setLockEndUUID(const QUuid& objectID, bool isOverlay) {
|
||||
withWriteLock([&] {
|
||||
_objectLockEnd = std::pair<QUuid, bool>(objectID, isOverlay);
|
||||
});
|
||||
|
@ -281,21 +281,49 @@ RenderState LaserPointer::buildRenderState(const QVariantMap& propMap) {
|
|||
return RenderState(startID, pathID, endID);
|
||||
}
|
||||
|
||||
PointerEvent LaserPointer::buildPointerEvent(const QUuid& uid, const QVariantMap& pickResult) const {
|
||||
PointerEvent LaserPointer::buildPointerEvent(const PickedObject& target, 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());
|
||||
QUuid pickedID = pickResult["objectID"].toUuid();
|
||||
glm::vec2 pos2D;
|
||||
if (type == ENTITY) {
|
||||
pos2D = projectOntoEntityXYPlane(uid, intersection);
|
||||
} else if (type == OVERLAY) {
|
||||
pos2D = projectOntoOverlayXYPlane(uid, intersection);
|
||||
if (pickedID != target.objectID) {
|
||||
QVariantMap searchRay = pickResult["searchRay"].toMap();
|
||||
glm::vec3 origin = vec3FromVariant(searchRay["origin"]);
|
||||
glm::vec3 direction = vec3FromVariant(searchRay["direction"]);
|
||||
if (target.type == ENTITY) {
|
||||
intersection = intersectRayWithEntityXYPlane(target.objectID, origin, direction);
|
||||
} else if (target.type == OVERLAY) {
|
||||
intersection = intersectRayWithOverlayXYPlane(target.objectID, origin, direction);
|
||||
}
|
||||
}
|
||||
if (target.type == ENTITY) {
|
||||
pos2D = projectOntoEntityXYPlane(target.objectID, intersection);
|
||||
} else if (target.type == OVERLAY) {
|
||||
pos2D = projectOntoOverlayXYPlane(target.objectID, intersection);
|
||||
}
|
||||
return PointerEvent(PointerEvent::Move, id, pos2D, intersection, surfaceNormal, direction, PointerEvent::NoButtons);
|
||||
}
|
||||
|
||||
glm::vec3 LaserPointer::intersectRayWithXYPlane(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& point, const glm::quat rotation, const glm::vec3& registration) const {
|
||||
glm::vec3 n = rotation * Vectors::FRONT;
|
||||
float t = glm::dot(n, point - origin) / glm::dot(n, direction);
|
||||
return origin + t * direction;
|
||||
}
|
||||
|
||||
glm::vec3 LaserPointer::intersectRayWithOverlayXYPlane(const QUuid& overlayID, const glm::vec3& origin, const glm::vec3& direction) const {
|
||||
glm::vec3 position = vec3FromVariant(qApp->getOverlays().getProperty(overlayID, "position").value);
|
||||
glm::quat rotation = quatFromVariant(qApp->getOverlays().getProperty(overlayID, "rotation").value);
|
||||
const glm::vec3 DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f);
|
||||
return intersectRayWithXYPlane(origin, direction, position, rotation, DEFAULT_REGISTRATION_POINT);
|
||||
}
|
||||
|
||||
glm::vec3 LaserPointer::intersectRayWithEntityXYPlane(const QUuid& entityID, const glm::vec3& origin, const glm::vec3& direction) const {
|
||||
auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
|
||||
return intersectRayWithXYPlane(origin, direction, props.getPosition(), props.getRotation(), props.getRegistrationPoint());
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -325,7 +353,7 @@ glm::vec2 LaserPointer::projectOntoOverlayXYPlane(const QUuid& overlayID, const
|
|||
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);
|
||||
glm::vec2 LaserPointer::projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos) const {
|
||||
auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
|
||||
return projectOntoXYPlane(worldPos, props.getPosition(), props.getRotation(), props.getDimensions(), props.getRegistrationPoint());
|
||||
}
|
|
@ -54,16 +54,16 @@ public:
|
|||
typedef std::unordered_map<std::string, RenderState> RenderStateMap;
|
||||
typedef std::unordered_map<std::string, std::pair<float, RenderState>> DefaultRenderStateMap;
|
||||
|
||||
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);
|
||||
LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, bool hover, const PointerTriggers& triggers,
|
||||
bool faceAvatar, bool centerEndY, bool lockEnd, bool distanceScaleEnd, bool enabled);
|
||||
~LaserPointer();
|
||||
|
||||
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) override;
|
||||
|
||||
void setLength(const float length) override;
|
||||
void setLockEndUUID(QUuid objectID, const bool isOverlay) override;
|
||||
void setLength(float length) override;
|
||||
void setLockEndUUID(const QUuid& objectID, bool isOverlay) override;
|
||||
|
||||
void updateVisuals(const QVariantMap& prevRayPickResult) override;
|
||||
|
||||
|
@ -73,7 +73,7 @@ public:
|
|||
static RenderState buildRenderState(const QVariantMap& propMap);
|
||||
|
||||
protected:
|
||||
PointerEvent buildPointerEvent(const QUuid& uid, const QVariantMap& pickResult) const override;
|
||||
PointerEvent buildPointerEvent(const PickedObject& target, const QVariantMap& pickResult) const override;
|
||||
|
||||
private:
|
||||
PointerTriggers _triggers;
|
||||
|
@ -88,10 +88,14 @@ private:
|
|||
std::pair<QUuid, bool> _objectLockEnd { std::pair<QUuid, bool>(QUuid(), false)};
|
||||
|
||||
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 updateRenderState(const RenderState& renderState, const IntersectionType type, float distance, const QUuid& objectID, const PickRay& pickRay, bool defaultState);
|
||||
void disableRenderState(const RenderState& renderState);
|
||||
|
||||
glm::vec2 projectOntoEntityXYPlane(const QUuid& entity, const glm::vec3& worldPos) const;
|
||||
|
||||
glm::vec3 intersectRayWithEntityXYPlane(const QUuid& entityID, const glm::vec3& origin, const glm::vec3& direction) const;
|
||||
glm::vec3 intersectRayWithOverlayXYPlane(const QUuid& overlayID, const glm::vec3& origin, const glm::vec3& direction) const;
|
||||
glm::vec3 intersectRayWithXYPlane(const glm::vec3& origin, const glm::vec3& direction, const glm::vec3& point, const glm::quat rotation, const glm::vec3& registration) const;
|
||||
glm::vec2 projectOntoEntityXYPlane(const QUuid& entityID, 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;
|
||||
|
||||
|
|
|
@ -87,6 +87,11 @@ QUuid PointerScriptingInterface::createLaserPointer(const QVariant& properties)
|
|||
}
|
||||
}
|
||||
|
||||
bool hover = false;
|
||||
if (propertyMap["hover"].isValid()) {
|
||||
hover = propertyMap["hover"].toBool();
|
||||
}
|
||||
|
||||
PointerTriggers triggers;
|
||||
auto userInputMapper = DependencyManager::get<UserInputMapper>();
|
||||
if (propertyMap["triggers"].isValid()) {
|
||||
|
@ -105,7 +110,7 @@ QUuid PointerScriptingInterface::createLaserPointer(const QVariant& properties)
|
|||
}
|
||||
}
|
||||
|
||||
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<LaserPointer>(properties, renderStates, defaultRenderStates, triggers,
|
||||
return DependencyManager::get<PointerManager>()->addPointer(std::make_shared<LaserPointer>(properties, renderStates, defaultRenderStates, hover, triggers,
|
||||
faceAvatar, centerEndY, lockEnd, distanceScaleEnd, enabled));
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ const QVariantMap Pointer::getPrevPickResult() {
|
|||
return DependencyManager::get<PickManager>()->getPrevPickResult(_pickUID);
|
||||
}
|
||||
|
||||
void Pointer::setPrecisionPicking(const bool precisionPicking) {
|
||||
void Pointer::setPrecisionPicking(bool precisionPicking) {
|
||||
DependencyManager::get<PickManager>()->setPrecisionPicking(_pickUID, precisionPicking);
|
||||
}
|
||||
|
||||
|
@ -60,16 +60,17 @@ void Pointer::generatePointerEvents(const QVariantMap& pickResult) {
|
|||
|
||||
// Hover events
|
||||
Pointer::PickedObject hoveredObject = getHoveredObject(pickResult);
|
||||
PointerEvent hoveredEvent = buildPointerEvent(hoveredObject.objectID, pickResult);
|
||||
PointerEvent hoveredEvent = buildPointerEvent(hoveredObject, pickResult);
|
||||
hoveredEvent.setType(PointerEvent::Move);
|
||||
// TODO: set buttons on hover events
|
||||
hoveredEvent.setButton(PointerEvent::NoButtons);
|
||||
if (_enabled) {
|
||||
if (_enabled && _hover) {
|
||||
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);
|
||||
PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject, pickResult);
|
||||
emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, prevHoveredEvent);
|
||||
emit pointerManager->hoverBeginOverlay(hoveredObject.objectID, hoveredEvent);
|
||||
}
|
||||
|
@ -87,7 +88,7 @@ void Pointer::generatePointerEvents(const QVariantMap& pickResult) {
|
|||
if (hoveredObject.objectID == _prevHoveredObject.objectID) {
|
||||
emit pointerManager->hoverContinueEntity(hoveredObject.objectID, hoveredEvent);
|
||||
} else {
|
||||
PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject.objectID, pickResult);
|
||||
PointerEvent prevHoveredEvent = buildPointerEvent(_prevHoveredObject, pickResult);
|
||||
emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, prevHoveredEvent);
|
||||
emit pointerManager->hoverBeginEntity(hoveredObject.objectID, hoveredEvent);
|
||||
}
|
||||
|
@ -122,7 +123,7 @@ void Pointer::generatePointerEvents(const QVariantMap& pickResult) {
|
|||
const std::string SHOULD_FOCUS_BUTTON = "Focus";
|
||||
for (const std::string& button : newButtons) {
|
||||
hoveredEvent.setType(PointerEvent::Press);
|
||||
hoveredEvent.setButton(PointerEvent::PrimaryButton);
|
||||
hoveredEvent.setButton(chooseButton(button));
|
||||
hoveredEvent.setShouldFocus(button == SHOULD_FOCUS_BUTTON);
|
||||
if (hoveredObject.type == ENTITY) {
|
||||
emit pointerManager->triggerBeginEntity(hoveredObject.objectID, hoveredEvent);
|
||||
|
@ -134,9 +135,9 @@ void Pointer::generatePointerEvents(const QVariantMap& pickResult) {
|
|||
|
||||
// Trigger continue
|
||||
for (const std::string& button : sameButtons) {
|
||||
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button].objectID, pickResult);
|
||||
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult);
|
||||
triggeredEvent.setType(PointerEvent::Move);
|
||||
triggeredEvent.setButton(PointerEvent::PrimaryButton);
|
||||
hoveredEvent.setButton(chooseButton(button));
|
||||
if (_triggeredObjects[button].type == ENTITY) {
|
||||
emit pointerManager->triggerContinueEntity(_triggeredObjects[button].objectID, triggeredEvent);
|
||||
} else if (_triggeredObjects[button].type == OVERLAY) {
|
||||
|
@ -146,9 +147,9 @@ void Pointer::generatePointerEvents(const QVariantMap& pickResult) {
|
|||
|
||||
// Trigger end
|
||||
for (const std::string& button : _prevButtons) {
|
||||
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button].objectID, pickResult);
|
||||
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult);
|
||||
triggeredEvent.setType(PointerEvent::Release);
|
||||
triggeredEvent.setButton(PointerEvent::PrimaryButton);
|
||||
hoveredEvent.setButton(chooseButton(button));
|
||||
if (_triggeredObjects[button].type == ENTITY) {
|
||||
emit pointerManager->triggerEndEntity(_triggeredObjects[button].objectID, triggeredEvent);
|
||||
} else if (_triggeredObjects[button].type == OVERLAY) {
|
||||
|
@ -159,4 +160,19 @@ void Pointer::generatePointerEvents(const QVariantMap& pickResult) {
|
|||
|
||||
_prevHoveredObject = hoveredObject;
|
||||
_prevButtons = buttons;
|
||||
}
|
||||
|
||||
PointerEvent::Button Pointer::chooseButton(const std::string& button) {
|
||||
const std::string PRIMARY_BUTTON = "Primary";
|
||||
const std::string SECONDARY_BUTTON = "Secondary";
|
||||
const std::string TERTIARY_BUTTON = "Tertiary";
|
||||
if (button == PRIMARY_BUTTON) {
|
||||
return PointerEvent::PrimaryButton;
|
||||
} else if (button == SECONDARY_BUTTON) {
|
||||
return PointerEvent::SecondaryButton;
|
||||
} else if (button == TERTIARY_BUTTON) {
|
||||
return PointerEvent::TertiaryButton;
|
||||
} else {
|
||||
return PointerEvent::NoButtons;
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ using PointerTriggers = std::vector<PointerTrigger>;
|
|||
|
||||
class Pointer : protected ReadWriteLockable {
|
||||
public:
|
||||
Pointer(const QUuid& uid, bool enabled) : _pickUID(uid), _enabled(enabled) {}
|
||||
Pointer(const QUuid& uid, bool enabled, bool hover) : _pickUID(uid), _enabled(enabled), _hover(hover) {}
|
||||
|
||||
virtual ~Pointer();
|
||||
|
||||
|
@ -49,13 +49,13 @@ public:
|
|||
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 setPrecisionPicking(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 setLength(float length) {}
|
||||
virtual void setLockEndUUID(const QUuid& objectID, bool isOverlay) {}
|
||||
|
||||
void update();
|
||||
virtual void updateVisuals(const QVariantMap& pickResult) = 0;
|
||||
|
@ -79,13 +79,17 @@ public:
|
|||
protected:
|
||||
const QUuid _pickUID;
|
||||
bool _enabled;
|
||||
bool _hover;
|
||||
|
||||
virtual PointerEvent buildPointerEvent(const QUuid& uid, const QVariantMap& pickResult) const = 0;
|
||||
virtual PointerEvent buildPointerEvent(const PickedObject& target, const QVariantMap& pickResult) const = 0;
|
||||
|
||||
private:
|
||||
PickedObject _prevHoveredObject;
|
||||
Buttons _prevButtons;
|
||||
std::unordered_map<std::string, PickedObject> _triggeredObjects;
|
||||
|
||||
PointerEvent::Button chooseButton(const std::string& button);
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_Pick_h
|
||||
|
|
|
@ -79,7 +79,7 @@ void PointerManager::update() {
|
|||
}
|
||||
}
|
||||
|
||||
void PointerManager::setPrecisionPicking(const QUuid& uid, const bool precisionPicking) const {
|
||||
void PointerManager::setPrecisionPicking(const QUuid& uid, bool precisionPicking) const {
|
||||
auto pointer = find(uid);
|
||||
if (pointer) {
|
||||
pointer->setPrecisionPicking(precisionPicking);
|
||||
|
@ -100,14 +100,14 @@ void PointerManager::setIncludeItems(const QUuid& uid, const QVector<QUuid>& inc
|
|||
}
|
||||
}
|
||||
|
||||
void PointerManager::setLength(const QUuid& uid, const float length) const {
|
||||
void PointerManager::setLength(const QUuid& uid, 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 {
|
||||
void PointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay) const {
|
||||
auto pointer = find(uid);
|
||||
if (pointer) {
|
||||
pointer->setLockEndUUID(objectID, isOverlay);
|
||||
|
|
|
@ -31,12 +31,12 @@ public:
|
|||
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 setPrecisionPicking(const QUuid& uid, 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 setLength(const QUuid& uid, float length) const;
|
||||
void setLockEndUUID(const QUuid& uid, const QUuid& objectID, bool isOverlay) const;
|
||||
|
||||
void update();
|
||||
|
||||
|
|
Loading…
Reference in a new issue