diff --git a/examples/multipleCursorsExample.js b/examples/multipleCursorsExample.js new file mode 100644 index 0000000000..3f2430d3db --- /dev/null +++ b/examples/multipleCursorsExample.js @@ -0,0 +1,79 @@ +// +// multipleCursorsExample.js +// examples +// +// Created by Thijs Wenker on 7/23/14. +// Copyright 2014 High Fidelity, Inc. +// +// This is an example script that demonstrates use of multiple cursors +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var wantDebugging = false; + +var cursors = {}; + +function Cursor(event) { + this.deviceID = event.deviceID; + + this.held_buttons = { + LEFT: false, + MIDDLE: false, + RIGHT: false + } + this.updatePosition = function(event) { + this.x = event.x; + this.y = event.y; + }; + this.pressEvent = function(event) { + if (this.held_buttons[event.button] != undefined) { + this.held_buttons[event.button] = true; + } + }; + this.releaseEvent = function(event) { + if (this.held_buttons[event.button] != undefined) { + this.held_buttons[event.button] = false; + } + }; + this.updatePosition(event); +} + +function mousePressEvent(event) { + if (cursors[event.deviceID] == undefined) { + cursors[event.deviceID] = new Cursor(event); + } + cursors[event.deviceID].pressEvent(event); +} + +function mouseReleaseEvent(event) { + if (cursors[event.deviceID] == undefined) { + cursors[event.deviceID] = new Cursor(event); + } + cursors[event.deviceID].releaseEvent(event); +} + +function mouseMoveEvent(event) { + if (cursors[event.deviceID] == undefined) { + cursors[event.deviceID] = new Cursor(event); + } else { + cursors[event.deviceID].updatePosition(event); + } +} + +var lastOutputString = ""; +function checkCursors() { + if(lastOutputString != JSON.stringify(cursors)) { + lastOutputString = JSON.stringify(cursors); + // outputs json string of all cursors only when a change occured + print(lastOutputString); + } +} + +Script.update.connect(checkCursors); + +// Map the mouse events to our functions +Controller.mousePressEvent.connect(mousePressEvent); +Controller.mouseMoveEvent.connect(mouseMoveEvent); +Controller.mouseReleaseEvent.connect(mouseReleaseEvent); \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index aad9c4de58..8e51d1f897 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -155,7 +155,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _mouseX(0), _mouseY(0), _lastMouseMove(usecTimestampNow()), - _lastMouseMoveType(QEvent::MouseMove), + _lastMouseMoveWasSimulated(false), _mouseHidden(false), _seenMouseMove(false), _touchAvgX(0.0f), @@ -1141,18 +1141,19 @@ void Application::focusOutEvent(QFocusEvent* event) { _keysPressed.clear(); } -void Application::mouseMoveEvent(QMouseEvent* event) { +void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { bool showMouse = true; + + // Used by application overlay to determine how to draw cursor(s) + _lastMouseMoveWasSimulated = deviceID > 0; + // If this mouse move event is emitted by a controller, dont show the mouse cursor - if (event->type() == CONTROLLER_MOVE_EVENT) { + if (_lastMouseMoveWasSimulated) { showMouse = false; } - // Used by application overlay to determine how to draw cursor(s) - _lastMouseMoveType = event->type(); - - _controllerScriptingInterface.emitMouseMoveEvent(event); // send events to any registered scripts + _controllerScriptingInterface.emitMouseMoveEvent(event, deviceID); // send events to any registered scripts // if one of our scripts have asked to capture this event, then stop processing it if (_controllerScriptingInterface.isMouseCaptured()) { @@ -1171,7 +1172,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { _mouseY = event->y(); } -void Application::mousePressEvent(QMouseEvent* event) { +void Application::mousePressEvent(QMouseEvent* event, unsigned int 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 @@ -1204,7 +1205,7 @@ void Application::mousePressEvent(QMouseEvent* event) { } } -void Application::mouseReleaseEvent(QMouseEvent* event) { +void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int 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 diff --git a/interface/src/Application.h b/interface/src/Application.h index d956a949ac..0259fe3b08 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -159,9 +159,9 @@ public: void focusOutEvent(QFocusEvent* event); void focusInEvent(QFocusEvent* event); - void mouseMoveEvent(QMouseEvent* event); - void mousePressEvent(QMouseEvent* event); - void mouseReleaseEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event, unsigned int deviceID = 0); + void mousePressEvent(QMouseEvent* event, unsigned int deviceID = 0); + void mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID = 0); void touchBeginEvent(QTouchEvent* event); void touchEndEvent(QTouchEvent* event); @@ -207,7 +207,7 @@ public: const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } int getMouseX() const { return _mouseX; } int getMouseY() const { return _mouseY; } - unsigned int getLastMouseMoveType() const { return _lastMouseMoveType; } + bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated;; } Faceplus* getFaceplus() { return &_faceplus; } Faceshift* getFaceshift() { return &_faceshift; } Visage* getVisage() { return &_visage; } @@ -507,7 +507,7 @@ private: int _mouseDragStartedX; int _mouseDragStartedY; quint64 _lastMouseMove; - unsigned int _lastMouseMoveType; + bool _lastMouseMoveWasSimulated; bool _mouseHidden; bool _seenMouseMove; diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index a79e2cee74..089d478198 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -373,6 +373,8 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { Qt::MouseButton bumperButton; Qt::MouseButton triggerButton; + unsigned int deviceID = index == 0 ? CONTROLLER_0_EVENT : CONTROLLER_1_EVENT; + if (Menu::getInstance()->getInvertSixenseButtons()) { bumperButton = Qt::LeftButton; triggerButton = Qt::RightButton; @@ -405,14 +407,14 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { if (_bumperPressed[index]) { QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, bumperButton, bumperButton, 0); - application->mouseReleaseEvent(&mouseEvent); + application->mouseReleaseEvent(&mouseEvent, deviceID); _bumperPressed[index] = false; } if (_triggerPressed[index]) { QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, triggerButton, triggerButton, 0); - application->mouseReleaseEvent(&mouseEvent); + application->mouseReleaseEvent(&mouseEvent, deviceID); _triggerPressed[index] = false; } @@ -421,17 +423,17 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { //If position has changed, emit a mouse move to the application if (pos.x() != _oldX[index] || pos.y() != _oldY[index]) { - QMouseEvent mouseEvent(static_cast(CONTROLLER_MOVE_EVENT), pos, Qt::NoButton, Qt::NoButton, 0); + QMouseEvent mouseEvent(QEvent::MouseMove, pos, Qt::NoButton, Qt::NoButton, 0); //Only send the mouse event if the opposite left button isnt held down. //This is specifically for edit voxels if (triggerButton == Qt::LeftButton) { if (!_triggerPressed[(int)(!index)]) { - application->mouseMoveEvent(&mouseEvent); + application->mouseMoveEvent(&mouseEvent, deviceID); } } else { if (!_bumperPressed[(int)(!index)]) { - application->mouseMoveEvent(&mouseEvent); + application->mouseMoveEvent(&mouseEvent, deviceID); } } } @@ -456,12 +458,12 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { QMouseEvent mouseEvent(QEvent::MouseButtonPress, pos, bumperButton, bumperButton, 0); - application->mousePressEvent(&mouseEvent); + application->mousePressEvent(&mouseEvent, deviceID); } } else if (_bumperPressed[index]) { QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, bumperButton, bumperButton, 0); - application->mouseReleaseEvent(&mouseEvent); + application->mouseReleaseEvent(&mouseEvent, deviceID); _bumperPressed[index] = false; } @@ -473,12 +475,12 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { QMouseEvent mouseEvent(QEvent::MouseButtonPress, pos, triggerButton, triggerButton, 0); - application->mousePressEvent(&mouseEvent); + application->mousePressEvent(&mouseEvent, deviceID); } } else if (_triggerPressed[index]) { QMouseEvent mouseEvent(QEvent::MouseButtonRelease, pos, triggerButton, triggerButton, 0); - application->mouseReleaseEvent(&mouseEvent); + application->mouseReleaseEvent(&mouseEvent, deviceID); _triggerPressed[index] = false; } diff --git a/interface/src/devices/SixenseManager.h b/interface/src/devices/SixenseManager.h index bae9e1c6d6..91f9e9884f 100644 --- a/interface/src/devices/SixenseManager.h +++ b/interface/src/devices/SixenseManager.h @@ -27,8 +27,9 @@ const unsigned int BUTTON_3 = 1U << 3; const unsigned int BUTTON_4 = 1U << 4; const unsigned int BUTTON_FWD = 1U << 7; -// Event type that represents moving the controller -const unsigned int CONTROLLER_MOVE_EVENT = 1500U; +// Event type that represents using the controller +const unsigned int CONTROLLER_0_EVENT = 1500U; +const unsigned int CONTROLLER_1_EVENT = 1501U; const float DEFAULT_SIXENSE_RETICLE_MOVE_SPEED = 37.5f; const bool DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS = false; diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index cf5414554e..d980639685 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -57,9 +57,9 @@ public: void emitKeyPressEvent(QKeyEvent* event) { emit keyPressEvent(KeyEvent(*event)); } void emitKeyReleaseEvent(QKeyEvent* event) { emit keyReleaseEvent(KeyEvent(*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 emitMouseMoveEvent(QMouseEvent* event, unsigned int deviceID = 0) { emit mouseMoveEvent(MouseEvent(*event, deviceID)); } + void emitMousePressEvent(QMouseEvent* event, unsigned int deviceID = 0) { emit mousePressEvent(MouseEvent(*event, deviceID)); } + void emitMouseReleaseEvent(QMouseEvent* event, unsigned int deviceID = 0) { emit mouseReleaseEvent(MouseEvent(*event, deviceID)); } void emitTouchBeginEvent(const TouchEvent& event) { emit touchBeginEvent(event); } void emitTouchEndEvent(const TouchEvent& event) { emit touchEndEvent(event); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 89ae2fbb46..3badde4042 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -535,7 +535,7 @@ void ApplicationOverlay::renderPointers() { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, _crosshairTexture); - if (OculusManager::isConnected() && application->getLastMouseMoveType() == QEvent::MouseMove) { + if (OculusManager::isConnected() && !application->getLastMouseMoveWasSimulated()) { //If we are in oculus, render reticle later _reticleActive[MOUSE] = true; _magActive[MOUSE] = true; @@ -546,7 +546,7 @@ void ApplicationOverlay::renderPointers() { _reticleActive[LEFT_CONTROLLER] = false; _reticleActive[RIGHT_CONTROLLER] = false; - } else if (application->getLastMouseMoveType() == CONTROLLER_MOVE_EVENT && Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) { + } else if (application->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) { //only render controller pointer if we aren't already rendering a mouse pointer _reticleActive[MOUSE] = false; _magActive[MOUSE] = false; diff --git a/libraries/script-engine/src/EventTypes.cpp b/libraries/script-engine/src/EventTypes.cpp index 3bd6303d02..9cf6c5b1a0 100644 --- a/libraries/script-engine/src/EventTypes.cpp +++ b/libraries/script-engine/src/EventTypes.cpp @@ -298,9 +298,10 @@ MouseEvent::MouseEvent() : }; -MouseEvent::MouseEvent(const QMouseEvent& event) : +MouseEvent::MouseEvent(const QMouseEvent& event, const unsigned int deviceID) : x(event.x()), y(event.y()), + deviceID(deviceID), isLeftButton(event.buttons().testFlag(Qt::LeftButton)), isRightButton(event.buttons().testFlag(Qt::RightButton)), isMiddleButton(event.buttons().testFlag(Qt::MiddleButton)), @@ -334,6 +335,7 @@ QScriptValue mouseEventToScriptValue(QScriptEngine* engine, const MouseEvent& ev obj.setProperty("x", event.x); obj.setProperty("y", event.y); obj.setProperty("button", event.button); + obj.setProperty("deviceID", event.deviceID); obj.setProperty("isLeftButton", event.isLeftButton); obj.setProperty("isRightButton", event.isRightButton); obj.setProperty("isMiddleButton", event.isMiddleButton); diff --git a/libraries/script-engine/src/EventTypes.h b/libraries/script-engine/src/EventTypes.h index ed7aabc3c9..7d4076dbf0 100644 --- a/libraries/script-engine/src/EventTypes.h +++ b/libraries/script-engine/src/EventTypes.h @@ -44,9 +44,10 @@ public: class MouseEvent { public: MouseEvent(); - MouseEvent(const QMouseEvent& event); + MouseEvent(const QMouseEvent& event, const unsigned int deviceID = 0); int x; int y; + unsigned int deviceID; QString button; bool isLeftButton; bool isRightButton;