mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 14:50:41 -07:00
96950b6b4e
## Link to GitHub Issue or related Pull Request, if one exists #181 ## Description of change Implement analog relative mode and delay option using a new millisecond-based algorithm. ## Testing WIP
161 lines
5.7 KiB
C++
161 lines
5.7 KiB
C++
#pragma once
|
|
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "cfg/analog.h"
|
|
#include "cfg/button.h"
|
|
|
|
namespace overlay::windows {
|
|
|
|
// single button binding entry (primary or alternative)
|
|
struct TemplateButtonEntry {
|
|
unsigned short vKey = INVALID_VKEY;
|
|
ButtonAnalogType analog_type = BAT_NONE;
|
|
std::string device_identifier;
|
|
bool invert = false;
|
|
double debounce_up = 0.0;
|
|
double debounce_down = 0.0;
|
|
int bat_threshold = 0;
|
|
unsigned short velocity_threshold = 0;
|
|
|
|
bool is_naive() const { return device_identifier.empty() && vKey != INVALID_VKEY; }
|
|
bool is_device() const { return !device_identifier.empty(); }
|
|
bool is_unbound() const { return device_identifier.empty() && vKey == INVALID_VKEY; }
|
|
|
|
static TemplateButtonEntry FromButton(const Button &btn) {
|
|
TemplateButtonEntry e;
|
|
e.vKey = btn.getVKey();
|
|
e.analog_type = btn.getAnalogType();
|
|
e.device_identifier = btn.getDeviceIdentifier();
|
|
e.invert = btn.getInvert();
|
|
e.debounce_up = btn.getDebounceUp();
|
|
e.debounce_down = btn.getDebounceDown();
|
|
e.bat_threshold = btn.getBatThreshold();
|
|
e.velocity_threshold = btn.getVelocityThreshold();
|
|
return e;
|
|
}
|
|
};
|
|
|
|
// button binding with primary + alternatives
|
|
struct TemplateButtonBinding {
|
|
std::string name;
|
|
TemplateButtonEntry primary;
|
|
std::vector<TemplateButtonEntry> alternatives;
|
|
|
|
TemplateButtonBinding() = default;
|
|
|
|
TemplateButtonBinding(std::string name, TemplateButtonEntry primary,
|
|
std::vector<TemplateButtonEntry> alternatives)
|
|
: name(std::move(name)), primary(std::move(primary)),
|
|
alternatives(std::move(alternatives)) {}
|
|
|
|
explicit TemplateButtonBinding(Button &btn) {
|
|
name = btn.getName();
|
|
primary = TemplateButtonEntry::FromButton(btn);
|
|
for (auto &alt : btn.getAlternatives()) {
|
|
alternatives.push_back(TemplateButtonEntry::FromButton(alt));
|
|
}
|
|
}
|
|
};
|
|
|
|
// analog binding
|
|
struct TemplateAnalogBinding {
|
|
std::string name;
|
|
std::string device_identifier;
|
|
unsigned short index = 0xFF;
|
|
float sensitivity = 1.f;
|
|
float deadzone = 0.f;
|
|
bool deadzone_mirror = false;
|
|
bool invert = false;
|
|
bool smoothing = false;
|
|
int multiplier = 1;
|
|
bool relative_mode = false;
|
|
uint32_t delay_ms = 0;
|
|
|
|
bool is_device() const { return !device_identifier.empty(); }
|
|
bool is_unbound() const { return device_identifier.empty() && index == 0xFF; }
|
|
|
|
TemplateAnalogBinding() = default;
|
|
|
|
explicit TemplateAnalogBinding(Analog &a) {
|
|
name = a.getName();
|
|
device_identifier = a.getDeviceIdentifier();
|
|
index = a.getIndex();
|
|
sensitivity = a.getSensitivity();
|
|
deadzone = a.getDeadzone();
|
|
deadzone_mirror = a.getDeadzoneMirror();
|
|
invert = a.getInvert();
|
|
smoothing = a.getSmoothing();
|
|
multiplier = a.getMultiplier();
|
|
relative_mode = a.isRelativeMode();
|
|
delay_ms = a.getDelayMs();
|
|
}
|
|
};
|
|
|
|
// single light binding entry (primary or alternative)
|
|
struct TemplateLightEntry {
|
|
std::string device_identifier;
|
|
unsigned int index = 0;
|
|
|
|
bool is_device() const { return !device_identifier.empty(); }
|
|
bool is_unbound() const { return device_identifier.empty(); }
|
|
};
|
|
|
|
// light binding with primary + alternatives
|
|
struct TemplateLightBinding {
|
|
std::string name;
|
|
TemplateLightEntry primary;
|
|
std::vector<TemplateLightEntry> alternatives;
|
|
|
|
TemplateLightBinding() = default;
|
|
|
|
TemplateLightBinding(std::string name, TemplateLightEntry primary,
|
|
std::vector<TemplateLightEntry> alternatives)
|
|
: name(std::move(name)), primary(std::move(primary)),
|
|
alternatives(std::move(alternatives)) {}
|
|
};
|
|
|
|
// controller preset
|
|
struct ControllerTemplate {
|
|
std::string name;
|
|
std::string game_name;
|
|
bool is_builtin = false;
|
|
std::vector<TemplateButtonBinding> buttons;
|
|
std::vector<TemplateButtonBinding> keypad_buttons;
|
|
std::vector<TemplateAnalogBinding> analogs;
|
|
std::vector<TemplateLightBinding> lights;
|
|
|
|
// helpers
|
|
int count_naive_buttons() const;
|
|
int count_device_buttons() const;
|
|
int count_device_analogs() const;
|
|
int count_device_lights() const;
|
|
std::set<std::string> get_used_devices() const;
|
|
|
|
// get all binding sources (device_identifier strings used in this preset)
|
|
std::vector<std::string> get_binding_sources() const;
|
|
|
|
// get summary of bindings for a specific source (for tooltip display)
|
|
std::string get_source_summary(const std::string &source) const;
|
|
|
|
// replace all occurrences of a source device_identifier with a new one
|
|
void rename_source(const std::string &old_id, const std::string &new_id);
|
|
};
|
|
|
|
// template management API
|
|
std::vector<ControllerTemplate> get_templates_for_game(const std::string &game_name);
|
|
std::vector<ControllerTemplate> load_user_templates();
|
|
bool save_user_template(
|
|
const ControllerTemplate &tmpl,
|
|
const bool save_buttons,
|
|
const bool save_keypads,
|
|
const bool save_analogs,
|
|
const bool save_lights);
|
|
|
|
bool delete_user_template(const std::string &game_name, const std::string &template_name);
|
|
bool rename_user_template(const std::string &game_name,
|
|
const std::string &old_name, const std::string &new_name);
|
|
}
|