summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2013-06-13 23:09:55 -0400
committerJasper St. Pierre <jstpierre@mecheye.net>2013-06-25 00:58:30 -0400
commit6246f6e81581339eb176cae044960e1f8437b488 (patch)
tree97ee262e44f276856c59bda17f76b302a537646e /Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp
parent877106b027431c6edb2d2c702fa6d811dac3d250 (diff)
InputCommon: Add a new ExpressionParser to replace the old hack language
This contains a new, hand-written expression parser to replace the old hack language based on string munging. The new approach is a simple AST-based evaluation approach, instead of the "list of operations" infix-based hack that there was before. The new language for configuration has support for parentheses, and counts "!" as a unary operator instead of the binary "NOT OR" operator it was before. A simple example: (X & Y) | !B Explicit device references, and complex device names ("Right Y+") are handled with backticks and colons: (`SDL/0/6 axis joystick:Right X+` & `DInput/0/Keyboard Mouse:A`) The basic editor UI that inserts tokens has not been updated to reflect the new language.
Diffstat (limited to 'Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp')
-rw-r--r--Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp128
1 files changed, 16 insertions, 112 deletions
diff --git a/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp
index e672e4598c..58e0653bbe 100644
--- a/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp
+++ b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp
@@ -21,6 +21,8 @@
#include "Thread.h"
+using namespace ciface::ExpressionParser;
+
namespace
{
const float INPUT_DETECT_THRESHOLD = 0.55f;
@@ -187,48 +189,10 @@ bool ControllerInterface::UpdateOutput(const bool force)
//
ControlState ControllerInterface::InputReference::State( const ControlState ignore )
{
- //if (NULL == device)
- //return 0;
-
- ControlState state = 0;
-
- std::vector<DeviceControl>::const_iterator
- ci = m_controls.begin(),
- ce = m_controls.end();
-
- // bit of hax for "NOT" to work at start of expression
- if (ci != ce)
- {
- if (ci->mode == 2)
- state = 1;
- }
-
- for (; ci!=ce; ++ci)
- {
- const ControlState istate = ci->control->ToInput()->GetState();
-
- switch (ci->mode)
- {
- // OR
- case 0 :
- state = std::max(state, istate);
- break;
- // AND
- case 1 :
- state = std::min(state, istate);
- break;
- // NOT
- case 2 :
- state = std::max(std::min(state, 1.0f - istate), 0.0f);
- break;
- // ADD
- case 3 :
- state += istate;
- break;
- }
- }
-
- return std::min(1.0f, state * range);
+ if (parsed_expression)
+ return parsed_expression->GetValue();
+ else
+ return 0.0f;
}
//
@@ -240,17 +204,9 @@ ControlState ControllerInterface::InputReference::State( const ControlState igno
//
ControlState ControllerInterface::OutputReference::State(const ControlState state)
{
- const ControlState tmp_state = std::min(1.0f, state * range);
-
- // output ref just ignores the modes ( |&!... )
-
- std::vector<DeviceControl>::iterator
- ci = m_controls.begin(),
- ce = m_controls.end();
- for (; ci != ce; ++ci)
- ci->control->ToOutput()->SetState(tmp_state);
-
- return state; // just return the output, watever
+ if (parsed_expression)
+ parsed_expression->SetValue(state);
+ return 0.0f;
}
//
@@ -262,65 +218,13 @@ ControlState ControllerInterface::OutputReference::State(const ControlState stat
void ControllerInterface::UpdateReference(ControllerInterface::ControlReference* ref
, const DeviceQualifier& default_device) const
{
- ref->m_controls.clear();
+ delete ref->parsed_expression;
+ ref->parsed_expression = NULL;
- // adding | to parse the last item, silly
- std::istringstream ss(ref->expression + '|');
-
- const std::string mode_chars("|&!^");
-
- ControlReference::DeviceControl devc;
-
- std::string dev_str;
- std::string ctrl_str;
-
- char c = 0;
- while (ss.read(&c, 1))
- {
- const size_t f = mode_chars.find(c);
-
- if (mode_chars.npos != f)
- {
- // add ctrl
- if (ctrl_str.size())
- {
- DeviceQualifier devq;
-
- // using default device or alterate device inside `backticks`
- if (dev_str.empty())
- devq = default_device;
- else
- devq.FromString(dev_str);
-
- // find device
- Device* const def_device = FindDevice(devq);
-
- if (def_device)
- {
- if (ref->is_input)
- devc.control = FindInput(ctrl_str, def_device);
- else
- devc.control = FindOutput(ctrl_str, def_device);
-
- if (devc.control)
- ref->m_controls.push_back(devc);
- }
- }
- // reset stuff for next ctrl
- devc.mode = (int)f;
- ctrl_str.clear();
- }
- else if ('`' == c)
- {
- // different device
- if (std::getline(ss, dev_str, '`').eof())
- break; // no terminating '`' character
- }
- else
- {
- ctrl_str += c;
- }
- }
+ ControlFinder finder(*this, default_device, ref->is_input);
+ ExpressionParseStatus status;
+ status = ParseExpression(ref->expression, finder, &ref->parsed_expression);
+ // XXX: do something with status?
}
//
@@ -388,7 +292,7 @@ Device::Control* ControllerInterface::OutputReference::Detect(const unsigned int
// ignore device
// don't hang if we don't even have any controls mapped
- if (m_controls.size())
+ if (BoundCount() > 0)
{
State(1);
unsigned int slept = 0;