prosperon/scripts/input.js

436 lines
9.4 KiB
JavaScript
Raw Normal View History

2024-04-03 00:44:08 -05:00
input.keycodes = {
2024-09-26 11:36:09 -05:00
32: "space",
45: "minus",
256: "escape",
257: "enter",
2024-04-10 16:21:46 -05:00
258: "tab",
259: "backspace",
260: "insert",
261: "delete",
2024-09-26 11:36:09 -05:00
262: "right",
2024-04-10 16:21:46 -05:00
263: "left",
2024-09-26 11:36:09 -05:00
264: "down",
2024-04-10 16:21:46 -05:00
265: "up",
2024-09-26 11:36:09 -05:00
266: "pgup",
267: "pgdown",
268: "home",
269: "end",
2024-03-11 22:23:02 -05:00
};
2024-04-03 00:44:08 -05:00
input.codekeys = {};
2024-09-26 11:36:09 -05:00
for (var code in input.keycodes) input.codekeys[input.keycodes[code]] = code;
2024-03-18 14:27:52 -05:00
2024-03-11 22:23:02 -05:00
var mod = {
shift: 0,
ctrl: 0,
alt: 0,
2024-09-26 11:36:09 -05:00
super: 0,
2024-03-11 22:23:02 -05:00
};
/*
released
rep
pressed
down
*/
2024-09-26 11:36:09 -05:00
function keycode(name) {
return charCodeAt(name);
}
function keyname_extd(key) {
if (!parseInt(key)) return key;
2024-04-14 14:53:41 -05:00
2024-03-11 22:23:02 -05:00
if (key > 289 && key < 302) {
2024-09-26 11:36:09 -05:00
var num = key - 289;
2024-03-11 22:23:02 -05:00
return `f${num}`;
}
2024-09-26 11:36:09 -05:00
2024-03-11 22:23:02 -05:00
if (key >= 320 && key <= 329) {
2024-09-26 11:36:09 -05:00
var num = key - 320;
2024-03-11 22:23:02 -05:00
return `kp${num}`;
}
2024-09-26 11:36:09 -05:00
2024-04-03 00:44:08 -05:00
if (input.keycodes[key]) return input.keycodes[key];
2024-03-11 22:23:02 -05:00
if (key >= 32 && key <= 126) return String.fromCharCode(key).lc();
2024-09-26 11:36:09 -05:00
2024-03-11 22:23:02 -05:00
return undefined;
}
2024-07-11 16:37:24 -05:00
var downkeys = {};
2024-03-11 22:23:02 -05:00
2024-09-26 11:36:09 -05:00
function modstr() {
2024-03-11 22:23:02 -05:00
var s = "";
if (mod.ctrl) s += "C-";
if (mod.alt) s += "M-";
if (mod.super) s += "S-";
return s;
}
2024-09-26 11:36:09 -05:00
prosperon.keydown = function (key, repeat) {
2024-07-11 16:37:24 -05:00
downkeys[key] = true;
2024-09-26 11:36:09 -05:00
if (key == 341 || key == 345) mod.ctrl = 1;
else if (key == 342 || key == 346) mod.alt = 1;
else if (key == 343 || key == 347) mod.super = 1;
else if (key == 340 || key == 344) mod.shift = 1;
2024-03-11 22:23:02 -05:00
else {
var emacs = modstr() + keyname_extd(key);
2024-09-26 11:36:09 -05:00
if (repeat) player[0].raw_input(emacs, "rep");
else player[0].raw_input(emacs, "pressed");
2024-03-11 22:23:02 -05:00
}
2024-09-26 11:36:09 -05:00
};
2024-03-11 22:23:02 -05:00
2024-09-26 11:36:09 -05:00
prosperon.keyup = function (key) {
2024-07-11 16:37:24 -05:00
delete downkeys[key];
2024-09-26 11:36:09 -05:00
if (key == 341 || key == 345) mod.ctrl = 0;
else if (key == 342 || key == 346) mod.alt = 0;
else if (key == 343 || key == 347) mod.super = 0;
else if (key == 340 || key == 344) mod.shift = 0;
2024-03-11 22:23:02 -05:00
else {
var emacs = modstr() + keyname_extd(key);
player[0].raw_input(emacs, "released");
}
2024-09-26 11:36:09 -05:00
};
2024-03-11 22:23:02 -05:00
2024-09-26 11:36:09 -05:00
prosperon.droppedfile = function (path) {
2024-03-11 22:23:02 -05:00
player[0].raw_input("drop", "pressed", path);
2024-09-26 11:36:09 -05:00
};
2024-03-11 22:23:02 -05:00
2024-09-26 11:36:09 -05:00
var mousepos = [0, 0];
2024-03-11 22:23:02 -05:00
2024-09-26 11:36:09 -05:00
prosperon.textinput = function (c) {
2024-04-03 17:17:32 -05:00
player[0].raw_input("char", "pressed", c);
};
2024-09-26 11:36:09 -05:00
prosperon.mousemove = function (pos, dx) {
2024-03-11 22:23:02 -05:00
mousepos = pos;
2024-05-17 12:39:04 -05:00
mousepos.y = window.size.y - mousepos.y;
2024-04-10 16:21:46 -05:00
player[0].mouse_input("move", pos, dx);
2024-03-11 22:23:02 -05:00
};
2024-09-26 11:36:09 -05:00
prosperon.mousescroll = function (dx) {
2024-03-11 22:23:02 -05:00
player[0].mouse_input(modstr() + "scroll", dx);
};
2024-09-26 11:36:09 -05:00
prosperon.mousedown = function (b) {
2024-04-03 00:44:08 -05:00
player[0].raw_input(modstr() + input.mouse.button[b], "pressed");
2024-07-11 16:37:24 -05:00
downkeys[input.mouse.button[b]] = true;
2024-03-11 22:23:02 -05:00
};
2024-09-26 11:36:09 -05:00
prosperon.mouseup = function (b) {
2024-04-10 16:21:46 -05:00
player[0].raw_input(input.mouse.button[b], "released");
2024-07-11 16:37:24 -05:00
delete downkeys[input.mouse.button[b]];
2024-03-11 22:23:02 -05:00
};
2024-04-03 17:17:32 -05:00
input.mouse = {};
2024-09-26 11:36:09 -05:00
input.mouse.screenpos = function () {
return mousepos.slice();
};
input.mouse.worldpos = function () {
2024-10-06 17:18:18 -05:00
return prosperon.camera.screen2world(mousepos);
2024-09-26 11:36:09 -05:00
};
input.mouse.disabled = function () {
input.mouse_mode(1);
2024-04-03 17:17:32 -05:00
};
2024-09-26 11:36:09 -05:00
input.mouse.normal = function () {
input.mouse_mode(0);
};
input.mouse.mode = function (m) {
if (input.mouse.custom[m]) input.cursor_img(input.mouse.custom[m]);
else input.mouse_cursor(m);
};
input.mouse.set_custom_cursor = function (img, mode = input.mouse.cursor.default) {
if (!img) delete input.mouse.custom[mode];
2024-04-03 17:17:32 -05:00
else {
input.cursor_img(img);
input.mouse.custom[mode] = img;
}
};
2024-09-26 11:36:09 -05:00
input.mouse.button = {
2024-10-06 17:18:18 -05:00
/* left, right, middle mouse */
0: "lm",
2024-04-03 17:17:32 -05:00
1: "rm",
2024-09-26 11:36:09 -05:00
2: "mm",
2024-04-03 17:17:32 -05:00
};
input.mouse.custom = [];
input.mouse.cursor = {
default: 0,
arrow: 1,
ibeam: 2,
cross: 3,
hand: 4,
ew: 5,
ns: 6,
nwse: 7,
nesw: 8,
resize: 9,
2024-09-26 11:36:09 -05:00
no: 10,
2023-09-11 17:09:21 -05:00
};
2024-04-03 00:44:08 -05:00
input.mouse.doc = {};
input.mouse.doc.pos = "The screen position of the mouse.";
input.mouse.doc.worldpos = "The position in the game world of the mouse.";
input.mouse.disabled.doc = "Set the mouse to hidden. This locks it to the game and hides it, but still provides movement and click events.";
input.mouse.normal.doc = "Set the mouse to show again after hiding.";
2024-04-03 00:44:08 -05:00
input.keyboard = {};
2024-09-26 11:36:09 -05:00
input.keyboard.down = function (code) {
if (typeof code === "number") return downkeys[code];
if (typeof code === "string") return downkeys[code.uc().charCodeAt()] || downkeys[code.lc().charCodeAt()];
2024-04-03 00:44:08 -05:00
return undefined;
2024-09-26 11:36:09 -05:00
};
2023-09-11 17:09:21 -05:00
2024-09-26 11:36:09 -05:00
input.state2str = function (state) {
if (typeof state === "string") return state;
switch (state) {
case 0:
return "down";
case 1:
return "pressed";
case 2:
return "released";
}
2024-09-26 11:36:09 -05:00
};
2024-09-26 11:36:09 -05:00
input.print_pawn_kbm = function (pawn) {
if (!("inputs" in pawn)) return;
var str = "";
for (var key in pawn.inputs) {
2023-09-22 09:44:58 -05:00
if (!pawn.inputs[key].doc) continue;
str += `${key} | ${pawn.inputs[key].doc}\n`;
}
return str;
};
var joysticks = {};
joysticks["wasd"] = {
uy: "w",
dy: "s",
ux: "d",
2024-09-26 11:36:09 -05:00
dx: "a",
};
2024-09-26 11:36:09 -05:00
input.procdown = function () {
for (var k in downkeys) player[0].raw_input(keyname_extd(k), "down");
for (var i in joysticks) {
var joy = joysticks[i];
var x = joy.ux - joy.dx;
var y = joy.uy - joy.dy;
player[0].joy_input(i, joysticks[i]);
}
2024-09-26 11:36:09 -05:00
};
2024-03-18 14:27:52 -05:00
2024-09-26 11:36:09 -05:00
input.print_md_kbm = function (pawn) {
if (!("inputs" in pawn)) return;
var str = "";
str += "|control|description|\n|---|---|\n";
for (var key in pawn.inputs) {
str += `|${key}|${pawn.inputs[key].doc}|`;
str += "\n";
}
return str;
};
2024-09-26 11:36:09 -05:00
input.has_bind = function (pawn, bind) {
return typeof pawn.inputs?.[bind] === "function";
};
2024-02-25 17:31:48 -06:00
input.action = {
add_new(name) {
2024-02-25 17:31:48 -06:00
var action = Object.create(input.action);
action.name = name;
action.inputs = [];
this.actions.push(action);
return action;
},
actions: [],
};
2024-09-26 11:36:09 -05:00
input.tabcomplete = function (val, list) {
if (!val) return val;
list.dofilter(function (x) {
return x.startsWith(val);
});
2024-09-26 11:36:09 -05:00
if (list.length === 1) {
return list[0];
}
var ret = undefined;
var i = val.length;
while (!ret && !Object.empty(list)) {
var char = list[0][i];
if (
!list.every(function (x) {
return x[i] === char;
})
)
ret = list[0].slice(0, i);
else {
i++;
list.dofilter(function (x) {
return x.length - 1 > i;
});
}
2024-09-26 11:36:09 -05:00
}
2024-09-26 11:36:09 -05:00
return ret ? ret : val;
};
/* May be a human player; may be an AI player */
2024-09-06 18:51:09 -05:00
/*
'block' on a pawn's input blocks any input from reaching below for the
*/
var Player = {
players: [],
input(fn, ...args) {
this.pawns.forEach(x => x[fn]?.(...args));
},
mouse_input(type, ...args) {
for (var pawn of this.pawns.reversed()) {
2024-09-26 11:36:09 -05:00
if (typeof pawn.inputs?.mouse?.[type] === "function") {
pawn.inputs.mouse[type].call(pawn, ...args);
pawn.inputs.post?.call(pawn);
if (!pawn.inputs.fallthru) return;
}
}
},
char_input(c) {
for (var pawn of this.pawns.reversed()) {
2024-09-26 11:36:09 -05:00
if (typeof pawn.inputs?.char === "function") {
pawn.inputs.char.call(pawn, c);
2024-09-26 11:36:09 -05:00
pawn.inputs.post?.call(pawn);
if (!pawn.inputs.fallthru) return;
}
2024-09-26 11:36:09 -05:00
}
},
joy_input(name, joystick) {
for (var pawn of this.pawns.reversed()) {
if (!pawn.inputs) return;
if (!pawn.inputs.joystick) return;
if (!pawn.inputs.joystick[name]) return;
var x = 0;
if (input.keyboard.down(joystick.ux)) x++;
if (input.keyboard.down(joystick.dx)) x--;
2024-09-26 11:36:09 -05:00
var y = 0;
if (input.keyboard.down(joystick.uy)) y++;
if (input.keyboard.down(joystick.dy)) y--;
2024-09-26 11:36:09 -05:00
pawn.inputs.joystick[name](x, y);
}
},
raw_input(cmd, state, ...args) {
for (var pawn of this.pawns.reversed()) {
2024-05-30 12:05:51 -05:00
if (!pawn.inputs) {
console.error(`pawn no longer has inputs object.`);
2024-09-26 11:36:09 -05:00
continue;
2024-05-30 12:05:51 -05:00
}
2024-09-06 18:51:09 -05:00
var block = pawn.inputs.block;
2024-09-26 11:36:09 -05:00
2024-05-30 12:05:51 -05:00
if (!pawn.inputs[cmd]) {
if (pawn.inputs.block) return;
2024-09-26 11:36:09 -05:00
continue;
}
2024-03-18 14:27:52 -05:00
var fn = null;
switch (state) {
2024-09-26 11:36:09 -05:00
case "pressed":
fn = pawn.inputs[cmd];
break;
case "rep":
fn = pawn.inputs[cmd].rep ? pawn.inputs[cmd] : null;
break;
case "released":
fn = pawn.inputs[cmd].released;
break;
case "down":
if (typeof pawn.inputs[cmd].down === "function") fn = pawn.inputs[cmd].down;
else if (pawn.inputs[cmd].down) fn = pawn.inputs[cmd];
}
2024-09-26 11:36:09 -05:00
if (typeof fn === "function") fn.call(pawn, ...args);
2023-10-11 17:22:41 -05:00
2024-09-06 18:51:09 -05:00
if (!pawn.inputs)
if (block) return;
2024-09-26 11:36:09 -05:00
else continue;
2024-09-06 18:51:09 -05:00
2024-09-26 11:36:09 -05:00
if (state === "released") pawn.inputs.release_post?.call(pawn);
2023-11-20 07:49:14 -06:00
2023-10-11 17:22:41 -05:00
if (!pawn.inputs.fallthru) return;
2024-09-26 11:36:09 -05:00
if (pawn.inputs.block) return;
}
},
obj_controlled(obj) {
for (var p in Player.players) {
2024-09-26 11:36:09 -05:00
if (p.pawns.contains(obj)) return true;
}
return false;
},
print_pawns() {
2024-09-26 11:36:09 -05:00
for (var pawn of this.pawns.reversed()) say(pawn.toString());
},
create() {
var n = Object.create(this);
n.pawns = [];
n.gamepads = [];
this.players.push(n);
2024-09-26 11:36:09 -05:00
this[this.players.length - 1] = n;
return n;
},
pawns: [],
control(pawn) {
2024-05-30 12:05:51 -05:00
if (!pawn.inputs) {
console.warn(`attempted to control a pawn without any input object.`);
return;
}
this.pawns.push_unique(pawn);
},
uncontrol(pawn) {
this.pawns = this.pawns.filter(x => x !== pawn);
},
};
2024-09-26 11:36:09 -05:00
input.do_uncontrol = function (pawn) {
Player.players.forEach(function (p) {
2024-04-03 08:37:29 -05:00
p.pawns = p.pawns.filter(x => x !== pawn);
});
2024-09-26 11:36:09 -05:00
};
2024-04-03 08:37:29 -05:00
for (var i = 0; i < 4; i++) {
Player.create();
}
Player.control.doc = "Control a provided object, if the object has an 'inputs' object.";
Player.uncontrol.doc = "Uncontrol a previously controlled object.";
Player.print_pawns.doc = "Print out a list of the current pawn control stack.";
Player.doc = {};
Player.doc.players = "A list of current players.";
var player = Player;
return {
2024-09-26 11:36:09 -05:00
player,
};