summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControlReference/ControlReference.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/InputCommon/ControlReference/ControlReference.cpp')
-rw-r--r--Source/Core/InputCommon/ControlReference/ControlReference.cpp148
1 files changed, 148 insertions, 0 deletions
diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp
new file mode 100644
index 0000000000..4268531668
--- /dev/null
+++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp
@@ -0,0 +1,148 @@
+// Copyright 2016 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "Common/Thread.h"
+// For InputGateOn()
+// This is a bad layering violation, but it's the cleanest
+// place I could find to put it.
+#include "Core/ConfigManager.h"
+#include "Core/Host.h"
+
+#include "InputCommon/ControlReference/ControlReference.h"
+
+using namespace ciface::ExpressionParser;
+
+constexpr ControlState INPUT_DETECT_THRESHOLD = 0.55;
+
+bool ControlReference::InputGateOn()
+{
+ return SConfig::GetInstance().m_BackgroundInput || Host_RendererHasFocus() || Host_UIHasFocus();
+}
+
+//
+// UpdateReference
+//
+// Updates a controlreference's binded devices/controls
+// need to call this to re-parse a control reference's expression after changing it
+//
+void ControlReference::UpdateReference(ciface::Core::DeviceContainer& devices,
+ const ciface::Core::DeviceQualifier& default_device)
+{
+ delete parsed_expression;
+ parsed_expression = nullptr;
+
+ ControlFinder finder(devices, default_device, is_input);
+ parse_error = ParseExpression(expression, finder, &parsed_expression);
+}
+
+//
+// InputReference :: State
+//
+// Gets the state of an input reference
+// override function for ControlReference::State ...
+//
+ControlState InputReference::State(const ControlState ignore)
+{
+ if (parsed_expression && InputGateOn())
+ return parsed_expression->GetValue() * range;
+ return 0.0;
+}
+
+//
+// OutputReference :: State
+//
+// Set the state of all binded outputs
+// overrides ControlReference::State .. combined them so I could make the GUI simple / inputs ==
+// same as outputs one list
+// I was lazy and it works so watever
+//
+ControlState OutputReference::State(const ControlState state)
+{
+ if (parsed_expression && InputGateOn())
+ parsed_expression->SetValue(state);
+ return 0.0;
+}
+
+//
+// InputReference :: Detect
+//
+// Wait for input on all binded devices
+// supports not detecting inputs that were held down at the time of Detect start,
+// which is useful for those crazy flightsticks that have certain buttons that are always held down
+// or some crazy axes or something
+// upon input, return pointer to detected Control
+// else return nullptr
+//
+ciface::Core::Device::Control* InputReference::Detect(const unsigned int ms,
+ ciface::Core::Device* const device)
+{
+ unsigned int time = 0;
+ std::vector<bool> states(device->Inputs().size());
+
+ if (device->Inputs().size() == 0)
+ return nullptr;
+
+ // get starting state of all inputs,
+ // so we can ignore those that were activated at time of Detect start
+ std::vector<ciface::Core::Device::Input *>::const_iterator i = device->Inputs().begin(),
+ e = device->Inputs().end();
+ for (std::vector<bool>::iterator state = states.begin(); i != e; ++i)
+ *state++ = ((*i)->GetState() > (1 - INPUT_DETECT_THRESHOLD));
+
+ while (time < ms)
+ {
+ device->UpdateInput();
+ i = device->Inputs().begin();
+ for (std::vector<bool>::iterator state = states.begin(); i != e; ++i, ++state)
+ {
+ // detected an input
+ if ((*i)->IsDetectable() && (*i)->GetState() > INPUT_DETECT_THRESHOLD)
+ {
+ // input was released at some point during Detect call
+ // return the detected input
+ if (false == *state)
+ return *i;
+ }
+ else if ((*i)->GetState() < (1 - INPUT_DETECT_THRESHOLD))
+ {
+ *state = false;
+ }
+ }
+ Common::SleepCurrentThread(10);
+ time += 10;
+ }
+
+ // no input was detected
+ return nullptr;
+}
+
+//
+// OutputReference :: Detect
+//
+// Totally different from the inputReference detect / I have them combined so it was simpler to make
+// the GUI.
+// The GUI doesn't know the difference between an input and an output / it's odd but I was lazy and
+// it was easy
+//
+// set all binded outputs to <range> power for x milliseconds return false
+//
+ciface::Core::Device::Control* OutputReference::Detect(const unsigned int ms,
+ ciface::Core::Device* const device)
+{
+ // ignore device
+
+ // don't hang if we don't even have any controls mapped
+ if (BoundCount() > 0)
+ {
+ State(1);
+ unsigned int slept = 0;
+
+ // this loop is to make stuff like flashing keyboard LEDs work
+ while (ms > (slept += 10))
+ Common::SleepCurrentThread(10);
+
+ State(0);
+ }
+ return nullptr;
+}