editor fix

This commit is contained in:
John Alanbrook 2024-04-03 17:17:32 -05:00
parent ccdcfafdf2
commit 32268fc25d
19 changed files with 360 additions and 422 deletions

View file

@ -212,7 +212,9 @@ Components only work in the context of an entity. They have no meaning outside o
While components can be added via scripting, it is easier to add them via the editor, as we will later see.
*** Ur system
The ur[fn::A German prefix meaning primitive, original, or earliest.] system is a prototypical inheritence system used by the actor files. When actor files are loaded, they are stored as an ur. An *ur* represents a set of instructions to create the (text, config) needed to spawn an actor or entity.
The ur[fn::A German prefix meaning primitive, original, or earliest.] system is a prototypical inheritence system used by the actor files. When actor files are loaded, they are stored as an ur. An *ur* holds a list of (text, config) required to create an entity.
When prosperon starts, it searches for urs by name. Any file ending in ".jso" or ".json" will be interpereted as an ur, with same named jso and json being applied as (text, config) for an ur. A jso or json alone also constitute an ur.
#+begin_scholium
Create an ur from the *hello* files above, and then spawn it.

View file

@ -1,5 +1,5 @@
this.phys = physics.kinematic;
this.dir_view2world = function(dir) { return dir.scale(this.realzoom()); };
this.dir_view2world = function(dir) { return dir.scale(this.zoom); };
this.view2world = function(pos) {
pos = pos.scale([window.rendersize.x/window.size.x, window.rendersize.y/window.size.y]);
pos = pos.sub(window.rendersize.scale(0.5));
@ -10,14 +10,11 @@ this.view2world = function(pos) {
this.world2view = function(pos) {
pos = pos.sub(this.pos);
pos = pos.scale(1.0/this.zoom);
pos = pos.add(window.rendersize);
pos = pos.add(window.rendersize.scale(0.5));
return pos;
};
this.realzoom = function() { return render.get_zoom(); };
this.screenright = function() {
return this.view2world(window.size).x;
}
this.screenright = function() { return this.view2world(window.size).x; }
this.screenleft = function() { return this.pos.x - (window.rendersize.x/2); }
this.zoom = 1;

View file

@ -489,6 +489,7 @@ component.edge2d = Object.copy(collider2d, {
'points',
'hollow',
'hollowt',
'angle',
]),
dimensions:2,
thickness:0,
@ -516,7 +517,7 @@ component.edge2d = Object.copy(collider2d, {
for (var i = spoints.length-1; i >= 0; i--) {
var newpoint = spoints[i].slice();
newpoint.x = -newpoint.x;
newpoint.x = -newpoint.x;
spoints.push(newpoint);
}
}
@ -527,8 +528,8 @@ component.edge2d = Object.copy(collider2d, {
for (var i = spoints.length-1; i >= 0; i--) {
var newpoint = spoints[i].slice();
newpoint.y = -newpoint.y;
spoints.push(newpoint);
newpoint.y = -newpoint.y;
spoints.push(newpoint);
}
}
@ -585,7 +586,7 @@ component.edge2d = Object.copy(collider2d, {
gizmo() {
if (this.type === Spline.type.catmull || this.type === -1) {
this.spoints().forEach(x => render.point(this.gameobject.this2screen(x), 3, Color.teal));
this.points.forEach((x,i) => render.coordinate(this.gameobject.this2screen(x), i));
this.points.forEach((x,i) => render.coordinate(this.gameobject.this2screen(x)));
} else {
for (var i = 0; i < this.points.length; i += 3)
render.coordinate(this.gameobject.this2screen(this.points[i]), i, Color.teal);
@ -614,23 +615,23 @@ component.edge2d = Object.copy(collider2d, {
if (p) {
var o = {
pos: p,
sync: me.sync.bind(me)
sync: me.sync.bind(me)
};
if (Spline.bezier_is_handle(this.points,i))
o.move = function(d) {
d = that.dir_world2this(d);
p.x += d.x;
p.y += d.y;
Spline.bezier_cp_mirror(me.points,i);
};
o.move = function(d) {
d = that.dir_world2this(d);
p.x += d.x;
p.y += d.y;
Spline.bezier_cp_mirror(me.points,i);
};
else
o.move = function(d) {
d = that.dir_world2this(d);
p.x += d.x;
p.y += d.y;
var pp = Spline.bezier_point_handles(me.points,i);
pp.forEach(ph => me.points[ph] = me.points[ph].add(d));
}
d = that.dir_world2this(d);
p.x += d.x;
p.y += d.y;
var pp = Spline.bezier_point_handles(me.points,i);
pp.forEach(ph => me.points[ph] = me.points[ph].add(d));
}
return o;
}
},

View file

@ -22,7 +22,7 @@ debug.draw = function() {
if (this.draw_gizmos)
game.all_objects(function(x) {
if (!x.icon) return;
GUI.image(x.icon, game.camera.world2view(x.pos));
gui.image(x.icon, game.camera.world2view(x.pos));
});
if (this.draw_names)
@ -143,12 +143,11 @@ debug.inputs.f9 = function() {
debug.inputs.f10 = function() { time.timescale = 0.1; };
debug.inputs.f10.doc = "Toggle timescale to 1/10.";
debug.inputs.f10.released = function () { time.timescale = 1.0; };
debug.inputs.f12 = function() { GUI.defaults.debug = !GUI.defaults.debug; console.warn("GUI toggle debug");};
debug.inputs.f12.doc = "Toggle drawing GUI debugging aids.";
debug.inputs.f12 = function() { gui.defaults.debug = !gui.defaults.debug; console.warn("gui toggle debug");};
debug.inputs.f12.doc = "Toggle drawing gui debugging aids.";
debug.inputs['M-1'] = render.normal;
debug.inputs['M-2'] = render.wireframe;
debug.inputs['C-M-f'] = function() {};
debug.inputs['C-M-f'].doc = "Enter camera fly mode.";

View file

@ -36,8 +36,8 @@ function ediff(from,to)
if (Array.isArray(v)) {
if (!Array.isArray(to[key]) || v.length !== to[key].length) {
var r = ediff(v,[]);
if (r) ret[key] = Object.values(r);
return;
if (r) ret[key] = Object.values(r);
return;
}
var diff = ediff(from[key], to[key]);
@ -47,14 +47,14 @@ function ediff(from,to)
return;
}
if (typeof v === 'object') {
if (typeof v === 'object' && v !== null) {
var diff = ediff(v, to[key]);
if (diff && !Object.empty(diff))
ret[key] = diff;
ret[key] = diff;
return;
}
if (typeof v === 'number') {
if (typeof v === 'number' || v === null) {
if (!isFinite(v)) v = null; // Squash infinity to null
if (v !== to[key])
ret[key] = v;

View file

@ -6,6 +6,8 @@
window.mode = window.modetypes.full;
game.loadurs();
console.info(`window size: ${window.size}, render size: ${window.rendersize}`);
player[0].control(debug);
Register.gui.register(debug.draw, debug);
@ -222,7 +224,7 @@ var editor = {
editor.cbs.push(Register.gui.register(editor.gui.bind(editor)));
editor.cbs.push(Register.draw.register(editor.draw.bind(editor)));
editor.cbs.push(Register.debug.register(editor.ed_debug.bind(editor)));
editor.cbs.push(Register.update.register(GUI.controls.update, GUI.controls));
editor.cbs.push(Register.update.register(gui.controls.update, gui.controls));
this.desktop = world.spawn();
world.rename_obj(this.desktop.toString(), "desktop");
@ -392,7 +394,6 @@ var editor = {
gui() {
/* Clean out killed objects */
this.selectlist = this.selectlist.filter(function(x) { return x.alive; });
render.text([0,0], game.camera.world2view([0,0]));
render.text("WORKING LAYER: " + this.working_layer, [0,520]);
@ -422,9 +423,11 @@ var editor = {
var depth = 0;
var alldirty = false;
for (var lvl of lvlchain) {
if (!lvl._ed) continue;
if (alldirty)
lvl._ed.dirty = true;
else {
if (!lvl._ed) continue;
lvl.check_dirty();
if (lvl._ed.dirty) alldirty = true;
}
@ -442,7 +445,6 @@ var editor = {
depth++;
render.text("$$$$$$", [0,ypos],1,editor.color_depths[depth]);
this.selectlist.forEach(function(x) {
render.text(x.urstr(), x.screenpos().add([0, 32]), 1, Color.editor.ur);
render.text(x.worldpos().map(function(x) { return Math.round(x); }), x.screenpos(), 1, Color.white);
@ -452,7 +454,8 @@ var editor = {
Object.entries(thiso.objects).forEach(function(x) {
var p = x[1].namestr();
render.text(p, x[1].screenpos().add([0,16]),1,editor.color_depths[depth]);
render.circle(x[1].screenpos(),10,Color.blue.alpha(0.3));
render.point(x[1].screenpos(),5,Color.blue.alpha(0.3));
render.point(x[1].screenpos(), 1, Color.red);
});
var mg = physics.pos_query(input.mouse.worldpos(),10);
@ -522,9 +525,12 @@ var editor = {
lvl_history: [],
load(urstr) {
var obj = editor.edit_level.spawn(urstr);
var mur = ur[urstr];
if (!mur) return;
var obj = editor.edit_level.spawn(mur);
obj.set_worldpos(input.mouse.worldpos());
this.selectlist = [obj];
console.warn(`made something and now the selected objects is ${this.selectlist.length} long.`);
},
load_prev() {
@ -553,15 +559,15 @@ var editor = {
/* make a new type path */
if (Object.access(ur,sub)) {
console.warn(`Ur named ${sub} already exists.`);
return;
return;
}
var file = `${sub}.json`;
io.slurpwrite(file, json.encode(obj.json_obj(),null,1));
ur[sub] = {
name: sub,
data: file,
proto: json.decode(json.encode(obj))
data: file,
proto: json.decode(json.encode(obj))
}
obj.ur = sub;
@ -583,12 +589,12 @@ var editor = {
if (obj === editor.edit_level) {
if (obj === editor.desktop) {
obj.clear();
var nobj = editor.edit_level.spawn(sub);
editor.selectlist = [nobj];
return;
}
editor.edit_level = editor.edit_level.master;
obj.clear();
var nobj = editor.edit_level.spawn(sub);
editor.selectlist = [nobj];
return;
}
editor.edit_level = editor.edit_level.master;
}
var t = obj.transform();
@ -664,7 +670,7 @@ editor.inputs.release_post = function() {
editor.edit_level.check_dirty();
/* snap all objects to be pixel perfect */
editor.edit_level.obj_descend(o => o.pos = o.pos.map(x => Math.round(x)));
game.all_objects(o => o.pos = o.pos.map(x => Math.round(x)), editor.edit_level);
};
editor.inputs['C-a'] = function() {
if (!Object.empty(editor.selectlist)) { editor.unselect(); return; }
@ -1404,7 +1410,7 @@ var inputpanel = {
toString() { return this.title; },
value: "",
on: false,
pos:[100,window.height-50],
pos:[100,window.size.y-50],
wh:[350,600],
anchor: [0,1],
padding:[5,-15],
@ -1422,7 +1428,7 @@ var inputpanel = {
];
else
this.win.items = itms;
this.win.draw(this.pos.slice());
this.win.draw([100, window.size.y-50]);
},
guibody() {
@ -1479,10 +1485,7 @@ var inputpanel = {
inputpanel.inputs = {};
inputpanel.inputs.post = function()
{
this.keycb();
}
inputpanel.inputs.post = function() { this.keycb(); }
inputpanel.inputs.char = function(c) {
this.value = this.value.slice(0,this.caret) + c + this.value.slice(this.caret);
@ -1524,26 +1527,20 @@ inputpanel.inputs['C-k'] = function() {
this.value = this.value.slice(0,this.caret);
};
inputpanel.inputs.lm = function()
{
GUI.controls.check_submit();
}
//load("scripts/textedit.js");
inputpanel.inputs.lm = function() { gui.controls.check_submit(); }
var replpanel = Object.copy(inputpanel, {
title: "",
closeonsubmit:false,
wh: [700,300],
pos: [50,50],
anchor: [0,0],
anchor: [0,1],
padding: [0,0],
scrolloffset: [0,0],
guibody() {
this.win.selectable = true;
var log = "";
log = log.slice(-5000);
var log = console.transcript;
return [
Mum.text({str:log, anchor:[0,0], offset:[0,-300].sub(this.scrolloffset), selectable: true}),
Mum.text({str:this.value,color:Color.green, offset:[0,-290], caret: this.caret})
@ -1801,8 +1798,6 @@ var objectexplorer = Object.copy(inputpanel, {
return items;
},
});
var openlevelpanel = Object.copy(inputpanel, {
@ -2005,9 +2000,6 @@ limited_editor.inputs['C-q'] = function()
var limited_editing = {};
limited_editing.inputs = {};
if (io.exists("editor.config"))
load_configs("editor.config");
/* This is the editor level & camera - NOT the currently edited level, but a level to hold editor things */
sim.pause();
window.editor = true;

View file

@ -120,53 +120,53 @@ qq = 'ms';
return `${t.toPrecision(4)} ${qq}`;
}
Object.assign(console, {
say(msg) { console.print(msg + "\n"); },
pprint(msg, lvl = 0) {
if (typeof msg === 'object')
msg = JSON.stringify(msg, null, 2);
var file = "nofile";
var line = 0;
var caller = (new Error()).stack.split('\n')[2];
if (caller) {
var md = caller.match(/\((.*)\:/);
var m = md ? md[1] : "SCRIPT";
if (m) file = m;
md = caller.match(/\:(\d*)\)/);
m = md ? md[1] : 0;
if (m) line = m;
}
console.rec(lvl, msg, file, line);
},
spam(msg) { console.pprint (msg,0); },
debug(msg) { console.pprint(msg,1); },
info(msg) { console.pprint(msg, 2); },
warn(msg) { console.pprint(msg, 3); },
error(msg) { console.pprint(msg + "\n" + console.stackstr(2), 4);},
panic(msg) { console.pprint(msg + "\n" + console.stackstr(2), 5); },
stackstr(skip=0) {
var err = new Error();
var stack = err.stack.split('\n');
return stack.slice(skip,stack.length).join('\n');
},
stack(skip = 0) {
console.log(console.stackstr(skip+1));
},
});
console.stdout_lvl = 1;
console.transcript = "";
console.say = function(msg) {
msg += "\n";
console.print(msg);
console.transcript += msg;
};
console.log = console.say;
console.trace = console.stack;
var say = console.say;
var print = console.print;
console.pprint = function(msg,lvl = 0) {
if (typeof msg === 'object')
msg = JSON.stringify(msg, null, 2);
var file = "nofile";
var line = 0;
var caller = (new Error()).stack.split('\n')[2];
if (caller) {
var md = caller.match(/\((.*)\:/);
var m = md ? md[1] : "SCRIPT";
if (m) file = m;
md = caller.match(/\:(\d*)\)/);
m = md ? md[1] : 0;
if (m) line = m;
}
console.rec(lvl, msg, file, line);
};
console.spam = function(msg) { console.pprint (msg,0); };
console.debug = function(msg) { console.pprint(msg,1); };
console.info = function(msg) { console.pprint(msg, 2); };
console.warn = function(msg) { console.pprint(msg, 3); };
console.error = function(msg) { console.pprint(msg + "\n" + console.stackstr(2), 4);};
console.panic = function(msg) { console.pprint(msg + "\n" + console.stackstr(2), 5); };
console.stackstr = function(skip=0) {
var err = new Error();
var stack = err.stack.split('\n');
return stack.slice(skip,stack.length).join('\n');
};
console.stack = function(skip = 0) { console.log(console.stackstr(skip+1)); };
console.stdout_lvl = 1;
console.trace = console.stack;
console.doc = {
level: "Set level to output logging to console.",
info: "Output info level message.",
@ -243,15 +243,14 @@ global.mixin("scripts/debug");
var frame_t = profile.secs(profile.now());
var phys_step = 1/60;
var sim = {
mode: "play",
play() { this.mode = "play"; os.reindex_static(); },
playing() { return this.mode === 'play'; },
pause() { this.mode = "pause"; console.stack(); },
paused() { return this.mode === 'pause'; },
step() { this.mode = 'step'; },
stepping() { return this.mode === 'step'; }
}
var sim = {};
sim.mode = "play";
sim.play = function() { this.mode = "play"; os.reindex_static(); };
sim.playing = function() { return this.mode === 'play'; };
sim.pause = function() { this.mode = "pause"; };
sim.paused = function() { return this.mode === 'pause'; };
sim.step = function() { this.mode = 'step'; };
sim.stepping = function() { return this.mode === 'step'; }
var physlag = 0;
@ -313,7 +312,8 @@ function process()
game.timescale = 1;
game.all_objects = function(fn) {
game.all_objects = function(fn, startobj) {
startobj ??= world;
var eachobj = function(obj,fn)
{
fn(obj);
@ -321,7 +321,7 @@ game.all_objects = function(fn) {
eachobj(obj.objects[o],fn);
}
eachobj(world,fn);
eachobj(startobj,fn);
};
game.tags = {};

View file

@ -84,14 +84,9 @@ var gameobject = {
this._ed.inst = false;
},
_ed: {
selectable: false,
dirty: false
},
namestr() {
var s = this.toString();
if (this._ed.dirty)
if (this._ed?.dirty)
if (this._ed.inst) s += "#";
else s += "*";
return s;
@ -259,17 +254,11 @@ var gameobject = {
ent.components = {};
ent.objects = {};
ent.timers = [];
ent.reparent(this);
ent._ed = {
selectable: true,
dirty: false,
inst: false,
urdiff: {},
};
if (typeof text === 'object') // assume it's an ur
if (typeof text === 'object' && text) // assume it's an ur
{
config = text.data;
ent.ur = text.name;
text = text.text;
}
@ -278,7 +267,8 @@ var gameobject = {
if (config)
Object.assign(ent, json.decode(io.slurp(config)));
ent.ur = text + "+" + config;
ent.ur ??= text + "+" + config;
ent.reparent(this);
for (var [prop, p] of Object.entries(ent)) {
if (!p) continue;
@ -300,11 +290,17 @@ var gameobject = {
if (sim.playing())
if (typeof ent.start === 'function') ent.start();
Object.hide(ent, 'ur', 'components', 'objects', '_ed', 'timers', 'master');
Object.hide(ent, 'ur', 'components', 'objects', 'timers', 'guid', 'master');
var mur = ent.get_ur();
if (mur && !mur.proto)
mur.proto = json.decode(json.encode(ent));
ent._ed = {
selectable: true,
dirty: false,
inst: false,
urdiff: {},
fresh: json.decode(json.encode(ent)),
};
Object.hide(ent, '_ed');
ent.sync();
@ -450,22 +446,19 @@ var gameobject = {
/* The unique components of this object. Its diff. */
json_obj() {
var u = this.get_ur();
if (!u) return {};
var proto = u.proto;
var fresh = this._ed.fresh;
var thiso = json.decode(json.encode(this)); // TODO: SLOW. Used to ignore properties in toJSON of components.
var d = ediff(thiso, proto);
var d = ediff(thiso, fresh);
d ??= {};
var objects = {};
proto.objects ??= {};
fresh.objects ??= {};
var curobjs = {};
for (var o in this.objects)
curobjs[o] = this.objects[o].instance_obj();
var odiff = ediff(curobjs, proto.objects);
var odiff = ediff(curobjs, fresh.objects);
if (odiff)
d.objects = curobjs;
@ -484,12 +477,6 @@ var gameobject = {
return t;
},
proto() {
var u = this.get_ur();
if (!u) return {};
return u.proto;
},
transform() {
var t = {};
t.pos = this.pos;
@ -497,7 +484,7 @@ var gameobject = {
t.angle = Math.places(this.angle, 4);
if (t.angle === 0) delete t.angle;
t.scale = this.scale;
t.scale = t.scale.map((x, i) => x / this.proto().scale[i]);
t.scale = t.scale.map((x, i) => x / this._ed.fresh.scale[i]);
t.scale = t.scale.map(x => Math.places(x, 3));
if (t.scale.every(x => x === 1)) delete t.scale;
return t;
@ -600,12 +587,6 @@ var gameobject = {
Object.assign(this[name], data);
return this[name];
},
obj_descend(fn) {
fn(this);
for (var o in this.objects)
this.objects[o].obj_descend(fn);
},
}
function go_init() {

View file

@ -1,64 +1,41 @@
/*
GUI functions take screen space coordinates
gui functions take screen space coordinates
*/
gui.scissor_win = function() { gui.scissor(0,0,window.width,window.height); }
var GUI = {
newmg(img) {
var def = {
path: "",
pos: [0,0],
size:[0,0],
frame: {
x: 0,
y: 0,
w: 1,
h: 1
},
angle: 0,
anchor: [0,0],
color: Color.white,
}
for (var i in def)
img[i] ??= def[i];
gui.input_lmouse_pressed = function() {
if (gui.selected)
gui.selected.action();
};
gui_newmg
},
input_lmouse_pressed() {
if (GUI.selected)
GUI.selected.action();
},
input_s_pressed() {
if (GUI.selected?.down) {
GUI.selected.selected = false;
GUI.selected = GUI.selected.down;
GUI.selected.selected = true;
}
},
input_w_pressed() {
if (GUI.selected?.up) {
GUI.selected.selected = false;
GUI.selected = GUI.selected.up;
GUI.selected.selected = true;
}
},
input_enter_pressed() {
if (GUI.selected) {
GUI.selected.action();
}
gui.input_s_pressed = function() {
if (gui.selected?.down) {
gui.selected.selected = false;
gui.selected = gui.selected.down;
gui.selected.selected = true;
}
};
GUI.controls = {};
GUI.controls.toString = function() { return "GUI controls"; };
GUI.controls.update = function() { };
gui.input_w_pressed = function() {
if (gui.selected?.up) {
gui.selected.selected = false;
gui.selected = gui.selected.up;
gui.selected.selected = true;
}
};
GUI.controls.set_mum = function(mum)
gui.input_enter_pressed = function() {
if (gui.selected) {
gui.selected.action();
}
}
gui.controls = {};
gui.controls.toString = function() { return "gui controls"; };
gui.controls.update = function() { };
gui.controls.set_mum = function(mum)
{
mum.selected = true;
@ -67,22 +44,22 @@ GUI.controls.set_mum = function(mum)
this.selected = mum;
}
GUI.controls.check_bb = function(mum)
gui.controls.check_bb = function(mum)
{
if (bbox.pointin(mum.bb, input.mouse.screenpos()))
GUI.controls.set_mum(mum);
gui.controls.set_mum(mum);
}
GUI.controls.inputs = {};
GUI.controls.inputs.fallthru = false;
GUI.controls.inputs.mouse = {};
GUI.controls.inputs.mouse.move = function(pos,dpos)
gui.controls.inputs = {};
gui.controls.inputs.fallthru = false;
gui.controls.inputs.mouse = {};
gui.controls.inputs.mouse.move = function(pos,dpos)
{
}
GUI.controls.inputs.mouse.scroll = function(scroll)
gui.controls.inputs.mouse.scroll = function(scroll)
{
}
GUI.controls.check_submit = function() {
gui.controls.check_submit = function() {
if (this.selected && this.selected.action)
this.selected.action(this.selected);
}
@ -145,7 +122,7 @@ Mum.text = Mum.extend({
cursor ??= [0,0];
cnt ??= Mum;
if (this.hide) return;
if (this.selectable) GUI.controls.check_bb(this);
if (this.selectable) gui.controls.check_bb(this);
this.caret ??= -1;
/* if (!this.bb)
@ -162,7 +139,7 @@ Mum.text = Mum.extend({
var aa = [0,1].sub(params.anchor);
var pos = cursor.add(params.wh.scale(aa)).add(params.offset);
gui.font_set(params.font);
gui.text(params.str, pos, params.font_size, params.color, this.width, params.caret);
render.text(params.str, pos, params.font_size, params.color, this.width, undefined, params.caret);
},
update_bb(cursor) {
@ -198,12 +175,12 @@ Mum.window = Mum.extend({
cursor ??= [0,0];
cnt ??= Mum;
var p = cursor.sub(this.wh.scale(this.anchor)).add(this.padding);
GUI.window(p,this.wh, this.color);
render.window(p,this.wh, this.color);
this.bb = bbox.blwh(p, this.wh);
gui.flush();
gui.scissor(p.x,p.y,this.wh.x,this.wh.y);
this.max_width = this.width;
if (this.selectable) GUI.controls.check_bb(this);
if (this.selectable) gui.controls.check_bb(this);
var pos = [this.bb.l, this.bb.t].add(this.padding);
this.items.forEach(function(item) {
if (item.hide) return;
@ -259,14 +236,6 @@ Mum.column = Mum.extend({
},
});
GUI.window = function(pos, wh, color)
{
var p = pos.slice();
p.x += wh.x/2;
p.y += wh.y/2;
render.box(p,wh,color);
}
Mum.debug_colors = {
bounds: Color.red.slice(),
margin: Color.blue.slice(),
@ -275,7 +244,4 @@ Mum.debug_colors = {
Object.values(Mum.debug_colors).forEach(function(v) { v.a = 100; });
return {
GUI,
Mum
};
return { Mum };

View file

@ -1,5 +1,5 @@
input.keycodes = {
259: "back",
259: "backspace",
258: "tab",
257: "enter",
256: "escape",
@ -111,7 +111,9 @@ prosperon.droppedfile = function(path)
var mousepos = [0,0];
prosperon.textinput = function(l){};
prosperon.textinput = function(c){
player[0].raw_input("char", "pressed", c);
};
prosperon.mousemove = function(pos, dx){
mousepos = pos;
player[0].mouse_input(modstr() + "move", pos, dx);
@ -126,48 +128,46 @@ prosperon.mouseup = function(b){
player[0].raw_input(modstr() + input.mouse.button[b], "released");
};
input.mouse = {
screenpos() { return mousepos.slice(); },
worldpos() { return game.camera.view2world(mousepos); },
disabled() { input.mouse_mode(1); },
normal() { input.mouse_mode(0); },
input.mouse = {};
input.mouse.screenpos = function() { return mousepos.slice(); };
input.mouse.worldpos = function() { return game.camera.view2world(mousepos); };
input.mouse.disabled = function() { input.mouse_mode(1); };
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);
};
mode(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) {
mode ??= input.mouse.cursor.default;
if (!img)
delete input.mouse.custom[mode];
else {
input.cursor_img(img);
input.mouse.custom[mode] = img;
}
};
set_custom_cursor(img, mode) {
mode ??= input.mouse.cursor.default;
if (!img)
delete input.mouse.custom[mode];
else {
input.cursor_img(img);
input.mouse.custom[mode] = img;
}
},
button: { /* left, right, middle mouse */
0: "lm",
1: "rm",
2: "mm"
},
custom:[],
cursor: {
default: 0,
arrow: 1,
ibeam: 2,
cross: 3,
hand: 4,
ew: 5,
ns: 6,
nwse: 7,
nesw: 8,
resize: 9,
no: 10
},
input.mouse.button = { /* left, right, middle mouse */
0: "lm",
1: "rm",
2: "mm"
};
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,
no: 10
};
input.mouse.doc = {};

View file

@ -12,7 +12,7 @@ var HIT = {
var pq = physics.pos_query;
physics.pos_query = function(pos,give) {
give ??= 25;
pq(pos,give);
return pq(pos,give);
}
physics.box_point_query = function(box,points) {

View file

@ -88,14 +88,13 @@ render.arrow = function(start, end, color, wingspan, wingangle) {
};
render.coordinate = function(pos, size, color) {
color ??= Color.white;
render.text(JSON.stringify(pos.map(p=>Math.round(p))), pos, size, color);
render.point(pos, 2, color);
render.text(JSON.stringify(pos.map(p=>Math.round(p))), pos, size, color);
render.point(pos, 2, color);
}
render.boundingbox = function(bb, color) {
color ??= Color.white;
cmd_points(0, bbox.topoints(bb), color);
render.poly(bbox.topoints(bb), color);
}
render.rectangle = function(lowerleft, upperright, color) {
@ -110,6 +109,12 @@ render.box = function(pos, wh, color) {
render.rectangle(lower,upper,color);
};
render.window = function(pos, wh, color) {
var p = pos.slice();
p = p.add(wh.scale(0.5));
render.box(p,wh,color);
};
render.text = function(str, pos, size, color, wrap, anchor, cursor) {
size ??= 1;
color ??= Color.white;
@ -122,7 +127,7 @@ render.text = function(str, pos, size, color, wrap, anchor, cursor) {
var w = bb.r*2;
var h = bb.t*2;
//gui.text draws with an anchor on top left corner
//render.text draws with an anchor on top left corner
var p = pos.slice();
p.x -= w * anchor.x;
bb.r += (w*anchor.x);

View file

@ -191,6 +191,8 @@ Cmdline.register_order("edit", function() {
return;
}
window.size = [1280, 720];
game.engine_start(function() {
global.mixin("scripts/editor.js");
use("editorconfig.js");

View file

@ -48,13 +48,7 @@ cpTransform m3_to_cpt(HMM_Mat3 m)
}
cpShape *phys2d_query_pos(cpVect pos) {
cpShapeFilter filter;
filter.group = CP_NO_GROUP;
filter.mask = CP_ALL_CATEGORIES;
filter.categories = CP_ALL_CATEGORIES;
cpShape *find = cpSpacePointQueryNearest(space, pos, 0.f, filter, NULL);
return find;
return cpSpacePointQueryNearest(space, pos, 0.f, allfilter, NULL);
}

View file

@ -51,10 +51,7 @@ gameobject *pos2gameobject(HMM_Vec2 pos, float give) {
return shape2go(hit);
for (int i = 0; i < arrlen(gameobjects); i++) {
if (!gameobjects[i]->body) continue;
HMM_Vec2 gpos = go_pos(gameobjects[i]);
float dist = HMM_DistV2(gpos,pos);
float dist = HMM_DistV2(go_pos(gameobjects[i]),pos);
if (dist <= give) return gameobjects[i];
}

View file

@ -608,111 +608,6 @@ JSC_CCALL(emitter_start, start_emitter(js2emitter(this)))
JSC_CCALL(emitter_stop, stop_emitter(js2emitter(this)))
JSC_CCALL(emitter_emit, emitter_emit(js2emitter(this), js2number(argv[0])))
JSValue js_os_cwd(JSContext *js, JSValue this, int argc, JSValue *argv)
{
char cwd[PATH_MAX];
#ifndef __EMSCRIPTEN__
getcwd(cwd, sizeof(cwd));
#else
cwd[0] = '.';
cwd[1] = 0;
#endif
return str2js(cwd);
}
JSC_SCALL(os_env, ret = str2js(getenv(str)))
JSValue js_os_sys(JSContext *js, JSValue this, int argc, JSValue *argv)
{
#ifdef __linux__
return str2js("linux");
#elif defined(_WIN32) || defined(_WIN64)
return str2js("windows");
#elif defined(__APPLE__)
return str2js("macos");
#endif
return JS_UNDEFINED;
}
JSC_CCALL(os_quit, quit();)
JSC_CCALL(os_exit, exit(js2number(argv[0]));)
JSC_CCALL(os_reindex_static, cpSpaceReindexStatic(space));
JSC_CCALL(os_gc, script_gc());
JSC_SSCALL(os_eval, ret = script_eval(str, str2))
JSC_SCALL(os_capture, capture_screen(js2number(argv[1]), js2number(argv[2]), js2number(argv[4]), js2number(argv[5]), str))
JSC_CCALL(os_sprite,
if (js2boolean(argv[0])) return JS_GetClassProto(js,js_sprite_id);
return sprite2js(sprite_make());
)
JSC_CCALL(os_make_gameobject, return gameobject2js(MakeGameobject()))
JSC_CCALL(os_make_circle2d,
gameobject *go = js2gameobject(argv[0]);
struct phys2d_circle *circle = Make2DCircle(go);
JSValue circleval = JS_NewObject(js);
js_setprop_str(circleval, "id", ptr2js(circle));
js_setprop_str(circleval, "shape", ptr2js(&circle->shape));
return circleval;
)
JSC_CCALL(os_make_model,
gameobject *go = js2gameobject(argv[0]);
struct drawmodel *dm = make_drawmodel(go);
JSValue ret = JS_NewObject(js);
js_setprop_str(ret, "id", ptr2js(dm));
return ret;
)
JSC_CCALL(os_make_poly2d,
gameobject *go = js2gameobject(argv[0]);
struct phys2d_poly *poly = Make2DPoly(go);
phys2d_poly_setverts(poly, NULL);
JSValue polyval = JS_NewObject(js);
js_setprop_str(polyval, "id", ptr2js(poly));
js_setprop_str(polyval, "shape", ptr2js(&poly->shape));
return polyval;
)
JSC_CCALL(os_make_edge2d,
gameobject *go = js2gameobject(argv[0]);
struct phys2d_edge *edge = Make2DEdge(go);
HMM_Vec2 *points = js2cpvec2arr(argv[1]);
phys2d_edge_update_verts(edge, points);
arrfree(points);
JSValue edgeval = JS_NewObject(js);
js_setprop_str(edgeval, "id", ptr2js(edge));
js_setprop_str(edgeval, "shape", ptr2js(&edge->shape));
return edgeval;
)
JSC_SCALL(os_make_texture,
ret = texture2js(texture_from_file(str));
YughInfo("Made texture with %s", str);
JS_SetPropertyStr(js, ret, "path", JS_DupValue(js,argv[0]));
)
JSC_SCALL(os_system, system(str); )
static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os,sprite,1),
MIST_FUNC_DEF(os, cwd, 0),
MIST_FUNC_DEF(os, env, 1),
MIST_FUNC_DEF(os, sys, 0),
MIST_FUNC_DEF(os, system, 1),
MIST_FUNC_DEF(os, quit, 0),
MIST_FUNC_DEF(os, exit, 1),
MIST_FUNC_DEF(os, reindex_static, 0),
MIST_FUNC_DEF(os, gc, 0),
MIST_FUNC_DEF(os, capture, 5),
MIST_FUNC_DEF(os, eval, 2),
MIST_FUNC_DEF(os, make_gameobject, 0),
MIST_FUNC_DEF(os, make_circle2d, 1),
MIST_FUNC_DEF(os, make_poly2d, 1),
MIST_FUNC_DEF(os, make_edge2d, 1),
MIST_FUNC_DEF(os, make_model, 2),
MIST_FUNC_DEF(os, make_texture, 1),
};
JSC_CCALL(render_grid, draw_grid(js2number(argv[0]), js2number(argv[1]), js2color(argv[2]));)
JSC_CCALL(render_point, draw_cppoint(js2vec2(argv[0]), js2number(argv[1]), js2color(argv[2])))
@ -1030,8 +925,7 @@ JSC_CCALL(physics_set_cat_mask, set_cat_mask(js2number(argv[0]), js2bitmask(argv
JSC_CCALL(physics_pos_query,
gameobject *go = pos2gameobject(js2vec2(argv[0]), js2number(argv[1]));
JSValue ret = go ? JS_DupValue(js,go->ref) : JS_UNDEFINED;
return ret;
return go ? JS_DupValue(js,go->ref) : JS_UNDEFINED;
)
JSC_CCALL(physics_closest_point,
@ -1207,8 +1101,14 @@ static JSValue js_window_set_size(JSContext *js, JSValue this, JSValue v) {
return JS_UNDEFINED;
}
JSC_GETSET_APPLY(window, rendersize, vec2)
static JSValue js_window_get_rendersize(JSContext *js, JSValue this) {
window *w = js2window(this);
if (w->rendersize.x == 0 || w->rendersize.y == 0) return vec22js(w->size);
return vec22js(w->rendersize);
}
static JSValue js_window_set_rendersize(JSContext *js, JSValue this, JSValue v) {
js2window(this)->rendersize = js2vec2(v);
}
JSC_GETSET(window, mode, number)
static JSValue js_window_get_fullscreen(JSContext *js, JSValue this) { return boolean2js(js2window(this)->fullscreen); }
static JSValue js_window_set_fullscreen(JSContext *js, JSValue this, JSValue v) { window_setfullscreen(js2window(this), js2boolean(v)); }
@ -1235,12 +1135,13 @@ static const JSCFunctionListEntry js_window_funcs[] = {
};
JSValue js_gameobject_set_pos(JSContext *js, JSValue this, JSValue val) {
gameobject *go = js2gameobject(this);
cpBodySetPosition(go->body, js2vec2(val).cp);
if (go->phys == CP_BODY_TYPE_STATIC)
cpSpaceReindexShapesForBody(space, go->body);
cpBody *b = js2gameobject(this)->body;
cpBodySetPosition(b, js2cvec2(val));
if (cpBodyGetType(b) == CP_BODY_TYPE_STATIC)
cpSpaceReindexShapesForBody(space, b);
return JS_UNDEFINED;
}
JSValue js_gameobject_get_pos(JSContext *js, JSValue this) { return vec22js((HMM_Vec2)cpBodyGetPosition(js2gameobject(this)->body)); }
JSValue js_gameobject_get_pos(JSContext *js, JSValue this) { return cvec22js(cpBodyGetPosition(js2gameobject(this)->body)); }
JSValue js_gameobject_set_angle (JSContext *js, JSValue this, JSValue val) { cpBodySetAngle(js2gameobject(this)->body, HMM_TurnToRad*js2number(val)); }
JSValue js_gameobject_get_angle (JSContext *js, JSValue this) { return number2js(HMM_RadToTurn*cpBodyGetAngle(js2gameobject(this)->body)); }
JSC_GETSET_BODY(velocity, Velocity, cvec2)
@ -1511,6 +1412,117 @@ static const JSCFunctionListEntry js_nota_funcs[] = {
MIST_FUNC_DEF(nota, decode, 1)
};
JSValue js_os_cwd(JSContext *js, JSValue this, int argc, JSValue *argv)
{
char cwd[PATH_MAX];
#ifndef __EMSCRIPTEN__
getcwd(cwd, sizeof(cwd));
#else
cwd[0] = '.';
cwd[1] = 0;
#endif
return str2js(cwd);
}
JSC_SCALL(os_env, ret = str2js(getenv(str)))
JSValue js_os_sys(JSContext *js, JSValue this, int argc, JSValue *argv)
{
#ifdef __linux__
return str2js("linux");
#elif defined(_WIN32) || defined(_WIN64)
return str2js("windows");
#elif defined(__APPLE__)
return str2js("macos");
#endif
return JS_UNDEFINED;
}
JSC_CCALL(os_quit, quit();)
JSC_CCALL(os_exit, exit(js2number(argv[0]));)
JSC_CCALL(os_reindex_static, cpSpaceReindexStatic(space));
JSC_CCALL(os_gc, script_gc());
JSC_SSCALL(os_eval, ret = script_eval(str, str2))
JSC_SCALL(os_capture, capture_screen(js2number(argv[1]), js2number(argv[2]), js2number(argv[4]), js2number(argv[5]), str))
JSC_CCALL(os_sprite,
if (js2boolean(argv[0])) return JS_GetClassProto(js,js_sprite_id);
return sprite2js(sprite_make());
)
JSC_CCALL(os_make_gameobject,
ret = gameobject2js(MakeGameobject());
JS_SetPropertyFunctionList(js, ret, js_gameobject_funcs, countof(js_gameobject_funcs));
return ret;
)
JSC_CCALL(os_make_circle2d,
gameobject *go = js2gameobject(argv[0]);
struct phys2d_circle *circle = Make2DCircle(go);
JSValue circleval = JS_NewObject(js);
js_setprop_str(circleval, "id", ptr2js(circle));
js_setprop_str(circleval, "shape", ptr2js(&circle->shape));
return circleval;
)
JSC_CCALL(os_make_model,
gameobject *go = js2gameobject(argv[0]);
struct drawmodel *dm = make_drawmodel(go);
JSValue ret = JS_NewObject(js);
js_setprop_str(ret, "id", ptr2js(dm));
return ret;
)
JSC_CCALL(os_make_poly2d,
gameobject *go = js2gameobject(argv[0]);
struct phys2d_poly *poly = Make2DPoly(go);
phys2d_poly_setverts(poly, NULL);
JSValue polyval = JS_NewObject(js);
js_setprop_str(polyval, "id", ptr2js(poly));
js_setprop_str(polyval, "shape", ptr2js(&poly->shape));
return polyval;
)
JSC_CCALL(os_make_edge2d,
gameobject *go = js2gameobject(argv[0]);
struct phys2d_edge *edge = Make2DEdge(go);
HMM_Vec2 *points = js2cpvec2arr(argv[1]);
phys2d_edge_update_verts(edge, points);
arrfree(points);
JSValue edgeval = JS_NewObject(js);
js_setprop_str(edgeval, "id", ptr2js(edge));
js_setprop_str(edgeval, "shape", ptr2js(&edge->shape));
return edgeval;
)
JSC_SCALL(os_make_texture,
ret = texture2js(texture_from_file(str));
YughInfo("Made texture with %s", str);
JS_SetPropertyStr(js, ret, "path", JS_DupValue(js,argv[0]));
)
JSC_SCALL(os_system, system(str); )
static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os,sprite,1),
MIST_FUNC_DEF(os, cwd, 0),
MIST_FUNC_DEF(os, env, 1),
MIST_FUNC_DEF(os, sys, 0),
MIST_FUNC_DEF(os, system, 1),
MIST_FUNC_DEF(os, quit, 0),
MIST_FUNC_DEF(os, exit, 1),
MIST_FUNC_DEF(os, reindex_static, 0),
MIST_FUNC_DEF(os, gc, 0),
MIST_FUNC_DEF(os, capture, 5),
MIST_FUNC_DEF(os, eval, 2),
MIST_FUNC_DEF(os, make_gameobject, 0),
MIST_FUNC_DEF(os, make_circle2d, 1),
MIST_FUNC_DEF(os, make_poly2d, 1),
MIST_FUNC_DEF(os, make_edge2d, 1),
MIST_FUNC_DEF(os, make_model, 2),
MIST_FUNC_DEF(os, make_texture, 1),
};
#include "steam.h"
void ffi_load() {

View file

@ -114,7 +114,6 @@ JS_SetPropertyFunctionList(js, TYPE##_proto, js_##TYPE##_funcs, countof(js_##TYP
JS_SetPropertyStr(js, TYPE##_proto, "memid", JS_NewCFunction(js, &js_##TYPE##_memid, "memid", 0)); \
JS_SetClassProto(js, js_##TYPE##_id, TYPE##_proto); \
#define countof(x) (sizeof(x)/sizeof((x)[0]))
void ffi_load();

View file

@ -29,15 +29,8 @@ extern HMM_Vec3 dirl_pos;
extern HMM_Mat4 projection;
extern HMM_Mat4 hudproj;
extern HMM_Mat4 useproj;
struct camera3d {
};
typedef struct camera3d camera3d;
struct draw_p {
float x;
float y;
@ -61,12 +54,8 @@ void openglRender(struct window *window, gameobject *cam, float zoom);
void opengl_rendermode(enum RenderMode r);
void openglInit3d(struct window *window);
void openglRender3d(struct window *window, camera3d *camera);
void capture_screen(int x, int y, int w, int h, const char *path);
HMM_Vec2 world2screen(HMM_Vec2 pos);
HMM_Vec2 screen2world(HMM_Vec2 pos);
void gif_rec_start(int w, int h, int cpf, int bitdepth);
void gif_rec_end(const char *path);

View file

@ -92,6 +92,7 @@ void c_clean() {
void c_event(const sapp_event *e)
{
char lcfmt[5];
switch (e->type) {
case SAPP_EVENTTYPE_MOUSE_MOVE:
script_evalf("prosperon.mousemove([%g, %g], [%g, %g]);", e->mouse_x, mainwin.size.y -e->mouse_y, e->mouse_dx, -e->mouse_dy);
@ -118,7 +119,8 @@ void c_event(const sapp_event *e)
break;
case SAPP_EVENTTYPE_CHAR:
script_evalf("prosperon.textinput(`\\%lc`);", e->char_code);
snprintf(lcfmt, 5, "%lc", e->char_code);
script_evalf("prosperon.textinput(`%s`);", lcfmt);
break;
case SAPP_EVENTTYPE_RESIZED: