Start and restart play mode

This commit is contained in:
John Alanbrook 2023-10-11 22:22:41 +00:00
parent cff5483325
commit 8f455476f1
9 changed files with 129 additions and 172 deletions

View file

@ -43,6 +43,14 @@ Object.rkeys = function(o)
return keys;
}
Object.extend = function(from, src)
{
var n = {};
Object.mixin(n, from);
Object.mixin(n, src);
return n;
}
Object.mixin = function(target, source)
{
if (typeof source !== 'object') return target;
@ -57,6 +65,15 @@ Object.mixin = function(target, source)
return target;
};
Object.deepmixin = function(target, source)
{
var o = source;
while (o !== Object.prototype) {
Object.mixin(target, o);
o = o.__proto__;
};
}
Object.deepfreeze = function(obj)
{
for (var key in obj) {
@ -67,23 +84,6 @@ Object.deepfreeze = function(obj)
}
/* Goes through each key and overwrites if it's present */
/*
Object.dainty_assign = function(target, source)
{
Object.keys(target).forEach(function(key) {
if (!(key in source)) return;
if (typeof target[key] === 'function') return;
if (Array.isArray(target[key]))
target[key] = deep_copy(source[key]);
else if (typeof target[key] === 'object')
Object.dainty_assign(target[key], source[key]);
else
target[key] = source[key];
});
}
*/
Object.dainty_assign = function(target, source)
{
Object.keys(source).forEach(function(k) {
@ -230,13 +230,6 @@ Object.defineProperty(Object.prototype, 'nulldef', {
}
});
/*Object.defineProperty(Object.prototype, 'writable', {
value: function(name) {
return Object.getPropertyDescriptor(this, name).writable;
}
});
*/
Object.defineProperty(Object.prototype, 'prop_obj', {
value: function() { return JSON.parse(JSON.stringify(this)); }
});

View file

@ -324,11 +324,14 @@ var collider2d = Object.copy(component, {
register_hit(fn, obj) {
register_collide(1, fn, obj, this.gameobject.body, this.shape);
},
/* set sensor(x) { cmd(18,this.shape,x); },
impl: {
set sensor(x) { cmd(18,this.shape,x); },
get sensor() { return cmd(21,this.shape); },
set enabled(x) { cmd(22,this.shape,x); },
get enabled() { return cmd(23,this.shape); }
*/
// set enabled(x) { cmd(22,this.shape,x); },
// get enabled() { return cmd(23,this.shape); }
},
});
collider2d.inputs = {};
@ -403,14 +406,14 @@ component.polygon2d = Object.copy(collider2d, {
},
});
component.polygon2d.impl = {
component.polygon2d.impl = Object.extend(collider2d.impl, {
sync() {
cmd_poly2d(0, this.id, this.spoints);
},
query() {
return cmd(80, this.shape);
},
};
});
var polygon2d = component.polygon2d;
@ -448,7 +451,6 @@ component.edge2d = Object.copy(collider2d, {
degrees:2,
dimensions:2,
thickness:0,
points: [],
/* open: 0
clamped: 1
beziers: 2
@ -524,7 +526,7 @@ component.edge2d = Object.copy(collider2d, {
assert knots%order != 0
*/
if (this.type === typeid.this.looped)
if (this.type === component.edge2d.typeid.this.looped)
return spline_cmd(0, this.degrees, this.dimensions, 0, spoints.wrapped(this.degrees), n);
return spline_cmd(0, this.degrees, this.dimensions, this.type, spoints, n);
@ -536,16 +538,8 @@ component.edge2d = Object.copy(collider2d, {
return points2bb(this.points.map(x => x.scale(this.gameobject.scale)));
},
make(go) {
var edge = Object.create(this);
edge.gameobject = go;
// edge.cpoints = [];
// edge.points = [];
Object.assign(edge, make_edge2d(go.body, edge.points, 0));
Object.mixin(edge,edge.impl);
Object.hide(edge, 'gameobject', 'id', 'shape');
return edge;
},
hides: ['gameobject', 'id', 'shape', 'points'],
_enghook: make_edge2d,
/* EDITOR */
gizmo() {
@ -570,23 +564,22 @@ component.edge2d = Object.copy(collider2d, {
sync: this.sync.bind(this),
};
return undefined;
},
});
component.edge2d.impl = {
component.edge2d.impl = Object.extend(collider2d.impl, {
set thickness(x) {
cmd_edge2d(1,this.id,x);
},
get thickness() { return cmd(112,this.id); },
sync() {
var sensor = this.sensor;
this.points = this.sample(this.samples);
cmd_edge2d(0,this.id,this.points);
var points = this.sample(this.samples);
cmd_edge2d(0,this.id,points);
this.sensor = sensor;
},
};
});
var bucket = component.edge2d;
bucket.inputs = {};
@ -655,6 +648,8 @@ bucket.inputs['C-M-lm'] = function() {
};
bucket.inputs['C-M-lm'].doc = "Select the given point as the '0' of this spline.";
bucket.inputs.lm = function(){};
bucket.inputs['C-lm'] = function() {
var idx = 0;
@ -670,13 +665,15 @@ bucket.inputs['C-lm'] = function() {
};
bucket.inputs['C-lm'].doc = "Add a point to the spline at the mouse position.";
bucket.inputs['S-lm'] = function() {
var idx = grab_from_points(screen2world(Mouse.pos), this.cpoints.map(function(x) {return x.add(this.gameobject.pos); }, this), 25);
bucket.inputs['C-M-lm'] = function() {
var idx = cmd(59, Mouse.worldpos.sub(this.gameobject.pos), this.cpoints, 250);
Log.warn(idx);
// var idx = grab_from_points(screen2world(Mouse.pos), this.cpoints.map(function(x) {return x.add(this.gameobject.pos); }, this), 25);
if (idx === -1) return;
this.cpoints.splice(idx, 1);
};
bucket.inputs['S-lm'].doc = "Remove point from the spline.";
bucket.inputs['C-M-lm'].doc = "Remove point from the spline.";
bucket.inputs.lb = function() {
var np = [];
@ -703,17 +700,6 @@ bucket.inputs.rb.doc = "Rotate the points CW.";
bucket.inputs.rb.rep = true;
component.circle2d = Object.copy(collider2d, {
impl: {
set radius(x) { cmd_circle2d(0,this.id,x); },
get radius() { return cmd_circle2d(2,this.id); },
set scale(x) { this.radius = x; },
get scale() { return this.radius; },
set offset(x) { cmd_circle2d(1,this.id,x); },
get offset() { return cmd_circle2d(3,this.id); },
},
radius:10,
offset:[0,0],
toString() { return "circle2d"; },
@ -727,6 +713,17 @@ component.circle2d = Object.copy(collider2d, {
_enghook: make_circle2d,
});
component.circle2d.impl = Object.extend(collider2d.impl, {
set radius(x) { cmd_circle2d(0,this.id,x); },
get radius() { return cmd_circle2d(2,this.id); },
set scale(x) { this.radius = x; },
get scale() { return this.radius; },
set offset(x) { cmd_circle2d(1,this.id,x); },
get offset() { return cmd_circle2d(3,this.id); },
});
/* ASSETS */
var Texture = {

View file

@ -154,8 +154,8 @@ DebugControls.inputs.f1.doc = "Draw physics debugging aids.";
//DebugControls.inputs.f3 = function() { Debug.draw_bb = !Debug.draw_bb; };
//DebugControls.inputs.f3.doc = "Toggle drawing bounding boxes.";
DebugControls.inputs.f4 = function() {
Debug.draw_names = !Debug.draw_names;
Debug.draw_gizmos = !Debug.draw_gizmos;
// Debug.draw_names = !Debug.draw_names;
// Debug.draw_gizmos = !Debug.draw_gizmos;
};
DebugControls.inputs.f4.doc = "Toggle drawing gizmos and names of objects.";

View file

@ -197,10 +197,10 @@ var editor = {
stash: undefined,
start_play_ed() {
this.stash = this.edit_level.json_obj();
this.edit_level.kill();
// load_configs("game.config");
this.stash = this.desktop.instance_obj();
Primum.clear();
Game.play();
Game.editor_mode(false);
Player.players[0].uncontrol(this);
Player.players[0].control(limited_editor);
Register.unregister_obj(this);
@ -215,6 +215,16 @@ var editor = {
Debug.register_call(editor.ed_debug, editor);
Register.update.register(gui_controls.update, gui_controls);
Player.players[0].control(gui_controls);
this.desktop = Primum.spawn(ur.arena);
this.edit_level = this.desktop;
editor.edit_level._ed.selectable = false;
if (this.stash) {
this.desktop.make_objs(this.stash.objects);
Object.dainty_assign(this.desktop, this.stash);
}
this.selectlist = [];
Game.view_camera(editor.camera);
},
end_debug() {
@ -356,23 +366,6 @@ var editor = {
}
},
clear_level() {
if (this.edit_level) {
if (this.edit_level.level) {
this.openpanel(gen_notify("Can't close a nested level. Save up to the root before continuing."));
return;
}
this.unselect();
this.edit_level.kill();
}
this.edit_level = Primum.spawn(ur.arena);
this.desktop = this.edit_level;
if (this.stash)
editor.edit_level._ed.selectable = false;
},
load_desktop(d) {
},
@ -663,13 +656,13 @@ editor.inputs['C-e'].doc = "Open asset explorer.";
editor.inputs['C-l'] = function() { editor.openpanel(entitylistpanel); };
editor.inputs['C-l'].doc = "Open list of spawned entities.";
/*editor.inputs['C-i'] = function() {
editor.inputs['C-i'] = function() {
if (editor.selectlist.length !== 1) return;
objectexplorer.obj = editor.selectlist[0];
editor.openpanel(objectexplorer);
};
editor.inputs['C-i'].doc = "Open the object explorer for a selected object.";
*/
editor.inputs['C-d'] = function() {
if (editor.selectlist.length === 0) return;
var duped = editor.dup_objects(editor.selectlist);
@ -854,13 +847,14 @@ editor.inputs['M-t'] = function() { editor.edit_level.objects.forEach(function(x
editor.inputs['M-t'].doc = "Unlock all objects in current level.";
editor.inputs['C-n'] = function() {
if (editor.edit_level._ed.dirty) {
/* if (editor.edit_level._ed.dirty) {
Log.info("Level has changed; save before starting a new one.");
editor.openpanel(gen_notify("Level is changed. Are you sure you want to close it?", _ => editor.clear_level()));
return;
}
editor.clear_level();
*/
};
editor.inputs['C-n'].doc = "Open a new level.";
@ -1631,23 +1625,23 @@ var objectexplorer = Object.copy(inputpanel, {
obj: undefined,
previous: [],
start() {
this.previous = [];
Input.setnuke();
},
on_close() { Input.setgame(); },
input_enter_pressed() {},
goto_obj(obj) {
if (obj === this.obj) return;
this.previous.push(this.obj);
this.obj = obj;
},
prev_obj() {
this.obj = this.previous.pop();
},
guibody() {
Nuke.label("Examining " + this.obj);
var items = [];
items.push(Mum.text({str:"Examining " + this.obj}));
var n = 0;
var curobj = this.obj;
@ -1657,23 +1651,14 @@ var objectexplorer = Object.copy(inputpanel, {
}
n--;
Nuke.newline(n);
curobj = this.obj.__proto__;
while (curobj) {
if (Nuke.button(curobj.toString()))
this.goto_obj(curobj);
items.push(Mum.text({str:curobj.toString(), action:this.goto_obj(curobj)}));
curobj = curobj.__proto__;
}
Nuke.newline(2);
if (this.previous.empty)
Nuke.label("");
else {
if (Nuke.button("prev: " + this.previous.last))
this.obj = this.previous.pop();
}
if (!this.previous.empty)
items.push(Mum.text({str:"prev: " + this.previous.last, action: this.prev_obj}));
Object.getOwnPropertyNames(this.obj).forEach(key => {
var descriptor = Object.getOwnPropertyDescriptor(this.obj, key);
@ -1688,70 +1673,52 @@ var objectexplorer = Object.copy(inputpanel, {
var name = (hidden ? "[hidden] " : "") + key;
var val = this.obj[key];
var nuke_str = key + "_nuke";
if (nuke_str in this.obj) {
this.obj[nuke_str]();
if (key in this.obj.__proto__) {
if (Nuke.button("delete " + key)) {
if (("_" + key) in this.obj)
delete this.obj["_"+key];
else
delete this.obj[key];
}
}
} else
switch (typeof val) {
case 'object':
if (val) {
if (Array.isArray(val)) {
this.obj[key] = Nuke.pprop(key,val);
// this.obj[key] = Nuke.pprop(key,val);
break;
}
Nuke.newline(2);
Nuke.label(name);
if (Nuke.button(val.toString())) this.goto_obj(val);
// Nuke.newline(2);
items.push(Mum.text({str:name}));
items.push(Mum.text({str:val.toString(), action: this.goto_obj.bind(val)}));
} else {
this.obj[key] = Nuke.pprop(key,val);
// this.obj[key] = Nuke.pprop(key,val);
}
break;
case 'function':
Nuke.newline(2);
Nuke.label(name);
Nuke.label("function");
items.push(Mum.text({str:name}));
items.push(Mum.text({str:"function"}));
break;
default:
if (!hidden) {// && Object.getOwnPropertyDescriptor(this.obj, key).writable) {
if (key.startsWith('_')) key = key.slice(1);
// this.obj[key] = Nuke.pprop(key, this.obj[key]);
this.obj[key] = Nuke.pprop(key, this.obj[key]);
if (key in this.obj.__proto__) {
/* if (key in this.obj.__proto__) {
if (Nuke.button("delete " + key)) {
if ("_"+key in this.obj)
delete this.obj["_"+key];
else
delete this.obj[key];
}
}
}*/
}
else {
Nuke.newline(2);
Nuke.label(name);
Nuke.label(val.toString());
items.push(Mum.text({str:name}));
items.push(Mum.text({str:val.toString()}));
}
break;
}
});
Nuke.newline();
Nuke.label("Properties that can be pulled in ...");
Nuke.newline(3);
items.push(Mum.text({str:"Properties that can be pulled in ..."}));
// Nuke.newline(3);
var pullprops = [];
for (var key in this.obj.__proto__) {
if (key.startsWith('_')) key = key.slice(1);
if (!this.obj.hasOwn(key)) {
if (typeof this.obj[key] === 'object' || typeof this.obj[key] === 'function') continue;
pullprops.push(key);
@ -1761,13 +1728,12 @@ var objectexplorer = Object.copy(inputpanel, {
pullprops = pullprops.sort();
pullprops.forEach(function(key) {
if (Nuke.button(key))
this.obj[key] = this.obj[key];
}, this);
items.push(Mum.text({str:key}));
// this.obj[key] = this.obj[key];
});
Game.objects.forEach(function(x) { x.sync(); });
Nuke.newline();
// Game.objects.forEach(function(x) { x.sync(); });
return items;
},
@ -1994,10 +1960,9 @@ limited_editor.inputs['M-p'] = function()
limited_editor.inputs['C-q'] = function()
{
Sound.killall();
Primum.clear();
editor.enter_editor();
Primum.clear_all();
editor.load_json(editor.stash);
Game.view_camera(editor.camera);
}
limited_editor.inputs['M-q'] = function()
@ -2013,10 +1978,10 @@ 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 */
editor.clear_level();
editor.camera = Game.camera;
Game.stop();
Game.editor_mode(true);
Debug.draw_phys(true);
editor.enter_editor();

View file

@ -601,6 +601,11 @@ var Game = {
this.objects[obj.body] = obj;
},
unregister_obj(obj) {
if (this.objects[obj.body] === obj)
this.objects[obj.body] = undefined;
},
/* Returns an object given an id */
object(id) {
return this.objects[id];

View file

@ -131,9 +131,9 @@ var gameobject = {
in_air() { return q_body(7, this.body);},
on_ground() { return !this.in_air(); },
spawn_from_instance(inst) {
var ur = prototypes.get_ur(inst.ur);
return this.spawn(inst.ur, inst);
},
spawn(ur, data) {
if (typeof ur === 'string')
ur = prototypes.get_ur(ur);
@ -380,19 +380,24 @@ var gameobject = {
// Register.endofloop(() => {
cmd(2, this.body);
delete Game.objects[this.body];
if (this.level)
Game.unregister_obj(this);
if (this.level) {
this.level.remove_obj(this);
this.level = undefined;
}
Player.uncontrol(this);
Register.unregister_obj(this);
this.instances.remove(this);
// this.instances.remove(this);
this.body = -1;
for (var key in this.components) {
Register.unregister_obj(this.components[key]);
this.components[key].kill();
this.components.gameobject = undefined;
}
delete this.components;
for (var key in this.objects)
this.objects[key].kill();
@ -406,13 +411,12 @@ var gameobject = {
down() { return [0,-1].rotate(Math.deg2rad(this.angle));},
right() { return [1,0].rotate(Math.deg2rad(this.angle));},
left() { return [-1,0].rotate(Math.deg2rad(this.angle));},
instances: [],
make(level, data) {
level ??= Primum;
var obj = Object.create(this);
obj.level = level;
this.instances.push(obj);
// this.instances.push(obj);
obj.body = make_gameobject();
obj.components = {};
obj.objects = {};
@ -441,33 +445,24 @@ var gameobject = {
}
};
if (this.objects) {
for (var prop in this.objects) {
var o = this.objects[prop];
var newobj = obj.spawn(o.ur, o);
if (!newobj) continue;
obj.rename_obj(newobj.toString(), prop);
}
}
if (this.objects)
obj.make_objs(this.objects);
Object.dainty_assign(obj, this);
obj.sync();
gameobject.check_registers(obj);
if (typeof obj.start === 'function') obj.start();
if (Game.playing() && typeof obj.start === 'function') obj.start();
return obj;
},
make_objs(objs) {
for (var prop in objs) {
var o = objs[prop];
var newobj = this.spawn(o.ur, o);
var newobj = this.spawn_from_instance(objs[prop]);
if (!newobj) continue;
this.rename_obj(newobj.toString(), prop);
Log.warn(`setting object ${prop} to ${JSON.stringify(o)}`);
// Object.assign(newobj,o);
}
},

View file

@ -153,9 +153,9 @@ var Player = {
if (typeof fn === 'function') {
fn.call(pawn, ... args);
pawn.inputs.post?.call(pawn);
if (!pawn.inputs.fallthru)
return;
}
if (!pawn.inputs.fallthru) return;
}
},

View file

@ -20,7 +20,7 @@ var Sound = {
sounds: [], /* array of loaded sound files */
play(file) {
if (!IO.exists(file)) {
Log.warn(`Cannot play sound ${file}: does not exist.`);
Log.error(`Cannot play sound ${file}: does not exist.`);
return;
}
this.id = cmd(14,file);

View file

@ -607,8 +607,10 @@ struct postphys_cb {
static struct postphys_cb *begins = NULL;
void flush_collide_cbs() {
for (int i = 0; i < arrlen(begins); i++)
for (int i = 0; i < arrlen(begins); i++) {
script_callee(begins[i].c, 1, &begins[i].send);
JS_FreeValue(js, begins[i].send);
}
arrsetlen(begins,0);
}