217 lines
5.6 KiB
C++
217 lines
5.6 KiB
C++
// Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
|
|
// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
|
|
|
|
#pragma once
|
|
|
|
#include "DeleteEmitter.h"
|
|
#include <SDL_events.h>
|
|
#include <SDL_keycode.h>
|
|
#include <sigc++/sigc++.h>
|
|
#include <cstdint>
|
|
#include <iostream>
|
|
#include <string_view>
|
|
|
|
namespace InputBindings {
|
|
enum class Response {
|
|
Ignored = 0,
|
|
Pressed,
|
|
Released
|
|
};
|
|
|
|
struct KeyBinding {
|
|
enum class Type : uint8_t {
|
|
Disabled,
|
|
KeyboardKey,
|
|
JoystickButton,
|
|
JoystickHat,
|
|
MouseButton
|
|
};
|
|
|
|
Type type = Type::Disabled;
|
|
union {
|
|
SDL_Keycode keycode = 0;
|
|
struct {
|
|
// 65536 possible IDs should be more than plenty, even with lots of hot-plug noise.
|
|
uint16_t id;
|
|
// if type = JoystickHat, this is the hat direction; otherwise it's the button index
|
|
uint8_t button;
|
|
uint8_t hat;
|
|
} joystick;
|
|
struct {
|
|
uint8_t button;
|
|
} mouse;
|
|
};
|
|
|
|
KeyBinding() = default;
|
|
|
|
KeyBinding(SDL_Keycode k) :
|
|
type(Type::KeyboardKey), keycode(k) {}
|
|
|
|
static KeyBinding JoystickButton(uint8_t joystickID, uint8_t button)
|
|
{
|
|
KeyBinding t;
|
|
t.type = Type::JoystickButton;
|
|
t.joystick = { joystickID, button, 0 };
|
|
return t;
|
|
}
|
|
|
|
static KeyBinding JoystickHat(uint8_t joystickID, uint8_t hat, uint8_t direction)
|
|
{
|
|
KeyBinding t;
|
|
t.type = Type::JoystickHat;
|
|
t.joystick = { joystickID, direction, hat };
|
|
return t;
|
|
}
|
|
|
|
static KeyBinding MouseButton(uint8_t mouseButton)
|
|
{
|
|
KeyBinding t;
|
|
t.type = Type::MouseButton;
|
|
t.mouse.button = mouseButton;
|
|
return t;
|
|
}
|
|
|
|
static KeyBinding FromEvent(SDL_Event &event);
|
|
|
|
bool Enabled() const { return type != Type::Disabled; }
|
|
Response Matches(const SDL_Event &ev) const;
|
|
|
|
bool operator==(const KeyBinding &rhs) const;
|
|
bool operator<(const KeyBinding &rhs) const;
|
|
|
|
// serialization
|
|
friend std::string_view &operator>>(std::string_view &, KeyBinding &);
|
|
friend std::ostream &operator<<(std::ostream &, const KeyBinding &);
|
|
};
|
|
|
|
struct JoyAxis {
|
|
uint8_t joystickId;
|
|
uint8_t axis;
|
|
int8_t direction; // if 0, the axis is disabled
|
|
|
|
bool Enabled() const { return direction != 0; }
|
|
|
|
bool operator==(const JoyAxis &rhs) const
|
|
{
|
|
if (!direction && !rhs.direction)
|
|
return true;
|
|
|
|
return joystickId == rhs.joystickId && axis == rhs.axis && direction == rhs.direction;
|
|
}
|
|
|
|
// serialization
|
|
friend std::string_view &operator>>(std::string_view &, JoyAxis &);
|
|
friend std::ostream &operator<<(std::ostream &, const JoyAxis &);
|
|
};
|
|
|
|
struct KeyChord {
|
|
KeyBinding activator;
|
|
KeyBinding modifier1;
|
|
KeyBinding modifier2;
|
|
|
|
KeyChord() = default;
|
|
KeyChord(KeyBinding a, KeyBinding m1 = {}, KeyBinding m2 = {}) :
|
|
activator(a),
|
|
modifier1(m1),
|
|
modifier2(m2)
|
|
{}
|
|
|
|
bool IsActive() const { return Enabled() && m_active; }
|
|
bool Enabled() const { return activator.Enabled(); }
|
|
|
|
bool operator==(const KeyChord &rhs) const
|
|
{
|
|
return activator == rhs.activator && modifier1 == rhs.modifier1 && modifier2 == rhs.modifier2;
|
|
}
|
|
bool operator!=(const KeyChord &rhs) const { return !(*this == rhs); }
|
|
|
|
// Groups chords by number of modifiers in descending order
|
|
bool operator<(const KeyChord &rhs) const
|
|
{
|
|
return (modifier2.Enabled() && !rhs.modifier2.Enabled()) || (modifier1.Enabled() && !rhs.modifier2.Enabled());
|
|
}
|
|
|
|
bool m_active = false;
|
|
uint8_t m_queuedEvents = 0;
|
|
|
|
// serialization
|
|
friend std::string_view &operator>>(std::string_view &, KeyChord &);
|
|
friend std::ostream &operator<<(std::ostream &, const KeyChord &);
|
|
};
|
|
|
|
struct Action : public DeleteEmitter {
|
|
KeyChord binding;
|
|
KeyChord binding2;
|
|
|
|
Action() = default;
|
|
Action(KeyChord b1, KeyChord b2 = {}) :
|
|
binding(b1),
|
|
binding2(b2)
|
|
{}
|
|
|
|
// NOTE: sigc::signals cannot be copied, this function is for convenience to copy bindings only
|
|
Action &operator=(const Action &rhs);
|
|
|
|
bool IsActive() { return m_active; }
|
|
bool Enabled() { return binding.Enabled() || binding2.Enabled(); }
|
|
|
|
bool m_active = false;
|
|
|
|
sigc::signal<void> onPressed;
|
|
sigc::signal<void> onReleased;
|
|
|
|
// serialization
|
|
friend std::string_view &operator>>(std::string_view &, Action &);
|
|
friend std::ostream &operator<<(std::ostream &, const Action &);
|
|
};
|
|
|
|
struct Axis : public DeleteEmitter {
|
|
JoyAxis axis;
|
|
KeyChord positive;
|
|
KeyChord negative;
|
|
|
|
Axis() = default;
|
|
Axis(JoyAxis a, KeyChord p = {}, KeyChord n = {}) :
|
|
axis(a),
|
|
positive(p),
|
|
negative(n)
|
|
{}
|
|
|
|
Axis(KeyChord p, KeyChord n = {}) :
|
|
axis{},
|
|
positive(p),
|
|
negative(n)
|
|
{}
|
|
|
|
// NOTE: sigc::signals cannot be copied, this function is for convenience to copy bindings only
|
|
Axis &operator=(const Axis &rhs);
|
|
|
|
bool IsActive() { return m_value != 0.0 || positive.IsActive() || negative.IsActive(); }
|
|
float GetValue() { return m_value; }
|
|
bool Enabled() { return axis.Enabled() || positive.Enabled() || negative.Enabled(); }
|
|
|
|
float m_value;
|
|
|
|
sigc::signal<void, float> onAxisValue;
|
|
|
|
// serialization
|
|
friend std::string_view &operator>>(std::string_view &, Axis &);
|
|
friend std::ostream &operator<<(std::ostream &, const Axis &);
|
|
};
|
|
|
|
std::string_view &operator>>(std::string_view &, KeyBinding &);
|
|
std::ostream &operator<<(std::ostream &, const KeyBinding &);
|
|
|
|
std::string_view &operator>>(std::string_view &, JoyAxis &);
|
|
std::ostream &operator<<(std::ostream &, const JoyAxis &);
|
|
|
|
std::string_view &operator>>(std::string_view &, KeyChord &);
|
|
std::ostream &operator<<(std::ostream &, const KeyChord &);
|
|
|
|
std::string_view &operator>>(std::string_view &, Action &);
|
|
std::ostream &operator<<(std::ostream &, const Action &);
|
|
|
|
std::string_view &operator>>(std::string_view &, Axis &);
|
|
std::ostream &operator<<(std::ostream &, const Axis &);
|
|
}; // namespace InputBindings
|