From 734a39f962916e49dfeaa0702a0d13f57d4c1c6d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 18 Oct 2015 18:58:03 -0700 Subject: [PATCH] Breaking up UserInputMapper, restoring some mappings --- interface/resources/qml/TestControllers.qml | 2 +- .../ControllerScriptingInterface.cpp | 315 ------------------ .../scripting/ControllerScriptingInterface.h | 47 +-- .../src/controllers/DeviceProxy.cpp | 31 ++ .../controllers/src/controllers/DeviceProxy.h | 57 ++++ .../controllers/src/controllers/Input.cpp | 19 ++ libraries/controllers/src/controllers/Input.h | 76 +++++ .../src/controllers/InputDevice.cpp | 4 +- .../controllers/src/controllers/InputDevice.h | 8 +- .../controllers/src/controllers/Pose.cpp | 30 ++ libraries/controllers/src/controllers/Pose.h | 43 +++ .../src/controllers/ScriptingInterface.cpp | 125 ++++--- .../src/controllers/ScriptingInterface.h | 39 ++- .../src/controllers/StandardController.cpp | 61 +++- .../src/controllers/UserInputMapper.cpp | 184 ++++++---- .../src/controllers/UserInputMapper.h | 111 +----- .../src/input-plugins/Joystick.cpp | 60 ++++ .../src/input-plugins/Joystick.h | 1 + .../src/input-plugins/SixenseManager.cpp | 75 ++++- .../src/input-plugins/SixenseManager.h | 2 + libraries/script-engine/src/ScriptEngine.cpp | 10 +- 21 files changed, 670 insertions(+), 630 deletions(-) create mode 100644 libraries/controllers/src/controllers/DeviceProxy.cpp create mode 100644 libraries/controllers/src/controllers/DeviceProxy.h create mode 100644 libraries/controllers/src/controllers/Input.cpp create mode 100644 libraries/controllers/src/controllers/Input.h create mode 100644 libraries/controllers/src/controllers/Pose.cpp create mode 100644 libraries/controllers/src/controllers/Pose.h diff --git a/interface/resources/qml/TestControllers.qml b/interface/resources/qml/TestControllers.qml index 388e452335..d8c9cb4343 100644 --- a/interface/resources/qml/TestControllers.qml +++ b/interface/resources/qml/TestControllers.qml @@ -87,7 +87,7 @@ HifiControls.VrDialog { mapping.from(hydra.RY).invert().to(standard.RY); mapping.from(hydra.RX).to(standard.RX); mapping.from(hydra.LY).to(standard.LY); - mapping.from(hydra.LY).to(standard.LX); + mapping.from(hydra.LX).to(standard.LX); // Assigning a value from a function // mapping.from(function() { return Math.sin(Date.now() / 250); }).to(standard.RX); // Constrainting a value to -1, 0, or 1, with a deadzone diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index f1f7b08587..931c97a7d2 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -23,109 +23,6 @@ // TODO: this needs to be removed, as well as any related controller-specific information #include -ControllerScriptingInterface::ControllerScriptingInterface() : - _mouseCaptured(false), - _touchCaptured(false), - _wheelCaptured(false), - _actionsCaptured(false) -{ - -} - -ControllerScriptingInterface::~ControllerScriptingInterface() { -} - - -static int actionMetaTypeId = qRegisterMetaType(); -static int inputChannelMetaTypeId = qRegisterMetaType(); -static int inputMetaTypeId = qRegisterMetaType(); -static int inputPairMetaTypeId = qRegisterMetaType(); - -QScriptValue inputToScriptValue(QScriptEngine* engine, const UserInputMapper::Input& input); -void inputFromScriptValue(const QScriptValue& object, UserInputMapper::Input& input); -QScriptValue inputChannelToScriptValue(QScriptEngine* engine, const UserInputMapper::InputChannel& inputChannel); -void inputChannelFromScriptValue(const QScriptValue& object, UserInputMapper::InputChannel& inputChannel); -QScriptValue actionToScriptValue(QScriptEngine* engine, const UserInputMapper::Action& action); -void actionFromScriptValue(const QScriptValue& object, UserInputMapper::Action& action); -QScriptValue inputPairToScriptValue(QScriptEngine* engine, const UserInputMapper::InputPair& inputPair); -void inputPairFromScriptValue(const QScriptValue& object, UserInputMapper::InputPair& inputPair); - -QScriptValue inputToScriptValue(QScriptEngine* engine, const UserInputMapper::Input& input) { - QScriptValue obj = engine->newObject(); - obj.setProperty("device", input.getDevice()); - obj.setProperty("channel", input.getChannel()); - obj.setProperty("type", (unsigned short) input.getType()); - obj.setProperty("id", input.getID()); - return obj; -} - -void inputFromScriptValue(const QScriptValue& object, UserInputMapper::Input& input) { - input.setDevice(object.property("device").toUInt16()); - input.setChannel(object.property("channel").toUInt16()); - input.setType(object.property("type").toUInt16()); - input.setID(object.property("id").toInt32()); -} - -QScriptValue inputChannelToScriptValue(QScriptEngine* engine, const UserInputMapper::InputChannel& inputChannel) { - QScriptValue obj = engine->newObject(); - obj.setProperty("input", inputToScriptValue(engine, inputChannel.getInput())); - obj.setProperty("modifier", inputToScriptValue(engine, inputChannel.getModifier())); - obj.setProperty("action", inputChannel.getAction()); - obj.setProperty("scale", inputChannel.getScale()); - return obj; -} - -void inputChannelFromScriptValue(const QScriptValue& object, UserInputMapper::InputChannel& inputChannel) { - UserInputMapper::Input input; - UserInputMapper::Input modifier; - inputFromScriptValue(object.property("input"), input); - inputChannel.setInput(input); - inputFromScriptValue(object.property("modifier"), modifier); - inputChannel.setModifier(modifier); - inputChannel.setAction(UserInputMapper::Action(object.property("action").toVariant().toInt())); - inputChannel.setScale(object.property("scale").toVariant().toFloat()); -} - -QScriptValue actionToScriptValue(QScriptEngine* engine, const UserInputMapper::Action& action) { - QScriptValue obj = engine->newObject(); - auto userInputMapper = DependencyManager::get(); - QVector inputChannels = userInputMapper->getInputChannelsForAction(action); - QScriptValue _inputChannels = engine->newArray(inputChannels.size()); - for (int i = 0; i < inputChannels.size(); i++) { - _inputChannels.setProperty(i, inputChannelToScriptValue(engine, inputChannels[i])); - } - obj.setProperty("action", (int) action); - obj.setProperty("actionName", userInputMapper->getActionName(action)); - obj.setProperty("inputChannels", _inputChannels); - return obj; -} - -void actionFromScriptValue(const QScriptValue& object, UserInputMapper::Action& action) { - action = UserInputMapper::Action(object.property("action").toVariant().toInt()); -} - -QScriptValue inputPairToScriptValue(QScriptEngine* engine, const UserInputMapper::InputPair& inputPair) { - QScriptValue obj = engine->newObject(); - obj.setProperty("input", inputToScriptValue(engine, inputPair.first)); - obj.setProperty("inputName", inputPair.second); - return obj; -} - -void inputPairFromScriptValue(const QScriptValue& object, UserInputMapper::InputPair& inputPair) { - inputFromScriptValue(object.property("input"), inputPair.first); - inputPair.second = QString(object.property("inputName").toVariant().toString()); -} - -void ControllerScriptingInterface::registerControllerTypes(QScriptEngine* engine) { - qScriptRegisterSequenceMetaType >(engine); - qScriptRegisterSequenceMetaType >(engine); - qScriptRegisterSequenceMetaType >(engine); - qScriptRegisterMetaType(engine, actionToScriptValue, actionFromScriptValue); - qScriptRegisterMetaType(engine, inputChannelToScriptValue, inputChannelFromScriptValue); - qScriptRegisterMetaType(engine, inputToScriptValue, inputFromScriptValue); - qScriptRegisterMetaType(engine, inputPairToScriptValue, inputPairFromScriptValue); -} - void ControllerScriptingInterface::handleMetaEvent(HFMetaEvent* event) { if (event->type() == HFActionEvent::startType()) { emit actionStartEvent(static_cast(*event)); @@ -183,162 +80,6 @@ const PalmData* ControllerScriptingInterface::getActivePalm(int palmIndex) const return NULL; } -/* -bool ControllerScriptingInterface::isPrimaryButtonPressed() const { - const PalmData* primaryPalm = getPrimaryPalm(); - if (primaryPalm) { - if (primaryPalm->getControllerButtons() & BUTTON_FWD) { - return true; - } - } - - return false; -} - -glm::vec2 ControllerScriptingInterface::getPrimaryJoystickPosition() const { - const PalmData* primaryPalm = getPrimaryPalm(); - if (primaryPalm) { - return glm::vec2(primaryPalm->getJoystickX(), primaryPalm->getJoystickY()); - } - - return glm::vec2(0); -} - -int ControllerScriptingInterface::getNumberOfButtons() const { - return getNumberOfActivePalms() * NUMBER_OF_BUTTONS_PER_PALM; -} - -bool ControllerScriptingInterface::isButtonPressed(int buttonIndex) const { - int palmIndex = buttonIndex / NUMBER_OF_BUTTONS_PER_PALM; - int buttonOnPalm = buttonIndex % NUMBER_OF_BUTTONS_PER_PALM; - const PalmData* palmData = getActivePalm(palmIndex); - if (palmData) { - switch (buttonOnPalm) { - case 0: - return palmData->getControllerButtons() & BUTTON_0; - case 1: - return palmData->getControllerButtons() & BUTTON_1; - case 2: - return palmData->getControllerButtons() & BUTTON_2; - case 3: - return palmData->getControllerButtons() & BUTTON_3; - case 4: - return palmData->getControllerButtons() & BUTTON_4; - case 5: - return palmData->getControllerButtons() & BUTTON_FWD; - } - } - return false; -} - -int ControllerScriptingInterface::getNumberOfTriggers() const { - return getNumberOfActivePalms() * NUMBER_OF_TRIGGERS_PER_PALM; -} - -float ControllerScriptingInterface::getTriggerValue(int triggerIndex) const { - // we know there's one trigger per palm, so the triggerIndex is the palm Index - int palmIndex = triggerIndex; - const PalmData* palmData = getActivePalm(palmIndex); - if (palmData) { - return palmData->getTrigger(); - } - return 0.0f; -} - -int ControllerScriptingInterface::getNumberOfJoysticks() const { - return getNumberOfActivePalms() * NUMBER_OF_JOYSTICKS_PER_PALM; -} - -glm::vec2 ControllerScriptingInterface::getJoystickPosition(int joystickIndex) const { - // we know there's one joystick per palm, so the joystickIndex is the palm Index - int palmIndex = joystickIndex; - const PalmData* palmData = getActivePalm(palmIndex); - if (palmData) { - return glm::vec2(palmData->getJoystickX(), palmData->getJoystickY()); - } - return glm::vec2(0); -} - -int ControllerScriptingInterface::getNumberOfSpatialControls() const { - return getNumberOfActivePalms() * NUMBER_OF_SPATIALCONTROLS_PER_PALM; -} - -glm::vec3 ControllerScriptingInterface::getSpatialControlPosition(int controlIndex) const { - int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; - int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM; - const PalmData* palmData = getActivePalm(palmIndex); - if (palmData) { - switch (controlOfPalm) { - case PALM_SPATIALCONTROL: - return palmData->getPosition(); - case TIP_SPATIALCONTROL: - return palmData->getTipPosition(); - } - } - return glm::vec3(0); // bad index -} - -glm::vec3 ControllerScriptingInterface::getSpatialControlVelocity(int controlIndex) const { - int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; - int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM; - const PalmData* palmData = getActivePalm(palmIndex); - if (palmData) { - switch (controlOfPalm) { - case PALM_SPATIALCONTROL: - return palmData->getVelocity(); - case TIP_SPATIALCONTROL: - return palmData->getTipVelocity(); - } - } - return glm::vec3(0); // bad index -} - -glm::quat ControllerScriptingInterface::getSpatialControlRawRotation(int controlIndex) const { - int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; - int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM; - const PalmData* palmData = getActivePalm(palmIndex); - if (palmData) { - switch (controlOfPalm) { - case PALM_SPATIALCONTROL: - return palmData->getRawRotation(); - case TIP_SPATIALCONTROL: - return palmData->getRawRotation(); // currently the tip doesn't have a unique rotation, use the palm rotation - } - } - return glm::quat(); // bad index -} - -glm::vec3 ControllerScriptingInterface::getSpatialControlRawAngularVelocity(int controlIndex) const { - int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; - int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM; - const PalmData* palmData = getActivePalm(palmIndex); - if (palmData) { - switch (controlOfPalm) { - case PALM_SPATIALCONTROL: - return palmData->getRawAngularVelocity(); - case TIP_SPATIALCONTROL: - return palmData->getRawAngularVelocity(); // Tip = palm angular velocity - } - } - return glm::vec3(0); // bad index -} - -glm::vec3 ControllerScriptingInterface::getSpatialControlNormal(int controlIndex) const { - int palmIndex = controlIndex / NUMBER_OF_SPATIALCONTROLS_PER_PALM; - int controlOfPalm = controlIndex % NUMBER_OF_SPATIALCONTROLS_PER_PALM; - const PalmData* palmData = getActivePalm(palmIndex); - if (palmData) { - switch (controlOfPalm) { - case PALM_SPATIALCONTROL: - return palmData->getNormal(); - case TIP_SPATIALCONTROL: - return palmData->getFingerDirection(); - } - } - return glm::vec3(0); // bad index -} -*/ - bool ControllerScriptingInterface::isKeyCaptured(QKeyEvent* event) const { return isKeyCaptured(KeyEvent(*event)); } @@ -448,62 +189,6 @@ void ControllerScriptingInterface::update() { controller::ScriptingInterface::update(); } -QVector ControllerScriptingInterface::getAllActions() { - return DependencyManager::get()->getAllActions(); -} - -QVector ControllerScriptingInterface::getInputChannelsForAction(UserInputMapper::Action action) { - return DependencyManager::get()->getInputChannelsForAction(action); -} - -QString ControllerScriptingInterface::getDeviceName(unsigned int device) { - return DependencyManager::get()->getDeviceName((unsigned short)device); -} - -QVector ControllerScriptingInterface::getAllInputsForDevice(unsigned int device) { - return DependencyManager::get()->getAllInputsForDevice(device); -} - -bool ControllerScriptingInterface::addInputChannel(UserInputMapper::InputChannel inputChannel) { - return DependencyManager::get()->addInputChannel(inputChannel._action, inputChannel._input, inputChannel._modifier, inputChannel._scale); -} - -bool ControllerScriptingInterface::removeInputChannel(UserInputMapper::InputChannel inputChannel) { - return DependencyManager::get()->removeInputChannel(inputChannel); -} - -QVector ControllerScriptingInterface::getAvailableInputs(unsigned int device) { - return DependencyManager::get()->getAvailableInputs((unsigned short)device); -} - -void ControllerScriptingInterface::resetAllDeviceBindings() { - DependencyManager::get()->resetAllDeviceBindings(); -} - -void ControllerScriptingInterface::resetDevice(unsigned int device) { - DependencyManager::get()->resetDevice(device); -} - -int ControllerScriptingInterface::findDevice(QString name) { - return DependencyManager::get()->findDevice(name); -} - -QVector ControllerScriptingInterface::getDeviceNames() { - return DependencyManager::get()->getDeviceNames(); -} - -float ControllerScriptingInterface::getActionValue(int action) { - return DependencyManager::get()->getActionState(UserInputMapper::Action(action)); -} - -int ControllerScriptingInterface::findAction(QString actionName) { - return DependencyManager::get()->findAction(actionName); -} - -QVector ControllerScriptingInterface::getActionNames() const { - return DependencyManager::get()->getActionNames(); -} - InputController::InputController(int deviceTrackerId, int subTrackerId, QObject* parent) : _deviceTrackerId(deviceTrackerId), _subTrackerId(subTrackerId), diff --git a/interface/src/scripting/ControllerScriptingInterface.h b/interface/src/scripting/ControllerScriptingInterface.h index 25d9a523d3..24065e6799 100644 --- a/interface/src/scripting/ControllerScriptingInterface.h +++ b/interface/src/scripting/ControllerScriptingInterface.h @@ -63,33 +63,8 @@ class ControllerScriptingInterface : public controller::ScriptingInterface { public: - ControllerScriptingInterface(); - ~ControllerScriptingInterface(); + virtual ~ControllerScriptingInterface() {} - Q_INVOKABLE QVector getAllActions(); - - Q_INVOKABLE bool addInputChannel(UserInputMapper::InputChannel inputChannel); - Q_INVOKABLE bool removeInputChannel(UserInputMapper::InputChannel inputChannel); - Q_INVOKABLE QVector getInputChannelsForAction(UserInputMapper::Action action); - - Q_INVOKABLE QVector getAvailableInputs(unsigned int device); - Q_INVOKABLE QVector getAllInputsForDevice(unsigned int device); - - Q_INVOKABLE QString getDeviceName(unsigned int device); - - Q_INVOKABLE float getActionValue(int action); - - Q_INVOKABLE void resetDevice(unsigned int device); - Q_INVOKABLE void resetAllDeviceBindings(); - Q_INVOKABLE int findDevice(QString name); - Q_INVOKABLE QVector getDeviceNames(); - - Q_INVOKABLE int findAction(QString actionName); - Q_INVOKABLE QVector getActionNames() const; - - - virtual void registerControllerTypes(QScriptEngine* engine); - void emitKeyPressEvent(QKeyEvent* event); void emitKeyReleaseEvent(QKeyEvent* event); @@ -108,10 +83,6 @@ public: bool isKeyCaptured(QKeyEvent* event) const; bool isKeyCaptured(const KeyEvent& event) const; - bool isMouseCaptured() const { return _mouseCaptured; } - bool isTouchCaptured() const { return _touchCaptured; } - bool isWheelCaptured() const { return _wheelCaptured; } - bool areActionsCaptured() const { return _actionsCaptured; } bool isJoystickCaptured(int joystickIndex) const; virtual void update() override; @@ -121,18 +92,6 @@ public slots: virtual void captureKeyEvents(const KeyEvent& event); virtual void releaseKeyEvents(const KeyEvent& event); - virtual void captureMouseEvents() { _mouseCaptured = true; } - virtual void releaseMouseEvents() { _mouseCaptured = false; } - - virtual void captureTouchEvents() { _touchCaptured = true; } - virtual void releaseTouchEvents() { _touchCaptured = false; } - - virtual void captureWheelEvents() { _wheelCaptured = true; } - virtual void releaseWheelEvents() { _wheelCaptured = false; } - - virtual void captureActionEvents() { _actionsCaptured = true; } - virtual void releaseActionEvents() { _actionsCaptured = false; } - virtual void captureJoystick(int joystickIndex); virtual void releaseJoystick(int joystickIndex); @@ -173,10 +132,6 @@ private: int getNumberOfActivePalms() const; const PalmData* getActivePalm(int palmIndex) const; - bool _mouseCaptured; - bool _touchCaptured; - bool _wheelCaptured; - bool _actionsCaptured; QMultiMap _capturedKeys; QSet _capturedJoysticks; diff --git a/libraries/controllers/src/controllers/DeviceProxy.cpp b/libraries/controllers/src/controllers/DeviceProxy.cpp new file mode 100644 index 0000000000..9ac701e80d --- /dev/null +++ b/libraries/controllers/src/controllers/DeviceProxy.cpp @@ -0,0 +1,31 @@ +// +// Created by Bradley Austin Davis on 2015/10/18 +// (based on UserInputMapper inner class created by Sam Gateau on 4/27/15) +// 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 "DeviceProxy.h" + +namespace controller { + + float DeviceProxy::getValue(const Input& input, int timestamp) const { + switch (input.getType()) { + case ChannelType::BUTTON: + return getButton(input, timestamp) ? 1.0f : 0.0f; + + case ChannelType::AXIS: + return getAxis(input, timestamp); + + case ChannelType::POSE: + return getPose(input, timestamp)._valid ? 1.0f : 0.0f; + + default: + return NAN; + } + } + +} + diff --git a/libraries/controllers/src/controllers/DeviceProxy.h b/libraries/controllers/src/controllers/DeviceProxy.h new file mode 100644 index 0000000000..78d13fe5c4 --- /dev/null +++ b/libraries/controllers/src/controllers/DeviceProxy.h @@ -0,0 +1,57 @@ +// +// Created by Bradley Austin Davis on 2015/10/18 +// (based on UserInputMapper inner class created by Sam Gateau on 4/27/15) +// 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 +// + +#pragma once +#ifndef hifi_controllers_DeviceProxy_h +#define hifi_controllers_DeviceProxy_h + +#include + +#include +#include + +#include "Input.h" +#include "Pose.h" + +namespace controller { + + using Modifiers = std::vector; + typedef QPair InputPair; + + + template + using InputGetter = std::function; + using ButtonGetter = InputGetter; + using AxisGetter = InputGetter; + using PoseGetter = InputGetter; + using ResetBindings = std::function; + using AvailableInputGetter = std::function; + + class DeviceProxy { + public: + DeviceProxy(QString name) : _baseName(name), _name(name) {} + const QString& getBaseName() const { return _baseName; } + const QString& getName() const { return _name; } + + ButtonGetter getButton = [] (const Input& input, int timestamp) -> bool { return false; }; + AxisGetter getAxis = [] (const Input& input, int timestamp) -> float { return 0.0f; }; + PoseGetter getPose = [](const Input& input, int timestamp) -> Pose { return Pose(); }; + AvailableInputGetter getAvailabeInputs = []() -> Input::NamedVector { return Input::NamedVector(); }; + ResetBindings resetDeviceBindings = [] () -> bool { return true; }; + float getValue(const Input& input, int timestamp = 0) const; + + using Pointer = std::shared_ptr; + + QString _baseName; + QString _name; + }; + +} + +#endif diff --git a/libraries/controllers/src/controllers/Input.cpp b/libraries/controllers/src/controllers/Input.cpp new file mode 100644 index 0000000000..29d2fed617 --- /dev/null +++ b/libraries/controllers/src/controllers/Input.cpp @@ -0,0 +1,19 @@ +// +// Created by Bradley Austin Davis on 2015/10/18 +// 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 "Input.h" + +namespace controller { + + const Input Input::INVALID_INPUT = Input(UINT32_MAX); + const uint16_t Input::INVALID_DEVICE = INVALID_INPUT.getDevice(); + const uint16_t Input::INVALID_CHANNEL = INVALID_INPUT.getChannel(); + const uint16_t Input::INVALID_TYPE = (uint16_t)INVALID_INPUT.getType(); + +} + diff --git a/libraries/controllers/src/controllers/Input.h b/libraries/controllers/src/controllers/Input.h new file mode 100644 index 0000000000..8cc682df70 --- /dev/null +++ b/libraries/controllers/src/controllers/Input.h @@ -0,0 +1,76 @@ +// +// Created by Bradley Austin Davis on 2015/10/18 +// (based on UserInputMapper inner class created by Sam Gateau on 4/27/15) +// 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 +// + +#pragma once +#ifndef hifi_controllers_Input_h +#define hifi_controllers_Input_h + +#include + +namespace controller { + +enum class ChannelType { + UNKNOWN = 0, + BUTTON = 1, + AXIS, + POSE, +}; + +// Input is the unique identifier to find a n input channel of a particular device +// Devices are responsible for registering to the UseInputMapper so their input channels can be sued and mapped +// to the Action channels +struct Input { + union { + struct { + uint16_t _device; // Up to 64K possible devices + uint16_t _channel : 13; // 2^13 possible channel per Device + uint16_t _type : 2; // 2 bits to store the Type directly in the ID + uint16_t _padding : 1; // 2 bits to store the Type directly in the ID + }; + uint32_t _id = 0; // by default Input is 0 meaning invalid + }; + + bool isValid() const { return (_id != 0); } + + uint16_t getDevice() const { return _device; } + uint16_t getChannel() const { return _channel; } + uint32_t getID() const { return _id; } + ChannelType getType() const { return (ChannelType) _type; } + + void setDevice(uint16_t device) { _device = device; } + void setChannel(uint16_t channel) { _channel = channel; } + void setType(uint16_t type) { _type = type; } + void setID(uint32_t ID) { _id = ID; } + + bool isButton() const { return getType() == ChannelType::BUTTON; } + bool isAxis() const { return getType() == ChannelType::AXIS; } + bool isPose() const { return getType() == ChannelType::POSE; } + + // WORKAROUND: the explicit initializer here avoids a bug in GCC-4.8.2 (but not found in 4.9.2) + // where the default initializer (a C++-11ism) for the union data above is not applied. + explicit Input() : _id(0) {} + explicit Input(uint32_t id) : _id(id) {} + explicit Input(uint16_t device, uint16_t channel, ChannelType type) : _device(device), _channel(channel), _type(uint16_t(type)), _padding(0) {} + Input(const Input& src) : _id(src._id) {} + Input& operator = (const Input& src) { _id = src._id; return (*this); } + bool operator ==(const Input& right) const { return _id == right._id; } + bool operator < (const Input& src) const { return _id < src._id; } + + static const Input INVALID_INPUT; + static const uint16_t INVALID_DEVICE; + static const uint16_t INVALID_CHANNEL; + static const uint16_t INVALID_TYPE; + + using NamedPair = QPair; + using NamedVector = QVector; +}; + +} + +#endif diff --git a/libraries/controllers/src/controllers/InputDevice.cpp b/libraries/controllers/src/controllers/InputDevice.cpp index 4b2376d32a..1f86741b88 100644 --- a/libraries/controllers/src/controllers/InputDevice.cpp +++ b/libraries/controllers/src/controllers/InputDevice.cpp @@ -13,7 +13,7 @@ bool InputDevice::_lowVelocityFilter = false; const float DEFAULT_HAND_RETICLE_MOVE_SPEED = 37.5f; -float InputDevice::reticleMoveSpeed = DEFAULT_HAND_RETICLE_MOVE_SPEED; +float InputDevice::_reticleMoveSpeed = DEFAULT_HAND_RETICLE_MOVE_SPEED; //Constants for getCursorPixelRangeMultiplier() const float MIN_PIXEL_RANGE_MULT = 0.4f; @@ -23,7 +23,7 @@ const float RANGE_MULT = (MAX_PIXEL_RANGE_MULT - MIN_PIXEL_RANGE_MULT) * 0.01f; //Returns a multiplier to be applied to the cursor range for the controllers float InputDevice::getCursorPixelRangeMult() { //scales (0,100) to (MINIMUM_PIXEL_RANGE_MULT, MAXIMUM_PIXEL_RANGE_MULT) - return InputDevice::reticleMoveSpeed * RANGE_MULT + MIN_PIXEL_RANGE_MULT; + return InputDevice::_reticleMoveSpeed * RANGE_MULT + MIN_PIXEL_RANGE_MULT; } float InputDevice::getButton(int channel) const { diff --git a/libraries/controllers/src/controllers/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h index 66f7addc58..4854df0ada 100644 --- a/libraries/controllers/src/controllers/InputDevice.h +++ b/libraries/controllers/src/controllers/InputDevice.h @@ -34,7 +34,7 @@ public: UserInputMapper::PoseValue getPose(int channel) const; virtual void registerToUserInputMapper(UserInputMapper& mapper) = 0; - virtual void assignDefaultInputMapping(UserInputMapper& mapper) {}; + virtual void assignDefaultInputMapping(UserInputMapper& mapper) = 0; // Update call MUST be called once per simulation loop // It takes care of updating the action states and deltas @@ -45,8 +45,8 @@ public: int getDeviceID() { return _deviceID; } static float getCursorPixelRangeMult(); - static float getReticleMoveSpeed() { return reticleMoveSpeed; } - static void setReticleMoveSpeed(float sixenseReticleMoveSpeed) { reticleMoveSpeed = sixenseReticleMoveSpeed; } + static float getReticleMoveSpeed() { return _reticleMoveSpeed; } + static void setReticleMoveSpeed(float reticleMoveSpeed) { _reticleMoveSpeed = reticleMoveSpeed; } static bool getLowVelocityFilter() { return _lowVelocityFilter; }; @@ -72,5 +72,5 @@ protected: static bool _lowVelocityFilter; private: - static float reticleMoveSpeed; + static float _reticleMoveSpeed; }; \ No newline at end of file diff --git a/libraries/controllers/src/controllers/Pose.cpp b/libraries/controllers/src/controllers/Pose.cpp new file mode 100644 index 0000000000..a716955d70 --- /dev/null +++ b/libraries/controllers/src/controllers/Pose.cpp @@ -0,0 +1,30 @@ +// +// Created by Bradley Austin Davis on 2015/10/18 +// 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 "Pose.h" + +namespace controller { + + Pose::Pose(const vec3& translation, const quat& rotation, + const vec3& velocity, const quat& angularVelocity) : + _translation(translation), _rotation(rotation), _velocity(velocity), _angularVelocity(angularVelocity) { } + + bool Pose::operator==(const Pose& right) const { + // invalid poses return false for comparison, even against identical invalid poses, like NaN + if (_valid || !right._valid) { + return false; + } + + // FIXME add margin of error? Or add an additional withinEpsilon function? + return _translation == right.getTranslation() && _rotation == right.getRotation() && + _velocity == right.getVelocity() && _angularVelocity == right.getAngularVelocity(); + } + + +} + diff --git a/libraries/controllers/src/controllers/Pose.h b/libraries/controllers/src/controllers/Pose.h new file mode 100644 index 0000000000..b77064f2c1 --- /dev/null +++ b/libraries/controllers/src/controllers/Pose.h @@ -0,0 +1,43 @@ +// +// Created by Bradley Austin Davis on 2015/10/18 +// (based on UserInputMapper inner class created by Sam Gateau on 4/27/15) +// 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 +// + +#pragma once +#ifndef hifi_controllers_Pose_h +#define hifi_controllers_Pose_h + +#include + +namespace controller { + + struct Pose { + public: + vec3 _translation; + quat _rotation; + vec3 _velocity; + quat _angularVelocity; + bool _valid{ false }; + + Pose() {} + Pose(const vec3& translation, const quat& rotation, + const vec3& velocity = vec3(), const quat& angularVelocity = quat()); + + Pose(const Pose&) = default; + Pose& operator = (const Pose&) = default; + bool operator ==(const Pose& right) const; + bool isValid() const { return _valid; } + vec3 getTranslation() const { return _translation; } + quat getRotation() const { return _rotation; } + vec3 getVelocity() const { return _velocity; } + quat getAngularVelocity() const { return _angularVelocity; } + }; + + +} + +#endif diff --git a/libraries/controllers/src/controllers/ScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp index 6d4ad1a566..c5c7969604 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -67,7 +67,7 @@ namespace controller { void ScriptEndpoint::updateValue() { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "updateValue", Qt::QueuedConnection); + QMetaObject::invokeMethod(this, "updateValue", Qt::QueuedConnection); return; } @@ -80,10 +80,10 @@ namespace controller { void ScriptEndpoint::internalApply(float newValue, float oldValue, int sourceID) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "internalApply", Qt::QueuedConnection, - Q_ARG(float, newValue), - Q_ARG(float, oldValue), - Q_ARG(int, sourceID)); + QMetaObject::invokeMethod(this, "internalApply", Qt::QueuedConnection, + Q_ARG(float, newValue), + Q_ARG(float, oldValue), + Q_ARG(int, sourceID)); return; } _callable.call(QScriptValue(), @@ -163,28 +163,28 @@ namespace controller { QJsonObject obj; QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8(), &error); - // check validity of the document - if (!doc.isNull()) { - if (doc.isObject()) { - obj = doc.object(); - + // check validity of the document + if (!doc.isNull()) { + if (doc.isObject()) { + obj = doc.object(); + auto mapping = std::make_shared("default"); auto mappingBuilder = new MappingBuilderProxy(*this, mapping); mappingBuilder->parse(obj); _mappingsByName[mapping->_name] = mapping; - - return mappingBuilder; - } else { - qDebug() << "Mapping json Document is not an object" << endl; - } - } else { - qDebug() << "Invalid JSON...\n"; - qDebug() << error.errorString(); - qDebug() << "JSON was:\n" << json << endl; - - } + + return mappingBuilder; + } else { + qDebug() << "Mapping json Document is not an object" << endl; + } + } else { + qDebug() << "Invalid JSON...\n"; + qDebug() << error.errorString(); + qDebug() << "JSON was:\n" << json << endl; + + } return nullptr; } @@ -204,7 +204,7 @@ namespace controller { if (request->getResult() == ResourceRequest::Success) { result = parseMapping(QString(request->getData())); } else { - qCWarning(controllers) << "Failed to load mapping url <" << jsonUrl << ">" << endl; + qCWarning(controllers) << "Failed to load mapping url <" << jsonUrl << ">" << endl; } request->deleteLater(); } @@ -263,8 +263,8 @@ namespace controller { return getValue(UserInputMapper::Input(device, source, UserInputMapper::ChannelType::AXIS).getID()); } - glm::mat4 ScriptingInterface::getPoseValue(StandardPoseChannel source, uint16_t device) const { - return glm::mat4(); + Pose ScriptingInterface::getPoseValue(StandardPoseChannel source, uint16_t device) const { + return Pose(); } void ScriptingInterface::update() { @@ -368,7 +368,7 @@ namespace controller { } UserInputMapper::Input ScriptingInterface::inputFor(const QString& inputName) { - return DependencyManager::get()->findDeviceInput(inputName); + return DependencyManager::get()->findDeviceInput(inputName); } Endpoint::Pointer ScriptingInterface::endpointFor(const UserInputMapper::Input& inputId) { @@ -494,6 +494,39 @@ namespace controller { } } } + + QVector ScriptingInterface::getAllActions() { + return DependencyManager::get()->getAllActions(); + } + + QString ScriptingInterface::getDeviceName(unsigned int device) { + return DependencyManager::get()->getDeviceName((unsigned short)device); + } + + QVector ScriptingInterface::getAvailableInputs(unsigned int device) { + return DependencyManager::get()->getAvailableInputs((unsigned short)device); + } + + int ScriptingInterface::findDevice(QString name) { + return DependencyManager::get()->findDevice(name); + } + + QVector ScriptingInterface::getDeviceNames() { + return DependencyManager::get()->getDeviceNames(); + } + + float ScriptingInterface::getActionValue(int action) { + return DependencyManager::get()->getActionState(UserInputMapper::Action(action)); + } + + int ScriptingInterface::findAction(QString actionName) { + return DependencyManager::get()->findAction(actionName); + } + + QVector ScriptingInterface::getActionNames() const { + return DependencyManager::get()->getActionNames(); + } + } // namespace controllers @@ -520,7 +553,7 @@ ScriptingInterface::ScriptingInterface() { int actionNumber = 0; qCDebug(controllers) << "Setting up standard actions"; for (const auto& actionName : actionNames) { - UserInputMapper::Input actionInput(UserInputMapper::Input::ACTIONS_DEVICE, actionNumber++, UserInputMapper::ChannelType::AXIS); + UserInputMapper::Input actionInput(UserInputMapper::ACTIONS_DEVICE, actionNumber++, UserInputMapper::ChannelType::AXIS); qCDebug(controllers) << "\tAction: " << actionName << " " << QString::number(actionInput.getID(), 16); // Expose the IDs to JS QString cleanActionName = QString(actionName).remove(ScriptingInterface::SANITIZE_NAME_EXPRESSION); @@ -532,43 +565,3 @@ ScriptingInterface::ScriptingInterface() { updateMaps(); } - -//var mapping = Controller.newMapping(); -//mapping.map(hydra.LeftButton0, actions.ContextMenu); -//mapping.map(hydra.LeftButton0).to(xbox.RT); -//mapping.from(xbox.RT).constrainToBoolean().invert().to(actions.Foo) -// mapping.from(xbox.RY).invert().deadZone(0.2).to(actions.Pitch) -// mapping.from(xbox.RY).filter(function(newValue, oldValue) { -// return newValue * 2.0 -//}).to(actions.Pitch) - -//mapping.from(function(time) { -// return Math.cos(time); -// }).to(actions.Pitch); - -// mapping.mapFromFunction(function() { -// return x; -// }, actions.ContextMenu); - -// mapping.from(xbox.LY).clamp(0, 1).to(actions.Forward); -// mapping.from(xbox.LY).clamp(-1, 0).to(actions.Backward); -// mapping.from(xbox.RY).clamp(0, 1).to(actions.Forward); -// mapping.from(xbox.RS).to(); -// mapping.from(xbox.ALL).to(); - -// mapping.from(xbox.RY).to(function(...) { ... }); -// mapping.from(xbox.RY).pass(); - -// mapping.suppress() ≅ mapping.to(null) -// mapping.pass() ≅ mapping.to(fromControl) - -// mapping.from(keyboard.RightParen).invert().to(actions.Yaw) -// mapping.from(keyboard.LeftParen).to(actions.Yaw) - -// mapping.from(hydra.LX).pulse(MIN_SNAP_TIME, 3.0).to(Actions.Yaw) - -// mapping.from(keyboard.LeftParen).pulse(MIN_SNAP_TIME).to(Actions.Yaw) -// // Enable and disable as above - -// mappingSnap.from(hydra.LX).to(function(newValue, oldValue) { -// timeSinceLastYaw += deltaTime diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index ef9d61c32d..f473562b9e 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -67,15 +67,22 @@ namespace controller { ScriptingInterface(); virtual ~ScriptingInterface(); + Q_INVOKABLE QVector getAllActions(); + Q_INVOKABLE QVector getAvailableInputs(unsigned int device); + Q_INVOKABLE QString getDeviceName(unsigned int device); + Q_INVOKABLE float getActionValue(int action); + Q_INVOKABLE int findDevice(QString name); + Q_INVOKABLE QVector getDeviceNames(); + Q_INVOKABLE int findAction(QString actionName); + Q_INVOKABLE QVector getActionNames() const; + Q_INVOKABLE float getValue(const int& source) const; Q_INVOKABLE float getButtonValue(StandardButtonChannel source, uint16_t device = 0) const; Q_INVOKABLE float getAxisValue(StandardAxisChannel source, uint16_t device = 0) const; - Q_INVOKABLE glm::mat4 getPoseValue(StandardPoseChannel source, uint16_t device = 0) const; + Q_INVOKABLE Pose getPoseValue(StandardPoseChannel source, uint16_t device = 0) const; Q_INVOKABLE QObject* newMapping(const QString& mappingName = QUuid::createUuid().toString()); Q_INVOKABLE void enableMapping(const QString& mappingName, bool enable = true); - Q_INVOKABLE void disableMapping(const QString& mappingName) { - enableMapping(mappingName, false); - } + Q_INVOKABLE void disableMapping(const QString& mappingName) { enableMapping(mappingName, false); } Q_INVOKABLE QObject* parseMapping(const QString& json); Q_INVOKABLE QObject* loadMapping(const QString& jsonUrl); @@ -102,13 +109,30 @@ namespace controller { Q_INVOKABLE const QVariantMap& getActions() { return _actions; } Q_INVOKABLE const QVariantMap& getStandard() { return _standard; } + bool isMouseCaptured() const { return _mouseCaptured; } + bool isTouchCaptured() const { return _touchCaptured; } + bool isWheelCaptured() const { return _wheelCaptured; } + bool areActionsCaptured() const { return _actionsCaptured; } + static QRegularExpression SANITIZE_NAME_EXPRESSION; public slots: virtual void update(); - virtual void registerControllerTypes(QScriptEngine* engine) = 0; virtual void updateMaps(); + virtual void captureMouseEvents() { _mouseCaptured = true; } + virtual void releaseMouseEvents() { _mouseCaptured = false; } + + virtual void captureTouchEvents() { _touchCaptured = true; } + virtual void releaseTouchEvents() { _touchCaptured = false; } + + virtual void captureWheelEvents() { _wheelCaptured = true; } + virtual void releaseWheelEvents() { _wheelCaptured = false; } + + virtual void captureActionEvents() { _actionsCaptured = true; } + virtual void releaseActionEvents() { _actionsCaptured = false; } + + private: friend class MappingBuilderProxy; friend class RouteBuilderProxy; @@ -141,6 +165,11 @@ namespace controller { ValueMap _overrideValues; MappingMap _mappingsByName; MappingStack _activeMappings; + + bool _mouseCaptured{ false }; + bool _touchCaptured{ false }; + bool _wheelCaptured{ false }; + bool _actionsCaptured{ false }; }; class ScriptEndpoint : public Endpoint { diff --git a/libraries/controllers/src/controllers/StandardController.cpp b/libraries/controllers/src/controllers/StandardController.cpp index 9c423eded2..6b1ada25ed 100644 --- a/libraries/controllers/src/controllers/StandardController.cpp +++ b/libraries/controllers/src/controllers/StandardController.cpp @@ -96,16 +96,65 @@ void StandardController::registerToUserInputMapper(UserInputMapper& mapper) { return availableInputs; }; - proxy->resetDeviceBindings = [this, &mapper] () -> bool { - mapper.removeAllInputChannelsForDevice(_deviceID); - this->assignDefaultInputMapping(mapper); - return true; - }; - mapper.registerStandardDevice(proxy); } void StandardController::assignDefaultInputMapping(UserInputMapper& mapper) { + const float JOYSTICK_MOVE_SPEED = 1.0f; + const float DPAD_MOVE_SPEED = 0.5f; + const float JOYSTICK_YAW_SPEED = 0.5f; + const float JOYSTICK_PITCH_SPEED = 0.25f; + const float BOOM_SPEED = 0.1f; + + // Y axes are flipped (up is negative) + // Left Joystick: Movement, strafing + mapper.addInputChannel(UserInputMapper::TRANSLATE_Z, makeInput(controller::LY), JOYSTICK_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::TRANSLATE_X, makeInput(controller::LX), JOYSTICK_MOVE_SPEED); + // Right Joystick: Camera orientation + mapper.addInputChannel(UserInputMapper::YAW, makeInput(controller::RX), JOYSTICK_YAW_SPEED); + mapper.addInputChannel(UserInputMapper::PITCH, makeInput(controller::RY), JOYSTICK_PITCH_SPEED); + + // Dpad movement + mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(controller::DU), DPAD_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(controller::DD), DPAD_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(controller::DR), DPAD_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(controller::DL), DPAD_MOVE_SPEED); + + // Button controls + mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(controller::Y), DPAD_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(controller::X), DPAD_MOVE_SPEED); + + // Zoom + mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(controller::RT), BOOM_SPEED); + mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(controller::LB), BOOM_SPEED); + + // Hold front right shoulder button for precision controls + // Left Joystick: Movement, strafing + mapper.addInputChannel(UserInputMapper::TRANSLATE_Z, makeInput(controller::LY), makeInput(controller::RB), JOYSTICK_MOVE_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::TRANSLATE_X, makeInput(controller::LY), makeInput(controller::RB), JOYSTICK_MOVE_SPEED / 2.0f); + + // Right Joystick: Camera orientation + mapper.addInputChannel(UserInputMapper::YAW, makeInput(controller::RX), makeInput(controller::RB), JOYSTICK_YAW_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::PITCH, makeInput(controller::RY), makeInput(controller::RB), JOYSTICK_PITCH_SPEED / 2.0f); + + // Dpad movement + mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(controller::DU), makeInput(controller::RB), DPAD_MOVE_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(controller::DD), makeInput(controller::RB), DPAD_MOVE_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(controller::DR), makeInput(controller::RB), DPAD_MOVE_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(controller::DL), makeInput(controller::RB), DPAD_MOVE_SPEED / 2.0f); + + // Button controls + mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(controller::Y), makeInput(controller::RB), DPAD_MOVE_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(controller::X), makeInput(controller::RB), DPAD_MOVE_SPEED / 2.0f); + + // Zoom + mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(controller::RT), makeInput(controller::RB), BOOM_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(controller::LT), makeInput(controller::RB), BOOM_SPEED / 2.0f); + + mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(controller::RB)); + + mapper.addInputChannel(UserInputMapper::ACTION1, makeInput(controller::B)); + mapper.addInputChannel(UserInputMapper::ACTION2, makeInput(controller::A)); } UserInputMapper::Input StandardController::makeInput(controller::StandardButtonChannel button) { diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index fbf1994d87..2c80eb98a1 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -1,7 +1,4 @@ // -// UserInputMapper.cpp -// input-plugins/src/input-plugins -// // Created by Sam Gateau on 4/27/15. // Copyright 2015 High Fidelity, Inc. // @@ -12,14 +9,10 @@ #include "UserInputMapper.h" #include "StandardController.h" -#include "Logging.h" +#include "Logging.h" -const UserInputMapper::Input UserInputMapper::Input::INVALID_INPUT = UserInputMapper::Input(UINT16_MAX); -const uint16_t UserInputMapper::Input::INVALID_DEVICE = INVALID_INPUT.getDevice(); -const uint16_t UserInputMapper::Input::INVALID_CHANNEL = INVALID_INPUT.getChannel(); -const uint16_t UserInputMapper::Input::INVALID_TYPE = (uint16_t)INVALID_INPUT.getType(); -const uint16_t UserInputMapper::Input::ACTIONS_DEVICE = INVALID_DEVICE - (uint16)1; -const uint16_t UserInputMapper::Input::STANDARD_DEVICE = 0; +const uint16_t UserInputMapper::ACTIONS_DEVICE = Input::INVALID_DEVICE - (uint16)1; +const uint16_t UserInputMapper::STANDARD_DEVICE = 0; // Default contruct allocate the poutput size with the current hardcoded action channels UserInputMapper::UserInputMapper() { @@ -46,18 +39,18 @@ bool UserInputMapper::registerDevice(uint16 deviceID, const DeviceProxy::Pointer proxy->_name += QString::number(numberOfType); } - qCDebug(controllers) << "Registered input device <" << proxy->_name << "> deviceID = " << deviceID; + qCDebug(controllers) << "Registered input device <" << proxy->_name << "> deviceID = " << deviceID; _registeredDevices[deviceID] = proxy; return true; } -bool UserInputMapper::registerStandardDevice(const DeviceProxy::Pointer& device) { - device->_name = "Standard"; // Just to make sure - _registeredDevices[getStandardDeviceID()] = device; - return true; -} +bool UserInputMapper::registerStandardDevice(const DeviceProxy::Pointer& device) { + device->_name = "Standard"; // Just to make sure + _registeredDevices[getStandardDeviceID()] = device; + return true; +} UserInputMapper::DeviceProxy::Pointer UserInputMapper::getDeviceProxy(const Input& input) { @@ -110,51 +103,51 @@ QVector UserInputMapper::getDeviceNames() { return result; } -UserInputMapper::Input UserInputMapper::findDeviceInput(const QString& inputName) const { - - // Split the full input name as such: deviceName.inputName - auto names = inputName.split('.'); - - if (names.size() >= 2) { - // Get the device name: - auto deviceName = names[0]; - auto inputName = names[1]; - - int deviceID = findDevice(deviceName); - if (deviceID != Input::INVALID_DEVICE) { - const auto& deviceProxy = _registeredDevices.at(deviceID); - auto deviceInputs = deviceProxy->getAvailabeInputs(); - - for (auto input : deviceInputs) { - if (input.second == inputName) { - return input.first; - } - } - - qCDebug(controllers) << "Couldn\'t find InputChannel named <" << inputName << "> for device <" << deviceName << ">"; - - } else if (deviceName == "Actions") { - deviceID = Input::ACTIONS_DEVICE; - int actionNum = 0; - for (auto action : _actionNames) { - if (action == inputName) { - return Input(Input::ACTIONS_DEVICE, actionNum, ChannelType::AXIS); - } - actionNum++; - } - - qCDebug(controllers) << "Couldn\'t find ActionChannel named <" << inputName << "> among actions"; - - } else { - qCDebug(controllers) << "Couldn\'t find InputDevice named <" << deviceName << ">"; - } - } else { - qCDebug(controllers) << "Couldn\'t understand <" << inputName << "> as a valid inputDevice.inputName"; - } - - return Input(); -} - +UserInputMapper::Input UserInputMapper::findDeviceInput(const QString& inputName) const { + + // Split the full input name as such: deviceName.inputName + auto names = inputName.split('.'); + + if (names.size() >= 2) { + // Get the device name: + auto deviceName = names[0]; + auto inputName = names[1]; + + int deviceID = findDevice(deviceName); + if (deviceID != Input::INVALID_DEVICE) { + const auto& deviceProxy = _registeredDevices.at(deviceID); + auto deviceInputs = deviceProxy->getAvailabeInputs(); + + for (auto input : deviceInputs) { + if (input.second == inputName) { + return input.first; + } + } + + qCDebug(controllers) << "Couldn\'t find InputChannel named <" << inputName << "> for device <" << deviceName << ">"; + + } else if (deviceName == "Actions") { + deviceID = ACTIONS_DEVICE; + int actionNum = 0; + for (auto action : _actionNames) { + if (action == inputName) { + return Input(ACTIONS_DEVICE, actionNum, ChannelType::AXIS); + } + actionNum++; + } + + qCDebug(controllers) << "Couldn\'t find ActionChannel named <" << inputName << "> among actions"; + + } else { + qCDebug(controllers) << "Couldn\'t find InputDevice named <" << deviceName << ">"; + } + } else { + qCDebug(controllers) << "Couldn\'t understand <" << inputName << "> as a valid inputDevice.inputName"; + } + + return Input::INVALID_INPUT; +} + bool UserInputMapper::addInputChannel(Action action, const Input& input, float scale) { @@ -261,7 +254,6 @@ void UserInputMapper::update(float deltaTime) { } int currentTimestamp = 0; - for (auto& channelInput : _actionToInputsMap) { auto& inputMapping = channelInput.second; auto& inputID = inputMapping._input; @@ -430,18 +422,62 @@ void UserInputMapper::registerStandardDevice() { _standardController->registerToUserInputMapper(*this); } -float UserInputMapper::DeviceProxy::getValue(const Input& input, int timestamp) const { - switch (input.getType()) { - case UserInputMapper::ChannelType::BUTTON: - return getButton(input, timestamp) ? 1.0f : 0.0f; - case UserInputMapper::ChannelType::AXIS: - return getAxis(input, timestamp); +static int actionMetaTypeId = qRegisterMetaType(); +static int inputMetaTypeId = qRegisterMetaType(); +static int inputPairMetaTypeId = qRegisterMetaType(); - case UserInputMapper::ChannelType::POSE: - return getPose(input, timestamp)._valid ? 1.0f : 0.0f; +QScriptValue inputToScriptValue(QScriptEngine* engine, const UserInputMapper::Input& input); +void inputFromScriptValue(const QScriptValue& object, UserInputMapper::Input& input); +QScriptValue actionToScriptValue(QScriptEngine* engine, const UserInputMapper::Action& action); +void actionFromScriptValue(const QScriptValue& object, UserInputMapper::Action& action); +QScriptValue inputPairToScriptValue(QScriptEngine* engine, const UserInputMapper::InputPair& inputPair); +void inputPairFromScriptValue(const QScriptValue& object, UserInputMapper::InputPair& inputPair); - default: - return 0.0f; - } -} \ No newline at end of file +QScriptValue inputToScriptValue(QScriptEngine* engine, const UserInputMapper::Input& input) { + QScriptValue obj = engine->newObject(); + obj.setProperty("device", input.getDevice()); + obj.setProperty("channel", input.getChannel()); + obj.setProperty("type", (unsigned short)input.getType()); + obj.setProperty("id", input.getID()); + return obj; +} + +void inputFromScriptValue(const QScriptValue& object, UserInputMapper::Input& input) { + input.setDevice(object.property("device").toUInt16()); + input.setChannel(object.property("channel").toUInt16()); + input.setType(object.property("type").toUInt16()); + input.setID(object.property("id").toInt32()); +} + +QScriptValue actionToScriptValue(QScriptEngine* engine, const UserInputMapper::Action& action) { + QScriptValue obj = engine->newObject(); + auto userInputMapper = DependencyManager::get(); + obj.setProperty("action", (int)action); + obj.setProperty("actionName", userInputMapper->getActionName(action)); + return obj; +} + +void actionFromScriptValue(const QScriptValue& object, UserInputMapper::Action& action) { + action = UserInputMapper::Action(object.property("action").toVariant().toInt()); +} + +QScriptValue inputPairToScriptValue(QScriptEngine* engine, const UserInputMapper::InputPair& inputPair) { + QScriptValue obj = engine->newObject(); + obj.setProperty("input", inputToScriptValue(engine, inputPair.first)); + obj.setProperty("inputName", inputPair.second); + return obj; +} + +void inputPairFromScriptValue(const QScriptValue& object, UserInputMapper::InputPair& inputPair) { + inputFromScriptValue(object.property("input"), inputPair.first); + inputPair.second = QString(object.property("inputName").toVariant().toString()); +} + +void UserInputMapper::registerControllerTypes(QScriptEngine* engine) { + qScriptRegisterSequenceMetaType >(engine); + qScriptRegisterSequenceMetaType >(engine); + qScriptRegisterMetaType(engine, actionToScriptValue, actionFromScriptValue); + qScriptRegisterMetaType(engine, inputToScriptValue, inputFromScriptValue); + qScriptRegisterMetaType(engine, inputPairToScriptValue, inputPairFromScriptValue); +} diff --git a/libraries/controllers/src/controllers/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h index 8b466d79c9..b8bc0850cf 100644 --- a/libraries/controllers/src/controllers/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -1,7 +1,4 @@ // -// UserInputMapper.h -// input-plugins/src/input-plugins -// // Created by Sam Gateau on 4/27/15. // Copyright 2015 High Fidelity, Inc. // @@ -9,6 +6,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#pragma once #ifndef hifi_UserInputMapper_h #define hifi_UserInputMapper_h @@ -20,6 +18,10 @@ #include #include +#include "Pose.h" +#include "Input.h" +#include "DeviceProxy.h" + class StandardController; typedef std::shared_ptr StandardControllerPointer; @@ -30,86 +32,22 @@ class UserInputMapper : public QObject, public Dependency { public: ~UserInputMapper(); + using DeviceProxy = controller::DeviceProxy; + using PoseValue = controller::Pose; + using Input = controller::Input; + using ChannelType = controller::ChannelType; + typedef unsigned short uint16; typedef unsigned int uint32; - enum class ChannelType { - UNKNOWN = 0, - BUTTON = 1, - AXIS, - POSE, - }; + static void registerControllerTypes(QScriptEngine* engine); - // Input is the unique identifier to find a n input channel of a particular device - // Devices are responsible for registering to the UseInputMapper so their input channels can be sued and mapped - // to the Action channels - class Input { - public: - union { - struct { - uint16 _device; // Up to 64K possible devices - uint16 _channel : 13; // 2^13 possible channel per Device - uint16 _type : 2; // 2 bits to store the Type directly in the ID - uint16 _padding : 1; // 2 bits to store the Type directly in the ID - }; - uint32 _id = 0; // by default Input is 0 meaning invalid - }; - - bool isValid() const { return (_id != 0); } - - uint16 getDevice() const { return _device; } - uint16 getChannel() const { return _channel; } - uint32 getID() const { return _id; } - ChannelType getType() const { return (ChannelType) _type; } - - void setDevice(uint16 device) { _device = device; } - void setChannel(uint16 channel) { _channel = channel; } - void setType(uint16 type) { _type = type; } - void setID(uint32 ID) { _id = ID; } - - bool isButton() const { return getType() == ChannelType::BUTTON; } - bool isAxis() const { return getType() == ChannelType::AXIS; } - bool isPose() const { return getType() == ChannelType::POSE; } - - // WORKAROUND: the explicit initializer here avoids a bug in GCC-4.8.2 (but not found in 4.9.2) - // where the default initializer (a C++-11ism) for the union data above is not applied. - explicit Input() : _id(0) {} - explicit Input(uint32 id) : _id(id) {} - explicit Input(uint16 device, uint16 channel, ChannelType type) : _device(device), _channel(channel), _type(uint16(type)), _padding(0) {} - Input(const Input& src) : _id(src._id) {} - Input& operator = (const Input& src) { _id = src._id; return (*this); } - bool operator ==(const Input& right) const { return _id == right._id; } - bool operator < (const Input& src) const { return _id < src._id; } - - static const Input INVALID_INPUT; - static const uint16 INVALID_DEVICE; - static const uint16 INVALID_CHANNEL; - static const uint16 INVALID_TYPE; - static const uint16 ACTIONS_DEVICE; - static const uint16 STANDARD_DEVICE; - }; + static const uint16 ACTIONS_DEVICE; + static const uint16 STANDARD_DEVICE; // Modifiers are just button inputID typedef std::vector< Input > Modifiers; - - class PoseValue { - public: - glm::vec3 _translation{ 0.0f }; - glm::quat _rotation; - bool _valid; - - PoseValue() : _valid(false) {}; - PoseValue(glm::vec3 translation, glm::quat rotation) : _translation(translation), _rotation(rotation), _valid(true) {} - PoseValue(const PoseValue&) = default; - PoseValue& operator = (const PoseValue&) = default; - bool operator ==(const PoseValue& right) const { return _translation == right.getTranslation() && _rotation == right.getRotation() && _valid == right.isValid(); } - - bool isValid() const { return _valid; } - glm::vec3 getTranslation() const { return _translation; } - glm::quat getRotation() const { return _rotation; } - }; - typedef std::function ButtonGetter; typedef std::function AxisGetter; typedef std::function PoseGetter; @@ -119,22 +57,6 @@ public: typedef QVector AvailableInput; - class DeviceProxy { - public: - DeviceProxy(QString name) : _baseName(name), _name(name) {} - const QString& getBaseName() const { return _baseName; } - const QString& getName() const { return _name; } - - QString _baseName; - QString _name; - ButtonGetter getButton = [] (const Input& input, int timestamp) -> bool { return false; }; - AxisGetter getAxis = [] (const Input& input, int timestamp) -> float { return 0.0f; }; - PoseGetter getPose = [] (const Input& input, int timestamp) -> PoseValue { return PoseValue(); }; - AvailableInputGetter getAvailabeInputs = [] () -> AvailableInput { return QVector(); }; - ResetBindings resetDeviceBindings = [] () -> bool { return true; }; - float getValue(const Input& input, int timestamp = 0) const; - typedef std::shared_ptr Pointer; - }; // GetFreeDeviceID should be called before registering a device to use an ID not used by a different device. uint16 getFreeDeviceID() { return _nextFreeDeviceID++; } @@ -222,7 +144,7 @@ public: // Return true if theinput channel is created correctly, false either bool addInputChannel(Action action, const Input& input, float scale = 1.0f); bool addInputChannel(Action action, const Input& input, const Input& modifer, float scale = 1.0f); - + // Under the hood, the input channels are organized in map sorted on the _output // The InputChannel class is just the full values describing the input channel in one object class InputChannel { @@ -276,7 +198,7 @@ public: typedef std::map DevicesMap; DevicesMap getDevices() { return _registeredDevices; } - uint16 getStandardDeviceID() const { return Input::STANDARD_DEVICE; } + uint16 getStandardDeviceID() const { return STANDARD_DEVICE; } DeviceProxy::Pointer getStandardDevice() { return _registeredDevices[getStandardDeviceID()]; } signals: @@ -288,7 +210,7 @@ protected: StandardControllerPointer _standardController; DevicesMap _registeredDevices; - uint16 _nextFreeDeviceID = Input::STANDARD_DEVICE + 1; + uint16 _nextFreeDeviceID = STANDARD_DEVICE + 1; typedef std::map InputToMoModifiersMap; InputToMoModifiersMap _inputToModifiersMap; @@ -309,6 +231,7 @@ protected: }; Q_DECLARE_METATYPE(UserInputMapper::InputPair) +Q_DECLARE_METATYPE(UserInputMapper::PoseValue) Q_DECLARE_METATYPE(QVector) Q_DECLARE_METATYPE(UserInputMapper::Input) Q_DECLARE_METATYPE(UserInputMapper::InputChannel) diff --git a/libraries/input-plugins/src/input-plugins/Joystick.cpp b/libraries/input-plugins/src/input-plugins/Joystick.cpp index aa5bbbba07..09e81f7346 100644 --- a/libraries/input-plugins/src/input-plugins/Joystick.cpp +++ b/libraries/input-plugins/src/input-plugins/Joystick.cpp @@ -143,3 +143,63 @@ void Joystick::registerToUserInputMapper(UserInputMapper& mapper) { mapper.registerDevice(_deviceID, proxy); } + +void Joystick::assignDefaultInputMapping(UserInputMapper& mapper) { +#ifdef HAVE_SDL2 + const float JOYSTICK_MOVE_SPEED = 1.0f; + const float DPAD_MOVE_SPEED = 0.5f; + const float JOYSTICK_YAW_SPEED = 0.5f; + const float JOYSTICK_PITCH_SPEED = 0.25f; + const float BOOM_SPEED = 0.1f; + + // Y axes are flipped (up is negative) + // Left Joystick: Movement, strafing + mapper.addInputChannel(UserInputMapper::TRANSLATE_Z, makeInput(controller::LY), JOYSTICK_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::TRANSLATE_X, makeInput(controller::LX), JOYSTICK_MOVE_SPEED); + // Right Joystick: Camera orientation + mapper.addInputChannel(UserInputMapper::YAW, makeInput(controller::RX), JOYSTICK_YAW_SPEED); + mapper.addInputChannel(UserInputMapper::PITCH, makeInput(controller::RY), JOYSTICK_PITCH_SPEED); + + // Dpad movement + mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(controller::DU), DPAD_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(controller::DD), DPAD_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(controller::DR), DPAD_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(controller::DL), DPAD_MOVE_SPEED); + + // Button controls + mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(controller::Y), DPAD_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(controller::X), DPAD_MOVE_SPEED); + + // Zoom + mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(controller::RT), BOOM_SPEED); + mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(controller::LT), BOOM_SPEED); + + // Hold front right shoulder button for precision controls + // Left Joystick: Movement, strafing + mapper.addInputChannel(UserInputMapper::TRANSLATE_Z, makeInput(controller::LY), makeInput(controller::RB), JOYSTICK_MOVE_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::TRANSLATE_X, makeInput(controller::LY), makeInput(controller::RB), JOYSTICK_MOVE_SPEED / 2.0f); + + // Right Joystick: Camera orientation + mapper.addInputChannel(UserInputMapper::YAW, makeInput(controller::RX), makeInput(controller::RB), JOYSTICK_YAW_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::PITCH, makeInput(controller::RY), makeInput(controller::RB), JOYSTICK_PITCH_SPEED / 2.0f); + + // Dpad movement + mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(controller::DU), makeInput(controller::RB), DPAD_MOVE_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(controller::DD), makeInput(controller::RB), DPAD_MOVE_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(controller::DR), makeInput(controller::RB), DPAD_MOVE_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(controller::DL), makeInput(controller::RB), DPAD_MOVE_SPEED / 2.0f); + + // Button controls + mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(controller::Y), makeInput(controller::RB), DPAD_MOVE_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(controller::X), makeInput(controller::RB), DPAD_MOVE_SPEED / 2.0f); + + // Zoom + mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(controller::RT), makeInput(controller::RB), BOOM_SPEED / 2.0f); + mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(controller::LT), makeInput(controller::RB), BOOM_SPEED / 2.0f); + + mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(controller::RB)); + + mapper.addInputChannel(UserInputMapper::ACTION1, makeInput(controller::B)); + mapper.addInputChannel(UserInputMapper::ACTION2, makeInput(controller::A)); +#endif +} \ No newline at end of file diff --git a/libraries/input-plugins/src/input-plugins/Joystick.h b/libraries/input-plugins/src/input-plugins/Joystick.h index 8e4cdb365f..ad99774737 100644 --- a/libraries/input-plugins/src/input-plugins/Joystick.h +++ b/libraries/input-plugins/src/input-plugins/Joystick.h @@ -37,6 +37,7 @@ public: // Device functions virtual void registerToUserInputMapper(UserInputMapper& mapper) override; + virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; virtual void update(float deltaTime, bool jointsCaptured) override; virtual void focusOutEvent() override; diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index 9d3d06ecb7..e8cebd8e54 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -449,6 +449,17 @@ void SixenseManager::handlePoseEvent(glm::vec3 position, glm::quat rotation, boo #endif // HAVE_SIXENSE } +static const auto L0 = controller::BACK; +static const auto L1 = controller::DL; +static const auto L2 = controller::DD; +static const auto L3 = controller::DR; +static const auto L4 = controller::DU; +static const auto R0 = controller::START; +static const auto R1 = controller::X; +static const auto R2 = controller::A; +static const auto R3 = controller::B; +static const auto R4 = controller::Y; + void SixenseManager::registerToUserInputMapper(UserInputMapper& mapper) { // Grab the current free device ID _deviceID = mapper.getFreeDeviceID(); @@ -459,31 +470,75 @@ void SixenseManager::registerToUserInputMapper(UserInputMapper& mapper) { using namespace controller; proxy->getAvailabeInputs = [this]() -> QVector { QVector availableInputs; - availableInputs.append(UserInputMapper::InputPair(makeInput(BACK), "L0")); - availableInputs.append(UserInputMapper::InputPair(makeInput(DL), "L1")); - availableInputs.append(UserInputMapper::InputPair(makeInput(DD), "L2")); - availableInputs.append(UserInputMapper::InputPair(makeInput(DR), "L3")); - availableInputs.append(UserInputMapper::InputPair(makeInput(DU), "L4")); + availableInputs.append(UserInputMapper::InputPair(makeInput(L0), "L0")); + availableInputs.append(UserInputMapper::InputPair(makeInput(L1), "L1")); + availableInputs.append(UserInputMapper::InputPair(makeInput(L2), "L2")); + availableInputs.append(UserInputMapper::InputPair(makeInput(L3), "L3")); + availableInputs.append(UserInputMapper::InputPair(makeInput(L4), "L4")); availableInputs.append(UserInputMapper::InputPair(makeInput(LB), "LB")); availableInputs.append(UserInputMapper::InputPair(makeInput(LS), "LS")); availableInputs.append(UserInputMapper::InputPair(makeInput(LX), "LX")); availableInputs.append(UserInputMapper::InputPair(makeInput(LY), "LY")); availableInputs.append(UserInputMapper::InputPair(makeInput(LT), "LT")); - availableInputs.append(UserInputMapper::InputPair(makeInput(START), "R0")); - availableInputs.append(UserInputMapper::InputPair(makeInput(X), "R1")); - availableInputs.append(UserInputMapper::InputPair(makeInput(A), "R2")); - availableInputs.append(UserInputMapper::InputPair(makeInput(B), "R3")); - availableInputs.append(UserInputMapper::InputPair(makeInput(Y), "R4")); + availableInputs.append(UserInputMapper::InputPair(makeInput(R0), "R0")); + availableInputs.append(UserInputMapper::InputPair(makeInput(R1), "R1")); + availableInputs.append(UserInputMapper::InputPair(makeInput(R2), "R2")); + availableInputs.append(UserInputMapper::InputPair(makeInput(R3), "R3")); + availableInputs.append(UserInputMapper::InputPair(makeInput(R4), "R4")); availableInputs.append(UserInputMapper::InputPair(makeInput(RB), "RB")); availableInputs.append(UserInputMapper::InputPair(makeInput(RS), "RS")); availableInputs.append(UserInputMapper::InputPair(makeInput(RX), "RX")); availableInputs.append(UserInputMapper::InputPair(makeInput(RY), "RY")); availableInputs.append(UserInputMapper::InputPair(makeInput(RT), "RT")); + availableInputs.append(UserInputMapper::InputPair(makeInput(LEFT), "LeftPose")); + availableInputs.append(UserInputMapper::InputPair(makeInput(RIGHT), "RightPose")); return availableInputs; }; mapper.registerDevice(_deviceID, proxy); } +void SixenseManager::assignDefaultInputMapping(UserInputMapper& mapper) { + const float JOYSTICK_MOVE_SPEED = 1.0f; + const float JOYSTICK_YAW_SPEED = 0.5f; + const float JOYSTICK_PITCH_SPEED = 0.25f; + const float BUTTON_MOVE_SPEED = 1.0f; + const float BOOM_SPEED = 0.1f; + using namespace controller; + + // Left Joystick: Movement, strafing + mapper.addInputChannel(UserInputMapper::TRANSLATE_Z, makeInput(LY), JOYSTICK_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::TRANSLATE_X, makeInput(LX), JOYSTICK_MOVE_SPEED); + + // Right Joystick: Camera orientation + mapper.addInputChannel(UserInputMapper::YAW, makeInput(RX), JOYSTICK_YAW_SPEED); + mapper.addInputChannel(UserInputMapper::PITCH, makeInput(RY), JOYSTICK_PITCH_SPEED); + + // Buttons + mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(L3), BOOM_SPEED); + mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(L1), BOOM_SPEED); + + mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(R3), BUTTON_MOVE_SPEED); + mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(R1), BUTTON_MOVE_SPEED); + + mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(L2)); + mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(R2)); + + mapper.addInputChannel(UserInputMapper::ACTION1, makeInput(L4)); + mapper.addInputChannel(UserInputMapper::ACTION2, makeInput(R4)); + + // FIXME +// mapper.addInputChannel(UserInputMapper::LEFT_HAND, makeInput(LEFT_HAND)); +// mapper.addInputChannel(UserInputMapper::RIGHT_HAND, makeInput(RIGHT_HAND)); + + mapper.addInputChannel(UserInputMapper::LEFT_HAND_CLICK, makeInput(LT)); + mapper.addInputChannel(UserInputMapper::RIGHT_HAND_CLICK, makeInput(RT)); + + // TODO find a mechanism to allow users to navigate the context menu via + mapper.addInputChannel(UserInputMapper::CONTEXT_MENU, makeInput(L0)); + mapper.addInputChannel(UserInputMapper::TOGGLE_MUTE, makeInput(R0)); + +} + // virtual void SixenseManager::saveSettings() const { Settings settings; diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index 2e7dd3223d..897ca72940 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -61,6 +61,8 @@ public: // Device functions virtual void registerToUserInputMapper(UserInputMapper& mapper) override; + virtual void assignDefaultInputMapping(UserInputMapper& mapper) override; + virtual void update(float deltaTime, bool jointsCaptured) override; virtual void focusOutEvent() override; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 0dfc2fe09e..dc08fd7a69 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -308,8 +308,6 @@ void ScriptEngine::init() { registerGlobalObject("Script", this); registerGlobalObject("Audio", &AudioScriptingInterface::getInstance()); - auto scriptingInterface = DependencyManager::get(); - registerGlobalObject("Controller", scriptingInterface.data()); registerGlobalObject("Entities", entityScriptingInterface.data()); registerGlobalObject("Quat", &_quatLibrary); registerGlobalObject("Vec3", &_vec3Library); @@ -319,11 +317,9 @@ void ScriptEngine::init() { // constants globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); - if (scriptingInterface) { - scriptingInterface->registerControllerTypes(this); - } - - + auto scriptingInterface = DependencyManager::get(); + registerGlobalObject("Controller", scriptingInterface.data()); + UserInputMapper::registerControllerTypes(this); } void ScriptEngine::registerValue(const QString& valueName, QScriptValue value) {