diff --git a/source/engine/ffi.c b/source/engine/ffi.c index 45f440b..c86ff84 100644 --- a/source/engine/ffi.c +++ b/source/engine/ffi.c @@ -53,6 +53,11 @@ JSValue int2js(int i) return JS_NewInt64(js, i); } +JSValue str2js(const char *c) +{ + return JS_NewString(js, c); +} + double js2number(JSValue v) { double g; @@ -979,6 +984,10 @@ JSValue duk_register(JSContext *js, JSValueConst this, int argc, JSValueConst *a case 7: register_pawn(c); break; + + case 8: + register_gamepad(c); + break; } return JS_NULL; diff --git a/source/engine/ffi.h b/source/engine/ffi.h index 4e2366c..df0f1ed 100644 --- a/source/engine/ffi.h +++ b/source/engine/ffi.h @@ -16,5 +16,6 @@ struct color js2color(JSValue v); double js2number(JSValue v); JSValue num2js(double g); JSValue int2js(int i); +JSValue str2js(const char *c); #endif diff --git a/source/engine/input.c b/source/engine/input.c index 7711e4a..8be7a0f 100644 --- a/source/engine/input.c +++ b/source/engine/input.c @@ -5,6 +5,7 @@ #include "stb_ds.h" #include "log.h" #include "ffi.h" +#include "time.h" int32_t mouseWheelX = 0; int32_t mouseWheelY = 0; @@ -24,12 +25,18 @@ static struct joystick *joysticks = NULL; static int mquit = 0; static struct callee pawn_callee; +static struct callee gamepad_callee; void register_pawn(struct callee c) { pawn_callee = c; } +void register_gamepad(struct callee c) +{ + gamepad_callee = c; +} + void add_downkey(int key) { for (int i = 0; i < arrlen(downkeys); i++) if (downkeys[i] == key) return; @@ -372,17 +379,48 @@ void input_poll(double wait) GLFWgamepadstate state; if (!glfwGetGamepadState(joysticks[i].id, &state)) continue; + JSValue argv[3]; + argv[0] = int2js(joysticks[i].id); + char inputstr[50]; for (int b = 0; b < 15; b++) { + argv[1] = str2js(gamepad2str(b)); + if (state.buttons[b]) { - - if (!joysticks[i].state.buttons[b]) - YughWarn("Pressed button %s.", gamepad2str(b)); + argv[2] = int2js(0); + script_callee(gamepad_callee,3,argv); + + if (!joysticks[i].state.buttons[b]) { + argv[2] = int2js(1); + script_callee(gamepad_callee,3,argv); + } } else if (!state.buttons[b] && joysticks[i].state.buttons[b]) { - YughWarn("Released button %s.", gamepad2str(b)); + argv[2] = int2js(2); + script_callee(gamepad_callee,3,argv); } } + argv[1] = str2js("axis_ljoy"); + cpVect v; + v.x = state.axes[0]; + v.y = -state.axes[1]; + argv[2] = vec2js(v); + script_callee(gamepad_callee,3,argv); + + argv[1] = str2js("axis_rjoy"); + v.x = state.axes[2]; + v.y = -state.axes[3]; + argv[2] = vec2js(v); + script_callee(gamepad_callee,3,argv); + + argv[1] = str2js("axis_ltrigger"); + argv[2] = num2js((state.axes[4]+1)/2); + script_callee(gamepad_callee,3,argv); + + argv[1] = str2js("axis_rtrigger"); + argv[2] = num2js((state.axes[5]+1)/2); + script_callee(gamepad_callee,3,argv); + joysticks[i].state = state; } } diff --git a/source/engine/input.h b/source/engine/input.h index 100a3a0..f4ac489 100644 --- a/source/engine/input.h +++ b/source/engine/input.h @@ -26,6 +26,7 @@ const char *keyname_extd(int key, int scancode); int action_down(int scancode); void register_pawn(struct callee c); +void register_gamepad(struct callee c); int want_quit(); void quit(); diff --git a/source/scripts/engine.js b/source/scripts/engine.js index 3118ede..39fbcdd 100644 --- a/source/scripts/engine.js +++ b/source/scripts/engine.js @@ -406,22 +406,52 @@ var physics = { }, }; +var Action = { + add_new(name) { + var action = Object.create(Action); + action.name = name; + action.inputs = []; + this.actions.push(action); + + return action; + }, + actions: [], +}; + /* May be a human player; may be an AI player */ var Player = { - pawns: [], + players: [], input(fn, ...args) { - this.pawns.forEach(x => if (fn in x) x[fn](...args)); + this.pawns.forEach(x => { if (fn in x) x[fn](...args); }); }, control(pawn) { - this.pawns.pushunique(pawn); + this.pawns.push_unique(pawn); }, uncontrol(pawn) { this.pawns = this.pawns.filter(x => x !== pawn); - } + }, }; +for (var i = 0; i < 4; i++) { + var player1 = Object.create(Player); + player1.pawns = []; + player1.gamepads = []; + Player.players.push(player1); +} + +function state2str(state) { + switch (state) { + case 0: + return "down"; + case 1: + return "pressed"; + case 2: + return "released"; + } +} + var Register = { updates: [], update(dt) { @@ -443,16 +473,25 @@ var Register = { this.nk_guis.forEach(x => x[0].call(x[1])); }, - pawns: [], - pawn_input(fn, ...args) { - this.pawns.forEach(x => { - if (fn in x) { - x[fn](...args); - } - }); + kbm_input(fn, ...args) { + Player.players[0].input(fn, ...args); }, - controller_input( + gamepad_playermap: [], + gamepad_input(pad, btn, state, ...args) { + var player = this.gamepad_playermap[pad]; + if (!player) return; + + var statestr = state2str(state); + + var rawfn = `gamepad_${btn}_${statestr}`; + player.input(rawfn, ...args); + + Action.actions.forEach(x => { + if (x.inputs.includes(btn)) + player.input(`action_${x.name}_${statestr}`, ...args); + }); + }, debugs: [], debug() { @@ -463,9 +502,10 @@ var Register = { this.updates = this.updates.filter(x => x[1] !== obj); this.guis = this.guis.filter(x => x[1] !== obj); this.nk_guis = this.nk_guis.filter(x => x[1] !== obj); - this.pawns = this.pawns.filter(x => x[1] !== obj); this.debugs = this.debugs.filter(x => x[1] !== obj); this.physupdates = this.physupdates.filter(x => x[1] !== obj); + + Player.players.forEach(x => x.uncontrol(obj)); }, }; register(0, Register.update, Register); @@ -473,7 +513,10 @@ register(1, Register.physupdate, Register); register(2, Register.gui, Register); register(3, Register.nk_gui, Register); register(6, Register.debug, Register); -register(7, Register.pawn_input, Register); +register(7, Register.kbm_input, Register); +register(8, Register.gamepad_input, Register); + +Register.gamepad_playermap[0] = Player.players[0]; function register_update(fn, obj) { Register.updates.push([fn, obj ? obj : null]); @@ -505,12 +548,13 @@ function unregister_nk_gui(fn, obj) { register_update(Yugine.exec, Yugine); -function set_pawn(obj) { - Register.pawns.push(obj); +/* These functions are the "defaults", and give control to player0 */ +function set_pawn(obj, player = Player.players[0]) { + player.control(obj); } -function unset_pawn(obj) { - Register.pawns = Register.pawns.filter(x => x !== obj); +function unset_pawn(obj, player = Player.players[0]) { + player.uncontrol(obj); } var Signal = {