Add action mapping

This commit is contained in:
John Alanbrook 2023-04-25 21:59:12 +00:00
parent dc1fda6611
commit 02707a9ada
5 changed files with 115 additions and 22 deletions

View file

@ -53,6 +53,11 @@ JSValue int2js(int i)
return JS_NewInt64(js, i); return JS_NewInt64(js, i);
} }
JSValue str2js(const char *c)
{
return JS_NewString(js, c);
}
double js2number(JSValue v) double js2number(JSValue v)
{ {
double g; double g;
@ -979,6 +984,10 @@ JSValue duk_register(JSContext *js, JSValueConst this, int argc, JSValueConst *a
case 7: case 7:
register_pawn(c); register_pawn(c);
break; break;
case 8:
register_gamepad(c);
break;
} }
return JS_NULL; return JS_NULL;

View file

@ -16,5 +16,6 @@ struct color js2color(JSValue v);
double js2number(JSValue v); double js2number(JSValue v);
JSValue num2js(double g); JSValue num2js(double g);
JSValue int2js(int i); JSValue int2js(int i);
JSValue str2js(const char *c);
#endif #endif

View file

@ -5,6 +5,7 @@
#include "stb_ds.h" #include "stb_ds.h"
#include "log.h" #include "log.h"
#include "ffi.h" #include "ffi.h"
#include "time.h"
int32_t mouseWheelX = 0; int32_t mouseWheelX = 0;
int32_t mouseWheelY = 0; int32_t mouseWheelY = 0;
@ -24,12 +25,18 @@ static struct joystick *joysticks = NULL;
static int mquit = 0; static int mquit = 0;
static struct callee pawn_callee; static struct callee pawn_callee;
static struct callee gamepad_callee;
void register_pawn(struct callee c) void register_pawn(struct callee c)
{ {
pawn_callee = c; pawn_callee = c;
} }
void register_gamepad(struct callee c)
{
gamepad_callee = c;
}
void add_downkey(int key) { void add_downkey(int key) {
for (int i = 0; i < arrlen(downkeys); i++) for (int i = 0; i < arrlen(downkeys); i++)
if (downkeys[i] == key) return; if (downkeys[i] == key) return;
@ -372,17 +379,48 @@ void input_poll(double wait)
GLFWgamepadstate state; GLFWgamepadstate state;
if (!glfwGetGamepadState(joysticks[i].id, &state)) continue; 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++) { for (int b = 0; b < 15; b++) {
if (state.buttons[b]) { argv[1] = str2js(gamepad2str(b));
if (!joysticks[i].state.buttons[b]) if (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]) { 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; joysticks[i].state = state;
} }
} }

View file

@ -26,6 +26,7 @@ const char *keyname_extd(int key, int scancode);
int action_down(int scancode); int action_down(int scancode);
void register_pawn(struct callee c); void register_pawn(struct callee c);
void register_gamepad(struct callee c);
int want_quit(); int want_quit();
void quit(); void quit();

View file

@ -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 */ /* May be a human player; may be an AI player */
var Player = { var Player = {
pawns: [], players: [],
input(fn, ...args) { 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) { control(pawn) {
this.pawns.pushunique(pawn); this.pawns.push_unique(pawn);
}, },
uncontrol(pawn) { uncontrol(pawn) {
this.pawns = this.pawns.filter(x => x !== 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 = { var Register = {
updates: [], updates: [],
update(dt) { update(dt) {
@ -443,16 +473,25 @@ var Register = {
this.nk_guis.forEach(x => x[0].call(x[1])); this.nk_guis.forEach(x => x[0].call(x[1]));
}, },
pawns: [], kbm_input(fn, ...args) {
pawn_input(fn, ...args) { Player.players[0].input(fn, ...args);
this.pawns.forEach(x => {
if (fn in x) {
x[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: [], debugs: [],
debug() { debug() {
@ -463,9 +502,10 @@ var Register = {
this.updates = this.updates.filter(x => x[1] !== obj); this.updates = this.updates.filter(x => x[1] !== obj);
this.guis = this.guis.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.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.debugs = this.debugs.filter(x => x[1] !== obj);
this.physupdates = this.physupdates.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); register(0, Register.update, Register);
@ -473,7 +513,10 @@ register(1, Register.physupdate, Register);
register(2, Register.gui, Register); register(2, Register.gui, Register);
register(3, Register.nk_gui, Register); register(3, Register.nk_gui, Register);
register(6, Register.debug, 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) { function register_update(fn, obj) {
Register.updates.push([fn, obj ? obj : null]); Register.updates.push([fn, obj ? obj : null]);
@ -505,12 +548,13 @@ function unregister_nk_gui(fn, obj) {
register_update(Yugine.exec, Yugine); register_update(Yugine.exec, Yugine);
function set_pawn(obj) { /* These functions are the "defaults", and give control to player0 */
Register.pawns.push(obj); function set_pawn(obj, player = Player.players[0]) {
player.control(obj);
} }
function unset_pawn(obj) { function unset_pawn(obj, player = Player.players[0]) {
Register.pawns = Register.pawns.filter(x => x !== obj); player.uncontrol(obj);
} }
var Signal = { var Signal = {