diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 37e213855b..c6d8fe7c9b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1414,10 +1414,9 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { if (activeWindow() == _window) { - _keyboardMouseDevice.mousePressEvent(event); - if (event->button() == Qt::LeftButton) { + if (event->button() == Qt::LeftButton) { _mouseDragStartedX = getTrueMouseX(); _mouseDragStartedY = getTrueMouseY(); _mousePressed = true; @@ -1458,9 +1457,8 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { return; } - _keyboardMouseDevice.mouseReleaseEvent(event); - if (activeWindow() == _window) { + _keyboardMouseDevice.mouseReleaseEvent(event); if (event->button() == Qt::LeftButton) { _mousePressed = false; diff --git a/interface/src/Application.h b/interface/src/Application.h index 60a5fbf929..7ae96de193 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -70,6 +70,7 @@ #include "ui/RunningScriptsWidget.h" #include "ui/ToolWindow.h" #include "ui/UserInputMapper.h" +#include "devices/KeyboardMouseDevice.h" #include "octree/OctreeFade.h" #include "octree/OctreePacketProcessor.h" #include "UndoStackScriptingInterface.h" diff --git a/interface/src/ui/UserInputMapper.cpp b/interface/src/ui/UserInputMapper.cpp index 601071a5d9..c1f9577efe 100755 --- a/interface/src/ui/UserInputMapper.cpp +++ b/interface/src/ui/UserInputMapper.cpp @@ -11,236 +11,6 @@ #include "UserInputMapper.h" #include -void KeyboardMouseDevice::update() { - _axisStateMap.clear(); - - // For touch event, we need to check that the last event is not too long ago - // Maybe it's a Qt issue, but the touch event sequence (begin, update, end) is not always called properly - // The following is a workaround to detect that the touch sequence is over in case we didn;t see the end event - if (_isTouching) { - const auto TOUCH_EVENT_MAXIMUM_WAIT = 100; //ms - auto currentTime = _clock.now(); - auto sinceLastTouch = std::chrono::duration_cast(currentTime - _lastTouchTime); - if (sinceLastTouch.count() > TOUCH_EVENT_MAXIMUM_WAIT) { - _isTouching = false; - } - } -} - -void KeyboardMouseDevice::focusOutEvent(QFocusEvent* event) { - _buttonPressedMap.clear(); -}; - -void KeyboardMouseDevice::keyPressEvent(QKeyEvent* event) { - auto input = makeInput((Qt::Key) event->key()); - auto result = _buttonPressedMap.insert(input.getChannel()); - if (!result.second) { - // key pressed again ? without catching the release event ? - } -} -void KeyboardMouseDevice::keyReleaseEvent(QKeyEvent* event) { - auto input = makeInput((Qt::Key) event->key()); - _buttonPressedMap.erase(input.getChannel()); -} - -void KeyboardMouseDevice::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { - auto input = makeInput((Qt::MouseButton) event->button()); - auto result = _buttonPressedMap.insert(input.getChannel()); - if (!result.second) { - // key pressed again ? without catching the release event ? - } - _lastCursor = event->pos(); -} -void KeyboardMouseDevice::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { - auto input = makeInput((Qt::MouseButton) event->button()); - _buttonPressedMap.erase(input.getChannel()); -} -void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { - QPoint currentPos = event->pos(); - QPoint currentMove = currentPos - _lastCursor; - - _axisStateMap[makeInput(MOUSE_AXIS_X_POS).getChannel()] = (currentMove.x() > 0 ? currentMove.x() : 0.0f); - _axisStateMap[makeInput(MOUSE_AXIS_X_NEG).getChannel()] = (currentMove.x() < 0 ? -currentMove.x() : 0.0f); - // Y mouse is inverted positive is pointing up the screen - _axisStateMap[makeInput(MOUSE_AXIS_Y_POS).getChannel()] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f); - _axisStateMap[makeInput(MOUSE_AXIS_Y_NEG).getChannel()] = (currentMove.y() > 0 ? currentMove.y() : 0.0f); - - _lastCursor = currentPos; -} -void KeyboardMouseDevice::wheelEvent(QWheelEvent* event) { - auto currentMove = event->angleDelta() / 120.0f; - - _axisStateMap[makeInput(MOUSE_AXIS_WHEEL_X_POS).getChannel()] = (currentMove.x() > 0 ? currentMove.x() : 0.0f); - _axisStateMap[makeInput(MOUSE_AXIS_WHEEL_X_NEG).getChannel()] = (currentMove.x() < 0 ? -currentMove.x() : 0.0f); - _axisStateMap[makeInput(MOUSE_AXIS_WHEEL_Y_POS).getChannel()] = (currentMove.y() > 0 ? currentMove.y() : 0.0f); - _axisStateMap[makeInput(MOUSE_AXIS_WHEEL_Y_NEG).getChannel()] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f); -} - -glm::vec2 KeyboardMouseDevice::evalAverageTouchPoints(const QList& points) const { - glm::vec2 averagePoint(0.0f); - if (points.count() > 0) { - for (auto& point : points) { - averagePoint += glm::vec2(point.pos().x(), point.pos().y()); - } - averagePoint /= (float)(points.count()); - } - return averagePoint; -} - - -void KeyboardMouseDevice::touchBeginEvent(const QTouchEvent* event) { - _isTouching = event->touchPointStates().testFlag(Qt::TouchPointPressed); - _lastTouch = evalAverageTouchPoints(event->touchPoints()); - _lastTouchTime = _clock.now(); -} -void KeyboardMouseDevice::touchEndEvent(const QTouchEvent* event) { - _isTouching = false; - _lastTouch = evalAverageTouchPoints(event->touchPoints()); - _lastTouchTime = _clock.now(); -} -void KeyboardMouseDevice::touchUpdateEvent(const QTouchEvent* event) { - auto currentPos = evalAverageTouchPoints(event->touchPoints()); - _lastTouchTime = _clock.now(); - - if (!_isTouching) { - _isTouching = event->touchPointStates().testFlag(Qt::TouchPointPressed); - } else { - auto currentMove = currentPos - _lastTouch; - - _axisStateMap[makeInput(TOUCH_AXIS_X_POS).getChannel()] = (currentMove.x > 0 ? currentMove.x : 0.0f); - _axisStateMap[makeInput(TOUCH_AXIS_X_NEG).getChannel()] = (currentMove.x < 0 ? -currentMove.x : 0.0f); - // Y mouse is inverted positive is pointing up the screen - _axisStateMap[makeInput(TOUCH_AXIS_Y_POS).getChannel()] = (currentMove.y < 0 ? -currentMove.y : 0.0f); - _axisStateMap[makeInput(TOUCH_AXIS_Y_NEG).getChannel()] = (currentMove.y > 0 ? currentMove.y : 0.0f); - } - - _lastTouch = currentPos; -} - -UserInputMapper::Input KeyboardMouseDevice::makeInput(Qt::Key code) { - return UserInputMapper::Input(_deviceID, code & KEYBOARD_MASK, UserInputMapper::ChannelType::BUTTON); -} -UserInputMapper::Input KeyboardMouseDevice::makeInput(Qt::MouseButton code) { - switch (code) { - case Qt::LeftButton: - return UserInputMapper::Input(_deviceID, MOUSE_BUTTON_LEFT, UserInputMapper::ChannelType::BUTTON); - case Qt::RightButton: - return UserInputMapper::Input(_deviceID, MOUSE_BUTTON_RIGHT, UserInputMapper::ChannelType::BUTTON); - case Qt::MiddleButton: - return UserInputMapper::Input(_deviceID, MOUSE_BUTTON_MIDDLE, UserInputMapper::ChannelType::BUTTON); - default: - return UserInputMapper::Input(); - }; -} -UserInputMapper::Input KeyboardMouseDevice::makeInput(KeyboardMouseDevice::MouseAxisChannel axis) { - return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS); -} -UserInputMapper::Input KeyboardMouseDevice::makeInput(KeyboardMouseDevice::TouchAxisChannel axis) { - return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS); -} -UserInputMapper::Input KeyboardMouseDevice::makeInput(KeyboardMouseDevice::TouchButtonChannel button) { - return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON); -} - -void KeyboardMouseDevice::registerToUserInputMapper(UserInputMapper& mapper) { - // Grab the current free device ID - _deviceID = mapper.getFreeDeviceID(); - - auto proxy = UserInputMapper::DeviceProxy::Pointer(new UserInputMapper::DeviceProxy()); - proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input._channel); }; - proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input._channel); }; - mapper.registerDevice(_deviceID, proxy); -} - -void KeyboardMouseDevice::assignDefaultInputMapping(UserInputMapper& mapper) { - const float BUTTON_MOVE_SPEED = 1.0f; - const float BUTTON_YAW_SPEED = 0.75f; - const float BUTTON_PITCH_SPEED = 0.5f; - const float MOUSE_YAW_SPEED = 0.5f; - const float MOUSE_PITCH_SPEED = 0.25f; - const float TOUCH_YAW_SPEED = 0.5f; - const float TOUCH_PITCH_SPEED = 0.25f; - //const float BUTTON_BOOM_SPEED = 0.1f; - - // AWSD keys mapping - mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(Qt::Key_S), BUTTON_MOVE_SPEED); - mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(Qt::Key_W), BUTTON_MOVE_SPEED); - mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(Qt::Key_A), BUTTON_MOVE_SPEED); - mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(Qt::Key_D), BUTTON_MOVE_SPEED); - mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(Qt::Key_C), BUTTON_MOVE_SPEED); - mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(Qt::Key_E), BUTTON_MOVE_SPEED); - - // mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(Qt::Key_W), makeInput(Qt::Key_Shift), BUTTON_BOOM_SPEED); - // mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(Qt::Key_S), makeInput(Qt::Key_Shift), BUTTON_BOOM_SPEED); - mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(Qt::Key_A), makeInput(Qt::Key_Shift), BUTTON_YAW_SPEED); - mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(Qt::Key_D), makeInput(Qt::Key_Shift), BUTTON_YAW_SPEED); - mapper.addInputChannel(UserInputMapper::PITCH_DOWN, makeInput(Qt::Key_C), makeInput(Qt::Key_Shift), BUTTON_PITCH_SPEED); - mapper.addInputChannel(UserInputMapper::PITCH_UP, makeInput(Qt::Key_E), makeInput(Qt::Key_Shift), BUTTON_PITCH_SPEED); - - // Arrow keys mapping - mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(Qt::Key_Down), BUTTON_MOVE_SPEED); - mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(Qt::Key_Up), BUTTON_MOVE_SPEED); - mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(Qt::Key_Left), BUTTON_MOVE_SPEED); - mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(Qt::Key_Right), BUTTON_MOVE_SPEED); - mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(Qt::Key_PageDown), BUTTON_MOVE_SPEED); - mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(Qt::Key_PageUp), BUTTON_MOVE_SPEED); - - // mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(Qt::Key_Up), makeInput(Qt::Key_Shift), BUTTON_BOOM_SPEED); - // mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(Qt::Key_Down), makeInput(Qt::Key_Shift), BUTTON_BOOM_SPEED); - mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(Qt::Key_Left), makeInput(Qt::Key_Shift), BUTTON_YAW_SPEED); - mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(Qt::Key_Right), makeInput(Qt::Key_Shift), BUTTON_YAW_SPEED); - mapper.addInputChannel(UserInputMapper::PITCH_DOWN, makeInput(Qt::Key_Down), makeInput(Qt::Key_Shift), BUTTON_PITCH_SPEED); - mapper.addInputChannel(UserInputMapper::PITCH_UP, makeInput(Qt::Key_Up), makeInput(Qt::Key_Shift), BUTTON_PITCH_SPEED); - - // Mouse move - mapper.addInputChannel(UserInputMapper::PITCH_DOWN, makeInput(MOUSE_AXIS_Y_NEG), makeInput(Qt::RightButton), MOUSE_PITCH_SPEED); - mapper.addInputChannel(UserInputMapper::PITCH_UP, makeInput(MOUSE_AXIS_Y_POS), makeInput(Qt::RightButton), MOUSE_PITCH_SPEED); - mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(MOUSE_AXIS_X_NEG), makeInput(Qt::RightButton), MOUSE_YAW_SPEED); - mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(MOUSE_AXIS_X_POS), makeInput(Qt::RightButton), MOUSE_YAW_SPEED); - - -#ifdef Q_OS_MAC - // wheel event modifier on Mac collide with the touchpad scroll event - mapper.addInputChannel(UserInputMapper::PITCH_DOWN, makeInput(TOUCH_AXIS_Y_NEG), TOUCH_PITCH_SPEED); - mapper.addInputChannel(UserInputMapper::PITCH_UP, makeInput(TOUCH_AXIS_Y_POS), TOUCH_PITCH_SPEED); - mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(TOUCH_AXIS_X_NEG), TOUCH_YAW_SPEED); - mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(TOUCH_AXIS_X_POS), TOUCH_YAW_SPEED); -#else - // Touch pad yaw pitch - mapper.addInputChannel(UserInputMapper::PITCH_DOWN, makeInput(TOUCH_AXIS_Y_NEG), TOUCH_PITCH_SPEED); - mapper.addInputChannel(UserInputMapper::PITCH_UP, makeInput(TOUCH_AXIS_Y_POS), TOUCH_PITCH_SPEED); - mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(TOUCH_AXIS_X_NEG), TOUCH_YAW_SPEED); - mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(TOUCH_AXIS_X_POS), TOUCH_YAW_SPEED); - - // Wheel move - //mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(MOUSE_AXIS_WHEEL_Y_NEG), BUTTON_BOOM_SPEED); - //mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(MOUSE_AXIS_WHEEL_Y_POS), BUTTON_BOOM_SPEED); - mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(MOUSE_AXIS_WHEEL_X_NEG), BUTTON_YAW_SPEED); - mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(MOUSE_AXIS_WHEEL_X_POS), BUTTON_YAW_SPEED); - -#endif - -} - -float KeyboardMouseDevice::getButton(int channel) const { - if (!_buttonPressedMap.empty()) { - if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) { - return 1.0f; - } else { - return 0.0f; - } - } - return 0.0f; -} -float KeyboardMouseDevice::getAxis(int channel) const { - auto axis = _axisStateMap.find(channel); - if (axis != _axisStateMap.end()) { - return (*axis).second; - } else { - return 0.0f; - } -} - // UserInputMapper Class bool UserInputMapper::registerDevice(uint16 deviceID, const DeviceProxy::Pointer& proxy){ diff --git a/interface/src/ui/UserInputMapper.h b/interface/src/ui/UserInputMapper.h index 6546645640..32a1782419 100755 --- a/interface/src/ui/UserInputMapper.h +++ b/interface/src/ui/UserInputMapper.h @@ -12,14 +12,12 @@ #ifndef hifi_UserInputMapper_h #define hifi_UserInputMapper_h -#include #include #include #include #include #include -#include class UserInputMapper : public QObject { Q_OBJECT @@ -177,94 +175,4 @@ protected: std::vector _actionScales = std::vector(NUM_ACTIONS, 1.0f); }; - -class KeyboardMouseDevice { -public: - - enum KeyboardChannel { - KEYBOARD_FIRST = 0, - KEYBOARD_LAST = 255, - KEYBOARD_MASK = 0x00FF, - }; - - enum MouseButtonChannel { - MOUSE_BUTTON_LEFT = KEYBOARD_LAST + 1, - MOUSE_BUTTON_RIGHT, - MOUSE_BUTTON_MIDDLE, - }; - - enum MouseAxisChannel { - MOUSE_AXIS_X_POS = MOUSE_BUTTON_MIDDLE + 1, - MOUSE_AXIS_X_NEG, - MOUSE_AXIS_Y_POS, - MOUSE_AXIS_Y_NEG, - MOUSE_AXIS_WHEEL_Y_POS, - MOUSE_AXIS_WHEEL_Y_NEG, - MOUSE_AXIS_WHEEL_X_POS, - MOUSE_AXIS_WHEEL_X_NEG, - }; - - enum TouchAxisChannel { - TOUCH_AXIS_X_POS = MOUSE_AXIS_WHEEL_X_NEG + 1, - TOUCH_AXIS_X_NEG, - TOUCH_AXIS_Y_POS, - TOUCH_AXIS_Y_NEG, - }; - - enum TouchButtonChannel { - TOUCH_BUTTON_PRESS = TOUCH_AXIS_Y_NEG + 1, - }; - - typedef std::unordered_set ButtonPressedMap; - typedef std::map AxisStateMap; // 8 axes - - void focusOutEvent(QFocusEvent* event); - - void keyPressEvent(QKeyEvent* event); - void keyReleaseEvent(QKeyEvent* 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(const QTouchEvent* event); - void touchEndEvent(const QTouchEvent* event); - void touchUpdateEvent(const QTouchEvent* event); - - void wheelEvent(QWheelEvent* event); - - // Get current state for each channels - float getButton(int channel) const; - float getAxis(int channel) const; - - // Let's make it easy for Qt because we assume we love Qt forever - UserInputMapper::Input makeInput(Qt::Key code); - UserInputMapper::Input makeInput(Qt::MouseButton code); - UserInputMapper::Input makeInput(KeyboardMouseDevice::MouseAxisChannel axis); - UserInputMapper::Input makeInput(KeyboardMouseDevice::TouchAxisChannel axis); - UserInputMapper::Input makeInput(KeyboardMouseDevice::TouchButtonChannel button); - - KeyboardMouseDevice() {} - - void registerToUserInputMapper(UserInputMapper& mapper); - void assignDefaultInputMapping(UserInputMapper& mapper); - - // Update call MUST be called once per simulation loop - // It takes care of updating the action states and deltas - void update(); - -protected: - ButtonPressedMap _buttonPressedMap; - AxisStateMap _axisStateMap; - - int _deviceID = 0; - QPoint _lastCursor; - glm::vec2 _lastTouch; - bool _isTouching = false; - - glm::vec2 evalAverageTouchPoints(const QList& points) const; - std::chrono::high_resolution_clock _clock; - std::chrono::high_resolution_clock::time_point _lastTouchTime; -}; - #endif // hifi_UserInputMapper_h