CavEX/source/platform/input.c

536 lines
14 KiB
C
Raw Permalink Normal View History

2022-12-17 06:30:52 -05:00
/*
Copyright (c) 2022 ByteBit/xtreme8000
This file is part of CavEX.
CavEX is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CavEX is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CavEX. If not, see <http://www.gnu.org/licenses/>.
*/
2022-11-22 15:39:32 -05:00
#include <assert.h>
#include "../cglm/cglm.h"
2023-07-05 17:01:59 -04:00
#include "gfx.h"
2022-11-22 15:39:32 -05:00
#include "input.h"
2023-03-27 12:58:52 -04:00
#ifdef PLATFORM_PC
#include <GLFW/glfw3.h>
extern GLFWwindow* window;
2023-07-05 17:01:59 -04:00
static bool input_pointer_enabled;
static double input_old_pointer_x, input_old_pointer_y;
static bool input_key_held[1024];
2023-03-27 12:58:52 -04:00
2023-07-09 08:27:47 -04:00
void input_init() {
2023-07-05 17:01:59 -04:00
for(int k = 0; k < 1024; k++)
2023-03-27 12:58:52 -04:00
input_key_held[k] = false;
2023-07-05 17:01:59 -04:00
input_pointer_enabled = false;
input_old_pointer_x = 0;
input_old_pointer_y = 0;
2023-03-27 12:58:52 -04:00
}
2023-07-09 08:27:47 -04:00
void input_poll() { }
2023-07-05 17:01:59 -04:00
void input_native_key_status(int key, bool* pressed, bool* released,
bool* held) {
if(key >= 1024) {
*pressed = false;
*released = false;
*held = false;
2023-03-27 12:58:52 -04:00
}
2023-07-05 17:01:59 -04:00
int state = key < 1000 ? glfwGetKey(window, key) :
glfwGetMouseButton(window, key - 1000);
*pressed = (state == GLFW_PRESS) && !input_key_held[key];
*released = (state == GLFW_RELEASE) && input_key_held[key];
*held = !(*released) && input_key_held[key];
if(state == GLFW_PRESS)
input_key_held[key] = true;
if(state == GLFW_RELEASE)
input_key_held[key] = false;
2023-03-27 12:58:52 -04:00
}
2023-07-09 08:27:47 -04:00
bool input_native_key_symbol(int key, int* symbol, int* symbol_help,
enum input_category* category, int* priority) {
*category = INPUT_CAT_NONE;
*symbol = 7;
*symbol_help = 7;
*priority = 1;
return true;
2023-03-27 12:58:52 -04:00
}
2023-07-05 17:01:59 -04:00
bool input_native_key_any(int* key) {
return false;
2023-03-27 12:58:52 -04:00
}
2023-07-09 08:27:47 -04:00
void input_pointer_enable(bool enable) {
2023-07-05 17:01:59 -04:00
glfwSetInputMode(window, GLFW_CURSOR,
enable ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED);
if(!input_pointer_enabled && enable)
glfwSetCursorPos(window, gfx_width() / 2, gfx_height() / 2);
if(input_pointer_enabled && !enable)
glfwGetCursorPos(window, &input_old_pointer_x, &input_old_pointer_y);
input_pointer_enabled = enable;
2023-03-27 12:58:52 -04:00
}
2023-07-09 08:27:47 -04:00
bool input_pointer(float* x, float* y, float* angle) {
2023-07-05 17:01:59 -04:00
double x2, y2;
glfwGetCursorPos(window, &x2, &y2);
*x = x2;
*y = y2;
2023-07-09 08:27:47 -04:00
*angle = 0.0F;
return input_pointer_enabled && x2 >= 0 && y2 >= 0 && x2 < gfx_width()
&& y2 < gfx_height();
2023-03-27 12:58:52 -04:00
}
2023-07-05 17:01:59 -04:00
void input_native_joystick(float dt, float* dx, float* dy) {
if(!input_pointer_enabled) {
double x2, y2;
glfwGetCursorPos(window, &x2, &y2);
*dx = (x2 - input_old_pointer_x) * 0.001F;
*dy = -(y2 - input_old_pointer_y) * 0.001F;
input_old_pointer_x = x2;
input_old_pointer_y = y2;
} else {
*dx = 0.0F;
*dy = 0.0F;
}
2023-03-27 12:58:52 -04:00
}
#endif
#ifdef PLATFORM_WII
#include <wiiuse/wpad.h>
2023-10-12 10:55:06 -04:00
static struct {
float dx, dy;
float magnitude;
bool available;
} joystick_input[3];
static bool js_emulated_btns_prev[3][4];
static bool js_emulated_btns_held[3][4];
2023-07-09 08:27:47 -04:00
void input_init() {
2023-07-05 17:01:59 -04:00
WPAD_Init();
2023-10-12 10:55:06 -04:00
WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR);
WPAD_SetVRes(WPAD_CHAN_0, gfx_width(), gfx_height());
for(int k = 0; k < 4; k++) {
for(int j = 0; j < 3; j++)
js_emulated_btns_prev[j][k] = js_emulated_btns_held[j][k] = false;
}
2022-11-22 15:39:32 -05:00
}
2023-07-09 08:27:47 -04:00
void input_poll() {
2023-07-05 17:01:59 -04:00
WPAD_ScanPads();
2023-10-12 10:55:06 -04:00
expansion_t e;
WPAD_Expansion(WPAD_CHAN_0, &e);
if(e.type == WPAD_EXP_NUNCHUK) {
joystick_input[0].dx = sin(glm_rad(e.nunchuk.js.ang));
joystick_input[0].dy = cos(glm_rad(e.nunchuk.js.ang));
joystick_input[0].magnitude = e.nunchuk.js.mag;
joystick_input[0].available = true;
} else {
joystick_input[0].available = false;
}
if(e.type == WPAD_EXP_CLASSIC) {
joystick_input[1].dx = sin(glm_rad(e.classic.ljs.ang));
joystick_input[1].dy = cos(glm_rad(e.classic.ljs.ang));
joystick_input[1].magnitude = e.classic.ljs.mag;
joystick_input[1].available = true;
joystick_input[2].dx = sin(glm_rad(e.classic.rjs.ang));
joystick_input[2].dy = cos(glm_rad(e.classic.rjs.ang));
joystick_input[2].magnitude = e.classic.rjs.mag;
joystick_input[2].available = true;
} else {
joystick_input[1].available = joystick_input[2].available = false;
}
for(int j = 0; j < 3; j++) {
for(int k = 0; k < 4; k++) {
js_emulated_btns_prev[j][k] = js_emulated_btns_held[j][k];
js_emulated_btns_held[j][k] = false;
}
if(joystick_input[j].available) {
float x = joystick_input[j].dx * joystick_input[j].magnitude;
float y = joystick_input[j].dy * joystick_input[j].magnitude;
if(x > 0.2F) {
js_emulated_btns_held[j][3] = true;
} else if(x < -0.2F) {
js_emulated_btns_held[j][2] = true;
}
if(y > 0.2F) {
js_emulated_btns_held[j][0] = true;
} else if(y < -0.2F) {
js_emulated_btns_held[j][1] = true;
}
}
}
2023-07-05 17:01:59 -04:00
}
2022-12-19 17:15:20 -05:00
2023-10-12 10:55:06 -04:00
static uint32_t input_wpad_translate(int key) {
2023-07-05 17:01:59 -04:00
switch(key) {
case 0: return WPAD_BUTTON_UP;
case 1: return WPAD_BUTTON_DOWN;
case 2: return WPAD_BUTTON_LEFT;
case 3: return WPAD_BUTTON_RIGHT;
case 4: return WPAD_BUTTON_A;
case 5: return WPAD_BUTTON_B;
case 6: return WPAD_BUTTON_1;
case 7: return WPAD_BUTTON_2;
case 8: return WPAD_BUTTON_PLUS;
case 9: return WPAD_BUTTON_MINUS;
case 10: return WPAD_BUTTON_HOME;
default: break;
}
2022-12-19 17:15:20 -05:00
2023-07-05 17:01:59 -04:00
expansion_t e;
WPAD_Expansion(WPAD_CHAN_0, &e);
2022-12-19 17:15:20 -05:00
2023-07-05 17:01:59 -04:00
if(e.type == WPAD_EXP_NUNCHUK) {
switch(key) {
case 100: return WPAD_NUNCHUK_BUTTON_Z;
case 101: return WPAD_NUNCHUK_BUTTON_C;
default: break;
}
} else if(e.type == WPAD_EXP_CLASSIC) {
switch(key) {
case 200: return WPAD_CLASSIC_BUTTON_UP;
case 201: return WPAD_CLASSIC_BUTTON_DOWN;
case 202: return WPAD_CLASSIC_BUTTON_LEFT;
case 203: return WPAD_CLASSIC_BUTTON_RIGHT;
case 204: return WPAD_CLASSIC_BUTTON_A;
case 205: return WPAD_CLASSIC_BUTTON_B;
case 206: return WPAD_CLASSIC_BUTTON_X;
case 207: return WPAD_CLASSIC_BUTTON_Y;
case 208: return WPAD_CLASSIC_BUTTON_ZL;
case 209: return WPAD_CLASSIC_BUTTON_ZR;
case 210: return WPAD_CLASSIC_BUTTON_FULL_L;
case 211: return WPAD_CLASSIC_BUTTON_FULL_R;
case 212: return WPAD_CLASSIC_BUTTON_PLUS;
case 213: return WPAD_CLASSIC_BUTTON_MINUS;
case 214: return WPAD_CLASSIC_BUTTON_HOME;
default: break;
}
} else if(e.type == WPAD_EXP_GUITARHERO3) {
switch(key) {
case 300: return WPAD_GUITAR_HERO_3_BUTTON_YELLOW;
case 301: return WPAD_GUITAR_HERO_3_BUTTON_GREEN;
case 302: return WPAD_GUITAR_HERO_3_BUTTON_BLUE;
case 303: return WPAD_GUITAR_HERO_3_BUTTON_RED;
case 304: return WPAD_GUITAR_HERO_3_BUTTON_ORANGE;
case 305: return WPAD_GUITAR_HERO_3_BUTTON_PLUS;
case 306: return WPAD_GUITAR_HERO_3_BUTTON_MINUS;
case 307: return WPAD_GUITAR_HERO_3_BUTTON_STRUM_UP;
case 308: return WPAD_GUITAR_HERO_3_BUTTON_STRUM_DOWN;
default: break;
2022-12-19 17:15:20 -05:00
}
}
2023-07-05 17:01:59 -04:00
return 0;
}
void input_native_key_status(int key, bool* pressed, bool* released,
bool* held) {
2023-10-12 10:55:06 -04:00
if(key >= 900 && key < 924) {
int js = (key - 900) / 10;
int offset = (key - 900) % 10;
if(offset < 4) {
*held = js_emulated_btns_held[js][offset]
&& js_emulated_btns_prev[js][offset];
*pressed = js_emulated_btns_held[js][offset]
&& !js_emulated_btns_prev[js][offset];
*released = !js_emulated_btns_held[js][offset]
&& js_emulated_btns_prev[js][offset];
return;
}
}
2023-07-05 17:01:59 -04:00
*pressed = WPAD_ButtonsDown(WPAD_CHAN_0) & input_wpad_translate(key);
*released = WPAD_ButtonsUp(WPAD_CHAN_0) & input_wpad_translate(key);
*held = !(*pressed) && !(*released)
&& WPAD_ButtonsHeld(WPAD_CHAN_0) & input_wpad_translate(key);
}
2022-12-19 17:15:20 -05:00
2023-07-09 08:27:47 -04:00
bool input_native_key_symbol(int key, int* symbol, int* symbol_help,
enum input_category* category, int* priority) {
2023-10-12 10:55:06 -04:00
if(key >= 900 && key < 904) {
*symbol = *symbol_help = 17;
*category = INPUT_CAT_NUNCHUK;
*priority = 1;
return true;
}
if(key >= 910 && key < 914) {
*symbol = *symbol_help = 18;
*category = INPUT_CAT_CLASSIC_CONTROLLER;
*priority = 1;
return true;
}
if(key >= 920 && key < 924) {
*symbol = *symbol_help = 19;
*category = INPUT_CAT_CLASSIC_CONTROLLER;
*priority = 1;
return true;
}
2023-07-09 08:27:47 -04:00
if(key < 0 || key > 308)
return false;
int symbols[] = {
[0] = 25, [1] = 26, [2] = 27, [3] = 28, [4] = 0, [5] = 1,
[6] = 2, [7] = 3, [8] = 5, [9] = 6, [10] = 4, [100] = 8,
[101] = 9, [200] = 25, [201] = 26, [202] = 27, [203] = 28, [204] = 10,
[205] = 11, [206] = 12, [207] = 13, [208] = 14, [209] = 15, [210] = 22,
[211] = 23, [212] = 5, [213] = 6, [214] = 4, [300] = 7, [301] = 7,
[302] = 7, [303] = 7, [304] = 7, [305] = 5, [306] = 6, [307] = 7,
[308] = 7,
};
*category = INPUT_CAT_NONE;
if(key >= 0 && key <= 10)
*category = INPUT_CAT_WIIMOTE;
if(key >= 100 && key <= 101)
*category = INPUT_CAT_NUNCHUK;
if(key >= 200 && key <= 214)
*category = INPUT_CAT_CLASSIC_CONTROLLER;
*symbol = symbols[key];
*symbol_help = symbols[key];
if(*symbol_help >= 25 && *symbol_help <= 28)
*symbol_help = 24;
expansion_t e;
WPAD_Expansion(WPAD_CHAN_0, &e);
if((*category == INPUT_CAT_NUNCHUK && e.type == WPAD_EXP_NUNCHUK)
|| (*category == INPUT_CAT_CLASSIC_CONTROLLER
&& e.type == WPAD_EXP_CLASSIC)) {
*priority = 2;
} else {
*priority = 1;
}
return true;
2023-07-05 17:01:59 -04:00
}
2022-12-19 17:15:20 -05:00
2023-07-05 17:01:59 -04:00
bool input_native_key_any(int* key) {
return false;
}
2023-07-09 08:27:47 -04:00
void input_pointer_enable(bool enable) { }
2023-07-05 17:01:59 -04:00
2023-07-09 08:27:47 -04:00
bool input_pointer(float* x, float* y, float* angle) {
2023-07-05 17:01:59 -04:00
struct ir_t ir;
WPAD_IR(WPAD_CHAN_0, &ir);
*x = ir.x;
*y = ir.y;
2023-07-09 08:27:47 -04:00
*angle = ir.angle;
2023-07-05 17:01:59 -04:00
return ir.valid;
2022-11-22 15:39:32 -05:00
}
2023-07-05 17:01:59 -04:00
void input_native_joystick(float dt, float* dx, float* dy) {
2023-10-12 10:55:06 -04:00
if(joystick_input[0].available && joystick_input[0].magnitude > 0.1F) {
*dx = joystick_input[0].dx * joystick_input[0].magnitude * dt;
*dy = joystick_input[0].dy * joystick_input[0].magnitude * dt;
} else if(joystick_input[2].available
&& joystick_input[2].magnitude > 0.1F) {
*dx = joystick_input[2].dx * joystick_input[2].magnitude * dt;
*dy = joystick_input[2].dy * joystick_input[2].magnitude * dt;
2023-07-05 17:01:59 -04:00
} else {
*dx = 0.0F;
*dy = 0.0F;
2022-11-22 15:39:32 -05:00
}
}
2023-07-05 17:01:59 -04:00
#endif
#include "../game/game_state.h"
static const char* input_config_translate(enum input_button key) {
switch(key) {
case IB_ACTION1: return "input.item_action_left";
case IB_ACTION2: return "input.item_action_right";
case IB_FORWARD: return "input.player_forward";
case IB_BACKWARD: return "input.player_backward";
case IB_LEFT: return "input.player_left";
case IB_RIGHT: return "input.player_right";
case IB_JUMP: return "input.player_jump";
case IB_SNEAK: return "input.player_sneak";
case IB_INVENTORY: return "input.inventory";
case IB_HOME: return "input.open_menu";
case IB_SCROLL_LEFT: return "input.scroll_left";
case IB_SCROLL_RIGHT: return "input.scroll_right";
2023-07-09 08:27:47 -04:00
case IB_GUI_UP: return "input.gui_up";
case IB_GUI_DOWN: return "input.gui_down";
case IB_GUI_LEFT: return "input.gui_left";
case IB_GUI_RIGHT: return "input.gui_right";
case IB_GUI_CLICK: return "input.gui_click";
case IB_GUI_CLICK_ALT: return "input.gui_click_alt";
2023-09-24 09:48:47 -04:00
case IB_SCREENSHOT: return "input.screenshot";
2023-07-05 17:01:59 -04:00
default: return NULL;
2022-12-19 17:15:20 -05:00
}
}
2023-07-09 08:27:47 -04:00
bool input_symbol(enum input_button b, int* symbol, int* symbol_help,
enum input_category* category) {
const char* key = input_config_translate(b);
if(!key)
return false;
size_t length = 8;
int mapping[length];
if(!config_read_int_array(&gstate.config_user, input_config_translate(b),
mapping, &length))
return false;
int priority = 0;
bool has_any = false;
for(size_t k = 0; k < length; k++) {
int symbol_tmp, symbol_help_tmp, priority_tmp;
enum input_category category_tmp;
if(input_native_key_symbol(mapping[k], &symbol_tmp, &symbol_help_tmp,
&category_tmp, &priority_tmp)
&& priority_tmp > priority) {
priority = priority_tmp;
*symbol = symbol_tmp;
*symbol_help = symbol_help_tmp;
*category = category_tmp;
has_any = true;
}
}
return has_any;
}
2022-11-22 15:39:32 -05:00
bool input_pressed(enum input_button b) {
2023-07-05 17:01:59 -04:00
const char* key = input_config_translate(b);
if(!key)
return false;
size_t length = 8;
int mapping[length];
if(!config_read_int_array(&gstate.config_user, input_config_translate(b),
mapping, &length))
return false;
bool any_pressed = false;
bool any_held = false;
bool any_released = false;
for(size_t k = 0; k < length; k++) {
bool pressed, released, held;
input_native_key_status(mapping[k], &pressed, &released, &held);
if(pressed)
any_pressed = true;
if(released)
any_released = true;
if(held)
any_held = true;
}
return any_pressed && !any_held && !any_released;
2022-11-22 15:39:32 -05:00
}
bool input_released(enum input_button b) {
2023-07-05 17:01:59 -04:00
const char* key = input_config_translate(b);
if(!key)
return false;
size_t length = 8;
int mapping[length];
if(!config_read_int_array(&gstate.config_user, input_config_translate(b),
mapping, &length))
return false;
bool any_pressed = false;
bool any_held = false;
bool any_released = false;
for(size_t k = 0; k < length; k++) {
bool pressed, released, held;
input_native_key_status(mapping[k], &pressed, &released, &held);
if(pressed)
any_pressed = true;
if(released)
any_released = true;
if(held)
any_held = true;
}
return !any_pressed && !any_held && any_released;
2022-11-22 15:39:32 -05:00
}
bool input_held(enum input_button b) {
2023-07-05 17:01:59 -04:00
const char* key = input_config_translate(b);
if(!key)
return false;
size_t length = 8;
int mapping[length];
if(!config_read_int_array(&gstate.config_user, input_config_translate(b),
mapping, &length))
return false;
bool any_pressed = false;
bool any_held = false;
for(size_t k = 0; k < length; k++) {
bool pressed, released, held;
input_native_key_status(mapping[k], &pressed, &released, &held);
if(pressed)
any_pressed = true;
if(held)
any_held = true;
}
return any_pressed || any_held;
2022-11-22 15:39:32 -05:00
}
bool input_joystick(float dt, float* x, float* y) {
2023-07-05 17:01:59 -04:00
input_native_joystick(dt, x, y);
return true;
2022-11-22 15:39:32 -05:00
}