Update hydra mappings and test code

This commit is contained in:
Brad Davis 2015-10-16 17:18:15 -07:00
parent 1dcf03d61e
commit db0fa6b8ed
15 changed files with 321 additions and 200 deletions

View file

@ -0,0 +1,30 @@
ControllerTest = function() {
print("Actions");
for (var prop in Controller.Actions) {
print("\t" + prop);
}
print("Standard");
for (var prop in Controller.Standard) {
print("\t" + prop);
}
print("Hardware");
for (var prop in Controller.Hardware) {
print("\t" + prop);
for (var prop2 in Controller.Hardware[prop]) {
print("\t\t" + prop2);
}
}
print("Done");
var that = this;
Script.scriptEnding.connect(function() {
that.onCleanup();
});
}
ControllerTest.prototype.onCleanup = function() {
}
new ControllerTest();

View file

@ -0,0 +1,28 @@
{
"name": "Hydra to Standard",
"channels": [
{ "from": "Hydra.LY", "to": "Standard.LY" },
{ "from": "Hydra.LX", "to": "Standard.LX" },
{ "from": "Hydra.LT", "to": "Standard.LT" },
{ "from": "Hydra.RY", "to": "Standard.RY" },
{ "from": "Hydra.RX", "to": "Standard.RX" },
{ "from": "Hydra.RT", "to": "Standard.RT" },
{ "from": "Hydra.LB", "to": "Standard.LB" },
{ "from": "Hydra.LS", "to": "Standard.LS" },
{ "from": "Hydra.RB", "to": "Standard.RB" },
{ "from": "Hydra.RS", "to": "Standard.RS" },
{ "from": "Hydra.L0", "to": "Standard.Back" },
{ "from": "Hydra.L1", "to": "Standard.DL" },
{ "from": "Hydra.L2", "to": "Standard.DD" },
{ "from": "Hydra.L3", "to": "Standard.DR" },
{ "from": "Hydra.L4", "to": "Standard.DU" },
{ "from": "Hydra.R0", "to": "Standard.Start" },
{ "from": "Hydra.R1", "to": "Standard.X" },
{ "from": "Hydra.R2", "to": "Standard.A" },
{ "from": "Hydra.R3", "to": "Standard.B" },
{ "from": "Hydra.R4", "to": "Standard.Y" }
]
}

View file

@ -0,0 +1,29 @@
{
"name": "XBox to Standard",
"channels": [
{ "from": "XBox.LY", "to": "Standard.LY" },
{ "from": "XBox.LX", "to": "Standard.LX" },
{ "from": "XBox.LT", "to": "Standard.LT" },
{ "from": "XBox.LB", "to": "Standard.LB" },
{ "from": "XBox.LS", "to": "Standard.LS" },
{ "from": "XBox.RY", "to": "Standard.RY" },
{ "from": "XBox.RX", "to": "Standard.RX" },
{ "from": "XBox.RT", "to": "Standard.RT" },
{ "from": "XBox.RB", "to": "Standard.RB" },
{ "from": "XBox.RS", "to": "Standard.RS" },
{ "from": "XBox.Back", "to": "Standard.Back" },
{ "from": "XBox.Start", "to": "Standard.Start" },
{ "from": "XBox.DU", "to": "Standard.DU" },
{ "from": "XBox.DD", "to": "Standard.DD" },
{ "from": "XBox.DL", "to": "Standard.DL" },
{ "from": "XBox.DR", "to": "Standard.DR" },
{ "from": "XBox.A", "to": "Standard.A" },
{ "from": "XBox.B", "to": "Standard.B" },
{ "from": "XBox.X", "to": "Standard.X" },
{ "from": "XBox.Y", "to": "Standard.Y" }
]
}

View file

@ -143,22 +143,3 @@ 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;
#endif
}
UserInputMapper::Input Joystick::makeInput(controller::StandardButtonChannel button) {
return UserInputMapper::Input(_deviceID, button, UserInputMapper::ChannelType::BUTTON);
}
UserInputMapper::Input Joystick::makeInput(controller::StandardAxisChannel axis) {
return UserInputMapper::Input(_deviceID, axis, UserInputMapper::ChannelType::AXIS);
}

