Add console object; add intuitive object view; console clear; add play hooks
This commit is contained in:
parent
f29981ca77
commit
b87cd41e70
|
@ -1,11 +1,17 @@
|
|||
# Yugine Scripting Guide
|
||||
|
||||
Script hooks exist to allow to modification of the game.
|
||||
|
||||
|config.js|called before any game play|
|
||||
|game.js|called to start the game|
|
||||
|editorconfig.js|called when the editor is loaded, used to personalize|
|
||||
|debug.js|called when play in editor is selected|
|
||||
|
||||
All objects in the Yugine can have an associated script. This script can perform setup, teardown, and handles responses for the object.
|
||||
|
||||
|function|description|
|
||||
|---|---|
|
||||
|setup|called before the object is loaded|
|
||||
|start|called when the object is loaded|
|
||||
|update(dt)|called once per game frame|
|
||||
|update(dt)|called once per game frame tick|
|
||||
|physupdate(dt)|called once per physics tick|
|
||||
|stop|called when the object is killed|
|
|
@ -80,6 +80,7 @@ Object.deepfreeze = function(obj)
|
|||
Object.dainty_assign = function(target, source)
|
||||
{
|
||||
Object.keys(source).forEach(function(k) {
|
||||
if (typeof source[k] === 'function') return;
|
||||
if (!(k in target)) return;
|
||||
if (Array.isArray(source[k]))
|
||||
target[k] = deep_copy(source[k]);
|
||||
|
@ -418,6 +419,14 @@ Object.defineProperty(String.prototype, 'tofirst', {
|
|||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'fromfirst', {
|
||||
value: function(val) {
|
||||
var idx = this.indexOf(val);
|
||||
if (idx === -1) return this;
|
||||
return this.slice(idx+1);
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(String.prototype, 'name', {
|
||||
value: function() {
|
||||
var idx = this.indexOf('/');
|
||||
|
|
|
@ -253,3 +253,15 @@ var Time = {
|
|||
|
||||
Player.players[0].control(DebugControls);
|
||||
Register.gui.register(Debug.draw, Debug);
|
||||
|
||||
var console = {};
|
||||
console.log = Log.say;
|
||||
console.info = Log.info;
|
||||
console.warn = Log.warn;
|
||||
console.error = Log.error;
|
||||
console.stack = Log.stack;
|
||||
console.clear = function()
|
||||
{
|
||||
cmd(146);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,10 @@ var editor = {
|
|||
},
|
||||
edit_mode: "basic",
|
||||
|
||||
get_this() {
|
||||
return this.edit_level;
|
||||
},
|
||||
|
||||
try_select() { /* nullify true if it should set selected to null if it doesn't find an object */
|
||||
var go = physics.pos_query(Mouse.worldpos);
|
||||
return this.do_select(go);
|
||||
|
@ -200,6 +204,7 @@ var editor = {
|
|||
start_play_ed() {
|
||||
this.stash = this.desktop.instance_obj();
|
||||
Primum.clear();
|
||||
load("config.js");
|
||||
Game.play();
|
||||
Game.editor_mode(false);
|
||||
Player.players[0].uncontrol(this);
|
||||
|
@ -218,8 +223,8 @@ var editor = {
|
|||
// Player.players[0].control(gui_controls);
|
||||
|
||||
this.desktop = Primum.spawn(ur.arena);
|
||||
Primum.rename_obj(this.desktop.toString(), "desktop");
|
||||
this.edit_level = this.desktop;
|
||||
this.desktop.toString = function() { return "desktop"; };
|
||||
editor.edit_level._ed.selectable = false;
|
||||
if (this.stash) {
|
||||
this.desktop.make_objs(this.stash.objects);
|
||||
|
@ -371,6 +376,18 @@ var editor = {
|
|||
|
||||
},
|
||||
|
||||
draw_objects_names(obj,root,depth){
|
||||
if (!obj) return;
|
||||
if (!obj.objects) return;
|
||||
depth ??= 0;
|
||||
root = root ? root + "." : root;
|
||||
Object.entries(obj.objects).forEach(function(x) {
|
||||
var p = root + x[0];
|
||||
GUI.text(p, world2screen(x[1].worldpos()), 1, editor.color_depths[depth]);
|
||||
editor.draw_objects_names(x[1], p, depth+1);
|
||||
});
|
||||
},
|
||||
|
||||
_sel_comp: undefined,
|
||||
get sel_comp() { return this._sel_comp; },
|
||||
set sel_comp(x) {
|
||||
|
@ -387,6 +404,8 @@ var editor = {
|
|||
|
||||
time: 0,
|
||||
|
||||
color_depths: [],
|
||||
|
||||
ed_gui() {
|
||||
/* Clean out killed objects */
|
||||
this.selectlist = this.selectlist.filter(function(x) { return x.alive; });
|
||||
|
@ -401,8 +420,10 @@ var editor = {
|
|||
}
|
||||
|
||||
GUI.text("0,0", world2screen([0,0]));
|
||||
|
||||
var thiso = editor.get_this();
|
||||
var clvl = thiso;
|
||||
|
||||
var clvl = this.selectlist.length === 1 ? this.selectlist[0] : this.edit_level;
|
||||
var lvlchain = [];
|
||||
while (clvl !== Primum) {
|
||||
lvlchain.push(clvl);
|
||||
|
@ -410,38 +431,35 @@ var editor = {
|
|||
}
|
||||
lvlchain.push(clvl);
|
||||
|
||||
var lvlcolorsample = 1;
|
||||
var colormap = ColorMap.Bathymetry;
|
||||
var lvlcolor = colormap.sample(lvlcolorsample);
|
||||
var ypos = 200;
|
||||
var colormap = ColorMap.Inferno;
|
||||
editor.color_depths = [];
|
||||
for (var i = 1; i > 0 ; i -= 0.1)
|
||||
editor.color_depths.push(colormap.sample(i));
|
||||
|
||||
var ypos = 200;
|
||||
var depth = 0;
|
||||
lvlchain.reverse();
|
||||
lvlchain.forEach(function(x,i) {
|
||||
lvlcolor = colormap.sample(lvlcolorsample);
|
||||
depth = i;
|
||||
var lvlstr = x.toString();
|
||||
if (x._ed.dirty)
|
||||
lvlstr += "*";
|
||||
if (i === lvlchain.length-1) lvlstr += "[this]";
|
||||
GUI.text(lvlstr, [0, ypos], 1, lvlcolor);
|
||||
GUI.text(lvlstr, [0, ypos], 1, editor.color_depths[depth]);
|
||||
|
||||
lvlcolorsample -= 0.1;
|
||||
|
||||
GUI.text("^^^^^^", [0,ypos+=5],1);
|
||||
ypos += 15;
|
||||
});
|
||||
|
||||
depth++;
|
||||
GUI.text("$$$$$$", [0,ypos],1,editor.color_depths[depth]);
|
||||
|
||||
/* Color selected objects with the next deeper color */
|
||||
lvlcolorsample -= 0.1;
|
||||
lvlcolor = colormap.sample(lvlcolorsample);
|
||||
|
||||
GUI.text("$$$$$$", [0,ypos],1,lvlcolor);
|
||||
|
||||
this.selectlist.forEach(function(x) {
|
||||
var sname = x.__proto__.toString();
|
||||
x._ed.check_dirty();
|
||||
if (x._ed.dirty) sname += "*";
|
||||
|
||||
GUI.text(sname, world2screen(x.worldpos()).add([0, 16]), 1, lvlcolor);
|
||||
GUI.text(sname, world2screen(x.worldpos()).add([0, 16]), 1, Color.editor.ur);
|
||||
GUI.text(x.worldpos().map(function(x) { return Math.round(x); }), world2screen(x.worldpos()), 1, Color.white);
|
||||
Debug.arrow(world2screen(x.worldpos()), world2screen(x.worldpos().add(x.up().scale(40))), Color.yellow, 1);
|
||||
|
||||
|
@ -449,22 +467,12 @@ var editor = {
|
|||
x.gizmo();
|
||||
});
|
||||
|
||||
if (this.selectlist.length === 0)
|
||||
for (var key in this.edit_level.objects) {
|
||||
var o = this.edit_level.objects[key];
|
||||
GUI.text(key, world2screen(o.worldpos()), 1, lvlcolor);
|
||||
}
|
||||
else
|
||||
this.selectlist.forEach(function(x) {
|
||||
Object.entries(x.objects).forEach(function(x) {
|
||||
GUI.text(x[0], world2screen(x[1].worldpos()), 1, lvlcolor);
|
||||
});
|
||||
});
|
||||
var mg = Game.obj_at(Mouse.worldpos);
|
||||
|
||||
this.edit_level.objects.forEach(function(x) {
|
||||
if ('ed_gizmo' in x)
|
||||
x.ed_gizmo();
|
||||
});
|
||||
if (mg) {
|
||||
var p = mg.path_from(thiso);
|
||||
GUI.text(p, world2screen(Mouse.worldpos),1,Color.teal);
|
||||
}
|
||||
|
||||
if (this.selectlist.length === 1) {
|
||||
var i = 1;
|
||||
|
@ -1047,6 +1055,13 @@ editor.inputs.mm = function() {
|
|||
};
|
||||
editor.inputs['C-mm'] = editor.inputs.mm;
|
||||
|
||||
editor.inputs['C-M-lm'] = function()
|
||||
{
|
||||
var go = Game.obj_at(Mouse.worldpos);
|
||||
if (!go) return;
|
||||
editor.edit_level = go.level;
|
||||
}
|
||||
|
||||
editor.inputs['C-M-mm'] = function() {
|
||||
editor.mousejoy = Mouse.pos;
|
||||
editor.joystart = editor.camera.pos;
|
||||
|
@ -1442,7 +1457,7 @@ var replpanel = Object.copy(inputpanel, {
|
|||
this.prevthis.unshift(this.value);
|
||||
this.prevmark = -1;
|
||||
var ecode = "";
|
||||
var repl_obj = (editor.selectlist.length === 1) ? editor.selectlist[0] : editor.edit_level;
|
||||
var repl_obj = editor.get_this();
|
||||
ecode += `var $ = repl_obj.objects;`;
|
||||
for (var key in repl_obj.objects)
|
||||
ecode += `var ${key} = editor.edit_level.objects['${key}'];`;
|
||||
|
@ -1461,6 +1476,15 @@ var replpanel = Object.copy(inputpanel, {
|
|||
});
|
||||
|
||||
replpanel.inputs = Object.create(inputpanel.inputs);
|
||||
replpanel.inputs.block = true;
|
||||
replpanel.inputs.lm = function()
|
||||
{
|
||||
var mg = Game.obj_at(Mouse.worldpos);
|
||||
if (!mg) return;
|
||||
var p = mg.path_from(editor.get_this());
|
||||
this.value = p;
|
||||
this.caret = this.value.length;
|
||||
}
|
||||
replpanel.inputs.tab = function() {
|
||||
this.resetscroll();
|
||||
if (!this.value) return;
|
||||
|
@ -1486,6 +1510,9 @@ replpanel.inputs.tab = function() {
|
|||
for (var k in obj)
|
||||
keys.push(k)
|
||||
|
||||
for (var k in editor.get_this())
|
||||
keys.push(k);
|
||||
|
||||
var comp = "";
|
||||
if (stub)
|
||||
comp = tab_complete(stub, keys);
|
||||
|
|
|
@ -43,6 +43,9 @@ var Color = {
|
|||
purple: [162,93,227],
|
||||
};
|
||||
|
||||
Color.editor = {};
|
||||
Color.editor.ur = Color.green;
|
||||
|
||||
Color.tohtml = function(v)
|
||||
{
|
||||
var html = v.map(function(n) { return Number.hex(n*255); });
|
||||
|
@ -600,6 +603,12 @@ var Game = {
|
|||
if (this.objects[obj.body] === obj)
|
||||
this.objects[obj.body] = undefined;
|
||||
},
|
||||
|
||||
obj_at(worldpos) {
|
||||
var idx = physics.pos_query(worldpos);
|
||||
if (idx === -1) return undefined;
|
||||
return Game.objects[idx];
|
||||
},
|
||||
|
||||
/* Returns an object given an id */
|
||||
object(id) {
|
||||
|
|
|
@ -12,6 +12,21 @@ function grab_from_points(pos, points, slop) {
|
|||
|
||||
var gameobject = {
|
||||
impl: {
|
||||
full_path() {
|
||||
return this.path_from(Primum);
|
||||
},
|
||||
|
||||
path_from(o) {
|
||||
var p = this.toString();
|
||||
var c = this.level;
|
||||
while (c && c !== o && c !== Primum) {
|
||||
p = c.toString() + "." + p;
|
||||
c = c.level;
|
||||
}
|
||||
if (c === Primum) p = "Primum." + p;
|
||||
return p;
|
||||
},
|
||||
|
||||
clear() {
|
||||
for (var k in this.objects) {
|
||||
Log.info(`Killing ${k}`);
|
||||
|
@ -160,15 +175,17 @@ var gameobject = {
|
|||
var str = obj.toString().replaceAll('.', '_');
|
||||
var n = 1;
|
||||
var t = str;
|
||||
while (Object.hasOwn(list, t)) {
|
||||
while (t in list) {
|
||||
t = str + n;
|
||||
n++;
|
||||
}
|
||||
return t;
|
||||
};
|
||||
|
||||
var name = unique_name(parent.objects, this.ur);
|
||||
var name = unique_name(parent, this.ur);
|
||||
|
||||
parent.objects[name] = this;
|
||||
parent[name] = this;
|
||||
this.toString = function() { return name; };
|
||||
},
|
||||
|
||||
|
@ -177,6 +194,7 @@ var gameobject = {
|
|||
delete this[obj.toString()];
|
||||
|
||||
delete this.objects[obj.toString()];
|
||||
delete this[obj.toString()];
|
||||
},
|
||||
|
||||
},
|
||||
|
@ -408,6 +426,7 @@ var gameobject = {
|
|||
if (typeof this.stop === 'function')
|
||||
this.stop();
|
||||
// });
|
||||
|
||||
},
|
||||
|
||||
up() { return [0,1].rotate(Math.deg2rad(this.angle));},
|
||||
|
@ -418,6 +437,7 @@ var gameobject = {
|
|||
make(level, data) {
|
||||
level ??= Primum;
|
||||
var obj = Object.create(this);
|
||||
obj.make = undefined;
|
||||
obj.level = level;
|
||||
// this.instances.push(obj);
|
||||
obj.body = make_gameobject();
|
||||
|
@ -454,11 +474,9 @@ var gameobject = {
|
|||
|
||||
Object.dainty_assign(obj, this);
|
||||
obj.sync();
|
||||
|
||||
gameobject.check_registers(obj);
|
||||
|
||||
if (Game.playing() && typeof obj.start === 'function') obj.start();
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
|
@ -479,7 +497,10 @@ var gameobject = {
|
|||
return;
|
||||
|
||||
this.objects[newname] = this.objects[name];
|
||||
this[newname] = this[name];
|
||||
this[newname].toString = function() { return newname; };
|
||||
delete this.objects[name];
|
||||
delete this[name];
|
||||
return this.objects[newname];
|
||||
},
|
||||
|
||||
|
@ -502,6 +523,7 @@ gameobject.impl.spawn.doc = `Spawn an entity of type 'ur' on this entity. Return
|
|||
|
||||
/* Default objects */
|
||||
var prototypes = {};
|
||||
prototypes.ur_ext = ".jso";
|
||||
prototypes.ur = {};
|
||||
prototypes.save_gameobjects = function() { slurpwrite(JSON.stringify(gameobjects,null,2), "proto.json"); };
|
||||
|
||||
|
@ -530,7 +552,7 @@ prototypes.from_file = function(file)
|
|||
|
||||
file = file.replaceAll('.','/');
|
||||
|
||||
var jsfile = prototypes.get_ur_file(urpath, ".js");
|
||||
var jsfile = prototypes.get_ur_file(urpath, prototypes.ur_ext);
|
||||
var jsonfile = prototypes.get_ur_file(urpath, ".json");
|
||||
|
||||
var script = undefined;
|
||||
|
@ -655,9 +677,8 @@ prototypes.get_ur_file = function(path, ext)
|
|||
|
||||
prototypes.generate_ur = function(path)
|
||||
{
|
||||
var ob = IO.glob("**.js");
|
||||
var ob = IO.glob("**" + prototypes.ur_ext);
|
||||
ob = ob.concat(IO.glob("**.json"));
|
||||
ob = ob.filter(function(path) { return path !== "game.js" && path !== "play.js" });
|
||||
ob = ob.map(function(path) { return path.set_ext(""); });
|
||||
ob.forEach(function(name) { prototypes.get_ur(name); });
|
||||
}
|
||||
|
|
|
@ -132,7 +132,11 @@ var Player = {
|
|||
if (!pawn.inputs.fallthru)
|
||||
return;
|
||||
}
|
||||
if (!pawn.inputs?.[cmd]) continue;
|
||||
|
||||
if (!pawn.inputs?.[cmd]) {
|
||||
if (pawn.inputs.block) return;
|
||||
continue;
|
||||
}
|
||||
|
||||
var fn = null;
|
||||
|
||||
|
@ -156,6 +160,7 @@ var Player = {
|
|||
}
|
||||
|
||||
if (!pawn.inputs.fallthru) return;
|
||||
if (pawn.inputs.block) return;
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -77,6 +77,11 @@ void log_print(const char *str)
|
|||
#endif
|
||||
}
|
||||
|
||||
void log_clear()
|
||||
{
|
||||
consolelog[0] = 0;
|
||||
}
|
||||
|
||||
void console_print(const char *str)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
|
|
|
@ -38,6 +38,7 @@ void sg_logging(const char *tag, uint32_t lvl, uint32_t id, const char *msg, uin
|
|||
void log_setfile(char *file);
|
||||
void log_cat(FILE *f);
|
||||
void log_print(const char *str);
|
||||
void log_clear();
|
||||
void console_print(const char *str);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1115,6 +1115,9 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
|||
if (js2bool(argv[1])) window_makefullscreen(&mainwin);
|
||||
else window_unfullscreen(&mainwin);
|
||||
break;
|
||||
case 146:
|
||||
log_clear();
|
||||
break;
|
||||
}
|
||||
|
||||
if (str)
|
||||
|
|
Loading…
Reference in a new issue