mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-08 07:22:25 +02:00
Breaking up UserInputMapper, restoring some mappings
This commit is contained in:
parent
a75316f27b
commit
734a39f962
21 changed files with 670 additions and 630 deletions
|
@ -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
|
||||
|
|
|
@ -23,109 +23,6 @@
|
|||
// TODO: this needs to be removed, as well as any related controller-specific information
|
||||
#include <input-plugins/SixenseManager.h>
|
||||
|
||||
ControllerScriptingInterface::ControllerScriptingInterface() :
|
||||
_mouseCaptured(false),
|
||||
_touchCaptured(false),
|
||||
_wheelCaptured(false),
|
||||
_actionsCaptured(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ControllerScriptingInterface::~ControllerScriptingInterface() {
|
||||
}
|
||||
|
||||
|
||||
static int actionMetaTypeId = qRegisterMetaType<UserInputMapper::Action>();
|
||||
static int inputChannelMetaTypeId = qRegisterMetaType<UserInputMapper::InputChannel>();
|
||||
static int inputMetaTypeId = qRegisterMetaType<UserInputMapper::Input>();
|
||||
static int inputPairMetaTypeId = qRegisterMetaType<UserInputMapper::InputPair>();
|
||||
|
||||
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<UserInputMapper>();
|
||||
QVector<UserInputMapper::InputChannel> 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<QVector<UserInputMapper::Action> >(engine);
|
||||
qScriptRegisterSequenceMetaType<QVector<UserInputMapper::InputChannel> >(engine);
|
||||
qScriptRegisterSequenceMetaType<QVector<UserInputMapper::InputPair> >(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<HFActionEvent&>(*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<UserInputMapper::Action> ControllerScriptingInterface::getAllActions() {
|
||||
return DependencyManager::get<UserInputMapper>()->getAllActions();
|
||||
}
|
||||
|
||||
QVector<UserInputMapper::InputChannel> ControllerScriptingInterface::getInputChannelsForAction(UserInputMapper::Action action) {
|
||||
return DependencyManager::get<UserInputMapper>()->getInputChannelsForAction(action);
|
||||
}
|
||||
|
||||
QString ControllerScriptingInterface::getDeviceName(unsigned int device) {
|
||||
return DependencyManager::get<UserInputMapper>()->getDeviceName((unsigned short)device);
|
||||
}
|
||||
|
||||
QVector<UserInputMapper::InputChannel> ControllerScriptingInterface::getAllInputsForDevice(unsigned int device) {
|
||||
return DependencyManager::get<UserInputMapper>()->getAllInputsForDevice(device);
|
||||
}
|
||||
|
||||
bool ControllerScriptingInterface::addInputChannel(UserInputMapper::InputChannel inputChannel) {
|
||||
return DependencyManager::get<UserInputMapper>()->addInputChannel(inputChannel._action, inputChannel._input, inputChannel._modifier, inputChannel._scale);
|
||||
}
|
||||
|
||||
bool ControllerScriptingInterface::removeInputChannel(UserInputMapper::InputChannel inputChannel) {
|
||||
return DependencyManager::get<UserInputMapper>()->removeInputChannel(inputChannel);
|
||||
}
|
||||
|
||||
QVector<UserInputMapper::InputPair> ControllerScriptingInterface::getAvailableInputs(unsigned int device) {
|
||||
return DependencyManager::get<UserInputMapper>()->getAvailableInputs((unsigned short)device);
|
||||
}
|
||||
|
||||
void ControllerScriptingInterface::resetAllDeviceBindings() {
|
||||
DependencyManager::get<UserInputMapper>()->resetAllDeviceBindings();
|
||||
}
|
||||
|
||||
void ControllerScriptingInterface::resetDevice(unsigned int device) {
|
||||
DependencyManager::get<UserInputMapper>()->resetDevice(device);
|
||||
}
|
||||
|
||||
int ControllerScriptingInterface::findDevice(QString name) {
|
||||
return DependencyManager::get<UserInputMapper>()->findDevice(name);
|
||||
}
|
||||
|
||||
QVector<QString> ControllerScriptingInterface::getDeviceNames() {
|
||||
return DependencyManager::get<UserInputMapper>()->getDeviceNames();
|
||||
}
|
||||
|
||||
float ControllerScriptingInterface::getActionValue(int action) {
|
||||
return DependencyManager::get<UserInputMapper>()->getActionState(UserInputMapper::Action(action));
|
||||
}
|
||||
|
||||
int ControllerScriptingInterface::findAction(QString actionName) {
|
||||
return DependencyManager::get<UserInputMapper>()->findAction(actionName);
|
||||
}
|
||||
|
||||
QVector<QString> ControllerScriptingInterface::getActionNames() const {
|
||||
return DependencyManager::get<UserInputMapper>()->getActionNames();
|
||||
}
|
||||
|
||||
InputController::InputController(int deviceTrackerId, int subTrackerId, QObject* parent) :
|
||||
_deviceTrackerId(deviceTrackerId),
|
||||
_subTrackerId(subTrackerId),
|
||||
|
|
|
@ -63,33 +63,8 @@ class ControllerScriptingInterface : public controller::ScriptingInterface {
|
|||
|
||||
|
||||
public:
|
||||
ControllerScriptingInterface();
|
||||
~ControllerScriptingInterface();
|
||||
virtual ~ControllerScriptingInterface() {}
|
||||
|
||||
Q_INVOKABLE QVector<UserInputMapper::Action> getAllActions();
|
||||
|
||||
Q_INVOKABLE bool addInputChannel(UserInputMapper::InputChannel inputChannel);
|
||||
Q_INVOKABLE bool removeInputChannel(UserInputMapper::InputChannel inputChannel);
|
||||
Q_INVOKABLE QVector<UserInputMapper::InputChannel> getInputChannelsForAction(UserInputMapper::Action action);
|
||||
|
||||
Q_INVOKABLE QVector<UserInputMapper::InputPair> getAvailableInputs(unsigned int device);
|
||||
Q_INVOKABLE QVector<UserInputMapper::InputChannel> 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<QString> getDeviceNames();
|
||||
|
||||
Q_INVOKABLE int findAction(QString actionName);
|
||||
Q_INVOKABLE QVector<QString> 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<int,KeyEvent> _capturedKeys;
|
||||
QSet<int> _capturedJoysticks;
|
||||
|
||||
|
|
31
libraries/controllers/src/controllers/DeviceProxy.cpp
Normal file
31
libraries/controllers/src/controllers/DeviceProxy.cpp
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
57
libraries/controllers/src/controllers/DeviceProxy.h
Normal file
57
libraries/controllers/src/controllers/DeviceProxy.h
Normal file
|
@ -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 <functional>
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVector>
|
||||
|
||||
#include "Input.h"
|
||||
#include "Pose.h"
|
||||
|
||||
namespace controller {
|
||||
|
||||
using Modifiers = std::vector<Input>;
|
||||
typedef QPair<Input, QString> InputPair;
|
||||
|
||||
|
||||
template<typename T>
|
||||
using InputGetter = std::function<T(const Input& input, int timestamp)>;
|
||||
using ButtonGetter = InputGetter<bool>;
|
||||
using AxisGetter = InputGetter<float>;
|
||||
using PoseGetter = InputGetter<Pose>;
|
||||
using ResetBindings = std::function<bool()>;
|
||||
using AvailableInputGetter = std::function<Input::NamedVector()>;
|
||||
|
||||
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<DeviceProxy>;
|
||||
|
||||
QString _baseName;
|
||||
QString _name;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
19
libraries/controllers/src/controllers/Input.cpp
Normal file
19
libraries/controllers/src/controllers/Input.cpp
Normal file
|
@ -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();
|
||||
|
||||
}
|
||||
|
76
libraries/controllers/src/controllers/Input.h
Normal file
76
libraries/controllers/src/controllers/Input.h
Normal file
|
@ -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 <GLMHelpers.h>
|
||||
|
||||
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<Input, QString>;
|
||||
using NamedVector = QVector<NamedPair>;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
};
|
30
libraries/controllers/src/controllers/Pose.cpp
Normal file
30
libraries/controllers/src/controllers/Pose.cpp
Normal file
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
43
libraries/controllers/src/controllers/Pose.h
Normal file
43
libraries/controllers/src/controllers/Pose.h
Normal file
|
@ -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 <GLMHelpers.h>
|
||||
|
||||
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
|
|
@ -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<Mapping>("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<UserInputMapper>()->findDeviceInput(inputName);
|
||||
return DependencyManager::get<UserInputMapper>()->findDeviceInput(inputName);
|
||||
}
|
||||
|
||||
Endpoint::Pointer ScriptingInterface::endpointFor(const UserInputMapper::Input& inputId) {
|
||||
|
@ -494,6 +494,39 @@ namespace controller {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVector<UserInputMapper::Action> ScriptingInterface::getAllActions() {
|
||||
return DependencyManager::get<UserInputMapper>()->getAllActions();
|
||||
}
|
||||
|
||||
QString ScriptingInterface::getDeviceName(unsigned int device) {
|
||||
return DependencyManager::get<UserInputMapper>()->getDeviceName((unsigned short)device);
|
||||
}
|
||||
|
||||
QVector<UserInputMapper::InputPair> ScriptingInterface::getAvailableInputs(unsigned int device) {
|
||||
return DependencyManager::get<UserInputMapper>()->getAvailableInputs((unsigned short)device);
|
||||
}
|
||||
|
||||
int ScriptingInterface::findDevice(QString name) {
|
||||
return DependencyManager::get<UserInputMapper>()->findDevice(name);
|
||||
}
|
||||
|
||||
QVector<QString> ScriptingInterface::getDeviceNames() {
|
||||
return DependencyManager::get<UserInputMapper>()->getDeviceNames();
|
||||
}
|
||||
|
||||
float ScriptingInterface::getActionValue(int action) {
|
||||
return DependencyManager::get<UserInputMapper>()->getActionState(UserInputMapper::Action(action));
|
||||
}
|
||||
|
||||
int ScriptingInterface::findAction(QString actionName) {
|
||||
return DependencyManager::get<UserInputMapper>()->findAction(actionName);
|
||||
}
|
||||
|
||||
QVector<QString> ScriptingInterface::getActionNames() const {
|
||||
return DependencyManager::get<UserInputMapper>()->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
|
||||
|
|
|
@ -67,15 +67,22 @@ namespace controller {
|
|||
ScriptingInterface();
|
||||
virtual ~ScriptingInterface();
|
||||
|
||||
Q_INVOKABLE QVector<UserInputMapper::Action> getAllActions();
|
||||
Q_INVOKABLE QVector<UserInputMapper::InputPair> 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<QString> getDeviceNames();
|
||||
Q_INVOKABLE int findAction(QString actionName);
|
||||
Q_INVOKABLE QVector<QString> 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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<QString> 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<UserInputMapper::Action>();
|
||||
static int inputMetaTypeId = qRegisterMetaType<UserInputMapper::Input>();
|
||||
static int inputPairMetaTypeId = qRegisterMetaType<UserInputMapper::InputPair>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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<UserInputMapper>();
|
||||
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<QVector<UserInputMapper::Action> >(engine);
|
||||
qScriptRegisterSequenceMetaType<QVector<UserInputMapper::InputPair> >(engine);
|
||||
qScriptRegisterMetaType(engine, actionToScriptValue, actionFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, inputToScriptValue, inputFromScriptValue);
|
||||
qScriptRegisterMetaType(engine, inputPairToScriptValue, inputPairFromScriptValue);
|
||||
}
|
||||
|
|
|
@ -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 <DependencyManager.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "Pose.h"
|
||||
#include "Input.h"
|
||||
#include "DeviceProxy.h"
|
||||
|
||||
class StandardController;
|
||||
typedef std::shared_ptr<StandardController> 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<bool (const Input& input, int timestamp)> ButtonGetter;
|
||||
typedef std::function<float (const Input& input, int timestamp)> AxisGetter;
|
||||
typedef std::function<PoseValue (const Input& input, int timestamp)> PoseGetter;
|
||||
|
@ -119,22 +57,6 @@ public:
|
|||
|
||||
typedef QVector<InputPair> 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<InputPair>(); };
|
||||
ResetBindings resetDeviceBindings = [] () -> bool { return true; };
|
||||
float getValue(const Input& input, int timestamp = 0) const;
|
||||
typedef std::shared_ptr<DeviceProxy> 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<int, DeviceProxy::Pointer> 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<int, Modifiers> InputToMoModifiersMap;
|
||||
InputToMoModifiersMap _inputToModifiersMap;
|
||||
|
@ -309,6 +231,7 @@ protected:
|
|||
};
|
||||
|
||||
Q_DECLARE_METATYPE(UserInputMapper::InputPair)
|
||||
Q_DECLARE_METATYPE(UserInputMapper::PoseValue)
|
||||
Q_DECLARE_METATYPE(QVector<UserInputMapper::InputPair>)
|
||||
Q_DECLARE_METATYPE(UserInputMapper::Input)
|
||||
Q_DECLARE_METATYPE(UserInputMapper::InputChannel)
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<UserInputMapper::InputPair> {
|
||||
QVector<UserInputMapper::InputPair> 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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -308,8 +308,6 @@ void ScriptEngine::init() {
|
|||
|
||||
registerGlobalObject("Script", this);
|
||||
registerGlobalObject("Audio", &AudioScriptingInterface::getInstance());
|
||||
auto scriptingInterface = DependencyManager::get<controller::ScriptingInterface>();
|
||||
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<controller::ScriptingInterface>();
|
||||
registerGlobalObject("Controller", scriptingInterface.data());
|
||||
UserInputMapper::registerControllerTypes(this);
|
||||
}
|
||||
|
||||
void ScriptEngine::registerValue(const QString& valueName, QScriptValue value) {
|
||||
|
|
Loading…
Reference in a new issue