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