Separate entity from rigidbody
This commit is contained in:
parent
e86e126894
commit
79e4772f93
|
@ -177,7 +177,7 @@ Object.mixin(os.sprite(true), {
|
||||||
height() { return this.dimensions().y; },
|
height() { return this.dimensions().y; },
|
||||||
});
|
});
|
||||||
globalThis.allsprites = {};
|
globalThis.allsprites = {};
|
||||||
os.sprite(true).make = function(go)
|
os.sprite().make = function(go)
|
||||||
{
|
{
|
||||||
var sp = os.sprite();
|
var sp = os.sprite();
|
||||||
sp.go = go;
|
sp.go = go;
|
||||||
|
|
|
@ -344,7 +344,7 @@ var editor = {
|
||||||
root = root ? root + "." : root;
|
root = root ? root + "." : root;
|
||||||
Object.entries(obj.objects).forEach(function(x) {
|
Object.entries(obj.objects).forEach(function(x) {
|
||||||
var p = root + x[0];
|
var p = root + x[0];
|
||||||
render.text(p, x[1].screenpos(), 1, editor.color_depths[depth]);
|
render.text(p, x[1].this2screen(), 1, editor.color_depths[depth]);
|
||||||
editor.draw_objects_names(x[1], p, depth+1);
|
editor.draw_objects_names(x[1], p, depth+1);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -402,7 +402,7 @@ var editor = {
|
||||||
if (this.comp_info && this.sel_comp)
|
if (this.comp_info && this.sel_comp)
|
||||||
render.text(input.print_pawn_kbm(this.sel_comp,false), [100,700],1);
|
render.text(input.print_pawn_kbm(this.sel_comp,false), [100,700],1);
|
||||||
|
|
||||||
render.cross(editor.edit_level.screenpos(),3,Color.blue);
|
render.cross(editor.edit_level.this2screen(),3,Color.blue);
|
||||||
|
|
||||||
var thiso = editor.get_this();
|
var thiso = editor.get_this();
|
||||||
var clvl = thiso;
|
var clvl = thiso;
|
||||||
|
@ -447,16 +447,16 @@ var editor = {
|
||||||
render.text("$$$$$$", [0,ypos],1,editor.color_depths[depth]);
|
render.text("$$$$$$", [0,ypos],1,editor.color_depths[depth]);
|
||||||
|
|
||||||
this.selectlist.forEach(function(x) {
|
this.selectlist.forEach(function(x) {
|
||||||
render.text(x.urstr(), x.screenpos().add([0, render.font.linegap*2]), 1, Color.editor.ur);
|
render.text(x.urstr(), x.this2screen().add([0, render.font.linegap*2]), 1, Color.editor.ur);
|
||||||
render.text(x.pos.map(function(x) { return Math.round(x); }), x.screenpos());
|
render.text(x.pos.map(function(x) { return Math.round(x); }), x.this2screen());
|
||||||
render.cross(x.screenpos(), 10, Color.blue);
|
render.cross(x.this2screen(), 10, Color.blue);
|
||||||
});
|
});
|
||||||
|
|
||||||
Object.entries(thiso.objects).forEach(function(x) {
|
Object.entries(thiso.objects).forEach(function(x) {
|
||||||
var p = x[1].namestr();
|
var p = x[1].namestr();
|
||||||
render.text(p, x[1].screenpos().add([0,render.font.linegap]),1,editor.color_depths[depth]);
|
render.text(p, x[1].this2screen().add([0,render.font.linegap]),1,editor.color_depths[depth]);
|
||||||
render.point(x[1].screenpos(),5,Color.blue.alpha(0.3));
|
render.point(x[1].this2screen(),5,Color.blue.alpha(0.3));
|
||||||
render.point(x[1].screenpos(), 1, Color.red);
|
render.point(x[1].this2screen(), 1, Color.red);
|
||||||
});
|
});
|
||||||
|
|
||||||
var mg = physics.pos_query(input.mouse.worldpos());
|
var mg = physics.pos_query(input.mouse.worldpos());
|
||||||
|
@ -474,7 +474,7 @@ var editor = {
|
||||||
for (var key in this.selectlist[0].components) {
|
for (var key in this.selectlist[0].components) {
|
||||||
var selected = this.sel_comp === this.selectlist[0].components[key];
|
var selected = this.sel_comp === this.selectlist[0].components[key];
|
||||||
var str = (selected ? ">" : " ") + key + " [" + this.selectlist[0].components[key].toString() + "]";
|
var str = (selected ? ">" : " ") + key + " [" + this.selectlist[0].components[key].toString() + "]";
|
||||||
render.text(str, this.selectlist[0].screenpos().add([0,-render.font.linegap*(i++)]));
|
render.text(str, this.selectlist[0].this2screen().add([0,-render.font.linegap*(i++)]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.sel_comp) {
|
if (this.sel_comp) {
|
||||||
|
@ -879,7 +879,7 @@ editor.inputs['C-s'] = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var savejs = saveobj.json_obj();
|
var savejs = saveobj.json_obj();
|
||||||
var tur = saveobj.get_ur();
|
var tur = saveobj.ur;
|
||||||
if (!tur) {
|
if (!tur) {
|
||||||
console.warn(`Can't save object because it has no ur.`);
|
console.warn(`Can't save object because it has no ur.`);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -289,7 +289,6 @@ game.engine_start = function(s) {
|
||||||
gggstart(function() {
|
gggstart(function() {
|
||||||
global.mixin("scripts/sound.js");
|
global.mixin("scripts/sound.js");
|
||||||
world_start();
|
world_start();
|
||||||
go_init();
|
|
||||||
window.set_icon(os.make_texture("icons/moon.gif"))
|
window.set_icon(os.make_texture("icons/moon.gif"))
|
||||||
Object.readonly(window.__proto__, 'vsync');
|
Object.readonly(window.__proto__, 'vsync');
|
||||||
Object.readonly(window.__proto__, 'enable_dragndrop');
|
Object.readonly(window.__proto__, 'enable_dragndrop');
|
||||||
|
@ -330,9 +329,9 @@ function process()
|
||||||
}
|
}
|
||||||
var st = profile.now();
|
var st = profile.now();
|
||||||
if (!game.camera)
|
if (!game.camera)
|
||||||
prosperon.window_render(world, 1);
|
prosperon.window_render(world.transform, 1);
|
||||||
else
|
else
|
||||||
prosperon.window_render(game.camera, game.camera.zoom);
|
prosperon.window_render(game.camera.transform, game.camera.zoom);
|
||||||
|
|
||||||
render.set_camera();
|
render.set_camera();
|
||||||
|
|
||||||
|
@ -627,7 +626,8 @@ global.mixin("scripts/actor");
|
||||||
global.mixin("scripts/entity");
|
global.mixin("scripts/entity");
|
||||||
|
|
||||||
function world_start() {
|
function world_start() {
|
||||||
globalThis.world = os.make_gameobject();
|
globalThis.world = Object.create(entity);
|
||||||
|
world.transform = os.make_transform2d();
|
||||||
world.objects = {};
|
world.objects = {};
|
||||||
world.toString = function() { return "world"; };
|
world.toString = function() { return "world"; };
|
||||||
world.ur = "world";
|
world.ur = "world";
|
||||||
|
|
|
@ -12,16 +12,398 @@ function obj_unique_name(name, obj) {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
var gameobject = {
|
function unique_name(list, name = "new_object") {
|
||||||
|
var str = name.replaceAll('.', '_');
|
||||||
|
var n = 1;
|
||||||
|
var t = str;
|
||||||
|
while (list.indexOf(t) !== -1) {
|
||||||
|
t = str + n;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
};
|
||||||
|
|
||||||
|
var entity = {
|
||||||
get_comp_by_name(name) {
|
get_comp_by_name(name) {
|
||||||
var comps = [];
|
var comps = [];
|
||||||
for (var c of Object.values(this.components))
|
for (var c of Object.values(this.components))
|
||||||
if (c.comp === name) comps.push(c);
|
if (c.comp === name) comps.push(c);
|
||||||
|
|
||||||
if (comps.length) return comps;
|
if (comps.length) return comps;
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
path_from(o) {
|
||||||
|
var p = this.toString();
|
||||||
|
var c = this.master;
|
||||||
|
while (c && c !== o && c !== world) {
|
||||||
|
p = c.toString() + "." + p;
|
||||||
|
c = c.master;
|
||||||
|
}
|
||||||
|
if (c === world) p = "world." + p;
|
||||||
|
return p;
|
||||||
|
},
|
||||||
|
|
||||||
|
full_path() { return this.path_from(world); },
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
for (var k in this.objects) {
|
||||||
|
this.objects[k].kill();
|
||||||
|
};
|
||||||
|
this.objects = {};
|
||||||
|
},
|
||||||
|
|
||||||
|
sync() {
|
||||||
|
this.components.forEach(function(x) { x.sync?.(); });
|
||||||
|
this.objects.forEach(function(x) { x.sync(); });
|
||||||
|
},
|
||||||
|
|
||||||
|
delay(fn, seconds) {
|
||||||
|
var timers = this.timers;
|
||||||
|
var stop = function() {
|
||||||
|
timers.remove(stop);
|
||||||
|
execute = undefined;
|
||||||
|
stop = undefined;
|
||||||
|
rm?.();
|
||||||
|
rm = undefined;
|
||||||
|
update = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function execute() {
|
||||||
|
fn();
|
||||||
|
stop?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
stop.remain = seconds;
|
||||||
|
stop.seconds = seconds;
|
||||||
|
stop.pct = function() { return 1 - (stop.remain/stop.seconds); };
|
||||||
|
|
||||||
|
function update(dt) {
|
||||||
|
stop.remain -= dt;
|
||||||
|
if (stop.remain <= 0) execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
var rm = Register.update.register(update);
|
||||||
|
timers.push(stop);
|
||||||
|
return stop;
|
||||||
|
},
|
||||||
|
|
||||||
|
cry(file) { return audio.cry(file); },
|
||||||
|
|
||||||
|
get pos() { return this.transform.pos; },
|
||||||
|
set pos(x) { this.transform.pos = x; },
|
||||||
|
get angle() { return this.transform.angle; },
|
||||||
|
set angle(x) { this.transform.angle = x; },
|
||||||
|
get scale() { return this.transform.scale; },
|
||||||
|
set scale(x) { this.transform.scale = x; },
|
||||||
|
|
||||||
|
move(vec) { this.pos = this.pos.add(vec); },
|
||||||
|
rotate(x) { this.angle += x; },
|
||||||
|
grow(vec) {
|
||||||
|
if (typeof vec === 'number') vec = [vec,vec];
|
||||||
|
this.scale = this.scale.map((x,i) => x*vec[i]);
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Reparent 'this' to be 'parent's child */
|
||||||
|
reparent(parent) {
|
||||||
|
assert(parent, `Tried to reparent ${this.toString()} to nothing.`);
|
||||||
|
console.spam(`parenting ${this.toString()} to ${parent.toString()}`);
|
||||||
|
if (this.master === parent) {
|
||||||
|
console.warn("not reparenting ...");
|
||||||
|
console.warn(`${this.master} is the same as ${parent}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = unique_name(Object.keys(parent), this.name);
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
|
this.master?.remove_obj(this);
|
||||||
|
this.master = parent;
|
||||||
|
parent.objects[this.guid] = this;
|
||||||
|
parent[name] = this;
|
||||||
|
Object.hide(parent, name);
|
||||||
|
},
|
||||||
|
|
||||||
|
remove_obj(obj) {
|
||||||
|
delete this.objects[obj.guid];
|
||||||
|
delete this[obj.name];
|
||||||
|
Object.unhide(this, obj.name);
|
||||||
|
},
|
||||||
|
|
||||||
|
spawn(text, config, callback) {
|
||||||
|
var st = profile.now();
|
||||||
|
var ent = Object.create(entity);
|
||||||
|
ent.transform = os.make_transform2d();
|
||||||
|
|
||||||
|
ent.guid = prosperon.guid();
|
||||||
|
|
||||||
|
ent.components = {};
|
||||||
|
ent.objects = {};
|
||||||
|
ent.timers = [];
|
||||||
|
|
||||||
|
if (!text)
|
||||||
|
ent.ur = emptyur;
|
||||||
|
else if (typeof text === 'object' && text) {// assume it's an ur
|
||||||
|
ent.ur = text;
|
||||||
|
text = ent.ur.text;
|
||||||
|
config = [ent.ur.data, config].filter(x => x).flat();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ent.ur = getur(text, config);
|
||||||
|
text = ent.ur.text;
|
||||||
|
config = [ent.ur.data, config];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof text === 'string')
|
||||||
|
use(text, ent);
|
||||||
|
else if (Array.isArray(text))
|
||||||
|
text.forEach(path => use(path,ent));
|
||||||
|
|
||||||
|
if (typeof config === 'string')
|
||||||
|
Object.merge(ent, json.decode(Resources.replstrs(config)));
|
||||||
|
else if (Array.isArray(config))
|
||||||
|
config.forEach(function(path) {
|
||||||
|
if (typeof path === 'string') {
|
||||||
|
console.info(`ingesting ${path} ...`);
|
||||||
|
Object.merge(ent, json.decode(Resources.replstrs(path)));
|
||||||
|
}
|
||||||
|
else if (typeof path === 'object')
|
||||||
|
Object.merge(ent,path);
|
||||||
|
});
|
||||||
|
|
||||||
|
ent.reparent(this);
|
||||||
|
|
||||||
|
for (var [prop, p] of Object.entries(ent)) {
|
||||||
|
if (!p) continue;
|
||||||
|
if (typeof p !== 'object') continue;
|
||||||
|
if (component.isComponent(p)) continue;
|
||||||
|
if (!p.comp) continue;
|
||||||
|
ent[prop] = component[p.comp].make(ent);
|
||||||
|
Object.merge(ent[prop], p);
|
||||||
|
ent.components[prop] = ent[prop];
|
||||||
|
};
|
||||||
|
|
||||||
|
check_registers(ent);
|
||||||
|
|
||||||
|
if (typeof ent.load === 'function') ent.load();
|
||||||
|
if (sim.playing())
|
||||||
|
if (typeof ent.start === 'function') ent.start();
|
||||||
|
|
||||||
|
Object.hide(ent, 'ur', 'components', 'objects', 'timers', 'guid', 'master');
|
||||||
|
|
||||||
|
ent._ed = {
|
||||||
|
selectable: true,
|
||||||
|
dirty: false,
|
||||||
|
inst: false,
|
||||||
|
urdiff: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.hide(ent, '_ed');
|
||||||
|
|
||||||
|
ent.sync();
|
||||||
|
|
||||||
|
if (!Object.empty(ent.objects)) {
|
||||||
|
var o = ent.objects;
|
||||||
|
delete ent.objects;
|
||||||
|
ent.objects = {};
|
||||||
|
for (var i in o) {
|
||||||
|
console.info(`creating ${i} on ${ent.toString()}`);
|
||||||
|
var newur = o[i].ur;
|
||||||
|
delete o[i].ur;
|
||||||
|
var n = ent.spawn(ur[newur], o[i]);
|
||||||
|
ent.rename_obj(n.toString(), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ent.tag) game.tag_add(ent.tag, ent);
|
||||||
|
|
||||||
|
if (callback) callback(ent);
|
||||||
|
|
||||||
|
|
||||||
|
ent.ur.fresh ??= json.decode(json.encode(ent));
|
||||||
|
ent.ur.fresh.objects = {};
|
||||||
|
for (var i in ent.objects)
|
||||||
|
ent.ur.fresh.objects[i] = ent.objects[i].instance_obj();
|
||||||
|
|
||||||
|
profile.addreport(entityreport, ent.ur.name, st);
|
||||||
|
return ent;
|
||||||
|
},
|
||||||
|
|
||||||
|
disable() { this.components.forEach(function(x) { x.disable(); }); },
|
||||||
|
enable() { this.components.forEach(function(x) { x.enable(); }); },
|
||||||
|
|
||||||
|
this2screen(pos) { return game.camera.world2view(this.this2world(pos)); },
|
||||||
|
screen2this(pos) { return this.world2this(game.camera.view2world(pos)); },
|
||||||
|
|
||||||
|
/* Make a unique object the same as its prototype */
|
||||||
|
revert() { Object.merge(this, this.ur.fresh); },
|
||||||
|
|
||||||
|
name: "new_object",
|
||||||
|
toString() { return this.name; },
|
||||||
|
width() {
|
||||||
|
var bb = this.boundingbox();
|
||||||
|
return bb.r - bb.l;
|
||||||
|
},
|
||||||
|
|
||||||
|
height() {
|
||||||
|
var bb = this.boundingbox();
|
||||||
|
return bb.t - bb.b;
|
||||||
|
},
|
||||||
|
|
||||||
|
flipx() { return this.scale.x < 0; },
|
||||||
|
flipy() { return this.scale.y < 0; },
|
||||||
|
|
||||||
|
mirror(plane) { this.scale = Vector.reflect(this.scale, plane); },
|
||||||
|
|
||||||
|
/* Bounding box of the object in world dimensions */
|
||||||
|
boundingbox() {
|
||||||
|
var boxes = [];
|
||||||
|
boxes.push({
|
||||||
|
t: 0,
|
||||||
|
r: 0,
|
||||||
|
b: 0,
|
||||||
|
l: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var key in this.components) {
|
||||||
|
if ('boundingbox' in this.components[key])
|
||||||
|
boxes.push(this.components[key].boundingbox());
|
||||||
|
}
|
||||||
|
for (var key in this.objects)
|
||||||
|
boxes.push(this.objects[key].boundingbox());
|
||||||
|
|
||||||
|
var bb = boxes.shift();
|
||||||
|
|
||||||
|
boxes.forEach(function(x) { bb = bbox.expand(bb, x); });
|
||||||
|
|
||||||
|
bb = bbox.move(bb, this.pos);
|
||||||
|
|
||||||
|
return bb ? bb : bbox.fromcwh([0, 0], [0, 0]);
|
||||||
|
},
|
||||||
|
|
||||||
|
/* The unique components of this object. Its diff. */
|
||||||
|
json_obj(depth=0) {
|
||||||
|
var fresh = this.ur.fresh;
|
||||||
|
var thiso = json.decode(json.encode(this)); // TODO: SLOW. Used to ignore properties in toJSON of components.
|
||||||
|
var d = ediff(thiso, fresh);
|
||||||
|
|
||||||
|
d ??= {};
|
||||||
|
|
||||||
|
fresh.objects ??= {};
|
||||||
|
var curobjs = {};
|
||||||
|
for (var o in this.objects)
|
||||||
|
curobjs[o] = this.objects[o].instance_obj();
|
||||||
|
|
||||||
|
var odiff = ediff(curobjs, fresh.objects);
|
||||||
|
if (odiff)
|
||||||
|
d.objects = curobjs;
|
||||||
|
|
||||||
|
delete d.pos;
|
||||||
|
delete d.angle;
|
||||||
|
delete d.scale;
|
||||||
|
delete d.velocity;
|
||||||
|
delete d.angularvelocity;
|
||||||
|
return d;
|
||||||
|
},
|
||||||
|
|
||||||
|
/* The object needed to store an object as an instance of a master */
|
||||||
|
instance_obj() {
|
||||||
|
var t = this.transform();
|
||||||
|
t.ur = this.ur.name;
|
||||||
|
return t;
|
||||||
|
},
|
||||||
|
|
||||||
|
transform() {
|
||||||
|
var t = {};
|
||||||
|
t.pos = this.get_pos(this.master).map(x => Math.places(x, 0));
|
||||||
|
t.angle = Math.places(this.get_angle(this.master), 4);
|
||||||
|
t.scale = this.get_scale(this.master).map(x => Math.places(x, 2));;
|
||||||
|
return t;
|
||||||
|
},
|
||||||
|
|
||||||
|
dup(diff) {
|
||||||
|
var n = this.master.spawn(this.ur);
|
||||||
|
Object.totalmerge(n, this.transform());
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
|
||||||
|
kill() {
|
||||||
|
if (this.__kill) return;
|
||||||
|
this.__kill = true;
|
||||||
|
console.spam(`Killing entity of type ${this.ur}`);
|
||||||
|
|
||||||
|
this.timers.forEach(t => t());
|
||||||
|
this.timers = [];
|
||||||
|
Event.rm_obj(this);
|
||||||
|
input.do_uncontrol(this);
|
||||||
|
|
||||||
|
if (this.master) {
|
||||||
|
this.master.remove_obj(this);
|
||||||
|
this.master = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var key in this.components) {
|
||||||
|
this.components[key].kill?.();
|
||||||
|
this.components[key].gameobject = undefined;
|
||||||
|
this[key].enabled = false;
|
||||||
|
delete this.components[key];
|
||||||
|
delete this[key];
|
||||||
|
}
|
||||||
|
delete this.components;
|
||||||
|
|
||||||
|
this.clear();
|
||||||
|
if (typeof this.stop === 'function') this.stop();
|
||||||
|
|
||||||
|
game.tag_clear_guid(this.guid);
|
||||||
|
|
||||||
|
for (var i in this) {
|
||||||
|
if (typeof this[i] === 'object') delete this[i];
|
||||||
|
if (typeof this[i] === 'function') delete this[i];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
make_objs(objs) {
|
||||||
|
for (var prop in objs) {
|
||||||
|
say(`spawning ${json.encode(objs[prop])}`);
|
||||||
|
var newobj = this.spawn(objs[prop]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
rename_obj(name, newname) {
|
||||||
|
if (!this.objects[name]) {
|
||||||
|
console.warn(`No object with name ${name}. Could not rename to ${newname}.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (name === newname) {
|
||||||
|
Object.hide(this, name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.objects[newname])
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.objects[newname] = this.objects[name];
|
||||||
|
this[newname] = this[name];
|
||||||
|
this[newname].toString = function() { return newname; };
|
||||||
|
Object.hide(this, newname);
|
||||||
|
delete this.objects[name];
|
||||||
|
delete this[name];
|
||||||
|
return this.objects[newname];
|
||||||
|
},
|
||||||
|
|
||||||
|
add_component(comp, data, name = comp.toString()) {
|
||||||
|
if (typeof comp.make !== 'function') return;
|
||||||
|
name = obj_unique_name(name, this);
|
||||||
|
this[name] = comp.make(this);
|
||||||
|
this[name].comp = comp.toString();
|
||||||
|
this.components[name] = this[name];
|
||||||
|
if (data)
|
||||||
|
Object.assign(this[name], data);
|
||||||
|
return this[name];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
var gameobject = {
|
||||||
check_dirty() {
|
check_dirty() {
|
||||||
this._ed.urdiff = this.json_obj();
|
this._ed.urdiff = this.json_obj();
|
||||||
this._ed.dirty = !Object.empty(this._ed.urdiff);
|
this._ed.dirty = !Object.empty(this._ed.urdiff);
|
||||||
|
@ -50,9 +432,6 @@ var gameobject = {
|
||||||
return str;
|
return str;
|
||||||
},
|
},
|
||||||
|
|
||||||
full_path() {
|
|
||||||
return this.path_from(world);
|
|
||||||
},
|
|
||||||
/* pin this object to the to object */
|
/* pin this object to the to object */
|
||||||
pin(to) {
|
pin(to) {
|
||||||
var p = joint.pin(this,to);
|
var p = joint.pin(this,to);
|
||||||
|
@ -95,63 +474,6 @@ var gameobject = {
|
||||||
var p = joint.motor(this, to, rate);
|
var p = joint.motor(this, to, rate);
|
||||||
},
|
},
|
||||||
|
|
||||||
path_from(o) {
|
|
||||||
var p = this.toString();
|
|
||||||
var c = this.master;
|
|
||||||
while (c && c !== o && c !== world) {
|
|
||||||
p = c.toString() + "." + p;
|
|
||||||
c = c.master;
|
|
||||||
}
|
|
||||||
if (c === world) p = "world." + p;
|
|
||||||
return p;
|
|
||||||
},
|
|
||||||
|
|
||||||
clear() {
|
|
||||||
for (var k in this.objects) {
|
|
||||||
this.objects[k].kill();
|
|
||||||
};
|
|
||||||
this.objects = {};
|
|
||||||
},
|
|
||||||
|
|
||||||
delay(fn, seconds) {
|
|
||||||
var timers = this.timers;
|
|
||||||
var stop = function() {
|
|
||||||
timers.remove(stop);
|
|
||||||
execute = undefined;
|
|
||||||
stop = undefined;
|
|
||||||
rm?.();
|
|
||||||
rm = undefined;
|
|
||||||
update = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function execute() {
|
|
||||||
fn();
|
|
||||||
stop?.();
|
|
||||||
}
|
|
||||||
|
|
||||||
stop.remain = seconds;
|
|
||||||
stop.seconds = seconds;
|
|
||||||
stop.pct = function() { return 1 - (stop.remain/stop.seconds); };
|
|
||||||
|
|
||||||
function update(dt) {
|
|
||||||
stop.remain -= dt;
|
|
||||||
if (stop.remain <= 0) execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
var rm = Register.update.register(update);
|
|
||||||
timers.push(stop);
|
|
||||||
return stop;
|
|
||||||
},
|
|
||||||
|
|
||||||
cry(file) { return audio.cry(file); },
|
|
||||||
|
|
||||||
set pos(x) { this.set_pos(x); },
|
|
||||||
get pos() { return this.rpos; },
|
|
||||||
set angle(x) { this.set_angle(x); },
|
|
||||||
get angle() { return this.rangle; },
|
|
||||||
set scale(x) { this.set_scale(x); },
|
|
||||||
get scale() { return this.rscale; },
|
|
||||||
|
|
||||||
set_pos(x, relative = world) {
|
set_pos(x, relative = world) {
|
||||||
var newpos = relative.this2world(x);
|
var newpos = relative.this2world(x);
|
||||||
var move = newpos.sub(this.pos);
|
var move = newpos.sub(this.pos);
|
||||||
|
@ -197,285 +519,8 @@ var gameobject = {
|
||||||
return this.scale.map((x,i) => x/masterscale[i]);
|
return this.scale.map((x,i) => x/masterscale[i]);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Moving, rotating, scaling functions, world relative */
|
|
||||||
move(vec) { this.set_pos(this.pos.add(vec)); },
|
|
||||||
rotate(x) { this.set_angle(this.angle + x); },
|
|
||||||
grow(vec) {
|
|
||||||
if (typeof vec === 'number') vec = [vec,vec,vec];
|
|
||||||
this.set_scale(this.scale.map((x, i) => x * vec[i]));
|
|
||||||
},
|
|
||||||
|
|
||||||
screenpos() { return game.camera.world2view(this.pos); },
|
|
||||||
|
|
||||||
get_ur() { return this.ur; },
|
|
||||||
|
|
||||||
/* spawn an entity
|
|
||||||
text can be:
|
|
||||||
the file path of a script
|
|
||||||
an ur object
|
|
||||||
nothing
|
|
||||||
*/
|
|
||||||
spawn(text, config, callback) {
|
|
||||||
var st = profile.now();
|
|
||||||
var ent = os.make_gameobject();
|
|
||||||
ent.guid = prosperon.guid();
|
|
||||||
ent.components = {};
|
|
||||||
ent.objects = {};
|
|
||||||
ent.timers = [];
|
|
||||||
|
|
||||||
Object.mixin(ent, {
|
|
||||||
set category(n) {
|
|
||||||
if (n === 0) {
|
|
||||||
this.categories = n;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var cat = (1 << (n-1));
|
|
||||||
this.categories = cat;
|
|
||||||
},
|
|
||||||
get category() {
|
|
||||||
if (this.categories === 0) return 0;
|
|
||||||
var pos = 0;
|
|
||||||
var num = this.categories;
|
|
||||||
while (num > 0) {
|
|
||||||
if (num & 1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pos++;
|
|
||||||
num >>>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pos+1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (typeof text === 'object' && text) {// assume it's an ur
|
|
||||||
ent.ur = text;
|
|
||||||
text = ent.ur.text;
|
|
||||||
config = [ent.ur.data, config].filter(x => x).flat();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ent.ur = getur(text, config);
|
|
||||||
text = ent.ur.text;
|
|
||||||
config = [ent.ur.data, config];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof text === 'string')
|
|
||||||
use(text, ent);
|
|
||||||
else if (Array.isArray(text))
|
|
||||||
text.forEach(path => use(path,ent));
|
|
||||||
|
|
||||||
if (typeof config === 'string')
|
|
||||||
Object.merge(ent, json.decode(Resources.replstrs(config)));
|
|
||||||
else if (Array.isArray(config))
|
|
||||||
config.forEach(function(path) {
|
|
||||||
if (typeof path === 'string') {
|
|
||||||
console.info(`ingesting ${path} ...`);
|
|
||||||
Object.merge(ent, json.decode(Resources.replstrs(path)));
|
|
||||||
}
|
|
||||||
else if (typeof path === 'object')
|
|
||||||
Object.merge(ent,path);
|
|
||||||
});
|
|
||||||
|
|
||||||
ent.reparent(this);
|
|
||||||
|
|
||||||
for (var [prop, p] of Object.entries(ent)) {
|
|
||||||
if (!p) continue;
|
|
||||||
if (typeof p !== 'object') continue;
|
|
||||||
if (component.isComponent(p)) continue;
|
|
||||||
if (!p.comp) continue;
|
|
||||||
ent[prop] = component[p.comp].make(ent);
|
|
||||||
Object.merge(ent[prop], p);
|
|
||||||
ent.components[prop] = ent[prop];
|
|
||||||
};
|
|
||||||
|
|
||||||
check_registers(ent);
|
|
||||||
|
|
||||||
if (typeof ent.load === 'function') ent.load();
|
|
||||||
if (sim.playing())
|
|
||||||
if (typeof ent.start === 'function') ent.start();
|
|
||||||
|
|
||||||
Object.hide(ent, 'ur', 'components', 'objects', 'timers', 'guid', 'master', 'categories');
|
|
||||||
|
|
||||||
ent._ed = {
|
|
||||||
selectable: true,
|
|
||||||
dirty: false,
|
|
||||||
inst: false,
|
|
||||||
urdiff: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.hide(ent, '_ed');
|
|
||||||
|
|
||||||
ent.sync();
|
|
||||||
|
|
||||||
if (!Object.empty(ent.objects)) {
|
|
||||||
var o = ent.objects;
|
|
||||||
delete ent.objects;
|
|
||||||
ent.objects = {};
|
|
||||||
for (var i in o) {
|
|
||||||
console.info(`creating ${i} on ${ent.toString()}`);
|
|
||||||
var newur = o[i].ur;
|
|
||||||
delete o[i].ur;
|
|
||||||
var n = ent.spawn(ur[newur], o[i]);
|
|
||||||
ent.rename_obj(n.toString(), i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ent.tag) game.tag_add(ent.tag, ent);
|
|
||||||
|
|
||||||
if (callback) callback(ent);
|
|
||||||
|
|
||||||
ent.ur.fresh ??= json.decode(json.encode(ent));
|
|
||||||
ent.ur.fresh.objects = {};
|
|
||||||
for (var i in ent.objects)
|
|
||||||
ent.ur.fresh.objects[i] = ent.objects[i].instance_obj();
|
|
||||||
|
|
||||||
profile.addreport(entityreport, ent.ur.name, st);
|
|
||||||
return ent;
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Reparent 'this' to be 'parent's child */
|
|
||||||
reparent(parent) {
|
|
||||||
assert(parent, `Tried to reparent ${this.toString()} to nothing.`);
|
|
||||||
console.spam(`parenting ${this.toString()} to ${parent.toString()}`);
|
|
||||||
if (this.master === parent) {
|
|
||||||
console.warn("not reparenting ...");
|
|
||||||
console.warn(`${this.master} is the same as ${parent}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.master?.remove_obj(this);
|
|
||||||
|
|
||||||
this.master = parent;
|
|
||||||
|
|
||||||
function unique_name(list, name = "new_object") {
|
|
||||||
var str = name.replaceAll('.', '_');
|
|
||||||
var n = 1;
|
|
||||||
var t = str;
|
|
||||||
while (list.indexOf(t) !== -1) {
|
|
||||||
t = str + n;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
return t;
|
|
||||||
};
|
|
||||||
|
|
||||||
var name = unique_name(Object.keys(parent.objects), this.ur.name);
|
|
||||||
|
|
||||||
parent.objects[name] = this;
|
|
||||||
parent[name] = this;
|
|
||||||
Object.hide(parent, name);
|
|
||||||
this.toString = function() { return name; };
|
|
||||||
},
|
|
||||||
|
|
||||||
remove_obj(obj) {
|
|
||||||
delete this.objects[obj.toString()];
|
|
||||||
delete this[obj.toString()];
|
|
||||||
Object.unhide(this, obj.toString());
|
|
||||||
},
|
|
||||||
|
|
||||||
components: {},
|
|
||||||
objects: {},
|
|
||||||
master: undefined,
|
|
||||||
|
|
||||||
this2screen(pos) { return game.camera.world2view(this.this2world(pos)); },
|
|
||||||
screen2this(pos) { return this.world2this(game.camera.view2world(pos)); },
|
|
||||||
|
|
||||||
in_air() { return this.in_air(); },
|
in_air() { return this.in_air(); },
|
||||||
|
|
||||||
hide() { this.components.forEach(x => x.hide?.());
|
|
||||||
this.objects.forEach(x => x.hide?.()); },
|
|
||||||
|
|
||||||
show() { this.components.forEach(function(x) { x.show?.(); });
|
|
||||||
this.objects.forEach(function(x) { x.show?.(); }); },
|
|
||||||
|
|
||||||
width() {
|
|
||||||
var bb = this.boundingbox();
|
|
||||||
return bb.r - bb.l;
|
|
||||||
},
|
|
||||||
|
|
||||||
height() {
|
|
||||||
var bb = this.boundingbox();
|
|
||||||
return bb.t - bb.b;
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Make a unique object the same as its prototype */
|
|
||||||
revert() { Object.merge(this, this.ur.fresh); },
|
|
||||||
|
|
||||||
toString() { return "new_object"; },
|
|
||||||
|
|
||||||
flipx() { return this.scale.x < 0; },
|
|
||||||
flipy() { return this.scale.y < 0; },
|
|
||||||
|
|
||||||
mirror(plane) { this.scale = Vector.reflect(this.scale, plane); },
|
|
||||||
|
|
||||||
disable() { this.components.forEach(function(x) { x.disable(); }); },
|
|
||||||
enable() { this.components.forEach(function(x) { x.enable(); }); },
|
|
||||||
|
|
||||||
/* Bounding box of the object in world dimensions */
|
|
||||||
boundingbox() {
|
|
||||||
var boxes = [];
|
|
||||||
boxes.push({
|
|
||||||
t: 0,
|
|
||||||
r: 0,
|
|
||||||
b: 0,
|
|
||||||
l: 0
|
|
||||||
});
|
|
||||||
|
|
||||||
for (var key in this.components) {
|
|
||||||
if ('boundingbox' in this.components[key])
|
|
||||||
boxes.push(this.components[key].boundingbox());
|
|
||||||
}
|
|
||||||
for (var key in this.objects)
|
|
||||||
boxes.push(this.objects[key].boundingbox());
|
|
||||||
|
|
||||||
var bb = boxes.shift();
|
|
||||||
|
|
||||||
boxes.forEach(function(x) { bb = bbox.expand(bb, x); });
|
|
||||||
|
|
||||||
bb = bbox.move(bb, this.pos);
|
|
||||||
|
|
||||||
return bb ? bb : bbox.fromcwh([0, 0], [0, 0]);
|
|
||||||
},
|
|
||||||
|
|
||||||
/* The unique components of this object. Its diff. */
|
|
||||||
json_obj(depth=0) {
|
|
||||||
var fresh = this.ur.fresh;
|
|
||||||
var thiso = json.decode(json.encode(this)); // TODO: SLOW. Used to ignore properties in toJSON of components.
|
|
||||||
var d = ediff(thiso, fresh);
|
|
||||||
|
|
||||||
d ??= {};
|
|
||||||
|
|
||||||
fresh.objects ??= {};
|
|
||||||
var curobjs = {};
|
|
||||||
for (var o in this.objects)
|
|
||||||
curobjs[o] = this.objects[o].instance_obj();
|
|
||||||
|
|
||||||
var odiff = ediff(curobjs, fresh.objects);
|
|
||||||
if (odiff)
|
|
||||||
d.objects = curobjs;
|
|
||||||
|
|
||||||
delete d.pos;
|
|
||||||
delete d.angle;
|
|
||||||
delete d.scale;
|
|
||||||
delete d.velocity;
|
|
||||||
delete d.angularvelocity;
|
|
||||||
return d;
|
|
||||||
},
|
|
||||||
|
|
||||||
/* The object needed to store an object as an instance of a master */
|
|
||||||
instance_obj() {
|
|
||||||
var t = this.transform();
|
|
||||||
t.ur = this.ur.name;
|
|
||||||
return t;
|
|
||||||
},
|
|
||||||
|
|
||||||
transform() {
|
|
||||||
var t = {};
|
|
||||||
t.pos = this.get_pos(this.master).map(x => Math.places(x, 0));
|
|
||||||
t.angle = Math.places(this.get_angle(this.master), 4);
|
|
||||||
t.scale = this.get_scale(this.master).map(x => Math.places(x, 2));;
|
|
||||||
return t;
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Velocity and angular velocity of the object */
|
/* Velocity and angular velocity of the object */
|
||||||
phys_obj() {
|
phys_obj() {
|
||||||
var phys = {};
|
var phys = {};
|
||||||
|
@ -483,111 +528,32 @@ var gameobject = {
|
||||||
phys.angularvelocity = this.angularvelocity;
|
phys.angularvelocity = this.angularvelocity;
|
||||||
return phys;
|
return phys;
|
||||||
},
|
},
|
||||||
|
|
||||||
phys_mat() {
|
set category(n) {
|
||||||
return {
|
if (n === 0) {
|
||||||
friction: this.friction,
|
this.categories = n;
|
||||||
elasticity: this.elasticity
|
return;
|
||||||
}
|
}
|
||||||
|
var cat = (1 << (n-1));
|
||||||
|
this.categories = cat;
|
||||||
},
|
},
|
||||||
|
get category() {
|
||||||
dup(diff) {
|
if (this.categories === 0) return 0;
|
||||||
var n = this.master.spawn(this.ur);
|
var pos = 0;
|
||||||
Object.totalmerge(n, this.transform());
|
var num = this.categories;
|
||||||
return n;
|
while (num > 0) {
|
||||||
},
|
if (num & 1) {
|
||||||
|
break;
|
||||||
kill() {
|
}
|
||||||
if (this.__kill) return;
|
pos++;
|
||||||
this.__kill = true;
|
num >>>= 1;
|
||||||
console.spam(`Killing entity of type ${this.ur}`);
|
|
||||||
|
|
||||||
this.timers.forEach(t => t());
|
|
||||||
this.timers = [];
|
|
||||||
Event.rm_obj(this);
|
|
||||||
input.do_uncontrol(this);
|
|
||||||
|
|
||||||
if (this.master) {
|
|
||||||
this.master.remove_obj(this);
|
|
||||||
this.master = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var key in this.components) {
|
|
||||||
this.components[key].kill?.();
|
|
||||||
this.components[key].gameobject = undefined;
|
|
||||||
this[key].enabled = false;
|
|
||||||
delete this.components[key];
|
|
||||||
delete this[key];
|
|
||||||
}
|
|
||||||
delete this.components;
|
|
||||||
|
|
||||||
this.clear();
|
|
||||||
if (typeof this.stop === 'function') this.stop();
|
|
||||||
|
|
||||||
game.tag_clear_guid(this.guid);
|
return pos+1;
|
||||||
|
|
||||||
for (var i in this) {
|
|
||||||
if (typeof this[i] === 'object') delete this[i];
|
|
||||||
if (typeof this[i] === 'function') delete this[i];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
up() { return [0, 1].rotate(this.angle); },
|
|
||||||
down() { return [0, -1].rotate(this.angle); },
|
|
||||||
right() { return [1, 0].rotate(this.angle); },
|
|
||||||
left() { return [-1, 0].rotate(this.angle); },
|
|
||||||
|
|
||||||
make_objs(objs) {
|
|
||||||
for (var prop in objs) {
|
|
||||||
say(`spawning ${json.encode(objs[prop])}`);
|
|
||||||
var newobj = this.spawn(objs[prop]);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
rename_obj(name, newname) {
|
|
||||||
if (!this.objects[name]) {
|
|
||||||
console.warn(`No object with name ${name}. Could not rename to ${newname}.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (name === newname) {
|
|
||||||
Object.hide(this, name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.objects[newname])
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.objects[newname] = this.objects[name];
|
|
||||||
this[newname] = this[name];
|
|
||||||
this[newname].toString = function() { return newname; };
|
|
||||||
Object.hide(this, newname);
|
|
||||||
delete this.objects[name];
|
|
||||||
delete this[name];
|
|
||||||
return this.objects[newname];
|
|
||||||
},
|
|
||||||
|
|
||||||
add_component(comp, data, name = comp.toString()) {
|
|
||||||
if (typeof comp.make !== 'function') return;
|
|
||||||
name = obj_unique_name(name, this);
|
|
||||||
this[name] = comp.make(this);
|
|
||||||
this[name].comp = comp.toString();
|
|
||||||
this.components[name] = this[name];
|
|
||||||
if (data)
|
|
||||||
Object.assign(this[name], data);
|
|
||||||
return this[name];
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
function go_init() {
|
|
||||||
var gop = os.make_gameobject().__proto__;
|
|
||||||
Object.mixin(gop, gameobject);
|
|
||||||
gop.sync = function() {
|
|
||||||
this.selfsync();
|
|
||||||
this.components.forEach(function(x) { x.sync?.(); });
|
|
||||||
this.objects.forEach(function(x) { x.sync?.(); });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gameobject.spawn.doc = `Spawn an entity of type 'ur' on this entity. Returns the spawned entity.`;
|
entity.spawn.doc = `Spawn an entity of type 'ur' on this entity. Returns the spawned entity.`;
|
||||||
|
|
||||||
gameobject.doc = {
|
gameobject.doc = {
|
||||||
doc: "All objects in the game created through spawning have these attributes.",
|
doc: "All objects in the game created through spawning have these attributes.",
|
||||||
|
@ -695,8 +661,18 @@ function apply_ur(u, ent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var emptyur = {
|
||||||
|
name: "empty"
|
||||||
|
}
|
||||||
|
|
||||||
var getur = function(text, data)
|
var getur = function(text, data)
|
||||||
{
|
{
|
||||||
|
if (!text && !data) {
|
||||||
|
console.info('empty ur');
|
||||||
|
return {
|
||||||
|
name: "empty"
|
||||||
|
};
|
||||||
|
}
|
||||||
var urstr = text + "+" + data;
|
var urstr = text + "+" + data;
|
||||||
if (!ur[urstr]) {
|
if (!ur[urstr]) {
|
||||||
ur[urstr] = {
|
ur[urstr] = {
|
||||||
|
@ -784,4 +760,4 @@ game.ur.save = function(str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { go_init }
|
return { entity }
|
|
@ -84,8 +84,6 @@ void model_free(model *m);
|
||||||
|
|
||||||
void model_draw_go(model *m, gameobject *go, gameobject *cam);
|
void model_draw_go(model *m, gameobject *go, gameobject *cam);
|
||||||
|
|
||||||
void model_init();
|
|
||||||
|
|
||||||
material *material_make();
|
material *material_make();
|
||||||
void material_free(material *mat);
|
void material_free(material *mat);
|
||||||
|
|
||||||
|
|
|
@ -204,9 +204,3 @@ HMM_Vec3 go_pos3d(gameobject *go)
|
||||||
HMM_Vec2 pos2d = go_pos(go);
|
HMM_Vec2 pos2d = go_pos(go);
|
||||||
return (HMM_Vec3){pos2d.x, pos2d.y, go->drawlayer};
|
return (HMM_Vec3){pos2d.x, pos2d.y, go->drawlayer};
|
||||||
}
|
}
|
||||||
|
|
||||||
void gameobject_draw_debug(gameobject *go) {
|
|
||||||
if (!go || !go->body) return;
|
|
||||||
|
|
||||||
cpBodyEachShape(go->body, body_draw_shapes_dbg, NULL);
|
|
||||||
}
|
|
||||||
|
|
|
@ -779,7 +779,21 @@ JSC_CCALL(render_setuniproj,
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(render_setunim4,
|
JSC_CCALL(render_setunim4,
|
||||||
HMM_Mat4 m = transform2d2mat4(js2transform2d(argv[2]));
|
HMM_Mat4 m = MAT1;
|
||||||
|
if (JS_IsArray(js, argv[2])) {
|
||||||
|
JSValue arr = argv[2];
|
||||||
|
int n = js_arrlen(arr);
|
||||||
|
if (n == 1)
|
||||||
|
m = transform2d2mat4(js2transform2d(js_getpropidx(arr,0)));
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
HMM_Mat4 p = transform2d2mat4(js2transform2d(js_getpropidx(arr, i)));
|
||||||
|
m = HMM_MulM4(p,m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
m = transform2d2mat4(js2transform2d(argv[2]));
|
||||||
|
|
||||||
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(m.e));
|
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(m.e));
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -920,7 +934,7 @@ static const JSCFunctionListEntry js_input_funcs[] = {
|
||||||
|
|
||||||
JSC_CCALL(prosperon_emitters_step, emitters_step(js2number(argv[0])))
|
JSC_CCALL(prosperon_emitters_step, emitters_step(js2number(argv[0])))
|
||||||
JSC_CCALL(prosperon_phys2d_step, phys2d_update(js2number(argv[0])))
|
JSC_CCALL(prosperon_phys2d_step, phys2d_update(js2number(argv[0])))
|
||||||
JSC_CCALL(prosperon_window_render, openglRender(&mainwin, js2gameobject(argv[0]), js2number(argv[1])))
|
JSC_CCALL(prosperon_window_render, openglRender(&mainwin, js2transform2d(argv[0]), js2number(argv[1])))
|
||||||
JSC_CCALL(prosperon_guid,
|
JSC_CCALL(prosperon_guid,
|
||||||
uint8_t bytes[16];
|
uint8_t bytes[16];
|
||||||
for (int i = 0; i < 16; i++) bytes[i] = rand()%256;
|
for (int i = 0; i < 16; i++) bytes[i] = rand()%256;
|
||||||
|
@ -1089,8 +1103,6 @@ static const JSCFunctionListEntry js_io_funcs[] = {
|
||||||
MIST_FUNC_DEF(io, mod,1)
|
MIST_FUNC_DEF(io, mod,1)
|
||||||
};
|
};
|
||||||
|
|
||||||
JSC_CCALL(debug_draw_gameobject, gameobject_draw_debug(js2gameobject(argv[0]));)
|
|
||||||
|
|
||||||
JSC_GETSET_GLOBAL(disabled_color, color)
|
JSC_GETSET_GLOBAL(disabled_color, color)
|
||||||
JSC_GETSET_GLOBAL(sleep_color, color)
|
JSC_GETSET_GLOBAL(sleep_color, color)
|
||||||
JSC_GETSET_GLOBAL(dynamic_color, color)
|
JSC_GETSET_GLOBAL(dynamic_color, color)
|
||||||
|
@ -1098,7 +1110,6 @@ JSC_GETSET_GLOBAL(kinematic_color, color)
|
||||||
JSC_GETSET_GLOBAL(static_color, color)
|
JSC_GETSET_GLOBAL(static_color, color)
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_debug_funcs[] = {
|
static const JSCFunctionListEntry js_debug_funcs[] = {
|
||||||
MIST_FUNC_DEF(debug, draw_gameobject, 1),
|
|
||||||
CGETSET_ADD(global, disabled_color),
|
CGETSET_ADD(global, disabled_color),
|
||||||
CGETSET_ADD(global, sleep_color),
|
CGETSET_ADD(global, sleep_color),
|
||||||
CGETSET_ADD(global, dynamic_color),
|
CGETSET_ADD(global, dynamic_color),
|
||||||
|
@ -1716,7 +1727,16 @@ JSC_SCALL(os_make_texture,
|
||||||
JSC_CCALL(os_make_font, return font2js(MakeFont(js2str(argv[0]), js2number(argv[1]))))
|
JSC_CCALL(os_make_font, return font2js(MakeFont(js2str(argv[0]), js2number(argv[1]))))
|
||||||
|
|
||||||
JSC_CCALL(os_make_transform2d,
|
JSC_CCALL(os_make_transform2d,
|
||||||
return transform2d2js(make_transform2d());
|
if (JS_IsUndefined(argv[0]))
|
||||||
|
return transform2d2js(make_transform2d());
|
||||||
|
|
||||||
|
int n = js2number(argv[0]);
|
||||||
|
transform2d *t = calloc(sizeof(transform2d), n);
|
||||||
|
JSValue arr = JS_NewArray(js);
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
js_setprop_num(arr, i, transform2d2js(t+i));
|
||||||
|
|
||||||
|
return arr;
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_SCALL(os_system, return number2js(system(str)); )
|
JSC_SCALL(os_system, return number2js(system(str)); )
|
||||||
|
@ -1742,7 +1762,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||||
MIST_FUNC_DEF(os, make_texture, 1),
|
MIST_FUNC_DEF(os, make_texture, 1),
|
||||||
MIST_FUNC_DEF(os, make_font, 2),
|
MIST_FUNC_DEF(os, make_font, 2),
|
||||||
MIST_FUNC_DEF(os, make_model, 1),
|
MIST_FUNC_DEF(os, make_model, 1),
|
||||||
MIST_FUNC_DEF(os, make_transform2d, 0),
|
MIST_FUNC_DEF(os, make_transform2d, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "steam.h"
|
#include "steam.h"
|
||||||
|
|
|
@ -258,8 +258,6 @@ void render_init() {
|
||||||
font_init();
|
font_init();
|
||||||
debugdraw_init();
|
debugdraw_init();
|
||||||
|
|
||||||
model_init();
|
|
||||||
|
|
||||||
sg_color c = (sg_color){0,0,0,1};
|
sg_color c = (sg_color){0,0,0,1};
|
||||||
pass_action = (sg_pass_action){
|
pass_action = (sg_pass_action){
|
||||||
.colors[0] = {.load_action = SG_LOADACTION_CLEAR, .clear_value = c},
|
.colors[0] = {.load_action = SG_LOADACTION_CLEAR, .clear_value = c},
|
||||||
|
@ -337,7 +335,7 @@ HMM_Mat4 useproj = {0};
|
||||||
#define MODE_EXPAND 4
|
#define MODE_EXPAND 4
|
||||||
#define MODE_FULL 5
|
#define MODE_FULL 5
|
||||||
|
|
||||||
void openglRender(struct window *window, gameobject *cam, float zoom) {
|
void openglRender(struct window *window, transform2d *cam, float zoom) {
|
||||||
sg_swapchain sch = sglue_swapchain();
|
sg_swapchain sch = sglue_swapchain();
|
||||||
sg_begin_pass(&(sg_pass){
|
sg_begin_pass(&(sg_pass){
|
||||||
.action = pass_action,
|
.action = pass_action,
|
||||||
|
@ -372,7 +370,7 @@ void openglRender(struct window *window, gameobject *cam, float zoom) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2D projection
|
// 2D projection
|
||||||
campos = go_pos(cam);
|
campos = cam->pos;
|
||||||
camzoom = zoom;
|
camzoom = zoom;
|
||||||
|
|
||||||
projection = HMM_Orthographic_RH_NO(
|
projection = HMM_Orthographic_RH_NO(
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "sokol/sokol_gfx.h"
|
#include "sokol/sokol_gfx.h"
|
||||||
#include "HandmadeMath.h"
|
#include "HandmadeMath.h"
|
||||||
#include "gameobject.h"
|
#include "gameobject.h"
|
||||||
|
#include "transform.h"
|
||||||
|
|
||||||
#define RGBA_MAX 255
|
#define RGBA_MAX 255
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ void render_init();
|
||||||
extern HMM_Vec2 campos;
|
extern HMM_Vec2 campos;
|
||||||
extern float camzoom;
|
extern float camzoom;
|
||||||
|
|
||||||
void openglRender(struct window *window, gameobject *cam, float zoom);
|
void openglRender(struct window *window, transform2d *cam, float zoom);
|
||||||
void opengl_rendermode(enum RenderMode r);
|
void opengl_rendermode(enum RenderMode r);
|
||||||
|
|
||||||
void openglInit3d(struct window *window);
|
void openglInit3d(struct window *window);
|
||||||
|
|
Loading…
Reference in a new issue