Merge pull request #6250 from jherico/peek

Adding peek support for endpoints
This commit is contained in:
Brad Hefta-Gaub 2015-10-31 16:09:27 -07:00
commit 286905c20c
19 changed files with 74 additions and 42 deletions

View file

@ -910,8 +910,8 @@ var leftController = new MyController(LEFT_HAND);
var MAPPING_NAME = "com.highfidelity.handControllerGrab"; var MAPPING_NAME = "com.highfidelity.handControllerGrab";
var mapping = Controller.newMapping(MAPPING_NAME); var mapping = Controller.newMapping(MAPPING_NAME);
mapping.from([Controller.Standard.RB, Controller.Standard.RT]).to(rightController.eitherTrigger); mapping.from([Controller.Standard.RB, Controller.Standard.RT]).peek().to(rightController.eitherTrigger);
mapping.from([Controller.Standard.LB, Controller.Standard.LT]).to(leftController.eitherTrigger); mapping.from([Controller.Standard.LB, Controller.Standard.LT]).peek().to(leftController.eitherTrigger);
Controller.enableMapping(MAPPING_NAME); Controller.enableMapping(MAPPING_NAME);

View file

@ -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 // 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 // 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 // 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) { if (debugRoutes && route->debug) {
qCDebug(controllers) << "Source unreadable"; 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 // Fetch the value, may have been overriden by previous loopback routes
if (source->isPose()) { if (source->isPose()) {
Pose value = getPose(source); Pose value = getPose(source, route->peek);
static const Pose IDENTITY_POSE { vec3(), quat() }; static const Pose IDENTITY_POSE { vec3(), quat() };
if (debugRoutes && route->debug) { if (debugRoutes && route->debug) {
if (!value.valid) { if (!value.valid) {
@ -554,7 +554,7 @@ bool UserInputMapper::applyRoute(const Route::Pointer& route, bool force) {
destination->apply(value, source); destination->apply(value, source);
} else { } else {
// Fetch the value, may have been overriden by previous loopback routes // 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) { if (debugRoutes && route->debug) {
qCDebug(controllers) << "Value was " << value; qCDebug(controllers) << "Value was " << value;
@ -691,8 +691,8 @@ void UserInputMapper::enableMapping(const QString& mappingName, bool enable) {
} }
} }
float UserInputMapper::getValue(const Endpoint::Pointer& endpoint) { float UserInputMapper::getValue(const Endpoint::Pointer& endpoint, bool peek) {
return endpoint->value(); return peek ? endpoint->peek() : endpoint->value();
} }
float UserInputMapper::getValue(const Input& input) const { float UserInputMapper::getValue(const Input& input) const {
@ -704,11 +704,11 @@ float UserInputMapper::getValue(const Input& input) const {
return endpoint->value(); return endpoint->value();
} }
Pose UserInputMapper::getPose(const Endpoint::Pointer& endpoint) { Pose UserInputMapper::getPose(const Endpoint::Pointer& endpoint, bool peek) {
if (!endpoint->isPose()) { if (!endpoint->isPose()) {
return Pose(); return Pose();
} }
return endpoint->pose(); return peek ? endpoint->peekPose() : endpoint->pose();
} }
Pose UserInputMapper::getPose(const Input& input) const { 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_CHANNELS = QStringLiteral("channels");
static const QString JSON_CHANNEL_FROM = QStringLiteral("from"); static const QString JSON_CHANNEL_FROM = QStringLiteral("from");
static const QString JSON_CHANNEL_DEBUG = QStringLiteral("debug"); 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_WHEN = QStringLiteral("when");
static const QString JSON_CHANNEL_TO = QStringLiteral("to"); static const QString JSON_CHANNEL_TO = QStringLiteral("to");
static const QString JSON_CHANNEL_FILTERS = QStringLiteral("filters"); 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->json = QString(QJsonDocument(obj).toJson());
result->source = parseSource(obj[JSON_CHANNEL_FROM]); result->source = parseSource(obj[JSON_CHANNEL_FROM]);
result->debug = obj[JSON_CHANNEL_DEBUG].toBool(); result->debug = obj[JSON_CHANNEL_DEBUG].toBool();
result->debug = obj[JSON_CHANNEL_PEEK].toBool();
if (!result->source) { if (!result->source) {
qWarning() << "Invalid route source " << obj[JSON_CHANNEL_FROM]; qWarning() << "Invalid route source " << obj[JSON_CHANNEL_FROM];
return Route::Pointer(); return Route::Pointer();

View file

@ -38,8 +38,8 @@ namespace controller {
class UserInputMapper : public QObject, public Dependency { class UserInputMapper : public QObject, public Dependency {
Q_OBJECT Q_OBJECT
SINGLETON_DEPENDENCY SINGLETON_DEPENDENCY
Q_ENUMS(Action) Q_ENUMS(Action)
public: public:
// FIXME move to unordered set / map // FIXME move to unordered set / map
@ -135,8 +135,8 @@ namespace controller {
int recordDeviceOfType(const QString& deviceName); int recordDeviceOfType(const QString& deviceName);
QHash<const QString&, int> _deviceCounts; QHash<const QString&, int> _deviceCounts;
static float getValue(const EndpointPointer& endpoint); static float getValue(const EndpointPointer& endpoint, bool peek = false);
static Pose getPose(const EndpointPointer& endpoint); static Pose getPose(const EndpointPointer& endpoint, bool peek = false);
friend class RouteBuilderProxy; friend class RouteBuilderProxy;
friend class MappingBuilderProxy; friend class MappingBuilderProxy;

View file

@ -36,12 +36,13 @@ namespace controller {
using WriteLambda = std::function<void(float)>; using WriteLambda = std::function<void(float)>;
Endpoint(const Input& input) : _input(input) {} 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 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 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 writeable() const { return true; }
virtual bool readable() const { return true; } virtual bool readable() const { return true; }
virtual void reset() { } virtual void reset() { }
@ -58,7 +59,7 @@ namespace controller {
LambdaEndpoint(ReadLambda readLambda, WriteLambda writeLambda = [](float) {}) LambdaEndpoint(ReadLambda readLambda, WriteLambda writeLambda = [](float) {})
: Endpoint(Input::INVALID_INPUT), _readLambda(readLambda), _writeLambda(writeLambda) { } : 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); } virtual void apply(float value, const Pointer& source) override { _writeLambda(value); }
private: private:
@ -73,10 +74,10 @@ namespace controller {
: Endpoint(id) { : 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 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 { virtual void apply(const Pose& value, const Pointer& source) override {
_currentPose = value; _currentPose = value;
} }

View file

@ -26,6 +26,7 @@ namespace controller {
Filter::List filters; Filter::List filters;
QString json; QString json;
bool debug { false }; bool debug { false };
bool peek { false };
using Pointer = std::shared_ptr<Route>; using Pointer = std::shared_ptr<Route>;
using List = std::list<Pointer>; using List = std::list<Pointer>;

View file

@ -52,6 +52,11 @@ QObject* RouteBuilderProxy::debug(bool enable) {
return this; return this;
} }
QObject* RouteBuilderProxy::peek(bool enable) {
_route->peek = enable;
return this;
}
QObject* RouteBuilderProxy::when(const QScriptValue& expression) { QObject* RouteBuilderProxy::when(const QScriptValue& expression) {
_route->conditional = _parent.conditionalFor(expression); _route->conditional = _parent.conditionalFor(expression);
return this; return this;

View file

@ -38,6 +38,7 @@ class RouteBuilderProxy : public QObject {
Q_INVOKABLE void to(const QScriptValue& destination); Q_INVOKABLE void to(const QScriptValue& destination);
Q_INVOKABLE QObject* debug(bool enable = true); Q_INVOKABLE QObject* debug(bool enable = true);
Q_INVOKABLE QObject* peek(bool enable = true);
Q_INVOKABLE QObject* when(const QScriptValue& expression); Q_INVOKABLE QObject* when(const QScriptValue& expression);
Q_INVOKABLE QObject* clamp(float min, float max); Q_INVOKABLE QObject* clamp(float min, float max);
Q_INVOKABLE QObject* hysteresis(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* constrainToInteger();
Q_INVOKABLE QObject* constrainToPositiveInteger(); Q_INVOKABLE QObject* constrainToPositiveInteger();
private: private:
void to(const Endpoint::Pointer& destination); void to(const Endpoint::Pointer& destination);
void conditional(const Conditional::Pointer& conditional); void conditional(const Conditional::Pointer& conditional);
void addFilter(Filter::Pointer filter); void addFilter(Filter::Pointer filter);

View file

@ -18,7 +18,7 @@ namespace controller {
class EndpointConditional : public Conditional { class EndpointConditional : public Conditional {
public: public:
EndpointConditional(Endpoint::Pointer endpoint) : _endpoint(endpoint) {} 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: private:
Endpoint::Pointer _endpoint; Endpoint::Pointer _endpoint;
}; };

View file

@ -23,10 +23,10 @@ class ActionEndpoint : public Endpoint {
public: public:
ActionEndpoint(const Input& id = Input::INVALID_INPUT) : Endpoint(id) { } 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 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 apply(const Pose& value, const Pointer& source) override;
virtual void reset() override; virtual void reset() override;

View file

@ -27,13 +27,19 @@ AnyEndpoint::AnyEndpoint(Endpoint::List children) : Endpoint(Input::INVALID_INPU
} }
} }
float AnyEndpoint::peek() const {
float result = 0;
for (auto& child : _children) {
result = std::max(result, child->peek());
}
return result;
}
// Fetching the value must trigger any necessary side effects of value() on ALL the children.
float AnyEndpoint::value() { float AnyEndpoint::value() {
float result = 0; float result = 0;
for (auto& child : _children) { for (auto& child : _children) {
float childResult = child->value(); result = std::max(result, child->value());
if (childResult != 0.0f) {
result = childResult;
}
} }
return result; return result;
} }

View file

@ -19,6 +19,7 @@ class AnyEndpoint : public Endpoint {
public: public:
using Endpoint::apply; using Endpoint::apply;
AnyEndpoint(Endpoint::List children); AnyEndpoint(Endpoint::List children);
virtual float peek() const override;
virtual float value() override; virtual float value() override;
virtual void apply(float newValue, const Endpoint::Pointer& source) override; virtual void apply(float newValue, const Endpoint::Pointer& source) override;
virtual bool writeable() const override; virtual bool writeable() const override;

View file

@ -21,9 +21,7 @@ public:
using Pointer = std::shared_ptr<ArrayEndpoint>; using Pointer = std::shared_ptr<ArrayEndpoint>;
ArrayEndpoint() : Endpoint(Input::INVALID_INPUT) { } ArrayEndpoint() : Endpoint(Input::INVALID_INPUT) { }
virtual float value() override { virtual float peek() const override { return 0.0f; }
return 0.0;
}
virtual void apply(float value, const Endpoint::Pointer& source) override { virtual void apply(float value, const Endpoint::Pointer& source) override {
for (auto& child : _children) { for (auto& child : _children) {

View file

@ -24,6 +24,12 @@ bool CompositeEndpoint::readable() const {
return first->readable() && second->readable(); 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 CompositeEndpoint::value() {
float result = first->value() * -1.0f + second->value(); float result = first->value() * -1.0f + second->value();
return result; return result;

View file

@ -18,6 +18,7 @@ namespace controller {
using Endpoint::apply; using Endpoint::apply;
CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second); CompositeEndpoint(Endpoint::Pointer first, Endpoint::Pointer second);
virtual float peek() const override;
virtual float value() override; virtual float value() override;
virtual void apply(float newValue, const Pointer& source) override; virtual void apply(float newValue, const Pointer& source) override;
virtual bool readable() const override; virtual bool readable() const override;

View file

@ -13,10 +13,10 @@
#include "../../UserInputMapper.h" #include "../../UserInputMapper.h"
using namespace controller; using namespace controller;
float InputEndpoint::value(){
_read = true; float InputEndpoint::peek() const {
if (isPose()) { if (isPose()) {
return pose().valid ? 1.0f : 0.0f; return peekPose().valid ? 1.0f : 0.0f;
} }
auto userInputMapper = DependencyManager::get<UserInputMapper>(); auto userInputMapper = DependencyManager::get<UserInputMapper>();
auto deviceProxy = userInputMapper->getDevice(_input); auto deviceProxy = userInputMapper->getDevice(_input);
@ -26,8 +26,12 @@ float InputEndpoint::value(){
return deviceProxy->getValue(_input); return deviceProxy->getValue(_input);
} }
Pose InputEndpoint::pose() { float InputEndpoint::value(){
_read = true; _read = true;
return peek();
}
Pose InputEndpoint::peekPose() const {
if (!isPose()) { if (!isPose()) {
return Pose(); return Pose();
} }
@ -39,3 +43,8 @@ Pose InputEndpoint::pose() {
return deviceProxy->getPose(_input.channel); return deviceProxy->getPose(_input.channel);
} }
Pose InputEndpoint::pose() {
_read = true;
return peekPose();
}

View file

@ -20,9 +20,11 @@ public:
: Endpoint(id) { : Endpoint(id) {
} }
virtual float peek() const override;
virtual float value() override; virtual float value() override;
// FIXME need support for writing back to vibration / force feedback effects // FIXME need support for writing back to vibration / force feedback effects
virtual void apply(float newValue, const Pointer& source) override {} virtual void apply(float newValue, const Pointer& source) override {}
virtual Pose peekPose() const override;
virtual Pose pose() override; virtual Pose pose() override;
virtual void apply(const Pose& value, const Pointer& source) override { } virtual void apply(const Pose& value, const Pointer& source) override { }

View file

@ -24,9 +24,8 @@ public:
: Endpoint(Input::INVALID_INPUT), _callable(callable) { : Endpoint(Input::INVALID_INPUT), _callable(callable) {
} }
virtual float value() { virtual float peek() const {
float result = (float)_callable.call().toNumber(); return (float)const_cast<JSEndpoint*>(this)->_callable.call().toNumber();
return result;
} }
virtual void apply(float newValue, const Pointer& source) { virtual void apply(float newValue, const Pointer& source) {

View file

@ -12,8 +12,8 @@
using namespace controller; using namespace controller;
float ScriptEndpoint::value() { float ScriptEndpoint::peek() const {
updateValue(); const_cast<ScriptEndpoint*>(this)->updateValue();
return _lastValueRead; return _lastValueRead;
} }

View file

@ -24,8 +24,8 @@ public:
: Endpoint(Input::INVALID_INPUT), _callable(callable) { : Endpoint(Input::INVALID_INPUT), _callable(callable) {
} }
virtual float value(); virtual float peek() const override;
virtual void apply(float newValue, const Pointer& source); virtual void apply(float newValue, const Pointer& source) override;
protected: protected:
Q_INVOKABLE void updateValue(); Q_INVOKABLE void updateValue();