summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon
diff options
context:
space:
mode:
authorAdmiral H. Curtiss <pikachu025@gmail.com>2024-04-13 00:42:03 +0200
committerGitHub <noreply@github.com>2024-04-13 00:42:03 +0200
commita44511741c81f3cbc29b66a7cbf75333fcf517b5 (patch)
treec5cecbef96f2bc5b6e182d49d7409ebc21112a85 /Source/Core/InputCommon
parent2011c7a4483942cb4001ac7edd584914670e5c33 (diff)
parent9321318cb6e15976a589d38edd5ca039d407cf23 (diff)
Merge pull request #12655 from jordan-woyak/numeric-setting-fix
NumericSetting: Stop values from binding to numbered input names.
Diffstat (limited to 'Source/Core/InputCommon')
-rw-r--r--Source/Core/InputCommon/ControlReference/ControlReference.h26
-rw-r--r--Source/Core/InputCommon/ControlReference/ExpressionParser.cpp6
-rw-r--r--Source/Core/InputCommon/ControlReference/FunctionExpression.cpp18
-rw-r--r--Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.cpp35
-rw-r--r--Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h9
5 files changed, 60 insertions, 34 deletions
diff --git a/Source/Core/InputCommon/ControlReference/ControlReference.h b/Source/Core/InputCommon/ControlReference/ControlReference.h
index f12e354bb3..984ab2cd0f 100644
--- a/Source/Core/InputCommon/ControlReference/ControlReference.h
+++ b/Source/Core/InputCommon/ControlReference/ControlReference.h
@@ -9,6 +9,12 @@
#include "InputCommon/ControlReference/ExpressionParser.h"
#include "InputCommon/ControllerInterface/CoreDevice.h"
+namespace ControllerEmu
+{
+template <typename T>
+T ControlStateCast(ControlState value);
+}
+
// ControlReference
//
// These are what you create to actually use the inputs, InputReference or OutputReference.
@@ -31,7 +37,10 @@ public:
virtual bool IsInput() const = 0;
template <typename T>
- T GetState();
+ T GetState()
+ {
+ return ControllerEmu::ControlStateCast<T>(State());
+ }
int BoundCount() const;
ciface::ExpressionParser::ParseStatus GetParseStatus() const;
@@ -51,24 +60,27 @@ protected:
ciface::ExpressionParser::ParseStatus::EmptyExpression;
};
+namespace ControllerEmu
+{
template <>
-inline bool ControlReference::GetState<bool>()
+inline bool ControlStateCast<bool>(ControlState value)
{
// Round to nearest of 0 or 1.
- return std::lround(State()) > 0;
+ return std::lround(value) > 0;
}
template <>
-inline int ControlReference::GetState<int>()
+inline int ControlStateCast<int>(ControlState value)
{
- return std::lround(State());
+ return std::lround(value);
}
template <>
-inline ControlState ControlReference::GetState<ControlState>()
+inline ControlState ControlStateCast<ControlState>(ControlState value)
{
- return State();
+ return value;
}
+} // namespace ControllerEmu
//
// InputReference
diff --git a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
index 30a261d13d..b76c170a2f 100644
--- a/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
+++ b/Source/Core/InputCommon/ControlReference/ExpressionParser.cpp
@@ -830,6 +830,12 @@ private:
// Interpret it as a unary minus function.
return ParseFunctionArguments("minus", MakeFunctionExpression("minus"), tok);
}
+ case TOK_ADD:
+ {
+ // An atom was expected but we got an addition symbol.
+ // Interpret it as a unary plus.
+ return ParseFunctionArguments("plus", MakeFunctionExpression("plus"), tok);
+ }
default:
{
return ParseResult::MakeErrorResult(tok, _trans("Expected start of expression."));
diff --git a/Source/Core/InputCommon/ControlReference/FunctionExpression.cpp b/Source/Core/InputCommon/ControlReference/FunctionExpression.cpp
index 46cfc37beb..15d8c72c0c 100644
--- a/Source/Core/InputCommon/ControlReference/FunctionExpression.cpp
+++ b/Source/Core/InputCommon/ControlReference/FunctionExpression.cpp
@@ -375,6 +375,22 @@ private:
}
};
+// usage: plus(expression)
+class UnaryPlusExpression : public FunctionExpression
+{
+private:
+ ArgumentValidation
+ ValidateArguments(const std::vector<std::unique_ptr<Expression>>& args) override
+ {
+ if (args.size() == 1)
+ return ArgumentsAreValid{};
+ else
+ return ExpectedArguments{"expression"};
+ }
+
+ ControlState GetValue() const override { return GetArg(0).GetValue(); }
+};
+
// usage: deadzone(input, amount)
class DeadzoneExpression : public FunctionExpression
{
@@ -689,6 +705,8 @@ std::unique_ptr<FunctionExpression> MakeFunctionExpression(std::string_view name
return std::make_unique<ToggleExpression>();
if (name == "minus")
return std::make_unique<UnaryMinusExpression>();
+ if (name == "plus")
+ return std::make_unique<UnaryPlusExpression>();
if (name == "deadzone")
return std::make_unique<DeadzoneExpression>();
if (name == "smooth")
diff --git a/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.cpp b/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.cpp
index ec28a4d6f6..f551e39b44 100644
--- a/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.cpp
+++ b/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.cpp
@@ -3,7 +3,7 @@
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
-#include <sstream>
+#include <fmt/format.h>
namespace ControllerEmu
{
@@ -11,6 +11,11 @@ NumericSettingBase::NumericSettingBase(const NumericSettingDetails& details) : m
{
}
+// Explicit instantiations so generic definitions can exist outside of the header.
+template class NumericSetting<int>;
+template class NumericSetting<double>;
+template class NumericSetting<bool>;
+
const char* NumericSettingBase::GetININame() const
{
return m_details.ini_name;
@@ -36,28 +41,20 @@ SettingVisibility NumericSettingBase::GetVisibility() const
return m_details.visibility;
}
-template <>
-void NumericSetting<int>::SetExpressionFromValue()
-{
- m_value.m_input.SetExpression(ValueToString(GetValue()));
-}
-
-template <>
-void NumericSetting<double>::SetExpressionFromValue()
+template <typename T>
+void NumericSetting<T>::SetExpressionFromValue()
{
- // We must use a dot decimal separator for expression parser.
- std::ostringstream ss;
- ss.imbue(std::locale::classic());
- ss << GetValue();
-
- m_value.m_input.SetExpression(ss.str());
+ // Always include -/+ sign to prevent CoalesceExpression binding.
+ // e.g. 1 is a valid input name for keyboard devices, +1 is not.
+ m_value.m_input.SetExpression(fmt::format("{:+g}", ControlState(GetValue())));
}
-template <>
-void NumericSetting<bool>::SetExpressionFromValue()
+template <typename T>
+void NumericSetting<T>::SimplifyIfPossible()
{
- // Cast bool to prevent "true"/"false" strings.
- m_value.m_input.SetExpression(ValueToString(int(GetValue())));
+ ValueType value;
+ if (TryParse(std::string(StripWhitespace(m_value.m_input.GetExpression())), &value))
+ m_value.SetValue(value);
}
template <>
diff --git a/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h b/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h
index 67d2fce1c7..b102b062e7 100644
--- a/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h
+++ b/Source/Core/InputCommon/ControllerEmu/Setting/NumericSetting.h
@@ -143,14 +143,7 @@ public:
}
bool IsSimpleValue() const override { return m_value.IsSimpleValue(); }
-
- void SimplifyIfPossible() override
- {
- ValueType value;
- if (TryParse(m_value.m_input.GetExpression(), &value))
- m_value.SetValue(value);
- }
-
+ void SimplifyIfPossible() override;
void SetExpressionFromValue() override;
InputReference& GetInputReference() override { return m_value.m_input; }
const InputReference& GetInputReference() const override { return m_value.m_input; }