Separate entity from rigidbody

This commit is contained in:
John Alanbrook 2024-05-02 17:13:09 -05:00
parent e86e126894
commit 79e4772f93
9 changed files with 460 additions and 473 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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";

View file

@ -12,7 +12,18 @@ 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))
@ -22,79 +33,6 @@ var gameobject = {
return undefined; return undefined;
}, },
check_dirty() {
this._ed.urdiff = this.json_obj();
this._ed.dirty = !Object.empty(this._ed.urdiff);
return; // TODO: IMPLEMENT
var lur = this.master.ur;
if (!lur) return;
var lur = lur.objects[this.toString()];
var d = ediff(this._ed.urdiff, lur);
if (!d || Object.empty(d))
this._ed.inst = true;
else
this._ed.inst = false;
},
namestr() {
var s = this.toString();
if (this._ed?.dirty)
if (this._ed.inst) s += "#";
else s += "*";
return s;
},
urstr() {
var str = this.ur.name;
if (this._ed.dirty) str = "*" + str;
return str;
},
full_path() {
return this.path_from(world);
},
/* pin this object to the to object */
pin(to) {
var p = joint.pin(this,to);
},
slide(to, a = [0,0], b = [0,0], min = 0, max = 50) {
var p = joint.slide(this, to, a, b, min, max);
p.max_force = 500;
p.break();
},
pivot(to, piv = this.pos) {
var p = joint.pivot(this, to, piv);
},
/* groove is on to, from local points a and b, anchored to this at local anchor */
groove(to, a, b, anchor = [0,0]) {
var p = joint.groove(to, this, a, b, anchor);
},
damped_spring(to, length = Vector.length(this.pos,to.pos), stiffness = 1, damping = 1) {
var dc = 2 * Math.sqrt(stiffness * this.mass);
var p = joint.damped_spring(this, to, [0, 0], [0, 0], stiffness, damping * dc);
},
damped_rotary_spring(to, angle = 0, stiffness = 1, damping = 1) {
/* calculate actual damping value from the damping ratio */
/* damping = 1 is critical */
var dc = 2 * Math.sqrt(stiffness * this.get_moi()); /* critical damping number */
/* zeta = actual/critical */
var p = joint.damped_rotary(this, to, angle, stiffness, damping * dc);
},
rotary_limit(to, min, max) {
var p = joint.rotary(this, to, Math.turn2rad(min), Math.turn2rad(max));
},
ratchet(to, ratch) {
var phase = this.angle - to.angle;
var p = joint.ratchet(this, to, phase, Math.turn2rad(ratch));
},
gear(to, ratio = 1, phase = 0) {
var phase = this.angle - to.angle;
var p = joint.gear(this, to, phase, ratio);
},
motor(to, rate) {
var p = joint.motor(this, to, rate);
},
path_from(o) { path_from(o) {
var p = this.toString(); var p = this.toString();
var c = this.master; var c = this.master;
@ -106,6 +44,8 @@ var gameobject = {
return p; return p;
}, },
full_path() { return this.path_from(world); },
clear() { clear() {
for (var k in this.objects) { for (var k in this.objects) {
this.objects[k].kill(); this.objects[k].kill();
@ -113,6 +53,11 @@ var gameobject = {
this.objects = {}; this.objects = {};
}, },
sync() {
this.components.forEach(function(x) { x.sync?.(); });
this.objects.forEach(function(x) { x.sync(); });
},
delay(fn, seconds) { delay(fn, seconds) {
var timers = this.timers; var timers = this.timers;
var stop = function() { var stop = function() {
@ -145,110 +90,60 @@ var gameobject = {
cry(file) { return audio.cry(file); }, cry(file) { return audio.cry(file); },
set pos(x) { this.set_pos(x); }, get pos() { return this.transform.pos; },
get pos() { return this.rpos; }, set pos(x) { this.transform.pos = x; },
set angle(x) { this.set_angle(x); }, get angle() { return this.transform.angle; },
get angle() { return this.rangle; }, set angle(x) { this.transform.angle = x; },
set scale(x) { this.set_scale(x); }, get scale() { return this.transform.scale; },
get scale() { return this.rscale; }, set scale(x) { this.transform.scale = x; },
set_pos(x, relative = world) { move(vec) { this.pos = this.pos.add(vec); },
var newpos = relative.this2world(x); rotate(x) { this.angle += x; },
var move = newpos.sub(this.pos);
this.rpos = newpos;
this.objects.forEach(x => x.move(move));
},
set_angle(x, relative = world) {
var newangle = relative.angle + x;
var diff = newangle - this.angle;
this.rangle = newangle;
this.objects.forEach(obj => {
obj.rotate(diff);
obj.set_pos(Vector.rotate(obj.get_pos(obj.master), diff), obj.master);
});
},
set_scale(x, relative = world) {
if (typeof x === 'number') x = [x,x,x];
var newscale = relative.scale.map((s,i) => x[i]*s);
var pct = this.scale.map((s,i) => newscale[i]/s);
this.rscale = newscale;
this.objects.forEach(obj => {
obj.grow(pct);
obj.set_pos(obj.get_pos(obj.master).map((x,i) => x*pct[i]), obj.master);
});
},
get_pos(relative = world) {
if (relative === world) return this.pos;
return relative.world2this(this.pos);
//return this.pos.sub(relative.pos);
},
get_angle(relative = world) {
if (relative === world) return this.angle;
return this.angle - relative.angle;
},
get_scale(relative = world) {
if (relative === world) return this.scale;
var masterscale = relative.scale;
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) { grow(vec) {
if (typeof vec === 'number') vec = [vec,vec,vec]; if (typeof vec === 'number') vec = [vec,vec];
this.set_scale(this.scale.map((x, i) => x * vec[i])); this.scale = this.scale.map((x,i) => x*vec[i]);
}, },
screenpos() { return game.camera.world2view(this.pos); }, /* 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;
}
get_ur() { return this.ur; }, 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 an entity
text can be:
the file path of a script
an ur object
nothing
*/
spawn(text, config, callback) { spawn(text, config, callback) {
var st = profile.now(); var st = profile.now();
var ent = os.make_gameobject(); var ent = Object.create(entity);
ent.transform = os.make_transform2d();
ent.guid = prosperon.guid(); ent.guid = prosperon.guid();
ent.components = {}; ent.components = {};
ent.objects = {}; ent.objects = {};
ent.timers = []; ent.timers = [];
Object.mixin(ent, { if (!text)
set category(n) { ent.ur = emptyur;
if (n === 0) { else if (typeof text === 'object' && text) {// assume it's an ur
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; ent.ur = text;
text = ent.ur.text; text = ent.ur.text;
config = [ent.ur.data, config].filter(x => x).flat(); config = [ent.ur.data, config].filter(x => x).flat();
@ -294,7 +189,7 @@ var gameobject = {
if (sim.playing()) if (sim.playing())
if (typeof ent.start === 'function') ent.start(); if (typeof ent.start === 'function') ent.start();
Object.hide(ent, 'ur', 'components', 'objects', 'timers', 'guid', 'master', 'categories'); Object.hide(ent, 'ur', 'components', 'objects', 'timers', 'guid', 'master');
ent._ed = { ent._ed = {
selectable: true, selectable: true,
@ -324,6 +219,7 @@ var gameobject = {
if (callback) callback(ent); if (callback) callback(ent);
ent.ur.fresh ??= json.decode(json.encode(ent)); ent.ur.fresh ??= json.decode(json.encode(ent));
ent.ur.fresh.objects = {}; ent.ur.fresh.objects = {};
for (var i in ent.objects) for (var i in ent.objects)
@ -333,60 +229,17 @@ var gameobject = {
return ent; return ent;
}, },
/* Reparent 'this' to be 'parent's child */ disable() { this.components.forEach(function(x) { x.disable(); }); },
reparent(parent) { enable() { this.components.forEach(function(x) { x.enable(); }); },
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)); }, this2screen(pos) { return game.camera.world2view(this.this2world(pos)); },
screen2this(pos) { return this.world2this(game.camera.view2world(pos)); }, screen2this(pos) { return this.world2this(game.camera.view2world(pos)); },
in_air() { return this.in_air(); }, /* Make a unique object the same as its prototype */
revert() { Object.merge(this, this.ur.fresh); },
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?.(); }); },
name: "new_object",
toString() { return this.name; },
width() { width() {
var bb = this.boundingbox(); var bb = this.boundingbox();
return bb.r - bb.l; return bb.r - bb.l;
@ -397,19 +250,11 @@ var gameobject = {
return bb.t - bb.b; 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; }, flipx() { return this.scale.x < 0; },
flipy() { return this.scale.y < 0; }, flipy() { return this.scale.y < 0; },
mirror(plane) { this.scale = Vector.reflect(this.scale, plane); }, 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 */ /* Bounding box of the object in world dimensions */
boundingbox() { boundingbox() {
var boxes = []; var boxes = [];
@ -476,22 +321,7 @@ var gameobject = {
return t; return t;
}, },
/* Velocity and angular velocity of the object */ dup(diff) {
phys_obj() {
var phys = {};
phys.velocity = this.velocity;
phys.angularvelocity = this.angularvelocity;
return phys;
},
phys_mat() {
return {
friction: this.friction,
elasticity: this.elasticity
}
},
dup(diff) {
var n = this.master.spawn(this.ur); var n = this.master.spawn(this.ur);
Object.totalmerge(n, this.transform()); Object.totalmerge(n, this.transform());
return n; return n;
@ -532,10 +362,6 @@ var gameobject = {
} }
}, },
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) { make_objs(objs) {
for (var prop in objs) { for (var prop in objs) {
@ -575,19 +401,159 @@ var gameobject = {
Object.assign(this[name], data); Object.assign(this[name], data);
return this[name]; return this[name];
}, },
} };
function go_init() { var gameobject = {
var gop = os.make_gameobject().__proto__; check_dirty() {
Object.mixin(gop, gameobject); this._ed.urdiff = this.json_obj();
gop.sync = function() { this._ed.dirty = !Object.empty(this._ed.urdiff);
this.selfsync(); return; // TODO: IMPLEMENT
this.components.forEach(function(x) { x.sync?.(); }); var lur = this.master.ur;
this.objects.forEach(function(x) { x.sync?.(); }); if (!lur) return;
var lur = lur.objects[this.toString()];
var d = ediff(this._ed.urdiff, lur);
if (!d || Object.empty(d))
this._ed.inst = true;
else
this._ed.inst = false;
},
namestr() {
var s = this.toString();
if (this._ed?.dirty)
if (this._ed.inst) s += "#";
else s += "*";
return s;
},
urstr() {
var str = this.ur.name;
if (this._ed.dirty) str = "*" + str;
return str;
},
/* pin this object to the to object */
pin(to) {
var p = joint.pin(this,to);
},
slide(to, a = [0,0], b = [0,0], min = 0, max = 50) {
var p = joint.slide(this, to, a, b, min, max);
p.max_force = 500;
p.break();
},
pivot(to, piv = this.pos) {
var p = joint.pivot(this, to, piv);
},
/* groove is on to, from local points a and b, anchored to this at local anchor */
groove(to, a, b, anchor = [0,0]) {
var p = joint.groove(to, this, a, b, anchor);
},
damped_spring(to, length = Vector.length(this.pos,to.pos), stiffness = 1, damping = 1) {
var dc = 2 * Math.sqrt(stiffness * this.mass);
var p = joint.damped_spring(this, to, [0, 0], [0, 0], stiffness, damping * dc);
},
damped_rotary_spring(to, angle = 0, stiffness = 1, damping = 1) {
/* calculate actual damping value from the damping ratio */
/* damping = 1 is critical */
var dc = 2 * Math.sqrt(stiffness * this.get_moi()); /* critical damping number */
/* zeta = actual/critical */
var p = joint.damped_rotary(this, to, angle, stiffness, damping * dc);
},
rotary_limit(to, min, max) {
var p = joint.rotary(this, to, Math.turn2rad(min), Math.turn2rad(max));
},
ratchet(to, ratch) {
var phase = this.angle - to.angle;
var p = joint.ratchet(this, to, phase, Math.turn2rad(ratch));
},
gear(to, ratio = 1, phase = 0) {
var phase = this.angle - to.angle;
var p = joint.gear(this, to, phase, ratio);
},
motor(to, rate) {
var p = joint.motor(this, to, rate);
},
set_pos(x, relative = world) {
var newpos = relative.this2world(x);
var move = newpos.sub(this.pos);
this.rpos = newpos;
this.objects.forEach(x => x.move(move));
},
set_angle(x, relative = world) {
var newangle = relative.angle + x;
var diff = newangle - this.angle;
this.rangle = newangle;
this.objects.forEach(obj => {
obj.rotate(diff);
obj.set_pos(Vector.rotate(obj.get_pos(obj.master), diff), obj.master);
});
},
set_scale(x, relative = world) {
if (typeof x === 'number') x = [x,x,x];
var newscale = relative.scale.map((s,i) => x[i]*s);
var pct = this.scale.map((s,i) => newscale[i]/s);
this.rscale = newscale;
this.objects.forEach(obj => {
obj.grow(pct);
obj.set_pos(obj.get_pos(obj.master).map((x,i) => x*pct[i]), obj.master);
});
},
get_pos(relative = world) {
if (relative === world) return this.pos;
return relative.world2this(this.pos);
//return this.pos.sub(relative.pos);
},
get_angle(relative = world) {
if (relative === world) return this.angle;
return this.angle - relative.angle;
},
get_scale(relative = world) {
if (relative === world) return this.scale;
var masterscale = relative.scale;
return this.scale.map((x,i) => x/masterscale[i]);
},
in_air() { return this.in_air(); },
/* Velocity and angular velocity of the object */
phys_obj() {
var phys = {};
phys.velocity = this.velocity;
phys.angularvelocity = this.angularvelocity;
return phys;
},
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;
} }
} }
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 }

View file

@ -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);

View file

@ -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);
}

View file

@ -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,
if (JS_IsUndefined(argv[0]))
return transform2d2js(make_transform2d()); 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"

View file

@ -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(

View file

@ -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);