Merge pull request #12655 from jordan-woyak/numeric-setting-fix
NumericSetting: Stop values from binding to numbered input names.
This commit is contained in:
commit
a44511741c
|
@ -332,6 +332,9 @@ MappingWidget::CreateSettingAdvancedMappingButton(ControllerEmu::NumericSettingB
|
||||||
if (setting.IsSimpleValue())
|
if (setting.IsSimpleValue())
|
||||||
setting.SetExpressionFromValue();
|
setting.SetExpressionFromValue();
|
||||||
|
|
||||||
|
// Ensure the UI has the game-controller indicator while editing the expression.
|
||||||
|
ConfigChanged();
|
||||||
|
|
||||||
IOWindow io(this, GetController(), &setting.GetInputReference(), IOWindow::Type::Input);
|
IOWindow io(this, GetController(), &setting.GetInputReference(), IOWindow::Type::Input);
|
||||||
SetQWidgetWindowDecorations(&io);
|
SetQWidgetWindowDecorations(&io);
|
||||||
io.exec();
|
io.exec();
|
||||||
|
|
|
@ -9,6 +9,12 @@
|
||||||
#include "InputCommon/ControlReference/ExpressionParser.h"
|
#include "InputCommon/ControlReference/ExpressionParser.h"
|
||||||
#include "InputCommon/ControllerInterface/CoreDevice.h"
|
#include "InputCommon/ControllerInterface/CoreDevice.h"
|
||||||
|
|
||||||
|
namespace ControllerEmu
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
T ControlStateCast(ControlState value);
|
||||||
|
}
|
||||||
|
|
||||||
// ControlReference
|
// ControlReference
|
||||||
//
|
//
|
||||||
// These are what you create to actually use the inputs, InputReference or OutputReference.
|
// These are what you create to actually use the inputs, InputReference or OutputReference.
|
||||||
|
@ -31,7 +37,10 @@ public:
|
||||||
virtual bool IsInput() const = 0;
|
virtual bool IsInput() const = 0;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T GetState();
|
T GetState()
|
||||||
|
{
|
||||||
|
return ControllerEmu::ControlStateCast<T>(State());
|
||||||
|
}
|
||||||
|
|
||||||
int BoundCount() const;
|
int BoundCount() const;
|
||||||
ciface::ExpressionParser::ParseStatus GetParseStatus() const;
|
ciface::ExpressionParser::ParseStatus GetParseStatus() const;
|
||||||
|
@ -51,24 +60,27 @@ protected:
|
||||||
ciface::ExpressionParser::ParseStatus::EmptyExpression;
|
ciface::ExpressionParser::ParseStatus::EmptyExpression;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace ControllerEmu
|
||||||
|
{
|
||||||
template <>
|
template <>
|
||||||
inline bool ControlReference::GetState<bool>()
|
inline bool ControlStateCast<bool>(ControlState value)
|
||||||
{
|
{
|
||||||
// Round to nearest of 0 or 1.
|
// Round to nearest of 0 or 1.
|
||||||
return std::lround(State()) > 0;
|
return std::lround(value) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline int ControlReference::GetState<int>()
|
inline int ControlStateCast<int>(ControlState value)
|
||||||
{
|
{
|
||||||
return std::lround(State());
|
return std::lround(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline ControlState ControlReference::GetState<ControlState>()
|
inline ControlState ControlStateCast<ControlState>(ControlState value)
|
||||||
{
|
{
|
||||||
return State();
|
return value;
|
||||||
}
|
}
|
||||||
|
} // namespace ControllerEmu
|
||||||
|
|
||||||
//
|
//
|
||||||
// InputReference
|
// InputReference
|
||||||
|
|
|
@ -830,6 +830,12 @@ private:
|
||||||
// Interpret it as a unary minus function.
|
// Interpret it as a unary minus function.
|
||||||
return ParseFunctionArguments("minus", MakeFunctionExpression("minus"), tok);
|
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:
|
default:
|
||||||
{
|
{
|
||||||
return ParseResult::MakeErrorResult(tok, _trans("Expected start of expression."));
|
return ParseResult::MakeErrorResult(tok, _trans("Expected start of expression."));
|
||||||
|
|
|
@ -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)
|
// usage: deadzone(input, amount)
|
||||||
class DeadzoneExpression : public FunctionExpression
|
class DeadzoneExpression : public FunctionExpression
|
||||||
{
|
{
|
||||||
|
@ -689,6 +705,8 @@ std::unique_ptr<FunctionExpression> MakeFunctionExpression(std::string_view name
|
||||||
return std::make_unique<ToggleExpression>();
|
return std::make_unique<ToggleExpression>();
|
||||||
if (name == "minus")
|
if (name == "minus")
|
||||||
return std::make_unique<UnaryMinusExpression>();
|
return std::make_unique<UnaryMinusExpression>();
|
||||||
|
if (name == "plus")
|
||||||
|
return std::make_unique<UnaryPlusExpression>();
|
||||||
if (name == "deadzone")
|
if (name == "deadzone")
|
||||||
return std::make_unique<DeadzoneExpression>();
|
return std::make_unique<DeadzoneExpression>();
|
||||||
if (name == "smooth")
|
if (name == "smooth")
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
namespace ControllerEmu
|
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
|
const char* NumericSettingBase::GetININame() const
|
||||||
{
|
{
|
||||||
return m_details.ini_name;
|
return m_details.ini_name;
|
||||||
|
@ -36,28 +41,20 @@ SettingVisibility NumericSettingBase::GetVisibility() const
|
||||||
return m_details.visibility;
|
return m_details.visibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <typename T>
|
||||||
void NumericSetting<int>::SetExpressionFromValue()
|
void NumericSetting<T>::SetExpressionFromValue()
|
||||||
{
|
{
|
||||||
m_value.m_input.SetExpression(ValueToString(GetValue()));
|
// 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 <>
|
template <typename T>
|
||||||
void NumericSetting<double>::SetExpressionFromValue()
|
void NumericSetting<T>::SimplifyIfPossible()
|
||||||
{
|
{
|
||||||
// We must use a dot decimal separator for expression parser.
|
ValueType value;
|
||||||
std::ostringstream ss;
|
if (TryParse(std::string(StripWhitespace(m_value.m_input.GetExpression())), &value))
|
||||||
ss.imbue(std::locale::classic());
|
m_value.SetValue(value);
|
||||||
ss << GetValue();
|
|
||||||
|
|
||||||
m_value.m_input.SetExpression(ss.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
void NumericSetting<bool>::SetExpressionFromValue()
|
|
||||||
{
|
|
||||||
// Cast bool to prevent "true"/"false" strings.
|
|
||||||
m_value.m_input.SetExpression(ValueToString(int(GetValue())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
|
@ -143,14 +143,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsSimpleValue() const override { return m_value.IsSimpleValue(); }
|
bool IsSimpleValue() const override { return m_value.IsSimpleValue(); }
|
||||||
|
void SimplifyIfPossible() override;
|
||||||
void SimplifyIfPossible() override
|
|
||||||
{
|
|
||||||
ValueType value;
|
|
||||||
if (TryParse(m_value.m_input.GetExpression(), &value))
|
|
||||||
m_value.SetValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetExpressionFromValue() override;
|
void SetExpressionFromValue() override;
|
||||||
InputReference& GetInputReference() override { return m_value.m_input; }
|
InputReference& GetInputReference() override { return m_value.m_input; }
|
||||||
const InputReference& GetInputReference() const override { return m_value.m_input; }
|
const InputReference& GetInputReference() const override { return m_value.m_input; }
|
||||||
|
|
Loading…
Reference in New Issue