2dkg/2dgk_7/2dgk_7/KInput.cpp
2021-12-06 19:50:38 +01:00

203 lines
6.9 KiB
C++

#include "KInput.h"
#include "Constants.h"
#include <SDL.h>
namespace KapitanGame {
KInput::KInput() {
Initialized = false;
}
void KInput::Init() {
if (Initialized) return;
if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) != 1)
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
const int nJoysticks = SDL_NumJoysticks();
GamepadsCount = 0;
// Count how many controllers there are
for (int i = 0; i < nJoysticks; i++)
if (SDL_IsGameController(i))
GamepadsCount++;
// If we have some controllers attached
if (GamepadsCount > 0)
{
for (int i = 0; i < GamepadsCount; i++)
{
// Open the controller and add it to our list
SDL_GameController* pad = SDL_GameControllerOpen(i);
if (SDL_GameControllerGetAttached(pad) == 1)
ConnectedControllers.push_back(pad);
else
printf("SDL_GetError() = %s\n", SDL_GetError());
}
SDL_GameControllerEventState(SDL_ENABLE);
}
// Vectors are empty to begin with, this sets their size
ControllerInputs.resize(GamepadsCount);
LastControllerInputs.resize(GamepadsCount);
// Set the status of the controllers to "nothing is happening"
for (int i = 0; i < GamepadsCount; i++) {
for (int a = 0; a < SDL_CONTROLLER_AXIS_MAX; a++) {
ControllerInputs[i].Axis[a] = 0;
LastControllerInputs[i].Axis[a] = 0;
}
for (int b = 0; b < SDL_CONTROLLER_BUTTON_MAX; b++) {
ControllerInputs[i].Buttons[b] = false;
LastControllerInputs[i].Buttons[b] = false;
}
}
Initialized = true;
}
void KInput::Free() {
for (const auto& pad : ConnectedControllers) {
SDL_GameControllerClose(pad);
}
ConnectedControllers.clear();
}
void KInput::HandleInputPreEvents() {
for (int i = 0; i < GamepadsCount; i++) {
for (int a = 0; a < SDL_CONTROLLER_AXIS_MAX; a++) {
LastControllerInputs[i].Axis[a] = ControllerInputs[i].Axis[a];
}
for (int b = 0; b < SDL_CONTROLLER_BUTTON_MAX; b++) {
LastControllerInputs[i].Buttons[b] = ControllerInputs[i].Buttons[b];
}
}
LastKeyboardInputs = KeyboardInputs;
}
void KInput::HandleInputPostEvents() {
int size = 0;
const Uint8* currentKeyStates = SDL_GetKeyboardState(&size);
KeyboardInputs = std::vector<Uint8>(currentKeyStates, currentKeyStates + size);
}
void KInput::HandleEvent(const SDL_Event& event) {
switch (event.type) {
// This happens when a device is added
// A future improvement is to cope with new controllers being plugged in
// when the game is running
case SDL_CONTROLLERDEVICEADDED:
printf("DEVICEADDED cdevice.which = %d\n", event.cdevice.which);
break;
// If a controller button is pressed
case SDL_CONTROLLERBUTTONDOWN:
// Cycle through the controllers
for (int i = 0; i < GamepadsCount; i++) {
// Looking for the button that was pressed
if (event.cbutton.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ConnectedControllers[i]))) {
// So the relevant state can be updated
ControllerInputs[i].Buttons[event.cbutton.button] = true;
}
}
break;
// Do the same for releasing a button
case SDL_CONTROLLERBUTTONUP:
for (int i = 0; i < GamepadsCount; i++) {
if (event.cbutton.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ConnectedControllers[i]))) {
ControllerInputs[i].Buttons[event.cbutton.button] = false;
}
}
break;
// And something similar for axis motion
case SDL_CONTROLLERAXISMOTION:
for (int i = 0; i < GamepadsCount; i++) {
if (event.cbutton.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ConnectedControllers[i]))) {
ControllerInputs[i].Axis[event.caxis.axis] = event.caxis.value;
}
}
break;
}
}
void KInput::BindAction(std::string name, InputState expectedInputState, KPlayerController* controller,
KPlayerCommand command) {
Actions.emplace_back(name, expectedInputState, controller, command);
}
bool KInput::CheckAction(const std::string& name, const InputState expectedInputState, Controllers controller) {
switch(expectedInputState) {
case InputState::Pressed:
const auto keyBind = KeyBinds.find(name);
if(keyBind!=KeyBinds.end()) {
if(IsKeyboardButtonPressed(keyBind->second)) {
return true;
}
}
const auto buttonBind = ButtonBinds[controller].find(name);
if(buttonBind!=ButtonBinds[controller].end()) {
if(IsControllerButtonPressed(controller, buttonBind)) {
return true;
}
}
return false;
case InputState::Released: break;
case InputState::Hold: break;
default: return false;
}
}
void KInput::ProcessActions() {
for(auto action : Actions) {
if(CheckAction(action.Name, action.ExpectedInputState, action.Controller)) {
//(action.ControllerObject->*action.Command)();
std::invoke(action.Command, action.ControllerObject);
}
}
}
bool KInput::IsControllerButtonPressed(const Controllers controllerId, const SDL_GameControllerButton button) {
if (controllerId < Controllers::Controller1 || controllerId > static_cast<Controllers>(GamepadsCount - 1)) return false;
return ControllerInputs[static_cast<int>(controllerId)].Buttons[button] && !LastControllerInputs[static_cast<int>(controllerId)].Buttons[button];
}
bool KInput::IsControllerButtonReleased(const Controllers controllerId, const SDL_GameControllerButton button) {
if (controllerId < Controllers::Controller1 || controllerId > static_cast<Controllers>(GamepadsCount - 1)) return false;
return !ControllerInputs[static_cast<int>(controllerId)].Buttons[button] && LastControllerInputs[static_cast<int>(controllerId)].Buttons[button];
}
bool KInput::IsControllerButtonHeld(const Controllers controllerId, const SDL_GameControllerButton button) {
if (controllerId < Controllers::Controller1 || controllerId > static_cast<Controllers>(GamepadsCount - 1)) return false;
return ControllerInputs[static_cast<int>(controllerId)].Buttons[button] && LastControllerInputs[static_cast<int>(controllerId)].Buttons[button];
}
float KInput::GetControllerAxis(const Controllers controllerId, const SDL_GameControllerAxis axis) {
if (controllerId <Controllers::Controller1 || controllerId > static_cast<Controllers>(GamepadsCount - 1)) return 0.0;
const int value = ControllerInputs[static_cast<int>(controllerId)].Axis[axis];
if (std::abs(value) < Constants::JOYSTICK_DEAD_ZONE) return 0.0;
return static_cast<float>(value) / 32768.0f;
}
bool KInput::IsKeyboardButtonPressed(const Uint8 scanCode) {
if (scanCode > KeyboardInputs.size() || scanCode > LastKeyboardInputs.size())
return false;
return KeyboardInputs[scanCode] && KeyboardInputs[scanCode] != LastKeyboardInputs[scanCode];
}
bool KInput::IsKeyboardButtonReleased(const Uint8 scanCode) {
if (scanCode > KeyboardInputs.size() || scanCode > LastKeyboardInputs.size())
return false;
return !KeyboardInputs[scanCode] && KeyboardInputs[scanCode] != LastKeyboardInputs[scanCode];
}
bool KInput::IsKeyboardButtonHeld(const Uint8 scanCode) {
if (scanCode > KeyboardInputs.size())
return false;
return KeyboardInputs[scanCode];
}
}