From a509f56116d308c96e38898e07d3538f26a1b7af Mon Sep 17 00:00:00 2001 From: Michael Maltese Date: Tue, 11 Oct 2016 17:48:38 -0700 Subject: InputCommon: Extract ControlReference from ControllerInterface Better separation of concerns. Relegates `ControllerInterface` to enumerating input controls, and the new `ControlReference` deals with combining inputs and configuration expression parsing. --- .../ControlReference/ControlReference.cpp | 148 +++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 Source/Core/InputCommon/ControlReference/ControlReference.cpp (limited to 'Source/Core/InputCommon/ControlReference/ControlReference.cpp') 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 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::const_iterator i = device->Inputs().begin(), + e = device->Inputs().end(); + for (std::vector::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::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 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; +} -- cgit v1.2.3 From 813a725f68775bd6a618e5eb3393f655313b647c Mon Sep 17 00:00:00 2001 From: Michael Maltese Date: Fri, 9 Dec 2016 13:07:49 -0800 Subject: ControlReference: move function bodies out of header --- .../ControlReference/ControlReference.cpp | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'Source/Core/InputCommon/ControlReference/ControlReference.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp index 4268531668..5b5d807781 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp +++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp @@ -36,6 +36,31 @@ void ControlReference::UpdateReference(ciface::Core::DeviceContainer& devices, parse_error = ParseExpression(expression, finder, &parsed_expression); } +ControlReference::~ControlReference() +{ + delete parsed_expression; +} +int ControlReference::BoundCount() const +{ + if (parsed_expression) + return parsed_expression->num_controls; + else + return 0; +} + +ControlReference::ControlReference(const bool _is_input) + : range(1), is_input(_is_input), parsed_expression(nullptr) +{ +} + +InputReference::InputReference() : ControlReference(true) +{ +} + +OutputReference::OutputReference() : ControlReference(false) +{ +} + // // InputReference :: State // -- cgit v1.2.3 From 9a632ea7b92b561de8304d8446b0d1e6e7e3e842 Mon Sep 17 00:00:00 2001 From: Michael Maltese Date: Fri, 9 Dec 2016 13:13:11 -0800 Subject: ControlReference: hide is_input behind function --- .../InputCommon/ControlReference/ControlReference.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ControlReference.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp index 5b5d807781..5dc8c858ed 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp +++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp @@ -32,7 +32,7 @@ void ControlReference::UpdateReference(ciface::Core::DeviceContainer& devices, delete parsed_expression; parsed_expression = nullptr; - ControlFinder finder(devices, default_device, is_input); + ControlFinder finder(devices, default_device, IsInput()); parse_error = ParseExpression(expression, finder, &parsed_expression); } @@ -48,19 +48,27 @@ int ControlReference::BoundCount() const return 0; } -ControlReference::ControlReference(const bool _is_input) - : range(1), is_input(_is_input), parsed_expression(nullptr) +ControlReference::ControlReference() : range(1), parsed_expression(nullptr) { } -InputReference::InputReference() : ControlReference(true) +InputReference::InputReference() : ControlReference() { } -OutputReference::OutputReference() : ControlReference(false) +OutputReference::OutputReference() : ControlReference() { } +bool InputReference::IsInput() const +{ + return true; +} +bool OutputReference::IsInput() const +{ + return false; +} + // // InputReference :: State // -- cgit v1.2.3 From 492d5b6ac7294ae183d47493b144ca0b3b4a7c2c Mon Sep 17 00:00:00 2001 From: Michael Maltese Date: Fri, 9 Dec 2016 13:19:23 -0800 Subject: ControlReference: hide parse_error behind GetParseStatus() --- Source/Core/InputCommon/ControlReference/ControlReference.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'Source/Core/InputCommon/ControlReference/ControlReference.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp index 5dc8c858ed..1d3d62e8c3 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp +++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp @@ -33,13 +33,14 @@ void ControlReference::UpdateReference(ciface::Core::DeviceContainer& devices, parsed_expression = nullptr; ControlFinder finder(devices, default_device, IsInput()); - parse_error = ParseExpression(expression, finder, &parsed_expression); + m_parse_status = ParseExpression(expression, finder, &parsed_expression); } ControlReference::~ControlReference() { delete parsed_expression; } + int ControlReference::BoundCount() const { if (parsed_expression) @@ -48,6 +49,11 @@ int ControlReference::BoundCount() const return 0; } +ExpressionParseStatus ControlReference::GetParseStatus() const +{ + return m_parse_status; +} + ControlReference::ControlReference() : range(1), parsed_expression(nullptr) { } -- cgit v1.2.3 From 2d51bf579f4c782951a3b9e7cd40327cdeb8b6b6 Mon Sep 17 00:00:00 2001 From: Michael Maltese Date: Fri, 9 Dec 2016 13:57:01 -0800 Subject: ControlReference: put parsed_expression in a unique_ptr --- .../ControlReference/ControlReference.cpp | 26 +++++++++------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'Source/Core/InputCommon/ControlReference/ControlReference.cpp') diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.cpp b/Source/Core/InputCommon/ControlReference/ControlReference.cpp index 1d3d62e8c3..56a1ad133f 100644 --- a/Source/Core/InputCommon/ControlReference/ControlReference.cpp +++ b/Source/Core/InputCommon/ControlReference/ControlReference.cpp @@ -29,22 +29,16 @@ bool ControlReference::InputGateOn() void ControlReference::UpdateReference(ciface::Core::DeviceContainer& devices, const ciface::Core::DeviceQualifier& default_device) { - delete parsed_expression; - parsed_expression = nullptr; - + Expression* expr; ControlFinder finder(devices, default_device, IsInput()); - m_parse_status = ParseExpression(expression, finder, &parsed_expression); -} - -ControlReference::~ControlReference() -{ - delete parsed_expression; + m_parse_status = ParseExpression(expression, finder, &expr); + m_parsed_expression.reset(expr); } int ControlReference::BoundCount() const { - if (parsed_expression) - return parsed_expression->num_controls; + if (m_parsed_expression) + return m_parsed_expression->num_controls; else return 0; } @@ -54,7 +48,7 @@ ExpressionParseStatus ControlReference::GetParseStatus() const return m_parse_status; } -ControlReference::ControlReference() : range(1), parsed_expression(nullptr) +ControlReference::ControlReference() : range(1), m_parsed_expression(nullptr) { } @@ -83,8 +77,8 @@ bool OutputReference::IsInput() const // ControlState InputReference::State(const ControlState ignore) { - if (parsed_expression && InputGateOn()) - return parsed_expression->GetValue() * range; + if (m_parsed_expression && InputGateOn()) + return m_parsed_expression->GetValue() * range; return 0.0; } @@ -98,8 +92,8 @@ ControlState InputReference::State(const ControlState ignore) // ControlState OutputReference::State(const ControlState state) { - if (parsed_expression && InputGateOn()) - parsed_expression->SetValue(state); + if (m_parsed_expression && InputGateOn()) + m_parsed_expression->SetValue(state); return 0.0; } -- cgit v1.2.3