Files
prosperon/controller.cm
2026-01-19 01:06:51 -06:00

344 lines
7.8 KiB
Plaintext

var input = use('input')
return {}
var downkeys = {};
function keyname(key)
{
var str = input.keyname(key);
return lower(str);
}
function modstr(mod = input.keymod()) {
var s = "";
if (mod.ctrl) s += "C-";
if (mod.alt) s += "M-";
if (mod.super) s += "S-";
return s;
}
prosperon.on('key_down', function key_down(e) {
downkeys[e.key] = true;
var emacs = modstr(e.mod) + keyname(e.key);
if (e.repeat) player[0].raw_input(emacs, "rep");
else player[0].raw_input(emacs, "pressed");
})
prosperon.on('quit', function() {
$stop()
})
prosperon.on('key_up', function key_up(e) {
delete downkeys[e.key];
var emacs = modstr(e.mod) + keyname(e.key);
player[0].raw_input(emacs, "released");
})
prosperon.on('drop_file', function (path) {
player[0].raw_input("drop", "pressed", path);
})
var mousepos = [0, 0];
prosperon.on('text_input', function (e) {
player[0].raw_input("char", "pressed", e.text);
})
prosperon.on('mouse_motion', function (e)
{
mousepos = e.pos;
player[0].mouse_input("move", e.pos, e.d_pos);
})
prosperon.on('mouse_wheel', function mousescroll(e) {
player[0].mouse_input(modstr() + "scroll", e.scroll);
})
prosperon.on('mouse_button_down', function(e) {
player[0].mouse_input(modstr() + e.button, "pressed");
input.mouse.buttons[e.button] = true
})
prosperon.on('mouse_button_up', function(e) {
player[0].mouse_input(modstr() + e.button, "released");
input.mouse.buttons[e.button] = false
})
input.mouse = {};
input.mouse.screenpos = function mouse_screenpos() {
return array(mousepos);
};
input.mouse.worldpos = function mouse_worldpos() {
return prosperon.camera.screen2world(mousepos);
};
input.mouse.viewpos = function mouse_viewpos()
{
var world = input.mouse.worldpos();
return array(world)
}
input.mouse.disabled = function mouse_disabled() {
input.mouse_mode(1);
};
input.mouse.normal = function mouse_normal() {
input.mouse_mode(0);
};
input.mouse.mode = function mouse_mode(m) {
if (input.mouse.custom[m]) input.cursor_img(input.mouse.custom[m]);
else input.mouse_cursor(m);
};
input.mouse.buttons = {
0:false,
1:false,
2:false
}
input.mouse.set_custom_cursor = function mouse_cursor(img, mode = input.mouse.cursor.default) {
if (!img) delete input.mouse.custom[mode];
else {
input.cursor_img(img);
input.mouse.custom[mode] = img;
}
};
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.";
input.keyboard = {};
input.keyboard.down = function (code) {
if (is_number(code)) return downkeys[code];
if (is_text(code)) return downkeys[codepoint(upper(code))] || downkeys[codepoint(lower(code))];
return null;
};
input.print_pawn_kbm = function (pawn) {
if (!("inputs" in pawn)) return;
var str = "";
for (var key in pawn.inputs) {
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",
dx: "a",
};
input.procdown = function procdown() {
for (var k in downkeys) player[0].raw_input(keyname(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]);
}
};
input.print_md_kbm = function print_md_kbm(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;
};
input.has_bind = function (pawn, bind) {
return is_function(pawn.inputs?.[bind]);
};
input.action = {
add_new(name) {
var action = meme(input.action);
action.name = name;
action.inputs = [];
this.actions.push(action);
return action;
},
actions: [],
};
input.tabcomplete = function tabcomplete(val, list) {
if (!val) return val;
list = filter(list, x => starts_with(x, val))
if (length(list) == 1) {
return list[0];
}
var ret = null;
var i = length(val);
while (!ret && length(list) != 0) {
var char = list[0][i];
if (
!every(list, x => x[i] == char)
)
ret = text(list[0], 0, i);
else {
i++;
list = filter(list, x => length(x) - 1 > i)
}
}
return ret ? ret : val;
};
/* May be a human player; may be an AI player */
/*
'block' on a pawn's input blocks any input from reaching below for the
*/
var Player = {
players: [],
input(fn, ...args) {
arrfor(this.pawns, x => x[fn]?.(...args));
},
mouse_input(type, ...args) {
arrfor(array(this.pawns), function(pawn) {
if (is_function(pawn.inputs.mouse[type])) {
call(pawn.inputs.mouse[type], pawn, ...args);
pawn.inputs.post?.call(pawn);
if (!pawn.inputs.fallthru) return;
}
}, true)
},
char_input(c) {
arrfor(array(this.pawns), function(pawn) {
if (is_function(pawn.inputs.char)) {
call(pawn.inputs.char, pawn, c);
pawn.inputs.post?.call(pawn);
if (!pawn.inputs.fallthru) return;
}
}, true)
},
joy_input(name, joystick) {
arrfor(array(this.pawns), function(pawn) {
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--;
var y = 0;
if (input.keyboard.down(joystick.uy)) y++;
if (input.keyboard.down(joystick.dy)) y--;
pawn.inputs.joystick[name](x, y);
}, true)
},
raw_input(cmd, state, ...args) {
arrfor(array(this.pawns), function(pawn) {
var inputs = pawn.inputs;
if (!inputs[cmd]) {
if (inputs.block) return;
continue;
}
var fn = null;
switch (state) {
case "pressed":
fn = inputs[cmd];
break;
case "rep":
fn = inputs[cmd].rep ? inputs[cmd] : null;
break;
case "released":
fn = inputs[cmd].released;
break;
case "down":
if (is_function(inputs[cmd].down)) fn = inputs[cmd].down;
else if (inputs[cmd].down) fn = inputs[cmd];
}
var consumed = false;
if (is_function(fn)) {
call(fn, pawn, ...args);
consumed = true;
}
if (state == "released") call(inputs.release_post, pawn);
if (inputs.block) return;
if (consumed) return;
}, true)
},
obj_controlled(obj) {
for (var p in Player.players) {
if (p.pawns[obj]) return true;
}
return false;
},
print_pawns() {
arrfor(array(this.pawns), x => log.console(x), true)
},
create() {
var n = meme(this);
n.pawns = {}
n.gamepads = [];
this.players.push(n);
this[length(this.players) - 1] = n;
return n;
},
control(pawn) {
if (!pawn)
return
if (!pawn.inputs)
throw Error("attempted to control a pawn without any input object.");
this.pawns[pawn] = true
},
uncontrol(pawn) {
delete this.pawns[pawn]
},
};
input.do_uncontrol = function input_do_uncontrol(pawn) {
if (!pawn.inputs) return;
arrfor(Player.players, function (p) {
delete p.pawns[pawn]
});
};
//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;
input.player = Player
return input