Conditional support from JS

This commit is contained in:
Brad Davis 2015-10-23 11:25:06 -07:00
parent d5425ac625
commit 4e6f64833f
6 changed files with 62 additions and 3 deletions

View file

@ -4,8 +4,10 @@ ControllerTest = function() {
var xbox = Controller.Hardware.GamePad;
this.mappingEnabled = false;
this.mapping = Controller.newMapping();
this.mapping.from(standard.LX).when([standard.LB, standard.RB]).to(actions.Yaw);
this.mapping.from(standard.RX).to(actions.StepYaw);
this.mapping.from(standard.RY).invert().to(actions.Pitch);
this.mapping.from(standard.RY).invert().to(actions.Pitch);
var testMakeAxis = false;

View file

@ -738,6 +738,47 @@ Endpoint::Pointer UserInputMapper::parseEndpoint(const QJsonValue& value) {
return result;
}
Conditional::Pointer UserInputMapper::conditionalFor(const QJSValue& condition) {
return Conditional::Pointer();
}
Conditional::Pointer UserInputMapper::conditionalFor(const QScriptValue& condition) {
if (condition.isArray()) {
int length = condition.property("length").toInteger();
Conditional::List children;
for (int i = 0; i < length; i++) {
Conditional::Pointer destination = conditionalFor(condition.property(i));
if (!destination) {
return Conditional::Pointer();
}
children.push_back(destination);
}
return std::make_shared<AndConditional>(children);
}
if (condition.isNumber()) {
return conditionalFor(Input(condition.toInt32()));
}
if (condition.isFunction()) {
return std::make_shared<ScriptConditional>(condition);
}
qWarning() << "Unsupported conditional type " << condition.toString();
return Conditional::Pointer();
}
Conditional::Pointer UserInputMapper::conditionalFor(const Input& inputId) const {
Locker locker(_lock);
auto iterator = _endpointsByInput.find(inputId);
if (_endpointsByInput.end() == iterator) {
qWarning() << "Unknown input: " << QString::number(inputId.getID(), 16);
return Conditional::Pointer();
}
return std::make_shared<EndpointConditional>(iterator->second);
}
Conditional::Pointer UserInputMapper::parseConditional(const QJsonValue& value) {
if (value.isArray()) {
// Support "when" : [ "GamePad.RB", "GamePad.LB" ]
@ -764,7 +805,6 @@ Conditional::Pointer UserInputMapper::parseConditional(const QJsonValue& value)
return Conditional::parse(value);
}
Filter::Pointer UserInputMapper::parseFilter(const QJsonValue& value) {
Filter::Pointer result;
if (value.isString()) {
@ -780,7 +820,6 @@ Filter::Pointer UserInputMapper::parseFilter(const QJsonValue& value) {
return result;
}
Filter::List UserInputMapper::parseFilters(const QJsonValue& value) {
if (value.isNull()) {
return Filter::List();

View file

@ -143,6 +143,7 @@ namespace controller {
friend class MappingBuilderProxy;
void runMappings();
static void applyRoutes(const RouteList& route);
static bool applyRoute(const RoutePointer& route, bool force = false);
void enableMapping(const MappingPointer& mapping);
@ -151,6 +152,9 @@ namespace controller {
EndpointPointer endpointFor(const QScriptValue& endpoint);
EndpointPointer endpointFor(const Input& endpoint) const;
EndpointPointer compositeEndpointFor(EndpointPointer first, EndpointPointer second);
ConditionalPointer conditionalFor(const QJSValue& endpoint);
ConditionalPointer conditionalFor(const QScriptValue& endpoint);
ConditionalPointer conditionalFor(const Input& endpoint) const;
MappingPointer parseMapping(const QJsonValue& json);
RoutePointer parseRoute(const QJsonValue& value);

View file

@ -28,6 +28,7 @@ namespace controller {
using Pointer = std::shared_ptr<Conditional>;
using List = std::list<Pointer>;
using Factory = hifi::SimpleFactory<Conditional, QString>;
using Lambda = std::function<bool()>;
virtual bool satisfied() = 0;
virtual bool parseParameters(const QJsonValue& parameters) { return true; }

View file

@ -33,7 +33,6 @@ void RouteBuilderProxy::to(const QScriptValue& destination) {
}
void RouteBuilderProxy::to(const Endpoint::Pointer& destination) {
auto sourceEndpoint = _route->source;
_route->destination = destination;
_mapping->routes.push_back(_route);
deleteLater();
@ -56,6 +55,17 @@ QObject* RouteBuilderProxy::filterQml(const QJSValue& expression) {
return this;
}
QObject* RouteBuilderProxy::when(const QScriptValue& expression) {
_route->conditional = _parent.conditionalFor(expression);
return this;
}
QObject* RouteBuilderProxy::whenQml(const QJSValue& expression) {
_route->conditional = _parent.conditionalFor(expression);
return this;
}
QObject* RouteBuilderProxy::filter(const QScriptValue& expression) {
return this;
}

View file

@ -35,9 +35,11 @@ class RouteBuilderProxy : public QObject {
Q_INVOKABLE void toQml(const QJSValue& destination);
Q_INVOKABLE QObject* filterQml(const QJSValue& expression);
Q_INVOKABLE QObject* whenQml(const QJSValue& expression);
Q_INVOKABLE void to(const QScriptValue& destination);
Q_INVOKABLE QObject* debug(bool enable = true);
Q_INVOKABLE QObject* when(const QScriptValue& expression);
Q_INVOKABLE QObject* filter(const QScriptValue& expression);
Q_INVOKABLE QObject* clamp(float min, float max);
Q_INVOKABLE QObject* pulse(float interval);
@ -49,6 +51,7 @@ class RouteBuilderProxy : public QObject {
private:
void to(const Endpoint::Pointer& destination);
void conditional(const Conditional::Pointer& conditional);
void addFilter(Filter::Lambda lambda);
void addFilter(Filter::Pointer filter);
UserInputMapper& _parent;