View file

@ -37,16 +37,12 @@ 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;
Joystick() : InputDevice("Joystick") {}
~Joystick();
UserInputMapper::Input makeInput(controller::StandardButtonChannel button);
UserInputMapper::Input makeInput(controller::StandardAxisChannel axis);
#ifdef HAVE_SDL2
Joystick(SDL_JoystickID instanceId, const QString& name, SDL_GameController* sdlGameController);
#endif

View file

@ -123,6 +123,8 @@ void SixenseManager::activate() {
loadSettings();
sixenseInit();
_activated = true;
auto userInputMapper = DependencyManager::get<UserInputMapper>();
registerToUserInputMapper(*userInputMapper);
#endif
}
@ -176,23 +178,13 @@ void SixenseManager::update(float deltaTime, bool jointsCaptured) {
auto userInputMapper = DependencyManager::get<UserInputMapper>();
if (sixenseGetNumActiveControllers() == 0) {
if (_hydrasConnected) {
qCDebug(inputplugins, "hydra disconnected");
}
_hydrasConnected = false;
if (_deviceID != 0) {
userInputMapper->removeDevice(_deviceID);
_deviceID = 0;
_poseStateMap.clear();
}
_poseStateMap.clear();
return;
}
PerformanceTimer perfTimer("sixense");
if (!_hydrasConnected) {
_hydrasConnected = true;
registerToUserInputMapper(*userInputMapper);
assignDefaultInputMapping(*userInputMapper);
UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra");
}
@ -226,12 +218,15 @@ void SixenseManager::update(float deltaTime, bool jointsCaptured) {
// NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters.
glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]);
position *= METERS_PER_MILLIMETER;
bool left = i == 0;
using namespace controller;
// Check to see if this hand/controller is on the base
const float CONTROLLER_AT_BASE_DISTANCE = 0.075f;
if (glm::length(position) >= CONTROLLER_AT_BASE_DISTANCE) {
handleButtonEvent(data->buttons, numActiveControllers - 1);
handleAxisEvent(data->joystick_x, data->joystick_y, data->trigger, numActiveControllers - 1);
handleButtonEvent(data->buttons, left);
_axisStateMap[left ? LX : RX] = data->joystick_x;
_axisStateMap[left ? LY : RY] = data->joystick_y;
_axisStateMap[left ? LT : RT] = data->trigger;
if (!jointsCaptured) {
// Rotation of Palm
@ -241,13 +236,8 @@ void SixenseManager::update(float deltaTime, bool jointsCaptured) {
_poseStateMap.clear();
}
} else {
_poseStateMap[(numActiveControllers - 1) == 0 ? LEFT_HAND : RIGHT_HAND] = UserInputMapper::PoseValue();
_poseStateMap[left ? controller::StandardPoseChannel::LEFT : controller::StandardPoseChannel::RIGHT] = UserInputMapper::PoseValue();
}
// // Read controller buttons and joystick into the hand
// palm->setControllerButtons(data->buttons);
// palm->setTrigger(data->trigger);
// palm->setJoystick(data->joystick_x, data->joystick_y);
}
if (numActiveControllers == 2) {
@ -367,39 +357,35 @@ void SixenseManager::focusOutEvent() {
_buttonPressedMap.clear();
};
void SixenseManager::handleAxisEvent(float stickX, float stickY, float trigger, int index) {
_axisStateMap[makeInput(AXIS_Y_POS, index).getChannel()] = (stickY > 0.0f) ? stickY : 0.0f;
_axisStateMap[makeInput(AXIS_Y_NEG, index).getChannel()] = (stickY < 0.0f) ? -stickY : 0.0f;
_axisStateMap[makeInput(AXIS_X_POS, index).getChannel()] = (stickX > 0.0f) ? stickX : 0.0f;
_axisStateMap[makeInput(AXIS_X_NEG, index).getChannel()] = (stickX < 0.0f) ? -stickX : 0.0f;
_axisStateMap[makeInput(BACK_TRIGGER, index).getChannel()] = trigger;
void SixenseManager::handleAxisEvent(float stickX, float stickY, float trigger, bool left) {
}
void SixenseManager::handleButtonEvent(unsigned int buttons, int index) {
void SixenseManager::handleButtonEvent(unsigned int buttons, bool left) {
using namespace controller;
if (buttons & BUTTON_0) {
_buttonPressedMap.insert(makeInput(BUTTON_0, index).getChannel());
_buttonPressedMap.insert(left ? BACK : START);
}
if (buttons & BUTTON_1) {
_buttonPressedMap.insert(makeInput(BUTTON_1, index).getChannel());
_buttonPressedMap.insert(left ? DL : X);
}
if (buttons & BUTTON_2) {
_buttonPressedMap.insert(makeInput(BUTTON_2, index).getChannel());
_buttonPressedMap.insert(left ? DD : A);
}
if (buttons & BUTTON_3) {
_buttonPressedMap.insert(makeInput(BUTTON_3, index).getChannel());
_buttonPressedMap.insert(left ? DR : B);
}
if (buttons & BUTTON_4) {
_buttonPressedMap.insert(makeInput(BUTTON_4, index).getChannel());
_buttonPressedMap.insert(left ? DU : Y);
}
if (buttons & BUTTON_FWD) {
_buttonPressedMap.insert(makeInput(BUTTON_FWD, index).getChannel());
_buttonPressedMap.insert(left ? LB : RB);
}
if (buttons & BUTTON_TRIGGER) {
_buttonPressedMap.insert(makeInput(BUTTON_TRIGGER, index).getChannel());
_buttonPressedMap.insert(left ? LS : RS);
}
}
void SixenseManager::handlePoseEvent(glm::vec3 position, glm::quat rotation, int index) {
void SixenseManager::handlePoseEvent(glm::vec3 position, glm::quat rotation, bool left) {
#ifdef HAVE_SIXENSE
// From ABOVE the sixense coordinate frame looks like this:
//
@ -443,7 +429,7 @@ void SixenseManager::handlePoseEvent(glm::vec3 position, glm::quat rotation, int
// In addition to Qsh each hand has pre-offset introduced by the shape of the sixense controllers
// and how they fit into the hand in their relaxed state. This offset is a quarter turn about
// the sixense's z-axis, with its direction different for the two hands:
float sign = (index == 0) ? 1.0f : -1.0f;
float sign = left ? 1.0f : -1.0f;
const glm::quat preOffset = glm::angleAxis(sign * PI / 2.0f, Vectors::UNIT_Z);
// Finally, there is a post-offset (same for both hands) to get the hand's rest orientation
@ -458,104 +444,46 @@ void SixenseManager::handlePoseEvent(glm::vec3 position, glm::quat rotation, int
// TODO: find a shortcut with fewer rotations.
rotation = _avatarRotation * postOffset * glm::inverse(sixenseToHand) * rotation * preOffset * sixenseToHand;
_poseStateMap[makeInput(JointChannel(index)).getChannel()] = UserInputMapper::PoseValue(position, rotation);
_poseStateMap[left ? controller::StandardPoseChannel::LEFT : controller::StandardPoseChannel::RIGHT] =
UserInputMapper::PoseValue(position, rotation);
#endif // HAVE_SIXENSE
}
void SixenseManager::registerToUserInputMapper(UserInputMapper& mapper) {
// Grab the current free device ID
_deviceID = mapper.getFreeDeviceID();
auto proxy = std::make_shared<UserInputMapper::DeviceProxy>(_name);
proxy->getButton = [this] (const UserInputMapper::Input& input, int timestamp) -> bool { return this->getButton(input.getChannel()); };
proxy->getAxis = [this] (const UserInputMapper::Input& input, int timestamp) -> float { return this->getAxis(input.getChannel()); };
proxy->getPose = [this](const UserInputMapper::Input& input, int timestamp) -> UserInputMapper::PoseValue { return this->getPose(input.getChannel()); };
proxy->getAvailabeInputs = [this] () -> QVector<UserInputMapper::InputPair> {
using namespace controller;
proxy->getAvailabeInputs = [this]() -> QVector<UserInputMapper::InputPair> {
QVector<UserInputMapper::InputPair> availableInputs;
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_0, 0), "Left Start"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_1, 0), "Left Button 1"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_2, 0), "Left Button 2"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_3, 0), "Left Button 3"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_4, 0), "Left Button 4"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_FWD, 0), "L1"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BACK_TRIGGER, 0), "L2"));
availableInputs.append(UserInputMapper::InputPair(makeInput(AXIS_Y_POS, 0), "Left Stick Up"));
availableInputs.append(UserInputMapper::InputPair(makeInput(AXIS_Y_NEG, 0), "Left Stick Down"));
availableInputs.append(UserInputMapper::InputPair(makeInput(AXIS_X_POS, 0), "Left Stick Right"));
availableInputs.append(UserInputMapper::InputPair(makeInput(AXIS_X_NEG, 0), "Left Stick Left"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_TRIGGER, 0), "Left Trigger Press"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_0, 1), "Right Start"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_1, 1), "Right Button 1"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_2, 1), "Right Button 2"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_3, 1), "Right Button 3"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_4, 1), "Right Button 4"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_FWD, 1), "R1"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BACK_TRIGGER, 1), "R2"));
availableInputs.append(UserInputMapper::InputPair(makeInput(AXIS_Y_POS, 1), "Right Stick Up"));
availableInputs.append(UserInputMapper::InputPair(makeInput(AXIS_Y_NEG, 1), "Right Stick Down"));
availableInputs.append(UserInputMapper::InputPair(makeInput(AXIS_X_POS, 1), "Right Stick Right"));
availableInputs.append(UserInputMapper::InputPair(makeInput(AXIS_X_NEG, 1), "Right Stick Left"));
availableInputs.append(UserInputMapper::InputPair(makeInput(BUTTON_TRIGGER, 1), "Right Trigger Press"));
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(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(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"));
return availableInputs;
};
proxy->resetDeviceBindings = [this, &mapper] () -> bool {
mapper.removeAllInputChannelsForDevice(_deviceID);
this->assignDefaultInputMapping(mapper);
return true;
};
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;
// Left Joystick: Movement, strafing
mapper.addInputChannel(UserInputMapper::LONGITUDINAL_FORWARD, makeInput(AXIS_Y_POS, 0), JOYSTICK_MOVE_SPEED);
mapper.addInputChannel(UserInputMapper::LONGITUDINAL_BACKWARD, makeInput(AXIS_Y_NEG, 0), JOYSTICK_MOVE_SPEED);
mapper.addInputChannel(UserInputMapper::LATERAL_RIGHT, makeInput(AXIS_X_POS, 0), JOYSTICK_MOVE_SPEED);
mapper.addInputChannel(UserInputMapper::LATERAL_LEFT, makeInput(AXIS_X_NEG, 0), JOYSTICK_MOVE_SPEED);
// Right Joystick: Camera orientation
mapper.addInputChannel(UserInputMapper::YAW_RIGHT, makeInput(AXIS_X_POS, 1), JOYSTICK_YAW_SPEED);
mapper.addInputChannel(UserInputMapper::YAW_LEFT, makeInput(AXIS_X_NEG, 1), JOYSTICK_YAW_SPEED);
mapper.addInputChannel(UserInputMapper::PITCH_UP, makeInput(AXIS_Y_POS, 1), JOYSTICK_PITCH_SPEED);
mapper.addInputChannel(UserInputMapper::PITCH_DOWN, makeInput(AXIS_Y_NEG, 1), JOYSTICK_PITCH_SPEED);
// Buttons
mapper.addInputChannel(UserInputMapper::BOOM_IN, makeInput(BUTTON_3, 0), BOOM_SPEED);
mapper.addInputChannel(UserInputMapper::BOOM_OUT, makeInput(BUTTON_1, 0), BOOM_SPEED);
mapper.addInputChannel(UserInputMapper::VERTICAL_UP, makeInput(BUTTON_3, 1), BUTTON_MOVE_SPEED);
mapper.addInputChannel(UserInputMapper::VERTICAL_DOWN, makeInput(BUTTON_1, 1), BUTTON_MOVE_SPEED);
mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(BUTTON_2, 0));
mapper.addInputChannel(UserInputMapper::SHIFT, makeInput(BUTTON_2, 1));
mapper.addInputChannel(UserInputMapper::ACTION1, makeInput(BUTTON_4, 0));
mapper.addInputChannel(UserInputMapper::ACTION2, makeInput(BUTTON_4, 1));
mapper.addInputChannel(UserInputMapper::LEFT_HAND, makeInput(LEFT_HAND));
mapper.addInputChannel(UserInputMapper::RIGHT_HAND, makeInput(RIGHT_HAND));
mapper.addInputChannel(UserInputMapper::LEFT_HAND_CLICK, makeInput(BACK_TRIGGER, 0));
mapper.addInputChannel(UserInputMapper::RIGHT_HAND_CLICK, makeInput(BACK_TRIGGER, 1));
// TODO find a mechanism to allow users to navigate the context menu via
mapper.addInputChannel(UserInputMapper::CONTEXT_MENU, makeInput(BUTTON_0, 0));
mapper.addInputChannel(UserInputMapper::TOGGLE_MUTE, makeInput(BUTTON_0, 1));
}
// virtual
void SixenseManager::saveSettings() const {
Settings settings;
@ -580,15 +508,3 @@ void SixenseManager::loadSettings() {
}
settings.endGroup();
}
UserInputMapper::Input SixenseManager::makeInput(unsigned int button, int index) {
return UserInputMapper::Input(_deviceID, button | (index == 0 ? LEFT_MASK : RIGHT_MASK), UserInputMapper::ChannelType::BUTTON);
}
UserInputMapper::Input SixenseManager::makeInput(SixenseManager::JoystickAxisChannel axis, int index) {
return UserInputMapper::Input(_deviceID, axis | (index == 0 ? LEFT_MASK : RIGHT_MASK), UserInputMapper::ChannelType::AXIS);
}
UserInputMapper::Input SixenseManager::makeInput(JointChannel joint) {
return UserInputMapper::Input(_deviceID, joint, UserInputMapper::ChannelType::POSE);
}

