MushMachine/framework/input/src/mm/services/input_service.hpp

156 lines
3.6 KiB
C++
Raw Normal View History

#pragma once
#include <SDL.h>
#include <glm/vec2.hpp>
#include <mm/services/sdl_service.hpp>
#include <array>
namespace MM::Input {
using PlayerID = uint16_t;
} // MM::Input
namespace MM::Services {
class InputService : public Service {
public:
// TODO: rework
enum input_action_t {
SPELL_WEAPON,
SPELL_1,
SPELL_2,
SPELL_3,
SPELL_4,
SPELL_5,
SPELL_6,
USE,
INPUT_ACTION_MAX
};
enum class k_view_mode_t {
NO_VIEW, // disables any kplayer view processing
USE_ARROWS, // TODO: implement
MOUSE_DRAG,
MOUSE_RELATIVE, // TODO: implement
MOUSE_RELATIVE_TO_CENTER, // TODO: refactor
};
struct keyboard_mapping {
SDL_Keycode move_up;
SDL_Keycode move_down;
SDL_Keycode move_left;
SDL_Keycode move_right;
SDL_Keycode actions[INPUT_ACTION_MAX];
input_action_t get(SDL_Keycode key);
};
struct controller_mapping {
SDL_GameControllerButton actions[INPUT_ACTION_MAX];
input_action_t get(SDL_GameControllerButton key);
};
private:
struct player_input_action_state {
bool is_controller;
SDL_JoystickID controller_instance_id;
union {
struct {
int16_t left_x;
int16_t left_y;
int16_t right_x;
int16_t right_y;
} controller;
struct {
bool up;
bool down;
bool left;
bool right;
bool mouse_button_down; // for MOUSE_DRAG
int32_t last_x, last_y;
int32_t curr_x, curr_y;
k_view_mode_t view_mode;
} keyboard;
} u; // union
bool active[INPUT_ACTION_MAX] = {false};
float move_force = 0.f;
float move_dir = 0.f;
float view_force = 0.f;
float view_dir = 0.f;
};
public: // HACK: proper methods
keyboard_mapping _k_map;
controller_mapping _c_map;
private:
// TODO: max player
static const Input::PlayerID max_player_id = 4;
std::array<player_input_action_state, max_player_id> _player;
std::array<bool, max_player_id> _player_active;
public:
InputService(void);
~InputService(void);
private:
SDLService::EventHandlerHandle _event_handle = nullptr;
public:
bool enable(Engine& engine) override;
void disable(Engine& engine) override;
const char* name(void) override { return "InputService"; }
// you will likely want to make the scene depend on this
std::vector<UpdateStrategies::UpdateCreationInfo> registerUpdates(void) override;
public:
// returns true if event was relevant
bool handleSDL_Event(const SDL_Event& e, MM::Engine& engine);
Input::PlayerID addPlayer(bool keyboard, SDL_JoystickID controller_id);
bool setKPlayerViewMode(Input::PlayerID id, k_view_mode_t mode);
// returns UINT16_MAX on error
Input::PlayerID findPlayerState(bool controller, SDL_JoystickID controller_id);
// check if action is set
bool get(Input::PlayerID id, input_action_t action);
const char* getKeyString(Input::PlayerID id, input_action_t action);
float getMoveForce(Input::PlayerID id);
float getViewForce(Input::PlayerID id);
glm::vec2 getMoveVec(Input::PlayerID id);
glm::vec2 getViewVec(Input::PlayerID id);
// returns values [0, 2PI)
float getMoveDir(Input::PlayerID id);
// returns values [0, 2PI)
float getViewDir(Input::PlayerID id);
private:
SDL_Keycode loadKey(const std::string& name, const SDL_Keycode default_key);
SDL_GameControllerButton loadButton(const std::string& name, const SDL_GameControllerButton default_button);
void updateKPlayerDirs(player_input_action_state& p);
void updateCPlayerDirs(player_input_action_state& p);
};
} // namespace MM::Services