summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControlReference
diff options
context:
space:
mode:
authorJordan Woyak <jordan.woyak@gmail.com>2018-12-30 16:06:29 -0600
committerJordan Woyak <jordan.woyak@gmail.com>2019-10-11 17:14:32 -0500
commite896835f86e52051b1998a344549dfa8ba79847a (patch)
tree3dd3d8523f1804400dc70550188cf6a932a0af3b /Source/Core/InputCommon/ControlReference
parent1efcf861ead76bbffb4ac22726d799975146707c (diff)
ExpressionParser: Renamed ControlFinder to ControlEnvironment. Added support for variables and assignment operator. ControlExpression objects now reference a matching input and output so the two can me mixed in any expression. (you can set rumble directly from inputs)
Diffstat (limited to 'Source/Core/InputCommon/ControlReference')
-rw-r--r--Source/Core/InputCommon/ControlReference/ControlReference.cpp8
-rw-r--r--Source/Core/InputCommon/ControlReference/ControlReference.h3
-rw-r--r--Source/Core/InputCommon/ControlReference/ExpressionParser.cpp124
-rw-r--r--Source/Core/InputCommon/ControlReference/ExpressionParser.h20
4 files changed, 114 insertions, 41 deletions
diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp
index cfc6fa658e..c17cfb3c86 100644
--- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp
+++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp
@@ -25,12 +25,12 @@ bool ControlReference::InputGateOn()
// Updates a controlreference's binded devices/controls
// need to call this to re-bind a control reference after changing its expression
//
-void ControlReference::UpdateReference(const ciface::Core::DeviceContainer& devices,
- const ciface::Core::DeviceQualifier& default_device)
+void ControlReference::UpdateReference(ciface::ExpressionParser::ControlEnvironment& env)
{
- ControlFinder finder(devices, default_device, IsInput());
if (m_parsed_expression)
- m_parsed_expression->UpdateReferences(finder);
+ {
+ m_parsed_expression->UpdateReferences(env);
+ }
}
int ControlReference::BoundCount() const
diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.h b/Source/Core/InputCommon/ControlReference/ControlReference.h
index 83fa288676..3f2c205501 100644
--- a/Source/Core/InputCommon/ControlReference/ControlReference.h
+++ b/Source/Core/InputCommon/ControlReference/ControlReference.h
@@ -30,8 +30,7 @@ public:
int BoundCount() const;
ciface::ExpressionParser::ParseStatus GetParseStatus() const;
- void UpdateReference(const ciface::Core::DeviceContainer& devices,
- const ciface::Core::DeviceQualifier& default_device);
+ void UpdateReference(ciface::ExpressionParser::ControlEnvironment& env);
std::string GetExpression() const;
void SetExpression(std::string expr);
diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
index 2de2650699..f375c465d7 100644
--- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
+++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
@@ -35,8 +35,10 @@ enum TokenType
TOK_MUL,
TOK_DIV,
TOK_MOD,
+ TOK_ASSIGN,
TOK_CONTROL,
TOK_LITERAL,
+ TOK_VARIABLE,
};
inline std::string OpName(TokenType op)
@@ -57,6 +59,10 @@ inline std::string OpName(TokenType op)
return "Div";
case TOK_MOD:
return "Mod";
+ case TOK_ASSIGN:
+ return "Assign";
+ case TOK_VARIABLE:
+ return "Var";
default:
assert(false);
return "";
@@ -97,10 +103,14 @@ public:
return "/";
case TOK_MOD:
return "%";
+ case TOK_ASSIGN:
+ return "=";
case TOK_CONTROL:
return "Device(" + data + ")";
case TOK_LITERAL:
return '\'' + data + '\'';
+ case TOK_VARIABLE:
+ return '$' + data;
case TOK_INVALID:
break;
}
@@ -131,21 +141,23 @@ public:
return false;
}
- Token GetUnaryFunction()
+ std::string FetchWordChars()
{
- std::string name;
+ std::string word;
std::regex valid_name_char("[a-z0-9_]", std::regex_constants::icase);
while (it != expr.end() && std::regex_match(std::string(1, *it), valid_name_char))
{
- name += *it;
+ word += *it;
++it;
}
- return Token(TOK_UNARY, name);
+ return word;
}
+ Token GetUnaryFunction() { return Token(TOK_UNARY, FetchWordChars()); }
+
Token GetLiteral()
{
std::string value;
@@ -153,6 +165,8 @@ public:
return Token(TOK_LITERAL, value);
}
+ Token GetVariable() { return Token(TOK_VARIABLE, FetchWordChars()); }
+
Token GetFullyQualifiedControl()
{
std::string value;
@@ -210,8 +224,12 @@ public:
return Token(TOK_DIV);
case '%':
return Token(TOK_MOD);
+ case '=':
+ return Token(TOK_ASSIGN);
case '\'':
return GetLiteral();
+ case '$':
+ return GetVariable();
case '`':
return GetFullyQualifiedControl();
default:
@@ -249,15 +267,14 @@ public:
class ControlExpression : public Expression
{
public:
- ControlQualifier qualifier;
- Device::Control* control = nullptr;
// Keep a shared_ptr to the device so the control pointer doesn't become invalid
+ // TODO: This is causing devices to be destructed after backends are shutdown:
std::shared_ptr<Device> m_device;
explicit ControlExpression(ControlQualifier qualifier_) : qualifier(qualifier_) {}
ControlState GetValue() const override
{
- if (!control)
+ if (!input)
return 0.0;
// Note: Inputs may return negative values in situations where opposing directions are
@@ -266,20 +283,26 @@ public:
// FYI: Clamping values greater than 1.0 is purposely not done to support unbounded values in
// the future. (e.g. raw accelerometer/gyro data)
- return std::max(0.0, control->ToInput()->GetState());
+ return std::max(0.0, input->GetState());
}
void SetValue(ControlState value) override
{
- if (control)
- control->ToOutput()->SetState(value);
+ if (output)
+ output->SetState(value);
}
- int CountNumControls() const override { return control ? 1 : 0; }
- void UpdateReferences(ControlFinder& finder) override
+ int CountNumControls() const override { return (input || output) ? 1 : 0; }
+ void UpdateReferences(ControlEnvironment& env) override
{
- m_device = finder.FindDevice(qualifier);
- control = finder.FindControl(qualifier);
+ m_device = env.FindDevice(qualifier);
+ input = env.FindInput(qualifier);
+ output = env.FindOutput(qualifier);
}
operator std::string() const override { return "`" + static_cast<std::string>(qualifier) + "`"; }
+
+private:
+ ControlQualifier qualifier;
+ Device::Input* input = nullptr;
+ Device::Output* output = nullptr;
};
class BinaryExpression : public Expression
@@ -319,6 +342,12 @@ public:
const ControlState result = std::fmod(lhsValue, rhsValue);
return std::isnan(result) ? 0.0 : result;
}
+ case TOK_ASSIGN:
+ {
+ lhs->SetValue(rhsValue);
+ // TODO: Should this instead GetValue(lhs) ?
+ return rhsValue;
+ }
default:
assert(false);
return 0;
@@ -338,10 +367,10 @@ public:
return lhs->CountNumControls() + rhs->CountNumControls();
}
- void UpdateReferences(ControlFinder& finder) override
+ void UpdateReferences(ControlEnvironment& env) override
{
- lhs->UpdateReferences(finder);
- rhs->UpdateReferences(finder);
+ lhs->UpdateReferences(env);
+ rhs->UpdateReferences(env);
}
operator std::string() const override
@@ -356,7 +385,7 @@ public:
UnaryExpression(std::unique_ptr<Expression>&& inner_) : inner(std::move(inner_)) {}
int CountNumControls() const override { return inner->CountNumControls(); }
- void UpdateReferences(ControlFinder& finder) override { inner->UpdateReferences(finder); }
+ void UpdateReferences(ControlEnvironment& env) override { inner->UpdateReferences(env); }
operator std::string() const override
{
@@ -462,7 +491,7 @@ public:
int CountNumControls() const override { return 1; }
- void UpdateReferences(ControlFinder&) override
+ void UpdateReferences(ControlEnvironment&) override
{
// Nothing needed.
}
@@ -523,6 +552,29 @@ std::unique_ptr<LiteralExpression> MakeLiteralExpression(std::string name)
}
}
+class VariableExpression : public Expression
+{
+public:
+ VariableExpression(std::string name) : m_name(name) {}
+
+ ControlState GetValue() const override { return *m_value_ptr; }
+
+ void SetValue(ControlState value) override { *m_value_ptr = value; }
+
+ int CountNumControls() const override { return 1; }
+
+ void UpdateReferences(ControlEnvironment& env) override
+ {
+ m_value_ptr = env.GetVariablePtr(m_name);
+ }
+
+ operator std::string() const override { return '$' + m_name; }
+
+protected:
+ const std::string m_name;
+ ControlState* m_value_ptr{};
+};
+
// This class proxies all methods to its either left-hand child if it has bound controls, or its
// right-hand child. Its intended use is for supporting old-style barewords expressions.
class CoalesceExpression : public Expression
@@ -543,10 +595,10 @@ public:
static_cast<std::string>(*m_rhs) + ')';
}
- void UpdateReferences(ControlFinder& finder) override
+ void UpdateReferences(ControlEnvironment& env) override
{
- m_lhs->UpdateReferences(finder);
- m_rhs->UpdateReferences(finder);
+ m_lhs->UpdateReferences(env);
+ m_rhs->UpdateReferences(env);
}
private:
@@ -559,7 +611,7 @@ private:
std::unique_ptr<Expression> m_rhs;
};
-std::shared_ptr<Device> ControlFinder::FindDevice(ControlQualifier qualifier) const
+std::shared_ptr<Device> ControlEnvironment::FindDevice(ControlQualifier qualifier) const
{
if (qualifier.has_device)
return container.FindDevice(qualifier.device_qualifier);
@@ -567,16 +619,27 @@ std::shared_ptr<Device> ControlFinder::FindDevice(ControlQualifier qualifier) co
return container.FindDevice(default_device);
}
-Device::Control* ControlFinder::FindControl(ControlQualifier qualifier) const
+Device::Input* ControlEnvironment::FindInput(ControlQualifier qualifier) const
{
const std::shared_ptr<Device> device = FindDevice(qualifier);
if (!device)
return nullptr;
- if (is_input)
- return device->FindInput(qualifier.control_name);
- else
- return device->FindOutput(qualifier.control_name);
+ return device->FindInput(qualifier.control_name);
+}
+
+Device::Output* ControlEnvironment::FindOutput(ControlQualifier qualifier) const
+{
+ const std::shared_ptr<Device> device = FindDevice(qualifier);
+ if (!device)
+ return nullptr;
+
+ return device->FindOutput(qualifier.control_name);
+}
+
+ControlState* ControlEnvironment::GetVariablePtr(const std::string& name)
+{
+ return &m_variables[name];
}
struct ParseResult
@@ -623,6 +686,10 @@ private:
{
return {ParseStatus::Successful, MakeLiteralExpression(tok.data)};
}
+ case TOK_VARIABLE:
+ {
+ return {ParseStatus::Successful, std::make_unique<VariableExpression>(tok.data)};
+ }
case TOK_LPAREN:
return Paren();
default:
@@ -665,6 +732,7 @@ private:
case TOK_MUL:
case TOK_DIV:
case TOK_MOD:
+ case TOK_ASSIGN:
return true;
default:
return false;
diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.h b/Source/Core/InputCommon/ControlReference/ExpressionParser.h
index 0a42d90c62..d9f7a5eb2b 100644
--- a/Source/Core/InputCommon/ControlReference/ExpressionParser.h
+++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.h
@@ -4,6 +4,7 @@
#pragma once
+#include <map>
#include <memory>
#include <string>
#include <utility>
@@ -46,21 +47,26 @@ public:
}
};
-class ControlFinder
+class ControlEnvironment
{
public:
- ControlFinder(const Core::DeviceContainer& container_, const Core::DeviceQualifier& default_,
- const bool is_input_)
- : container(container_), default_device(default_), is_input(is_input_)
+ using VariableContainer = std::map<std::string, ControlState>;
+
+ ControlEnvironment(const Core::DeviceContainer& container_, const Core::DeviceQualifier& default_,
+ VariableContainer& vars)
+ : m_variables(vars), container(container_), default_device(default_)
{
}
+
std::shared_ptr<Core::Device> FindDevice(ControlQualifier qualifier) const;
- Core::Device::Control* FindControl(ControlQualifier qualifier) const;
+ Core::Device::Input* FindInput(ControlQualifier qualifier) const;
+ Core::Device::Output* FindOutput(ControlQualifier qualifier) const;
+ ControlState* GetVariablePtr(const std::string& name);
private:
+ VariableContainer& m_variables;
const Core::DeviceContainer& container;
const Core::DeviceQualifier& default_device;
- bool is_input;
};
class Expression
@@ -70,7 +76,7 @@ public:
virtual ControlState GetValue() const = 0;
virtual void SetValue(ControlState state) = 0;
virtual int CountNumControls() const = 0;
- virtual void UpdateReferences(ControlFinder& finder) = 0;
+ virtual void UpdateReferences(ControlEnvironment& finder) = 0;
virtual operator std::string() const = 0;
};