View file

@ -25,6 +25,7 @@
#endif
#include <controllers/InputDevice.h>
#include <controllers/StandardControls.h>
#include "InputPlugin.h"
@ -44,19 +45,6 @@ const bool DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS = false;
class SixenseManager : public InputPlugin, public InputDevice {
Q_OBJECT
public:
enum JoystickAxisChannel {
AXIS_Y_POS = 1U << 0,
AXIS_Y_NEG = 1U << 3,
AXIS_X_POS = 1U << 4,
AXIS_X_NEG = 1U << 5,
BACK_TRIGGER = 1U << 6,
};
enum JointChannel {
LEFT_HAND = 0,
RIGHT_HAND,
};
SixenseManager();
// Plugin functions
@ -73,14 +61,9 @@ 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;
UserInputMapper::Input makeInput(unsigned int button, int index);
UserInputMapper::Input makeInput(JoystickAxisChannel axis, int index);
UserInputMapper::Input makeInput(JointChannel joint);
virtual void saveSettings() const override;
virtual void loadSettings() override;
@ -88,9 +71,9 @@ public slots:
void setSixenseFilter(bool filter);
private:
void handleButtonEvent(unsigned int buttons, int index);
void handleAxisEvent(float x, float y, float trigger, int index);
void handlePoseEvent(glm::vec3 position, glm::quat rotation, int index);
void handleButtonEvent(unsigned int buttons, bool left);
void handleAxisEvent(float x, float y, float trigger, bool left);
void handlePoseEvent(glm::vec3 position, glm::quat rotation, bool left);
void updateCalibration(void* controllers);

View file

@ -0,0 +1,35 @@
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import QtQuick.Dialogs 1.0
import "./hydra"
import "./controls"
Item {
id: root
width: 480
height: width * 3.0 / 4.0
property var device
property real scale: width / 480
property real rightOffset: (width / 2) * scale
Image {
anchors.fill: parent
source: "hydra/hydra.png"
HydraStick {
leftStick: true
scale: root.scale
device: root.device
}
HydraStick {
leftStick: false
scale: root.scale
device: root.device
}
}
}

View file

@ -8,14 +8,20 @@ import "./controls"
Item {
id: root
property real aspect: 300.0 / 215.0
width: 300
height: width / aspect
property var device
property real scale: 1.0
width: 300 * scale
height: 215 * scale
property string label: ""
property real scale: width / 300.0
Image {
Text {
anchors.left: parent.left
anchors.top: parent.top
text: root.label
visible: root.label != ""
}
anchors.fill: parent
source: "xbox/xbox360-controller-md.png"

View file

@ -10,16 +10,24 @@ Column {
id: root
property var actions: Controllers.Actions
property var standard: Controllers.Standard
property var hydra: null
property var testMapping: null
property var xbox: null
Component.onCompleted: {
var patt = /^X360Controller/;
var xboxRegex = /^X360Controller/;
var hydraRegex = /^Hydra/;
for (var prop in Controllers.Hardware) {
if(patt.test(prop)) {
if(xboxRegex.test(prop)) {
root.xbox = Controllers.Hardware[prop]
break
print("found xbox")
continue
}
if (hydraRegex.test(prop)) {
root.hydra = Controllers.Hardware[prop]
print("found hydra")
continue
}
}
}
@ -79,23 +87,15 @@ Column {
mapping.join(standard.LB, standard.RB).to(actions.Yaw);
mapping.from(actions.Yaw).clamp(0, 1).invert().to(actions.YAW_RIGHT);
mapping.from(actions.Yaw).clamp(-1, 0).to(actions.YAW_LEFT);
// mapping.modifier(keyboard.Ctrl).scale(2.0)
// mapping.from(keyboard.A).to(actions.TranslateLeft)
// mapping.from(keyboard.A, keyboard.Shift).to(actions.TurnLeft)
// mapping.from(keyboard.A, keyboard.Shift, keyboard.Ctrl).scale(2.0).to(actions.TurnLeft)
// // First loopbacks
// // Then non-loopbacks by constraint level (number of inputs)
// mapping.from(xbox.RX).deadZone(0.2).to(xbox.RX)
// mapping.from(standard.RB, standard.LB, keyboard.Shift).to(actions.TurnLeft)
// mapping.from(keyboard.A, keyboard.Shift).to(actions.TurnLeft)
// mapping.from(keyboard.W).when(keyboard.Shift).to(actions.Forward)
testMapping = mapping;
enabled = false
@ -114,12 +114,19 @@ Column {
}
}
Row {
Xbox { device: root.standard; label: "Standard"; width: 360 }
}
Row {
spacing: 8
Xbox { device: root.xbox }
Xbox { device: root.standard }
Xbox { device: root.xbox; label: "XBox"; width: 360 }
}
Row {
spacing: 8
Hydra { device: root.hydra; width: 360 }
}
Row {
spacing: 8

View file

@ -8,6 +8,8 @@ Item {
property int size: 64
width: size
height: size
property bool invertY: false
property int halfSize: size / 2
property var controlIds: [ 0, 0 ]
@ -18,6 +20,9 @@ Item {
Controllers.getValue(controlIds[0]),
Controllers.getValue(controlIds[1])
);
if (root.invertY) {
value.y = value.y * -1.0
}
canvas.requestPaint();
}

View file

@ -0,0 +1,18 @@
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import QtQuick.Dialogs 1.0
import "./../controls"
Item {
id: root
width: 72 * scale
height: 48 * scale
property var device
property real scale: 1.0
property bool leftStick: true
}

View file

@ -0,0 +1,91 @@
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import QtQuick.Dialogs 1.0
import "./../controls"
Item {
id: root
property var device
property real scale: 1.0
property bool leftStick: true
width: parent.width / 2; height: parent.height
x: leftStick ? 0 : parent.width / 2
Text {
x: parent.width / 2 - width / 2; y: parent.height / 2 - height / 2
text: root.leftStick ? "L" : "R"
color: 'green'
}
// Analog Stick
AnalogStick {
size: 64 * root.scale
x: 127 * root.scale - width / 2; y: 45 * root.scale - width / 2; z: 100
invertY: true
controlIds: [
root.leftStick ? root.device.LX : root.device.RX,
root.leftStick ? root.device.LY : root.device.RY
]
}
// Stick press
ToggleButton {
controlId: root.leftStick ? root.device.LS : root.device.RS
width: 16 * root.scale; height: 16 * root.scale
x: 127 * root.scale - width / 2; y: 45 * root.scale - width / 2;
color: 'yellow'
}
// Trigger
AnalogButton {
controlId: root.leftStick ? root.device.LT : root.device.RT
width: 8 * root.scale ; height: 64 * root.scale
y: 24 * root.scale
x: root.leftStick ? (48 * root.scale) : root.width - (48 * root.scale) - width / 2
}
// Bumper
ToggleButton {
controlId: root.leftStick ? root.device.LB : root.device.RB
height: 16 * root.scale; width: 32 * root.scale
x: 128 * root.scale - width / 2; y: 24 * root.scale
color: 'red'
}
ToggleButton {
controlId: root.leftStick ? root.device.L0 : root.device.R0
height: 16 * root.scale; width: 4 * root.scale
x: 128 * root.scale - width / 2; y: 109 * root.scale
color: 'yellow'
}
ToggleButton {
controlId: root.leftStick ? root.device.L1 : root.device.R1
width: 16 * root.scale; height: 16 * root.scale
x: 103 * root.scale - width / 2; y: 100 * root.scale - height / 2
color: 'yellow'
}
ToggleButton {
controlId: root.leftStick ? root.device.L2 : root.device.R2
width: 16 * root.scale; height: 16 * root.scale
x: 148 * root.scale - width / 2; y: 100 * root.scale - height / 2
color: 'yellow'
}
ToggleButton {
controlId: root.leftStick ? root.device.L3 : root.device.R3
width: 16 * root.scale; height: 16 * root.scale
x: 97 * root.scale - width / 2; y: 76 * root.scale - height / 2
color: 'yellow'
}
ToggleButton {
controlId: root.leftStick ? root.device.L4 : root.device.R4
width: 16 * root.scale; height: 16 * root.scale
x: 155 * root.scale - width / 2; y: 76 * root.scale - height / 2
color: 'yellow'
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View file

@ -88,14 +88,9 @@ public:
int main(int argc, char** argv) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
for (auto path : qApp->libraryPaths()) {
qDebug() << path;
}
for (auto path : qApp->libraryPaths()) {
qDebug() << path;
}
new PluginContainerProxy();
// Simulate our application idle loop
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [] {
static float last = secTimestampNow();
@ -122,11 +117,12 @@ int main(int argc, char** argv) {
auto keyboardMouseDevice = static_cast<KeyboardMouseDevice*>(inputPlugin.data()); // TODO: this seems super hacky
keyboardMouseDevice->registerToUserInputMapper(*userInputMapper);
}
inputPlugin->pluginUpdate(0, false);
}
//new PluginContainerProxy();
auto rootContext = engine.rootContext();
rootContext->setContextProperty("Controllers", new MyControllerScriptingInterface());
}
engine.load(getQmlDir() + "main.qml");
app.exec();
return 0;