203 lines
6.9 KiB
C++
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];
|
|
}
|
|
}
|
|
|