mirror of
https://github.com/patchzyy/wiicompiled
synced 2026-09-10 09:11:52 -04:00
be153e0fa0
* Add Dolphin-compatible input expressions and GCPadNew.ini import Rebased onto current main; addresses both CodeRabbit reviews on #89. - Expression engine matching Dolphin's semantics: doubles rather than booleans, 0.5 press threshold, & as min, | as max, and the functions if, min, max, clamp, abs, sqrt, pow, sin, cos, tan, deadzone, timer, toggle, hold, tap, pulse and smooth. Timing uses a steady clock in seconds, as Dolphin does, so a copied expression behaves identically. - Expressions bind to the GameCube buttons and triggers, combined with the existing button mapping rather than replacing it, and are skipped while the settings overlay holds input. - Import reads [GCPadN] from the Dolphin config directory or from GCPadNew.ini beside the executable. Stick axes are not expression driven and keep their normal mapping. - Fixes #74: a digital button bound to L or R now reports a fully pulled analog trigger, plus a PlayStation preset and a vibration toggle. Review fixes: config paths round-trip through RuntimeConfigFile::PathToUtf8 and PathFromUtf8 so non-ASCII paths open correctly on Windows, and the duplicated exists branch is gone; the tap count is clamped before the unsigned conversion; the expression editor uses resizable storage via ImGuiInputTextFlags_CallbackResize so a long expression cannot be saved truncated; clamp bounds are ordered before std::clamp; <cstdlib> is included for std::strtod; non-finite values are rejected at the evaluator boundary as well as at the deadzone and timer divisions; and InputBindings::Reload() runs from InitializeRuntimeSettings rather than the vibration handler. runtime/tests/test_expr.cpp covers operator precedence, each stateful function and every case raised in review. Third review round: smooth() guards NaN as well as infinity so a zero rate cannot latch a non-finite value in node state; division evaluates both operands so stateful functions in the left subtree still update when the divisor is zero; the expression editor clears stale errors when the port changes; and runtime/tests/test_expr.cpp is registered with CTest as mkw_input_expr_tests, following the existing test targets. * Update runtime/src/input_expr.cpp Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update runtime/src/input_expr.cpp Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update runtime/src/input_expr.cpp Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
54 lines
1.7 KiB
C++
54 lines
1.7 KiB
C++
#pragma once
|
|
|
|
// Dolphin-compatible input expressions.
|
|
//
|
|
// Values are doubles in Dolphin's ControlState style; a control counts as
|
|
// pressed above kConditionThreshold. Timing matches Dolphin: wall-clock
|
|
// seconds on a steady clock, so an expression copied from GCPadNew.ini
|
|
// behaves the same here as it does there.
|
|
|
|
#include <filesystem>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace InputExpr {
|
|
|
|
inline constexpr double kConditionThreshold = 0.5;
|
|
|
|
// Resolves a backtick-quoted input name to its current value.
|
|
using InputSource = std::function<double(const std::string&)>;
|
|
|
|
struct Node;
|
|
|
|
class Expression {
|
|
public:
|
|
Expression();
|
|
~Expression();
|
|
Expression(Expression&&) noexcept;
|
|
Expression& operator=(Expression&&) noexcept;
|
|
|
|
// Returns false and fills error on a syntax problem.
|
|
static bool Parse(const std::string& text, Expression& out, std::string& error);
|
|
|
|
bool Empty() const { return m_root == nullptr; }
|
|
double Evaluate(const InputSource& source) const;
|
|
|
|
// Input names the expression references, for diagnostics.
|
|
std::vector<std::string> ReferencedInputs() const;
|
|
|
|
private:
|
|
std::unique_ptr<Node> m_root;
|
|
};
|
|
|
|
// Parses a Dolphin GCPadNew.ini and returns the expression text for each
|
|
// control of the requested pad, keyed by Dolphin's own control names
|
|
// ("Buttons/A", "D-Pad/Up", "Triggers/L", ...). Returns false if the file
|
|
// cannot be read or the section is missing.
|
|
bool ReadDolphinConfig(const std::filesystem::path& path, int padIndex,
|
|
std::vector<std::pair<std::string, std::string>>& controls,
|
|
std::string& deviceName, std::string& error);
|
|
|
|
} // namespace InputExpr
|