commit
2007fb7edc
200 files changed
+27710
No files matched your search
+198
@@ -0,0 +1,198 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include <vector>
|
||||
|
||||
struct Game;
|
||||
struct SDL_Gamepad;
|
||||
struct SDL_Joystick;
|
||||
|
||||
constexpr int KEY_COUNT = 512;
|
||||
constexpr int TYPED_LENGTH = 64;
|
||||
|
||||
enum Control
|
||||
{
|
||||
CONTROL_LEFT,
|
||||
CONTROL_RIGHT,
|
||||
CONTROL_UP,
|
||||
CONTROL_DOWN,
|
||||
CONTROL_JUMP,
|
||||
CONTROL_ATTACK,
|
||||
CONTROL_CHARGE,
|
||||
CONTROL_LEVEL_DOWN,
|
||||
CONTROL_LEVEL_UP,
|
||||
CONTROL_READY,
|
||||
CONTROL_NEXT_WEAPON,
|
||||
CONTROL_PREVIOUS_WEAPON,
|
||||
CONTROL_MENU,
|
||||
CONTROL_CHAT,
|
||||
CONTROL_COUNT
|
||||
};
|
||||
|
||||
// What each control is called in the Controls settings, and its key in settings.txt.
|
||||
constexpr const char* CONTROL_NAMES[CONTROL_COUNT] = {
|
||||
"Move Left", "Move Right", "Up", "Down", "Jump", "Attack", "Charge", "Level Down", "Level Up", "Ready",
|
||||
"Next Weapon", "Previous Weapon", "Menu", "Chat"};
|
||||
constexpr const char* CONTROL_KEYS[CONTROL_COUNT] = {
|
||||
"left", "right", "up", "down", "jump", "attack", "charge", "level_down", "level_up", "ready",
|
||||
"next_weapon", "previous_weapon", "menu", "chat"};
|
||||
|
||||
// One tick of a fighter's intent, from the keyboard, a gamepad or a bot. Buttons holds a bit per Control held this
|
||||
// tick, cursor is the world point it aims at, slot is a weapon slot to switch to (-1 for none), and edit a change to
|
||||
// its loadout or settings made from the menu this tick (see edit_encode, -1 for none).
|
||||
struct Controls
|
||||
{
|
||||
Vec2 cursor;
|
||||
Uint16 buttons = 0;
|
||||
int edit = -1;
|
||||
int slot = -1;
|
||||
};
|
||||
|
||||
constexpr int EDIT_QUEUE = 16;
|
||||
|
||||
enum MouseButton
|
||||
{
|
||||
MOUSE_LEFT,
|
||||
MOUSE_RIGHT,
|
||||
MOUSE_MIDDLE,
|
||||
MOUSE_COUNT
|
||||
};
|
||||
|
||||
// A control's two bindings: one on the keyboard side (a key's scancode, or past the keys a mouse button or wheel
|
||||
// direction) and one on the gamepad (a button, or past the buttons a stick or trigger direction). -1 is unbound.
|
||||
struct Binding
|
||||
{
|
||||
int key = -1;
|
||||
int pad = -1;
|
||||
};
|
||||
|
||||
constexpr int PAD_MAX = 4;
|
||||
constexpr int DEVICE_NONE = -1;
|
||||
constexpr int DEVICE_KEYBOARD = 0;
|
||||
constexpr int DEVICE_COUNT = PAD_MAX + 1;
|
||||
constexpr int PAD_AXES = 6;
|
||||
|
||||
// Menu navigation directions, as bits.
|
||||
enum Nav
|
||||
{
|
||||
NAV_UP = 1,
|
||||
NAV_DOWN = 2,
|
||||
NAV_LEFT = 4,
|
||||
NAV_RIGHT = 8
|
||||
};
|
||||
|
||||
// One step of the test gamepad script: at time seconds, pad's button (or axis) index goes to value.
|
||||
struct PadEvent
|
||||
{
|
||||
float time = 0;
|
||||
float value = 0;
|
||||
int index = 0;
|
||||
int pad = 0;
|
||||
bool isAxis = false;
|
||||
};
|
||||
|
||||
// One way of playing: the keyboard and mouse, or a gamepad. Previous is what its controls were last tick (for
|
||||
// presses), stick the last way its right stick leaned, pick a Choice pick and ready a Ready click waiting for the next
|
||||
// tick, presses the gamepad buttons pressed since the last poll (for menus) and taps those pressed since the last
|
||||
// tick (held for it, however quick). Nav is the menu directions pressed since the last poll (D-pad, left stick or
|
||||
// arrow keys, repeating while held), held the D-pad and left stick directions held, and repeat when they next repeat.
|
||||
// Down and axes are the gamepad's buttons held and sticks and triggers (-1 to 1) as of the last poll, which bindings
|
||||
// read so a replayed tick sees the gamepad as it was.
|
||||
struct Device
|
||||
{
|
||||
SDL_Gamepad* pad = nullptr;
|
||||
Vec2 stick = {1, 0};
|
||||
Uint64 repeat = 0;
|
||||
float axes[PAD_AXES] = {};
|
||||
Uint32 down = 0;
|
||||
Uint32 presses = 0;
|
||||
Uint32 taps = 0;
|
||||
int held = 0;
|
||||
int nav = 0;
|
||||
// Edits waiting to go out, one per tick, oldest first.
|
||||
int edits[EDIT_QUEUE] = {};
|
||||
int editCount = 0;
|
||||
bool previous[CONTROL_COUNT] = {};
|
||||
bool isAiming = false;
|
||||
bool isClaimed = false;
|
||||
bool isReady = false;
|
||||
};
|
||||
|
||||
// Per-frame keyboard, mouse and gamepad state. Edges persist until a tick consumes them with tick_end. Menus read it
|
||||
// directly, and gameplay only sees it turned into Controls through the bindings, per device: the keyboard and mouse
|
||||
// (which also take any gamepad no one has claimed), or a claimed gamepad. Mouse is in canvas pixels. Widgets drawn
|
||||
// every frame use the per-frame parts instead: whether the left button was clicked since the last poll, and while a
|
||||
// text field has the keyboard, the text typed, backspaces and whether Enter or Escape ended it, and scroll, the wheel
|
||||
// turned since the last poll (wheel is the same for ticks, kept until one ends), whether the mouse moved, and whether
|
||||
// Enter was pressed outside typing (confirming in menus). Play request is the menu's Play button, waiting for the next
|
||||
// tick to start the game. Clicks, keys and buttons come from
|
||||
// press events too, so one let go quicker than a frame or tick still counts. Typing hides every key from the game. F
|
||||
// toggles fullscreen whenever nothing is being typed. A gamepad's right stick aims while it's in use (for the
|
||||
// keyboard's device, until the mouse moves). Capture listens for the next input on one side of a control's binding
|
||||
// (Escape cancels), which then doesn't count as pressed. RPG_TEST_PADS names a script of virtual gamepad presses for
|
||||
// testing ("seconds pad button|axis index value" a line).
|
||||
class Input
|
||||
{
|
||||
public:
|
||||
Binding bindings[CONTROL_COUNT];
|
||||
Device devices[DEVICE_COUNT];
|
||||
Vec2 mouse;
|
||||
char typed[TYPED_LENGTH] = {};
|
||||
float scroll = 0;
|
||||
float wheel = 0;
|
||||
int captureControl = -1;
|
||||
int erases = 0;
|
||||
int slotPressed = -1;
|
||||
bool isBindingChanged = false;
|
||||
bool isCaptureGamepad = false;
|
||||
bool isClicked = false;
|
||||
bool isConfirmed = false;
|
||||
bool isMouseMoved = false;
|
||||
bool isPlayRequested = false;
|
||||
bool isRightClicked = false;
|
||||
bool isQuit = false;
|
||||
bool isSubmitted = false;
|
||||
// Whether the text being typed was given up on (Escape) rather than entered.
|
||||
bool isCancelled = false;
|
||||
|
||||
Input();
|
||||
void poll(Game& game);
|
||||
void tick_end();
|
||||
void bindings_reset();
|
||||
Controls controls_get(int device, Vec2 camera, Vec2 origin, int slot, bool isMenuOpen);
|
||||
void edit_send(int device, int edit);
|
||||
Vec2 aim_get(int device, Vec2 camera, Vec2 origin);
|
||||
bool is_down(int scancode);
|
||||
bool is_pressed(int scancode);
|
||||
bool is_control_pressed(Control control);
|
||||
bool is_key_control_pressed(Control control);
|
||||
bool is_pad_pressed(int device, int button);
|
||||
Uint32 pad_presses_get(int device);
|
||||
bool is_pad_tapped(int button);
|
||||
int nav_get(int device);
|
||||
bool is_mouse_down(MouseButton button);
|
||||
bool is_mouse_pressed(MouseButton button);
|
||||
bool is_mouse_released(MouseButton button);
|
||||
void binding_name_get(int binding, bool isGamepad, char* text, int size);
|
||||
|
||||
bool is_control_down(int device, Control control);
|
||||
|
||||
private:
|
||||
std::vector<PadEvent> script;
|
||||
std::vector<SDL_Joystick*> virtualPads;
|
||||
bool buttons[MOUSE_COUNT] = {};
|
||||
bool buttonsPrevious[MOUSE_COUNT] = {};
|
||||
bool keys[KEY_COUNT] = {};
|
||||
bool keysPrevious[KEY_COUNT] = {};
|
||||
bool keysTapped[KEY_COUNT] = {};
|
||||
bool presses[MOUSE_COUNT] = {};
|
||||
bool pressesUnticked[MOUSE_COUNT] = {};
|
||||
bool isSwallowed = false;
|
||||
bool wasTyping = false;
|
||||
|
||||
bool is_key_binding_down(int binding);
|
||||
bool is_pad_binding_down(Device& device, int binding);
|
||||
void capture_take(int binding);
|
||||
void script_load();
|
||||
void script_play(Game& game);
|
||||
};
|
||||
Reference in new issue
Block a user