diff --git a/examples/tests/controllerInterfaceTest.js b/examples/tests/controllerInterfaceTest.js index 48ad8f0879..0dccd1209a 100644 --- a/examples/tests/controllerInterfaceTest.js +++ b/examples/tests/controllerInterfaceTest.js @@ -1,29 +1,63 @@ ControllerTest = function() { var standard = Controller.Standard; var actions = Controller.Actions; + var xbox = Controller.Hardware.GamePad; this.mappingEnabled = false; this.mapping = Controller.newMapping(); this.mapping.from(standard.RX).to(actions.StepYaw); + this.mapping.from(standard.RY).invert().to(actions.Pitch); + + + var testMakeAxis = false; + if (testMakeAxis) { + this.mapping.makeAxis(standard.LB, standard.RB).pulse(0.25).scale(40.0).to(actions.StepYaw); + } + + var testStepYaw = false; + if (!testMakeAxis && testStepYaw){ + this.mapping.from(standard.LB).pulse(0.10).invert().scale(40.0).to(actions.StepYaw); + this.mapping.from(standard.RB).pulse(0.10).scale(15.0).to(actions.StepYaw); + } + + var testFunctionSource = false; + if (testFunctionSource) { + this.mapping.from(function(){ + return Math.sin(Date.now() / 250); + }).to(actions.Yaw); + } + + var testFunctionDest = true; + if (testFunctionDest) { + this.mapping.from(standard.DU).pulse(1.0).to(function(value){ + if (value != 0.0) { + print(value); + } + }); + + } + this.mapping.enable(); this.mappingEnabled = true; - - 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); + var dumpInputs = false; + if (dumpInputs) { + 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"); } - print("Done"); var that = this; Script.scriptEnding.connect(function() { diff --git a/interface/resources/qml/TestControllers.qml b/interface/resources/qml/TestControllers.qml index 3d1e13c6e3..a21735b3cc 100644 --- a/interface/resources/qml/TestControllers.qml +++ b/interface/resources/qml/TestControllers.qml @@ -25,12 +25,15 @@ HifiControls.VrDialog { function buildMapping() { testMapping = Controller.newMapping(); - testMapping.from(standard.RY).invert().to(actions.Pitch); + testMapping.fromQml(standard.RY).invert().toQml(actions.Pitch); + testMapping.fromQml(function(){ + return Math.sin(Date.now() / 250); + }).toQml(actions.Yaw); //testMapping.makeAxis(standard.LB, standard.RB).to(actions.Yaw); // Step yaw takes a number of degrees - testMapping.from(standard.LB).invert().scale(15.0).to(actions.StepYaw); - testMapping.from(standard.RB).scale(15.0).to(actions.StepYaw); - testMapping.from(standard.RX).scale(15.0).to(actions.StepYaw); + testMapping.fromQml(standard.LB).pulse(0.10).invert().scale(40.0).toQml(actions.StepYaw); + testMapping.fromQml(standard.RB).pulse(0.10).scale(15.0).toQml(actions.StepYaw); + testMapping.fromQml(standard.RX).scale(15.0).toQml(actions.StepYaw); } function toggleMapping() { @@ -88,8 +91,9 @@ HifiControls.VrDialog { Hydra { device: root.hydra; width: 180 } } - Row { - spacing: 8 + Grid { + columns: 6 + spacing: 4 ScrollingGraph { controlId: Controller.Actions.Yaw label: "Yaw" diff --git a/libraries/controllers/src/controllers/Input.cpp b/libraries/controllers/src/controllers/Input.cpp index 29d2fed617..4f645c3f95 100644 --- a/libraries/controllers/src/controllers/Input.cpp +++ b/libraries/controllers/src/controllers/Input.cpp @@ -10,10 +10,9 @@ 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(); - + const uint16_t Input::INVALID_DEVICE = 0xffff; + const uint16_t Input::INVALID_CHANNEL = 0x1fff; + const uint16_t Input::INVALID_TYPE = (uint16_t)ChannelType::INVALID; + const Input Input::INVALID_INPUT = Input(INVALID_DEVICE, INVALID_CHANNEL, ChannelType::INVALID); } diff --git a/libraries/controllers/src/controllers/Input.h b/libraries/controllers/src/controllers/Input.h index 6f997c9f91..7382d365ec 100644 --- a/libraries/controllers/src/controllers/Input.h +++ b/libraries/controllers/src/controllers/Input.h @@ -16,7 +16,7 @@ namespace controller { enum class ChannelType { - UNKNOWN = 0, + INVALID = 0, BUTTON = 1, AXIS, POSE, diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index ae806ed613..107b6f8192 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -145,10 +145,17 @@ void ScriptEndpoint::internalApply(float newValue, float oldValue, int sourceID) QScriptValueList({ QScriptValue(newValue), QScriptValue(oldValue), QScriptValue(sourceID) })); } +static const Input INVALID_STANDARD_INPUT = Input(UserInputMapper::STANDARD_DEVICE, Input::INVALID_CHANNEL, ChannelType::INVALID); + class CompositeEndpoint : public Endpoint, Endpoint::Pair { public: CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second) - : Endpoint(Input::INVALID_INPUT), Pair(first, second) { } + : Endpoint(Input::INVALID_INPUT), Pair(first, second) { + if (first->getInput().device == UserInputMapper::STANDARD_DEVICE && + second->getInput().device == UserInputMapper::STANDARD_DEVICE) { + this->_input = INVALID_STANDARD_INPUT; + } + } virtual float value() { float result = first->value() * -1.0f + second->value(); @@ -188,7 +195,20 @@ class AnyEndpoint : public Endpoint { friend class UserInputMapper; public: using Pointer = std::shared_ptr; - AnyEndpoint() : Endpoint(Input::INVALID_INPUT) {} + AnyEndpoint(Endpoint::List children) : Endpoint(Input::INVALID_INPUT), _children(children) { + bool standard = true; + // Ensure if we're building a composite of standard devices the composite itself + // is treated as a standard device for rule processing order + for (auto endpoint : children) { + if (endpoint->getInput().device != UserInputMapper::STANDARD_DEVICE) { + standard = false; + break; + } + } + if (standard) { + this->_input = INVALID_STANDARD_INPUT; + } + } virtual float value() override { float result = 0; @@ -1013,15 +1033,15 @@ Endpoint::Pointer UserInputMapper::parseDestination(const QJsonValue& value) { Endpoint::Pointer UserInputMapper::parseSource(const QJsonValue& value) { if (value.isArray()) { - AnyEndpoint::Pointer result = std::make_shared(); + Endpoint::List children; for (auto arrayItem : value.toArray()) { Endpoint::Pointer destination = parseEndpoint(arrayItem); if (!destination) { return Endpoint::Pointer(); } - result->_children.push_back(destination); + children.push_back(destination); } - return result; + return std::make_shared(children); } return parseEndpoint(value); diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp index 462a319a90..1af3f271be 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp @@ -20,13 +20,7 @@ using namespace controller; -QObject* MappingBuilderProxy::from(int input) { - qCDebug(controllers) << "Creating new Route builder proxy from " << input; - auto sourceEndpoint = _parent.endpointFor(Input(input)); - return from(sourceEndpoint); -} - -QObject* MappingBuilderProxy::from(const QJSValue& source) { +QObject* MappingBuilderProxy::fromQml(const QJSValue& source) { qCDebug(controllers) << "Creating new Route builder proxy from " << source.toString(); auto sourceEndpoint = _parent.endpointFor(source); return from(sourceEndpoint); @@ -49,7 +43,13 @@ QObject* MappingBuilderProxy::from(const Endpoint::Pointer& source) { } } -QObject* MappingBuilderProxy::makeAxis(const QJSValue& source1, const QJSValue& source2) { +QObject* MappingBuilderProxy::makeAxisQml(const QJSValue& source1, const QJSValue& source2) { + auto source1Endpoint = _parent.endpointFor(source1); + auto source2Endpoint = _parent.endpointFor(source2); + return from(_parent.compositeEndpointFor(source1Endpoint, source2Endpoint)); +} + +QObject* MappingBuilderProxy::makeAxis(const QScriptValue& source1, const QScriptValue& source2) { auto source1Endpoint = _parent.endpointFor(source1); auto source2Endpoint = _parent.endpointFor(source2); return from(_parent.compositeEndpointFor(source1Endpoint, source2Endpoint)); diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h index 07c1730836..93aa022647 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h @@ -32,10 +32,11 @@ public: MappingBuilderProxy(UserInputMapper& parent, Mapping::Pointer mapping) : _parent(parent), _mapping(mapping) { } - Q_INVOKABLE QObject* from(int sourceInput); - Q_INVOKABLE QObject* from(const QJSValue& source); + Q_INVOKABLE QObject* fromQml(const QJSValue& source); + Q_INVOKABLE QObject* makeAxisQml(const QJSValue& source1, const QJSValue& source2); + Q_INVOKABLE QObject* from(const QScriptValue& source); - Q_INVOKABLE QObject* makeAxis(const QJSValue& source1, const QJSValue& source2); + Q_INVOKABLE QObject* makeAxis(const QScriptValue& source1, const QScriptValue& source2); Q_INVOKABLE QObject* enable(bool enable = true); Q_INVOKABLE QObject* disable() { return enable(false); } diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp index 14bcbca80e..186cf2e84e 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp @@ -20,13 +20,7 @@ using namespace controller; -void RouteBuilderProxy::to(int destinationInput) { - qCDebug(controllers) << "Completing route " << destinationInput; - auto destinationEndpoint = _parent.endpointFor(Input(destinationInput)); - return to(destinationEndpoint); -} - -void RouteBuilderProxy::to(const QJSValue& destination) { +void RouteBuilderProxy::toQml(const QJSValue& destination) { qCDebug(controllers) << "Completing route " << destination.toString(); auto destinationEndpoint = _parent.endpointFor(destination); return to(destinationEndpoint); @@ -45,7 +39,7 @@ void RouteBuilderProxy::to(const Endpoint::Pointer& destination) { deleteLater(); } -QObject* RouteBuilderProxy::filter(const QJSValue& expression) { +QObject* RouteBuilderProxy::filterQml(const QJSValue& expression) { if (expression.isCallable()) { addFilter([=](float value) { QJSValue originalExpression = expression; diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h index 1b66a3d996..6bceba995a 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h @@ -31,11 +31,10 @@ class RouteBuilderProxy : public QObject { RouteBuilderProxy(UserInputMapper& parent, Mapping::Pointer mapping, Route::Pointer route) : _parent(parent), _mapping(mapping), _route(route) { } - Q_INVOKABLE void to(int destination); - Q_INVOKABLE void to(const QJSValue& destination); - Q_INVOKABLE void to(const QScriptValue& destination); + Q_INVOKABLE void toQml(const QJSValue& destination); + Q_INVOKABLE QObject* filterQml(const QJSValue& expression); - Q_INVOKABLE QObject* filter(const QJSValue& expression); + Q_INVOKABLE void to(const QScriptValue& destination); Q_INVOKABLE QObject* filter(const QScriptValue& expression); Q_INVOKABLE QObject* clamp(float min, float max); Q_INVOKABLE QObject* pulse(float interval);