Merge pull request #6300 from jherico/lisa

Breaking up InputDevices and InputPlugins, cleanup of some shared_ptr madness
This commit is contained in:
Clément Brisset 2015-11-06 16:15:53 -08:00
commit 143e92ee1b
17 changed files with 371 additions and 264 deletions

View file

@ -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) {

View file

@ -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");

View 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")

View 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

View file

@ -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;

View file

@ -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;
};

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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();
}

View file

@ -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;
};

View file

@ -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();
}

View file

@ -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();

View file

@ -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;
}

View file

@ -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 };
};

View file

@ -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);
}