mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 06:40:42 -07:00
af8d8dae9f
## Link to GitHub Issue or related Pull Request, if one exists n/a ## Description of change Currently, all analogs are treated as circular values that wrap around. This works for knobs and turntables, but can get weird for linear values (like tilt sensors and sliders) especially once analog options are enabled, such as sensitivity. This PR groups analogs into 3 buckets: circular, linear (centered), and linear (positive). Linear types get different algorithms applied to it when options are set (e.g., sensitivity caps out at 0, 1 instead of wrapping around). In linear mode: * Sensitivity value applies an exponential response curve (power curve) to the original value. * Multiplier/divisor serves as a linear cut-off. * Relative mode works as you expect, but of course, values don't wrap around. * Invert and deadzone work as you expect (since they applied to the controller input anyway) * Smoothing is removed from the UI and has no effect. * Delay is unaffected. Also, fix a small bug with -/+ button not working for analog `Delay` option. ## Testing WIP
154 lines
5.6 KiB
C++
154 lines
5.6 KiB
C++
#pragma once
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <windows.h>
|
|
#include "option.h"
|
|
|
|
#include "button.h"
|
|
#include "analog.h"
|
|
#include "light.h"
|
|
|
|
namespace rawinput {
|
|
class RawInputManager;
|
|
struct Device;
|
|
}
|
|
|
|
class Game;
|
|
class Option;
|
|
|
|
namespace GameAPI {
|
|
namespace Buttons {
|
|
/**
|
|
* Parses the config and returns the buttons set by the user.
|
|
*
|
|
* @param a std::string containing the game name OR a pointer to a Game
|
|
* @return a vector pointer containing pointers of Button's set by the user
|
|
*/
|
|
std::vector<Button> getButtons(const std::string &game_name);
|
|
std::vector<Button> getButtons(Game *);
|
|
|
|
/**
|
|
* Sorts Buttons by their name
|
|
*
|
|
* @param a pointer to a vector pointer of Button pointers that will be sorted by the order of a vector pointer of strings
|
|
* OR a parameter pack of std::string... can be used.
|
|
* @return void
|
|
*/
|
|
std::vector<Button> sortButtons(
|
|
const std::vector<Button> &buttons,
|
|
const std::vector<std::string> &button_names,
|
|
const std::vector<unsigned short> *vkey_defaults = nullptr);
|
|
|
|
template<typename T>
|
|
void sortButtons(std::vector<Button> *buttons, T t) {
|
|
const std::vector<std::string> names { t };
|
|
|
|
if (buttons) {
|
|
*buttons = GameAPI::Buttons::sortButtons(*buttons, names);
|
|
}
|
|
}
|
|
|
|
template<typename T, typename... Rest>
|
|
void sortButtons(std::vector<Button> *buttons, T t, Rest... rest) {
|
|
const std::vector<std::string> names { t, rest... };
|
|
|
|
if (buttons) {
|
|
*buttons = GameAPI::Buttons::sortButtons(*buttons, names);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the state of whether a button is pressed or not.
|
|
* Highly recommended to use either of these two functions than the other two below them.
|
|
*
|
|
* @return either a GameAPI::Buttons::State::BUTTON_PRESSED or a Game::API::Buttons::State::BUTTON_NOT_PRESSED
|
|
*/
|
|
State getState(rawinput::RawInputManager *manager, Button &button, bool check_alts = true);
|
|
State getState(std::unique_ptr<rawinput::RawInputManager> &manager, Button &button, bool check_alts = true);
|
|
|
|
/**
|
|
* Returns the current velocity of a button.
|
|
* When not pressed, the returned velocity is 0.
|
|
* When pressed, the velocity can be anywhere in the range [0, 1]
|
|
* @return velocity in the range [0, 1]
|
|
*/
|
|
float getVelocity(rawinput::RawInputManager *manager, Button &button);
|
|
float getVelocity(std::unique_ptr<rawinput::RawInputManager> &manager, Button &button);
|
|
}
|
|
|
|
namespace Analogs {
|
|
std::vector<Analog> getAnalogs(const std::string &game_name);
|
|
|
|
std::vector<Analog> sortAnalogs(
|
|
const std::vector<Analog> &analogs,
|
|
const std::vector<std::string> &analog_names);
|
|
|
|
struct AnalogWithType {
|
|
const std::string name;
|
|
const AnalogType type;
|
|
|
|
AnalogWithType(std::string name, AnalogType type) :
|
|
name(std::move(name)), type(type) {}
|
|
};
|
|
|
|
void sortAnalogsWithType(std::vector<Analog> *analogs, const std::initializer_list<AnalogWithType> list);
|
|
|
|
template<typename T, typename... Rest>
|
|
void sortAnalogs(std::vector<Analog> *analogs, T t, Rest... rest) {
|
|
const std::vector<std::string> analog_names { t, rest... };
|
|
|
|
if (analogs) {
|
|
*analogs = GameAPI::Analogs::sortAnalogs(*analogs, analog_names);
|
|
}
|
|
}
|
|
|
|
float getState(rawinput::RawInputManager *manager, rawinput::Device *device, Analog &analog);
|
|
float getState(rawinput::RawInputManager *manager, Analog &analog);
|
|
float getState(std::unique_ptr<rawinput::RawInputManager> &manager, Analog &analog);
|
|
}
|
|
|
|
namespace Lights {
|
|
|
|
std::vector<Light> getLights(const std::string &game_name);
|
|
|
|
std::vector<Light> sortLights(
|
|
const std::vector<Light> &lights,
|
|
const std::vector<std::string> &light_names);
|
|
|
|
template<typename T, typename... Rest>
|
|
void sortLights(std::vector<Light> *lights, T t, Rest... rest) {
|
|
const std::vector<std::string> light_names { t, rest... };
|
|
|
|
if (lights) {
|
|
*lights = GameAPI::Lights::sortLights(*lights, light_names);
|
|
}
|
|
}
|
|
|
|
struct LightAndCategory {
|
|
const std::string category_name;
|
|
const std::string light_name;
|
|
|
|
LightAndCategory(std::string category_name, std::string light_name) :
|
|
category_name(std::move(category_name)), light_name(std::move(light_name)) {}
|
|
};
|
|
|
|
void sortLightsWithCategory(std::vector<Light> *lights, const std::initializer_list<LightAndCategory> list);
|
|
|
|
void writeLight(rawinput::RawInputManager *manager, rawinput::Device *device, int index, float value);
|
|
void writeLight(rawinput::RawInputManager *manager, Light &light, float value);
|
|
void writeLight(std::unique_ptr<rawinput::RawInputManager> &manager, Light &light, float value);
|
|
|
|
float readLight(rawinput::Device *device, int index);
|
|
float readLight(rawinput::RawInputManager *manager, Light &light);
|
|
float readLight(std::unique_ptr<rawinput::RawInputManager> &manager, Light &light);
|
|
}
|
|
|
|
namespace Options {
|
|
std::vector<Option> getOptions(const std::string &game_name);
|
|
|
|
void sortOptions(std::vector<Option> &, const std::vector<OptionDefinition> &);
|
|
}
|
|
}
|