diff --git a/examples/controllers/controllerMappings.js b/examples/controllers/controllerMappings.js index 4de173f16c..66efa63676 100644 --- a/examples/controllers/controllerMappings.js +++ b/examples/controllers/controllerMappings.js @@ -1,90 +1,90 @@ - -// -// controllerScriptingExamples.js -// examples -// -// Created by Sam Gondelman on 6/2/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 -// - -// Assumes you only have the default keyboard connected - -/*myFirstMapping = function() { -return { - "name": "example", - "channels": [ - { "from": "Keyboard.W", "to": "Actions.LONGITUDINAL_FORWARD" }, - { "from": "Keyboard.S", "to": "Actions.LONGITUDINAL_BACKWARD" }, - - { "from": "Keyboard.Left", "to": "Actions.LATERAL_LEFT" }, - { "from": "Keyboard.Right", "to": "Actions.LATERAL_RIGHT" }, - - { "from": "Keyboard.A", "to": "Actions.YAW_LEFT" }, - { "from": "Keyboard.D", "to": "Actions.YAW_RIGHT" }, - - { "from": "Keyboard.C", "to": "Actions.VERTICAL_DOWN" }, - { "from": "Keyboard.E", "to": "Actions.VERTICAL_UP" }, - { - "from": "Standard.LX", - "filters": [ { - "type": "scale", - "params": [2.0], - } - ], - "to": "Actions.LATERAL_LEFT", - }, { - "from": "Keyboard.B", - "to": "Actions.Yaw" - } - ] -} -} -*/ -mySecondMapping = function() { -return { - "name": "example2", - "channels": [ - { "from": "Standard.LY", "to": "Actions.TranslateZ" }, - { "from": "Standard.LX", "to": "Actions.Yaw" }, - ] -} -} - -//Script.include('mapping-test0.json'); -/*var myFirstMappingJSON = myFirstMapping(); -print('myFirstMappingJSON' + JSON.stringify(myFirstMappingJSON)); - -var mapping = Controller.parseMapping(JSON.stringify(myFirstMappingJSON)); - - -Controller.enableMapping("example3"); - -var mySecondMappingJSON = mySecondMapping(); -print('mySecondMappingJSON' + JSON.stringify(mySecondMappingJSON)); - -var mapping2 = Controller.parseMapping(JSON.stringify(mySecondMappingJSON)); -mapping2.enable(); - -Controller.enableMapping("example2"); -*/ -var mapping3 = Controller.loadMapping(Script.resolvePath("example3.json")); -Controller.enableMapping("example3"); - -/* -Object.keys(Controller.Standard).forEach(function (input) { - print("Controller.Standard." + input + ":" + Controller.Standard[input]); -}); - -Object.keys(Controller.Hardware).forEach(function (deviceName) { - Object.keys(Controller.Hardware[deviceName]).forEach(function (input) { - print("Controller.Hardware." + deviceName + "." + input + ":" + Controller.Hardware[deviceName][input]); - }); -}); - -Object.keys(Controller.Actions).forEach(function (actionName) { - print("Controller.Actions." + actionName + ":" + Controller.Actions[actionName]); -}); + +// +// controllerScriptingExamples.js +// examples +// +// Created by Sam Gondelman on 6/2/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 +// + +// Assumes you only have the default keyboard connected + +/*myFirstMapping = function() { +return { + "name": "example", + "channels": [ + { "from": "Keyboard.W", "to": "Actions.LONGITUDINAL_FORWARD" }, + { "from": "Keyboard.S", "to": "Actions.LONGITUDINAL_BACKWARD" }, + + { "from": "Keyboard.Left", "to": "Actions.LATERAL_LEFT" }, + { "from": "Keyboard.Right", "to": "Actions.LATERAL_RIGHT" }, + + { "from": "Keyboard.A", "to": "Actions.YAW_LEFT" }, + { "from": "Keyboard.D", "to": "Actions.YAW_RIGHT" }, + + { "from": "Keyboard.C", "to": "Actions.VERTICAL_DOWN" }, + { "from": "Keyboard.E", "to": "Actions.VERTICAL_UP" }, + { + "from": "Standard.LX", + "filters": [ { + "type": "scale", + "params": [2.0], + } + ], + "to": "Actions.LATERAL_LEFT", + }, { + "from": "Keyboard.B", + "to": "Actions.Yaw" + } + ] +} +} +*/ +mySecondMapping = function() { +return { + "name": "example2", + "channels": [ + { "from": "Standard.LY", "to": "Actions.TranslateZ" }, + { "from": "Standard.LX", "to": "Actions.Yaw" }, + ] +} +} + +//Script.include('mapping-test0.json'); +/*var myFirstMappingJSON = myFirstMapping(); +print('myFirstMappingJSON' + JSON.stringify(myFirstMappingJSON)); + +var mapping = Controller.parseMapping(JSON.stringify(myFirstMappingJSON)); + + +Controller.enableMapping("example3"); + +var mySecondMappingJSON = mySecondMapping(); +print('mySecondMappingJSON' + JSON.stringify(mySecondMappingJSON)); + +var mapping2 = Controller.parseMapping(JSON.stringify(mySecondMappingJSON)); +mapping2.enable(); + +Controller.enableMapping("example2"); +*/ +var mapping3 = Controller.loadMapping(Script.resolvePath("example3.json")); +Controller.enableMapping("example3"); + +/* +Object.keys(Controller.Standard).forEach(function (input) { + print("Controller.Standard." + input + ":" + Controller.Standard[input]); +}); + +Object.keys(Controller.Hardware).forEach(function (deviceName) { + Object.keys(Controller.Hardware[deviceName]).forEach(function (input) { + print("Controller.Hardware." + deviceName + "." + input + ":" + Controller.Hardware[deviceName][input]); + }); +}); + +Object.keys(Controller.Actions).forEach(function (actionName) { + print("Controller.Actions." + actionName + ":" + Controller.Actions[actionName]); +}); */ \ No newline at end of file diff --git a/interface/resources/controllers/hydra.json b/interface/resources/controllers/hydra.json index 25c8db61cb..c20d54b7c1 100644 --- a/interface/resources/controllers/hydra.json +++ b/interface/resources/controllers/hydra.json @@ -23,6 +23,9 @@ { "from": "Hydra.R1", "to": "Standard.X" }, { "from": "Hydra.R2", "to": "Standard.A" }, { "from": "Hydra.R3", "to": "Standard.B" }, - { "from": "Hydra.R4", "to": "Standard.Y" } - ] + { "from": "Hydra.R4", "to": "Standard.Y" }, + + { "from": "Hydra.LeftHand", "to": "Standard.LeftHand" }, + { "from": "Hydra.RightHand", "to": "Standard.RightHand" } + ] } diff --git a/interface/resources/controllers/standard.json b/interface/resources/controllers/standard.json index 364d24ae16..b662e5394d 100644 --- a/interface/resources/controllers/standard.json +++ b/interface/resources/controllers/standard.json @@ -36,6 +36,8 @@ "from": "Standard.LT", "to": "Actions.BOOM_OUT", "filters": [ { "type": "scale", "scale": 0.1 } ] - } + }, + { "from": "Standard.LeftHand", "to": "Actions.LEFT_HAND" }, + { "from": "Standard.RightHand", "to": "Actions.RIGHT_HAND" } ] } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c3eb3dfe7c..4e23e19652 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2725,12 +2725,12 @@ void Application::update(float deltaTime) { myAvatar->clearDriveKeys(); if (_myCamera.getMode() != CAMERA_MODE_INDEPENDENT) { if (!_controllerScriptingInterface->areActionsCaptured()) { - myAvatar->setDriveKeys(FWD, userInputMapper->getActionState(controller::LONGITUDINAL_FORWARD)); - myAvatar->setDriveKeys(BACK, userInputMapper->getActionState(controller::LONGITUDINAL_BACKWARD)); - myAvatar->setDriveKeys(UP, userInputMapper->getActionState(controller::VERTICAL_UP)); - myAvatar->setDriveKeys(DOWN, userInputMapper->getActionState(controller::VERTICAL_DOWN)); - myAvatar->setDriveKeys(LEFT, userInputMapper->getActionState(controller::LATERAL_LEFT)); - myAvatar->setDriveKeys(RIGHT, userInputMapper->getActionState(controller::LATERAL_RIGHT)); + myAvatar->setDriveKeys(FWD, userInputMapper->getActionState(controller::Action::LONGITUDINAL_FORWARD)); + myAvatar->setDriveKeys(BACK, userInputMapper->getActionState(controller::Action::LONGITUDINAL_BACKWARD)); + myAvatar->setDriveKeys(UP, userInputMapper->getActionState(controller::Action::VERTICAL_UP)); + myAvatar->setDriveKeys(DOWN, userInputMapper->getActionState(controller::Action::VERTICAL_DOWN)); + myAvatar->setDriveKeys(LEFT, userInputMapper->getActionState(controller::Action::LATERAL_LEFT)); + myAvatar->setDriveKeys(RIGHT, userInputMapper->getActionState(controller::Action::LATERAL_RIGHT)); if (deltaTime > FLT_EPSILON) { // For rotations what we really want are meausures of "angles per second" (in order to prevent // fps-dependent spin rates) so we need to scale the units of the controller contribution. @@ -2738,25 +2738,25 @@ void Application::update(float deltaTime) { // controllers to provide a delta_per_second value rather than a raw delta.) const float EXPECTED_FRAME_RATE = 60.0f; float timeFactor = EXPECTED_FRAME_RATE * deltaTime; - myAvatar->setDriveKeys(ROT_UP, userInputMapper->getActionState(controller::PITCH_UP) / timeFactor); - myAvatar->setDriveKeys(ROT_DOWN, userInputMapper->getActionState(controller::PITCH_DOWN) / timeFactor); - myAvatar->setDriveKeys(ROT_LEFT, userInputMapper->getActionState(controller::YAW_LEFT) / timeFactor); - myAvatar->setDriveKeys(ROT_RIGHT, userInputMapper->getActionState(controller::YAW_RIGHT) / timeFactor); + myAvatar->setDriveKeys(ROT_UP, userInputMapper->getActionState(controller::Action::PITCH_UP) / timeFactor); + myAvatar->setDriveKeys(ROT_DOWN, userInputMapper->getActionState(controller::Action::PITCH_DOWN) / timeFactor); + myAvatar->setDriveKeys(ROT_LEFT, userInputMapper->getActionState(controller::Action::YAW_LEFT) / timeFactor); + myAvatar->setDriveKeys(ROT_RIGHT, userInputMapper->getActionState(controller::Action::YAW_RIGHT) / timeFactor); } } - myAvatar->setDriveKeys(BOOM_IN, userInputMapper->getActionState(controller::BOOM_IN)); - myAvatar->setDriveKeys(BOOM_OUT, userInputMapper->getActionState(controller::BOOM_OUT)); + myAvatar->setDriveKeys(BOOM_IN, userInputMapper->getActionState(controller::Action::BOOM_IN)); + myAvatar->setDriveKeys(BOOM_OUT, userInputMapper->getActionState(controller::Action::BOOM_OUT)); } - controller::Pose leftHand = userInputMapper->getPoseState(controller::LEFT_HAND); - controller::Pose rightHand = userInputMapper->getPoseState(controller::RIGHT_HAND); + controller::Pose leftHand = userInputMapper->getPoseState(controller::Action::LEFT_HAND); + controller::Pose rightHand = userInputMapper->getPoseState(controller::Action::RIGHT_HAND); Hand* hand = DependencyManager::get()->getMyAvatar()->getHand(); - setPalmData(hand, leftHand, deltaTime, LEFT_HAND_INDEX, userInputMapper->getActionState(controller::LEFT_HAND_CLICK)); - setPalmData(hand, rightHand, deltaTime, RIGHT_HAND_INDEX, userInputMapper->getActionState(controller::RIGHT_HAND_CLICK)); + setPalmData(hand, leftHand, deltaTime, LEFT_HAND_INDEX, userInputMapper->getActionState(controller::Action::LEFT_HAND_CLICK)); + setPalmData(hand, rightHand, deltaTime, RIGHT_HAND_INDEX, userInputMapper->getActionState(controller::Action::RIGHT_HAND_CLICK)); if (Menu::getInstance()->isOptionChecked(MenuOption::EnableHandMouseInput)) { - emulateMouse(hand, userInputMapper->getActionState(controller::LEFT_HAND_CLICK), - userInputMapper->getActionState(controller::SHIFT), LEFT_HAND_INDEX); - emulateMouse(hand, userInputMapper->getActionState(controller::RIGHT_HAND_CLICK), - userInputMapper->getActionState(controller::SHIFT), RIGHT_HAND_INDEX); + emulateMouse(hand, userInputMapper->getActionState(controller::Action::LEFT_HAND_CLICK), + userInputMapper->getActionState(controller::Action::SHIFT), LEFT_HAND_INDEX); + emulateMouse(hand, userInputMapper->getActionState(controller::Action::RIGHT_HAND_CLICK), + userInputMapper->getActionState(controller::Action::SHIFT), RIGHT_HAND_INDEX); } updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process... diff --git a/libraries/controllers/src/controllers/Actions.cpp b/libraries/controllers/src/controllers/Actions.cpp index 2c5cf84931..78ba42db8b 100644 --- a/libraries/controllers/src/controllers/Actions.cpp +++ b/libraries/controllers/src/controllers/Actions.cpp @@ -19,33 +19,33 @@ namespace controller { proxy->getAxis = [this](const Input& input, int timestamp) -> float { return 0; }; proxy->getAvailabeInputs = [this]() -> QVector { QVector availableInputs{ - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, LONGITUDINAL_BACKWARD, ChannelType::AXIS), "LONGITUDINAL_BACKWARD"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, LONGITUDINAL_FORWARD, ChannelType::AXIS), "LONGITUDINAL_FORWARD"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, LATERAL_LEFT, ChannelType::AXIS), "LATERAL_LEFT"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, LATERAL_RIGHT, ChannelType::AXIS), "LATERAL_RIGHT"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, VERTICAL_DOWN, ChannelType::AXIS), "VERTICAL_DOWN"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, VERTICAL_UP, ChannelType::AXIS), "VERTICAL_UP"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, YAW_LEFT, ChannelType::AXIS), "YAW_LEFT"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, YAW_RIGHT, ChannelType::AXIS), "YAW_RIGHT"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, PITCH_DOWN, ChannelType::AXIS), "PITCH_DOWN"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, PITCH_UP, ChannelType::AXIS), "PITCH_UP"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, BOOM_IN, ChannelType::AXIS), "BOOM_IN"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, BOOM_OUT, ChannelType::AXIS), "BOOM_OUT"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, LEFT_HAND, ChannelType::POSE), "LEFT_HAND"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, RIGHT_HAND, ChannelType::POSE), "RIGHT_HAND"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, LEFT_HAND_CLICK, ChannelType::BUTTON), "LEFT_HAND_CLICK"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, RIGHT_HAND_CLICK, ChannelType::BUTTON), "RIGHT_HAND_CLICK"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, SHIFT, ChannelType::BUTTON), "SHIFT"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, ACTION1, ChannelType::BUTTON), "ACTION1"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, ACTION2, ChannelType::BUTTON), "ACTION2"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, CONTEXT_MENU, ChannelType::BUTTON), "CONTEXT_MENU"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, TOGGLE_MUTE, ChannelType::AXIS), "TOGGLE_MUTE"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, TRANSLATE_X, ChannelType::AXIS), "TranslateX"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, TRANSLATE_Y, ChannelType::AXIS), "TranslateY"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, TRANSLATE_Z, ChannelType::AXIS), "TranslateZ"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, ROLL, ChannelType::AXIS), "Roll"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, PITCH, ChannelType::AXIS), "Pitch"), - Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, YAW, ChannelType::AXIS), "Yaw") + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::LONGITUDINAL_BACKWARD), ChannelType::AXIS), "LONGITUDINAL_BACKWARD"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::LONGITUDINAL_FORWARD), ChannelType::AXIS), "LONGITUDINAL_FORWARD"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::LATERAL_LEFT), ChannelType::AXIS), "LATERAL_LEFT"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::LATERAL_RIGHT), ChannelType::AXIS), "LATERAL_RIGHT"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::VERTICAL_DOWN), ChannelType::AXIS), "VERTICAL_DOWN"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::VERTICAL_UP), ChannelType::AXIS), "VERTICAL_UP"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::YAW_LEFT), ChannelType::AXIS), "YAW_LEFT"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::YAW_RIGHT), ChannelType::AXIS), "YAW_RIGHT"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::PITCH_DOWN), ChannelType::AXIS), "PITCH_DOWN"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::PITCH_UP), ChannelType::AXIS), "PITCH_UP"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::BOOM_IN), ChannelType::AXIS), "BOOM_IN"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::BOOM_OUT), ChannelType::AXIS), "BOOM_OUT"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::LEFT_HAND), ChannelType::POSE), "LEFT_HAND"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::RIGHT_HAND), ChannelType::POSE), "RIGHT_HAND"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::LEFT_HAND_CLICK), ChannelType::BUTTON), "LEFT_HAND_CLICK"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::RIGHT_HAND_CLICK), ChannelType::BUTTON), "RIGHT_HAND_CLICK"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::SHIFT), ChannelType::BUTTON), "SHIFT"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::ACTION1), ChannelType::BUTTON), "ACTION1"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::ACTION2), ChannelType::BUTTON), "ACTION2"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::CONTEXT_MENU), ChannelType::BUTTON), "CONTEXT_MENU"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::TOGGLE_MUTE), ChannelType::AXIS), "TOGGLE_MUTE"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::TRANSLATE_X), ChannelType::AXIS), "TranslateX"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::TRANSLATE_Y), ChannelType::AXIS), "TranslateY"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::TRANSLATE_Z), ChannelType::AXIS), "TranslateZ"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::ROLL), ChannelType::AXIS), "Roll"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::PITCH), ChannelType::AXIS), "Pitch"), + Input::NamedPair(Input(UserInputMapper::ACTIONS_DEVICE, toInt(Action::YAW), ChannelType::AXIS), "Yaw") }; return availableInputs; }; diff --git a/libraries/controllers/src/controllers/Actions.h b/libraries/controllers/src/controllers/Actions.h index f4e9f665e2..77a772de9e 100644 --- a/libraries/controllers/src/controllers/Actions.h +++ b/libraries/controllers/src/controllers/Actions.h @@ -19,7 +19,7 @@ namespace controller { // Actions are the output channels of the Mapper, that's what the InputChannel map to // For now the Actions are hardcoded, this is bad, but we will fix that in the near future -enum Action { +enum class Action { TRANSLATE_X = 0, TRANSLATE_Y, TRANSLATE_Z, @@ -71,6 +71,8 @@ enum Action { NUM_ACTIONS, }; +template +int toInt(T enumValue) { return static_cast(enumValue); } class ActionsDevice : public QObject, public InputDevice { Q_OBJECT diff --git a/libraries/controllers/src/controllers/Endpoint.h b/libraries/controllers/src/controllers/Endpoint.h index 3e4ce94490..5d529ace30 100644 --- a/libraries/controllers/src/controllers/Endpoint.h +++ b/libraries/controllers/src/controllers/Endpoint.h @@ -17,6 +17,7 @@ #include #include "Input.h" +#include "Pose.h" class QScriptValue; @@ -37,7 +38,13 @@ namespace controller { Endpoint(const Input& input) : _input(input) {} virtual float value() = 0; virtual void apply(float newValue, float oldValue, const Pointer& source) = 0; + virtual Pose pose() { return Pose(); } + virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) {} + + virtual const bool isPose() { return _input.isPose(); } + const Input& getInput() { return _input; } + protected: Input _input; }; diff --git a/libraries/controllers/src/controllers/ScriptingInterface.cpp b/libraries/controllers/src/controllers/ScriptingInterface.cpp index b10c4a83b0..40c65549a8 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.cpp +++ b/libraries/controllers/src/controllers/ScriptingInterface.cpp @@ -24,6 +24,7 @@ #include "Logging.h" #include "InputDevice.h" + static QRegularExpression SANITIZE_NAME_EXPRESSION{ "[\\(\\)\\.\\s]" }; static QVariantMap createDeviceMap(const controller::DeviceProxy::Pointer device) { @@ -93,8 +94,13 @@ namespace controller { return getValue(Input(device, source, ChannelType::AXIS).getID()); } + Pose ScriptingInterface::getPoseValue(const int& source) const { + auto userInputMapper = DependencyManager::get(); + return userInputMapper->getPose(Input((uint32_t)source)); + } + Pose ScriptingInterface::getPoseValue(StandardPoseChannel source, uint16_t device) const { - return Pose(); + return getPoseValue(Input(device, source, ChannelType::POSE).getID()); } //bool ScriptingInterface::isPrimaryButtonPressed() const { diff --git a/libraries/controllers/src/controllers/ScriptingInterface.h b/libraries/controllers/src/controllers/ScriptingInterface.h index b43e065822..85b1c3c6d9 100644 --- a/libraries/controllers/src/controllers/ScriptingInterface.h +++ b/libraries/controllers/src/controllers/ScriptingInterface.h @@ -78,7 +78,9 @@ namespace controller { 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 Pose getPoseValue(const int& source) 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); } diff --git a/libraries/controllers/src/controllers/StandardController.cpp b/libraries/controllers/src/controllers/StandardController.cpp index 304f1e87aa..e9a2e71973 100644 --- a/libraries/controllers/src/controllers/StandardController.cpp +++ b/libraries/controllers/src/controllers/StandardController.cpp @@ -74,8 +74,8 @@ void StandardController::buildDeviceProxy(DeviceProxy::Pointer proxy) { availableInputs.append(Input::NamedPair(makeInput(controller::RT), "RT")); // Poses - availableInputs.append(Input::NamedPair(makeInput(controller::LEFT), "LeftPose")); - availableInputs.append(Input::NamedPair(makeInput(controller::RIGHT), "RightPose")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::LEFT_HAND), "LeftHand")); + availableInputs.append(UserInputMapper::InputPair(makeInput(controller::RIGHT_HAND), "RightHand")); // Aliases, PlayStation style names availableInputs.append(Input::NamedPair(makeInput(controller::LB), "L1")); diff --git a/libraries/controllers/src/controllers/StandardControls.h b/libraries/controllers/src/controllers/StandardControls.h index 0990e34224..dc39a8bbeb 100644 --- a/libraries/controllers/src/controllers/StandardControls.h +++ b/libraries/controllers/src/controllers/StandardControls.h @@ -50,8 +50,8 @@ namespace controller { // No correlation to SDL enum StandardPoseChannel { - LEFT = 0, - RIGHT, + LEFT_HAND = 0, + RIGHT_HAND, HEAD, NUM_STANDARD_POSES }; diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 757f680163..5d93150aed 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -33,7 +33,6 @@ controller::UserInputMapper::UserInputMapper() { _standardController = std::make_shared(); registerDevice(new ActionsDevice()); registerDevice(_standardController.get()); - assignDefaulActionScales(); } namespace controller { @@ -65,8 +64,13 @@ public: virtual float value() override { return _currentValue; } virtual void apply(float newValue, float oldValue, const Pointer& source) override { _currentValue = newValue; } + virtual Pose pose() override { return _currentPose; } + virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override { + _currentPose = newValue; + } private: float _currentValue{ 0.0f }; + Pose _currentPose{}; }; @@ -122,7 +126,7 @@ void ScriptEndpoint::internalApply(float newValue, float oldValue, int sourceID) class CompositeEndpoint : public Endpoint, Endpoint::Pair { public: CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second) - : Endpoint(Input(Input::INVALID_INPUT)), Pair(first, second) { } + : Endpoint(Input::INVALID_INPUT), Pair(first, second) { } virtual float value() { float result = first->value() * -1.0f + second->value(); @@ -138,6 +142,50 @@ private: Endpoint::Pointer _second; }; + +class InputEndpoint : public Endpoint { +public: + InputEndpoint(const Input& id = Input::INVALID_INPUT) + : Endpoint(id) { + } + + virtual float value() override { + _currentValue = 0.0f; + if (isPose()) { + return _currentValue; + } + auto userInputMapper = DependencyManager::get(); + auto deviceProxy = userInputMapper->getDeviceProxy(_input); + if (!deviceProxy) { + return _currentValue; + } + _currentValue = deviceProxy->getValue(_input, 0); + return _currentValue; + } + virtual void apply(float newValue, float oldValue, const Pointer& source) override {} + + virtual Pose pose() override { + _currentPose = Pose(); + if (!isPose()) { + return _currentPose; + } + auto userInputMapper = DependencyManager::get(); + auto deviceProxy = userInputMapper->getDeviceProxy(_input); + if (!deviceProxy) { + return _currentPose; + } + _currentPose = deviceProxy->getPose(_input, 0); + return _currentPose; + } + + virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override { + } + +private: + float _currentValue{ 0.0f }; + Pose _currentPose{}; +}; + class ActionEndpoint : public Endpoint { public: ActionEndpoint(const Input& id = Input::INVALID_INPUT) @@ -154,11 +202,20 @@ public: } } + virtual Pose pose() override { return _currentPose; } + virtual void apply(const Pose& newValue, const Pose& oldValue, const Pointer& source) override { + _currentPose = newValue; + if (!(_input == Input::INVALID_INPUT)) { + auto userInputMapper = DependencyManager::get(); + userInputMapper->setActionState(Action(_input.getChannel()), _currentPose); + } + } + private: float _currentValue{ 0.0f }; + Pose _currentPose{}; }; - UserInputMapper::~UserInputMapper() { } @@ -341,24 +398,29 @@ void UserInputMapper::update(float deltaTime) { update(); // Scale all the channel step with the scale - for (auto i = 0; i < NUM_ACTIONS; i++) { + for (auto i = 0; i < toInt(Action::NUM_ACTIONS); i++) { if (_externalActionStates[i] != 0) { _actionStates[i] += _externalActionStates[i]; _externalActionStates[i] = 0.0f; } + + if (_externalPoseStates[i].isValid()) { + _poseStates[i] = _externalPoseStates[i]; + _externalPoseStates[i] = Pose(); + } } // merge the bisected and non-bisected axes for now - fixBisectedAxis(_actionStates[TRANSLATE_X], _actionStates[LATERAL_LEFT], _actionStates[LATERAL_RIGHT]); - fixBisectedAxis(_actionStates[TRANSLATE_Y], _actionStates[VERTICAL_DOWN], _actionStates[VERTICAL_UP]); - fixBisectedAxis(_actionStates[TRANSLATE_Z], _actionStates[LONGITUDINAL_FORWARD], _actionStates[LONGITUDINAL_BACKWARD]); - fixBisectedAxis(_actionStates[TRANSLATE_CAMERA_Z], _actionStates[BOOM_IN], _actionStates[BOOM_OUT]); - fixBisectedAxis(_actionStates[ROTATE_Y], _actionStates[YAW_LEFT], _actionStates[YAW_RIGHT]); - fixBisectedAxis(_actionStates[ROTATE_X], _actionStates[PITCH_UP], _actionStates[PITCH_DOWN]); + fixBisectedAxis(_actionStates[toInt(Action::TRANSLATE_X)], _actionStates[toInt(Action::LATERAL_LEFT)], _actionStates[toInt(Action::LATERAL_RIGHT)]); + fixBisectedAxis(_actionStates[toInt(Action::TRANSLATE_Y)], _actionStates[toInt(Action::VERTICAL_DOWN)], _actionStates[toInt(Action::VERTICAL_UP)]); + fixBisectedAxis(_actionStates[toInt(Action::TRANSLATE_Z)], _actionStates[toInt(Action::LONGITUDINAL_FORWARD)], _actionStates[toInt(Action::LONGITUDINAL_BACKWARD)]); + fixBisectedAxis(_actionStates[toInt(Action::TRANSLATE_CAMERA_Z)], _actionStates[toInt(Action::BOOM_IN)], _actionStates[toInt(Action::BOOM_OUT)]); + fixBisectedAxis(_actionStates[toInt(Action::ROTATE_Y)], _actionStates[toInt(Action::YAW_LEFT)], _actionStates[toInt(Action::YAW_RIGHT)]); + fixBisectedAxis(_actionStates[toInt(Action::ROTATE_X)], _actionStates[toInt(Action::PITCH_UP)], _actionStates[toInt(Action::PITCH_DOWN)]); static const float EPSILON = 0.01f; - for (auto i = 0; i < NUM_ACTIONS; i++) { + for (auto i = 0; i < toInt(Action::NUM_ACTIONS); i++) { _actionStates[i] *= _actionScales[i]; // Emit only on change, and emit when moving back to 0 if (fabsf(_actionStates[i] - _lastActionStates[i]) > EPSILON) { @@ -376,7 +438,7 @@ Input::NamedVector UserInputMapper::getAvailableInputs(uint16 deviceID) const { QVector UserInputMapper::getAllActions() const { QVector actions; - for (auto i = 0; i < NUM_ACTIONS; i++) { + for (auto i = 0; i < toInt(Action::NUM_ACTIONS); i++) { actions.append(Action(i)); } return actions; @@ -384,7 +446,7 @@ QVector UserInputMapper::getAllActions() const { QString UserInputMapper::getActionName(Action action) const { for (auto actionPair : getActionInputs()) { - if (actionPair.first.channel == action) { + if (actionPair.first.channel == toInt(action)) { return actionPair.second; } } @@ -399,39 +461,41 @@ QVector UserInputMapper::getActionNames() const { } return result; } - +/* void UserInputMapper::assignDefaulActionScales() { - _actionScales[LONGITUDINAL_BACKWARD] = 1.0f; // 1m per unit - _actionScales[LONGITUDINAL_FORWARD] = 1.0f; // 1m per unit - _actionScales[LATERAL_LEFT] = 1.0f; // 1m per unit - _actionScales[LATERAL_RIGHT] = 1.0f; // 1m per unit - _actionScales[VERTICAL_DOWN] = 1.0f; // 1m per unit - _actionScales[VERTICAL_UP] = 1.0f; // 1m per unit - _actionScales[YAW_LEFT] = 1.0f; // 1 degree per unit - _actionScales[YAW_RIGHT] = 1.0f; // 1 degree per unit - _actionScales[PITCH_DOWN] = 1.0f; // 1 degree per unit - _actionScales[PITCH_UP] = 1.0f; // 1 degree per unit - _actionScales[BOOM_IN] = 0.5f; // .5m per unit - _actionScales[BOOM_OUT] = 0.5f; // .5m per unit - _actionScales[LEFT_HAND] = 1.0f; // default - _actionScales[RIGHT_HAND] = 1.0f; // default - _actionScales[LEFT_HAND_CLICK] = 1.0f; // on - _actionScales[RIGHT_HAND_CLICK] = 1.0f; // on - _actionScales[SHIFT] = 1.0f; // on - _actionScales[ACTION1] = 1.0f; // default - _actionScales[ACTION2] = 1.0f; // default - _actionScales[TRANSLATE_X] = 1.0f; // default - _actionScales[TRANSLATE_Y] = 1.0f; // default - _actionScales[TRANSLATE_Z] = 1.0f; // default - _actionScales[ROLL] = 1.0f; // default - _actionScales[PITCH] = 1.0f; // default - _actionScales[YAW] = 1.0f; // default + _actionScales[toInt(Action::LONGITUDINAL_BACKWARD)] = 1.0f; // 1m per unit + _actionScales[toInt(Action::LONGITUDINAL_FORWARD)] = 1.0f; // 1m per unit + _actionScales[toInt(Action::LATERAL_LEFT)] = 1.0f; // 1m per unit + _actionScales[toInt(Action::LATERAL_RIGHT)] = 1.0f; // 1m per unit + _actionScales[toInt(Action::VERTICAL_DOWN)] = 1.0f; // 1m per unit + _actionScales[toInt(Action::VERTICAL_UP)] = 1.0f; // 1m per unit + _actionScales[toInt(Action::YAW_LEFT)] = 1.0f; // 1 degree per unit + _actionScales[toInt(Action::YAW_RIGHT)] = 1.0f; // 1 degree per unit + _actionScales[toInt(Action::PITCH_DOWN)] = 1.0f; // 1 degree per unit + _actionScales[toInt(Action::PITCH_UP)] = 1.0f; // 1 degree per unit + _actionScales[toInt(Action::BOOM_IN)] = 0.5f; // .5m per unit + _actionScales[toInt(Action::BOOM_OUT)] = 0.5f; // .5m per unit + _actionScales[toInt(Action::LEFT_HAND)] = 1.0f; // default + _actionScales[toInt(Action::RIGHT_HAND)] = 1.0f; // default + _actionScales[toInt(Action::LEFT_HAND_CLICK)] = 1.0f; // on + _actionScales[toInt(Action::RIGHT_HAND_CLICK)] = 1.0f; // on + _actionScales[toInt(Action::SHIFT)] = 1.0f; // on + _actionScales[toInt(Action::ACTION1)] = 1.0f; // default + _actionScales[toInt(Action::ACTION2)] = 1.0f; // default + _actionScales[toInt(Action::TRANSLATE_X)] = 1.0f; // default + _actionScales[toInt(Action::TRANSLATE_Y)] = 1.0f; // default + _actionScales[toInt(Action::TRANSLATE_Z)] = 1.0f; // default + _actionScales[toInt(Action::ROLL)] = 1.0f; // default + _actionScales[toInt(Action::PITCH)] = 1.0f; // default + _actionScales[toInt(Action::YAW)] = 1.0f; // default } +*/ static int actionMetaTypeId = qRegisterMetaType(); static int inputMetaTypeId = qRegisterMetaType(); static int inputPairMetaTypeId = qRegisterMetaType(); + QScriptValue inputToScriptValue(QScriptEngine* engine, const Input& input); void inputFromScriptValue(const QScriptValue& object, Input& input); QScriptValue actionToScriptValue(QScriptEngine* engine, const Action& action); @@ -546,17 +610,24 @@ void UserInputMapper::update() { } // Fetch the value, may have been overriden by previous loopback routes - float value = getValue(source); - - // Apply each of the filters. - for (const auto& filter : route->filters) { - value = filter->apply(value); - } - - if (loopback) { - _overrideValues[source] = value; + if (source->isPose()) { + Pose value = getPose(source); + // no filters yet for pose + destination->apply(value, Pose(), source); } else { - destination->apply(value, 0, source); + // Fetch the value, may have been overriden by previous loopback routes + float value = getValue(source); + + // Apply each of the filters. + for (const auto& filter : route->filters) { + value = filter->apply(value); + } + + if (loopback) { + _overrideValues[source] = value; + } else { + destination->apply(value, 0, source); + } } } } @@ -685,6 +756,20 @@ float UserInputMapper::getValue(const Input& input) const { return endpoint->value(); } +Pose UserInputMapper::getPose(const Endpoint::Pointer& endpoint) const { + if (!endpoint->isPose()) { + return Pose(); + } + return endpoint->pose(); +} + +Pose UserInputMapper::getPose(const Input& input) const { + auto endpoint = endpointFor(input); + if (!endpoint) { + return Pose(); + } + return getPose(endpoint); +} Mapping::Pointer UserInputMapper::loadMapping(const QString& jsonFile) { if (jsonFile.isEmpty()) { diff --git a/libraries/controllers/src/controllers/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h index 5d5895fa7b..ec1267cd0c 100644 --- a/libraries/controllers/src/controllers/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -32,6 +32,10 @@ #include "Actions.h" namespace controller { + + class RouteBuilderProxy; + class MappingBuilderProxy; + class UserInputMapper : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY @@ -77,14 +81,14 @@ namespace controller { QVector getAllActions() const; QString getActionName(Action action) const; - float getActionState(Action action) const { return _actionStates[action]; } - Pose getPoseState(Action action) const { return _poseStates[action]; } + float getActionState(Action action) const { return _actionStates[toInt(action)]; } + Pose getPoseState(Action action) const { return _poseStates[toInt(action)]; } int findAction(const QString& actionName) const; QVector getActionNames() const; - void assignDefaulActionScales(); - void setActionState(Action action, float value) { _externalActionStates[action] = value; } - void deltaActionState(Action action, float delta) { _externalActionStates[action] += delta; } + void setActionState(Action action, float value) { _externalActionStates[toInt(action)] = value; } + void deltaActionState(Action action, float delta) { _externalActionStates[toInt(action)] += delta; } + void setActionState(Action action, const Pose& value) { _externalPoseStates[toInt(action)] = value; } static Input makeStandardInput(controller::StandardButtonChannel button); static Input makeStandardInput(controller::StandardAxisChannel axis); @@ -108,6 +112,7 @@ namespace controller { void enableMapping(const QString& mappingName, bool enable = true); float getValue(const Input& input) const; + Pose getPose(const Input& input) const; signals: void actionEvent(int action, float state); @@ -122,11 +127,12 @@ namespace controller { DevicesMap _registeredDevices; uint16 _nextFreeDeviceID = STANDARD_DEVICE + 1; - std::vector _actionStates = std::vector(NUM_ACTIONS, 0.0f); - std::vector _externalActionStates = std::vector(NUM_ACTIONS, 0.0f); - std::vector _actionScales = std::vector(NUM_ACTIONS, 1.0f); - std::vector _lastActionStates = std::vector(NUM_ACTIONS, 0.0f); - std::vector _poseStates = std::vector(NUM_ACTIONS); + std::vector _actionStates = std::vector(toInt(Action::NUM_ACTIONS), 0.0f); + std::vector _externalActionStates = std::vector(toInt(Action::NUM_ACTIONS), 0.0f); + std::vector _actionScales = std::vector(toInt(Action::NUM_ACTIONS), 1.0f); + std::vector _lastActionStates = std::vector(toInt(Action::NUM_ACTIONS), 0.0f); + std::vector _poseStates = std::vector(toInt(Action::NUM_ACTIONS)); + std::vector _externalPoseStates = std::vector(toInt(Action::NUM_ACTIONS)); glm::mat4 _sensorToWorldMat; @@ -134,6 +140,8 @@ namespace controller { QHash _deviceCounts; float getValue(const Endpoint::Pointer& endpoint) const; + Pose getPose(const Endpoint::Pointer& endpoint) const; + friend class RouteBuilderProxy; friend class MappingBuilderProxy; Endpoint::Pointer endpointFor(const QJSValue& endpoint); @@ -155,6 +163,7 @@ namespace controller { MappingDeviceMap _mappingsByDevice; MappingStack _activeMappings; }; + } Q_DECLARE_METATYPE(controller::UserInputMapper::InputPair) diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp index e76f55534f..14bcbca80e 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp @@ -18,7 +18,7 @@ #include "../ScriptingInterface.h" #include "../Logging.h" -namespace controller { +using namespace controller; void RouteBuilderProxy::to(int destinationInput) { qCDebug(controllers) << "Completing route " << destinationInput; @@ -107,4 +107,3 @@ void RouteBuilderProxy::addFilter(Filter::Pointer filter) { _route->filters.push_back(filter); } -} diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index eab3c03740..c9b8ba11ce 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -235,7 +235,7 @@ void SixenseManager::update(float deltaTime, bool jointsCaptured) { _poseStateMap.clear(); } } else { - _poseStateMap[left ? controller::StandardPoseChannel::LEFT : controller::StandardPoseChannel::RIGHT] = controller::Pose(); + _poseStateMap[left ? controller::StandardPoseChannel::LEFT_HAND : controller::StandardPoseChannel::RIGHT_HAND] = controller::Pose(); } } @@ -443,7 +443,8 @@ void SixenseManager::handlePoseEvent(glm::vec3 position, glm::quat rotation, boo // TODO: find a shortcut with fewer rotations. rotation = _avatarRotation * postOffset * glm::inverse(sixenseToHand) * rotation * preOffset * sixenseToHand; - _poseStateMap[left ? controller::StandardPoseChannel::LEFT : controller::StandardPoseChannel::RIGHT] = controller::Pose(position, rotation); + + _poseStateMap[left ? controller::StandardPoseChannel::LEFT_HAND : controller::StandardPoseChannel::RIGHT_HAND] = controller::Pose(position, rotation); #endif // HAVE_SIXENSE } @@ -488,8 +489,8 @@ void SixenseManager::buildDeviceProxy(controller::DeviceProxy::Pointer proxy) { availableInputs.append(Input::NamedPair(makeInput(RX), "RX")); availableInputs.append(Input::NamedPair(makeInput(RY), "RY")); availableInputs.append(Input::NamedPair(makeInput(RT), "RT")); - availableInputs.append(Input::NamedPair(makeInput(LEFT), "LeftPose")); - availableInputs.append(Input::NamedPair(makeInput(RIGHT), "RightPose")); + availableInputs.append(Input::NamedPair(makeInput(LEFT_HAND), "LeftHand")); + availableInputs.append(Input::NamedPair(makeInput(RIGHT_HAND), "RightHand")); return availableInputs; }; } diff --git a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp index 1c8d8c2add..66697e8b11 100644 --- a/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp +++ b/libraries/input-plugins/src/input-plugins/ViveControllerManager.cpp @@ -165,8 +165,8 @@ void ViveControllerManager::updateRendering(RenderArgs* args, render::ScenePoint //pendingChanges.updateItem(_leftHandRenderID, ); - controller::Pose leftHand = _poseStateMap[controller::StandardPoseChannel::LEFT]; - controller::Pose rightHand = _poseStateMap[controller::StandardPoseChannel::RIGHT]; + controller::Pose leftHand = _poseStateMap[controller::StandardPoseChannel::LEFT_HAND]; + controller::Pose rightHand = _poseStateMap[controller::StandardPoseChannel::RIGHT_HAND]; gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { auto geometryCache = DependencyManager::get(); @@ -389,7 +389,7 @@ void ViveControllerManager::handlePoseEvent(const mat4& mat, bool left) { position += rotation * glm::vec3(0, 0, -CONTROLLER_LENGTH_OFFSET); - _poseStateMap[left ? controller::LEFT : controller::RIGHT] = controller::Pose(position, rotation); + _poseStateMap[left ? controller::LEFT_HAND : controller::RIGHT_HAND] = controller::Pose(position, rotation); } void ViveControllerManager::buildDeviceProxy(controller::DeviceProxy::Pointer proxy) {