From 305e69def64d3648ad15f89aa68c1ec0990e8ca4 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 28 Jan 2014 19:47:45 -0800 Subject: [PATCH] really get controller key, mouse, etc scripting working --- interface/src/Application.cpp | 57 ++++++++++ .../src/ControllerScriptingInterface.cpp | 35 ++++++ interface/src/ControllerScriptingInterface.h | 49 ++++++--- libraries/particles/src/ParticleTree.cpp | 14 +-- .../AbstractControllerScriptingInterface.h | 13 +++ libraries/script-engine/src/EventTypes.cpp | 103 +++++++++++------- libraries/script-engine/src/EventTypes.h | 27 ++++- 7 files changed, 226 insertions(+), 72 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fd365d67e8..1a673da70c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -683,6 +683,11 @@ void Application::controlledBroadcastToNodes(unsigned char* broadcastData, size_ void Application::keyPressEvent(QKeyEvent* event) { _controllerScriptingInterface.emitKeyPressEvent(event); // send events to any registered scripts + + // if one of our scripts have asked to capture this event, then stop processing it + if (_controllerScriptingInterface.isKeyCaptured(event)) { + return; + } if (activeWindow() == _window) { if (_chatEntryOn) { @@ -1098,6 +1103,12 @@ void Application::keyReleaseEvent(QKeyEvent* event) { _controllerScriptingInterface.emitKeyReleaseEvent(event); // send events to any registered scripts + // if one of our scripts have asked to capture this event, then stop processing it + if (_controllerScriptingInterface.isKeyCaptured(event)) { + return; + } + + if (activeWindow() == _window) { if (_chatEntryOn) { _myAvatar.setKeyState(NO_KEY_DOWN); @@ -1162,6 +1173,12 @@ void Application::keyReleaseEvent(QKeyEvent* event) { void Application::mouseMoveEvent(QMouseEvent* event) { _controllerScriptingInterface.emitMouseMoveEvent(event); // send events to any registered scripts + // if one of our scripts have asked to capture this event, then stop processing it + if (_controllerScriptingInterface.isMouseCaptured()) { + return; + } + + _lastMouseMove = usecTimestampNow(); if (_mouseHidden) { getGLWidget()->setCursor(Qt::ArrowCursor); @@ -1209,6 +1226,13 @@ const float HOVER_VOXEL_DECAY = 0.999f; void Application::mousePressEvent(QMouseEvent* event) { _controllerScriptingInterface.emitMousePressEvent(event); // send events to any registered scripts + + // if one of our scripts have asked to capture this event, then stop processing it + if (_controllerScriptingInterface.isMouseCaptured()) { + return; + } + + if (activeWindow() == _window) { if (event->button() == Qt::LeftButton) { _mouseX = event->x(); @@ -1277,6 +1301,12 @@ void Application::mousePressEvent(QMouseEvent* event) { void Application::mouseReleaseEvent(QMouseEvent* event) { _controllerScriptingInterface.emitMouseReleaseEvent(event); // send events to any registered scripts + + // if one of our scripts have asked to capture this event, then stop processing it + if (_controllerScriptingInterface.isMouseCaptured()) { + return; + } + if (activeWindow() == _window) { if (event->button() == Qt::LeftButton) { _mouseX = event->x(); @@ -1294,6 +1324,12 @@ void Application::mouseReleaseEvent(QMouseEvent* event) { void Application::touchUpdateEvent(QTouchEvent* event) { _controllerScriptingInterface.emitTouchUpdateEvent(event); // send events to any registered scripts + + // if one of our scripts have asked to capture this event, then stop processing it + if (_controllerScriptingInterface.isTouchCaptured()) { + return; + } + bool validTouch = false; if (activeWindow() == _window) { const QList& tPoints = event->touchPoints(); @@ -1321,21 +1357,42 @@ void Application::touchBeginEvent(QTouchEvent* event) { _controllerScriptingInterface.emitTouchBeginEvent(event); // send events to any registered scripts touchUpdateEvent(event); + + // if one of our scripts have asked to capture this event, then stop processing it + if (_controllerScriptingInterface.isTouchCaptured()) { + return; + } + + // put any application specific touch behavior below here.. _lastTouchAvgX = _touchAvgX; _lastTouchAvgY = _touchAvgY; + } void Application::touchEndEvent(QTouchEvent* event) { _controllerScriptingInterface.emitTouchEndEvent(event); // send events to any registered scripts + + // if one of our scripts have asked to capture this event, then stop processing it + if (_controllerScriptingInterface.isTouchCaptured()) { + return; + } + + // put any application specific touch behavior below here.. _touchDragStartedAvgX = _touchAvgX; _touchDragStartedAvgY = _touchAvgY; _isTouchPressed = false; + } const bool USE_MOUSEWHEEL = false; void Application::wheelEvent(QWheelEvent* event) { _controllerScriptingInterface.emitWheelEvent(event); // send events to any registered scripts + + // if one of our scripts have asked to capture this event, then stop processing it + if (_controllerScriptingInterface.isWheelCaptured()) { + return; + } // Wheel Events disabled for now because they are also activated by touch look pitch up/down. if (USE_MOUSEWHEEL && (activeWindow() == _window)) { diff --git a/interface/src/ControllerScriptingInterface.cpp b/interface/src/ControllerScriptingInterface.cpp index fd27eb2428..491c38a9de 100644 --- a/interface/src/ControllerScriptingInterface.cpp +++ b/interface/src/ControllerScriptingInterface.cpp @@ -179,5 +179,40 @@ glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex return glm::vec3(0); // bad index } +bool ControllerScriptingInterface::isKeyCaptured(QKeyEvent* event) const { +qDebug() << "ControllerScriptingInterface::isKeyCaptured() event=" << event; + return isKeyCaptured(KeyEvent(*event)); +} +bool ControllerScriptingInterface::isKeyCaptured(const KeyEvent& event) const { + +qDebug() << "ControllerScriptingInterface::isKeyCaptured() event.key=" << event.key; + + // if we've captured some combination of this key it will be in the map + if (_capturedKeys.contains(event.key, event)) { +qDebug() << "ControllerScriptingInterface::isKeyCaptured() event.key=" << event.key << " returning TRUE"; + return true; + } + return false; +} + +void ControllerScriptingInterface::captureKeyEvents(const KeyEvent& event) { + // if it's valid + if (event.isValid) { + // and not already captured + if (!isKeyCaptured(event)) { + // then add this KeyEvent record to the captured combos for this key + _capturedKeys.insert(event.key, event); + } + } +} + +void ControllerScriptingInterface::releaseKeyEvents(const KeyEvent& event) { + if (event.isValid) { + // and not already captured + if (isKeyCaptured(event)) { + _capturedKeys.remove(event.key, event); + } + } +} diff --git a/interface/src/ControllerScriptingInterface.h b/interface/src/ControllerScriptingInterface.h index ca14729151..6b09d34909 100644 --- a/interface/src/ControllerScriptingInterface.h +++ b/interface/src/ControllerScriptingInterface.h @@ -1,3 +1,4 @@ + // // ControllerScriptingInterface.h // hifi @@ -19,23 +20,24 @@ class ControllerScriptingInterface : public AbstractControllerScriptingInterface Q_OBJECT public: - void emitKeyPressEvent(QKeyEvent* x) { - KeyEvent event(x); - emit keyPressEvent(event); - } - - /** - void emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(*event); } + void emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); } + void emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*event)); } - void emitMouseMoveEvent(QMouseEvent* event) { emit mouseMoveEvent(*event); } - void emitMousePressEvent(QMouseEvent* event) { emit mousePressEvent(*event); } - void emitMouseReleaseEvent(QMouseEvent* event) { emit mouseReleaseEvent(*event); } + void emitMouseMoveEvent(QMouseEvent* event) { emit mouseMoveEvent(MouseEvent(*event)); } + void emitMousePressEvent(QMouseEvent* event) { emit mousePressEvent(MouseEvent(*event)); } + void emitMouseReleaseEvent(QMouseEvent* event) { emit mouseReleaseEvent(MouseEvent(*event)); } + + void emitTouchBeginEvent(QTouchEvent* event) { emit touchBeginEvent(*event); } + void emitTouchEndEvent(QTouchEvent* event) { emit touchEndEvent(*event); } + void emitTouchUpdateEvent(QTouchEvent* event) { emit touchUpdateEvent(*event); } + void emitWheelEvent(QWheelEvent* event) { emit wheelEvent(*event); } + + bool isKeyCaptured(QKeyEvent* event) const; + bool isKeyCaptured(const KeyEvent& event) const; + bool isMouseCaptured() const { return _mouseCaptured; } + bool isTouchCaptured() const { return _touchCaptured; } + bool isWheelCaptured() const { return _wheelCaptured; } - void emitTouchBeginEvent(QTouchEvent* event) { emit touchBeginEvent(event); } - void emitTouchEndEvent(QTouchEvent* event) { emit touchEndEvent(event); } - void emitTouchUpdateEvent(QTouchEvent* event) { emit touchUpdateEvent(event); } - void emitWheelEvent(QWheelEvent* event) { emit wheelEvent(event); } - **/ public slots: virtual bool isPrimaryButtonPressed() const; @@ -55,6 +57,18 @@ public slots: virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const; virtual glm::vec3 getSpatialControlNormal(int controlIndex) const; + virtual void captureKeyEvents(const KeyEvent& event); + virtual void releaseKeyEvents(const KeyEvent& event); + + virtual void captureMouseEvents() { _mouseCaptured = true; } + virtual void releaseMouseEvents() { _mouseCaptured = false; } + + virtual void captureTouchEvents() { _touchCaptured = true; } + virtual void releaseTouchEvents() { _touchCaptured = false; } + + virtual void captureWheelEvents() { _wheelCaptured = true; } + virtual void releaseWheelEvents() { _wheelCaptured = false; } + // The following signals are defined by AbstractControllerScriptingInterface // // signals: @@ -66,6 +80,11 @@ private: const PalmData* getPalm(int palmIndex) const; int getNumberOfActivePalms() const; const PalmData* getActivePalm(int palmIndex) const; + + bool _mouseCaptured; + bool _touchCaptured; + bool _wheelCaptured; + QMultiMap _capturedKeys; }; const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip diff --git a/libraries/particles/src/ParticleTree.cpp b/libraries/particles/src/ParticleTree.cpp index 7f8f168e5d..6cb46b3340 100644 --- a/libraries/particles/src/ParticleTree.cpp +++ b/libraries/particles/src/ParticleTree.cpp @@ -498,11 +498,9 @@ bool ParticleTree::encodeParticlesDeletedSince(uint64_t& sinceTime, unsigned cha while (iterator != _recentlyDeletedParticleIDs.constEnd()) { QList values = _recentlyDeletedParticleIDs.values(iterator.key()); for (int valueItem = 0; valueItem < values.size(); ++valueItem) { - //qDebug() << "considering... " << iterator.key() << ": " << values.at(valueItem); // if the timestamp is more recent then out last sent time, include it if (iterator.key() > sinceTime) { - //qDebug() << "including... " << iterator.key() << ": " << values.at(valueItem); uint32_t particleID = values.at(valueItem); memcpy(copyAt, &particleID, sizeof(particleID)); copyAt += sizeof(particleID); @@ -540,16 +538,14 @@ bool ParticleTree::encodeParticlesDeletedSince(uint64_t& sinceTime, unsigned cha // called by the server when it knows all nodes have been sent deleted packets void ParticleTree::forgetParticlesDeletedBefore(uint64_t sinceTime) { - //qDebug() << "forgetParticlesDeletedBefore()"; QSet keysToRemove; _recentlyDeletedParticlesLock.lockForWrite(); QMultiMap::iterator iterator = _recentlyDeletedParticleIDs.begin(); + // First find all the keys in the map that are older and need to be deleted while (iterator != _recentlyDeletedParticleIDs.end()) { - //qDebug() << "considering... time/key:" << iterator.key(); if (iterator.key() <= sinceTime) { - //qDebug() << "YES older... time/key:" << iterator.key(); keysToRemove << iterator.key(); } ++iterator; @@ -557,18 +553,15 @@ void ParticleTree::forgetParticlesDeletedBefore(uint64_t sinceTime) { // Now run through the keysToRemove and remove them foreach (uint64_t value, keysToRemove) { - //qDebug() << "removing the key, _recentlyDeletedParticleIDs.remove(value); time/key:" << value; _recentlyDeletedParticleIDs.remove(value); } _recentlyDeletedParticlesLock.unlock(); - //qDebug() << "DONE forgetParticlesDeletedBefore()"; } void ParticleTree::processEraseMessage(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr, Node* sourceNode) { - //qDebug() << "ParticleTree::processEraseMessage()..."; const unsigned char* packetData = (const unsigned char*)dataByteArray.constData(); const unsigned char* dataAt = packetData; @@ -583,14 +576,11 @@ void ParticleTree::processEraseMessage(const QByteArray& dataByteArray, const Hi dataAt += sizeof(numberOfIds); processedBytes += sizeof(numberOfIds); - //qDebug() << "got erase message for numberOfIds:" << numberOfIds; - if (numberOfIds > 0) { FindAndDeleteParticlesArgs args; for (size_t i = 0; i < numberOfIds; i++) { if (processedBytes + sizeof(uint32_t) > packetLength) { - //qDebug() << "bailing?? processedBytes:" << processedBytes << " packetLength:" << packetLength; break; // bail to prevent buffer overflow } @@ -599,12 +589,10 @@ void ParticleTree::processEraseMessage(const QByteArray& dataByteArray, const Hi dataAt += sizeof(particleID); processedBytes += sizeof(particleID); - //qDebug() << "got erase message for particleID:" << particleID; args._idsToDelete.push_back(particleID); } // calling recurse to actually delete the particles - //qDebug() << "calling recurse to actually delete the particles"; recurseTreeWithOperation(findAndDeleteOperation, &args); } } diff --git a/libraries/script-engine/src/AbstractControllerScriptingInterface.h b/libraries/script-engine/src/AbstractControllerScriptingInterface.h index b3f482c74e..4fad5f6edc 100644 --- a/libraries/script-engine/src/AbstractControllerScriptingInterface.h +++ b/libraries/script-engine/src/AbstractControllerScriptingInterface.h @@ -38,6 +38,19 @@ public slots: virtual glm::vec3 getSpatialControlVelocity(int controlIndex) const = 0; virtual glm::vec3 getSpatialControlNormal(int controlIndex) const = 0; + virtual void captureKeyEvents(const KeyEvent& event) = 0; + virtual void releaseKeyEvents(const KeyEvent& event) = 0; + + virtual void captureMouseEvents() = 0; + virtual void releaseMouseEvents() = 0; + + virtual void captureTouchEvents() = 0; + virtual void releaseTouchEvents() = 0; + + virtual void captureWheelEvents() = 0; + virtual void releaseWheelEvents() = 0; + + signals: void keyPressEvent(const KeyEvent& event); void keyReleaseEvent(const KeyEvent& event); diff --git a/libraries/script-engine/src/EventTypes.cpp b/libraries/script-engine/src/EventTypes.cpp index e11fa72495..5c4ab7f2a7 100644 --- a/libraries/script-engine/src/EventTypes.cpp +++ b/libraries/script-engine/src/EventTypes.cpp @@ -10,47 +10,28 @@ #include "EventTypes.h" -void registerEventTypes(QScriptEngine* engine) { - qScriptRegisterMetaType(engine, keyEventToScriptValue, keyEventFromScriptValue); - qScriptRegisterMetaType(engine, mouseEventToScriptValue, mouseEventFromScriptValue); - qScriptRegisterMetaType(engine, touchEventToScriptValue, touchEventFromScriptValue); - qScriptRegisterMetaType(engine, wheelEventToScriptValue, wheelEventFromScriptValue); + +KeyEvent::KeyEvent() { + key = 0; + isShifted = false; + isMeta = false; + isValid = false; } -QScriptValue keyEventToScriptValue(QScriptEngine* engine, const KeyEvent& event) { - QScriptValue obj = engine->newObject(); - /* - obj.setProperty("key", event.key()); - obj.setProperty("isAutoRepeat", event.isAutoRepeat()); - bool isShifted = event.modifiers().testFlag(Qt::ShiftModifier); - bool isMeta = event.modifiers().testFlag(Qt::ControlModifier); - - obj.setProperty("isShifted", isShifted); - obj.setProperty("isMeta", isMeta); - */ - - return obj; +KeyEvent::KeyEvent(const QKeyEvent& event) { + key = event.key(); + isShifted = event.modifiers().testFlag(Qt::ShiftModifier); + isMeta = event.modifiers().testFlag(Qt::ControlModifier); + isValid = true; } -void keyEventFromScriptValue(const QScriptValue &object, KeyEvent& event) { - // nothing for now... +MouseEvent::MouseEvent(const QMouseEvent& event) { + x = event.x(); + y = event.y(); } -QScriptValue mouseEventToScriptValue(QScriptEngine* engine, const MouseEvent& event) { - QScriptValue obj = engine->newObject(); - obj.setProperty("x", event.x()); - obj.setProperty("y", event.y()); - return obj; -} - -void mouseEventFromScriptValue(const QScriptValue &object, MouseEvent& event) { - // nothing for now... -} - -QScriptValue touchEventToScriptValue(QScriptEngine* engine, const TouchEvent& event) { - QScriptValue obj = engine->newObject(); - +TouchEvent::TouchEvent(const QTouchEvent& event) { // convert the touch points into an average const QList& tPoints = event.touchPoints(); float touchAvgX = 0.0f; @@ -64,9 +45,53 @@ QScriptValue touchEventToScriptValue(QScriptEngine* engine, const TouchEvent& ev touchAvgX /= (float)(numTouches); touchAvgY /= (float)(numTouches); } - - obj.setProperty("averageX", touchAvgX); - obj.setProperty("averageY", touchAvgY); + x = touchAvgX; + y = touchAvgY; +} + +WheelEvent::WheelEvent(const QWheelEvent& event) { + x = event.x(); + y = event.y(); +} + + +void registerEventTypes(QScriptEngine* engine) { + qScriptRegisterMetaType(engine, keyEventToScriptValue, keyEventFromScriptValue); + qScriptRegisterMetaType(engine, mouseEventToScriptValue, mouseEventFromScriptValue); + qScriptRegisterMetaType(engine, touchEventToScriptValue, touchEventFromScriptValue); + qScriptRegisterMetaType(engine, wheelEventToScriptValue, wheelEventFromScriptValue); +} + +QScriptValue keyEventToScriptValue(QScriptEngine* engine, const KeyEvent& event) { + QScriptValue obj = engine->newObject(); + obj.setProperty("key", event.key); + obj.setProperty("isShifted", event.isShifted); + obj.setProperty("isMeta", event.isMeta); + return obj; +} + +void keyEventFromScriptValue(const QScriptValue &object, KeyEvent& event) { + event.key = object.property("key").toVariant().toInt(); + event.isShifted = object.property("isShifted").toVariant().toBool(); + event.isMeta = object.property("isMeta").toVariant().toBool(); + event.isValid = object.property("key").isValid(); +} + +QScriptValue mouseEventToScriptValue(QScriptEngine* engine, const MouseEvent& event) { + QScriptValue obj = engine->newObject(); + obj.setProperty("x", event.x); + obj.setProperty("y", event.y); + return obj; +} + +void mouseEventFromScriptValue(const QScriptValue &object, MouseEvent& event) { + // nothing for now... +} + +QScriptValue touchEventToScriptValue(QScriptEngine* engine, const TouchEvent& event) { + QScriptValue obj = engine->newObject(); + obj.setProperty("x", event.x); + obj.setProperty("y", event.y); return obj; } @@ -76,8 +101,8 @@ void touchEventFromScriptValue(const QScriptValue &object, TouchEvent& event) { QScriptValue wheelEventToScriptValue(QScriptEngine* engine, const WheelEvent& event) { QScriptValue obj = engine->newObject(); - obj.setProperty("x", event.x()); - obj.setProperty("y", event.y()); + obj.setProperty("x", event.x); + obj.setProperty("y", event.y); return obj; } diff --git a/libraries/script-engine/src/EventTypes.h b/libraries/script-engine/src/EventTypes.h index 5ed014f09a..c3764b2619 100644 --- a/libraries/script-engine/src/EventTypes.h +++ b/libraries/script-engine/src/EventTypes.h @@ -18,25 +18,42 @@ #include #include + class KeyEvent { public: - KeyEvent() { }; - KeyEvent(QKeyEvent* other) { }; + KeyEvent(); + KeyEvent(const QKeyEvent& event); + inline bool operator==(const KeyEvent& other) const { + return other.key == key && other.isShifted == isShifted && other.isMeta == isMeta; } + int key; + bool isShifted; + bool isMeta; + bool isValid; }; + class MouseEvent { public: - MouseEvent() { }; + MouseEvent() : x(0), y(0) { }; + MouseEvent(const QMouseEvent& event); + int x; + int y; }; class TouchEvent { public: - TouchEvent() { }; + TouchEvent() : x(0), y(0) { }; + TouchEvent(const QTouchEvent& event); + float x; + float y; }; class WheelEvent { public: - WheelEvent() { }; + WheelEvent() : x(0), y(0) { }; + WheelEvent(const QWheelEvent& event); + int x; + int y; };