From 40e6f1cad5237dcde77df83906fbd3c69722e4e5 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 19 Dec 2018 17:14:30 +1300 Subject: [PATCH 01/11] Fix Controller mouse move missing values during rapid movement --- .../src/input-plugins/KeyboardMouseDevice.cpp | 15 ++++++++------- .../src/input-plugins/KeyboardMouseDevice.h | 1 + 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index ddd51e9b9b..2ff0e0ca16 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -29,6 +29,14 @@ void KeyboardMouseDevice::pluginUpdate(float deltaTime, const controller::InputC _inputDevice->_axisStateMap[MOUSE_AXIS_X] = _lastCursor.x(); _inputDevice->_axisStateMap[MOUSE_AXIS_Y] = _lastCursor.y(); + + QPoint currentMove = _lastCursor - _previousCursor; + _inputDevice->_axisStateMap[MOUSE_AXIS_X_POS] = (currentMove.x() > 0 ? currentMove.x() : 0.0f); + _inputDevice->_axisStateMap[MOUSE_AXIS_X_NEG] = (currentMove.x() < 0 ? -currentMove.x() : 0.0f); + // Y mouse is inverted positive is pointing up the screen + _inputDevice->_axisStateMap[MOUSE_AXIS_Y_POS] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f); + _inputDevice->_axisStateMap[MOUSE_AXIS_Y_NEG] = (currentMove.y() > 0 ? currentMove.y() : 0.0f); + _previousCursor = _lastCursor; }); // For touch event, we need to check that the last event is not too long ago @@ -102,13 +110,6 @@ void KeyboardMouseDevice::eraseMouseClicked() { void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event) { QPoint currentPos = event->pos(); - QPoint currentMove = currentPos - _lastCursor; - - _inputDevice->_axisStateMap[MOUSE_AXIS_X_POS] = (currentMove.x() > 0 ? currentMove.x() : 0.0f); - _inputDevice->_axisStateMap[MOUSE_AXIS_X_NEG] = (currentMove.x() < 0 ? -currentMove.x() : 0.0f); - // Y mouse is inverted positive is pointing up the screen - _inputDevice->_axisStateMap[MOUSE_AXIS_Y_POS] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f); - _inputDevice->_axisStateMap[MOUSE_AXIS_Y_NEG] = (currentMove.y() > 0 ? currentMove.y() : 0.0f); // FIXME - this has the characteristic that it will show large jumps when you move the cursor // outside of the application window, because we don't get MouseEvents when the cursor is outside diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index b94acb8b71..0b0ae5a5bb 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -118,6 +118,7 @@ public: protected: QPoint _lastCursor; + QPoint _previousCursor; QPoint _mousePressPos; quint64 _mousePressTime; bool _mouseMoved; From 4aa26715c0f85d34fc793e66bf77e31cc5cabe85 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 19 Dec 2018 17:21:48 +1300 Subject: [PATCH 02/11] Remove unused variable --- .../input-plugins/src/input-plugins/KeyboardMouseDevice.cpp | 3 --- .../input-plugins/src/input-plugins/KeyboardMouseDevice.h | 1 - 2 files changed, 4 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index 2ff0e0ca16..c14db86ae9 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -81,7 +81,6 @@ void KeyboardMouseDevice::mousePressEvent(QMouseEvent* event) { } _lastCursor = event->pos(); _mousePressTime = usecTimestampNow(); - _mouseMoved = false; _mousePressPos = event->pos(); _clickDeadspotActive = true; @@ -116,8 +115,6 @@ void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event) { // of the application window. _lastCursor = currentPos; - _mouseMoved = true; - const int CLICK_EVENT_DEADSPOT = 6; // pixels if (_clickDeadspotActive && (_mousePressPos - currentPos).manhattanLength() > CLICK_EVENT_DEADSPOT) { _clickDeadspotActive = false; diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index 0b0ae5a5bb..45ca496c11 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -121,7 +121,6 @@ protected: QPoint _previousCursor; QPoint _mousePressPos; quint64 _mousePressTime; - bool _mouseMoved; bool _clickDeadspotActive; glm::vec2 _lastTouch; std::shared_ptr _inputDevice { std::make_shared() }; From 84c6bb47976da7a2725582c68064d0ec9765783a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 20 Dec 2018 14:34:12 +1300 Subject: [PATCH 03/11] Introduce optional timestamp into internal Controller axis values This can be used to determine if consecutive identifical values should be output. --- .../controllers/src/controllers/AxisValue.cpp | 18 +++++++++++ .../controllers/src/controllers/AxisValue.h | 31 +++++++++++++++++++ .../src/controllers/InputDevice.cpp | 6 ++-- .../controllers/src/controllers/InputDevice.h | 5 +-- .../src/input-plugins/KeyboardMouseDevice.cpp | 30 +++++++++--------- .../src/input-plugins/TouchscreenDevice.cpp | 13 ++++---- .../TouchscreenVirtualPadDevice.cpp | 18 ++++++----- plugins/hifiSdl2/src/Joystick.cpp | 6 ++-- .../oculus/src/OculusControllerManager.cpp | 16 +++++----- plugins/openvr/src/ViveControllerManager.cpp | 14 ++++----- 10 files changed, 106 insertions(+), 51 deletions(-) create mode 100644 libraries/controllers/src/controllers/AxisValue.cpp create mode 100644 libraries/controllers/src/controllers/AxisValue.h diff --git a/libraries/controllers/src/controllers/AxisValue.cpp b/libraries/controllers/src/controllers/AxisValue.cpp new file mode 100644 index 0000000000..49201dbf7a --- /dev/null +++ b/libraries/controllers/src/controllers/AxisValue.cpp @@ -0,0 +1,18 @@ +// +// AxisValue.cpp +// +// Created by David Rowe on 14 Dec 2018. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "AxisValue.h" + +namespace controller { + + AxisValue::AxisValue(const float value, const quint64 timestamp) : + value(value), timestamp(timestamp) { } + +} diff --git a/libraries/controllers/src/controllers/AxisValue.h b/libraries/controllers/src/controllers/AxisValue.h new file mode 100644 index 0000000000..67fd5736b8 --- /dev/null +++ b/libraries/controllers/src/controllers/AxisValue.h @@ -0,0 +1,31 @@ +// +// AxisValue.h +// +// Created by David Rowe on 13 Dec 2018. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once +#ifndef hifi_controllers_AxisValue_h +#define hifi_controllers_AxisValue_h + +#include + +namespace controller { + + struct AxisValue { + public: + float value { 0.0f }; + // The value can be timestamped to determine if consecutive identical values should be output (e.g., mouse movement). + quint64 timestamp { 0 }; + + AxisValue() {} + AxisValue(const float value, const quint64 timestamp); + }; + +} + +#endif // hifi_controllers_AxisValue_h diff --git a/libraries/controllers/src/controllers/InputDevice.cpp b/libraries/controllers/src/controllers/InputDevice.cpp index a907842a17..e46bb3c8b5 100644 --- a/libraries/controllers/src/controllers/InputDevice.cpp +++ b/libraries/controllers/src/controllers/InputDevice.cpp @@ -26,12 +26,12 @@ namespace controller { return 0.0f; } - float InputDevice::getAxis(int channel) const { + AxisValue InputDevice::getAxis(int channel) const { auto axis = _axisStateMap.find(channel); if (axis != _axisStateMap.end()) { return (*axis).second; } else { - return 0.0f; + return AxisValue(); } } @@ -71,7 +71,7 @@ namespace controller { float InputDevice::getValue(ChannelType channelType, uint16_t channel) const { switch (channelType) { case ChannelType::AXIS: - return getAxis(channel); + return getAxis(channel).value; case ChannelType::BUTTON: return getButton(channel); diff --git a/libraries/controllers/src/controllers/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h index 7479ef7b75..1d4ab1c5d8 100644 --- a/libraries/controllers/src/controllers/InputDevice.h +++ b/libraries/controllers/src/controllers/InputDevice.h @@ -16,6 +16,7 @@ #include +#include "AxisValue.h" #include "Pose.h" #include "Input.h" #include "StandardControls.h" @@ -103,12 +104,12 @@ public: using Pointer = std::shared_ptr; typedef std::unordered_set ButtonPressedMap; - typedef std::map AxisStateMap; + typedef std::map AxisStateMap; typedef std::map PoseStateMap; // Get current state for each channel float getButton(int channel) const; - float getAxis(int channel) const; + AxisValue getAxis(int channel) const; Pose getPose(int channel) const; float getValue(const Input& input) const; diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index c14db86ae9..ebc5a5cd3e 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -27,15 +27,15 @@ void KeyboardMouseDevice::pluginUpdate(float deltaTime, const controller::InputC _inputDevice->update(deltaTime, inputCalibrationData); eraseMouseClicked(); - _inputDevice->_axisStateMap[MOUSE_AXIS_X] = _lastCursor.x(); - _inputDevice->_axisStateMap[MOUSE_AXIS_Y] = _lastCursor.y(); + _inputDevice->_axisStateMap[MOUSE_AXIS_X].value = _lastCursor.x(); + _inputDevice->_axisStateMap[MOUSE_AXIS_Y].value = _lastCursor.y(); QPoint currentMove = _lastCursor - _previousCursor; - _inputDevice->_axisStateMap[MOUSE_AXIS_X_POS] = (currentMove.x() > 0 ? currentMove.x() : 0.0f); - _inputDevice->_axisStateMap[MOUSE_AXIS_X_NEG] = (currentMove.x() < 0 ? -currentMove.x() : 0.0f); + _inputDevice->_axisStateMap[MOUSE_AXIS_X_POS].value = (currentMove.x() > 0 ? currentMove.x() : 0.0f); + _inputDevice->_axisStateMap[MOUSE_AXIS_X_NEG].value = (currentMove.x() < 0 ? -currentMove.x() : 0.0f); // Y mouse is inverted positive is pointing up the screen - _inputDevice->_axisStateMap[MOUSE_AXIS_Y_POS] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f); - _inputDevice->_axisStateMap[MOUSE_AXIS_Y_NEG] = (currentMove.y() > 0 ? currentMove.y() : 0.0f); + _inputDevice->_axisStateMap[MOUSE_AXIS_Y_POS].value = (currentMove.y() < 0 ? -currentMove.y() : 0.0f); + _inputDevice->_axisStateMap[MOUSE_AXIS_Y_NEG].value = (currentMove.y() > 0 ? currentMove.y() : 0.0f); _previousCursor = _lastCursor; }); @@ -124,10 +124,11 @@ void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event) { void KeyboardMouseDevice::wheelEvent(QWheelEvent* event) { auto currentMove = event->angleDelta() / 120.0f; - _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_POS).getChannel()] = (currentMove.x() > 0 ? currentMove.x() : 0.0f); - _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_NEG).getChannel()] = (currentMove.x() < 0 ? -currentMove.x() : 0.0f); - _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_POS).getChannel()] = (currentMove.y() > 0 ? currentMove.y() : 0.0f); - _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_NEG).getChannel()] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f); + // ####### TODO: Use AxisValue timestamps? + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_POS).getChannel()].value = (currentMove.x() > 0 ? currentMove.x() : 0, 0); + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_NEG).getChannel()].value = (currentMove.x() < 0 ? -currentMove.x() : 0, 0); + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_POS).getChannel()].value = (currentMove.y() > 0 ? currentMove.y() : 0); + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_NEG).getChannel()].value = (currentMove.y() < 0 ? -currentMove.y() : 0); } glm::vec2 evalAverageTouchPoints(const QList& points) { @@ -167,11 +168,12 @@ void KeyboardMouseDevice::touchUpdateEvent(const QTouchEvent* event) { } else { auto currentMove = currentPos - _lastTouch; - _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_POS).getChannel()] = (currentMove.x > 0 ? currentMove.x : 0.0f); - _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_NEG).getChannel()] = (currentMove.x < 0 ? -currentMove.x : 0.0f); + // ####### TODO: Use AxisValue timestamp fields? + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_POS).getChannel()].value = (currentMove.x > 0 ? currentMove.x : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_NEG).getChannel()].value = (currentMove.x < 0 ? -currentMove.x : 0.0f); // Y mouse is inverted positive is pointing up the screen - _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_Y_POS).getChannel()] = (currentMove.y < 0 ? -currentMove.y : 0.0f); - _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_Y_NEG).getChannel()] = (currentMove.y > 0 ? currentMove.y : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_Y_POS).getChannel()].value = (currentMove.y < 0 ? -currentMove.y : 0.0f); + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_Y_NEG).getChannel()].value = (currentMove.y > 0 ? currentMove.y : 0.0f); } _lastTouch = currentPos; diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenDevice.cpp index 20952df4d7..804ab3585b 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/TouchscreenDevice.cpp @@ -38,28 +38,29 @@ void TouchscreenDevice::pluginUpdate(float deltaTime, const controller::InputCal _inputDevice->update(deltaTime, inputCalibrationData); }); + // ####### TODO: Use AxisValue timestamp fields? float distanceScaleX, distanceScaleY; if (_touchPointCount == 1) { if (_firstTouchVec.x < _currentTouchVec.x) { distanceScaleX = (_currentTouchVec.x - _firstTouchVec.x) / _screenDPIScale.x; - _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_POS).getChannel()] = distanceScaleX; + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_POS).getChannel()].value = distanceScaleX; } else if (_firstTouchVec.x > _currentTouchVec.x) { distanceScaleX = (_firstTouchVec.x - _currentTouchVec.x) / _screenDPIScale.x; - _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_NEG).getChannel()] = distanceScaleX; + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_NEG).getChannel()].value = distanceScaleX; } // Y axis is inverted, positive is pointing up the screen if (_firstTouchVec.y > _currentTouchVec.y) { distanceScaleY = (_firstTouchVec.y - _currentTouchVec.y) / _screenDPIScale.y; - _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_Y_POS).getChannel()] = distanceScaleY; + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_Y_POS).getChannel()].value = distanceScaleY; } else if (_firstTouchVec.y < _currentTouchVec.y) { distanceScaleY = (_currentTouchVec.y - _firstTouchVec.y) / _screenDPIScale.y; - _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_Y_NEG).getChannel()] = distanceScaleY; + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_Y_NEG).getChannel()].value = distanceScaleY; } } else if (_touchPointCount == 2) { if (_pinchScale > _lastPinchScale && _pinchScale != 0) { - _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_POS).getChannel()] = 1.0f; + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_POS).getChannel()].value = 1.0f; } else if (_pinchScale != 0) { - _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_NEG).getChannel()] = 1.0f; + _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_GESTURE_PINCH_NEG).getChannel()].value = 1.0; } _lastPinchScale = _pinchScale; } diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp index 32194e1b84..247f484c95 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/TouchscreenVirtualPadDevice.cpp @@ -135,8 +135,8 @@ glm::vec2 TouchscreenVirtualPadDevice::clippedPointInCircle(float radius, glm::v void TouchscreenVirtualPadDevice::processInputDeviceForMove(VirtualPad::Manager& virtualPadManager) { vec2 clippedPoint = clippedPointInCircle(_fixedRadiusForCalc, _moveRefTouchPoint, _moveCurrentTouchPoint); - _inputDevice->_axisStateMap[controller::LX] = (clippedPoint.x - _moveRefTouchPoint.x) / _fixedRadiusForCalc; - _inputDevice->_axisStateMap[controller::LY] = (clippedPoint.y - _moveRefTouchPoint.y) / _fixedRadiusForCalc; + _inputDevice->_axisStateMap[controller::LX].value = (clippedPoint.x - _moveRefTouchPoint.x) / _fixedRadiusForCalc; + _inputDevice->_axisStateMap[controller::LY].value = (clippedPoint.y - _moveRefTouchPoint.y) / _fixedRadiusForCalc; virtualPadManager.getLeftVirtualPad()->setFirstTouch(_moveRefTouchPoint); virtualPadManager.getLeftVirtualPad()->setCurrentTouch(clippedPoint); @@ -148,8 +148,10 @@ void TouchscreenVirtualPadDevice::processInputDeviceForView() { // We use average across how many times we've got touchUpdate events. // Using the average instead of the full deltaX and deltaY, makes deltaTime in MyAvatar dont't accelerate rotation when there is a low touchUpdate rate (heavier domains). // (Because it multiplies this input value by deltaTime (with a coefficient)). - _inputDevice->_axisStateMap[controller::RX] = _viewTouchUpdateCount == 0 ? 0 : (_viewCurrentTouchPoint.x - _viewRefTouchPoint.x) / _viewTouchUpdateCount; - _inputDevice->_axisStateMap[controller::RY] = _viewTouchUpdateCount == 0 ? 0 : (_viewCurrentTouchPoint.y - _viewRefTouchPoint.y) / _viewTouchUpdateCount; + _inputDevice->_axisStateMap[controller::RX].value = + _viewTouchUpdateCount == 0 ? 0 : (_viewCurrentTouchPoint.x - _viewRefTouchPoint.x) / _viewTouchUpdateCount; + _inputDevice->_axisStateMap[controller::RY].value = + _viewTouchUpdateCount == 0 ? 0 : (_viewCurrentTouchPoint.y - _viewRefTouchPoint.y) / _viewTouchUpdateCount; // after use, save last touch point as ref _viewRefTouchPoint = _viewCurrentTouchPoint; @@ -442,8 +444,8 @@ void TouchscreenVirtualPadDevice::moveTouchUpdate(glm::vec2 touchPoint) { void TouchscreenVirtualPadDevice::moveTouchEnd() { if (_moveHasValidTouch) { // do stuff once _moveHasValidTouch = false; - _inputDevice->_axisStateMap[controller::LX] = 0; - _inputDevice->_axisStateMap[controller::LY] = 0; + _inputDevice->_axisStateMap[controller::LX].value = 0; + _inputDevice->_axisStateMap[controller::LY].value = 0; } } @@ -465,8 +467,8 @@ void TouchscreenVirtualPadDevice::viewTouchUpdate(glm::vec2 touchPoint) { void TouchscreenVirtualPadDevice::viewTouchEnd() { if (_viewHasValidTouch) { // do stuff once _viewHasValidTouch = false; - _inputDevice->_axisStateMap[controller::RX] = 0; - _inputDevice->_axisStateMap[controller::RY] = 0; + _inputDevice->_axisStateMap[controller::RX].value = 0; + _inputDevice->_axisStateMap[controller::RY].value = 0; } } diff --git a/plugins/hifiSdl2/src/Joystick.cpp b/plugins/hifiSdl2/src/Joystick.cpp index be4ad6e4ee..ad0b459544 100644 --- a/plugins/hifiSdl2/src/Joystick.cpp +++ b/plugins/hifiSdl2/src/Joystick.cpp @@ -46,8 +46,8 @@ void Joystick::closeJoystick() { void Joystick::update(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { for (auto axisState : _axisStateMap) { - if (fabsf(axisState.second) < CONTROLLER_THRESHOLD) { - _axisStateMap[axisState.first] = 0.0f; + if (fabsf(axisState.second.value) < CONTROLLER_THRESHOLD) { + _axisStateMap[axisState.first].value = 0.0f; } } } @@ -59,7 +59,7 @@ void Joystick::focusOutEvent() { void Joystick::handleAxisEvent(const SDL_ControllerAxisEvent& event) { SDL_GameControllerAxis axis = (SDL_GameControllerAxis) event.axis; - _axisStateMap[makeInput((controller::StandardAxisChannel)axis).getChannel()] = (float)event.value / MAX_AXIS; + _axisStateMap[makeInput((controller::StandardAxisChannel)axis).getChannel()].value = (float)event.value / MAX_AXIS; } void Joystick::handleButtonEvent(const SDL_ControllerButtonEvent& event) { diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 392d990638..76ff4a1755 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -258,15 +258,15 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, using namespace controller; // Axes const auto& inputState = _parent._touchInputState; - _axisStateMap[LX] = inputState.Thumbstick[ovrHand_Left].x; - _axisStateMap[LY] = inputState.Thumbstick[ovrHand_Left].y; - _axisStateMap[LT] = inputState.IndexTrigger[ovrHand_Left]; - _axisStateMap[LEFT_GRIP] = inputState.HandTrigger[ovrHand_Left]; + _axisStateMap[LX].value = inputState.Thumbstick[ovrHand_Left].x; + _axisStateMap[LY].value = inputState.Thumbstick[ovrHand_Left].y; + _axisStateMap[LT].value = inputState.IndexTrigger[ovrHand_Left]; + _axisStateMap[LEFT_GRIP].value = inputState.HandTrigger[ovrHand_Left]; - _axisStateMap[RX] = inputState.Thumbstick[ovrHand_Right].x; - _axisStateMap[RY] = inputState.Thumbstick[ovrHand_Right].y; - _axisStateMap[RT] = inputState.IndexTrigger[ovrHand_Right]; - _axisStateMap[RIGHT_GRIP] = inputState.HandTrigger[ovrHand_Right]; + _axisStateMap[RX].value = inputState.Thumbstick[ovrHand_Right].x; + _axisStateMap[RY].value = inputState.Thumbstick[ovrHand_Right].y; + _axisStateMap[RT].value = inputState.IndexTrigger[ovrHand_Right]; + _axisStateMap[RIGHT_GRIP].value = inputState.HandTrigger[ovrHand_Right]; // Buttons for (const auto& pair : BUTTON_MAP) { diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 53c23403a5..3aea5f1ce0 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -928,8 +928,8 @@ void ViveControllerManager::InputDevice::partitionTouchpad(int sButton, int xAxi const float CENTER_DEADBAND = 0.6f; const float DIAGONAL_DIVIDE_IN_RADIANS = PI / 4.0f; if (_buttonPressedMap.find(sButton) != _buttonPressedMap.end()) { - float absX = abs(_axisStateMap[xAxis]); - float absY = abs(_axisStateMap[yAxis]); + float absX = abs(_axisStateMap[xAxis].value); + float absY = abs(_axisStateMap[yAxis].value); glm::vec2 cartesianQuadrantI(absX, absY); float angle = glm::atan(cartesianQuadrantI.y / cartesianQuadrantI.x); float radius = glm::length(cartesianQuadrantI); @@ -956,10 +956,10 @@ void ViveControllerManager::InputDevice::handleAxisEvent(float deltaTime, uint32 } else { stick = _filteredRightStick.process(deltaTime, stick); } - _axisStateMap[isLeftHand ? LX : RX] = stick.x; - _axisStateMap[isLeftHand ? LY : RY] = stick.y; + _axisStateMap[isLeftHand ? LX : RX].value = stick.x; + _axisStateMap[isLeftHand ? LY : RY].value = stick.y; } else if (axis == vr::k_EButton_SteamVR_Trigger) { - _axisStateMap[isLeftHand ? LT : RT] = x; + _axisStateMap[isLeftHand ? LT : RT].value = x; // The click feeling on the Vive controller trigger represents a value of *precisely* 1.0, // so we can expose that as an additional button if (x >= 1.0f) { @@ -1000,7 +1000,7 @@ void ViveControllerManager::InputDevice::handleButtonEvent(float deltaTime, uint if (button == vr::k_EButton_ApplicationMenu) { _buttonPressedMap.insert(isLeftHand ? LEFT_APP_MENU : RIGHT_APP_MENU); } else if (button == vr::k_EButton_Grip) { - _axisStateMap[isLeftHand ? LEFT_GRIP : RIGHT_GRIP] = 1.0f; + _axisStateMap[isLeftHand ? LEFT_GRIP : RIGHT_GRIP].value = 1.0f; } else if (button == vr::k_EButton_SteamVR_Trigger) { _buttonPressedMap.insert(isLeftHand ? LT : RT); } else if (button == vr::k_EButton_SteamVR_Touchpad) { @@ -1008,7 +1008,7 @@ void ViveControllerManager::InputDevice::handleButtonEvent(float deltaTime, uint } } else { if (button == vr::k_EButton_Grip) { - _axisStateMap[isLeftHand ? LEFT_GRIP : RIGHT_GRIP] = 0.0f; + _axisStateMap[isLeftHand ? LEFT_GRIP : RIGHT_GRIP].value = 0.0f; } } From d12b504a8842b478ad4c184d235dcfff09e14e3d Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 31 Dec 2018 11:55:02 +1300 Subject: [PATCH 04/11] Use Controller axis value timestamp for mouse movement Controller events --- interface/src/raypick/PathPointer.cpp | 2 +- .../controllers/src/controllers/AxisValue.cpp | 3 +++ .../controllers/src/controllers/AxisValue.h | 3 +++ .../src/controllers/InputDevice.cpp | 13 +++++------ .../controllers/src/controllers/InputDevice.h | 4 ++-- .../src/controllers/ScriptingInterface.cpp | 6 ++--- .../src/controllers/UserInputMapper.cpp | 20 ++++++++--------- .../src/controllers/UserInputMapper.h | 6 ++--- .../src/controllers/impl/Endpoint.h | 22 ++++++++++--------- .../controllers/src/controllers/impl/Filter.h | 3 ++- .../impl/conditionals/EndpointConditional.h | 2 +- .../impl/endpoints/ActionEndpoint.cpp | 12 +++++----- .../impl/endpoints/ActionEndpoint.h | 6 ++--- .../impl/endpoints/AnyEndpoint.cpp | 18 +++++++-------- .../controllers/impl/endpoints/AnyEndpoint.h | 6 ++--- .../impl/endpoints/ArrayEndpoint.h | 4 ++-- .../impl/endpoints/CompositeEndpoint.cpp | 10 ++++----- .../impl/endpoints/CompositeEndpoint.h | 6 ++--- .../impl/endpoints/InputEndpoint.cpp | 8 +++---- .../impl/endpoints/InputEndpoint.h | 7 +++--- .../controllers/impl/endpoints/JSEndpoint.cpp | 10 ++++----- .../controllers/impl/endpoints/JSEndpoint.h | 4 ++-- .../impl/endpoints/ScriptEndpoint.cpp | 10 ++++----- .../impl/endpoints/ScriptEndpoint.h | 7 +++--- .../impl/endpoints/StandardEndpoint.h | 8 +++---- .../impl/filters/AccelerationLimiterFilter.h | 2 +- .../controllers/impl/filters/ClampFilter.h | 4 ++-- .../impl/filters/ConstrainToIntegerFilter.h | 4 ++-- .../ConstrainToPositiveIntegerFilter.h | 4 ++-- .../impl/filters/DeadZoneFilter.cpp | 10 ++++----- .../controllers/impl/filters/DeadZoneFilter.h | 2 +- .../impl/filters/ExponentialSmoothingFilter.h | 2 +- .../impl/filters/HysteresisFilter.cpp | 8 +++---- .../impl/filters/HysteresisFilter.h | 2 +- .../impl/filters/LowVelocityFilter.h | 2 +- .../controllers/impl/filters/NotFilter.cpp | 4 ++-- .../src/controllers/impl/filters/NotFilter.h | 2 +- .../impl/filters/PostTransformFilter.h | 2 +- .../controllers/impl/filters/PulseFilter.cpp | 8 +++---- .../controllers/impl/filters/PulseFilter.h | 2 +- .../controllers/impl/filters/RotateFilter.h | 2 +- .../controllers/impl/filters/ScaleFilter.h | 4 ++-- .../impl/filters/TransformFilter.h | 2 +- .../impl/filters/TranslateFilter.h | 2 +- .../src/input-plugins/KeyboardMouseDevice.cpp | 15 +++++++++---- .../src/input-plugins/KeyboardMouseDevice.h | 3 +++ 46 files changed, 152 insertions(+), 134 deletions(-) diff --git a/interface/src/raypick/PathPointer.cpp b/interface/src/raypick/PathPointer.cpp index 00ab32bde4..8a6995936f 100644 --- a/interface/src/raypick/PathPointer.cpp +++ b/interface/src/raypick/PathPointer.cpp @@ -223,7 +223,7 @@ Pointer::Buttons PathPointer::getPressedButtons(const PickResultPointer& pickRes std::string button = trigger.getButton(); TriggerState& state = _states[button]; // TODO: right now, LaserPointers don't support axes, only on/off buttons - if (trigger.getEndpoint()->peek() >= 1.0f) { + if (trigger.getEndpoint()->peek().value >= 1.0f) { toReturn.insert(button); if (_previousButtons.find(button) == _previousButtons.end()) { diff --git a/libraries/controllers/src/controllers/AxisValue.cpp b/libraries/controllers/src/controllers/AxisValue.cpp index 49201dbf7a..4b7913754c 100644 --- a/libraries/controllers/src/controllers/AxisValue.cpp +++ b/libraries/controllers/src/controllers/AxisValue.cpp @@ -15,4 +15,7 @@ namespace controller { AxisValue::AxisValue(const float value, const quint64 timestamp) : value(value), timestamp(timestamp) { } + bool AxisValue::operator==(const AxisValue& right) const { + return value == right.value && timestamp == right.timestamp; + } } diff --git a/libraries/controllers/src/controllers/AxisValue.h b/libraries/controllers/src/controllers/AxisValue.h index 67fd5736b8..e4bc20f7d2 100644 --- a/libraries/controllers/src/controllers/AxisValue.h +++ b/libraries/controllers/src/controllers/AxisValue.h @@ -24,6 +24,9 @@ namespace controller { AxisValue() {} AxisValue(const float value, const quint64 timestamp); + + bool operator ==(const AxisValue& right) const; + bool operator !=(const AxisValue& right) const { return !(*this == right); } }; } diff --git a/libraries/controllers/src/controllers/InputDevice.cpp b/libraries/controllers/src/controllers/InputDevice.cpp index e46bb3c8b5..dd430263fa 100644 --- a/libraries/controllers/src/controllers/InputDevice.cpp +++ b/libraries/controllers/src/controllers/InputDevice.cpp @@ -68,26 +68,25 @@ namespace controller { return Input::NamedPair(makeInput(pose), name); } - float InputDevice::getValue(ChannelType channelType, uint16_t channel) const { + AxisValue InputDevice::getValue(ChannelType channelType, uint16_t channel) const { switch (channelType) { case ChannelType::AXIS: - return getAxis(channel).value; + return getAxis(channel); case ChannelType::BUTTON: - return getButton(channel); + return { getButton(channel), 0 }; case ChannelType::POSE: - return getPose(channel).valid ? 1.0f : 0.0f; + return { getPose(channel).valid ? 1.0f : 0.0f, 0 }; default: break; } - return 0.0f; + return { 0.0f, 0 }; } - - float InputDevice::getValue(const Input& input) const { + AxisValue InputDevice::getValue(const Input& input) const { return getValue(input.getType(), input.channel); } diff --git a/libraries/controllers/src/controllers/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h index 1d4ab1c5d8..7c3c31cb38 100644 --- a/libraries/controllers/src/controllers/InputDevice.h +++ b/libraries/controllers/src/controllers/InputDevice.h @@ -112,8 +112,8 @@ public: AxisValue getAxis(int channel) const; Pose getPose(int channel) const; - float getValue(const Input& input) const; - float getValue(ChannelType channelType, uint16_t channel) const; + AxisValue getValue(const Input& input) const; + AxisValue getValue(ChannelType channelType, uint16_t channel) const; Pose getPoseValue(uint16_t channel) const; const QString& getName() const { return _name; } diff --git a/libraries/controllers/src/controllers/ScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp index ce730bffa8..07c59e1aaa 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -89,17 +89,17 @@ namespace controller { float ScriptingInterface::getValue(const int& source) const { auto userInputMapper = DependencyManager::get(); - return userInputMapper->getValue(Input((uint32_t)source)); + return userInputMapper->getValue(Input((uint32_t)source)).value; } float ScriptingInterface::getAxisValue(int source) const { auto userInputMapper = DependencyManager::get(); - return userInputMapper->getValue(Input((uint32_t)source)); + return userInputMapper->getValue(Input((uint32_t)source)).value; } Pose ScriptingInterface::getPoseValue(const int& source) const { auto userInputMapper = DependencyManager::get(); - return userInputMapper->getPose(Input((uint32_t)source)); + return userInputMapper->getPose(Input((uint32_t)source)); } QVector ScriptingInterface::getAllActions() { diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 307064c073..e8503d8d1e 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -290,17 +290,17 @@ void UserInputMapper::update(float deltaTime) { if ((int)_lastStandardStates.size() != standardInputs.size()) { _lastStandardStates.resize(standardInputs.size()); for (auto& lastValue : _lastStandardStates) { - lastValue = 0; + lastValue = AxisValue(); } } for (int i = 0; i < standardInputs.size(); ++i) { const auto& input = standardInputs[i].first; - float value = getValue(input); - float& oldValue = _lastStandardStates[i]; + AxisValue value = getValue(input); + AxisValue& oldValue = _lastStandardStates[i]; if (value != oldValue) { oldValue = value; - emit inputEvent(input.id, value); + emit inputEvent(input.id, value.value); } } inputRecorder->frameTick(); @@ -604,10 +604,10 @@ bool UserInputMapper::applyRoute(const Route::Pointer& route, bool force) { destination->apply(value, source); } else { // Fetch the value, may have been overriden by previous loopback routes - float value = getValue(source, route->peek); + auto value = getValue(source, route->peek); if (debugRoutes && route->debug) { - qCDebug(controllers) << "Value was " << value; + qCDebug(controllers) << "Value was " << value.value << value.timestamp; } // Apply each of the filters. for (const auto& filter : route->filters) { @@ -615,7 +615,7 @@ bool UserInputMapper::applyRoute(const Route::Pointer& route, bool force) { } if (debugRoutes && route->debug) { - qCDebug(controllers) << "Filtered value was " << value; + qCDebug(controllers) << "Filtered value was " << value.value << value.timestamp; } destination->apply(value, source); @@ -741,15 +741,15 @@ void UserInputMapper::enableMapping(const QString& mappingName, bool enable) { } } -float UserInputMapper::getValue(const Endpoint::Pointer& endpoint, bool peek) { +AxisValue UserInputMapper::getValue(const Endpoint::Pointer& endpoint, bool peek) { return peek ? endpoint->peek() : endpoint->value(); } -float UserInputMapper::getValue(const Input& input) const { +AxisValue UserInputMapper::getValue(const Input& input) const { Locker locker(_lock); auto endpoint = endpointFor(input); if (!endpoint) { - return 0; + return AxisValue(); } return endpoint->value(); } diff --git a/libraries/controllers/src/controllers/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h index 5fd21e6299..2b3c947491 100644 --- a/libraries/controllers/src/controllers/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -121,7 +121,7 @@ namespace controller { void unloadMappings(const QStringList& jsonFiles); void unloadMapping(const QString& jsonFile); - float getValue(const Input& input) const; + AxisValue getValue(const Input& input) const; Pose getPose(const Input& input) const; // perform an action when the UserInputMapper mutex is acquired. @@ -147,9 +147,9 @@ namespace controller { std::vector _actionScales = std::vector(toInt(Action::NUM_ACTIONS), 1.0f); std::vector _lastActionStates = std::vector(toInt(Action::NUM_ACTIONS), 0.0f); std::vector _poseStates = std::vector(toInt(Action::NUM_ACTIONS)); - std::vector _lastStandardStates = std::vector(); + std::vector _lastStandardStates = std::vector(); - static float getValue(const EndpointPointer& endpoint, bool peek = false); + static AxisValue getValue(const EndpointPointer& endpoint, bool peek = false); static Pose getPose(const EndpointPointer& endpoint, bool peek = false); friend class RouteBuilderProxy; diff --git a/libraries/controllers/src/controllers/impl/Endpoint.h b/libraries/controllers/src/controllers/impl/Endpoint.h index a938dd30b6..29ba7c97f0 100644 --- a/libraries/controllers/src/controllers/impl/Endpoint.h +++ b/libraries/controllers/src/controllers/impl/Endpoint.h @@ -16,6 +16,7 @@ #include +#include "../AxisValue.h" #include "../Input.h" #include "../Pose.h" @@ -36,12 +37,13 @@ namespace controller { using WriteLambda = std::function; Endpoint(const Input& input) : _input(input) {} - virtual float value() { return peek(); } - virtual float peek() const = 0; - virtual void apply(float value, const Pointer& source) = 0; + virtual AxisValue value() { return peek(); } + virtual AxisValue peek() const = 0; + virtual void apply(AxisValue value, const Pointer& source) = 0; virtual Pose peekPose() const { return Pose(); }; virtual Pose pose() { return peekPose(); } virtual void apply(const Pose& value, const Pointer& source) {} + virtual bool isAxis() const { return _input.isAxis(); } virtual bool isPose() const { return _input.isPose(); } virtual bool writeable() const { return true; } virtual bool readable() const { return true; } @@ -59,8 +61,8 @@ namespace controller { LambdaEndpoint(ReadLambda readLambda, WriteLambda writeLambda = [](float) {}) : Endpoint(Input::INVALID_INPUT), _readLambda(readLambda), _writeLambda(writeLambda) { } - virtual float peek() const override { return _readLambda(); } - virtual void apply(float value, const Pointer& source) override { _writeLambda(value); } + virtual AxisValue peek() const override { return AxisValue(_readLambda(), 0); } + virtual void apply(AxisValue value, const Pointer& source) override { _writeLambda(value.value); } private: ReadLambda _readLambda; @@ -76,8 +78,8 @@ namespace controller { : Endpoint(Input::INVALID_INPUT), _readLambda(readLambda), _writeLambda(writeLambda) { } - virtual float peek() const override { return _readLambda(); } - virtual void apply(float value, const Pointer& source) override { _writeLambda(value); } + virtual AxisValue peek() const override { return AxisValue(_readLambda(), 0); } + virtual void apply(AxisValue value, const Pointer& source) override { _writeLambda(value.value); } private: const ReadLambda& _readLambda; @@ -91,15 +93,15 @@ namespace controller { : Endpoint(id) { } - virtual float peek() const override { return _currentValue; } - virtual void apply(float value, const Pointer& source) override { _currentValue = value; } + virtual AxisValue peek() const override { return _currentValue; } + virtual void apply(AxisValue value, const Pointer& source) override { _currentValue = value; } virtual Pose peekPose() const override { return _currentPose; } virtual void apply(const Pose& value, const Pointer& source) override { _currentPose = value; } protected: - float _currentValue { 0.0f }; + AxisValue _currentValue { 0.0f, 0 }; Pose _currentPose {}; }; diff --git a/libraries/controllers/src/controllers/impl/Filter.h b/libraries/controllers/src/controllers/impl/Filter.h index 7afabb4bcb..5c88a5be58 100644 --- a/libraries/controllers/src/controllers/impl/Filter.h +++ b/libraries/controllers/src/controllers/impl/Filter.h @@ -21,6 +21,7 @@ #include +#include "../AxisValue.h" #include "../Pose.h" class QJsonValue; @@ -37,7 +38,7 @@ namespace controller { virtual ~Filter() = default; - virtual float apply(float value) const = 0; + virtual AxisValue apply(AxisValue value) const = 0; virtual Pose apply(Pose value) const = 0; // Factory features diff --git a/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h b/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h index 0ba1347087..50a33471e7 100644 --- a/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h +++ b/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h @@ -18,7 +18,7 @@ namespace controller { class EndpointConditional : public Conditional { public: EndpointConditional(Endpoint::Pointer endpoint) : _endpoint(endpoint) {} - virtual bool satisfied() override { return _endpoint && _endpoint->peek() != 0.0f; } + virtual bool satisfied() override { return _endpoint && _endpoint->peek().value != 0.0f; } private: Endpoint::Pointer _endpoint; }; diff --git a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp index f73268b41f..122af5a30c 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp @@ -15,22 +15,22 @@ using namespace controller; -void ActionEndpoint::apply(float newValue, const Pointer& source) { +void ActionEndpoint::apply(AxisValue newValue, const Pointer& source) { auto userInputMapper = DependencyManager::get(); InputRecorder* inputRecorder = InputRecorder::getInstance(); QString actionName; if (inputRecorder->isPlayingback() || inputRecorder->isRecording()) { actionName = userInputMapper->getActionName(Action(_input.getChannel())); if (inputRecorder->isPlayingback()) { - newValue = inputRecorder->getActionState(actionName); + newValue = AxisValue(inputRecorder->getActionState(actionName), 0); } } - _currentValue += newValue; + _currentValue.value += newValue.value; if (_input != Input::INVALID_INPUT) { - userInputMapper->deltaActionState(Action(_input.getChannel()), newValue); + userInputMapper->deltaActionState(Action(_input.getChannel()), newValue.value); } - inputRecorder->setActionState(actionName, newValue); + inputRecorder->setActionState(actionName, newValue.value); } void ActionEndpoint::apply(const Pose& value, const Pointer& source) { @@ -51,7 +51,7 @@ void ActionEndpoint::apply(const Pose& value, const Pointer& source) { } void ActionEndpoint::reset() { - _currentValue = 0.0f; + _currentValue = AxisValue(); _currentPose = Pose(); } diff --git a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.h index 1073dc6593..94da4663aa 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.h @@ -23,8 +23,8 @@ class ActionEndpoint : public Endpoint { public: ActionEndpoint(const Input& id = Input::INVALID_INPUT) : Endpoint(id) { } - virtual float peek() const override { return _currentValue; } - virtual void apply(float newValue, const Pointer& source) override; + virtual AxisValue peek() const override { return _currentValue; } + virtual void apply(AxisValue newValue, const Pointer& source) override; virtual Pose peekPose() const override { return _currentPose; } virtual void apply(const Pose& value, const Pointer& source) override; @@ -32,7 +32,7 @@ public: virtual void reset() override; private: - float _currentValue{ 0.0f }; + AxisValue _currentValue { 0.0f, 0 }; Pose _currentPose{}; }; diff --git a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp index 598dfb6ee8..75acdd9d13 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp @@ -27,13 +27,13 @@ AnyEndpoint::AnyEndpoint(Endpoint::List children) : Endpoint(Input::INVALID_INPU } } -// The value of an any-point is considered to be the maxiumum absolute value, +// The value of an any-point is considered to be the maximum absolute value, // this handles any's of multiple axis values as well as single values as well -float AnyEndpoint::peek() const { - float result = 0.0f; +AxisValue AnyEndpoint::peek() const { + auto result = AxisValue(); for (auto& child : _children) { auto childValue = child->peek(); - if (std::abs(childValue) > std::abs(result)) { + if (std::abs(childValue.value) > std::abs(result.value)) { result = childValue; } } @@ -41,18 +41,18 @@ float AnyEndpoint::peek() const { } // Fetching the value must trigger any necessary side effects of value() on ALL the children. -float AnyEndpoint::value() { - float result = 0.0f; +AxisValue AnyEndpoint::value() { + auto result = AxisValue(); for (auto& child : _children) { auto childValue = child->value(); - if (std::abs(childValue) > std::abs(result)) { - result = childValue; + if (std::abs(childValue.value) > std::abs(result.value)) { + result.value = childValue.value; } } return result; } -void AnyEndpoint::apply(float newValue, const Endpoint::Pointer& source) { +void AnyEndpoint::apply(AxisValue newValue, const Endpoint::Pointer& source) { qFatal("AnyEndpoint is read only"); } diff --git a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h index 8947eb675f..a9634f10d8 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h @@ -19,9 +19,9 @@ class AnyEndpoint : public Endpoint { public: using Endpoint::apply; AnyEndpoint(Endpoint::List children); - virtual float peek() const override; - virtual float value() override; - virtual void apply(float newValue, const Endpoint::Pointer& source) override; + virtual AxisValue peek() const override; + virtual AxisValue value() override; + virtual void apply(AxisValue newValue, const Endpoint::Pointer& source) override; virtual bool writeable() const override; virtual bool readable() const override; diff --git a/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h index 34d30a2e97..f928a4f568 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h @@ -21,9 +21,9 @@ public: using Pointer = std::shared_ptr; ArrayEndpoint() : Endpoint(Input::INVALID_INPUT) { } - virtual float peek() const override { return 0.0f; } + virtual AxisValue peek() const override { return AxisValue(); } - virtual void apply(float value, const Endpoint::Pointer& source) override { + virtual void apply(AxisValue value, const Endpoint::Pointer& source) override { for (auto& child : _children) { if (child->writeable()) { child->apply(value, source); diff --git a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp index 1bd27489f8..bd75c97dd7 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp @@ -24,18 +24,18 @@ bool CompositeEndpoint::readable() const { return first->readable() && second->readable(); } -float CompositeEndpoint::peek() const { - float result = first->peek() * -1.0f + second->peek(); +AxisValue CompositeEndpoint::peek() const { + auto result = AxisValue(first->peek().value * -1.0f + second->peek().value, 0); return result; } // Fetching via value() must trigger any side effects of value() on the children -float CompositeEndpoint::value() { - float result = first->value() * -1.0f + second->value(); +AxisValue CompositeEndpoint::value() { + auto result = AxisValue(first->value().value * -1.0f + second->value().value, 0); return result; } -void CompositeEndpoint::apply(float newValue, const Pointer& source) { +void CompositeEndpoint::apply(AxisValue newValue, const Pointer& source) { // Composites are read only } diff --git a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h index 3249aa1d37..004df36273 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h @@ -18,9 +18,9 @@ namespace controller { using Endpoint::apply; CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second); - virtual float peek() const override; - virtual float value() override; - virtual void apply(float newValue, const Pointer& source) override; + virtual AxisValue peek() const override; + virtual AxisValue value() override; + virtual void apply(AxisValue newValue, const Pointer& source) override; virtual bool readable() const override; }; diff --git a/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.cpp index ce58c948d1..3755d860b6 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.cpp @@ -14,19 +14,19 @@ using namespace controller; -float InputEndpoint::peek() const { +AxisValue InputEndpoint::peek() const { if (isPose()) { - return peekPose().valid ? 1.0f : 0.0f; + return peekPose().valid ? AxisValue(1.0f, 0) : AxisValue(0.0f, 0); } auto userInputMapper = DependencyManager::get(); auto deviceProxy = userInputMapper->getDevice(_input); if (!deviceProxy) { - return 0.0f; + return AxisValue(); } return deviceProxy->getValue(_input); } -float InputEndpoint::value(){ +AxisValue InputEndpoint::value() { _read = true; return peek(); } diff --git a/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.h index 7e4560dcf9..9581228cef 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.h @@ -20,10 +20,11 @@ public: : Endpoint(id) { } - virtual float peek() const override; - virtual float value() override; + virtual AxisValue peek() const override; + virtual AxisValue value() override; // FIXME need support for writing back to vibration / force feedback effects - virtual void apply(float newValue, const Pointer& source) override {} + virtual void apply(AxisValue newValue, const Pointer& source) override {} + virtual Pose peekPose() const override; virtual Pose pose() override; virtual void apply(const Pose& value, const Pointer& source) override { } diff --git a/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.cpp index 2f20cd82c6..c01b67f1bc 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.cpp @@ -30,18 +30,18 @@ QString formatException(const QJSValue& exception) { return result; } -float JSEndpoint::peek() const { +AxisValue JSEndpoint::peek() const { QJSValue result = _callable.call(); if (result.isError()) { qCDebug(controllers).noquote() << formatException(result); - return 0.0f; + return AxisValue(); } else { - return (float)result.toNumber(); + return AxisValue((float)result.toNumber(), 0); } } -void JSEndpoint::apply(float newValue, const Pointer& source) { - QJSValue result = _callable.call(QJSValueList({ QJSValue(newValue) })); +void JSEndpoint::apply(AxisValue newValue, const Pointer& source) { + QJSValue result = _callable.call(QJSValueList({ QJSValue(newValue.value) })); if (result.isError()) { qCDebug(controllers).noquote() << formatException(result); } diff --git a/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h index 4d179da8e6..6c953399dd 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h @@ -24,8 +24,8 @@ public: : Endpoint(Input::INVALID_INPUT), _callable(callable) { } - virtual float peek() const override; - virtual void apply(float newValue, const Pointer& source) override; + virtual AxisValue peek() const override; + virtual void apply(AxisValue newValue, const Pointer& source) override; private: mutable QJSValue _callable; diff --git a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp index e2c48d776f..9f971d2f04 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp @@ -34,9 +34,9 @@ QString formatException(const QScriptValue& exception) { return result; } -float ScriptEndpoint::peek() const { +AxisValue ScriptEndpoint::peek() const { const_cast(this)->updateValue(); - return _lastValueRead; + return AxisValue(_lastValueRead, 0); } void ScriptEndpoint::updateValue() { @@ -58,15 +58,15 @@ void ScriptEndpoint::updateValue() { } } -void ScriptEndpoint::apply(float value, const Pointer& source) { +void ScriptEndpoint::apply(AxisValue value, const Pointer& source) { if (value == _lastValueWritten) { return; } - internalApply(value, source->getInput().getID()); + _lastValueWritten = value; + internalApply(value.value, source->getInput().getID()); } void ScriptEndpoint::internalApply(float value, int sourceID) { - _lastValueWritten = value; if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "internalApply", Qt::QueuedConnection, Q_ARG(float, value), diff --git a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h index 00439f5560..e739ab0b01 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h @@ -24,9 +24,8 @@ public: : Endpoint(Input::INVALID_INPUT), _callable(callable) { } - virtual float peek() const override; - virtual void apply(float newValue, const Pointer& source) override; - + virtual AxisValue peek() const override; + virtual void apply(AxisValue newValue, const Pointer& source) override; virtual Pose peekPose() const override; virtual void apply(const Pose& newValue, const Pointer& source) override; @@ -42,7 +41,7 @@ protected: private: QScriptValue _callable; float _lastValueRead { 0.0f }; - float _lastValueWritten { 0.0f }; + AxisValue _lastValueWritten { 0.0f, 0 }; bool _returnPose { false }; Pose _lastPoseRead; diff --git a/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h index 2006809fed..26a8063cdc 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/StandardEndpoint.h @@ -25,19 +25,19 @@ public: virtual bool writeable() const override { return !_written; } virtual bool readable() const override { return !_read; } virtual void reset() override { - apply(0.0f, Endpoint::Pointer()); + apply(AxisValue(), Endpoint::Pointer()); apply(Pose(), Endpoint::Pointer()); _written = _read = false; } - virtual float value() override { + virtual AxisValue value() override { _read = true; return VirtualEndpoint::value(); } - virtual void apply(float value, const Pointer& source) override { + virtual void apply(AxisValue value, const Pointer& source) override { // For standard endpoints, the first NON-ZERO write counts. - if (value != 0.0f) { + if (value != AxisValue()) { _written = true; } VirtualEndpoint::apply(value, source); diff --git a/libraries/controllers/src/controllers/impl/filters/AccelerationLimiterFilter.h b/libraries/controllers/src/controllers/impl/filters/AccelerationLimiterFilter.h index 269fd54102..15653a7df6 100644 --- a/libraries/controllers/src/controllers/impl/filters/AccelerationLimiterFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/AccelerationLimiterFilter.h @@ -19,7 +19,7 @@ namespace controller { public: AccelerationLimiterFilter() {} - float apply(float value) const override { return value; } + AxisValue apply(AxisValue value) const override { return value; } Pose apply(Pose value) const override; bool parseParameters(const QJsonValue& parameters) override; diff --git a/libraries/controllers/src/controllers/impl/filters/ClampFilter.h b/libraries/controllers/src/controllers/impl/filters/ClampFilter.h index b06a43515f..04684655c9 100644 --- a/libraries/controllers/src/controllers/impl/filters/ClampFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/ClampFilter.h @@ -18,8 +18,8 @@ class ClampFilter : public Filter { REGISTER_FILTER_CLASS(ClampFilter); public: ClampFilter(float min = 0.0, float max = 1.0) : _min(min), _max(max) {}; - virtual float apply(float value) const override { - return glm::clamp(value, _min, _max); + virtual AxisValue apply(AxisValue value) const override { + return { glm::clamp(value.value, _min, _max), value.timestamp }; } virtual Pose apply(Pose value) const override { return value; } diff --git a/libraries/controllers/src/controllers/impl/filters/ConstrainToIntegerFilter.h b/libraries/controllers/src/controllers/impl/filters/ConstrainToIntegerFilter.h index 129e08741d..2cce5f828d 100644 --- a/libraries/controllers/src/controllers/impl/filters/ConstrainToIntegerFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/ConstrainToIntegerFilter.h @@ -19,8 +19,8 @@ class ConstrainToIntegerFilter : public Filter { public: ConstrainToIntegerFilter() = default; - virtual float apply(float value) const override { - return glm::sign(value); + virtual AxisValue apply(AxisValue value) const override { + return { glm::sign(value.value), value.timestamp }; } virtual Pose apply(Pose value) const override { return value; } diff --git a/libraries/controllers/src/controllers/impl/filters/ConstrainToPositiveIntegerFilter.h b/libraries/controllers/src/controllers/impl/filters/ConstrainToPositiveIntegerFilter.h index 8f2140721a..07dd6654f1 100644 --- a/libraries/controllers/src/controllers/impl/filters/ConstrainToPositiveIntegerFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/ConstrainToPositiveIntegerFilter.h @@ -19,8 +19,8 @@ class ConstrainToPositiveIntegerFilter : public Filter { public: ConstrainToPositiveIntegerFilter() = default; - virtual float apply(float value) const override { - return (value <= 0.0f) ? 0.0f : 1.0f; + virtual AxisValue apply(AxisValue value) const override { + return { (value.value <= 0.0f) ? 0.0f : 1.0f, value.timestamp }; } virtual Pose apply(Pose value) const override { return value; } diff --git a/libraries/controllers/src/controllers/impl/filters/DeadZoneFilter.cpp b/libraries/controllers/src/controllers/impl/filters/DeadZoneFilter.cpp index f07ef25976..84d3b9de60 100644 --- a/libraries/controllers/src/controllers/impl/filters/DeadZoneFilter.cpp +++ b/libraries/controllers/src/controllers/impl/filters/DeadZoneFilter.cpp @@ -12,13 +12,13 @@ #include using namespace controller; -float DeadZoneFilter::apply(float value) const { - float scale = ((value < 0.0f) ? -1.0f : 1.0f) / (1.0f - _min); - float magnitude = std::abs(value); +AxisValue DeadZoneFilter::apply(AxisValue value) const { + float scale = ((value.value < 0.0f) ? -1.0f : 1.0f) / (1.0f - _min); + float magnitude = std::abs(value.value); if (magnitude < _min) { - return 0.0f; + return { 0.0f, value.timestamp }; } - return (magnitude - _min) * scale; + return { (magnitude - _min) * scale, value.timestamp }; } bool DeadZoneFilter::parseParameters(const QJsonValue& parameters) { diff --git a/libraries/controllers/src/controllers/impl/filters/DeadZoneFilter.h b/libraries/controllers/src/controllers/impl/filters/DeadZoneFilter.h index d898647126..7ac1e8a51d 100644 --- a/libraries/controllers/src/controllers/impl/filters/DeadZoneFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/DeadZoneFilter.h @@ -19,7 +19,7 @@ class DeadZoneFilter : public Filter { public: DeadZoneFilter(float min = 0.0) : _min(min) {}; - virtual float apply(float value) const override; + virtual AxisValue apply(AxisValue value) const override; virtual Pose apply(Pose value) const override { return value; } diff --git a/libraries/controllers/src/controllers/impl/filters/ExponentialSmoothingFilter.h b/libraries/controllers/src/controllers/impl/filters/ExponentialSmoothingFilter.h index 134f57243e..e0135a8f68 100644 --- a/libraries/controllers/src/controllers/impl/filters/ExponentialSmoothingFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/ExponentialSmoothingFilter.h @@ -21,7 +21,7 @@ namespace controller { ExponentialSmoothingFilter(float rotationConstant, float translationConstant) : _translationConstant(translationConstant), _rotationConstant(rotationConstant) {} - float apply(float value) const override { return value; } + AxisValue apply(AxisValue value) const override { return value; } Pose apply(Pose value) const override; bool parseParameters(const QJsonValue& parameters) override; diff --git a/libraries/controllers/src/controllers/impl/filters/HysteresisFilter.cpp b/libraries/controllers/src/controllers/impl/filters/HysteresisFilter.cpp index a7f22e1de4..91e59a39b9 100644 --- a/libraries/controllers/src/controllers/impl/filters/HysteresisFilter.cpp +++ b/libraries/controllers/src/controllers/impl/filters/HysteresisFilter.cpp @@ -20,17 +20,17 @@ HysteresisFilter::HysteresisFilter(float min, float max) : _min(min), _max(max) }; -float HysteresisFilter::apply(float value) const { +AxisValue HysteresisFilter::apply(AxisValue value) const { if (_signaled) { - if (value <= _min) { + if (value.value <= _min) { _signaled = false; } } else { - if (value >= _max) { + if (value.value >= _max) { _signaled = true; } } - return _signaled ? 1.0f : 0.0f; + return { _signaled ? 1.0f : 0.0f, value.timestamp }; } bool HysteresisFilter::parseParameters(const QJsonValue& parameters) { diff --git a/libraries/controllers/src/controllers/impl/filters/HysteresisFilter.h b/libraries/controllers/src/controllers/impl/filters/HysteresisFilter.h index 4eb563754f..c7c817ecfa 100644 --- a/libraries/controllers/src/controllers/impl/filters/HysteresisFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/HysteresisFilter.h @@ -18,7 +18,7 @@ class HysteresisFilter : public Filter { REGISTER_FILTER_CLASS(HysteresisFilter); public: HysteresisFilter(float min = 0.25, float max = 0.75); - virtual float apply(float value) const override; + virtual AxisValue apply(AxisValue value) const override; virtual Pose apply(Pose value) const override { return value; } diff --git a/libraries/controllers/src/controllers/impl/filters/LowVelocityFilter.h b/libraries/controllers/src/controllers/impl/filters/LowVelocityFilter.h index ac5299dc6f..eb4f53797f 100644 --- a/libraries/controllers/src/controllers/impl/filters/LowVelocityFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/LowVelocityFilter.h @@ -21,7 +21,7 @@ namespace controller { LowVelocityFilter(float rotationConstant, float translationConstant) : _translationConstant(translationConstant), _rotationConstant(rotationConstant) {} - float apply(float value) const override { return value; } + AxisValue apply(AxisValue value) const override { return value; } Pose apply(Pose newPose) const override; bool parseParameters(const QJsonValue& parameters) override; diff --git a/libraries/controllers/src/controllers/impl/filters/NotFilter.cpp b/libraries/controllers/src/controllers/impl/filters/NotFilter.cpp index 73460aed91..c0396857e5 100644 --- a/libraries/controllers/src/controllers/impl/filters/NotFilter.cpp +++ b/libraries/controllers/src/controllers/impl/filters/NotFilter.cpp @@ -5,6 +5,6 @@ using namespace controller; NotFilter::NotFilter() { } -float NotFilter::apply(float value) const { - return (value == 0.0f) ? 1.0f : 0.0f; +AxisValue NotFilter::apply(AxisValue value) const { + return { (value.value == 0.0f) ? 1.0f : 0.0f, value.timestamp }; } diff --git a/libraries/controllers/src/controllers/impl/filters/NotFilter.h b/libraries/controllers/src/controllers/impl/filters/NotFilter.h index ceb7d29de3..d68a9feff7 100644 --- a/libraries/controllers/src/controllers/impl/filters/NotFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/NotFilter.h @@ -11,7 +11,7 @@ class NotFilter : public Filter { public: NotFilter(); - virtual float apply(float value) const override; + virtual AxisValue apply(AxisValue value) const override; virtual Pose apply(Pose value) const override { return value; } }; diff --git a/libraries/controllers/src/controllers/impl/filters/PostTransformFilter.h b/libraries/controllers/src/controllers/impl/filters/PostTransformFilter.h index 3c1cb4f80c..aeb24cc3f8 100644 --- a/libraries/controllers/src/controllers/impl/filters/PostTransformFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/PostTransformFilter.h @@ -21,7 +21,7 @@ class PostTransformFilter : public Filter { public: PostTransformFilter() = default; PostTransformFilter(glm::mat4 transform) : _transform(transform) {} - virtual float apply(float value) const override { return value; } + virtual AxisValue apply(AxisValue value) const override { return value; } virtual Pose apply(Pose value) const override { return value.postTransform(_transform); } virtual bool parseParameters(const QJsonValue& parameters) override { return parseMat4Parameter(parameters, _transform); } private: diff --git a/libraries/controllers/src/controllers/impl/filters/PulseFilter.cpp b/libraries/controllers/src/controllers/impl/filters/PulseFilter.cpp index 6ef9d40802..d37eb99ca9 100644 --- a/libraries/controllers/src/controllers/impl/filters/PulseFilter.cpp +++ b/libraries/controllers/src/controllers/impl/filters/PulseFilter.cpp @@ -15,21 +15,21 @@ using namespace controller; const float PulseFilter::DEFAULT_LAST_EMIT_TIME = -::std::numeric_limits::max(); -float PulseFilter::apply(float value) const { +AxisValue PulseFilter::apply(AxisValue value) const { float result = 0.0f; - if (0.0f != value) { + if (0.0f != value.value) { float now = secTimestampNow(); float delta = now - _lastEmitTime; if (delta >= _interval) { _lastEmitTime = now; - result = value; + result = value.value; } } else if (_resetOnZero) { _lastEmitTime = DEFAULT_LAST_EMIT_TIME; } - return result; + return { result, value.timestamp }; } bool PulseFilter::parseParameters(const QJsonValue& parameters) { diff --git a/libraries/controllers/src/controllers/impl/filters/PulseFilter.h b/libraries/controllers/src/controllers/impl/filters/PulseFilter.h index 2e0da0efa9..dc56b3c6c9 100644 --- a/libraries/controllers/src/controllers/impl/filters/PulseFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/PulseFilter.h @@ -21,7 +21,7 @@ public: PulseFilter() = default; PulseFilter(float interval) : _interval(interval) {} - virtual float apply(float value) const override; + virtual AxisValue apply(AxisValue value) const override; virtual Pose apply(Pose value) const override { return value; } diff --git a/libraries/controllers/src/controllers/impl/filters/RotateFilter.h b/libraries/controllers/src/controllers/impl/filters/RotateFilter.h index c6735f6aa9..d1f1f2d269 100644 --- a/libraries/controllers/src/controllers/impl/filters/RotateFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/RotateFilter.h @@ -22,7 +22,7 @@ public: RotateFilter() = default; RotateFilter(glm::quat rotation) : _rotation(rotation) {} - virtual float apply(float value) const override { return value; } + virtual AxisValue apply(AxisValue value) const override { return value; } virtual Pose apply(Pose value) const override { return value.transform(glm::mat4(glm::quat(_rotation))); diff --git a/libraries/controllers/src/controllers/impl/filters/ScaleFilter.h b/libraries/controllers/src/controllers/impl/filters/ScaleFilter.h index 936498a7a1..3eb58e7f47 100644 --- a/libraries/controllers/src/controllers/impl/filters/ScaleFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/ScaleFilter.h @@ -22,8 +22,8 @@ public: ScaleFilter() = default; ScaleFilter(float scale) : _scale(scale) {} - virtual float apply(float value) const override { - return value * _scale; + virtual AxisValue apply(AxisValue value) const override { + return { value.value * _scale, value.timestamp }; } virtual Pose apply(Pose value) const override { diff --git a/libraries/controllers/src/controllers/impl/filters/TransformFilter.h b/libraries/controllers/src/controllers/impl/filters/TransformFilter.h index a34edaa337..c81af2ef17 100644 --- a/libraries/controllers/src/controllers/impl/filters/TransformFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/TransformFilter.h @@ -22,7 +22,7 @@ public: TransformFilter() = default; TransformFilter(glm::mat4 transform) : _transform(transform) {} - virtual float apply(float value) const override { return value; } + virtual AxisValue apply(AxisValue value) const override { return value; } virtual Pose apply(Pose value) const override { return value.transform(_transform); } virtual bool parseParameters(const QJsonValue& parameters) override { return parseMat4Parameter(parameters, _transform); } diff --git a/libraries/controllers/src/controllers/impl/filters/TranslateFilter.h b/libraries/controllers/src/controllers/impl/filters/TranslateFilter.h index ced9cbc689..476481807d 100644 --- a/libraries/controllers/src/controllers/impl/filters/TranslateFilter.h +++ b/libraries/controllers/src/controllers/impl/filters/TranslateFilter.h @@ -22,7 +22,7 @@ public: TranslateFilter() = default; TranslateFilter(glm::vec3 translate) : _translate(translate) {} - virtual float apply(float value) const override { return value; } + virtual AxisValue apply(AxisValue value) const override { return value; } virtual Pose apply(Pose value) const override { return value.transform(glm::translate(_translate)); } virtual bool parseParameters(const QJsonValue& parameters) override { return parseVec3Parameter(parameters, _translate); } diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index ebc5a5cd3e..df58ea81c2 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -21,6 +21,13 @@ const char* KeyboardMouseDevice::NAME = "Keyboard/Mouse"; bool KeyboardMouseDevice::_enableTouch = true; +void KeyboardMouseDevice::updateDeltaAxisValue(int channel, float value) { + // Use timestamps for delta values so that consecutive identical values can be output. + if (value != 0.0f || _inputDevice->_axisStateMap[channel].value != 0) { + _inputDevice->_axisStateMap[channel] = { value, usecTimestampNow() }; + } +} + void KeyboardMouseDevice::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { auto userInputMapper = DependencyManager::get(); userInputMapper->withLock([&, this]() { @@ -31,11 +38,11 @@ void KeyboardMouseDevice::pluginUpdate(float deltaTime, const controller::InputC _inputDevice->_axisStateMap[MOUSE_AXIS_Y].value = _lastCursor.y(); QPoint currentMove = _lastCursor - _previousCursor; - _inputDevice->_axisStateMap[MOUSE_AXIS_X_POS].value = (currentMove.x() > 0 ? currentMove.x() : 0.0f); - _inputDevice->_axisStateMap[MOUSE_AXIS_X_NEG].value = (currentMove.x() < 0 ? -currentMove.x() : 0.0f); + updateDeltaAxisValue(MOUSE_AXIS_X_POS, currentMove.x() > 0 ? currentMove.x() : 0.0f); + updateDeltaAxisValue(MOUSE_AXIS_X_NEG, currentMove.x() < 0 ? -currentMove.x() : 0.0f); // Y mouse is inverted positive is pointing up the screen - _inputDevice->_axisStateMap[MOUSE_AXIS_Y_POS].value = (currentMove.y() < 0 ? -currentMove.y() : 0.0f); - _inputDevice->_axisStateMap[MOUSE_AXIS_Y_NEG].value = (currentMove.y() > 0 ? currentMove.y() : 0.0f); + updateDeltaAxisValue(MOUSE_AXIS_Y_POS, currentMove.y() < 0 ? -currentMove.y() : 0.0f); + updateDeltaAxisValue(MOUSE_AXIS_Y_NEG, currentMove.y() > 0 ? currentMove.y() : 0.0f); _previousCursor = _lastCursor; }); diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index 45ca496c11..f6921c8e23 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -130,6 +130,9 @@ protected: std::chrono::high_resolution_clock::time_point _lastTouchTime; static bool _enableTouch; + +private: + void updateDeltaAxisValue(int channel, float value); }; #endif // hifi_KeyboardMouseDevice_h From f381361c8231f94d354e142f0a04f50f95f6effc Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 31 Dec 2018 13:53:59 +1300 Subject: [PATCH 05/11] Fix typos --- .../src/input-plugins/KeyboardMouseDevice.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index df58ea81c2..ad24ffba5e 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -132,10 +132,10 @@ void KeyboardMouseDevice::wheelEvent(QWheelEvent* event) { auto currentMove = event->angleDelta() / 120.0f; // ####### TODO: Use AxisValue timestamps? - _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_POS).getChannel()].value = (currentMove.x() > 0 ? currentMove.x() : 0, 0); - _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_NEG).getChannel()].value = (currentMove.x() < 0 ? -currentMove.x() : 0, 0); - _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_POS).getChannel()].value = (currentMove.y() > 0 ? currentMove.y() : 0); - _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_NEG).getChannel()].value = (currentMove.y() < 0 ? -currentMove.y() : 0); + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_POS).getChannel()].value = currentMove.x() > 0 ? currentMove.x() : 0; + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_NEG).getChannel()].value = currentMove.x() < 0 ? -currentMove.x() : 0; + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_POS).getChannel()].value = currentMove.y() > 0 ? currentMove.y() : 0; + _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_NEG).getChannel()].value = currentMove.y() < 0 ? -currentMove.y() : 0; } glm::vec2 evalAverageTouchPoints(const QList& points) { From d073dc22ac4131955bccb71a72519401be83c671 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 2 Jan 2019 13:39:31 +1300 Subject: [PATCH 06/11] Misc fixes --- libraries/controllers/src/controllers/impl/Endpoint.h | 1 - .../src/controllers/impl/endpoints/AnyEndpoint.cpp | 2 +- .../src/controllers/impl/endpoints/CompositeEndpoint.cpp | 8 ++++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/controllers/src/controllers/impl/Endpoint.h b/libraries/controllers/src/controllers/impl/Endpoint.h index 29ba7c97f0..bcf71f3094 100644 --- a/libraries/controllers/src/controllers/impl/Endpoint.h +++ b/libraries/controllers/src/controllers/impl/Endpoint.h @@ -43,7 +43,6 @@ namespace controller { virtual Pose peekPose() const { return Pose(); }; virtual Pose pose() { return peekPose(); } virtual void apply(const Pose& value, const Pointer& source) {} - virtual bool isAxis() const { return _input.isAxis(); } virtual bool isPose() const { return _input.isPose(); } virtual bool writeable() const { return true; } virtual bool readable() const { return true; } diff --git a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp index 75acdd9d13..7f0f0fec48 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp @@ -46,7 +46,7 @@ AxisValue AnyEndpoint::value() { for (auto& child : _children) { auto childValue = child->value(); if (std::abs(childValue.value) > std::abs(result.value)) { - result.value = childValue.value; + result = childValue; } } return result; diff --git a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp index bd75c97dd7..f54c786a33 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp @@ -25,13 +25,17 @@ bool CompositeEndpoint::readable() const { } AxisValue CompositeEndpoint::peek() const { - auto result = AxisValue(first->peek().value * -1.0f + second->peek().value, 0); + auto negative = first->peek(); + auto positive = second->peek(); + auto result = AxisValue(positive.value - negative.value, std::max(positive.timestamp, negative.timestamp)); return result; } // Fetching via value() must trigger any side effects of value() on the children AxisValue CompositeEndpoint::value() { - auto result = AxisValue(first->value().value * -1.0f + second->value().value, 0); + auto negative = first->value(); + auto positive = second->value(); + auto result = AxisValue(positive.value - negative.value, std::max(positive.timestamp, negative.timestamp)); return result; } From 3b531f3c99b3a64a1d69001e3ca8d4d33718d8d2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 2 Jan 2019 13:41:55 +1300 Subject: [PATCH 07/11] Update JSDoc --- .../scripting/ControllerScriptingInterface.h | 2 +- .../src/input-plugins/KeyboardMouseDevice.cpp | 27 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 051a372aad..b063e98992 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -104,7 +104,7 @@ class ScriptEngine; *
    *
  • {@link Controller.getValue|getValue}
  • *
  • {@link Controller.getAxisValue|getAxisValue}
  • - *
  • {@link Controller.getPoseValue|getgetPoseValue}
  • + *
  • {@link Controller.getPoseValue|getPoseValue}
  • *
  • {@link Controller.getActionValue|getActionValue}
  • *
* diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index ad24ffba5e..c819aaeacf 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -254,16 +254,23 @@ controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevic * * PgDownnumbernumberThe page down key on the keyboard or keypad is pressed. * - * LeftMouseButtonnumbernumberThe left mouse button pressed. - * MiddleMouseButtonnumbernumberThe middle mouse button pressed. - * RightMouseButtonnumbernumberThe right mouse button pressed. - * LeftMouseClickednumbernumberThe left mouse button clicked. - * MiddleMouseClickednumbernumberThe middle mouse button clicked. - * RightMouseClickednumbernumberThe right mouse button clicked. - * MouseMoveRightnumbernumberThe mouse moved right. - * MouseMoveLeftnumbernumberThe mouse moved left. - * MouseMoveUpnumbernumberThe mouse moved up. - * MouseMoveDownnumbernumberThe mouse moved down. + * LeftMouseButtonnumbernumberThe left mouse button is pressed. + * MiddleMouseButtonnumbernumberThe middle mouse button is pressed. + * + * RightMouseButtonnumbernumberThe right mouse button is pressed. + * LeftMouseClickednumbernumberThe left mouse button was clicked. + * MiddleMouseClickednumbernumberThe middle mouse button was clicked. + * + * RightMouseClickednumbernumberThe right mouse button was clicked. + * + * MouseMoveRightnumbernumberThe mouse moved right. The data value is how + * far it moved. + * MouseMoveLeftnumbernumberThe mouse moved left. The data value is how far + * it moved. + * MouseMoveUpnumbernumberThe mouse moved up. The data value is how far it + * moved. + * MouseMoveDownnumbernumberThe mouse moved down. The data value is how far + * it moved. * MouseXnumbernumberThe mouse x-coordinate changed. The data value is its * new x-coordinate value. * MouseYnumbernumberThe mouse y-coordinate changed. The data value is its From 2ccef09d007a957e3842cb13b256da9f04a18637 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 3 Jan 2019 12:35:44 +1300 Subject: [PATCH 08/11] Make operation clearer --- .../input-plugins/src/input-plugins/KeyboardMouseDevice.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index c819aaeacf..91b737ee40 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -22,10 +22,8 @@ const char* KeyboardMouseDevice::NAME = "Keyboard/Mouse"; bool KeyboardMouseDevice::_enableTouch = true; void KeyboardMouseDevice::updateDeltaAxisValue(int channel, float value) { - // Use timestamps for delta values so that consecutive identical values can be output. - if (value != 0.0f || _inputDevice->_axisStateMap[channel].value != 0) { - _inputDevice->_axisStateMap[channel] = { value, usecTimestampNow() }; - } + // Associate timestamps with non-zero delta values so that consecutive identical values can be output. + _inputDevice->_axisStateMap[channel] = { value, value != 0.0f ? usecTimestampNow() : 0 }; } void KeyboardMouseDevice::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { From 36da8bfa588895f74b21e3255ce181874636787a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 3 Jan 2019 15:05:21 +1300 Subject: [PATCH 09/11] Remove TODOs --- .../input-plugins/src/input-plugins/KeyboardMouseDevice.cpp | 4 ---- .../input-plugins/src/input-plugins/TouchscreenDevice.cpp | 1 - 2 files changed, 5 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index 91b737ee40..3383d71a52 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -128,8 +128,6 @@ void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event) { void KeyboardMouseDevice::wheelEvent(QWheelEvent* event) { auto currentMove = event->angleDelta() / 120.0f; - - // ####### TODO: Use AxisValue timestamps? _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_POS).getChannel()].value = currentMove.x() > 0 ? currentMove.x() : 0; _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_X_NEG).getChannel()].value = currentMove.x() < 0 ? -currentMove.x() : 0; _inputDevice->_axisStateMap[_inputDevice->makeInput(MOUSE_AXIS_WHEEL_Y_POS).getChannel()].value = currentMove.y() > 0 ? currentMove.y() : 0; @@ -172,8 +170,6 @@ void KeyboardMouseDevice::touchUpdateEvent(const QTouchEvent* event) { _isTouching = event->touchPointStates().testFlag(Qt::TouchPointPressed); } else { auto currentMove = currentPos - _lastTouch; - - // ####### TODO: Use AxisValue timestamp fields? _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_POS).getChannel()].value = (currentMove.x > 0 ? currentMove.x : 0.0f); _inputDevice->_axisStateMap[_inputDevice->makeInput(TOUCH_AXIS_X_NEG).getChannel()].value = (currentMove.x < 0 ? -currentMove.x : 0.0f); // Y mouse is inverted positive is pointing up the screen diff --git a/libraries/input-plugins/src/input-plugins/TouchscreenDevice.cpp b/libraries/input-plugins/src/input-plugins/TouchscreenDevice.cpp index 804ab3585b..807d7f0ef9 100644 --- a/libraries/input-plugins/src/input-plugins/TouchscreenDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/TouchscreenDevice.cpp @@ -38,7 +38,6 @@ void TouchscreenDevice::pluginUpdate(float deltaTime, const controller::InputCal _inputDevice->update(deltaTime, inputCalibrationData); }); - // ####### TODO: Use AxisValue timestamp fields? float distanceScaleX, distanceScaleY; if (_touchPointCount == 1) { if (_firstTouchVec.x < _currentTouchVec.x) { From 14d39d174756145377c6af6dba275b9dce40ab46 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 3 Jan 2019 15:53:37 +1300 Subject: [PATCH 10/11] Make mouselook yaw and pitch directly proportional to mouse movement --- .../resources/controllers/keyboardMouse.json | 25 ++++++++----------- interface/src/Application.cpp | 2 ++ interface/src/avatar/MyAvatar.cpp | 6 +++-- interface/src/avatar/MyAvatar.h | 2 ++ .../controllers/src/controllers/Actions.cpp | 17 ++++++++++--- .../controllers/src/controllers/Actions.h | 4 +++ 6 files changed, 35 insertions(+), 21 deletions(-) diff --git a/interface/resources/controllers/keyboardMouse.json b/interface/resources/controllers/keyboardMouse.json index 2ad07911c6..74c11203ef 100644 --- a/interface/resources/controllers/keyboardMouse.json +++ b/interface/resources/controllers/keyboardMouse.json @@ -123,7 +123,16 @@ { "from": { "makeAxis" : ["Keyboard.MouseMoveLeft", "Keyboard.MouseMoveRight"] }, "when": "Keyboard.RightMouseButton", - "to": "Actions.Yaw", + "to": "Actions.DeltaYaw", + "filters": + [ + { "type": "scale", "scale": 0.6 } + ] + }, + + { "from": { "makeAxis" : ["Keyboard.MouseMoveUp", "Keyboard.MouseMoveDown"] }, + "when": "Keyboard.RightMouseButton", + "to": "Actions.DeltaPitch", "filters": [ { "type": "scale", "scale": 0.6 } @@ -144,20 +153,6 @@ { "from": "Keyboard.PgDown", "to": "Actions.VERTICAL_DOWN" }, { "from": "Keyboard.PgUp", "to": "Actions.VERTICAL_UP" }, - { "from": "Keyboard.MouseMoveUp", "when": "Keyboard.RightMouseButton", "to": "Actions.PITCH_UP", - "filters": - [ - { "type": "scale", "scale": 0.6 } - ] - - }, - { "from": "Keyboard.MouseMoveDown", "when": "Keyboard.RightMouseButton", "to": "Actions.PITCH_DOWN", - "filters": - [ - { "type": "scale", "scale": 0.6 } - ] - }, - { "from": "Keyboard.TouchpadDown", "to": "Actions.PITCH_DOWN" }, { "from": "Keyboard.TouchpadUp", "to": "Actions.PITCH_UP" }, diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a5c1ad6cf0..dfd9873352 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5970,6 +5970,8 @@ void Application::update(float deltaTime) { if (deltaTime > FLT_EPSILON) { myAvatar->setDriveKey(MyAvatar::PITCH, -1.0f * userInputMapper->getActionState(controller::Action::PITCH)); myAvatar->setDriveKey(MyAvatar::YAW, -1.0f * userInputMapper->getActionState(controller::Action::YAW)); + myAvatar->setDriveKey(MyAvatar::DELTA_PITCH, -1.0f * userInputMapper->getActionState(controller::Action::DELTA_PITCH)); + myAvatar->setDriveKey(MyAvatar::DELTA_YAW, -1.0f * userInputMapper->getActionState(controller::Action::DELTA_YAW)); myAvatar->setDriveKey(MyAvatar::STEP_YAW, -1.0f * userInputMapper->getActionState(controller::Action::STEP_YAW)); } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 397817cf60..50e4ad8b9d 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2696,9 +2696,10 @@ void MyAvatar::updateOrientation(float deltaTime) { _bodyYawDelta = 0.0f; } } - float totalBodyYaw = _bodyYawDelta * deltaTime; + // Rotate directly proportional to delta yaw and delta pitch from right-click mouse movement. + totalBodyYaw += getDriveKey(DELTA_YAW) * _yawSpeed / YAW_SPEED_DEFAULT; // Comfort Mode: If you press any of the left/right rotation drive keys or input, you'll // get an instantaneous 15 degree turn. If you keep holding the key down you'll get another @@ -2766,7 +2767,8 @@ void MyAvatar::updateOrientation(float deltaTime) { head->setBaseRoll(ROLL(euler)); } else { head->setBaseYaw(0.0f); - head->setBasePitch(getHead()->getBasePitch() + getDriveKey(PITCH) * _pitchSpeed * deltaTime); + head->setBasePitch(getHead()->getBasePitch() + getDriveKey(PITCH) * _pitchSpeed * deltaTime + + getDriveKey(DELTA_PITCH) * _pitchSpeed / PITCH_SPEED_DEFAULT); head->setBaseRoll(0.0f); } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index b2381366bb..134aca645c 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -264,6 +264,8 @@ public: STEP_YAW, PITCH, ZOOM, + DELTA_YAW, + DELTA_PITCH, MAX_DRIVE_KEYS }; Q_ENUM(DriveKeys) diff --git a/libraries/controllers/src/controllers/Actions.cpp b/libraries/controllers/src/controllers/Actions.cpp index 6923ef4b98..5a396231b6 100644 --- a/libraries/controllers/src/controllers/Actions.cpp +++ b/libraries/controllers/src/controllers/Actions.cpp @@ -52,11 +52,17 @@ namespace controller { * TranslateZnumbernumberMove the user's avatar in the direction of its * z-axis, if the camera isn't in independent or mirror modes. * PitchnumbernumberRotate the user's avatar head and attached camera - * about its negative x-axis (i.e., positive values pitch down), if the camera isn't in HMD, independent, or mirror - * modes. - * YawnumbernumberRotate the user's avatar about its y-axis, if the - * camera isn't in independent or mirror modes. + * about its negative x-axis (i.e., positive values pitch down) at a rate proportional to the control value, if the + * camera isn't in HMD, independent, or mirror modes. + * YawnumbernumberRotate the user's avatar about its y-axis at a rate + * proportional to the control value, if the camera isn't in independent or mirror modes. * RollnumbernumberNo action. + * DeltaPitchnumbernumberRotate the user's avatar head and attached + * camera about its negative x-axis (i.e., positive values pitch down) by an amount proportional to the control value, + * if the camera isn't in HMD, independent, or mirror modes. + * DeltaYawnumbernumberRotate the user's avatar about its y-axis by an + * amount proportional to the control value, if the camera isn't in independent or mirror modes. + * DeltaRollnumbernumberNo action. * StepTranslateXnumbernumberNo action. * StepTranslateYnumbernumberNo action. * StepTranslateZnumbernumberNo action. @@ -318,6 +324,9 @@ namespace controller { makeAxisPair(Action::ROLL, "Roll"), makeAxisPair(Action::PITCH, "Pitch"), makeAxisPair(Action::YAW, "Yaw"), + makeAxisPair(Action::DELTA_YAW, "DeltaYaw"), + makeAxisPair(Action::DELTA_PITCH, "DeltaPitch"), + makeAxisPair(Action::DELTA_ROLL, "DeltaRoll"), makeAxisPair(Action::STEP_YAW, "StepYaw"), makeAxisPair(Action::STEP_PITCH, "StepPitch"), makeAxisPair(Action::STEP_ROLL, "StepRoll"), diff --git a/libraries/controllers/src/controllers/Actions.h b/libraries/controllers/src/controllers/Actions.h index 0c77d63863..a12a3d60a9 100644 --- a/libraries/controllers/src/controllers/Actions.h +++ b/libraries/controllers/src/controllers/Actions.h @@ -27,6 +27,10 @@ enum class Action { ROTATE_Y, YAW = ROTATE_Y, ROTATE_Z, ROLL = ROTATE_Z, + DELTA_PITCH, + DELTA_YAW, + DELTA_ROLL, + STEP_YAW, // FIXME does this have a use case? STEP_PITCH, From 683e63346964197b77aa57ed0c627305d37032b1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 8 Jan 2019 09:18:53 +1300 Subject: [PATCH 11/11] Fix play back of input recording's numeric values --- .../controllers/src/controllers/InputRecorder.cpp | 7 +++++++ .../controllers/src/controllers/InputRecorder.h | 1 + .../src/controllers/UserInputMapper.cpp | 15 +++++++++++++++ .../controllers/impl/endpoints/ActionEndpoint.cpp | 9 +++------ 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/libraries/controllers/src/controllers/InputRecorder.cpp b/libraries/controllers/src/controllers/InputRecorder.cpp index 54d1aaf131..928dbf0521 100644 --- a/libraries/controllers/src/controllers/InputRecorder.cpp +++ b/libraries/controllers/src/controllers/InputRecorder.cpp @@ -297,6 +297,13 @@ namespace controller { return 0.0f; } + InputRecorder::ActionStates InputRecorder::getActionstates() { + if (_actionStateList.size() > 0) { + return _actionStateList[_playCount]; + } + return {}; + } + controller::Pose InputRecorder::getPoseState(const QString& action) { if (_poseStateList.size() > 0) { return _poseStateList[_playCount][action]; diff --git a/libraries/controllers/src/controllers/InputRecorder.h b/libraries/controllers/src/controllers/InputRecorder.h index 9adb8e386f..a0fcb2e87e 100644 --- a/libraries/controllers/src/controllers/InputRecorder.h +++ b/libraries/controllers/src/controllers/InputRecorder.h @@ -45,6 +45,7 @@ namespace controller { void setActionState(const QString& action, float value); void setActionState(const QString& action, const controller::Pose& pose); float getActionState(const QString& action); + ActionStates getActionstates(); controller::Pose getPoseState(const QString& action); QString getSaveDirectory(); void frameTick(); diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index e8503d8d1e..33dc37312e 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -489,6 +489,21 @@ void UserInputMapper::runMappings() { } applyRoutes(_standardRoutes); + InputRecorder* inputRecorder = InputRecorder::getInstance(); + if (inputRecorder->isPlayingback()) { + if (debugRoutes) { + qCDebug(controllers) << "Playing back recording actions"; + } + + // Play back each numeric action even if there is no current route active for the action. + auto actionStates = inputRecorder->getActionstates(); + for (InputRecorder::ActionStates::iterator it = actionStates.begin(); it != actionStates.end(); ++it) { + setActionState((Action)findAction(it->first), it->second); + } + + // Poses are played back in StandardEndpoint. + } + if (debugRoutes) { qCDebug(controllers) << "Done with mappings"; } diff --git a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp index 122af5a30c..58744c468c 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.cpp @@ -18,19 +18,16 @@ using namespace controller; void ActionEndpoint::apply(AxisValue newValue, const Pointer& source) { auto userInputMapper = DependencyManager::get(); InputRecorder* inputRecorder = InputRecorder::getInstance(); - QString actionName; if (inputRecorder->isPlayingback() || inputRecorder->isRecording()) { - actionName = userInputMapper->getActionName(Action(_input.getChannel())); - if (inputRecorder->isPlayingback()) { - newValue = AxisValue(inputRecorder->getActionState(actionName), 0); - } + QString actionName = userInputMapper->getActionName(Action(_input.getChannel())); + inputRecorder->setActionState(actionName, newValue.value); } _currentValue.value += newValue.value; + if (_input != Input::INVALID_INPUT) { userInputMapper->deltaActionState(Action(_input.getChannel()), newValue.value); } - inputRecorder->setActionState(actionName, newValue.value); } void ActionEndpoint::apply(const Pose& value, const Pointer& source) {