mirror of
https://github.com/overte-org/overte.git
synced 2025-04-16 11:50:45 +02:00
Merge pull request #6300 from jherico/lisa
Breaking up InputDevices and InputPlugins, cleanup of some shared_ptr madness
This commit is contained in:
commit
143e92ee1b
17 changed files with 371 additions and 264 deletions
|
@ -653,7 +653,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
userInputMapper->registerDevice(_applicationStateDevice);
|
||||
|
||||
// Setup the keyboardMouseDevice and the user input mapper with the default bindings
|
||||
userInputMapper->registerDevice(_keyboardMouseDevice);
|
||||
userInputMapper->registerDevice(_keyboardMouseDevice->getInputDevice());
|
||||
|
||||
|
||||
userInputMapper->loadDefaultMapping(userInputMapper->getStandardDeviceID());
|
||||
|
@ -729,8 +729,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
// Now that menu is initalized we can sync myAvatar with it's state.
|
||||
getMyAvatar()->updateMotionBehaviorFromMenu();
|
||||
|
||||
// FIXME spacemouse code still needs cleanup
|
||||
#if 0
|
||||
// the 3Dconnexion device wants to be initiliazed after a window is displayed.
|
||||
SpacemouseManager::getInstance().init();
|
||||
#endif
|
||||
|
||||
auto& packetReceiver = nodeList->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::DomainConnectionDenied, this, "handleDomainConnectionDeniedPacket");
|
||||
|
@ -1850,9 +1853,12 @@ void Application::focusOutEvent(QFocusEvent* event) {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME spacemouse code still needs cleanup
|
||||
#if 0
|
||||
//SpacemouseDevice::getInstance().focusOutEvent();
|
||||
//SpacemouseManager::getInstance().getDevice()->focusOutEvent();
|
||||
SpacemouseManager::getInstance().ManagerFocusOutEvent();
|
||||
#endif
|
||||
|
||||
// synthesize events for keys currently pressed, since we may not get their release events
|
||||
foreach (int key, _keysPressed) {
|
||||
|
|
|
@ -465,8 +465,6 @@ Menu::Menu() {
|
|||
avatar, SLOT(setEnableMeshVisible(bool)));
|
||||
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false);
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::Connexion, 0, false, &SpacemouseManager::getInstance(), SLOT(toggleSpacemouse(bool)));
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ComfortMode, 0, true);
|
||||
|
||||
MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
|
||||
|
|
11
libraries/display-plugins/src/display-plugins/Logging.cpp
Normal file
11
libraries/display-plugins/src/display-plugins/Logging.cpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/11
|
||||
// Copyright 2015 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 "Logging.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(displayPlugins, "hifi.plugins.display")
|
16
libraries/display-plugins/src/display-plugins/Logging.h
Normal file
16
libraries/display-plugins/src/display-plugins/Logging.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis 2015/10/11
|
||||
// Copyright 2015 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
|
||||
//
|
||||
|
||||
#ifndef hifi_DisplayPlugins_Logging_h
|
||||
#define hifi_DisplayPlugins_Logging_h
|
||||
|
||||
#include <QLoggingCategory>
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(displayPlugins)
|
||||
|
||||
#endif
|
|
@ -37,8 +37,6 @@ const QString & OpenVrDisplayPlugin::getName() const {
|
|||
return NAME;
|
||||
}
|
||||
|
||||
vr::IVRSystem* _hmd{ nullptr };
|
||||
int hmdRefCount = 0;
|
||||
static vr::IVRCompositor* _compositor{ nullptr };
|
||||
vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
||||
mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount];
|
||||
|
@ -78,24 +76,17 @@ mat4 toGlm(const vr::HmdMatrix34_t& m) {
|
|||
}
|
||||
|
||||
bool OpenVrDisplayPlugin::isSupported() const {
|
||||
bool success = vr::VR_IsHmdPresent();
|
||||
if (success) {
|
||||
vr::HmdError eError = vr::HmdError_None;
|
||||
auto hmd = vr::VR_Init(&eError);
|
||||
success = (hmd != nullptr);
|
||||
vr::VR_Shutdown();
|
||||
}
|
||||
auto hmd = acquireOpenVrSystem();
|
||||
bool success = nullptr != hmd;
|
||||
releaseOpenVrSystem();
|
||||
return success;
|
||||
}
|
||||
|
||||
void OpenVrDisplayPlugin::activate() {
|
||||
_container->setIsOptionChecked(StandingHMDSensorMode, true);
|
||||
|
||||
hmdRefCount++;
|
||||
vr::HmdError eError = vr::HmdError_None;
|
||||
if (!_hmd) {
|
||||
_hmd = vr::VR_Init(&eError);
|
||||
Q_ASSERT(eError == vr::HmdError_None);
|
||||
_hmd = acquireOpenVrSystem();
|
||||
}
|
||||
Q_ASSERT(_hmd);
|
||||
|
||||
|
@ -114,6 +105,7 @@ void OpenVrDisplayPlugin::activate() {
|
|||
});
|
||||
|
||||
|
||||
vr::HmdError eError = vr::HmdError_None;
|
||||
_compositor = (vr::IVRCompositor*)vr::VR_GetGenericInterface(vr::IVRCompositor_Version, &eError);
|
||||
Q_ASSERT(eError == vr::HmdError_None);
|
||||
Q_ASSERT(_compositor);
|
||||
|
@ -133,11 +125,8 @@ void OpenVrDisplayPlugin::activate() {
|
|||
|
||||
void OpenVrDisplayPlugin::deactivate() {
|
||||
_container->setIsOptionChecked(StandingHMDSensorMode, false);
|
||||
|
||||
hmdRefCount--;
|
||||
|
||||
if (hmdRefCount == 0 && _hmd) {
|
||||
vr::VR_Shutdown();
|
||||
if (_hmd) {
|
||||
releaseOpenVrSystem();
|
||||
_hmd = nullptr;
|
||||
}
|
||||
_compositor = nullptr;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <QtGlobal>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <openvr.h>
|
||||
|
||||
#include "../WindowOpenGLDisplayPlugin.h"
|
||||
|
||||
|
@ -39,6 +40,7 @@ protected:
|
|||
virtual void finishFrame() override;
|
||||
|
||||
private:
|
||||
vr::IVRSystem* _hmd { nullptr };
|
||||
static const QString NAME;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/11/01
|
||||
// Copyright 2015 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 "OpenVrHelpers.h"
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
#include "../Logging.h"
|
||||
|
||||
using Mutex = std::mutex;
|
||||
using Lock = std::unique_lock<Mutex>;
|
||||
|
||||
static int refCount { 0 };
|
||||
static Mutex mutex;
|
||||
static vr::IVRSystem* activeHmd { nullptr };
|
||||
static bool hmdPresent = vr::VR_IsHmdPresent();
|
||||
|
||||
static const uint32_t RELEASE_OPENVR_HMD_DELAY_MS = 5000;
|
||||
|
||||
vr::IVRSystem* acquireOpenVrSystem() {
|
||||
if (hmdPresent) {
|
||||
Lock lock(mutex);
|
||||
if (!activeHmd) {
|
||||
qCDebug(displayPlugins) << "openvr: No vr::IVRSystem instance active, building";
|
||||
vr::HmdError eError = vr::HmdError_None;
|
||||
activeHmd = vr::VR_Init(&eError);
|
||||
qCDebug(displayPlugins) << "openvr display: HMD is " << activeHmd << " error is " << eError;
|
||||
}
|
||||
if (activeHmd) {
|
||||
qCDebug(displayPlugins) << "openvr: incrementing refcount";
|
||||
++refCount;
|
||||
}
|
||||
}
|
||||
return activeHmd;
|
||||
}
|
||||
|
||||
void releaseOpenVrSystem() {
|
||||
if (activeHmd) {
|
||||
Lock lock(mutex);
|
||||
qDebug() << "openvr: decrementing refcount";
|
||||
--refCount;
|
||||
if (0 == refCount) {
|
||||
qDebug() << "openvr: zero refcount, deallocate VR system";
|
||||
// Avoid spamming the VR system with activate/deactivate calls at system startup by
|
||||
// putting in a delay before we destory the shutdown the VR subsystem
|
||||
|
||||
// FIXME releasing the VR system at all seems to trigger an exception deep inside the Oculus DLL.
|
||||
// disabling for now.
|
||||
//QTimer* releaseTimer = new QTimer();
|
||||
//releaseTimer->singleShot(RELEASE_OPENVR_HMD_DELAY_MS, [releaseTimer] {
|
||||
// Lock lock(mutex);
|
||||
// qDebug() << "Delayed openvr destroy activated";
|
||||
// if (0 == refCount && nullptr != activeHmd) {
|
||||
// qDebug() << "Delayed openvr destroy: releasing resources";
|
||||
// activeHmd = nullptr;
|
||||
// vr::VR_Shutdown();
|
||||
// } else {
|
||||
// qDebug() << "Delayed openvr destroy: HMD still in use";
|
||||
// }
|
||||
// releaseTimer->deleteLater();
|
||||
//});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -7,10 +7,16 @@
|
|||
//
|
||||
#pragma once
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <openvr.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
vr::IVRSystem* acquireOpenVrSystem();
|
||||
void releaseOpenVrSystem();
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
const QString KeyboardMouseDevice::NAME = "Keyboard/Mouse";
|
||||
|
||||
void KeyboardMouseDevice::update(float deltaTime, bool jointsCaptured) {
|
||||
_axisStateMap.clear();
|
||||
void KeyboardMouseDevice::pluginUpdate(float deltaTime, bool jointsCaptured) {
|
||||
_inputDevice->update(deltaTime, jointsCaptured);
|
||||
|
||||
// For touch event, we need to check that the last event is not too long ago
|
||||
// Maybe it's a Qt issue, but the touch event sequence (begin, update, end) is not always called properly
|
||||
|
@ -35,26 +35,30 @@ void KeyboardMouseDevice::update(float deltaTime, bool jointsCaptured) {
|
|||
}
|
||||
}
|
||||
|
||||
void KeyboardMouseDevice::focusOutEvent() {
|
||||
void KeyboardMouseDevice::InputDevice::update(float deltaTime, bool jointsCaptured) {
|
||||
_axisStateMap.clear();
|
||||
}
|
||||
|
||||
void KeyboardMouseDevice::InputDevice::focusOutEvent() {
|
||||
_buttonPressedMap.clear();
|
||||
};
|
||||
}
|
||||
|
||||
void KeyboardMouseDevice::keyPressEvent(QKeyEvent* event) {
|
||||
auto input = makeInput((Qt::Key) event->key());
|
||||
auto result = _buttonPressedMap.insert(input.getChannel());
|
||||
auto input = _inputDevice->makeInput((Qt::Key) event->key());
|
||||
auto result = _inputDevice->_buttonPressedMap.insert(input.getChannel());
|
||||
if (!result.second) {
|
||||
// key pressed again ? without catching the release event ?
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardMouseDevice::keyReleaseEvent(QKeyEvent* event) {
|
||||
auto input = makeInput((Qt::Key) event->key());
|
||||
_buttonPressedMap.erase(input.getChannel());
|
||||
auto input = _inputDevice->makeInput((Qt::Key) event->key());
|
||||
_inputDevice->_buttonPressedMap.erase(input.getChannel());
|
||||
}
|
||||
|
||||
void KeyboardMouseDevice::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
auto input = makeInput((Qt::MouseButton) event->button());
|
||||
auto result = _buttonPressedMap.insert(input.getChannel());
|
||||
auto input = _inputDevice->makeInput((Qt::MouseButton) event->button());
|
||||
auto result = _inputDevice->_buttonPressedMap.insert(input.getChannel());
|
||||
if (!result.second) {
|
||||
// key pressed again ? without catching the release event ?
|
||||
}
|
||||
|
@ -65,32 +69,32 @@ void KeyboardMouseDevice::mousePressEvent(QMouseEvent* event, unsigned int devic
|
|||
}
|
||||
|
||||
void KeyboardMouseDevice::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
auto input = makeInput((Qt::MouseButton) event->button());
|
||||
_buttonPressedMap.erase(input.getChannel());
|
||||
auto input = _inputDevice->makeInput((Qt::MouseButton) event->button());
|
||||
_inputDevice->_buttonPressedMap.erase(input.getChannel());
|
||||
|
||||
// if we pressed and released at the same location, then create a "_CLICKED" input for this button
|
||||
// we might want to add some small tolerance to this so if you do a small drag it still counts as
|
||||
// a clicked.
|
||||
if (_mousePressAt == event->pos()) {
|
||||
_buttonPressedMap.insert(makeInput((Qt::MouseButton) event->button(), true).getChannel());
|
||||
_inputDevice->_buttonPressedMap.insert(_inputDevice->makeInput((Qt::MouseButton) event->button(), true).getChannel());
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardMouseDevice::eraseMouseClicked() {
|
||||
_buttonPressedMap.erase(makeInput(Qt::LeftButton, true).getChannel());
|
||||
_buttonPressedMap.erase(makeInput(Qt::MiddleButton, true).getChannel());
|
||||
_buttonPressedMap.erase(makeInput(Qt::RightButton, true).getChannel());
|
||||
_inputDevice->_buttonPressedMap.erase(_inputDevice->makeInput(Qt::LeftButton, true).getChannel());
|
||||
_inputDevice->_buttonPressedMap.erase(_inputDevice->makeInput(Qt::MiddleButton, true).getChannel());
|
||||
_inputDevice->_buttonPressedMap.erase(_inputDevice->makeInput(Qt::RightButton, true).getChannel());
|
||||
}
|
||||
|
||||
void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
QPoint currentPos = event->pos();
|
||||
QPoint currentMove = currentPos - _lastCursor;
|
||||
|
||||
_axisStateMap[makeInput(MOUSE_AXIS_X_POS).getChannel()] = (currentMove.x() > 0 ? currentMove.x() : 0.0f);
|
||||
_axisStateMap[makeInput(MOUSE_AXIS_X_NEG).getChannel()] = (currentMove.x() < 0 ? -currentMove.x() : 0.0f);
|
||||
_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
|
||||
_axisStateMap[makeInput(MOUSE_AXIS_Y_POS).getChannel()] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f);
|
||||
_axisStateMap[makeInput(MOUSE_AXIS_Y_NEG).getChannel()] = (currentMove.y() > 0 ? currentMove.y() : 0.0f);
|
||||
_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);
|
||||
|
||||
_lastCursor = currentPos;
|
||||
|
||||
|
@ -100,10 +104,10 @@ void KeyboardMouseDevice::mouseMoveEvent(QMouseEvent* event, unsigned int device
|
|||
void KeyboardMouseDevice::wheelEvent(QWheelEvent* event) {
|
||||
auto currentMove = event->angleDelta() / 120.0f;
|
||||
|
||||
_axisStateMap[makeInput(MOUSE_AXIS_WHEEL_X_POS).getChannel()] = (currentMove.x() > 0 ? currentMove.x() : 0.0f);
|
||||
_axisStateMap[makeInput(MOUSE_AXIS_WHEEL_X_NEG).getChannel()] = (currentMove.x() < 0 ? -currentMove.x() : 0.0f);
|
||||
_axisStateMap[makeInput(MOUSE_AXIS_WHEEL_Y_POS).getChannel()] = (currentMove.y() > 0 ? currentMove.y() : 0.0f);
|
||||
_axisStateMap[makeInput(MOUSE_AXIS_WHEEL_Y_NEG).getChannel()] = (currentMove.y() < 0 ? -currentMove.y() : 0.0f);
|
||||
_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);
|
||||
}
|
||||
|
||||
glm::vec2 evalAverageTouchPoints(const QList<QTouchEvent::TouchPoint>& points) {
|
||||
|
@ -138,17 +142,17 @@ void KeyboardMouseDevice::touchUpdateEvent(const QTouchEvent* event) {
|
|||
} else {
|
||||
auto currentMove = currentPos - _lastTouch;
|
||||
|
||||
_axisStateMap[makeInput(TOUCH_AXIS_X_POS).getChannel()] = (currentMove.x > 0 ? currentMove.x : 0.0f);
|
||||
_axisStateMap[makeInput(TOUCH_AXIS_X_NEG).getChannel()] = (currentMove.x < 0 ? -currentMove.x : 0.0f);
|
||||
_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);
|
||||
// Y mouse is inverted positive is pointing up the screen
|
||||
_axisStateMap[makeInput(TOUCH_AXIS_Y_POS).getChannel()] = (currentMove.y < 0 ? -currentMove.y : 0.0f);
|
||||
_axisStateMap[makeInput(TOUCH_AXIS_Y_NEG).getChannel()] = (currentMove.y > 0 ? currentMove.y : 0.0f);
|
||||
_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);
|
||||
}
|
||||
|
||||
_lastTouch = currentPos;
|
||||
}
|
||||
|
||||
controller::Input KeyboardMouseDevice::makeInput(Qt::Key code) const {
|
||||
controller::Input KeyboardMouseDevice::InputDevice::makeInput(Qt::Key code) const {
|
||||
auto shortCode = (uint16_t)(code & KEYBOARD_MASK);
|
||||
if (shortCode != code) {
|
||||
shortCode |= 0x0800; // add this bit instead of the way Qt::Key add a bit on the 3rd byte for some keys
|
||||
|
@ -156,7 +160,7 @@ controller::Input KeyboardMouseDevice::makeInput(Qt::Key code) const {
|
|||
return controller::Input(_deviceID, shortCode, controller::ChannelType::BUTTON);
|
||||
}
|
||||
|
||||
controller::Input KeyboardMouseDevice::makeInput(Qt::MouseButton code, bool clicked) const {
|
||||
controller::Input KeyboardMouseDevice::InputDevice::makeInput(Qt::MouseButton code, bool clicked) const {
|
||||
switch (code) {
|
||||
case Qt::LeftButton:
|
||||
return controller::Input(_deviceID, clicked ? MOUSE_BUTTON_LEFT_CLICKED :
|
||||
|
@ -172,19 +176,19 @@ controller::Input KeyboardMouseDevice::makeInput(Qt::MouseButton code, bool clic
|
|||
};
|
||||
}
|
||||
|
||||
controller::Input KeyboardMouseDevice::makeInput(KeyboardMouseDevice::MouseAxisChannel axis) const {
|
||||
controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevice::MouseAxisChannel axis) const {
|
||||
return controller::Input(_deviceID, axis, controller::ChannelType::AXIS);
|
||||
}
|
||||
|
||||
controller::Input KeyboardMouseDevice::makeInput(KeyboardMouseDevice::TouchAxisChannel axis) const {
|
||||
controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevice::TouchAxisChannel axis) const {
|
||||
return controller::Input(_deviceID, axis, controller::ChannelType::AXIS);
|
||||
}
|
||||
|
||||
controller::Input KeyboardMouseDevice::makeInput(KeyboardMouseDevice::TouchButtonChannel button) const {
|
||||
controller::Input KeyboardMouseDevice::InputDevice::makeInput(KeyboardMouseDevice::TouchButtonChannel button) const {
|
||||
return controller::Input(_deviceID, button, controller::ChannelType::BUTTON);
|
||||
}
|
||||
|
||||
controller::Input::NamedVector KeyboardMouseDevice::getAvailableInputs() const {
|
||||
controller::Input::NamedVector KeyboardMouseDevice::InputDevice::getAvailableInputs() const {
|
||||
using namespace controller;
|
||||
static QVector<Input::NamedPair> availableInputs;
|
||||
static std::once_flag once;
|
||||
|
@ -229,7 +233,7 @@ controller::Input::NamedVector KeyboardMouseDevice::getAvailableInputs() const {
|
|||
return availableInputs;
|
||||
}
|
||||
|
||||
QString KeyboardMouseDevice::getDefaultMappingConfig() const {
|
||||
QString KeyboardMouseDevice::InputDevice::getDefaultMappingConfig() const {
|
||||
static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/keyboardMouse.json";
|
||||
return MAPPING_JSON;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ class QKeyEvent;
|
|||
class QMouseEvent;
|
||||
class QWheelEvent;
|
||||
|
||||
class KeyboardMouseDevice : public InputPlugin, public controller::InputDevice {
|
||||
class KeyboardMouseDevice : public InputPlugin {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum KeyboardChannel {
|
||||
|
@ -64,22 +64,14 @@ public:
|
|||
TOUCH_BUTTON_PRESS = TOUCH_AXIS_Y_NEG + 1,
|
||||
};
|
||||
|
||||
KeyboardMouseDevice() : InputDevice("Keyboard") {}
|
||||
|
||||
// Plugin functions
|
||||
virtual bool isSupported() const override { return true; }
|
||||
virtual bool isJointController() const override { return false; }
|
||||
const QString& getName() const override { return NAME; }
|
||||
|
||||
virtual void pluginFocusOutEvent() override { focusOutEvent(); }
|
||||
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); }
|
||||
virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); }
|
||||
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override;
|
||||
|
||||
// Device functions
|
||||
virtual controller::Input::NamedVector getAvailableInputs() const override;
|
||||
virtual QString getDefaultMappingConfig() const override;
|
||||
virtual void update(float deltaTime, bool jointsCaptured) override;
|
||||
virtual void focusOutEvent() override;
|
||||
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
void keyReleaseEvent(QKeyEvent* event);
|
||||
|
||||
|
@ -94,21 +86,40 @@ public:
|
|||
|
||||
void wheelEvent(QWheelEvent* event);
|
||||
|
||||
// Let's make it easy for Qt because we assume we love Qt forever
|
||||
controller::Input makeInput(Qt::Key code) const;
|
||||
controller::Input makeInput(Qt::MouseButton code, bool clicked = false) const;
|
||||
controller::Input makeInput(MouseAxisChannel axis) const;
|
||||
controller::Input makeInput(TouchAxisChannel axis) const;
|
||||
controller::Input makeInput(TouchButtonChannel button) const;
|
||||
|
||||
static const QString NAME;
|
||||
|
||||
protected:
|
||||
|
||||
class InputDevice : public controller::InputDevice {
|
||||
public:
|
||||
InputDevice() : controller::InputDevice("Keyboard") {}
|
||||
private:
|
||||
// Device functions
|
||||
virtual controller::Input::NamedVector getAvailableInputs() const override;
|
||||
virtual QString getDefaultMappingConfig() const override;
|
||||
virtual void update(float deltaTime, bool jointsCaptured) override;
|
||||
virtual void focusOutEvent() override;
|
||||
|
||||
// Let's make it easy for Qt because we assume we love Qt forever
|
||||
controller::Input makeInput(Qt::Key code) const;
|
||||
controller::Input makeInput(Qt::MouseButton code, bool clicked = false) const;
|
||||
controller::Input makeInput(MouseAxisChannel axis) const;
|
||||
controller::Input makeInput(TouchAxisChannel axis) const;
|
||||
controller::Input makeInput(TouchButtonChannel button) const;
|
||||
|
||||
friend class KeyboardMouseDevice;
|
||||
};
|
||||
|
||||
public:
|
||||
const std::shared_ptr<InputDevice>& getInputDevice() const { return _inputDevice; }
|
||||
|
||||
protected:
|
||||
QPoint _lastCursor;
|
||||
QPoint _mousePressAt;
|
||||
glm::vec2 _lastTouch;
|
||||
std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>() };
|
||||
|
||||
bool _isTouching = false;
|
||||
|
||||
std::chrono::high_resolution_clock _clock;
|
||||
std::chrono::high_resolution_clock::time_point _lastTouchTime;
|
||||
};
|
||||
|
|
|
@ -30,6 +30,11 @@
|
|||
|
||||
#ifdef HAVE_SIXENSE
|
||||
#include "sixense.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
static QLibrary* _sixenseLibrary { nullptr };
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// TODO: This should not be here
|
||||
|
@ -39,13 +44,10 @@ Q_LOGGING_CATEGORY(inputplugins, "hifi.inputplugins")
|
|||
|
||||
#ifdef HAVE_SIXENSE
|
||||
|
||||
const int CALIBRATION_STATE_IDLE = 0;
|
||||
const int CALIBRATION_STATE_IN_PROGRESS = 1;
|
||||
const int CALIBRATION_STATE_COMPLETE = 2;
|
||||
|
||||
const glm::vec3 DEFAULT_AVATAR_POSITION(-0.25f, -0.35f, -0.3f); // in hydra frame
|
||||
|
||||
const float CONTROLLER_THRESHOLD = 0.35f;
|
||||
const glm::vec3 SixenseManager::DEFAULT_AVATAR_POSITION { -0.25f, -0.35f, -0.3f }; // in hydra frame
|
||||
const float SixenseManager::CONTROLLER_THRESHOLD { 0.35f };
|
||||
const float SixenseManager::DEFAULT_REACH_LENGTH { 1.5f };
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -66,14 +68,6 @@ const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
|
|||
const QString TOGGLE_SMOOTH = "Smooth Sixense Movement";
|
||||
const float DEFAULT_REACH_LENGTH = 1.5f;
|
||||
|
||||
static std::shared_ptr<SixenseManager> instance;
|
||||
SixenseManager::SixenseManager() :
|
||||
InputDevice("Hydra"),
|
||||
_reachLength(DEFAULT_REACH_LENGTH)
|
||||
{
|
||||
instance = std::shared_ptr<SixenseManager>(this);
|
||||
}
|
||||
|
||||
bool SixenseManager::isSupported() const {
|
||||
#ifdef HAVE_SIXENSE
|
||||
|
||||
|
@ -91,8 +85,6 @@ bool SixenseManager::isSupported() const {
|
|||
void SixenseManager::activate() {
|
||||
InputPlugin::activate();
|
||||
#ifdef HAVE_SIXENSE
|
||||
_calibrationState = CALIBRATION_STATE_IDLE;
|
||||
_avatarPosition = DEFAULT_AVATAR_POSITION;
|
||||
|
||||
_container->addMenu(MENU_PATH);
|
||||
_container->addMenuItem(MENU_PATH, TOGGLE_SMOOTH,
|
||||
|
@ -100,7 +92,7 @@ void SixenseManager::activate() {
|
|||
true, true);
|
||||
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
userInputMapper->registerDevice(instance);
|
||||
userInputMapper->registerDevice(_inputDevice);
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
|
@ -139,12 +131,12 @@ void SixenseManager::deactivate() {
|
|||
_container->removeMenuItem(MENU_NAME, TOGGLE_SMOOTH);
|
||||
_container->removeMenu(MENU_PATH);
|
||||
|
||||
_poseStateMap.clear();
|
||||
_collectedSamples.clear();
|
||||
_inputDevice->_poseStateMap.clear();
|
||||
_inputDevice->_collectedSamples.clear();
|
||||
|
||||
if (_deviceID != controller::Input::INVALID_DEVICE) {
|
||||
if (_inputDevice->_deviceID != controller::Input::INVALID_DEVICE) {
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
userInputMapper->removeDevice(_deviceID);
|
||||
userInputMapper->removeDevice(_inputDevice->_deviceID);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
@ -170,7 +162,15 @@ void SixenseManager::setSixenseFilter(bool filter) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void SixenseManager::update(float deltaTime, bool jointsCaptured) {
|
||||
void SixenseManager::pluginUpdate(float deltaTime, bool jointsCaptured) {
|
||||
_inputDevice->update(deltaTime, jointsCaptured);
|
||||
if (_inputDevice->_calibrationState == CALIBRATION_STATE_COMPLETE) {
|
||||
_container->requestReset();
|
||||
_inputDevice->_calibrationState = CALIBRATION_STATE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) {
|
||||
// FIXME - Some of the code in update() will crash if you haven't actually activated the
|
||||
// plugin. But we want register with the UserInputMapper if we don't call this.
|
||||
// We need to clean this up.
|
||||
|
@ -297,7 +297,7 @@ const float MINIMUM_ARM_REACH = 0.3f; // meters
|
|||
const float MAXIMUM_NOISE_LEVEL = 0.05f; // meters
|
||||
const quint64 LOCK_DURATION = USECS_PER_SECOND / 4; // time for lock to be acquired
|
||||
|
||||
void SixenseManager::updateCalibration(void* controllersX) {
|
||||
void SixenseManager::InputDevice::updateCalibration(void* controllersX) {
|
||||
auto controllers = reinterpret_cast<sixenseControllerData*>(controllersX);
|
||||
const sixenseControllerData* dataLeft = controllers;
|
||||
const sixenseControllerData* dataRight = controllers + 1;
|
||||
|
@ -309,26 +309,25 @@ void SixenseManager::updateCalibration(void* controllersX) {
|
|||
}
|
||||
switch (_calibrationState) {
|
||||
case CALIBRATION_STATE_COMPLETE:
|
||||
{
|
||||
// compute calibration results
|
||||
_avatarPosition = - 0.5f * (_reachLeft + _reachRight); // neck is midway between right and left hands
|
||||
glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft);
|
||||
glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, Vectors::UNIT_Y));
|
||||
xAxis = glm::normalize(glm::cross(Vectors::UNIT_Y, zAxis));
|
||||
_reachLength = glm::dot(xAxis, _reachRight - _reachLeft);
|
||||
_avatarRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, Vectors::UNIT_Y, zAxis)));
|
||||
const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f;
|
||||
_avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR;
|
||||
_container->requestReset();
|
||||
qCDebug(inputplugins, "succeess: sixense calibration");
|
||||
}
|
||||
break;
|
||||
{
|
||||
// compute calibration results
|
||||
_avatarPosition = - 0.5f * (_reachLeft + _reachRight); // neck is midway between right and left hands
|
||||
glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft);
|
||||
glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, Vectors::UNIT_Y));
|
||||
xAxis = glm::normalize(glm::cross(Vectors::UNIT_Y, zAxis));
|
||||
_reachLength = glm::dot(xAxis, _reachRight - _reachLeft);
|
||||
_avatarRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, Vectors::UNIT_Y, zAxis)));
|
||||
const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f;
|
||||
_avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR;
|
||||
qCDebug(inputplugins, "succeess: sixense calibration");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_calibrationState = CALIBRATION_STATE_IDLE;
|
||||
qCDebug(inputplugins, "failed: sixense calibration");
|
||||
break;
|
||||
}
|
||||
|
||||
_calibrationState = CALIBRATION_STATE_IDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -382,15 +381,15 @@ void SixenseManager::updateCalibration(void* controllersX) {
|
|||
|
||||
#endif // HAVE_SIXENSE
|
||||
|
||||
void SixenseManager::focusOutEvent() {
|
||||
void SixenseManager::InputDevice::focusOutEvent() {
|
||||
_axisStateMap.clear();
|
||||
_buttonPressedMap.clear();
|
||||
};
|
||||
|
||||
void SixenseManager::handleAxisEvent(float stickX, float stickY, float trigger, bool left) {
|
||||
void SixenseManager::InputDevice::handleAxisEvent(float stickX, float stickY, float trigger, bool left) {
|
||||
}
|
||||
|
||||
void SixenseManager::handleButtonEvent(unsigned int buttons, bool left) {
|
||||
void SixenseManager::InputDevice::handleButtonEvent(unsigned int buttons, bool left) {
|
||||
using namespace controller;
|
||||
if (buttons & BUTTON_0) {
|
||||
_buttonPressedMap.insert(left ? BACK : START);
|
||||
|
@ -415,7 +414,7 @@ void SixenseManager::handleButtonEvent(unsigned int buttons, bool left) {
|
|||
}
|
||||
}
|
||||
|
||||
void SixenseManager::handlePoseEvent(float deltaTime, glm::vec3 position, glm::quat rotation, bool left) {
|
||||
void SixenseManager::InputDevice::handlePoseEvent(float deltaTime, glm::vec3 position, glm::quat rotation, bool left) {
|
||||
#ifdef HAVE_SIXENSE
|
||||
auto hand = left ? controller::StandardPoseChannel::LEFT_HAND : controller::StandardPoseChannel::RIGHT_HAND;
|
||||
|
||||
|
@ -521,7 +520,7 @@ static const auto R4 = controller::Y;
|
|||
|
||||
using namespace controller;
|
||||
|
||||
controller::Input::NamedVector SixenseManager::getAvailableInputs() const {
|
||||
controller::Input::NamedVector SixenseManager::InputDevice::getAvailableInputs() const {
|
||||
using namespace controller;
|
||||
static const Input::NamedVector availableInputs {
|
||||
makePair(L0, "L0"),
|
||||
|
@ -551,7 +550,7 @@ controller::Input::NamedVector SixenseManager::getAvailableInputs() const {
|
|||
};
|
||||
|
||||
|
||||
QString SixenseManager::getDefaultMappingConfig() const {
|
||||
QString SixenseManager::InputDevice::getDefaultMappingConfig() const {
|
||||
static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/hydra.json";
|
||||
return MAPPING_JSON;
|
||||
}
|
||||
|
@ -562,9 +561,9 @@ void SixenseManager::saveSettings() const {
|
|||
QString idString = getID();
|
||||
settings.beginGroup(idString);
|
||||
{
|
||||
settings.setVec3Value(QString("avatarPosition"), _avatarPosition);
|
||||
settings.setQuatValue(QString("avatarRotation"), _avatarRotation);
|
||||
settings.setValue(QString("reachLength"), QVariant(_reachLength));
|
||||
settings.setVec3Value(QString("avatarPosition"), _inputDevice->_avatarPosition);
|
||||
settings.setQuatValue(QString("avatarRotation"), _inputDevice->_avatarRotation);
|
||||
settings.setValue(QString("reachLength"), QVariant(_inputDevice->_reachLength));
|
||||
}
|
||||
settings.endGroup();
|
||||
}
|
||||
|
@ -574,9 +573,9 @@ void SixenseManager::loadSettings() {
|
|||
QString idString = getID();
|
||||
settings.beginGroup(idString);
|
||||
{
|
||||
settings.getVec3ValueIfValid(QString("avatarPosition"), _avatarPosition);
|
||||
settings.getQuatValueIfValid(QString("avatarRotation"), _avatarRotation);
|
||||
settings.getFloatValueIfValid(QString("reachLength"), _reachLength);
|
||||
settings.getVec3ValueIfValid(QString("avatarPosition"), _inputDevice->_avatarPosition);
|
||||
settings.getQuatValueIfValid(QString("avatarRotation"), _inputDevice->_avatarRotation);
|
||||
settings.getFloatValueIfValid(QString("reachLength"), _inputDevice->_reachLength);
|
||||
}
|
||||
settings.endGroup();
|
||||
}
|
||||
|
|
|
@ -44,11 +44,10 @@ const unsigned int BUTTON_TRIGGER = 1U << 8;
|
|||
const bool DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS = false;
|
||||
|
||||
// Handles interaction with the Sixense SDK (e.g., Razer Hydra).
|
||||
class SixenseManager : public InputPlugin, public controller::InputDevice {
|
||||
class SixenseManager : public InputPlugin {
|
||||
Q_OBJECT
|
||||
public:
|
||||
SixenseManager();
|
||||
|
||||
|
||||
// Plugin functions
|
||||
virtual bool isSupported() const override;
|
||||
virtual bool isJointController() const override { return true; }
|
||||
|
@ -58,15 +57,8 @@ public:
|
|||
virtual void activate() override;
|
||||
virtual void deactivate() override;
|
||||
|
||||
virtual void pluginFocusOutEvent() override { focusOutEvent(); }
|
||||
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); }
|
||||
|
||||
// Device functions
|
||||
virtual controller::Input::NamedVector getAvailableInputs() const override;
|
||||
virtual QString getDefaultMappingConfig() const override;
|
||||
|
||||
virtual void update(float deltaTime, bool jointsCaptured) override;
|
||||
virtual void focusOutEvent() override;
|
||||
virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); }
|
||||
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override;
|
||||
|
||||
virtual void saveSettings() const override;
|
||||
virtual void loadSettings() override;
|
||||
|
@ -75,38 +67,57 @@ public slots:
|
|||
void setSixenseFilter(bool filter);
|
||||
|
||||
private:
|
||||
void handleButtonEvent(unsigned int buttons, bool left);
|
||||
void handleAxisEvent(float x, float y, float trigger, bool left);
|
||||
void handlePoseEvent(float deltaTime, glm::vec3 position, glm::quat rotation, bool left);
|
||||
|
||||
void updateCalibration(void* controllers);
|
||||
|
||||
int _calibrationState;
|
||||
|
||||
// these are calibration results
|
||||
glm::vec3 _avatarPosition; // in hydra-frame
|
||||
glm::quat _avatarRotation; // in hydra-frame
|
||||
float _reachLength;
|
||||
|
||||
// these are measured values used to compute the calibration results
|
||||
quint64 _lockExpiry;
|
||||
glm::vec3 _averageLeft;
|
||||
glm::vec3 _averageRight;
|
||||
glm::vec3 _reachLeft;
|
||||
glm::vec3 _reachRight;
|
||||
float _lastDistance;
|
||||
bool _useSixenseFilter = true;
|
||||
|
||||
|
||||
static const int MAX_NUM_AVERAGING_SAMPLES = 50; // At ~100 updates per seconds this means averaging over ~.5s
|
||||
static const int CALIBRATION_STATE_IDLE = 0;
|
||||
static const int CALIBRATION_STATE_IN_PROGRESS = 1;
|
||||
static const int CALIBRATION_STATE_COMPLETE = 2;
|
||||
static const glm::vec3 DEFAULT_AVATAR_POSITION;
|
||||
static const float CONTROLLER_THRESHOLD;
|
||||
static const float DEFAULT_REACH_LENGTH;
|
||||
|
||||
|
||||
using Samples = std::pair< MovingAverage< glm::vec3, MAX_NUM_AVERAGING_SAMPLES>, MovingAverage< glm::vec4, MAX_NUM_AVERAGING_SAMPLES> >;
|
||||
using MovingAverageMap = std::map< int, Samples >;
|
||||
MovingAverageMap _collectedSamples;
|
||||
|
||||
#ifdef __APPLE__
|
||||
QLibrary* _sixenseLibrary { nullptr };
|
||||
#endif
|
||||
|
||||
class InputDevice : public controller::InputDevice {
|
||||
public:
|
||||
InputDevice() : controller::InputDevice("Hydra") {}
|
||||
private:
|
||||
// Device functions
|
||||
virtual controller::Input::NamedVector getAvailableInputs() const override;
|
||||
virtual QString getDefaultMappingConfig() const override;
|
||||
virtual void update(float deltaTime, bool jointsCaptured) override;
|
||||
virtual void focusOutEvent() override;
|
||||
|
||||
void handleButtonEvent(unsigned int buttons, bool left);
|
||||
void handleAxisEvent(float x, float y, float trigger, bool left);
|
||||
void handlePoseEvent(float deltaTime, glm::vec3 position, glm::quat rotation, bool left);
|
||||
void updateCalibration(void* controllers);
|
||||
|
||||
friend class SixenseManager;
|
||||
|
||||
MovingAverageMap _collectedSamples;
|
||||
|
||||
int _calibrationState { CALIBRATION_STATE_IDLE };
|
||||
// these are calibration results
|
||||
glm::vec3 _avatarPosition { DEFAULT_AVATAR_POSITION }; // in hydra-frame
|
||||
glm::quat _avatarRotation; // in hydra-frame
|
||||
|
||||
float _reachLength { DEFAULT_REACH_LENGTH };
|
||||
float _lastDistance;
|
||||
// these are measured values used to compute the calibration results
|
||||
quint64 _lockExpiry;
|
||||
glm::vec3 _averageLeft;
|
||||
glm::vec3 _averageRight;
|
||||
glm::vec3 _reachLeft;
|
||||
glm::vec3 _reachRight;
|
||||
};
|
||||
|
||||
|
||||
|
||||
bool _useSixenseFilter = true;
|
||||
std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>() };
|
||||
|
||||
static const QString NAME;
|
||||
static const QString HYDRA_ID_STRING;
|
||||
};
|
||||
|
|
|
@ -21,11 +21,10 @@
|
|||
|
||||
const float MAX_AXIS = 75.0f; // max forward = 2x speed
|
||||
|
||||
static std::shared_ptr<SpacemouseDevice> instance;
|
||||
SpacemouseDevice::SpacemouseDevice() :
|
||||
InputDevice("Spacemouse")
|
||||
static std::shared_ptr<SpacemouseDevice> instance = std::make_shared<SpacemouseDevice>();
|
||||
|
||||
SpacemouseDevice::SpacemouseDevice() : InputDevice("Spacemouse")
|
||||
{
|
||||
instance = std::shared_ptr<SpacemouseDevice>(this);
|
||||
}
|
||||
|
||||
void SpacemouseDevice::focusOutEvent() {
|
||||
|
@ -118,14 +117,6 @@ void SpacemouseDevice::update(float deltaTime, bool jointsCaptured) {
|
|||
// for osx the api will call DeviceAddedHandler or DeviceRemoveHandler when a 3Dconnexion device is attached or detached
|
||||
}
|
||||
|
||||
SpacemouseManager& SpacemouseManager::getInstance() {
|
||||
static SpacemouseManager sharedInstance;
|
||||
if (instance == nullptr) {
|
||||
new SpacemouseDevice();
|
||||
}
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
void SpacemouseManager::ManagerFocusOutEvent() {
|
||||
instance->focusOutEvent();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
class SpacemouseManager : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static SpacemouseManager& getInstance();
|
||||
void ManagerFocusOutEvent();
|
||||
void init();
|
||||
void destroy() {};
|
||||
|
@ -92,7 +91,6 @@ class SpacemouseManager : public QObject, public QAbstractNativeEventFilter {
|
|||
public:
|
||||
SpacemouseManager() {};
|
||||
|
||||
static SpacemouseManager& getInstance();
|
||||
void init();
|
||||
void destroy();
|
||||
bool Is3dmouseAttached();
|
||||
|
@ -169,7 +167,6 @@ private:
|
|||
class SpacemouseManager : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static SpacemouseManager& getInstance();
|
||||
void init();
|
||||
void destroy();
|
||||
bool Is3dmouseAttached();
|
||||
|
|
|
@ -27,12 +27,13 @@
|
|||
#include <controllers/StandardControls.h>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
extern vr::IVRSystem* _hmd;
|
||||
extern int hmdRefCount;
|
||||
extern vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount];
|
||||
extern mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount];
|
||||
#endif
|
||||
|
||||
vr::IVRSystem* acquireOpenVrSystem();
|
||||
void releaseOpenVrSystem();
|
||||
|
||||
|
||||
const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches
|
||||
const QString CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b";
|
||||
|
@ -44,28 +45,11 @@ const QString MENU_NAME = "Vive Controllers";
|
|||
const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
|
||||
const QString RENDER_CONTROLLERS = "Render Hand Controllers";
|
||||
|
||||
static std::shared_ptr<ViveControllerManager> instance;
|
||||
|
||||
ViveControllerManager::ViveControllerManager() :
|
||||
InputDevice("Vive"),
|
||||
_trackedControllers(0),
|
||||
_modelLoaded(false),
|
||||
_leftHandRenderID(0),
|
||||
_rightHandRenderID(0),
|
||||
_renderControllers(false)
|
||||
{
|
||||
instance = std::shared_ptr<ViveControllerManager>(this);
|
||||
}
|
||||
|
||||
bool ViveControllerManager::isSupported() const {
|
||||
#ifdef Q_OS_WIN
|
||||
bool success = vr::VR_IsHmdPresent();
|
||||
if (success) {
|
||||
vr::HmdError eError = vr::HmdError_None;
|
||||
auto hmd = vr::VR_Init(&eError);
|
||||
success = (hmd != nullptr);
|
||||
vr::VR_Shutdown();
|
||||
}
|
||||
auto hmd = acquireOpenVrSystem();
|
||||
bool success = hmd != nullptr;
|
||||
releaseOpenVrSystem();
|
||||
return success;
|
||||
#else
|
||||
return false;
|
||||
|
@ -80,11 +64,8 @@ void ViveControllerManager::activate() {
|
|||
[this] (bool clicked) { this->setRenderControllers(clicked); },
|
||||
true, true);
|
||||
|
||||
hmdRefCount++;
|
||||
if (!_hmd) {
|
||||
vr::HmdError eError = vr::HmdError_None;
|
||||
_hmd = vr::VR_Init(&eError);
|
||||
Q_ASSERT(eError == vr::HmdError_None);
|
||||
_hmd = acquireOpenVrSystem();
|
||||
}
|
||||
Q_ASSERT(_hmd);
|
||||
|
||||
|
@ -138,7 +119,7 @@ void ViveControllerManager::activate() {
|
|||
|
||||
// unregister with UserInputMapper
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
userInputMapper->registerDevice(instance);
|
||||
userInputMapper->registerDevice(_inputDevice);
|
||||
_registeredWithInputMapper = true;
|
||||
}
|
||||
|
||||
|
@ -149,18 +130,17 @@ void ViveControllerManager::deactivate() {
|
|||
_container->removeMenuItem(MENU_NAME, RENDER_CONTROLLERS);
|
||||
_container->removeMenu(MENU_PATH);
|
||||
|
||||
hmdRefCount--;
|
||||
|
||||
if (hmdRefCount == 0 && _hmd) {
|
||||
vr::VR_Shutdown();
|
||||
if (_hmd) {
|
||||
releaseOpenVrSystem();
|
||||
_hmd = nullptr;
|
||||
}
|
||||
_poseStateMap.clear();
|
||||
|
||||
_inputDevice->_poseStateMap.clear();
|
||||
#endif
|
||||
|
||||
// unregister with UserInputMapper
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
userInputMapper->removeDevice(_deviceID);
|
||||
userInputMapper->removeDevice(_inputDevice->_deviceID);
|
||||
_registeredWithInputMapper = false;
|
||||
}
|
||||
|
||||
|
@ -177,8 +157,8 @@ void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePoint
|
|||
//pendingChanges.updateItem(_leftHandRenderID, );
|
||||
|
||||
|
||||
controller::Pose leftHand = _poseStateMap[controller::StandardPoseChannel::LEFT_HAND];
|
||||
controller::Pose rightHand = _poseStateMap[controller::StandardPoseChannel::RIGHT_HAND];
|
||||
controller::Pose leftHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::LEFT_HAND];
|
||||
controller::Pose rightHand = _inputDevice->_poseStateMap[controller::StandardPoseChannel::RIGHT_HAND];
|
||||
|
||||
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
@ -223,15 +203,28 @@ void ViveControllerManager::renderHand(const controller::Pose& pose, gpu::Batch&
|
|||
batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
|
||||
}
|
||||
|
||||
void ViveControllerManager::update(float deltaTime, bool jointsCaptured) {
|
||||
|
||||
void ViveControllerManager::pluginUpdate(float deltaTime, bool jointsCaptured) {
|
||||
_inputDevice->update(deltaTime, jointsCaptured);
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
|
||||
if (_inputDevice->_trackedControllers == 0 && _registeredWithInputMapper) {
|
||||
userInputMapper->removeDevice(_inputDevice->_deviceID);
|
||||
_registeredWithInputMapper = false;
|
||||
_inputDevice->_poseStateMap.clear();
|
||||
}
|
||||
|
||||
if (!_registeredWithInputMapper && _inputDevice->_trackedControllers > 0) {
|
||||
userInputMapper->registerDevice(_inputDevice);
|
||||
_registeredWithInputMapper = true;
|
||||
UserActivityLogger::getInstance().connectedDevice("spatial_controller", "steamVR");
|
||||
}
|
||||
}
|
||||
|
||||
void ViveControllerManager::InputDevice::update(float deltaTime, bool jointsCaptured) {
|
||||
#ifdef Q_OS_WIN
|
||||
_poseStateMap.clear();
|
||||
|
||||
// TODO: This shouldn't be necessary
|
||||
if (!_hmd) {
|
||||
return;
|
||||
}
|
||||
|
||||
_buttonPressedMap.clear();
|
||||
|
||||
PerformanceTimer perfTimer("ViveControllerManager::update");
|
||||
|
@ -279,33 +272,17 @@ void ViveControllerManager::update(float deltaTime, bool jointsCaptured) {
|
|||
}
|
||||
}
|
||||
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
|
||||
if (numTrackedControllers == 0) {
|
||||
if (_registeredWithInputMapper) {
|
||||
userInputMapper->removeDevice(_deviceID);
|
||||
_registeredWithInputMapper = false;
|
||||
_poseStateMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (_trackedControllers == 0 && numTrackedControllers > 0) {
|
||||
userInputMapper->registerDevice(instance);
|
||||
_registeredWithInputMapper = true;
|
||||
UserActivityLogger::getInstance().connectedDevice("spatial_controller", "steamVR");
|
||||
}
|
||||
|
||||
_trackedControllers = numTrackedControllers;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ViveControllerManager::focusOutEvent() {
|
||||
void ViveControllerManager::InputDevice::focusOutEvent() {
|
||||
_axisStateMap.clear();
|
||||
_buttonPressedMap.clear();
|
||||
};
|
||||
|
||||
// These functions do translation from the Steam IDs to the standard controller IDs
|
||||
void ViveControllerManager::handleAxisEvent(uint32_t axis, float x, float y, bool left) {
|
||||
void ViveControllerManager::InputDevice::handleAxisEvent(uint32_t axis, float x, float y, bool left) {
|
||||
#ifdef Q_OS_WIN
|
||||
//FIX ME? It enters here every frame: probably we want to enter only if an event occurs
|
||||
axis += vr::k_EButton_Axis0;
|
||||
|
@ -320,7 +297,7 @@ void ViveControllerManager::handleAxisEvent(uint32_t axis, float x, float y, boo
|
|||
}
|
||||
|
||||
// These functions do translation from the Steam IDs to the standard controller IDs
|
||||
void ViveControllerManager::handleButtonEvent(uint32_t button, bool pressed, bool left) {
|
||||
void ViveControllerManager::InputDevice::handleButtonEvent(uint32_t button, bool pressed, bool left) {
|
||||
#ifdef Q_OS_WIN
|
||||
if (!pressed) {
|
||||
return;
|
||||
|
@ -342,7 +319,7 @@ void ViveControllerManager::handleButtonEvent(uint32_t button, bool pressed, boo
|
|||
#endif
|
||||
}
|
||||
|
||||
void ViveControllerManager::handlePoseEvent(const mat4& mat, bool left) {
|
||||
void ViveControllerManager::InputDevice::handlePoseEvent(const mat4& mat, bool left) {
|
||||
glm::vec3 position = extractTranslation(mat);
|
||||
glm::quat rotation = glm::quat_cast(mat);
|
||||
|
||||
|
@ -409,7 +386,7 @@ void ViveControllerManager::handlePoseEvent(const mat4& mat, bool left) {
|
|||
_poseStateMap[left ? controller::LEFT_HAND : controller::RIGHT_HAND] = controller::Pose(position, rotation);
|
||||
}
|
||||
|
||||
controller::Input::NamedVector ViveControllerManager::getAvailableInputs() const {
|
||||
controller::Input::NamedVector ViveControllerManager::InputDevice::getAvailableInputs() const {
|
||||
using namespace controller;
|
||||
QVector<Input::NamedPair> availableInputs{
|
||||
// Trackpad analogs
|
||||
|
@ -450,7 +427,7 @@ controller::Input::NamedVector ViveControllerManager::getAvailableInputs() const
|
|||
return availableInputs;
|
||||
}
|
||||
|
||||
QString ViveControllerManager::getDefaultMappingConfig() const {
|
||||
QString ViveControllerManager::InputDevice::getDefaultMappingConfig() const {
|
||||
static const QString MAPPING_JSON = PathUtils::resourcesPath() + "/controllers/vive.json";
|
||||
return MAPPING_JSON;
|
||||
}
|
||||
|
|
|
@ -24,10 +24,13 @@
|
|||
#include <RenderArgs.h>
|
||||
#include <render/Scene.h>
|
||||
|
||||
class ViveControllerManager : public InputPlugin, public controller::InputDevice {
|
||||
namespace vr {
|
||||
class IVRSystem;
|
||||
}
|
||||
|
||||
class ViveControllerManager : public InputPlugin {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViveControllerManager();
|
||||
|
||||
// Plugin functions
|
||||
virtual bool isSupported() const override;
|
||||
|
@ -37,40 +40,51 @@ public:
|
|||
virtual void activate() override;
|
||||
virtual void deactivate() override;
|
||||
|
||||
virtual void pluginFocusOutEvent() override { focusOutEvent(); }
|
||||
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override { update(deltaTime, jointsCaptured); }
|
||||
|
||||
// Device functions
|
||||
virtual controller::Input::NamedVector getAvailableInputs() const override;
|
||||
virtual QString getDefaultMappingConfig() const override;
|
||||
virtual void update(float deltaTime, bool jointsCaptured) override;
|
||||
virtual void focusOutEvent() override;
|
||||
virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); }
|
||||
virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override;
|
||||
|
||||
void updateRendering(RenderArgs* args, render::ScenePointer scene, render::PendingChanges pendingChanges);
|
||||
|
||||
void setRenderControllers(bool renderControllers) { _renderControllers = renderControllers; }
|
||||
|
||||
private:
|
||||
class InputDevice : public controller::InputDevice {
|
||||
public:
|
||||
InputDevice(vr::IVRSystem*& hmd) : controller::InputDevice("Vive"), _hmd(hmd) {}
|
||||
private:
|
||||
// Device functions
|
||||
virtual controller::Input::NamedVector getAvailableInputs() const override;
|
||||
virtual QString getDefaultMappingConfig() const override;
|
||||
virtual void update(float deltaTime, bool jointsCaptured) override;
|
||||
virtual void focusOutEvent() override;
|
||||
|
||||
void handleButtonEvent(uint32_t button, bool pressed, bool left);
|
||||
void handleAxisEvent(uint32_t axis, float x, float y, bool left);
|
||||
void handlePoseEvent(const mat4& mat, bool left);
|
||||
|
||||
int _trackedControllers { 0 };
|
||||
vr::IVRSystem*& _hmd;
|
||||
friend class ViveControllerManager;
|
||||
};
|
||||
|
||||
void renderHand(const controller::Pose& pose, gpu::Batch& batch, int sign);
|
||||
|
||||
void handleButtonEvent(uint32_t button, bool pressed, bool left);
|
||||
void handleAxisEvent(uint32_t axis, float x, float y, bool left);
|
||||
void handlePoseEvent(const mat4& mat, bool left);
|
||||
|
||||
int _trackedControllers;
|
||||
|
||||
bool _modelLoaded;
|
||||
bool _registeredWithInputMapper { false };
|
||||
bool _modelLoaded { false };
|
||||
model::Geometry _modelGeometry;
|
||||
gpu::TexturePointer _texture;
|
||||
|
||||
int _leftHandRenderID;
|
||||
int _rightHandRenderID;
|
||||
int _leftHandRenderID { 0 };
|
||||
int _rightHandRenderID { 0 };
|
||||
|
||||
bool _renderControllers;
|
||||
bool _renderControllers { false };
|
||||
vr::IVRSystem* _hmd { nullptr };
|
||||
std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>(_hmd) };
|
||||
|
||||
static const QString NAME;
|
||||
|
||||
bool _registeredWithInputMapper { false };
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ int main(int argc, char** argv) {
|
|||
inputPlugin->activate();
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
if (name == KeyboardMouseDevice::NAME) {
|
||||
userInputMapper->registerDevice(std::dynamic_pointer_cast<KeyboardMouseDevice>(inputPlugin));
|
||||
userInputMapper->registerDevice(std::dynamic_pointer_cast<KeyboardMouseDevice>(inputPlugin)->getInputDevice());
|
||||
}
|
||||
inputPlugin->pluginUpdate(0, false);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue