Simplify reparenting; fix deleting objects and copying objects
This commit is contained in:
parent
58d4132f4d
commit
9a1f1408a6
|
@ -62,9 +62,24 @@ Object.dainty_assign = function(target, source)
|
|||
}
|
||||
}
|
||||
|
||||
Object.containingKey = function(obj, prop)
|
||||
{
|
||||
if (typeof obj !== 'object') return undefined;
|
||||
if (!(prop in obj)) return undefined;
|
||||
|
||||
var o = obj;
|
||||
while (o.__proto__ && !Object.hasOwn(o, prop))
|
||||
o = o.__proto__;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
Object.isAccessor = function(obj, prop)
|
||||
{
|
||||
var desc = Object.getOwnPropertyDescriptor(obj,prop);
|
||||
var o = Object.containingKey(obj,prop);
|
||||
if (!o) return false;
|
||||
|
||||
var desc = Object.getOwnPropertyDescriptor(o,prop);
|
||||
if (!desc) return false;
|
||||
if (desc.get || desc.set) return true;
|
||||
return false;
|
||||
|
@ -78,6 +93,7 @@ Object.mergekey = function(o1,o2,k)
|
|||
if (Array.isArray(o2[k]))
|
||||
o1[k] = o2[k].slice();
|
||||
else {
|
||||
if (!o1[k]) o1[k] = {};
|
||||
Object.merge(o1[k], o2[k]);
|
||||
}
|
||||
} else
|
||||
|
|
|
@ -34,7 +34,8 @@ component.sprite = {
|
|||
toString() { return "sprite"; },
|
||||
make(go) {
|
||||
var nsprite = Object.create(component.sprite.maker);
|
||||
Object.assign(nsprite, make_sprite(go));
|
||||
nsprite.gameobject = go;
|
||||
Object.assign(nsprite, make_sprite(go.body));
|
||||
nsprite.ur = this;
|
||||
return nsprite;
|
||||
},
|
||||
|
@ -108,7 +109,7 @@ var aseframeset2anim = function(frameset, meta)
|
|||
};
|
||||
|
||||
frameset.forEach(ase_make_frame);
|
||||
|
||||
anim.dim = [frameset[0].sourceSize.x, frameset[0].sourceSize.y];
|
||||
anim.loop = true;
|
||||
return anim;
|
||||
}
|
||||
|
@ -153,6 +154,9 @@ var gif2anim = function(gif)
|
|||
anim.frames.push(frame);
|
||||
}
|
||||
anim.loop = true;
|
||||
var dim = cmd(64,gif);
|
||||
dim.y /= frames;
|
||||
anim.dim = dim;
|
||||
return anim;
|
||||
}
|
||||
|
||||
|
@ -169,6 +173,8 @@ var strip2anim = function(strip)
|
|||
frame.time = 0.05;
|
||||
anim.frames.push(frame);
|
||||
}
|
||||
anim.dim = cmd(64,strip);
|
||||
anim.dim.x /= frames;
|
||||
return anim;
|
||||
}
|
||||
|
||||
|
@ -183,13 +189,11 @@ component.char2d = Object.copy(sprite, {
|
|||
get layer() { return this.gameobject.draw_layer; },
|
||||
|
||||
boundingbox() {
|
||||
var dim = cmd(64,this.path);
|
||||
var dim = this.curplaying.dim.slice();
|
||||
dim = dim.scale(this.gameobject.scale);
|
||||
var realpos = [0,0];
|
||||
// var realpos = this.pos.slice();
|
||||
|
||||
// realpos.x = realpos.x * dim.x + (dim.x/2);
|
||||
// realpos.y = realpos.y * dim.y + (dim.y/2);
|
||||
var realpos = this.pos.slice();
|
||||
realpos.x = realpos.x * dim.x + (dim.x/2);
|
||||
realpos.y = realpos.y * dim.y + (dim.y/2);
|
||||
return cwh2bb(realpos,dim);
|
||||
},
|
||||
|
||||
|
@ -205,7 +209,8 @@ component.char2d = Object.copy(sprite, {
|
|||
|
||||
make(go) {
|
||||
var char = Object.create(this);
|
||||
Object.assign(char, make_sprite(go));
|
||||
char.gameobject = go;
|
||||
Object.assign(char, make_sprite(go.body));
|
||||
char.frame = 0;
|
||||
char.timer = timer.make(char.advance.bind(char), 1);
|
||||
char.timer.loop = true;
|
||||
|
@ -329,7 +334,8 @@ component.polygon2d = Object.copy(collider2d, {
|
|||
|
||||
make(go) {
|
||||
var poly = Object.create(this);
|
||||
Object.assign(poly, make_poly2d(go, this.points));
|
||||
poly.gameobject = go;
|
||||
Object.assign(poly, make_poly2d(go.body, this.points));
|
||||
poly.defn('points', this.points.copy());
|
||||
|
||||
poly.sync();
|
||||
|
@ -502,7 +508,8 @@ component.bucket = Object.copy(collider2d, {
|
|||
|
||||
make(go) {
|
||||
var edge = Object.create(this);
|
||||
Object.assign(edge, make_edge2d(go, this.points, this.thickness));
|
||||
edge.gameobject = go;
|
||||
Object.assign(edge, make_edge2d(go.body, this.points, this.thickness));
|
||||
Object.assign(edge, {
|
||||
set thickness(x) {
|
||||
cmd_edge2d(1,this.id,x);
|
||||
|
@ -682,7 +689,8 @@ component.circle2d = Object.copy(collider2d, {
|
|||
|
||||
make(go) {
|
||||
var circle = Object.create(this);
|
||||
Object.assign(circle, make_circle2d(go, circle.radius, circle.offset));
|
||||
circle.gameobject = go;
|
||||
Object.assign(circle, make_circle2d(go.body, circle.radius, circle.offset));
|
||||
return circle;
|
||||
},
|
||||
|
||||
|
|
|
@ -498,6 +498,7 @@ return;
|
|||
GUI.text(lvlstr, [0, ypos], 1, ColorMap.Inferno.sample(lvlcolorsample));
|
||||
lvlcolorsample -= 0.1;
|
||||
|
||||
if (!clvl.level) break;
|
||||
clvl = clvl.level;
|
||||
if (clvl) {
|
||||
GUI.text("^^^^^^", [0,ypos-15],1);
|
||||
|
@ -990,6 +991,7 @@ editor.inputs['C-f1'].doc = "Enter basic edit mode.";
|
|||
editor.inputs['C-f2'] = function() { editor.edit_mode = "brush"; };
|
||||
editor.inputs['C-f2'].doc = "Enter brush mode.";
|
||||
|
||||
|
||||
editor.inputs.f2 = function() {
|
||||
objectexplorer.on_close = save_configs;
|
||||
objectexplorer.obj = configs;
|
||||
|
|
|
@ -567,7 +567,9 @@ var ur_json = function()
|
|||
return ret;
|
||||
}
|
||||
|
||||
return objdiff(this, this.ur);
|
||||
var ur = objdiff(this,this.ur);
|
||||
|
||||
return ur ? ur : {};
|
||||
}
|
||||
|
||||
|
||||
|
@ -744,13 +746,13 @@ Register.update.register(Game.exec, Game);
|
|||
load("scripts/entity.js");
|
||||
|
||||
var preprimum = {};
|
||||
preprimum.add_child = function() {};
|
||||
preprimum.objects = [];
|
||||
var World = gameobject.make(gameobject.ur, preprimum);
|
||||
var Primum = World;
|
||||
Primum.level = undefined;
|
||||
Primum.toString = function() { return "Primum"; };
|
||||
Primum.selectable = false;
|
||||
World.reparent = function(parent) { Log.warn("Cannot reparent the Primum."); }
|
||||
World.unparent = function() { Log.warn("The Primum has no parent, always."); }
|
||||
|
||||
/* Load configs */
|
||||
function load_configs(file) {
|
||||
|
|
|
@ -187,7 +187,8 @@ var gameobject = {
|
|||
set pos(x) {
|
||||
var diff = x.sub(this.pos);
|
||||
this.objects.forEach(function(x) { x.pos = x.pos.add(diff); });
|
||||
set_body(2,this.body,x); },
|
||||
set_body(2,this.body,x);
|
||||
},
|
||||
get pos() { return q_body(1,this.body); },
|
||||
|
||||
get angle() { return Math.rad2deg(q_body(2,this.body))%360; },
|
||||
|
@ -244,7 +245,6 @@ var gameobject = {
|
|||
return gameobject.make(ur, this);
|
||||
},
|
||||
|
||||
|
||||
/* Bounding box of the object in world dimensions */
|
||||
boundingbox() {
|
||||
var boxes = [];
|
||||
|
@ -254,6 +254,8 @@ var gameobject = {
|
|||
if ('boundingbox' in this.components[key])
|
||||
boxes.push(this.components[key].boundingbox());
|
||||
}
|
||||
for (var key in this.$)
|
||||
boxes.push(this.$[key].boundingbox());
|
||||
|
||||
if (boxes.empty) return cwh2bb([0,0], [0,0]);
|
||||
|
||||
|
@ -276,9 +278,45 @@ var gameobject = {
|
|||
return bb ? bb : cwh2bb([0,0], [0,0]);
|
||||
},
|
||||
|
||||
json_obj() {
|
||||
function objdiff(from, to) {
|
||||
if (!to) return from; // Everything on from is unique
|
||||
var ret = {};
|
||||
|
||||
for (var key in from) {
|
||||
if (!from[key] || !to[key]) continue;
|
||||
if (typeof from[key] === 'function') continue;
|
||||
if (typeof to === 'object' && !(key in to)) continue;
|
||||
|
||||
if (typeof from[key] === 'object') {
|
||||
if ('ur' in from[key]) {
|
||||
var urdiff = objdiff(from[key],from[key].ur);
|
||||
if (urdiff && !urdiff.empty) ret[key] = urdiff;
|
||||
continue;
|
||||
}
|
||||
var diff = objdiff(from[key], to[key]);
|
||||
if (diff && !diff.empty) ret[key] = diff;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (from[key] !== to[key])
|
||||
ret[key] = from[key];
|
||||
}
|
||||
if (ret.empty) return undefined;
|
||||
return ret;
|
||||
}
|
||||
|
||||
var ur = objdiff(this,this.ur);
|
||||
|
||||
return ur ? ur : {};
|
||||
},
|
||||
|
||||
dup(diff) {
|
||||
var dup = Primum.spawn(this.__proto__);
|
||||
Object.assign(dup, this);
|
||||
var dup = this.level.spawn(this.ur);
|
||||
var thisur = this.json_obj();
|
||||
thisur.pos = this.pos;
|
||||
thisur.angle = this.angle;
|
||||
Object.totalmerge(dup, thisur);
|
||||
return dup;
|
||||
},
|
||||
|
||||
|
@ -307,31 +345,40 @@ var gameobject = {
|
|||
}
|
||||
|
||||
this.objects.forEach(x => x.kill());
|
||||
|
||||
this.stop();
|
||||
if (typeof this.stop === 'function')
|
||||
this.stop();
|
||||
});
|
||||
},
|
||||
|
||||
up() { return [0,1].rotate(Math.deg2rad(this.angle));},
|
||||
// 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));},
|
||||
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));},
|
||||
reparent(parent) {
|
||||
if (this.level === parent) return;
|
||||
parent.objects.push(this);
|
||||
|
||||
if (this.level)
|
||||
this.level.objects.remove(this);
|
||||
this.level = parent;
|
||||
},
|
||||
|
||||
make(ur, level) {
|
||||
level ??= Primum;
|
||||
var obj = Object.create(gameobject);
|
||||
obj.defn('body', make_gameobject());
|
||||
obj.defn('components', {});
|
||||
obj.body = make_gameobject();
|
||||
obj.components = {};
|
||||
obj.objects = [];
|
||||
|
||||
Game.register_obj(obj);
|
||||
gameobject.make_parentable(obj);
|
||||
|
||||
cmd(113, obj.body, obj); // set the internal obj reference to this obj
|
||||
|
||||
obj.$ = {};
|
||||
obj.ur = ur;
|
||||
|
||||
level.add_child(obj);
|
||||
obj.reparent(level);
|
||||
|
||||
for (var prop in ur) {
|
||||
var p = ur[prop];
|
||||
if (typeof p !== 'object') continue;
|
||||
|
@ -340,16 +387,16 @@ var gameobject = {
|
|||
obj[prop] = obj.spawn(prototypes.get_ur(p.ur));
|
||||
obj.$[prop] = obj[prop];
|
||||
} else if ('make' in p) {
|
||||
obj[prop] = p.make(obj.body);
|
||||
obj[prop] = p.make(obj);
|
||||
obj.components[prop] = obj[prop];
|
||||
} else if ('comp' in p) {
|
||||
obj[prop] = component[p.comp].make(obj.body);
|
||||
obj[prop] = component[p.comp].make(obj);
|
||||
obj.components[prop] = obj[prop];
|
||||
}
|
||||
};
|
||||
|
||||
Object.totalmerge(obj,ur);
|
||||
obj.check_registers(obj);
|
||||
obj.check_registers(obj);
|
||||
|
||||
if (typeof obj.start === 'function') obj.start();
|
||||
|
||||
|
@ -387,37 +434,6 @@ gameobject.ur = {
|
|||
layer: 0,
|
||||
};
|
||||
|
||||
gameobject.make_parentable = function(obj) {
|
||||
var objects = [];
|
||||
Object.defHidden(obj, 'level');
|
||||
|
||||
obj.remove_child = function(child) {
|
||||
objects.remove(child);
|
||||
}
|
||||
|
||||
obj.add_child = function(child) {
|
||||
child.unparent();
|
||||
objects.push(child);
|
||||
child.level = obj;
|
||||
}
|
||||
|
||||
/* Reparent this object to a new one */
|
||||
obj.reparent = function(parent) {
|
||||
if (parent === obj.level)
|
||||
return;
|
||||
|
||||
parent.add_child(obj);
|
||||
obj.level = parent;
|
||||
}
|
||||
|
||||
obj.unparent = function() {
|
||||
if (!obj.level) return;
|
||||
obj.level.remove_child(obj);
|
||||
obj.parent = undefined;
|
||||
}
|
||||
obj.objects = objects;
|
||||
}
|
||||
|
||||
gameobject.entity = {};
|
||||
|
||||
/* Default objects */
|
||||
|
|
|
@ -25,6 +25,7 @@ char *catstr[] = {"engine", "script", "render"};
|
|||
|
||||
FILE *logfile = NULL;
|
||||
|
||||
#define ERROR_BUFFER 1024
|
||||
#define CONSOLE_BUF 1024*1024*5 /* 5MB */
|
||||
|
||||
char *lastlog;
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define ERROR_BUFFER 1024
|
||||
|
||||
#define LOG_INFO 0
|
||||
#define LOG_WARN 1
|
||||
#define LOG_ERROR 2
|
||||
|
|
Loading…
Reference in a new issue