mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:44:01 +02:00
first cut at wiring up new entity specific UI/UX events
This commit is contained in:
parent
8c013a84ff
commit
277da5a24f
5 changed files with 193 additions and 0 deletions
|
@ -1248,6 +1248,8 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
if (_lastMouseMoveWasSimulated) {
|
||||
showMouse = false;
|
||||
}
|
||||
|
||||
_entities.mouseMoveEvent(event, deviceID);
|
||||
|
||||
_controllerScriptingInterface.emitMouseMoveEvent(event, deviceID); // send events to any registered scripts
|
||||
|
||||
|
@ -1269,6 +1271,9 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
}
|
||||
|
||||
void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
|
||||
_entities.mousePressEvent(event, deviceID);
|
||||
|
||||
_controllerScriptingInterface.emitMousePressEvent(event); // send events to any registered scripts
|
||||
|
||||
// if one of our scripts have asked to capture this event, then stop processing it
|
||||
|
@ -1306,6 +1311,9 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
}
|
||||
|
||||
void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
|
||||
_entities.mouseReleaseEvent(event, deviceID);
|
||||
|
||||
_controllerScriptingInterface.emitMouseReleaseEvent(event); // send events to any registered scripts
|
||||
|
||||
// if one of our scripts have asked to capture this event, then stop processing it
|
||||
|
@ -1940,6 +1948,10 @@ void Application::init() {
|
|||
connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity,
|
||||
ScriptEngine::getEntityScriptingInterface(), &EntityScriptingInterface::entityCollisionWithEntity);
|
||||
|
||||
// connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing
|
||||
// of events related clicking, hovering over, and entering entities
|
||||
_entities.connectSignalsToSlots(ScriptEngine::getEntityScriptingInterface());
|
||||
|
||||
_entityClipboardRenderer.init();
|
||||
_entityClipboardRenderer.setViewFrustum(getViewFrustum());
|
||||
_entityClipboardRenderer.setTree(&_entityClipboard);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <BoxEntityItem.h>
|
||||
#include <ModelEntityItem.h>
|
||||
#include <MouseEvent.h>
|
||||
#include <PerfStat.h>
|
||||
#include <RenderArgs.h>
|
||||
|
||||
|
@ -24,6 +25,8 @@
|
|||
#include "Menu.h"
|
||||
#include "EntityTreeRenderer.h"
|
||||
|
||||
#include "devices/OculusManager.h"
|
||||
|
||||
#include "RenderableBoxEntityItem.h"
|
||||
#include "RenderableLightEntityItem.h"
|
||||
#include "RenderableModelEntityItem.h"
|
||||
|
@ -42,6 +45,9 @@ EntityTreeRenderer::EntityTreeRenderer() :
|
|||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, RenderableBoxEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, RenderableSphereEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, RenderableLightEntityItem::factory)
|
||||
|
||||
_currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID
|
||||
_currentClickingOnEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID
|
||||
}
|
||||
|
||||
EntityTreeRenderer::~EntityTreeRenderer() {
|
||||
|
@ -382,4 +388,130 @@ void EntityTreeRenderer::deleteReleasedModels() {
|
|||
}
|
||||
}
|
||||
|
||||
PickRay EntityTreeRenderer::computePickRay(float x, float y) {
|
||||
float screenWidth = Application::getInstance()->getGLWidget()->width();
|
||||
float screenHeight = Application::getInstance()->getGLWidget()->height();
|
||||
PickRay result;
|
||||
if (OculusManager::isConnected()) {
|
||||
Camera* camera = Application::getInstance()->getCamera();
|
||||
result.origin = camera->getPosition();
|
||||
Application::getInstance()->getApplicationOverlay().computeOculusPickRay(x / screenWidth, y / screenHeight, result.direction);
|
||||
} else {
|
||||
ViewFrustum* viewFrustum = Application::getInstance()->getViewFrustum();
|
||||
viewFrustum->computePickRay(x / screenWidth, y / screenHeight, result.origin, result.direction);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
RayToEntityIntersectionResult EntityTreeRenderer::findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType) {
|
||||
RayToEntityIntersectionResult result;
|
||||
if (_tree) {
|
||||
EntityTree* entityTree = static_cast<EntityTree*>(_tree);
|
||||
|
||||
OctreeElement* element;
|
||||
EntityItem* intersectedEntity = NULL;
|
||||
result.intersects = entityTree->findRayIntersection(ray.origin, ray.direction, element, result.distance, result.face,
|
||||
(void**)&intersectedEntity, lockType, &result.accurate);
|
||||
if (result.intersects && intersectedEntity) {
|
||||
result.entityID = intersectedEntity->getEntityItemID();
|
||||
result.properties = intersectedEntity->getProperties();
|
||||
result.intersection = ray.origin + (ray.direction * result.distance);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface) {
|
||||
connect(this, &EntityTreeRenderer::mousePressOnEntity, entityScriptingInterface, &EntityScriptingInterface::mousePressOnEntity);
|
||||
connect(this, &EntityTreeRenderer::mouseMoveOnEntity, entityScriptingInterface, &EntityScriptingInterface::mouseMoveOnEntity);
|
||||
connect(this, &EntityTreeRenderer::mouseReleaseOnEntity, entityScriptingInterface, &EntityScriptingInterface::mouseReleaseOnEntity);
|
||||
|
||||
connect(this, &EntityTreeRenderer::clickDownOnEntity, entityScriptingInterface, &EntityScriptingInterface::clickDownOnEntity);
|
||||
connect(this, &EntityTreeRenderer::holdingClickOnEntity, entityScriptingInterface, &EntityScriptingInterface::holdingClickOnEntity);
|
||||
connect(this, &EntityTreeRenderer::clickReleaseOnEntity, entityScriptingInterface, &EntityScriptingInterface::clickReleaseOnEntity);
|
||||
|
||||
connect(this, &EntityTreeRenderer::hoverEnterEntity, entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity);
|
||||
connect(this, &EntityTreeRenderer::hoverOverEntity, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
|
||||
connect(this, &EntityTreeRenderer::hoverLeaveEntity, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mousePressEvent");
|
||||
PickRay ray = computePickRay(event->x(), event->y());
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock);
|
||||
if (rayPickResult.intersects) {
|
||||
//qDebug() << "mousePressEvent over entity:" << rayPickResult.entityID;
|
||||
emit mousePressOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
|
||||
_currentClickingOnEntityID = rayPickResult.entityID;
|
||||
emit clickDownOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID));
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseReleaseEvent");
|
||||
PickRay ray = computePickRay(event->x(), event->y());
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock);
|
||||
if (rayPickResult.intersects) {
|
||||
//qDebug() << "mouseReleaseEvent over entity:" << rayPickResult.entityID;
|
||||
emit mouseReleaseOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
}
|
||||
|
||||
// Even if we're no longer intersecting with an entity, if we started clicking on it, and now
|
||||
// we're releasing the button, then this is considered a clickOn event
|
||||
if (!_currentClickingOnEntityID.isInvalidID()) {
|
||||
emit clickReleaseOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID));
|
||||
}
|
||||
|
||||
// makes it the unknown ID, we just released so we can't be clicking on anything
|
||||
_currentClickingOnEntityID = EntityItemID::createInvalidEntityID();
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseMoveEvent");
|
||||
PickRay ray = computePickRay(event->x(), event->y());
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::TryLock);
|
||||
if (rayPickResult.intersects) {
|
||||
//qDebug() << "mouseMoveEvent over entity:" << rayPickResult.entityID;
|
||||
emit mouseMoveOnEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
|
||||
// handle the hover logic...
|
||||
|
||||
// if we were previously hovering over an entity, and this new entity is not the same as our previous entity
|
||||
// then we need to send the hover leave.
|
||||
if (!_currentHoverOverEntityID.isInvalidID() && rayPickResult.entityID != _currentHoverOverEntityID) {
|
||||
emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID));
|
||||
}
|
||||
|
||||
// If the new hover entity does not match the previous hover entity then we are entering the new one
|
||||
// this is true if the _currentHoverOverEntityID is known or unknown
|
||||
if (rayPickResult.entityID != _currentHoverOverEntityID) {
|
||||
emit hoverEnterEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
}
|
||||
|
||||
// and finally, no matter what, if we're intersecting an entity then we're definitely hovering over it, and
|
||||
// we should send our hover over event
|
||||
emit hoverOverEntity(rayPickResult.entityID, MouseEvent(*event, deviceID));
|
||||
|
||||
// remember what we're hovering over
|
||||
_currentHoverOverEntityID = rayPickResult.entityID;
|
||||
|
||||
} else {
|
||||
// handle the hover logic...
|
||||
// if we were previously hovering over an entity, and we're no longer hovering over any entity then we need to
|
||||
// send the hover leave for our previous entity
|
||||
if (!_currentHoverOverEntityID.isInvalidID()) {
|
||||
emit hoverLeaveEntity(_currentHoverOverEntityID, MouseEvent(*event, deviceID));
|
||||
_currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID
|
||||
}
|
||||
}
|
||||
|
||||
// Even if we're no longer intersecting with an entity, if we started clicking on an entity and we have
|
||||
// not yet released the hold then this is still considered a holdingClickOnEntity event
|
||||
if (!_currentClickingOnEntityID.isInvalidID()) {
|
||||
emit holdingClickOnEntity(_currentClickingOnEntityID, MouseEvent(*event, deviceID));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include <EntityTree.h>
|
||||
#include <EntityScriptingInterface.h> // for RayToEntityIntersectionResult
|
||||
#include <Octree.h>
|
||||
#include <OctreePacketData.h>
|
||||
#include <OctreeRenderer.h>
|
||||
|
@ -75,9 +76,37 @@ public:
|
|||
void releaseModel(Model* model);
|
||||
|
||||
void deleteReleasedModels();
|
||||
|
||||
// event handles which may generate entity related events
|
||||
void mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID);
|
||||
void mousePressEvent(QMouseEvent* event, unsigned int deviceID);
|
||||
void mouseMoveEvent(QMouseEvent* event, unsigned int deviceID);
|
||||
|
||||
/// connect our signals to anEntityScriptingInterface for firing of events related clicking,
|
||||
/// hovering over, and entering entities
|
||||
void connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface);
|
||||
|
||||
signals:
|
||||
void mousePressOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void mouseMoveOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void mouseReleaseOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
|
||||
void clickDownOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void holdingClickOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void clickReleaseOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
|
||||
void hoverEnterEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void hoverOverEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void hoverLeaveEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
|
||||
private:
|
||||
QList<Model*> _releasedModels;
|
||||
void renderProxies(const EntityItem* entity, RenderArgs* args);
|
||||
PickRay computePickRay(float x, float y);
|
||||
RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType);
|
||||
|
||||
EntityItemID _currentHoverOverEntityID;
|
||||
EntityItemID _currentClickingOnEntityID;
|
||||
};
|
||||
|
||||
#endif // hifi_EntityTreeRenderer_h
|
||||
|
|
|
@ -49,7 +49,10 @@ public:
|
|||
EntityItemID convertToKnownIDVersion() const;
|
||||
EntityItemID convertToCreatorTokenVersion() const;
|
||||
|
||||
bool isInvalidID() const { return id == UNKNOWN_ENTITY_ID && creatorTokenID == UNKNOWN_ENTITY_TOKEN && isKnownID == false; }
|
||||
|
||||
// these methods allow you to create models, and later edit them.
|
||||
static EntityItemID createInvalidEntityID() { return EntityItemID(UNKNOWN_ENTITY_ID, UNKNOWN_ENTITY_TOKEN, false); }
|
||||
static EntityItemID getIDfromCreatorTokenID(uint32_t creatorTokenID);
|
||||
static uint32_t getNextCreatorTokenID();
|
||||
static void handleAddEntityResponse(const QByteArray& packet);
|
||||
|
@ -74,6 +77,10 @@ inline bool operator==(const EntityItemID& a, const EntityItemID& b) {
|
|||
return a.id == b.id;
|
||||
}
|
||||
|
||||
inline bool operator!=(const EntityItemID& a, const EntityItemID& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
inline uint qHash(const EntityItemID& a, uint seed) {
|
||||
QUuid temp;
|
||||
if (a.id == UNKNOWN_ENTITY_ID) {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
|
||||
class EntityTree;
|
||||
class MouseEvent;
|
||||
|
||||
|
||||
class RayToEntityIntersectionResult {
|
||||
|
@ -101,6 +102,18 @@ signals:
|
|||
void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const CollisionInfo& collision);
|
||||
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const CollisionInfo& collision);
|
||||
|
||||
void mousePressOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void mouseMoveOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void mouseReleaseOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
|
||||
void clickDownOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void holdingClickOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void clickReleaseOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
|
||||
void hoverEnterEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void hoverOverEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
void hoverLeaveEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||
|
||||
private:
|
||||
void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties);
|
||||
|
||||
|
|
Loading…
Reference in a new issue