From 4938e5ea8421c2fa5aa29df363f3492a0d9cabdf Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 21 Oct 2015 23:58:36 -0700 Subject: [PATCH 1/3] Fixing function based routes, makeAxis --- examples/tests/controllerInterfaceTest.js | 21 ++++++++++++++++++- interface/resources/qml/TestControllers.qml | 7 +++++-- .../controllers/src/controllers/Input.cpp | 9 ++++---- libraries/controllers/src/controllers/Input.h | 2 +- .../src/controllers/UserInputMapper.cpp | 9 +++++++- .../controllers/impl/MappingBuilderProxy.cpp | 10 ++++----- .../controllers/impl/MappingBuilderProxy.h | 6 +++--- 7 files changed, 46 insertions(+), 18 deletions(-) diff --git a/examples/tests/controllerInterfaceTest.js b/examples/tests/controllerInterfaceTest.js index 48ad8f0879..35a92daa6b 100644 --- a/examples/tests/controllerInterfaceTest.js +++ b/examples/tests/controllerInterfaceTest.js @@ -4,10 +4,29 @@ ControllerTest = function() { 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.fromFunction(function(){ + return Math.sin(Date.now() / 250); + }).to(actions.Yaw); + } + this.mapping.enable(); this.mappingEnabled = true; - print("Actions"); for (var prop in Controller.Actions) { print("\t" + prop); diff --git a/interface/resources/qml/TestControllers.qml b/interface/resources/qml/TestControllers.qml index 3d1e13c6e3..f967b8bf9c 100644 --- a/interface/resources/qml/TestControllers.qml +++ b/interface/resources/qml/TestControllers.qml @@ -26,10 +26,13 @@ HifiControls.VrDialog { function buildMapping() { testMapping = Controller.newMapping(); testMapping.from(standard.RY).invert().to(actions.Pitch); + testMapping.fromQmlFunction(function(){ + return Math.sin(Date.now() / 250); + }).to(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.LB).pulse(0.10).invert().scale(40.0).to(actions.StepYaw); + testMapping.from(standard.RB).pulse(0.10).scale(15.0).to(actions.StepYaw); testMapping.from(standard.RX).scale(15.0).to(actions.StepYaw); } 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..f1138479bf 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(); diff --git a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp index 462a319a90..91b11115d9 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp @@ -26,13 +26,13 @@ QObject* MappingBuilderProxy::from(int input) { return from(sourceEndpoint); } -QObject* MappingBuilderProxy::from(const QJSValue& source) { +QObject* MappingBuilderProxy::fromQmlFunction(const QJSValue& source) { qCDebug(controllers) << "Creating new Route builder proxy from " << source.toString(); auto sourceEndpoint = _parent.endpointFor(source); return from(sourceEndpoint); } -QObject* MappingBuilderProxy::from(const QScriptValue& source) { +QObject* MappingBuilderProxy::fromFunction(const QScriptValue& source) { qCDebug(controllers) << "Creating new Route builder proxy from " << source.toString(); auto sourceEndpoint = _parent.endpointFor(source); return from(sourceEndpoint); @@ -49,9 +49,9 @@ QObject* MappingBuilderProxy::from(const Endpoint::Pointer& source) { } } -QObject* MappingBuilderProxy::makeAxis(const QJSValue& source1, const QJSValue& source2) { - auto source1Endpoint = _parent.endpointFor(source1); - auto source2Endpoint = _parent.endpointFor(source2); +QObject* MappingBuilderProxy::makeAxis(int source1, int source2) { + auto source1Endpoint = _parent.endpointFor(Input(source1)); + auto source2Endpoint = _parent.endpointFor(Input(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..06ffcd8ea3 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.h @@ -33,9 +33,9 @@ public: : _parent(parent), _mapping(mapping) { } Q_INVOKABLE QObject* from(int sourceInput); - Q_INVOKABLE QObject* from(const QJSValue& source); - Q_INVOKABLE QObject* from(const QScriptValue& source); - Q_INVOKABLE QObject* makeAxis(const QJSValue& source1, const QJSValue& source2); + Q_INVOKABLE QObject* fromQmlFunction(const QJSValue& source); + Q_INVOKABLE QObject* fromFunction(const QScriptValue& source); + Q_INVOKABLE QObject* makeAxis(int source1, const int source2); Q_INVOKABLE QObject* enable(bool enable = true); Q_INVOKABLE QObject* disable() { return enable(false); } From 5d4cbfdacba62c81fb14df4c58e0b7dbffc8dfec Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 22 Oct 2015 09:40:41 -0700 Subject: [PATCH 2/3] Resolving ambiguity between functions and inputs differently --- examples/tests/controllerInterfaceTest.js | 35 ++++++++++--------- interface/resources/qml/TestControllers.qml | 17 ++++----- .../controllers/impl/MappingBuilderProxy.cpp | 22 ++++++------ .../controllers/impl/MappingBuilderProxy.h | 9 ++--- .../controllers/impl/RouteBuilderProxy.cpp | 10 ++---- .../src/controllers/impl/RouteBuilderProxy.h | 7 ++-- 6 files changed, 49 insertions(+), 51 deletions(-) diff --git a/examples/tests/controllerInterfaceTest.js b/examples/tests/controllerInterfaceTest.js index 35a92daa6b..a4e0557c78 100644 --- a/examples/tests/controllerInterfaceTest.js +++ b/examples/tests/controllerInterfaceTest.js @@ -17,9 +17,9 @@ ControllerTest = function() { this.mapping.from(standard.RB).pulse(0.10).scale(15.0).to(actions.StepYaw); } - var testFunctionSource = false; + var testFunctionSource = true; if (testFunctionSource) { - this.mapping.fromFunction(function(){ + this.mapping.from(function(){ return Math.sin(Date.now() / 250); }).to(actions.Yaw); } @@ -27,22 +27,25 @@ ControllerTest = function() { 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 f967b8bf9c..a21735b3cc 100644 --- a/interface/resources/qml/TestControllers.qml +++ b/interface/resources/qml/TestControllers.qml @@ -25,15 +25,15 @@ HifiControls.VrDialog { function buildMapping() { testMapping = Controller.newMapping(); - testMapping.from(standard.RY).invert().to(actions.Pitch); - testMapping.fromQmlFunction(function(){ + testMapping.fromQml(standard.RY).invert().toQml(actions.Pitch); + testMapping.fromQml(function(){ return Math.sin(Date.now() / 250); - }).to(actions.Yaw); + }).toQml(actions.Yaw); //testMapping.makeAxis(standard.LB, standard.RB).to(actions.Yaw); // Step yaw takes a number of degrees - testMapping.from(standard.LB).pulse(0.10).invert().scale(40.0).to(actions.StepYaw); - testMapping.from(standard.RB).pulse(0.10).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() { @@ -91,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/impl/MappingBuilderProxy.cpp b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp index 91b11115d9..1af3f271be 100644 --- a/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp +++ b/libraries/controllers/src/controllers/impl/MappingBuilderProxy.cpp @@ -20,19 +20,13 @@ 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::fromQmlFunction(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); } -QObject* MappingBuilderProxy::fromFunction(const QScriptValue& source) { +QObject* MappingBuilderProxy::from(const QScriptValue& source) { qCDebug(controllers) << "Creating new Route builder proxy from " << source.toString(); auto sourceEndpoint = _parent.endpointFor(source); return from(sourceEndpoint); @@ -49,9 +43,15 @@ QObject* MappingBuilderProxy::from(const Endpoint::Pointer& source) { } } -QObject* MappingBuilderProxy::makeAxis(int source1, int source2) { - auto source1Endpoint = _parent.endpointFor(Input(source1)); - auto source2Endpoint = _parent.endpointFor(Input(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 06ffcd8ea3..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* fromQmlFunction(const QJSValue& source); - Q_INVOKABLE QObject* fromFunction(const QScriptValue& source); - Q_INVOKABLE QObject* makeAxis(int source1, const int source2); + 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 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); From 6cf0bdcffede8b783b7255b19c0e31505c8a38db Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 22 Oct 2015 10:00:11 -0700 Subject: [PATCH 3/3] Testing function destination and fixing bug in rule ordering for multi-soure --- examples/tests/controllerInterfaceTest.js | 14 ++++++++++++- .../src/controllers/UserInputMapper.cpp | 21 +++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/examples/tests/controllerInterfaceTest.js b/examples/tests/controllerInterfaceTest.js index a4e0557c78..0dccd1209a 100644 --- a/examples/tests/controllerInterfaceTest.js +++ b/examples/tests/controllerInterfaceTest.js @@ -1,11 +1,13 @@ 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); @@ -17,12 +19,22 @@ ControllerTest = function() { this.mapping.from(standard.RB).pulse(0.10).scale(15.0).to(actions.StepYaw); } - var testFunctionSource = true; + 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; diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index f1138479bf..107b6f8192 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -195,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; @@ -1020,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);