From abbfe153959cbe51db4b18b409903da7cfadc2f7 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 30 Oct 2015 14:34:18 -0700 Subject: [PATCH 1/2] Adding peek support for endpoints --- examples/controllers/handControllerGrab.js | 4 ++-- .../src/controllers/UserInputMapper.cpp | 16 +++++++++------- .../src/controllers/UserInputMapper.h | 8 ++++---- .../controllers/src/controllers/impl/Endpoint.h | 15 ++++++++------- .../controllers/src/controllers/impl/Route.h | 1 + .../src/controllers/impl/RouteBuilderProxy.cpp | 5 +++++ .../src/controllers/impl/RouteBuilderProxy.h | 3 ++- .../impl/conditionals/EndpointConditional.h | 2 +- .../controllers/impl/endpoints/ActionEndpoint.h | 4 ++-- .../controllers/impl/endpoints/AnyEndpoint.cpp | 11 +++++++++++ .../controllers/impl/endpoints/AnyEndpoint.h | 1 + .../controllers/impl/endpoints/ArrayEndpoint.h | 4 +--- .../impl/endpoints/CompositeEndpoint.cpp | 6 ++++++ .../impl/endpoints/CompositeEndpoint.h | 1 + .../impl/endpoints/InputEndpoint.cpp | 17 +++++++++++++---- .../controllers/impl/endpoints/InputEndpoint.h | 2 ++ .../src/controllers/impl/endpoints/JSEndpoint.h | 5 ++--- .../impl/endpoints/ScriptEndpoint.cpp | 4 ++-- .../controllers/impl/endpoints/ScriptEndpoint.h | 4 ++-- 19 files changed, 75 insertions(+), 38 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 727e42cdc1..a866983194 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -909,8 +909,8 @@ var leftController = new MyController(LEFT_HAND); var MAPPING_NAME = "com.highfidelity.handControllerGrab"; var mapping = Controller.newMapping(MAPPING_NAME); -mapping.from([Controller.Standard.RB, Controller.Standard.RT]).to(rightController.eitherTrigger); -mapping.from([Controller.Standard.LB, Controller.Standard.LT]).to(leftController.eitherTrigger); +mapping.from([Controller.Standard.RB, Controller.Standard.RT]).peek().to(rightController.eitherTrigger); +mapping.from([Controller.Standard.LB, Controller.Standard.LT]).peek().to(leftController.eitherTrigger); Controller.enableMapping(MAPPING_NAME); diff --git a/libraries/controllers/src/controllers/UserInputMapper.cpp b/libraries/controllers/src/controllers/UserInputMapper.cpp index 8e121de7fb..1a0fae8158 100755 --- a/libraries/controllers/src/controllers/UserInputMapper.cpp +++ b/libraries/controllers/src/controllers/UserInputMapper.cpp @@ -513,7 +513,7 @@ bool UserInputMapper::applyRoute(const Route::Pointer& route, bool force) { // and someone else wires it to CONTEXT_MENU, I don't want both to occur when // I press the button. The exception is if I'm wiring a control back to itself // in order to adjust my interface, like inverting the Y axis on an analog stick - if (!source->readable()) { + if (!route->peek && !source->readable()) { if (debugRoutes && route->debug) { qCDebug(controllers) << "Source unreadable"; } @@ -539,7 +539,7 @@ bool UserInputMapper::applyRoute(const Route::Pointer& route, bool force) { // Fetch the value, may have been overriden by previous loopback routes if (source->isPose()) { - Pose value = getPose(source); + Pose value = getPose(source, route->peek); static const Pose IDENTITY_POSE { vec3(), quat() }; if (debugRoutes && route->debug) { if (!value.valid) { @@ -554,7 +554,7 @@ bool UserInputMapper::applyRoute(const Route::Pointer& route, bool force) { destination->apply(value, source); } else { // Fetch the value, may have been overriden by previous loopback routes - float value = getValue(source); + float value = getValue(source, route->peek); if (debugRoutes && route->debug) { qCDebug(controllers) << "Value was " << value; @@ -691,8 +691,8 @@ void UserInputMapper::enableMapping(const QString& mappingName, bool enable) { } } -float UserInputMapper::getValue(const Endpoint::Pointer& endpoint) { - return endpoint->value(); +float UserInputMapper::getValue(const Endpoint::Pointer& endpoint, bool peek) { + return peek ? endpoint->peek() : endpoint->value(); } float UserInputMapper::getValue(const Input& input) const { @@ -704,11 +704,11 @@ float UserInputMapper::getValue(const Input& input) const { return endpoint->value(); } -Pose UserInputMapper::getPose(const Endpoint::Pointer& endpoint) { +Pose UserInputMapper::getPose(const Endpoint::Pointer& endpoint, bool peek) { if (!endpoint->isPose()) { return Pose(); } - return endpoint->pose(); + return peek ? endpoint->peekPose() : endpoint->pose(); } Pose UserInputMapper::getPose(const Input& input) const { @@ -742,6 +742,7 @@ static const QString JSON_NAME = QStringLiteral("name"); static const QString JSON_CHANNELS = QStringLiteral("channels"); static const QString JSON_CHANNEL_FROM = QStringLiteral("from"); static const QString JSON_CHANNEL_DEBUG = QStringLiteral("debug"); +static const QString JSON_CHANNEL_PEEK = QStringLiteral("peek"); static const QString JSON_CHANNEL_WHEN = QStringLiteral("when"); static const QString JSON_CHANNEL_TO = QStringLiteral("to"); static const QString JSON_CHANNEL_FILTERS = QStringLiteral("filters"); @@ -953,6 +954,7 @@ Route::Pointer UserInputMapper::parseRoute(const QJsonValue& value) { result->json = QString(QJsonDocument(obj).toJson()); result->source = parseSource(obj[JSON_CHANNEL_FROM]); result->debug = obj[JSON_CHANNEL_DEBUG].toBool(); + result->debug = obj[JSON_CHANNEL_PEEK].toBool(); if (!result->source) { qWarning() << "Invalid route source " << obj[JSON_CHANNEL_FROM]; return Route::Pointer(); diff --git a/libraries/controllers/src/controllers/UserInputMapper.h b/libraries/controllers/src/controllers/UserInputMapper.h index 7684ecb7c5..c1dfcf5d33 100644 --- a/libraries/controllers/src/controllers/UserInputMapper.h +++ b/libraries/controllers/src/controllers/UserInputMapper.h @@ -38,8 +38,8 @@ namespace controller { class UserInputMapper : public QObject, public Dependency { Q_OBJECT - SINGLETON_DEPENDENCY - Q_ENUMS(Action) + SINGLETON_DEPENDENCY + Q_ENUMS(Action) public: // FIXME move to unordered set / map @@ -135,8 +135,8 @@ namespace controller { int recordDeviceOfType(const QString& deviceName); QHash _deviceCounts; - static float getValue(const EndpointPointer& endpoint); - static Pose getPose(const EndpointPointer& endpoint); + static float getValue(const EndpointPointer& endpoint, bool peek = false); + static Pose getPose(const EndpointPointer& endpoint, bool peek = false); friend class RouteBuilderProxy; friend class MappingBuilderProxy; diff --git a/libraries/controllers/src/controllers/impl/Endpoint.h b/libraries/controllers/src/controllers/impl/Endpoint.h index bc604da2c5..475dc035bb 100644 --- a/libraries/controllers/src/controllers/impl/Endpoint.h +++ b/libraries/controllers/src/controllers/impl/Endpoint.h @@ -36,12 +36,13 @@ namespace controller { using WriteLambda = std::function; Endpoint(const Input& input) : _input(input) {} - virtual float value() = 0; + virtual float value() { return peek(); } + virtual float peek() const = 0; virtual void apply(float value, const Pointer& source) = 0; - virtual Pose pose() { return Pose(); } + virtual Pose peekPose() const { return Pose(); }; + virtual Pose pose() { return peekPose(); } virtual void apply(const Pose& value, const Pointer& source) {} - virtual bool isPose() { return _input.isPose(); } - + virtual bool isPose() const { return _input.isPose(); } virtual bool writeable() const { return true; } virtual bool readable() const { return true; } virtual void reset() { } @@ -58,7 +59,7 @@ namespace controller { LambdaEndpoint(ReadLambda readLambda, WriteLambda writeLambda = [](float) {}) : Endpoint(Input::INVALID_INPUT), _readLambda(readLambda), _writeLambda(writeLambda) { } - virtual float value() override { return _readLambda(); } + virtual float peek() const override { return _readLambda(); } virtual void apply(float value, const Pointer& source) override { _writeLambda(value); } private: @@ -73,10 +74,10 @@ namespace controller { : Endpoint(id) { } - virtual float value() override { return _currentValue; } + virtual float peek() const override { return _currentValue; } virtual void apply(float value, const Pointer& source) override { _currentValue = value; } - virtual Pose pose() override { return _currentPose; } + virtual Pose peekPose() const override { return _currentPose; } virtual void apply(const Pose& value, const Pointer& source) override { _currentPose = value; } diff --git a/libraries/controllers/src/controllers/impl/Route.h b/libraries/controllers/src/controllers/impl/Route.h index 5ad3d36628..554dd82d5a 100644 --- a/libraries/controllers/src/controllers/impl/Route.h +++ b/libraries/controllers/src/controllers/impl/Route.h @@ -26,6 +26,7 @@ namespace controller { Filter::List filters; QString json; bool debug { false }; + bool peek { false }; using Pointer = std::shared_ptr; using List = std::list; diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp index 49e615439d..5ae52893e0 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.cpp @@ -52,6 +52,11 @@ QObject* RouteBuilderProxy::debug(bool enable) { return this; } +QObject* RouteBuilderProxy::peek(bool enable) { + _route->peek = enable; + return this; +} + QObject* RouteBuilderProxy::when(const QScriptValue& expression) { _route->conditional = _parent.conditionalFor(expression); return this; diff --git a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h index d55aa80f6b..1c0ed6931d 100644 --- a/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h +++ b/libraries/controllers/src/controllers/impl/RouteBuilderProxy.h @@ -38,6 +38,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE void to(const QScriptValue& destination); Q_INVOKABLE QObject* debug(bool enable = true); + Q_INVOKABLE QObject* peek(bool enable = true); Q_INVOKABLE QObject* when(const QScriptValue& expression); Q_INVOKABLE QObject* clamp(float min, float max); Q_INVOKABLE QObject* hysteresis(float min, float max); @@ -48,7 +49,7 @@ class RouteBuilderProxy : public QObject { Q_INVOKABLE QObject* constrainToInteger(); Q_INVOKABLE QObject* constrainToPositiveInteger(); -private: + private: void to(const Endpoint::Pointer& destination); void conditional(const Conditional::Pointer& conditional); void addFilter(Filter::Pointer filter); diff --git a/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h b/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h index 54ed57e871..0ba1347087 100644 --- a/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h +++ b/libraries/controllers/src/controllers/impl/conditionals/EndpointConditional.h @@ -18,7 +18,7 @@ namespace controller { class EndpointConditional : public Conditional { public: EndpointConditional(Endpoint::Pointer endpoint) : _endpoint(endpoint) {} - virtual bool satisfied() override { return _endpoint && _endpoint->value() != 0.0f; } + virtual bool satisfied() override { return _endpoint && _endpoint->peek() != 0.0f; } private: Endpoint::Pointer _endpoint; }; diff --git a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.h index 574fdcedb5..e07dc9e4c8 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/ActionEndpoint.h @@ -23,10 +23,10 @@ class ActionEndpoint : public Endpoint { public: ActionEndpoint(const Input& id = Input::INVALID_INPUT) : Endpoint(id) { } - virtual float value() override { return _currentValue; } + virtual float peek() const { return _currentValue; } virtual void apply(float newValue, const Pointer& source) override; - virtual Pose pose() override { return _currentPose; } + virtual Pose peekPose() const { return _currentPose; } virtual void apply(const Pose& value, const Pointer& source) override; virtual void reset() override; diff --git a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp index 24f3479ea8..0dd53fe78f 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp @@ -27,6 +27,17 @@ AnyEndpoint::AnyEndpoint(Endpoint::List children) : Endpoint(Input::INVALID_INPU } } +float AnyEndpoint::peek() const { + for (auto& child : _children) { + float childResult = child->peek(); + if (childResult != 0.0f) { + return childResult; + } + } + return 0.0f; +} + +// Fetching the value must trigger any necessary side effects of value() on ALL the children. float AnyEndpoint::value() { float result = 0; for (auto& child : _children) { diff --git a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h index 24834ce223..8947eb675f 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.h @@ -19,6 +19,7 @@ class AnyEndpoint : public Endpoint { public: using Endpoint::apply; AnyEndpoint(Endpoint::List children); + virtual float peek() const override; virtual float value() override; virtual void apply(float newValue, const Endpoint::Pointer& source) override; virtual bool writeable() const override; diff --git a/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h index 899fa46de0..34d30a2e97 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/ArrayEndpoint.h @@ -21,9 +21,7 @@ public: using Pointer = std::shared_ptr; ArrayEndpoint() : Endpoint(Input::INVALID_INPUT) { } - virtual float value() override { - return 0.0; - } + virtual float peek() const override { return 0.0f; } virtual void apply(float value, const Endpoint::Pointer& source) override { for (auto& child : _children) { diff --git a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp index 913bf0136b..1bd27489f8 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.cpp @@ -24,6 +24,12 @@ bool CompositeEndpoint::readable() const { return first->readable() && second->readable(); } +float CompositeEndpoint::peek() const { + float result = first->peek() * -1.0f + second->peek(); + return result; +} + +// Fetching via value() must trigger any side effects of value() on the children float CompositeEndpoint::value() { float result = first->value() * -1.0f + second->value(); return result; diff --git a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h index b29266464c..3249aa1d37 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/CompositeEndpoint.h @@ -18,6 +18,7 @@ namespace controller { using Endpoint::apply; CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second); + virtual float peek() const override; virtual float value() override; virtual void apply(float newValue, const Pointer& source) override; virtual bool readable() const override; diff --git a/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.cpp index bb1f6df191..ce58c948d1 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.cpp @@ -13,10 +13,10 @@ #include "../../UserInputMapper.h" using namespace controller; -float InputEndpoint::value(){ - _read = true; + +float InputEndpoint::peek() const { if (isPose()) { - return pose().valid ? 1.0f : 0.0f; + return peekPose().valid ? 1.0f : 0.0f; } auto userInputMapper = DependencyManager::get(); auto deviceProxy = userInputMapper->getDevice(_input); @@ -26,8 +26,12 @@ float InputEndpoint::value(){ return deviceProxy->getValue(_input); } -Pose InputEndpoint::pose() { +float InputEndpoint::value(){ _read = true; + return peek(); +} + +Pose InputEndpoint::peekPose() const { if (!isPose()) { return Pose(); } @@ -39,3 +43,8 @@ Pose InputEndpoint::pose() { return deviceProxy->getPose(_input.channel); } +Pose InputEndpoint::pose() { + _read = true; + return peekPose(); +} + diff --git a/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.h index d58f0c2e73..663168bedc 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/InputEndpoint.h @@ -20,9 +20,11 @@ public: : Endpoint(id) { } + virtual float peek() const override; virtual float value() override; // FIXME need support for writing back to vibration / force feedback effects virtual void apply(float newValue, const Pointer& source) override {} + virtual Pose peekPose() const override; virtual Pose pose() override; virtual void apply(const Pose& value, const Pointer& source) override { } diff --git a/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h index 5113fef657..958914264e 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/JSEndpoint.h @@ -24,9 +24,8 @@ public: : Endpoint(Input::INVALID_INPUT), _callable(callable) { } - virtual float value() { - float result = (float)_callable.call().toNumber(); - return result; + virtual float peek() const { + return (float)const_cast(this)->_callable.call().toNumber(); } virtual void apply(float newValue, const Pointer& source) { diff --git a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp index d9b4a5fc59..bb9517b136 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.cpp @@ -12,8 +12,8 @@ using namespace controller; -float ScriptEndpoint::value() { - updateValue(); +float ScriptEndpoint::peek() const { + const_cast(this)->updateValue(); return _lastValueRead; } diff --git a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h index 37160fcb48..836af721f6 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h +++ b/libraries/controllers/src/controllers/impl/endpoints/ScriptEndpoint.h @@ -24,8 +24,8 @@ public: : Endpoint(Input::INVALID_INPUT), _callable(callable) { } - virtual float value(); - virtual void apply(float newValue, const Pointer& source); + virtual float peek() const override; + virtual void apply(float newValue, const Pointer& source) override; protected: Q_INVOKABLE void updateValue(); From 0e13348b5a3f4874552097cff8f58a122be72676 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 31 Oct 2015 13:24:26 -0700 Subject: [PATCH 2/2] PR feedback --- .../src/controllers/impl/endpoints/AnyEndpoint.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp index 0dd53fe78f..a3b719b2c1 100644 --- a/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp +++ b/libraries/controllers/src/controllers/impl/endpoints/AnyEndpoint.cpp @@ -28,23 +28,18 @@ AnyEndpoint::AnyEndpoint(Endpoint::List children) : Endpoint(Input::INVALID_INPU } float AnyEndpoint::peek() const { + float result = 0; for (auto& child : _children) { - float childResult = child->peek(); - if (childResult != 0.0f) { - return childResult; - } + result = std::max(result, child->peek()); } - return 0.0f; + return result; } // Fetching the value must trigger any necessary side effects of value() on ALL the children. float AnyEndpoint::value() { float result = 0; for (auto& child : _children) { - float childResult = child->value(); - if (childResult != 0.0f) { - result = childResult; - } + result = std::max(result, child->value()); } return result; }