mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
pc: add option to translate absolute analog values to fader input (#375)
## Link to GitHub Issue, if one exists n/a ## Description of change Add a new option that allows absolute position analog input, such as SDVX controller knobs and IIDX turntables, to be bound as input for Polaris Chord faders. In practice this means turning a knob counter-clockwise results in fader being held left (relative to velocity), and vice versa. ## Testing Tested using FauceTwo and a mouse.
This commit is contained in:
@@ -7,8 +7,68 @@
|
|||||||
#include "games/io.h"
|
#include "games/io.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "util/tapeled.h"
|
#include "util/tapeled.h"
|
||||||
|
#include "pc.h"
|
||||||
|
#include "util/utils.h"
|
||||||
|
|
||||||
namespace games::pc {
|
namespace games::pc {
|
||||||
|
bool PC_KNOB_MODE = false;
|
||||||
|
|
||||||
|
constexpr float RELATIVE_DECAY = 0.02f;
|
||||||
|
struct FADER_RELATIVE {
|
||||||
|
// ranges from 0.f to 1.f
|
||||||
|
float previous_raw = 0.5f;
|
||||||
|
|
||||||
|
// ranges from -1.f to +1.f
|
||||||
|
float effective_value = 0.f;
|
||||||
|
};
|
||||||
|
|
||||||
|
FADER_RELATIVE fader_l_relative;
|
||||||
|
FADER_RELATIVE fader_r_relative;
|
||||||
|
|
||||||
|
float calculate_analog_raw_delta(float old_value, float new_value) {
|
||||||
|
// assumed that values are between 0.f and 1.f
|
||||||
|
|
||||||
|
float delta = 0.f;
|
||||||
|
if ((old_value < 0.25f) && (0.75f < new_value)) {
|
||||||
|
// wrapped around: going left
|
||||||
|
delta = -((1.f - new_value) + old_value);
|
||||||
|
|
||||||
|
} else if ((new_value < 0.25f) && (0.75f < old_value)) {
|
||||||
|
// wrapped around: going right
|
||||||
|
delta = (1.f - old_value) + new_value;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
delta = new_value - old_value;
|
||||||
|
}
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
float apply_decay(float val) {
|
||||||
|
// return to center over time
|
||||||
|
if (RELATIVE_DECAY < val) {
|
||||||
|
return val - RELATIVE_DECAY;
|
||||||
|
} else if (val < -RELATIVE_DECAY) {
|
||||||
|
return val + RELATIVE_DECAY;
|
||||||
|
} else {
|
||||||
|
return 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float get_fader_knob_mode_value(float raw_analog, FADER_RELATIVE &fader) {
|
||||||
|
// add new value...
|
||||||
|
const float delta = calculate_analog_raw_delta(fader.previous_raw, raw_analog);
|
||||||
|
fader.effective_value += (delta * 20.f);
|
||||||
|
fader.previous_raw = raw_analog;
|
||||||
|
|
||||||
|
// capture the result after adding new input value
|
||||||
|
fader.effective_value = CLAMP(fader.effective_value, -1.f, 1.f);
|
||||||
|
const float result = fader.effective_value;
|
||||||
|
|
||||||
|
// post-process for next iteration: apply decay (return to center over time)
|
||||||
|
fader.effective_value = apply_decay(fader.effective_value);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* class definitions
|
* class definitions
|
||||||
@@ -270,7 +330,13 @@ namespace games::pc {
|
|||||||
// FADER-L
|
// FADER-L
|
||||||
float val = 0.f;
|
float val = 0.f;
|
||||||
if (analogs[Analogs::FaderL].isSet()) {
|
if (analogs[Analogs::FaderL].isSet()) {
|
||||||
val = (GameAPI::Analogs::getState(RI_MGR, analogs[Analogs::FaderL]) - 0.5f) * 2;
|
if (PC_KNOB_MODE) {
|
||||||
|
val = get_fader_knob_mode_value(
|
||||||
|
GameAPI::Analogs::getState(RI_MGR, analogs[Analogs::FaderL]),
|
||||||
|
fader_l_relative);
|
||||||
|
} else {
|
||||||
|
val = (GameAPI::Analogs::getState(RI_MGR, analogs[Analogs::FaderL]) - 0.5f) * 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderL_Left]) &&
|
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderL_Left]) &&
|
||||||
GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderL_Right])) {
|
GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderL_Right])) {
|
||||||
@@ -289,7 +355,13 @@ namespace games::pc {
|
|||||||
// FADER-R
|
// FADER-R
|
||||||
val = 0.f;
|
val = 0.f;
|
||||||
if (analogs[Analogs::FaderR].isSet()) {
|
if (analogs[Analogs::FaderR].isSet()) {
|
||||||
val = (GameAPI::Analogs::getState(RI_MGR, analogs[Analogs::FaderR]) - 0.5f) * 2;
|
if (PC_KNOB_MODE) {
|
||||||
|
val = get_fader_knob_mode_value(
|
||||||
|
GameAPI::Analogs::getState(RI_MGR, analogs[Analogs::FaderR]),
|
||||||
|
fader_r_relative);
|
||||||
|
} else {
|
||||||
|
val = (GameAPI::Analogs::getState(RI_MGR, analogs[Analogs::FaderR]) - 0.5f) * 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderR_Left]) &&
|
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderR_Left]) &&
|
||||||
GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderR_Right])) {
|
GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderR_Right])) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
namespace games::pc {
|
namespace games::pc {
|
||||||
extern std::string PC_INJECT_ARGS;
|
extern std::string PC_INJECT_ARGS;
|
||||||
extern bool PC_NO_IO;
|
extern bool PC_NO_IO;
|
||||||
|
extern bool PC_KNOB_MODE;
|
||||||
|
|
||||||
class PCGame : public games::Game {
|
class PCGame : public games::Game {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -1112,6 +1112,9 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
if (options[launcher::Options::PCNoIO].is_active()) {
|
if (options[launcher::Options::PCNoIO].is_active()) {
|
||||||
games::pc::PC_NO_IO = options[launcher::Options::PCNoIO].value_bool();
|
games::pc::PC_NO_IO = options[launcher::Options::PCNoIO].value_bool();
|
||||||
}
|
}
|
||||||
|
if (options[launcher::Options::PCKnobMode].value_bool()) {
|
||||||
|
games::pc::PC_KNOB_MODE = true;
|
||||||
|
}
|
||||||
if (options[launcher::Options::spice2x_EnableSMXStage].value_bool()) {
|
if (options[launcher::Options::spice2x_EnableSMXStage].value_bool()) {
|
||||||
rawinput::ENABLE_SMX_STAGE = true;
|
rawinput::ENABLE_SMX_STAGE = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1806,6 +1806,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.category = "Game Options (Advanced)"
|
.category = "Game Options (Advanced)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// PCArgs
|
||||||
.title = "PC Arguments Override",
|
.title = "PC Arguments Override",
|
||||||
.name = "pcargs",
|
.name = "pcargs",
|
||||||
.desc = "Command line arguments passed to the game.",
|
.desc = "Command line arguments passed to the game.",
|
||||||
@@ -1815,6 +1816,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.category = "Game Options (Advanced)",
|
.category = "Game Options (Advanced)",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// PCNoIO
|
||||||
.title = "PC Disable IO Emulation",
|
.title = "PC Disable IO Emulation",
|
||||||
.name = "pcnoio",
|
.name = "pcnoio",
|
||||||
.desc = "Disables BI2X hooks for PC",
|
.desc = "Disables BI2X hooks for PC",
|
||||||
@@ -1823,6 +1825,15 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.game_name = "Polaris Chord",
|
.game_name = "Polaris Chord",
|
||||||
.category = "Game Options (Advanced)"
|
.category = "Game Options (Advanced)"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// PCKnobMode
|
||||||
|
.title = "PC Fader Knobs Mode",
|
||||||
|
.name = "pcknobs",
|
||||||
|
.desc = "Allows SDVX knobs and IIDX turntables to be bound as Polaris Chord faders",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.game_name = "Polaris Chord",
|
||||||
|
.category = "Game Options",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// spice2x_LightsOverallBrightness
|
// spice2x_LightsOverallBrightness
|
||||||
.title = "Lights Brightness Adjustment",
|
.title = "Lights Brightness Adjustment",
|
||||||
|
|||||||
@@ -205,6 +205,7 @@ namespace launcher {
|
|||||||
MFGNoIO,
|
MFGNoIO,
|
||||||
PCArgs,
|
PCArgs,
|
||||||
PCNoIO,
|
PCNoIO,
|
||||||
|
PCKnobMode,
|
||||||
spice2x_LightsOverallBrightness,
|
spice2x_LightsOverallBrightness,
|
||||||
spice2x_WindowBorder,
|
spice2x_WindowBorder,
|
||||||
spice2x_WindowSize,
|
spice2x_WindowSize,
|
||||||
|
|||||||
Reference in New Issue
Block a user