Sprites are now defined in C; gameobject getsets
This commit is contained in:
parent
3e8bbdbeb2
commit
bb24fd2bc0
|
@ -19,25 +19,22 @@ var component = {
|
||||||
return (typeof component[c.toString()] === 'object');
|
return (typeof component[c.toString()] === 'object');
|
||||||
},
|
},
|
||||||
|
|
||||||
hides: ['gameobject', 'id'],
|
|
||||||
|
|
||||||
make(go) {
|
make(go) {
|
||||||
var nc = Object.create(this);
|
var nc = Object.create(this);
|
||||||
nc.gameobject = go;
|
nc.gameobject = go;
|
||||||
Object.assign(nc, this._enghook(go.body));
|
Object.mixin(nc, this._enghook(go.body));
|
||||||
assign_impl(nc,this.impl);
|
assign_impl(nc,this.impl);
|
||||||
Object.hide(nc, ...this.hides);
|
Object.hide(nc, ['gameobject', 'id']);
|
||||||
nc.post();
|
nc.post();
|
||||||
return nc;
|
return nc;
|
||||||
},
|
},
|
||||||
|
|
||||||
kill() { console.info("Kill not created for this component yet"); },
|
kill() { console.info("Kill not created for this component yet"); },
|
||||||
sync() {},
|
sync(){},
|
||||||
post(){},
|
post(){},
|
||||||
gui() { },
|
gui(){},
|
||||||
gizmo() { },
|
gizmo(){},
|
||||||
|
|
||||||
prepare_center() {},
|
|
||||||
finish_center() {},
|
finish_center() {},
|
||||||
extend(spec) { return Object.copy(this, spec); },
|
extend(spec) { return Object.copy(this, spec); },
|
||||||
};
|
};
|
||||||
|
@ -68,126 +65,95 @@ var assign_impl = function(obj, impl)
|
||||||
obj[key] = tmp[key];
|
obj[key] = tmp[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
component.sprite = Object.copy(component, {
|
function json_from_whitelist(whitelist)
|
||||||
pos:[0,0],
|
{
|
||||||
color:[1,1,1,1],
|
return function() {
|
||||||
layer:0,
|
var o = {};
|
||||||
enabled:true,
|
for (var p of whitelist)
|
||||||
path: "",
|
o[p] = this[p];
|
||||||
rect: {s0:0, s1: 1, t0: 0, t1: 1},
|
return o;
|
||||||
toString() { return "sprite"; },
|
}
|
||||||
_enghook: make_sprite,
|
}
|
||||||
});
|
|
||||||
|
|
||||||
component.sprite.mode = {
|
Object.mixin(cmd(268,true), {
|
||||||
simple: 0,
|
toJSON:json_from_whitelist([
|
||||||
tile: 1
|
"path",
|
||||||
};
|
"pos",
|
||||||
|
"scale",
|
||||||
component.sprite.impl = {
|
"angle",
|
||||||
toJSON() {
|
"color",
|
||||||
var j = {};
|
"emissive",
|
||||||
Object.keys(this).forEach(k => j[k] = this[k]);
|
"parallax",
|
||||||
delete j.rect;
|
"frame"
|
||||||
return j;
|
]),
|
||||||
|
anim:{},
|
||||||
|
playing: 0,
|
||||||
|
play(str) {
|
||||||
|
var sp = this;
|
||||||
|
str ??= 0;
|
||||||
|
var playing = this.anim[str];
|
||||||
|
if (!playing) return; //TODO: ERROR
|
||||||
|
var f = 0;
|
||||||
|
|
||||||
|
function advance() {
|
||||||
|
sp.path = playing.path;
|
||||||
|
sp.frame = playing.frames[f].rect;
|
||||||
|
f = (f+1)%playing.frames.length;
|
||||||
|
if (f === 0)
|
||||||
|
sp.anim_done?.();
|
||||||
|
sp.gameobject?.delay(advance, playing.frames[f].time);
|
||||||
|
}
|
||||||
|
advance();
|
||||||
},
|
},
|
||||||
|
stop() {},
|
||||||
set path(x) {
|
set path(p) {
|
||||||
if (this.cancel) {
|
p = Resources.find_image(p);
|
||||||
this.cancel();
|
if (!p) return;
|
||||||
this.cancel = undefined;
|
if (p === this.path) return;
|
||||||
}
|
this.tex = cmd(269,p);
|
||||||
|
var anim = SpriteAnim.make(p);
|
||||||
if (!Resources.is_animation(x)) {
|
if (!anim) return;
|
||||||
this.rect = component.sprite.rect;
|
this.anim = anim;
|
||||||
cmd(12,this.id,x,this.rect);
|
this.play();
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.anims = SpriteAnim.make(x);
|
|
||||||
Object.hide(this, 'anims');
|
|
||||||
var anim = this.anims[0];
|
|
||||||
this.rect = anim.frames[0].rect;
|
|
||||||
cmd(12,this.id,anim.path,this.rect);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
get path() {
|
get path() {
|
||||||
var s = cmd(116,this.id);
|
return this.tex.path();
|
||||||
if (s === "icons/no_tex.gif") return undefined;
|
|
||||||
return s;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
play(name) {
|
|
||||||
if (!this.anims) return;
|
|
||||||
if (this.cancel) this.cancel();
|
|
||||||
name ??= 0;
|
|
||||||
var frame = 0;
|
|
||||||
var anim = this.anims[name];
|
|
||||||
var advance = function() {
|
|
||||||
frame = (frame+1)%anim.frames.length;
|
|
||||||
this.rect = anim.frames[frame].rect;
|
|
||||||
cmd(12,this.id,anim.path,this.rect);
|
|
||||||
this.cancel = this.gameobject.delay(advance.bind(this), anim.frames[frame].time);
|
|
||||||
}
|
|
||||||
advance.call(this);
|
|
||||||
},
|
|
||||||
|
|
||||||
stop() {
|
|
||||||
if (!this.cancel) return;
|
|
||||||
this.cancel();
|
|
||||||
this.cancel = undefined;
|
|
||||||
},
|
|
||||||
setframe(f) {
|
|
||||||
if (!this.anims) return;
|
|
||||||
this.stop();
|
|
||||||
var anim = this.anims[0];
|
|
||||||
this.rect = anim.frames[f].rect;
|
|
||||||
cmd(12,this.id,anim.path,this.rect);
|
|
||||||
},
|
|
||||||
|
|
||||||
toString() { return "sprite"; },
|
toString() { return "sprite"; },
|
||||||
hide() { this.enabled = false; },
|
move(d) { this.pos = this.pos.add(d); },
|
||||||
show() { this.enabled = true; },
|
|
||||||
asset(str) { this.path = str; },
|
|
||||||
get enabled() { return cmd(114,this.id); },
|
|
||||||
set enabled(x) { cmd(20,this.id,x); },
|
|
||||||
set color(x) { cmd(96,this.id,x); },
|
|
||||||
get color() {return cmd(148,this.id);},
|
|
||||||
get pos() { return cmd(111, this.id); },
|
|
||||||
set pos(x) { cmd(37,this.id,x); },
|
|
||||||
get parallax() { return cmd(232, this.id); },
|
|
||||||
set parallax(x) { cmd(233,this.id,x); },
|
|
||||||
get angle() { return cmd(217,this.id); },
|
|
||||||
set angle(x) { cmd(218,this.id,x); },
|
|
||||||
get scale() { return cmd(215, this.id); },
|
|
||||||
set scale(x) { cmd(216, this.id, x); },
|
|
||||||
grow(x) {
|
grow(x) {
|
||||||
this.scale = this.scale.scale(x);
|
this.scale = this.scale.scale(x);
|
||||||
this.pos = this.pos.scale(x);
|
this.pos = this.pos.scale(x);
|
||||||
},
|
},
|
||||||
get drawmode() { return cmd(220,this.id); },
|
|
||||||
set drawmode(x) { cmd(219,this.id,x); },
|
|
||||||
emissive(x) { cmd(170, this.id, x); },
|
|
||||||
sync() { },
|
sync() { },
|
||||||
pickm() { return this; },
|
pick() { return this; },
|
||||||
move(d) { this.pos = this.pos.add(d); },
|
|
||||||
|
|
||||||
boundingbox() {
|
boundingbox() {
|
||||||
var dim = this.dimensions();
|
var dim = this.dimensions();
|
||||||
dim = dim.scale(this.gameobject.gscale());
|
dim = dim.scale(this.gameobject.gscale());
|
||||||
var realpos = dim.scale(0.5).add(this.pos);
|
var realpos = dim.scale(0.5).add(this.pos);
|
||||||
return bbox.fromcwh(realpos,dim);
|
return bbox.fromcwh(realpos,dim);
|
||||||
},
|
},
|
||||||
|
|
||||||
kill() { cmd(9,this.id); },
|
|
||||||
dimensions() {
|
dimensions() {
|
||||||
var dim = Resources.texture.dimensions(this.path);
|
var dim = [this.tex.width(), this.tex.height()];
|
||||||
dim.x *= (this.rect.s1-this.rect.s0);
|
dim.x *= this.frame.w;
|
||||||
dim.y *= (this.rect.t1-this.rect.t0);
|
dim.y *= this.frame.h;
|
||||||
return dim;
|
return dim;
|
||||||
},
|
},
|
||||||
width() { return this.dimensions().x; },
|
width() { return this.dimensions().x; },
|
||||||
height() { return this.dimensions().y; },
|
height() { return this.dimensions().y; },
|
||||||
};
|
});
|
||||||
|
|
||||||
|
cmd(268,true).make = function(go)
|
||||||
|
{
|
||||||
|
var sp = cmd(268);
|
||||||
|
sp.go = go.body;
|
||||||
|
sp.gameobject = go;
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
component.sprite = cmd(268,true);
|
||||||
|
|
||||||
Object.freeze(sprite);
|
Object.freeze(sprite);
|
||||||
|
|
||||||
|
@ -195,6 +161,7 @@ component.model = Object.copy(component, {
|
||||||
path:"",
|
path:"",
|
||||||
_enghook: make_model,
|
_enghook: make_model,
|
||||||
});
|
});
|
||||||
|
|
||||||
component.model.impl = {
|
component.model.impl = {
|
||||||
set path(x) { cmd(149, this.id, x); },
|
set path(x) { cmd(149, this.id, x); },
|
||||||
draw() { cmd(150, this.id); },
|
draw() { cmd(150, this.id); },
|
||||||
|
@ -245,10 +212,10 @@ var SpriteAnim = {
|
||||||
for (var f = 0; f < frames; f++) {
|
for (var f = 0; f < frames; f++) {
|
||||||
var frame = {};
|
var frame = {};
|
||||||
frame.rect = {
|
frame.rect = {
|
||||||
s0: 0,
|
x: 0,
|
||||||
s1: 1,
|
w: 1,
|
||||||
t0: yslice*f,
|
y: yslice*f,
|
||||||
t1: yslice*(f+1)
|
h: yslice
|
||||||
};
|
};
|
||||||
frame.time = 0.05;
|
frame.time = 0.05;
|
||||||
anim.frames.push(frame);
|
anim.frames.push(frame);
|
||||||
|
@ -290,10 +257,10 @@ var SpriteAnim = {
|
||||||
var f = ase_frame.frame;
|
var f = ase_frame.frame;
|
||||||
var frame = {};
|
var frame = {};
|
||||||
frame.rect = {
|
frame.rect = {
|
||||||
s0: f.x/dim.w,
|
x: f.x/dim.w,
|
||||||
s1: (f.x+f.w)/dim.w,
|
w: f.w/dim.w,
|
||||||
t0: f.y/dim.h,
|
y: f.y/dim.h,
|
||||||
t1: (f.y+f.h)/dim.h
|
h: f.h/dim.h
|
||||||
};
|
};
|
||||||
frame.time = ase_frame.duration / 1000;
|
frame.time = ase_frame.duration / 1000;
|
||||||
anim.frames.push(frame);
|
anim.frames.push(frame);
|
||||||
|
@ -365,6 +332,10 @@ collider2d.inputs['M-t'] = function() { this.enabled = !this.enabled; }
|
||||||
collider2d.inputs['M-t'].doc = "Toggle if this collider is enabled.";
|
collider2d.inputs['M-t'].doc = "Toggle if this collider is enabled.";
|
||||||
|
|
||||||
component.polygon2d = Object.copy(collider2d, {
|
component.polygon2d = Object.copy(collider2d, {
|
||||||
|
toJSON:json_from_whitelist([
|
||||||
|
'points',
|
||||||
|
'sensor'
|
||||||
|
]),
|
||||||
toString() { return "polygon2d"; },
|
toString() { return "polygon2d"; },
|
||||||
flipx: false,
|
flipx: false,
|
||||||
flipy: false,
|
flipy: false,
|
||||||
|
@ -463,6 +434,13 @@ polygon2d.inputs['C-b'] = function() {
|
||||||
polygon2d.inputs['C-b'].doc = "Freeze mirroring in place.";
|
polygon2d.inputs['C-b'].doc = "Freeze mirroring in place.";
|
||||||
|
|
||||||
component.edge2d = Object.copy(collider2d, {
|
component.edge2d = Object.copy(collider2d, {
|
||||||
|
toJSON:json_from_whitelist([
|
||||||
|
'sensor',
|
||||||
|
'thickness',
|
||||||
|
'points',
|
||||||
|
'hollow',
|
||||||
|
'hollowt',
|
||||||
|
]),
|
||||||
dimensions:2,
|
dimensions:2,
|
||||||
thickness:0,
|
thickness:0,
|
||||||
/* if type === -1, point to point */
|
/* if type === -1, point to point */
|
||||||
|
@ -821,6 +799,11 @@ component.circle2d = Object.copy(collider2d, {
|
||||||
});
|
});
|
||||||
|
|
||||||
component.circle2d.impl = Object.mix({
|
component.circle2d.impl = Object.mix({
|
||||||
|
toJSON:json_from_whitelist([
|
||||||
|
"pos",
|
||||||
|
"radius",
|
||||||
|
]),
|
||||||
|
|
||||||
set radius(x) { cmd_circle2d(0,this.id,x); },
|
set radius(x) { cmd_circle2d(0,this.id,x); },
|
||||||
get radius() { return cmd_circle2d(2,this.id); },
|
get radius() { return cmd_circle2d(2,this.id); },
|
||||||
|
|
||||||
|
@ -840,4 +823,4 @@ component.circle2d.impl = Object.mix({
|
||||||
|
|
||||||
}, collider2d.impl);
|
}, collider2d.impl);
|
||||||
|
|
||||||
return {component};
|
return {component, SpriteAnim};
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
function obj_unique_name(name, obj)
|
function obj_unique_name(name, obj) {
|
||||||
{
|
|
||||||
name = name.replaceAll('.', '_');
|
name = name.replaceAll('.', '_');
|
||||||
if (!(name in obj)) return name;
|
if (!(name in obj)) return name;
|
||||||
var t = 1;
|
var t = 1;
|
||||||
var n = name + t;
|
var n = name + t;
|
||||||
while (n in obj) {
|
while (n in obj) {
|
||||||
t++;
|
t++;
|
||||||
n = name+t;
|
n = name + t;
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var gameobject_impl = {
|
var gameobject_impl = {
|
||||||
get pos() {
|
get pos() {
|
||||||
assert(this.master, `Entity ${this.toString()} has no master.`);
|
assert(this.master, `Entity ${this.toString()} has no master.`);
|
||||||
|
@ -27,7 +25,7 @@ var gameobject_impl = {
|
||||||
assert(this.master, `No master set on ${this.toString()}`);
|
assert(this.master, `No master set on ${this.toString()}`);
|
||||||
return this.worldangle() - this.master.worldangle();
|
return this.worldangle() - this.master.worldangle();
|
||||||
},
|
},
|
||||||
|
|
||||||
set angle(x) {
|
set angle(x) {
|
||||||
var diff = x - this.angle;
|
var diff = x - this.angle;
|
||||||
|
|
||||||
|
@ -36,64 +34,64 @@ var gameobject_impl = {
|
||||||
x.pos = Vector.rotate(x.pos, diff);
|
x.pos = Vector.rotate(x.pos, diff);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.sworldangle(x-this.master.worldangle());
|
this.sworldangle(x - this.master.worldangle());
|
||||||
},
|
},
|
||||||
|
|
||||||
get scale() {
|
get scale() {
|
||||||
assert(this.master, `No master set on ${this.toString()}`);
|
assert(this.master, `No master set on ${this.toString()}`);
|
||||||
var pscale = [1,1,1];
|
var pscale = [1, 1, 1];
|
||||||
return this.gscale().map((x,i) => x/(this.master.gscale()[i]*pscale[i]));
|
return this.gscale().map((x, i) => x / (this.master.gscale()[i] * pscale[i]));
|
||||||
},
|
},
|
||||||
|
|
||||||
set scale(x) {
|
set scale(x) {
|
||||||
if (typeof x === 'number')
|
if (typeof x === 'number')
|
||||||
x = [x,x];
|
x = [x, x];
|
||||||
|
|
||||||
var pct = this.scale.map((s,i) => x[i]/s);
|
var pct = this.scale.map((s, i) => x[i] / s);
|
||||||
this.grow(pct);
|
this.grow(pct);
|
||||||
|
|
||||||
/* TRANSLATE ALL SUB OBJECTS */
|
/* TRANSLATE ALL SUB OBJECTS */
|
||||||
this.objects.forEach(obj => {
|
this.objects.forEach(obj => {
|
||||||
obj.grow(pct);
|
obj.grow(pct);
|
||||||
obj.pos = obj.pos.map((x,i)=>x*pct[i]);
|
obj.pos = obj.pos.map((x, i) => x * pct[i]);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
get draw_layer() { return cmd(171, this.body); },
|
get draw_layer() { return this.body.drawlayer; },
|
||||||
set draw_layer(x) { cmd(172, this.body, x); },
|
set draw_layer(x) { this.body.drawlayer = x; },
|
||||||
set layer(x) { cmd(75,this.body,x); },
|
set layer(x) { this.body.layer = x; },
|
||||||
get layer() { return cmd(77,this.body); },
|
get layer() { return this.body.layer; },
|
||||||
set warp_layer(x) { cmd(251, this.body,x); },
|
set warp_layer(x) { this.body.warp_filter = x; },
|
||||||
get warp_layer() { return cmd(252, this.body); },
|
get warp_layer() { return this.body.warp_filter; },
|
||||||
|
|
||||||
set mass(x) { set_body(7,this.body,x); },
|
set mass(x) { set_body(7, this.body, x); },
|
||||||
get mass() {
|
get mass() {
|
||||||
if (!(this.phys === physics.dynamic))
|
if (!(this.phys === physics.dynamic))
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
||||||
return q_body(5, this.body);
|
return q_body(5, this.body);
|
||||||
},
|
},
|
||||||
get elasticity() { return cmd(107,this.body); },
|
get elasticity() { return this.body.e; },
|
||||||
set elasticity(x) { cmd(106,this.body,x); },
|
set elasticity(x) { this.body.e = x; },
|
||||||
get friction() { return cmd(109,this.body); },
|
get friction() { return this.body.f; },
|
||||||
set friction(x) { cmd(108,this.body,x); },
|
set friction(x) { this.body.f = x; },
|
||||||
set timescale(x) { cmd(168,this.body,x); },
|
set timescale(x) { this.body.timescale = x; },
|
||||||
get timescale() { return cmd(169,this.body); },
|
get timescale() { return this.body.timescale; },
|
||||||
set phys(x) { set_body(1, this.body, x); },
|
set phys(x) { set_body(1, this.body, x); },
|
||||||
get phys() { return q_body(0,this.body); },
|
get phys() { return q_body(0, this.body); },
|
||||||
get velocity() { return q_body(3, this.body); },
|
get velocity() { return q_body(3, this.body); },
|
||||||
set velocity(x) { set_body(9, this.body, x); },
|
set velocity(x) { set_body(9, this.body, x); },
|
||||||
get damping() { return cmd(157,this.body); },
|
get damping() { return this.body.damping; },
|
||||||
set damping(x) { cmd(156, this.body, x); },
|
set damping(x) { this.body.damping = x },
|
||||||
get angularvelocity() { return Math.rad2turn(q_body(4,this.body)); },
|
get angularvelocity() { return Math.rad2turn(q_body(4, this.body)); },
|
||||||
set angularvelocity(x) { set_body(8, this.body, Math.turn2rad(x)); },
|
set angularvelocity(x) { set_body(8, this.body, Math.turn2rad(x)); },
|
||||||
get max_velocity() { return cmd(152, this.body); },
|
get max_velocity() { return this.body.maxvelocity; },
|
||||||
set max_velocity(x) { cmd(151, this.body, x); },
|
set max_velocity(x) { this.body.maxvelocity = x; },
|
||||||
get max_angularvelocity() { return cmd(155,this.body); },
|
get max_angularvelocity() { return this.body.maxangularvelocity; },
|
||||||
set max_angularvelocity(x) { cmd(154,this.body,x); },
|
set max_angularvelocity(x) { this.body.maxangularvelocity = x; },
|
||||||
get_moi() { return q_body(6, this.body); },
|
get_moi() { return q_body(6, this.body); },
|
||||||
set_moi(x) {
|
set_moi(x) {
|
||||||
if(x <= 0) {
|
if (x <= 0) {
|
||||||
console.error("Cannot set moment of inertia to 0 or less.");
|
console.error("Cannot set moment of inertia to 0 or less.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -117,7 +115,7 @@ var gameobject = {
|
||||||
var lur = ur[this.master.ur];
|
var lur = ur[this.master.ur];
|
||||||
if (!lur) return;
|
if (!lur) return;
|
||||||
var lur = lur.objects[this.toString()];
|
var lur = lur.objects[this.toString()];
|
||||||
var d = ediff(this._ed.urdiff,lur);
|
var d = ediff(this._ed.urdiff, lur);
|
||||||
if (!d || Object.empty(d))
|
if (!d || Object.empty(d))
|
||||||
this._ed.inst = true;
|
this._ed.inst = true;
|
||||||
else
|
else
|
||||||
|
@ -127,7 +125,7 @@ var gameobject = {
|
||||||
selectable: false,
|
selectable: false,
|
||||||
dirty: false
|
dirty: false
|
||||||
},
|
},
|
||||||
|
|
||||||
namestr() {
|
namestr() {
|
||||||
var s = this.toString();
|
var s = this.toString();
|
||||||
if (this._ed.dirty)
|
if (this._ed.dirty)
|
||||||
|
@ -137,41 +135,41 @@ var gameobject = {
|
||||||
},
|
},
|
||||||
|
|
||||||
urstr() {
|
urstr() {
|
||||||
if (this._ed.dirty) return "*"+this.ur;
|
if (this._ed.dirty) return "*" + this.ur;
|
||||||
return this.ur;
|
return this.ur;
|
||||||
},
|
},
|
||||||
|
|
||||||
full_path() {
|
full_path() {
|
||||||
return this.path_from(world);
|
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 = cmd(222,this.body, to.body);
|
var p = cmd(222, this.body, to.body);
|
||||||
},
|
},
|
||||||
slide(to, a, b, min, max) {
|
slide(to, a, b, min, max) {
|
||||||
a ??= [0,0];
|
a ??= [0, 0];
|
||||||
b ??= [0,0];
|
b ??= [0, 0];
|
||||||
min ??= 0;
|
min ??= 0;
|
||||||
max ??= 50;
|
max ??= 50;
|
||||||
var p = cmd(229,this.body,to.body,a,b,min,max);
|
var p = cmd(229, this.body, to.body, a, b, min, max);
|
||||||
p.max_force = 500;
|
p.max_force = 500;
|
||||||
p.break();
|
p.break();
|
||||||
},
|
},
|
||||||
pivot(to, piv) {
|
pivot(to, piv) {
|
||||||
piv ??= this.worldpos();
|
piv ??= this.worldpos();
|
||||||
var p = cmd(221,this.body,to.body,piv);
|
var p = cmd(221, this.body, to.body, piv);
|
||||||
},
|
},
|
||||||
/* groove is on to, from local points a and b, anchored to this at local anchor */
|
/* groove is on to, from local points a and b, anchored to this at local anchor */
|
||||||
groove(to, a, b, anchor) {
|
groove(to, a, b, anchor) {
|
||||||
anchor ??= [0,0];
|
anchor ??= [0, 0];
|
||||||
var p = cmd(228, to.body, this.body, a, b, anchor);
|
var p = cmd(228, to.body, this.body, a, b, anchor);
|
||||||
},
|
},
|
||||||
damped_spring(to, length, stiffness, damping) {
|
damped_spring(to, length, stiffness, damping) {
|
||||||
length ??= Vector.length(this.worldpos(), to.worldpos());
|
length ??= Vector.length(this.worldpos(), to.worldpos());
|
||||||
stiffness ??= 1;
|
stiffness ??= 1;
|
||||||
damping ??= 1;
|
damping ??= 1;
|
||||||
var dc = 2*Math.sqrt(stiffness*this.mass);
|
var dc = 2 * Math.sqrt(stiffness * this.mass);
|
||||||
var p = cmd(227, this.body, to.body, [0,0], [0,0], stiffness, damping*dc);
|
var p = cmd(227, this.body, to.body, [0, 0], [0, 0], stiffness, damping * dc);
|
||||||
},
|
},
|
||||||
damped_rotary_spring(to, angle, stiffness, damping) {
|
damped_rotary_spring(to, angle, stiffness, damping) {
|
||||||
angle ??= 0;
|
angle ??= 0;
|
||||||
|
@ -179,14 +177,14 @@ var gameobject = {
|
||||||
damping ??= 1;
|
damping ??= 1;
|
||||||
/* calculate actual damping value from the damping ratio */
|
/* calculate actual damping value from the damping ratio */
|
||||||
/* damping = 1 is critical */
|
/* damping = 1 is critical */
|
||||||
var dc = 2*Math.sqrt(stiffness*this.get_moi()); /* critical damping number */
|
var dc = 2 * Math.sqrt(stiffness * this.get_moi()); /* critical damping number */
|
||||||
/* zeta = actual/critical */
|
/* zeta = actual/critical */
|
||||||
var p = cmd(226,this.body,to.body,angle,stiffness,damping*dc);
|
var p = cmd(226, this.body, to.body, angle, stiffness, damping * dc);
|
||||||
},
|
},
|
||||||
rotary_limit(to, min, max) {
|
rotary_limit(to, min, max) {
|
||||||
var p = cmd(225,this.body,to.body, Math.turn2rad(min),Math.turn2rad(max));
|
var p = cmd(225, this.body, to.body, Math.turn2rad(min), Math.turn2rad(max));
|
||||||
},
|
},
|
||||||
ratchet(to,ratch) {
|
ratchet(to, ratch) {
|
||||||
var phase = this.angle - to.angle;
|
var phase = this.angle - to.angle;
|
||||||
var p = cmd(230, this.body, to.body, phase, Math.turn2rad(ratch));
|
var p = cmd(230, this.body, to.body, phase, Math.turn2rad(ratch));
|
||||||
},
|
},
|
||||||
|
@ -194,183 +192,187 @@ var gameobject = {
|
||||||
phase ??= 1;
|
phase ??= 1;
|
||||||
ratio ??= 1;
|
ratio ??= 1;
|
||||||
var phase = this.angle - to.angle;
|
var phase = this.angle - to.angle;
|
||||||
var p = cmd(223,this.body,to.body,phase,ratio);
|
var p = cmd(223, this.body, to.body, phase, ratio);
|
||||||
},
|
},
|
||||||
motor(to, rate) {
|
motor(to, rate) {
|
||||||
var p = cmd(231, this.body, to.body, rate);
|
var p = cmd(231, this.body, to.body, 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 t = timer.delay(fn.bind(this), seconds);
|
|
||||||
this.timers.push(t);
|
|
||||||
return t;
|
|
||||||
},
|
|
||||||
|
|
||||||
tween(prop, values, def){
|
path_from(o) {
|
||||||
var t = Tween.make(this, prop, values, def);
|
var p = this.toString();
|
||||||
t.play();
|
var c = this.master;
|
||||||
|
while (c && c !== o && c !== world) {
|
||||||
var k = function() { t.pause(); }
|
p = c.toString() + "." + p;
|
||||||
this.timers.push(k);
|
c = c.master;
|
||||||
return k;
|
}
|
||||||
},
|
if (c === world) p = "world." + p;
|
||||||
|
return p;
|
||||||
|
},
|
||||||
|
|
||||||
cry(file) {
|
clear() {
|
||||||
return;
|
for (var k in this.objects) {
|
||||||
this.crying = audio.sound.play(file, audio.sound.bus.sfx);
|
this.objects[k].kill();
|
||||||
var killfn = () => {this.crying = undefined; console.warn("killed"); }
|
};
|
||||||
this.crying.hook = killfn;
|
this.objects = {};
|
||||||
return killfn;
|
},
|
||||||
},
|
|
||||||
|
|
||||||
set torque(x) { if (!(x >= 0 && x <= Infinity)) return; cmd(153, this.body, x); },
|
delay(fn, seconds) {
|
||||||
gscale() { return cmd(103,this.body); },
|
var t = timer.delay(fn.bind(this), seconds);
|
||||||
sgscale(x) {
|
this.timers.push(t);
|
||||||
if (typeof x === 'number')
|
return t;
|
||||||
x = [x,x];
|
},
|
||||||
cmd(36,this.body,x)
|
|
||||||
},
|
|
||||||
|
|
||||||
phys_material() {
|
|
||||||
var mat = {};
|
|
||||||
mat.elasticity = this.elasticity;
|
|
||||||
mat.friction = this.friction;
|
|
||||||
return mat;
|
|
||||||
},
|
|
||||||
|
|
||||||
worldpos() { return q_body(1,this.body); },
|
tween(prop, values, def) {
|
||||||
set_worldpos(x) {
|
var t = Tween.make(this, prop, values, def);
|
||||||
var poses = this.objects.map(x => x.pos);
|
t.play();
|
||||||
set_body(2,this.body,x);
|
|
||||||
this.objects.forEach((o,i) => o.set_worldpos(this.this2world(poses[i])));
|
|
||||||
},
|
|
||||||
screenpos() { return Window.world2screen(this.worldpos()); },
|
|
||||||
|
|
||||||
worldangle() { return Math.rad2turn(q_body(2,this.body)); },
|
var k = function() { t.pause(); }
|
||||||
sworldangle(x) { set_body(0,this.body,Math.turn2rad(x)); },
|
this.timers.push(k);
|
||||||
|
return k;
|
||||||
|
},
|
||||||
|
|
||||||
get_ur() {
|
cry(file) {
|
||||||
// if (this.ur === 'empty') return undefined;
|
return;
|
||||||
return Object.access(ur,this.ur);
|
this.crying = audio.sound.play(file, audio.sound.bus.sfx);
|
||||||
},
|
var killfn = () => { this.crying = undefined;
|
||||||
|
console.warn("killed"); }
|
||||||
|
this.crying.hook = killfn;
|
||||||
|
return killfn;
|
||||||
|
},
|
||||||
|
|
||||||
/* spawn an entity
|
set torque(x) { if (!(x >= 0 && x <= Infinity)) return;
|
||||||
|
cmd(153, this.body, x); },
|
||||||
|
gscale() { return cmd(103, this.body); },
|
||||||
|
sgscale(x) {
|
||||||
|
if (typeof x === 'number')
|
||||||
|
x = [x, x];
|
||||||
|
cmd(36, this.body, x)
|
||||||
|
},
|
||||||
|
|
||||||
|
phys_material() {
|
||||||
|
var mat = {};
|
||||||
|
mat.elasticity = this.elasticity;
|
||||||
|
mat.friction = this.friction;
|
||||||
|
return mat;
|
||||||
|
},
|
||||||
|
|
||||||
|
worldpos() { return q_body(1, this.body); },
|
||||||
|
set_worldpos(x) {
|
||||||
|
var poses = this.objects.map(x => x.pos);
|
||||||
|
set_body(2, this.body, x);
|
||||||
|
this.objects.forEach((o, i) => o.set_worldpos(this.this2world(poses[i])));
|
||||||
|
},
|
||||||
|
screenpos() { return Window.world2screen(this.worldpos()); },
|
||||||
|
|
||||||
|
worldangle() { return Math.rad2turn(q_body(2, this.body)); },
|
||||||
|
sworldangle(x) { set_body(0, this.body, Math.turn2rad(x)); },
|
||||||
|
|
||||||
|
get_ur() {
|
||||||
|
// if (this.ur === 'empty') return undefined;
|
||||||
|
return Object.access(ur, this.ur);
|
||||||
|
},
|
||||||
|
|
||||||
|
/* spawn an entity
|
||||||
text can be:
|
text can be:
|
||||||
the file path of a script
|
the file path of a script
|
||||||
an ur object
|
an ur object
|
||||||
nothing
|
nothing
|
||||||
*/
|
*/
|
||||||
spawn(text) {
|
spawn(text) {
|
||||||
var ent = Object.create(gameobject);
|
var ent = Object.create(gameobject);
|
||||||
|
|
||||||
if (typeof text === 'object')
|
|
||||||
text = text.name;
|
|
||||||
|
|
||||||
if (typeof text === 'undefined')
|
if (typeof text === 'object')
|
||||||
ent.ur = "empty";
|
text = text.name;
|
||||||
else if (typeof text !== 'string') {
|
|
||||||
console.error(`Must pass in an ur type or a string to make an entity.`);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (Object.access(ur,text))
|
|
||||||
ent.ur = text;
|
|
||||||
else if (io.exists(text))
|
|
||||||
ent.ur = "script";
|
|
||||||
else {
|
|
||||||
console.warn(`Cannot make an entity from '${text}'. Not a valid ur.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.mixin(ent,gameobject_impl);
|
|
||||||
ent.body = make_gameobject();
|
|
||||||
ent.warp_layer = [true];
|
|
||||||
ent.phys = 2;
|
|
||||||
ent.components = {};
|
|
||||||
ent.objects = {};
|
|
||||||
ent.timers = [];
|
|
||||||
|
|
||||||
ent.reparent(this);
|
|
||||||
|
|
||||||
ent._ed = {
|
if (typeof text === 'undefined')
|
||||||
selectable: true,
|
ent.ur = "empty";
|
||||||
dirty: false,
|
else if (typeof text !== 'string') {
|
||||||
inst: false,
|
console.error(`Must pass in an ur type or a string to make an entity.`);
|
||||||
urdiff: {},
|
return;
|
||||||
};
|
} else {
|
||||||
|
if (Object.access(ur, text))
|
||||||
|
ent.ur = text;
|
||||||
|
else if (io.exists(text))
|
||||||
|
ent.ur = "script";
|
||||||
|
else {
|
||||||
|
console.warn(`Cannot make an entity from '${text}'. Not a valid ur.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cmd(113, ent.body, ent); // set the internal obj reference to this obj
|
Object.mixin(ent, gameobject_impl);
|
||||||
|
ent.body = make_gameobject();
|
||||||
|
ent.warp_layer = [true];
|
||||||
|
ent.phys = 2;
|
||||||
|
ent.components = {};
|
||||||
|
ent.objects = {};
|
||||||
|
ent.timers = [];
|
||||||
|
|
||||||
Object.hide(ent, 'ur', 'body', 'components', 'objects', '_ed', 'timers', 'master');
|
ent.reparent(this);
|
||||||
if (ent.ur === 'empty') {
|
|
||||||
if (!ur.empty.proto) ur.empty.proto = json.decode(json.encode(ent));
|
|
||||||
return ent;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ent.ur === 'script')
|
ent._ed = {
|
||||||
eval_env(io.slurp(text), ent, ent.ur);
|
selectable: true,
|
||||||
else
|
dirty: false,
|
||||||
apply_ur(ent.ur, ent);
|
inst: false,
|
||||||
|
urdiff: {},
|
||||||
|
};
|
||||||
|
|
||||||
for (var [prop,p] of Object.entries(ent)) {
|
cmd(113, ent.body, ent); // set the internal obj reference to this obj
|
||||||
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);
|
Object.hide(ent, 'ur', 'body', 'components', 'objects', '_ed', 'timers', 'master');
|
||||||
ent.components.forEach(function(x) {
|
if (ent.ur === 'empty') {
|
||||||
if (typeof x.collide === 'function')
|
if (!ur.empty.proto) ur.empty.proto = json.decode(json.encode(ent));
|
||||||
register_collide(1, x.collide.bind(x), ent.body, x.shape);
|
return ent;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
|
||||||
if (typeof ent.load === 'function') ent.load();
|
|
||||||
if (Game.playing())
|
|
||||||
if (typeof ent.start === 'function') ent.start();
|
|
||||||
|
|
||||||
var mur = ent.get_ur();
|
|
||||||
if (mur && !mur.proto)
|
|
||||||
mur.proto = json.decode(json.encode(ent));
|
|
||||||
|
|
||||||
ent.sync();
|
|
||||||
|
|
||||||
if (!Object.empty(ent.objects)) {
|
|
||||||
var o = ent.objects;
|
|
||||||
delete ent.objects;
|
|
||||||
for (var i in o) {
|
|
||||||
say(`MAKING ${i}`);
|
|
||||||
var n = ent.spawn(ur[o[i].ur]);
|
|
||||||
ent.rename_obj(n.toString(), i);
|
|
||||||
delete o[i].ur;
|
|
||||||
Object.assign(n, o[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ent;
|
if (ent.ur === 'script')
|
||||||
},
|
eval_env(io.slurp(text), ent, ent.ur);
|
||||||
|
else
|
||||||
|
apply_ur(ent.ur, ent);
|
||||||
|
|
||||||
|
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);
|
||||||
|
ent.components.forEach(function(x) {
|
||||||
|
if (typeof x.collide === 'function')
|
||||||
|
register_collide(1, x.collide.bind(x), ent.body, x.shape);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (typeof ent.load === 'function') ent.load();
|
||||||
|
if (Game.playing())
|
||||||
|
if (typeof ent.start === 'function') ent.start();
|
||||||
|
|
||||||
|
var mur = ent.get_ur();
|
||||||
|
if (mur && !mur.proto)
|
||||||
|
mur.proto = json.decode(json.encode(ent));
|
||||||
|
|
||||||
|
ent.sync();
|
||||||
|
|
||||||
|
if (!Object.empty(ent.objects)) {
|
||||||
|
var o = ent.objects;
|
||||||
|
delete ent.objects;
|
||||||
|
for (var i in o) {
|
||||||
|
say(`MAKING ${i}`);
|
||||||
|
var n = ent.spawn(ur[o[i].ur]);
|
||||||
|
ent.rename_obj(n.toString(), i);
|
||||||
|
delete o[i].ur;
|
||||||
|
Object.assign(n, o[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.body.phys = this.body.phys; // simple way to sync
|
||||||
|
|
||||||
|
return ent;
|
||||||
|
},
|
||||||
|
|
||||||
/* Reparent 'this' to be 'parent's child */
|
/* Reparent 'this' to be 'parent's child */
|
||||||
reparent(parent) {
|
reparent(parent) {
|
||||||
|
@ -382,9 +384,9 @@ var gameobject = {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.master?.remove_obj(this);
|
this.master?.remove_obj(this);
|
||||||
|
|
||||||
this.master = parent;
|
this.master = parent;
|
||||||
|
|
||||||
function unique_name(list, name) {
|
function unique_name(list, name) {
|
||||||
name ??= "new_object";
|
name ??= "new_object";
|
||||||
var str = name.replaceAll('.', '_');
|
var str = name.replaceAll('.', '_');
|
||||||
|
@ -392,7 +394,7 @@ var gameobject = {
|
||||||
var t = str;
|
var t = str;
|
||||||
while (list.indexOf(t) !== -1) {
|
while (list.indexOf(t) !== -1) {
|
||||||
t = str + n;
|
t = str + n;
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
};
|
};
|
||||||
|
@ -403,34 +405,36 @@ var gameobject = {
|
||||||
parent[name] = this;
|
parent[name] = this;
|
||||||
this.toString = function() { return name; };
|
this.toString = function() { return name; };
|
||||||
},
|
},
|
||||||
|
|
||||||
remove_obj(obj) {
|
remove_obj(obj) {
|
||||||
if (this[obj.toString()] === this.objects[obj.toString()])
|
if (this[obj.toString()] === this.objects[obj.toString()])
|
||||||
delete this[obj.toString()];
|
delete this[obj.toString()];
|
||||||
|
|
||||||
delete this.objects[obj.toString()];
|
delete this.objects[obj.toString()];
|
||||||
delete this[obj.toString()];
|
delete this[obj.toString()];
|
||||||
},
|
},
|
||||||
|
|
||||||
components: {},
|
components: {},
|
||||||
objects: {},
|
objects: {},
|
||||||
master: undefined,
|
master: undefined,
|
||||||
|
|
||||||
pulse(vec) { set_body(4, this.body, vec);},
|
|
||||||
shove(vec) { set_body(12,this.body,vec);},
|
|
||||||
shove_at(vec, at) { set_body(14,this.body,vec,at); },
|
|
||||||
world2this(pos) { return cmd(70, this.body, pos); },
|
|
||||||
this2world(pos) { return cmd(71, this.body, pos); },
|
|
||||||
this2screen(pos) { return Window.world2screen(this.this2world(pos)); },
|
|
||||||
screen2this(pos) { return this.world2this(Window.screen2world(pos)); },
|
|
||||||
dir_world2this(dir) { return cmd(160, this.body, dir); },
|
|
||||||
dir_this2world(dir) { return cmd(161, this.body, dir); },
|
|
||||||
|
|
||||||
alive() { return this.body >= 0; },
|
|
||||||
in_air() { return q_body(7, this.body);},
|
|
||||||
|
|
||||||
hide() { this.components.forEach(x=>x.hide?.()); this.objects.forEach(x=>x.hide?.());},
|
pulse(vec) { set_body(4, this.body, vec); },
|
||||||
show() { this.components.forEach(function(x) { x.show?.(); }); this.objects.forEach(function(x) { x.show?.(); }); },
|
shove(vec) { set_body(12, this.body, vec); },
|
||||||
|
shove_at(vec, at) { set_body(14, this.body, vec, at); },
|
||||||
|
world2this(pos) { return cmd(70, this.body, pos); },
|
||||||
|
this2world(pos) { return cmd(71, this.body, pos); },
|
||||||
|
this2screen(pos) { return Window.world2screen(this.this2world(pos)); },
|
||||||
|
screen2this(pos) { return this.world2this(Window.screen2world(pos)); },
|
||||||
|
dir_world2this(dir) { return cmd(160, this.body, dir); },
|
||||||
|
dir_this2world(dir) { return cmd(161, this.body, dir); },
|
||||||
|
|
||||||
|
alive() { return this.body >= 0; },
|
||||||
|
in_air() { return q_body(7, this.body); },
|
||||||
|
|
||||||
|
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() {
|
width() {
|
||||||
var bb = this.boundingbox();
|
var bb = this.boundingbox();
|
||||||
|
@ -439,13 +443,13 @@ var gameobject = {
|
||||||
|
|
||||||
height() {
|
height() {
|
||||||
var bb = this.boundingbox();
|
var bb = this.boundingbox();
|
||||||
return bb.t-bb.b;
|
return bb.t - bb.b;
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Moving, rotating, scaling functions, world relative */
|
/* Moving, rotating, scaling functions, world relative */
|
||||||
move(vec) { this.set_worldpos(this.worldpos().add(vec)); },
|
move(vec) { this.set_worldpos(this.worldpos().add(vec)); },
|
||||||
rotate(x) { this.sworldangle(this.worldangle()+x); },
|
rotate(x) { this.sworldangle(this.worldangle() + x); },
|
||||||
grow(vec) { this.sgscale(this.gscale().map((x,i)=>x*vec[i])); },
|
grow(vec) { this.sgscale(this.gscale().map((x, i) => x * vec[i])); },
|
||||||
|
|
||||||
/* Make a unique object the same as its prototype */
|
/* Make a unique object the same as its prototype */
|
||||||
revert() {
|
revert() {
|
||||||
|
@ -462,155 +466,155 @@ var gameobject = {
|
||||||
},
|
},
|
||||||
|
|
||||||
toString() { return "new_object"; },
|
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) {
|
mirror(plane) {
|
||||||
this.scale = Vector.reflect(this.scale, plane);
|
this.scale = Vector.reflect(this.scale, plane);
|
||||||
},
|
},
|
||||||
|
|
||||||
save:true,
|
|
||||||
selectable:true,
|
|
||||||
ed_locked:false,
|
|
||||||
|
|
||||||
disable() { this.components.forEach(function(x) { x.disable(); });},
|
|
||||||
enable() { this.components.forEach(function(x) { x.enable(); });},
|
|
||||||
sync() {
|
|
||||||
this.components.forEach(function(x) { x.sync?.(); });
|
|
||||||
this.objects.forEach(function(x) { x.sync?.(); });
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Bounding box of the object in world dimensions */
|
save: true,
|
||||||
boundingbox() {
|
selectable: true,
|
||||||
var boxes = [];
|
ed_locked: false,
|
||||||
boxes.push({
|
|
||||||
t:0,
|
|
||||||
r:0,
|
|
||||||
b:0,
|
|
||||||
l:0
|
|
||||||
});
|
|
||||||
|
|
||||||
for (var key in this.components) {
|
disable() { this.components.forEach(function(x) { x.disable(); }); },
|
||||||
if ('boundingbox' in this.components[key])
|
enable() { this.components.forEach(function(x) { x.enable(); }); },
|
||||||
boxes.push(this.components[key].boundingbox());
|
sync() {
|
||||||
}
|
this.components.forEach(function(x) { x.sync?.(); });
|
||||||
for (var key in this.objects)
|
this.objects.forEach(function(x) { x.sync?.(); });
|
||||||
boxes.push(this.objects[key].boundingbox());
|
},
|
||||||
|
|
||||||
var bb = boxes.shift();
|
/* Bounding box of the object in world dimensions */
|
||||||
|
boundingbox() {
|
||||||
|
var boxes = [];
|
||||||
|
boxes.push({
|
||||||
|
t: 0,
|
||||||
|
r: 0,
|
||||||
|
b: 0,
|
||||||
|
l: 0
|
||||||
|
});
|
||||||
|
|
||||||
boxes.forEach(function(x) { bb = bbox.expand(bb, x); });
|
for (var key in this.components) {
|
||||||
|
if ('boundingbox' in this.components[key])
|
||||||
bb = bbox.move(bb, this.pos);
|
boxes.push(this.components[key].boundingbox());
|
||||||
|
}
|
||||||
|
for (var key in this.objects)
|
||||||
|
boxes.push(this.objects[key].boundingbox());
|
||||||
|
|
||||||
return bb ? bb : bbox.fromcwh([0,0], [0,0]);
|
var bb = boxes.shift();
|
||||||
},
|
|
||||||
|
|
||||||
/* The unique components of this object. Its diff. */
|
boxes.forEach(function(x) { bb = bbox.expand(bb, x); });
|
||||||
json_obj() {
|
|
||||||
var u = this.get_ur();
|
|
||||||
if (!u) return {};
|
|
||||||
var proto = u.proto;
|
|
||||||
var thiso = json.decode(json.encode(this)); // TODO: SLOW. Used to ignore properties in toJSON of components.
|
|
||||||
|
|
||||||
var d = ediff(thiso,proto);
|
|
||||||
|
|
||||||
d ??= {};
|
|
||||||
|
|
||||||
var objects = {};
|
|
||||||
proto.objects ??= {};
|
|
||||||
var curobjs = {};
|
|
||||||
for (var o in this.objects)
|
|
||||||
curobjs[o] = this.objects[o].instance_obj();
|
|
||||||
|
|
||||||
var odiff = ediff(curobjs, proto.objects);
|
bb = bbox.move(bb, this.pos);
|
||||||
if (odiff)
|
|
||||||
d.objects = curobjs;
|
|
||||||
|
|
||||||
delete d.pos;
|
return bb ? bb : bbox.fromcwh([0, 0], [0, 0]);
|
||||||
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 */
|
/* The unique components of this object. Its diff. */
|
||||||
instance_obj() {
|
json_obj() {
|
||||||
var t = this.transform();
|
var u = this.get_ur();
|
||||||
t.ur = this.ur;
|
if (!u) return {};
|
||||||
return t;
|
var proto = u.proto;
|
||||||
},
|
var thiso = json.decode(json.encode(this)); // TODO: SLOW. Used to ignore properties in toJSON of components.
|
||||||
|
|
||||||
proto() {
|
var d = ediff(thiso, proto);
|
||||||
var u = this.get_ur();
|
|
||||||
if (!u) return {};
|
|
||||||
return u.proto;
|
|
||||||
},
|
|
||||||
|
|
||||||
transform() {
|
d ??= {};
|
||||||
var t = {};
|
|
||||||
t.pos = this.pos;
|
|
||||||
if (t.pos.every(x=>x===0)) delete t.pos;
|
|
||||||
t.angle = Math.places(this.angle,4);
|
|
||||||
if (t.angle === 0) delete t.angle;
|
|
||||||
t.scale = this.scale;
|
|
||||||
t.scale = t.scale.map((x,i) => x/this.proto().scale[i]);
|
|
||||||
t.scale = t.scale.map(x => Math.places(x,3));
|
|
||||||
if (t.scale.every(x=>x===1)) delete t.scale;
|
|
||||||
return t;
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Velocity and angular velocity of the object */
|
var objects = {};
|
||||||
phys_obj() {
|
proto.objects ??= {};
|
||||||
var phys = {};
|
var curobjs = {};
|
||||||
phys.velocity = this.velocity;
|
for (var o in this.objects)
|
||||||
phys.angularvelocity = this.angularvelocity;
|
curobjs[o] = this.objects[o].instance_obj();
|
||||||
return phys;
|
|
||||||
},
|
|
||||||
|
|
||||||
dup(diff) {
|
var odiff = ediff(curobjs, proto.objects);
|
||||||
var n = this.master.spawn(this.__proto__);
|
if (odiff)
|
||||||
Object.totalmerge(n, this.instance_obj());
|
d.objects = curobjs;
|
||||||
return n;
|
|
||||||
},
|
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;
|
||||||
|
return t;
|
||||||
|
},
|
||||||
|
|
||||||
|
proto() {
|
||||||
|
var u = this.get_ur();
|
||||||
|
if (!u) return {};
|
||||||
|
return u.proto;
|
||||||
|
},
|
||||||
|
|
||||||
|
transform() {
|
||||||
|
var t = {};
|
||||||
|
t.pos = this.pos;
|
||||||
|
if (t.pos.every(x => x === 0)) delete t.pos;
|
||||||
|
t.angle = Math.places(this.angle, 4);
|
||||||
|
if (t.angle === 0) delete t.angle;
|
||||||
|
t.scale = this.scale;
|
||||||
|
t.scale = t.scale.map((x, i) => x / this.proto().scale[i]);
|
||||||
|
t.scale = t.scale.map(x => Math.places(x, 3));
|
||||||
|
if (t.scale.every(x => x === 1)) delete t.scale;
|
||||||
|
return t;
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Velocity and angular velocity of the object */
|
||||||
|
phys_obj() {
|
||||||
|
var phys = {};
|
||||||
|
phys.velocity = this.velocity;
|
||||||
|
phys.angularvelocity = this.angularvelocity;
|
||||||
|
return phys;
|
||||||
|
},
|
||||||
|
|
||||||
|
dup(diff) {
|
||||||
|
var n = this.master.spawn(this.__proto__);
|
||||||
|
Object.totalmerge(n, this.instance_obj());
|
||||||
|
return n;
|
||||||
|
},
|
||||||
|
|
||||||
kill() {
|
kill() {
|
||||||
if (this.__kill) return;
|
if (this.__kill) return;
|
||||||
this.__kill = true;
|
this.__kill = true;
|
||||||
|
|
||||||
this.timers.forEach(t => t());
|
this.timers.forEach(t => t());
|
||||||
this.timers = [];
|
this.timers = [];
|
||||||
Event.rm_obj(this);
|
Event.rm_obj(this);
|
||||||
Player.do_uncontrol(this);
|
Player.do_uncontrol(this);
|
||||||
register_collide(2, undefined, this.body);
|
register_collide(2, undefined, this.body);
|
||||||
|
|
||||||
if (this.master) {
|
if (this.master) {
|
||||||
this.master.remove_obj(this);
|
this.master.remove_obj(this);
|
||||||
this.master = undefined;
|
this.master = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.__proto__.instances)
|
if (this.__proto__.instances)
|
||||||
delete this.__proto__.instances[this.toString()];
|
delete this.__proto__.instances[this.toString()];
|
||||||
|
|
||||||
for (var key in this.components) {
|
for (var key in this.components) {
|
||||||
this.components[key].kill();
|
this.components[key].kill?.();
|
||||||
this.components[key].gameobject = undefined;
|
this.components[key].gameobject = undefined;
|
||||||
delete this.components[key];
|
delete this.components[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.clear();
|
this.clear();
|
||||||
this.objects = undefined;
|
this.objects = undefined;
|
||||||
|
|
||||||
if (typeof this.stop === 'function') this.stop();
|
if (typeof this.stop === 'function') this.stop();
|
||||||
if (typeof this.die === 'function') this.die();
|
if (typeof this.die === 'function') this.die();
|
||||||
},
|
},
|
||||||
|
|
||||||
up() { return [0,1].rotate(this.angle);},
|
up() { return [0, 1].rotate(this.angle); },
|
||||||
down() { return [0,-1].rotate(this.angle);},
|
down() { return [0, -1].rotate(this.angle); },
|
||||||
right() { return [1,0].rotate(this.angle);},
|
right() { return [1, 0].rotate(this.angle); },
|
||||||
left() { 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) {
|
||||||
|
@ -659,7 +663,7 @@ var gameobject = {
|
||||||
this.objects[o].obj_descend(fn);
|
this.objects[o].obj_descend(fn);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
Object.mixin(gameobject,gameobject_impl);
|
Object.mixin(gameobject, gameobject_impl);
|
||||||
|
|
||||||
gameobject.spawn.doc = `Spawn an entity of type 'ur' on this entity. Returns the spawned entity.`;
|
gameobject.spawn.doc = `Spawn an entity of type 'ur' on this entity. Returns the spawned entity.`;
|
||||||
|
|
||||||
|
@ -737,14 +741,13 @@ ur {
|
||||||
|
|
||||||
/* Apply an ur u to an entity e */
|
/* Apply an ur u to an entity e */
|
||||||
/* u is given as */
|
/* u is given as */
|
||||||
function apply_ur(u, e)
|
function apply_ur(u, e) {
|
||||||
{
|
|
||||||
console.log(`applying ur ${u}`);
|
console.log(`applying ur ${u}`);
|
||||||
if (typeof u !== 'string') {
|
if (typeof u !== 'string') {
|
||||||
console.warn("Must give u as a string.");
|
console.warn("Must give u as a string.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var urs = u.split('.');
|
var urs = u.split('.');
|
||||||
var config = {};
|
var config = {};
|
||||||
var topur = ur;
|
var topur = ur;
|
||||||
|
@ -759,7 +762,7 @@ function apply_ur(u, e)
|
||||||
var script = Resources.replstrs(topur.text);
|
var script = Resources.replstrs(topur.text);
|
||||||
eval_env(script, e, topur.text);
|
eval_env(script, e, topur.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topur.data) {
|
if (topur.data) {
|
||||||
var jss = Resources.replstrs(topur.data);
|
var jss = Resources.replstrs(topur.data);
|
||||||
Object.merge(config, json.decode(jss));
|
Object.merge(config, json.decode(jss));
|
||||||
|
@ -769,28 +772,27 @@ function apply_ur(u, e)
|
||||||
Object.merge(e, config);
|
Object.merge(e, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
function file2fqn(file)
|
function file2fqn(file) {
|
||||||
{
|
|
||||||
var fqn = file.strip_ext();
|
var fqn = file.strip_ext();
|
||||||
if (fqn.folder_same_name())
|
if (fqn.folder_same_name())
|
||||||
fqn = fqn.up_path();
|
fqn = fqn.up_path();
|
||||||
|
|
||||||
fqn = fqn.replace('/','.');
|
fqn = fqn.replace('/', '.');
|
||||||
var topur;
|
var topur;
|
||||||
if (topur = Object.access(ur,fqn)) return topur;
|
if (topur = Object.access(ur, fqn)) return topur;
|
||||||
|
|
||||||
var fqnlast = fqn.split('.').last();
|
var fqnlast = fqn.split('.').last();
|
||||||
|
|
||||||
if (topur = Object.access(ur,fqn.tolast('.'))) {
|
if (topur = Object.access(ur, fqn.tolast('.'))) {
|
||||||
topur[fqnlast] = {
|
topur[fqnlast] = {
|
||||||
name: fqn
|
name: fqn
|
||||||
};
|
};
|
||||||
ur._list.push(fqn);
|
ur._list.push(fqn);
|
||||||
return Object.access(ur,fqn);
|
return Object.access(ur, fqn);
|
||||||
}
|
}
|
||||||
|
|
||||||
fqn = fqnlast;
|
fqn = fqnlast;
|
||||||
|
|
||||||
ur[fqn] = {
|
ur[fqn] = {
|
||||||
name: fqn
|
name: fqn
|
||||||
};
|
};
|
||||||
|
@ -821,4 +823,4 @@ Game.loadurs = function() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
gameobject
|
gameobject
|
||||||
}
|
}
|
|
@ -40,6 +40,27 @@ var GUI = {
|
||||||
gui_img(path,pos, [1.0,1.0], 0.0, false, [0.0,0.0], Color.white);
|
gui_img(path,pos, [1.0,1.0], 0.0, false, [0.0,0.0], Color.white);
|
||||||
return bbox.fromcwh([0,0], wh);
|
return bbox.fromcwh([0,0], wh);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
newmg(img) {
|
||||||
|
var def = {
|
||||||
|
path: "",
|
||||||
|
pos: [0,0],
|
||||||
|
size:[0,0],
|
||||||
|
frame: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
w: 1,
|
||||||
|
h: 1
|
||||||
|
},
|
||||||
|
angle: 0,
|
||||||
|
anchor: [0,0],
|
||||||
|
color: Color.white,
|
||||||
|
}
|
||||||
|
for (var i in def)
|
||||||
|
img[i] ??= def[i];
|
||||||
|
|
||||||
|
gui_newmg
|
||||||
|
},
|
||||||
|
|
||||||
input_lmouse_pressed() {
|
input_lmouse_pressed() {
|
||||||
if (GUI.selected)
|
if (GUI.selected)
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
var audio = {};
|
var audio = {};
|
||||||
|
|
||||||
|
var sound_pref = ['wav', 'flac', 'mp3', 'qoa'];
|
||||||
|
|
||||||
audio.sound = {
|
audio.sound = {
|
||||||
bus: {},
|
bus: {},
|
||||||
samplerate() { return cmd(198); },
|
samplerate() { return cmd(198); },
|
||||||
sounds: [], /* array of loaded sound files */
|
sounds: [], /* array of loaded sound files */
|
||||||
play(file, bus) {
|
play(file, bus) {
|
||||||
if (!io.exists(file)) {
|
file = Resources.find_sound(file);
|
||||||
|
if (!file) {
|
||||||
console.error(`Cannot play sound ${file}: does not exist.`);
|
console.error(`Cannot play sound ${file}: does not exist.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,14 +41,27 @@ os.prefpath = function() {
|
||||||
var projectfile = ".prosperon/project.json";
|
var projectfile = ".prosperon/project.json";
|
||||||
|
|
||||||
var Resources = {};
|
var Resources = {};
|
||||||
Resources.images = ["png", "jpg", "jpeg", "gif"];
|
Resources.images = ["png", "gif", "jpg", "jpeg"];
|
||||||
Resources.sounds = ["wav", "mp3", "flac", "qoa"];
|
Resources.sounds = ["wav", 'flac', 'mp3', "qoa"];
|
||||||
Resources.scripts = "js";
|
Resources.scripts = "js";
|
||||||
Resources.is_image = function(path) {
|
Resources.is_image = function(path) {
|
||||||
var ext = path.ext();
|
var ext = path.ext();
|
||||||
return Resources.images.any(x => x === ext);
|
return Resources.images.any(x => x === ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function find_ext(file, ext)
|
||||||
|
{
|
||||||
|
if (io.exists(file)) return file;
|
||||||
|
for (var e of ext) {
|
||||||
|
var nf = `${file}.${e}`;
|
||||||
|
if (io.exists(nf)) return nf;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resources.find_image = function(file) { return find_ext(file,Resources.images); }
|
||||||
|
Resources.find_sound = function(file) { return find_ext(file,Resources.sounds); }
|
||||||
|
|
||||||
Resources.is_sound = function(path) {
|
Resources.is_sound = function(path) {
|
||||||
var ext = path.ext();
|
var ext = path.ext();
|
||||||
return Resources.sounds.any(x => x === ext);
|
return Resources.sounds.any(x => x === ext);
|
||||||
|
|
|
@ -21,6 +21,7 @@ cpSpace *space = NULL;
|
||||||
|
|
||||||
struct rgba color_white = {255,255,255,255};
|
struct rgba color_white = {255,255,255,255};
|
||||||
struct rgba color_black = {0,0,0,255};
|
struct rgba color_black = {0,0,0,255};
|
||||||
|
struct rgba color_clear = {0,0,0,0};
|
||||||
|
|
||||||
struct rgba disabled_color = {148,148,148,255};
|
struct rgba disabled_color = {148,148,148,255};
|
||||||
struct rgba sleep_color = {255,140,228,255};
|
struct rgba sleep_color = {255,140,228,255};
|
||||||
|
@ -624,13 +625,13 @@ JSValue arb2js(cpArbiter *arb)
|
||||||
norm.cp = cpArbiterGetNormal(arb);
|
norm.cp = cpArbiterGetNormal(arb);
|
||||||
|
|
||||||
JSValue obj = JS_NewObject(js);
|
JSValue obj = JS_NewObject(js);
|
||||||
JS_SetPropertyStr(js, obj, "normal", vec2js(norm));
|
JS_SetPropertyStr(js, obj, "normal", vec22js(norm));
|
||||||
JS_SetPropertyStr(js, obj, "obj", JS_DupValue(js,go2->ref));
|
JS_SetPropertyStr(js, obj, "obj", JS_DupValue(js,go2->ref));
|
||||||
JS_SetPropertyStr(js, obj, "sensor", JS_NewBool(js, cpShapeGetSensor(shape2)));
|
JS_SetPropertyStr(js, obj, "sensor", JS_NewBool(js, cpShapeGetSensor(shape2)));
|
||||||
|
|
||||||
HMM_Vec2 srfv;
|
HMM_Vec2 srfv;
|
||||||
srfv.cp = cpArbiterGetSurfaceVelocity(arb);
|
srfv.cp = cpArbiterGetSurfaceVelocity(arb);
|
||||||
JS_SetPropertyStr(js, obj, "velocity", vec2js(srfv));
|
JS_SetPropertyStr(js, obj, "velocity", vec22js(srfv));
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,19 +143,19 @@ void mesh_add_material(mesh *mesh, cgltf_material *mat)
|
||||||
mesh->bind.fs.images[0] = texture_fromdata(buf->buffer->data, buf->size)->id;
|
mesh->bind.fs.images[0] = texture_fromdata(buf->buffer->data, buf->size)->id;
|
||||||
} else {
|
} else {
|
||||||
// char *imp = seprint("%s/%s", dirname(mesh->model->path), img->uri);
|
// char *imp = seprint("%s/%s", dirname(mesh->model->path), img->uri);
|
||||||
// mesh->bind.fs.images[0] = texture_pullfromfile(imp)->id;
|
// mesh->bind.fs.images[0] = texture_from_file(imp)->id;
|
||||||
// free(imp);
|
// free(imp);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
mesh->bind.fs.images[0] = texture_pullfromfile("k")->id;
|
mesh->bind.fs.images[0] = texture_from_file("k")->id;
|
||||||
|
|
||||||
mesh->bind.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
|
mesh->bind.fs.samplers[0] = sg_make_sampler(&(sg_sampler_desc){});
|
||||||
/*
|
/*
|
||||||
cgltf_texture *tex;
|
cgltf_texture *tex;
|
||||||
if (tex = mat->normal_texture.texture)
|
if (tex = mat->normal_texture.texture)
|
||||||
mesh->bind.fs.images[1] = texture_pullfromfile(tex->image->uri)->id;
|
mesh->bind.fs.images[1] = texture_from_file(tex->image->uri)->id;
|
||||||
else
|
else
|
||||||
mesh->bind.fs.images[1] = texture_pullfromfile("k")->id;*/
|
mesh->bind.fs.images[1] = texture_from_file("k")->id;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
sg_buffer texcoord_floats(float *f, int verts, int comp)
|
sg_buffer texcoord_floats(float *f, int verts, int comp)
|
||||||
|
|
|
@ -19,11 +19,11 @@ struct datastream {
|
||||||
soundbyte *ring;
|
soundbyte *ring;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Texture;
|
struct texture;
|
||||||
|
|
||||||
void MakeDatastream();
|
void MakeDatastream();
|
||||||
struct datastream *ds_openvideo(const char *path);
|
struct datastream *ds_openvideo(const char *path);
|
||||||
struct Texture *ds_maketexture(struct datastream *);
|
struct texture *ds_maketexture(struct datastream *);
|
||||||
void ds_advance(struct datastream *ds, double);
|
void ds_advance(struct datastream *ds, double);
|
||||||
void ds_seek(struct datastream *ds, double);
|
void ds_seek(struct datastream *ds, double);
|
||||||
void ds_advanceframes(struct datastream *ds, int frames);
|
void ds_advanceframes(struct datastream *ds, int frames);
|
||||||
|
|
|
@ -180,11 +180,11 @@ struct sFont *MakeFont(const char *fontfile, int height) {
|
||||||
for (unsigned char c = 32; c < 127; c++) {
|
for (unsigned char c = 32; c < 127; c++) {
|
||||||
stbtt_packedchar glyph = glyphs[c - 32];
|
stbtt_packedchar glyph = glyphs[c - 32];
|
||||||
|
|
||||||
struct glrect r;
|
struct rect r;
|
||||||
r.s0 = (glyph.x0) / (float)packsize;
|
r.x = (glyph.x0) / (float)packsize;
|
||||||
r.s1 = (glyph.x1) / (float)packsize;
|
r.w = (glyph.x1-glyph.x0) / (float)packsize;
|
||||||
r.t0 = (glyph.y0) / (float)packsize;
|
r.y = (glyph.y0) / (float)packsize;
|
||||||
r.t1 = (glyph.y1) / (float)packsize;
|
r.h = (glyph.y1-glyph.y0) / (float)packsize;
|
||||||
|
|
||||||
stbtt_GetCodepointHMetrics(&fontinfo, c, &newfont->Characters[c].Advance, &newfont->Characters[c].leftbearing);
|
stbtt_GetCodepointHMetrics(&fontinfo, c, &newfont->Characters[c].Advance, &newfont->Characters[c].leftbearing);
|
||||||
newfont->Characters[c].leftbearing *= newfont->emscale;
|
newfont->Characters[c].leftbearing *= newfont->emscale;
|
||||||
|
@ -260,10 +260,10 @@ void sdrawCharacter(struct Character c, HMM_Vec2 cursor, float scale, struct rgb
|
||||||
|
|
||||||
// if (vert.pos.x > frame.l || vert.pos.y > frame.t || (vert.pos.y + vert.wh.y) < frame.b || (vert.pos.x + vert.wh.x) < frame.l) return;
|
// if (vert.pos.x > frame.l || vert.pos.y > frame.t || (vert.pos.y + vert.wh.y) < frame.b || (vert.pos.x + vert.wh.x) < frame.l) return;
|
||||||
|
|
||||||
vert.uv.u = c.rect.s0*USHRT_MAX;
|
vert.uv.u = c.rect.x*USHRT_MAX;
|
||||||
vert.uv.v = c.rect.t0*USHRT_MAX;
|
vert.uv.v = c.rect.y*USHRT_MAX;
|
||||||
vert.st.u = (c.rect.s1-c.rect.s0)*USHRT_MAX;
|
vert.st.u = c.rect.w*USHRT_MAX;
|
||||||
vert.st.v = (c.rect.t1-c.rect.t0)*USHRT_MAX;
|
vert.st.v = c.rect.h*USHRT_MAX;
|
||||||
vert.color = color;
|
vert.color = color;
|
||||||
|
|
||||||
memcpy(text_buffer + curchar, &vert, sizeof(struct text_vert));
|
memcpy(text_buffer + curchar, &vert, sizeof(struct text_vert));
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct Character {
|
||||||
float Bearing[2]; // Offset from baseline to left/top of glyph
|
float Bearing[2]; // Offset from baseline to left/top of glyph
|
||||||
int Advance; // Horizontal offset to advance to next glyph
|
int Advance; // Horizontal offset to advance to next glyph
|
||||||
int leftbearing;
|
int leftbearing;
|
||||||
struct glrect rect;
|
struct rect rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sFont {
|
struct sFont {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define FREELIST_H
|
#define FREELIST_H
|
||||||
|
|
||||||
/* Given a pointer to a struct, create a free list
|
/* Given a pointer to a struct, create a free list
|
||||||
Struct must have a 'next' field
|
Struct must have an 'unsigned int next' field
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct freelistheader
|
struct freelistheader
|
||||||
|
@ -32,7 +32,7 @@ static inline unsigned int freelist_check(struct freelistheader *h, void *data,
|
||||||
#define freelist_size(p,l) do{p = freelist_make(sizeof(*p),l); for(int i = 0; i < l; i++) { p[i].next = i+1; }}while(0)
|
#define freelist_size(p,l) do{p = freelist_make(sizeof(*p),l); for(int i = 0; i < l; i++) { p[i].next = i+1; }}while(0)
|
||||||
#define freelist_len(p) (freelist_header(p)->len)
|
#define freelist_len(p) (freelist_header(p)->len)
|
||||||
#define freelist_first(p) (freelist_header(p)->first)
|
#define freelist_first(p) (freelist_header(p)->first)
|
||||||
#define freelist_grab(i,p) do{i=freelist_header(p)->first; freelist_header(p)->first = p[i].next; p[i].next = -1;freelist_header(p)->count++;}while(0)
|
#define freelist_grab(p,i) do{i=freelist_header(p)->first; freelist_header(p)->first = p[i].next; p[i].next = -1;freelist_header(p)->count++;}while(0)
|
||||||
#define freelist_kill(p,i) do{p[i].next = freelist_first(p);freelist_first(p)=i;freelist_header(p)->count--;}while(0)
|
#define freelist_kill(p,i) do{p[i].next = freelist_first(p);freelist_first(p)=i;freelist_header(p)->count--;}while(0)
|
||||||
#define freelist_free(p) (free(freelist_header(p)))
|
#define freelist_free(p) (free(freelist_header(p)))
|
||||||
#define freelist_count(p) (freelist_header(p)->count)
|
#define freelist_count(p) (freelist_header(p)->count)
|
||||||
|
|
|
@ -67,10 +67,11 @@ static JSValue TYPE##2js(TYPE *n) { \
|
||||||
JS_SetOpaque(j,n);\
|
JS_SetOpaque(j,n);\
|
||||||
return j; }\
|
return j; }\
|
||||||
|
|
||||||
|
|
||||||
QJSCLASS(gameobject)
|
QJSCLASS(gameobject)
|
||||||
QJSCLASS(emitter)
|
QJSCLASS(emitter)
|
||||||
QJSCLASS(dsp_node)
|
QJSCLASS(dsp_node)
|
||||||
|
QJSCLASS(texture)
|
||||||
|
QJSCLASS(sprite)
|
||||||
QJSCLASS(warp_gravity)
|
QJSCLASS(warp_gravity)
|
||||||
QJSCLASS(warp_damp)
|
QJSCLASS(warp_damp)
|
||||||
QJSCLASS(material)
|
QJSCLASS(material)
|
||||||
|
@ -107,6 +108,7 @@ JS_SetPropertyStr(js, globalThis, #NAME, NAME); \
|
||||||
JS_NewClassID(&js_##TYPE##_id);\
|
JS_NewClassID(&js_##TYPE##_id);\
|
||||||
JS_NewClass(JS_GetRuntime(js), js_##TYPE##_id, &js_##TYPE##_class);\
|
JS_NewClass(JS_GetRuntime(js), js_##TYPE##_id, &js_##TYPE##_class);\
|
||||||
|
|
||||||
|
/* Defines a class and uses its function list as its prototype */
|
||||||
#define QJSCLASSPREP_FUNCS(TYPE) \
|
#define QJSCLASSPREP_FUNCS(TYPE) \
|
||||||
QJSCLASSPREP(TYPE); \
|
QJSCLASSPREP(TYPE); \
|
||||||
JSValue TYPE##_proto = JS_NewObject(js); \
|
JSValue TYPE##_proto = JS_NewObject(js); \
|
||||||
|
@ -215,7 +217,6 @@ void *js2ptr(JSValue v) { return JS_GetOpaque(v,js_ptr_id); }
|
||||||
JSValue number2js(double g) {
|
JSValue number2js(double g) {
|
||||||
return JS_NewFloat64(js,g);
|
return JS_NewFloat64(js,g);
|
||||||
}
|
}
|
||||||
struct sprite *js2sprite(JSValue v) { return id2sprite(js2int(v)); }
|
|
||||||
|
|
||||||
JSValue ptr2js(void *ptr) {
|
JSValue ptr2js(void *ptr) {
|
||||||
JSValue obj = JS_NewObjectClass(js, js_ptr_id);
|
JSValue obj = JS_NewObjectClass(js, js_ptr_id);
|
||||||
|
@ -231,15 +232,6 @@ double js_get_prop_number(JSValue v, const char *p) {
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct glrect js2glrect(JSValue v) {
|
|
||||||
struct glrect rect;
|
|
||||||
rect.s0 = js_get_prop_number(v, "s0");
|
|
||||||
rect.s1 = js_get_prop_number(v, "s1");
|
|
||||||
rect.t0 = js_get_prop_number(v, "t0");
|
|
||||||
rect.t1 = js_get_prop_number(v, "t1");
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue js_arridx(JSValue v, int idx) { return js_getpropidx(v, idx); }
|
JSValue js_arridx(JSValue v, int idx) { return js_getpropidx(v, idx); }
|
||||||
|
|
||||||
int js_arrlen(JSValue v) {
|
int js_arrlen(JSValue v) {
|
||||||
|
@ -406,6 +398,14 @@ HMM_Vec2 js2vec2(JSValue v)
|
||||||
return v2;
|
return v2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSValue vec22js(HMM_Vec2 v)
|
||||||
|
{
|
||||||
|
JSValue array = JS_NewArray(js);
|
||||||
|
js_setprop_num(array,0,number2js(v.x));
|
||||||
|
js_setprop_num(array,1,number2js(v.y));
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
HMM_Vec3 js2vec3(JSValue v)
|
HMM_Vec3 js2vec3(JSValue v)
|
||||||
{
|
{
|
||||||
HMM_Vec3 v3;
|
HMM_Vec3 v3;
|
||||||
|
@ -474,17 +474,10 @@ void vec2float(HMM_Vec2 v, float *f) {
|
||||||
f[1] = v.y;
|
f[1] = v.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSValue vec2js(HMM_Vec2 v) {
|
|
||||||
JSValue array = JS_NewArray(js);
|
|
||||||
js_setprop_num(array,0,number2js(v.x));
|
|
||||||
js_setprop_num(array,1,number2js(v.y));
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue vecarr2js(HMM_Vec2 *points, int n) {
|
JSValue vecarr2js(HMM_Vec2 *points, int n) {
|
||||||
JSValue array = JS_NewArray(js);
|
JSValue array = JS_NewArray(js);
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++)
|
||||||
js_setprop_num(array,i,vec2js(points[i]));
|
js_setprop_num(array,i,vec22js(points[i]));
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
@ -695,11 +688,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
ret = JS_NewInt64(js, script_dofile(str));
|
ret = JS_NewInt64(js, script_dofile(str));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
|
||||||
YughWarn("Do not set pawns here anymore; Do it entirely in script.");
|
|
||||||
// set_pawn(js2ptrduk_get_heapptr(duk, 1));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
set_timescale(js2number(argv[1]));
|
set_timescale(js2number(argv[1]));
|
||||||
break;
|
break;
|
||||||
|
@ -715,34 +703,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
case 7:
|
case 7:
|
||||||
physMS = js2number(argv[1]);
|
physMS = js2number(argv[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 8:
|
|
||||||
phys2d_set_gravity(js2vec2(argv[1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 9:
|
|
||||||
sprite_delete(js2int(argv[1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 10:
|
|
||||||
YughWarn("Pawns are handled in script only now.");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 11:
|
|
||||||
str = JS_ToCString(js, argv[1]);
|
|
||||||
ret = JS_NewInt64(js, file_mod_secs(str));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 12:
|
|
||||||
str = JS_ToCString(js, argv[2]);
|
|
||||||
sprite_loadtex(id2sprite(js2int(argv[1])), str, js2glrect(argv[3]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 13:
|
|
||||||
str = JS_ToCString(js, argv[1]);
|
|
||||||
str2 = JS_ToCString(js, argv[2]);
|
|
||||||
play_song(str, str2);
|
|
||||||
break;
|
|
||||||
case 15:
|
case 15:
|
||||||
gameobject_draw_debug(js2gameobject(argv[1]));
|
gameobject_draw_debug(js2gameobject(argv[1]));
|
||||||
break;
|
break;
|
||||||
|
@ -760,10 +721,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
shape_set_sensor(js2ptr(argv[1]), JS_ToBool(js, argv[2]));
|
shape_set_sensor(js2ptr(argv[1]), JS_ToBool(js, argv[2]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 20:
|
|
||||||
sprite_enabled(js2int(argv[1]), JS_ToBool(js, argv[2]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 21:
|
case 21:
|
||||||
ret = JS_NewBool(js, shape_get_sensor(js2ptr(argv[1])));
|
ret = JS_NewBool(js, shape_get_sensor(js2ptr(argv[1])));
|
||||||
break;
|
break;
|
||||||
|
@ -776,79 +733,12 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
ret = JS_NewBool(js, shape_is_enabled(js2ptr(argv[1])));
|
ret = JS_NewBool(js, shape_is_enabled(js2ptr(argv[1])));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 24:
|
|
||||||
timer_pause(js2timer(argv[1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 25:
|
|
||||||
timer_stop(js2timer(argv[1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 26:
|
|
||||||
timer_start(js2timer(argv[1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 27:
|
|
||||||
timer_remove(js2int(argv[1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 28:
|
|
||||||
timerr_settime(js2timer(argv[1]), js2number(argv[2]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 29:
|
|
||||||
ret = JS_NewFloat64(js, js2timer(argv[1])->interval);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 31:
|
|
||||||
free(js2ptr(argv[1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 32:
|
|
||||||
ret = JS_NewFloat64(js, js2timer(argv[1])->remain_time);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 33:
|
|
||||||
ret = JS_NewBool(js, js2timer(argv[1])->on);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 34:
|
|
||||||
ret = JS_NewBool(js, js2timer(argv[1])->repeat);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 35:
|
|
||||||
js2timer(argv[1])->repeat = JS_ToBool(js, argv[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 36:
|
case 36:
|
||||||
js2gameobject(argv[1])->scale.XY = js2vec2(argv[2]);
|
js2gameobject(argv[1])->scale.XY = js2vec2(argv[2]);
|
||||||
gameobject_apply(js2gameobject(argv[1]));
|
gameobject_apply(js2gameobject(argv[1]));
|
||||||
cpSpaceReindexShapesForBody(space, js2gameobject(argv[1])->body);
|
cpSpaceReindexShapesForBody(space, js2gameobject(argv[1])->body);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 37:
|
|
||||||
if (!id2sprite(js2int(argv[1]))) break;
|
|
||||||
id2sprite(js2int(argv[1]))->t.pos = js2vec2(argv[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 40:
|
|
||||||
js2gameobject(argv[1])->filter.categories = js2bitmask(argv[2]);
|
|
||||||
gameobject_apply(js2gameobject(argv[1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 41:
|
|
||||||
js2gameobject(argv[1])->filter.mask = js2bitmask(argv[2]);
|
|
||||||
gameobject_apply(js2gameobject(argv[1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 42:
|
|
||||||
ret = bitmask2js(js2gameobject(argv[1])->filter.categories);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 43:
|
|
||||||
ret = bitmask2js(js2gameobject(argv[1])->filter.mask);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 44:
|
case 44:
|
||||||
go = pos2gameobject(js2vec2(argv[1]), js2number(argv[2]));
|
go = pos2gameobject(js2vec2(argv[1]), js2number(argv[2]));
|
||||||
ret = go ? JS_DupValue(js,go->ref) : JS_UNDEFINED;
|
ret = go ? JS_DupValue(js,go->ref) : JS_UNDEFINED;
|
||||||
|
@ -884,10 +774,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
draw_box(js2vec2(argv[1]), js2vec2(argv[2]), js2color(argv[3]));
|
draw_box(js2vec2(argv[1]), js2vec2(argv[2]), js2color(argv[3]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 54:
|
|
||||||
gameobject_apply(js2gameobject(argv[1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 59:
|
case 59:
|
||||||
v1 = js2cpvec2arr(argv[2]);
|
v1 = js2cpvec2arr(argv[2]);
|
||||||
ret = JS_NewInt64(js, point2segindex(js2vec2(argv[1]), v1, js2number(argv[3])));
|
ret = JS_NewInt64(js, point2segindex(js2vec2(argv[1]), v1, js2number(argv[3])));
|
||||||
|
@ -901,17 +787,9 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
add_zoom(js2number(argv[1]));
|
add_zoom(js2number(argv[1]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 63:
|
|
||||||
set_cam_body(NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 64:
|
case 64:
|
||||||
str = JS_ToCString(js, argv[1]);
|
str = JS_ToCString(js, argv[1]);
|
||||||
ret = vec2js(tex_get_dimensions(texture_pullfromfile(str)));
|
ret = vec22js(tex_get_dimensions(texture_from_file(str)));
|
||||||
break;
|
|
||||||
|
|
||||||
case 66:
|
|
||||||
ret = strarr2js(ls(","));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 67:
|
case 67:
|
||||||
|
@ -923,37 +801,17 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 70:
|
case 70:
|
||||||
ret = vec2js(world2go(js2gameobject(argv[1]), js2vec2(argv[2])));
|
ret = vec22js(world2go(js2gameobject(argv[1]), js2vec2(argv[2])));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 71:
|
case 71:
|
||||||
ret = vec2js(go2world(js2gameobject(argv[1]), js2vec2(argv[2])));
|
ret = vec22js(go2world(js2gameobject(argv[1]), js2vec2(argv[2])));
|
||||||
break;
|
|
||||||
|
|
||||||
case 72:
|
|
||||||
ret = vec2js((HMM_Vec2)cpSpaceGetGravity(space));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 73:
|
|
||||||
cpSpaceSetDamping(space, js2number(argv[1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 74:
|
|
||||||
ret = JS_NewFloat64(js, cpSpaceGetDamping(space));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 75:
|
|
||||||
js2gameobject(argv[1])->layer = js2int(argv[2]);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 76:
|
case 76:
|
||||||
set_cat_mask(js2int(argv[1]), js2bitmask(argv[2]));
|
set_cat_mask(js2int(argv[1]), js2bitmask(argv[2]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 77:
|
|
||||||
ret = int2js(js2gameobject(argv[1])->layer);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 79:
|
case 79:
|
||||||
ret = JS_NewBool(js, phys_stepping());
|
ret = JS_NewBool(js, phys_stepping());
|
||||||
break;
|
break;
|
||||||
|
@ -978,7 +836,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 85:
|
case 85:
|
||||||
ret = vec2js(HMM_ProjV2(js2vec2(argv[1]), js2vec2(argv[2])));
|
ret = vec22js(HMM_ProjV2(js2vec2(argv[1]), js2vec2(argv[2])));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 86:
|
case 86:
|
||||||
|
@ -1010,36 +868,13 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
ret = int2js(logLevel);
|
ret = int2js(logLevel);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 96:
|
|
||||||
id2sprite(js2int(argv[1]))->color = js2color(argv[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 97:
|
case 97:
|
||||||
str = js2str(argv[1]);
|
str = js2str(argv[1]);
|
||||||
cursor_img(str);
|
cursor_img(str);
|
||||||
break;
|
break;
|
||||||
case 103:
|
case 103:
|
||||||
ret = vec2js(js2gameobject(argv[1])->scale.XY);
|
ret = vec22js(js2gameobject(argv[1])->scale.XY);
|
||||||
break;
|
break;
|
||||||
case 106:
|
|
||||||
js2gameobject(argv[1])->e = js2number(argv[2]);
|
|
||||||
break;
|
|
||||||
case 107:
|
|
||||||
ret = number2js(js2gameobject(argv[1])->e);
|
|
||||||
break;
|
|
||||||
case 108:
|
|
||||||
js2gameobject(argv[1])->f = js2number(argv[2]);
|
|
||||||
break;
|
|
||||||
case 109:
|
|
||||||
ret = number2js(js2gameobject(argv[1])->f);
|
|
||||||
break;
|
|
||||||
case 110:
|
|
||||||
ret = number2js(js2gameobject(argv[1])->e);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 111:
|
|
||||||
ret = vec2js(js2sprite(argv[1])->t.pos);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 112:
|
case 112:
|
||||||
ret = number2js(((struct phys2d_edge*)js2ptr(argv[1]))->thickness);
|
ret = number2js(((struct phys2d_edge*)js2ptr(argv[1]))->thickness);
|
||||||
|
@ -1049,18 +884,10 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
js2gameobject(argv[1])->ref = argv[2];
|
js2gameobject(argv[1])->ref = argv[2];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 114:
|
|
||||||
ret = bool2js(js2sprite(argv[1])->enabled);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 115:
|
case 115:
|
||||||
draw_circle(js2vec2(argv[1]), js2number(argv[2]), js2number(argv[2]), js2color(argv[3]), -1);
|
draw_circle(js2vec2(argv[1]), js2number(argv[2]), js2number(argv[2]), js2color(argv[3]), -1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 116:
|
|
||||||
ret = str2js(tex_get_path(js2sprite(argv[1])->tex));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 117:
|
case 117:
|
||||||
str = JS_ToCString(js, argv[1]);
|
str = JS_ToCString(js, argv[1]);
|
||||||
ret = script_runfile(str);
|
ret = script_runfile(str);
|
||||||
|
@ -1141,16 +968,11 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 136:
|
case 136:
|
||||||
ret = vec2js(world2screen(js2vec2(argv[1])));
|
ret = vec22js(world2screen(js2vec2(argv[1])));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 137:
|
case 137:
|
||||||
ret = vec2js(screen2world(js2vec2(argv[1])));
|
ret = vec22js(screen2world(js2vec2(argv[1])));
|
||||||
break;
|
|
||||||
|
|
||||||
case 138:
|
|
||||||
str = JS_ToCString(js, argv[1]);
|
|
||||||
ret = JS_NewInt64(js, jso_file(str));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 139:
|
case 139:
|
||||||
|
@ -1171,13 +993,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
console_print(str);
|
console_print(str);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 143:
|
|
||||||
str = JS_ToCString(js, argv[1]);
|
|
||||||
if (!getenv(str)) ret = JS_UNDEFINED;
|
|
||||||
else
|
|
||||||
ret = str2js(getenv(str));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 145:
|
case 145:
|
||||||
if (js2bool(argv[1])) window_makefullscreen(&mainwin);
|
if (js2bool(argv[1])) window_makefullscreen(&mainwin);
|
||||||
else window_unfullscreen(&mainwin);
|
else window_unfullscreen(&mainwin);
|
||||||
|
@ -1186,12 +1001,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
log_clear();
|
log_clear();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 147:
|
|
||||||
exit(js2int(argv[1]));
|
|
||||||
break;
|
|
||||||
case 148:
|
|
||||||
ret = color2js(id2sprite(js2int(argv[1]))->color);
|
|
||||||
break;
|
|
||||||
case 149:
|
case 149:
|
||||||
((struct drawmodel *)js2ptr(argv[1]))->model = GetExistingModel(js2str(argv[2]));
|
((struct drawmodel *)js2ptr(argv[1]))->model = GetExistingModel(js2str(argv[2]));
|
||||||
break;
|
break;
|
||||||
|
@ -1200,58 +1009,18 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
draw_drawmodel(js2ptr(argv[1]));
|
draw_drawmodel(js2ptr(argv[1]));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 151:
|
|
||||||
js2gameobject(argv[1])->maxvelocity = js2number(argv[2]);
|
|
||||||
break;
|
|
||||||
case 152:
|
|
||||||
ret = number2js(js2gameobject(argv[1])->maxvelocity);
|
|
||||||
break;
|
|
||||||
case 153:
|
case 153:
|
||||||
cpBodySetTorque(js2gameobject(argv[1])->body, js2number(argv[2]));
|
cpBodySetTorque(js2gameobject(argv[1])->body, js2number(argv[2]));
|
||||||
break;
|
break;
|
||||||
case 154:
|
|
||||||
js2gameobject(argv[1])->maxangularvelocity = js2number(argv[2]);
|
|
||||||
break;
|
|
||||||
case 155:
|
|
||||||
ret = number2js(js2gameobject(argv[1])->maxangularvelocity);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 156:
|
|
||||||
js2gameobject(argv[1])->damping = js2number(argv[2]);
|
|
||||||
break;
|
|
||||||
case 157:
|
|
||||||
ret = number2js(js2gameobject(argv[1])->damping);
|
|
||||||
break;
|
|
||||||
case 160:
|
case 160:
|
||||||
ret = vec2js(mat_t_dir(t_world2go(js2gameobject(argv[1])), js2vec2(argv[2])));
|
ret = vec22js(mat_t_dir(t_world2go(js2gameobject(argv[1])), js2vec2(argv[2])));
|
||||||
break;
|
break;
|
||||||
case 161:
|
case 161:
|
||||||
ret = vec2js(mat_t_dir(t_go2world(js2gameobject(argv[1])), js2vec2(argv[2])));
|
ret = vec22js(mat_t_dir(t_go2world(js2gameobject(argv[1])), js2vec2(argv[2])));
|
||||||
break;
|
|
||||||
case 162:
|
|
||||||
str = JS_ToCString(js, argv[1]);
|
|
||||||
ret = int2js(remove(str));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 164:
|
|
||||||
unplug_node(js2ptr(argv[1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 168:
|
|
||||||
js2gameobject(argv[1])->timescale = js2number(argv[2]);
|
|
||||||
break;
|
|
||||||
case 169:
|
|
||||||
ret = number2js(js2gameobject(argv[1])->timescale);
|
|
||||||
break;
|
|
||||||
case 170:
|
|
||||||
id2sprite(js2int(argv[1]))->emissive = js2color(argv[2]);
|
|
||||||
break;
|
|
||||||
case 171:
|
|
||||||
ret = number2js(js2gameobject(argv[1])->drawlayer);
|
|
||||||
break;
|
|
||||||
case 172:
|
|
||||||
js2gameobject(argv[1])->drawlayer = js2number(argv[2]);
|
|
||||||
break;
|
|
||||||
case 173:
|
case 173:
|
||||||
str = js2str(argv[1]);
|
str = js2str(argv[1]);
|
||||||
capture_screen(js2number(argv[2]), js2number(argv[3]), js2number(argv[4]), js2number(argv[5]), str);
|
capture_screen(js2number(argv[2]), js2number(argv[3]), js2number(argv[4]), js2number(argv[5]), str);
|
||||||
|
@ -1340,24 +1109,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
case 214:
|
case 214:
|
||||||
ret = int2js(go_count());
|
ret = int2js(go_count());
|
||||||
break;
|
break;
|
||||||
case 215:
|
|
||||||
ret = vec2js(js2sprite(argv[1])->t.scale);
|
|
||||||
break;
|
|
||||||
case 216:
|
|
||||||
js2sprite(argv[1])->t.scale = js2vec2(argv[2]);
|
|
||||||
break;
|
|
||||||
case 217:
|
|
||||||
ret = number2js(js2sprite(argv[1])->t.angle);
|
|
||||||
break;
|
|
||||||
case 218:
|
|
||||||
js2sprite(argv[1])->t.angle = js2number(argv[2]);
|
|
||||||
break;
|
|
||||||
case 219:
|
|
||||||
js2sprite(argv[1])->drawmode = js2number(argv[2]);
|
|
||||||
break;
|
|
||||||
case 220:
|
|
||||||
ret = number2js(js2sprite(argv[1])->drawmode);
|
|
||||||
break;
|
|
||||||
case 221:
|
case 221:
|
||||||
ret = constraint2js(constraint_make(cpPivotJointNew(js2gameobject(argv[1])->body, js2gameobject(argv[2])->body,js2vec2(argv[3]).cp)));
|
ret = constraint2js(constraint_make(cpPivotJointNew(js2gameobject(argv[1])->body, js2gameobject(argv[2])->body,js2vec2(argv[3]).cp)));
|
||||||
break;
|
break;
|
||||||
|
@ -1392,12 +1144,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
case 231:
|
case 231:
|
||||||
ret = constraint2js(constraint_make(cpSimpleMotorNew(js2body(argv[1]), js2body(argv[2]), js2number(argv[3]))));
|
ret = constraint2js(constraint_make(cpSimpleMotorNew(js2body(argv[1]), js2body(argv[2]), js2number(argv[3]))));
|
||||||
break;
|
break;
|
||||||
case 232:
|
|
||||||
ret = number2js(js2sprite(argv[1])->parallax);
|
|
||||||
break;
|
|
||||||
case 233:
|
|
||||||
js2sprite(argv[1])->parallax = js2number(argv[2]);
|
|
||||||
break;
|
|
||||||
case 234:
|
case 234:
|
||||||
ret = emitter2js(make_emitter());
|
ret = emitter2js(make_emitter());
|
||||||
break;
|
break;
|
||||||
|
@ -1406,17 +1153,12 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
break;
|
break;
|
||||||
case 249:
|
case 249:
|
||||||
str = JS_ToCString(js,argv[2]);
|
str = JS_ToCString(js,argv[2]);
|
||||||
js2emitter(argv[1])->texture = texture_pullfromfile(str);
|
js2emitter(argv[1])->texture = texture_from_file(str);
|
||||||
break;
|
break;
|
||||||
case 250:
|
case 250:
|
||||||
sapp_show_keyboard(js2bool(argv[1]));
|
sapp_show_keyboard(js2bool(argv[1]));
|
||||||
break;
|
break;
|
||||||
case 251:
|
|
||||||
js2gameobject(argv[1])->warp_filter = js2bitmask(argv[2]);
|
|
||||||
break;
|
|
||||||
case 252:
|
|
||||||
ret = bitmask2js(js2gameobject(argv[1])->warp_filter);
|
|
||||||
break;
|
|
||||||
case 253:
|
case 253:
|
||||||
ret = warp_gravity2js(warp_gravity_make());
|
ret = warp_gravity2js(warp_gravity_make());
|
||||||
break;
|
break;
|
||||||
|
@ -1460,7 +1202,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
aspect_mode = js2int(argv[1]);
|
aspect_mode = js2int(argv[1]);
|
||||||
break;
|
break;
|
||||||
case 265:
|
case 265:
|
||||||
ret = vec2js((HMM_Vec2){mainwin.width, mainwin.height});
|
ret = vec22js((HMM_Vec2){mainwin.width, mainwin.height});
|
||||||
break;
|
break;
|
||||||
case 266:
|
case 266:
|
||||||
mainwin.width = js2number(argv[1]);
|
mainwin.width = js2number(argv[1]);
|
||||||
|
@ -1468,6 +1210,16 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
case 267:
|
case 267:
|
||||||
mainwin.height = js2number(argv[1]);
|
mainwin.height = js2number(argv[1]);
|
||||||
break;
|
break;
|
||||||
|
case 268:
|
||||||
|
if (js2bool(argv[1]))
|
||||||
|
ret = JS_GetClassProto(js, js_sprite_id);
|
||||||
|
else
|
||||||
|
ret = sprite2js(sprite_make());
|
||||||
|
break;
|
||||||
|
case 269:
|
||||||
|
str = js2str(argv[1]);
|
||||||
|
ret = texture2js(texture_from_file(str));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (str) JS_FreeCString(js, str);
|
if (str) JS_FreeCString(js, str);
|
||||||
|
@ -1526,10 +1278,6 @@ JSValue duk_sys_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *ar
|
||||||
cpSpaceReindexStatic(space);
|
cpSpaceReindexStatic(space);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
|
||||||
sim_pause();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
sim_pause();
|
sim_pause();
|
||||||
break;
|
break;
|
||||||
|
@ -1613,14 +1361,6 @@ JSValue duk_set_body(JSContext *js, JSValueConst this, int argc, JSValueConst *a
|
||||||
cpBodySetVelocity(go->body, js2vec2(argv[2]).cp);
|
cpBodySetVelocity(go->body, js2vec2(argv[2]).cp);
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
|
|
||||||
case 10:
|
|
||||||
go->e = fmax(js2number(argv[2]), 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 11:
|
|
||||||
go->f = fmax(js2number(argv[2]), 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 12:
|
case 12:
|
||||||
cpBodyApplyForceAtWorldPoint(go->body, js2vec2(argv[2]).cp, cpBodyGetPosition(go->body));
|
cpBodyApplyForceAtWorldPoint(go->body, js2vec2(argv[2]).cp, cpBodyGetPosition(go->body));
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
|
@ -1649,13 +1389,13 @@ JSValue duk_q_body(JSContext *js, JSValueConst this, int argc, JSValueConst *arg
|
||||||
return JS_NewInt64(js, cpBodyGetType(go->body));
|
return JS_NewInt64(js, cpBodyGetType(go->body));
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
return vec2js((HMM_Vec2)cpBodyGetPosition(go->body));
|
return vec22js((HMM_Vec2)cpBodyGetPosition(go->body));
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
return JS_NewFloat64(js, cpBodyGetAngle(go->body));
|
return JS_NewFloat64(js, cpBodyGetAngle(go->body));
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
return vec2js((HMM_Vec2)cpBodyGetVelocity(go->body));
|
return vec22js((HMM_Vec2)cpBodyGetVelocity(go->body));
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
return JS_NewFloat64(js, cpBodyGetAngularVelocity(go->body));
|
return JS_NewFloat64(js, cpBodyGetAngularVelocity(go->body));
|
||||||
|
@ -1668,21 +1408,11 @@ JSValue duk_q_body(JSContext *js, JSValueConst this, int argc, JSValueConst *arg
|
||||||
|
|
||||||
case 7:
|
case 7:
|
||||||
return JS_NewBool(js, phys2d_in_air(go->body));
|
return JS_NewBool(js, phys2d_in_air(go->body));
|
||||||
|
|
||||||
case 8:
|
|
||||||
gameobject_free(go);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSValue duk_make_sprite(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
|
||||||
JSValue sprite = JS_NewObject(js);
|
|
||||||
js_setprop_str(sprite,"id",JS_NewInt64(js, make_sprite(js2gameobject(argv[0]))));
|
|
||||||
return sprite;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue duk_make_circle2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
JSValue duk_make_circle2d(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) {
|
||||||
gameobject *go = js2gameobject(argv[0]);
|
gameobject *go = js2gameobject(argv[0]);
|
||||||
|
|
||||||
|
@ -1722,7 +1452,7 @@ JSValue duk_cmd_circle2d(JSContext *js, JSValueConst this, int argc, JSValueCons
|
||||||
return number2js(circle->radius);
|
return number2js(circle->radius);
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
return vec2js(circle->offset);
|
return vec22js(circle->offset);
|
||||||
}
|
}
|
||||||
phys2d_shape_apply(&circle->shape);
|
phys2d_shape_apply(&circle->shape);
|
||||||
|
|
||||||
|
@ -2085,6 +1815,85 @@ static const JSCFunctionListEntry js_sound_funcs[] = {
|
||||||
CGETSET_ADD(sound, hook)
|
CGETSET_ADD(sound, hook)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GETSET_PAIR_BODY(ID, ENTRY, TYPE) \
|
||||||
|
JSValue ID##_set_##ENTRY (JSContext *js, JSValue this, JSValue val) { \
|
||||||
|
js2##ID (this)->ENTRY = js2##TYPE (val); \
|
||||||
|
ID##_apply(js2##ID (this)); \
|
||||||
|
return JS_UNDEFINED; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
JSValue ID##_get_##ENTRY (JSContext *js, JSValue this) { \
|
||||||
|
return TYPE##2js(js2##ID (this)->ENTRY); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
GETSET_PAIR_BODY(gameobject, f, number)
|
||||||
|
GETSET_PAIR_BODY(gameobject, e, number)
|
||||||
|
GETSET_PAIR_BODY(gameobject, mass, number)
|
||||||
|
GETSET_PAIR(gameobject, damping, number)
|
||||||
|
GETSET_PAIR(gameobject, timescale, number)
|
||||||
|
GETSET_PAIR(gameobject, maxvelocity, number)
|
||||||
|
GETSET_PAIR(gameobject, maxangularvelocity, number)
|
||||||
|
GETSET_PAIR_BODY(gameobject, layer, number)
|
||||||
|
GETSET_PAIR(gameobject, warp_filter, bitmask)
|
||||||
|
GETSET_PAIR(gameobject, scale, vec3)
|
||||||
|
GETSET_PAIR(gameobject, drawlayer, number)
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_gameobject_funcs[] = {
|
||||||
|
CGETSET_ADD(gameobject, f),
|
||||||
|
CGETSET_ADD(gameobject, e),
|
||||||
|
CGETSET_ADD(gameobject,mass),
|
||||||
|
CGETSET_ADD(gameobject,damping),
|
||||||
|
CGETSET_ADD(gameobject,timescale),
|
||||||
|
CGETSET_ADD(gameobject,maxvelocity),
|
||||||
|
CGETSET_ADD(gameobject,maxangularvelocity),
|
||||||
|
CGETSET_ADD(gameobject,layer),
|
||||||
|
CGETSET_ADD(gameobject,warp_filter),
|
||||||
|
|
||||||
|
CGETSET_ADD(gameobject,scale),
|
||||||
|
CGETSET_ADD(gameobject,drawlayer)
|
||||||
|
};
|
||||||
|
|
||||||
|
GETSET_PAIR(sprite, color, color)
|
||||||
|
GETSET_PAIR(sprite, emissive, color)
|
||||||
|
GETSET_PAIR(sprite, enabled, bool)
|
||||||
|
GETSET_PAIR(sprite, parallax, number)
|
||||||
|
GETSET_PAIR(sprite, tex, texture)
|
||||||
|
GETSET_PAIR(sprite, pos, vec2)
|
||||||
|
GETSET_PAIR(sprite, scale, vec2)
|
||||||
|
GETSET_PAIR(sprite, angle, number)
|
||||||
|
GETSET_PAIR(sprite, frame, rect)
|
||||||
|
GETSET_PAIR(sprite,go,gameobject)
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_sprite_funcs[] = {
|
||||||
|
CGETSET_ADD(sprite,pos),
|
||||||
|
CGETSET_ADD(sprite,scale),
|
||||||
|
CGETSET_ADD(sprite,angle),
|
||||||
|
CGETSET_ADD(sprite,tex),
|
||||||
|
CGETSET_ADD(sprite,color),
|
||||||
|
CGETSET_ADD(sprite,emissive),
|
||||||
|
CGETSET_ADD(sprite,enabled),
|
||||||
|
CGETSET_ADD(sprite,parallax),
|
||||||
|
CGETSET_ADD(sprite,frame),
|
||||||
|
CGETSET_ADD(sprite,go)
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GETFN(ID, ENTRY, TYPE) \
|
||||||
|
JSValue ID##_get_##ENTRY (JSContext *js, JSValue this, JSValue val) {\
|
||||||
|
return TYPE##2js(js2##ID (this)->ENTRY); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
GETFN(texture,width,number)
|
||||||
|
GETFN(texture,height,number)
|
||||||
|
JSValue texture_get_path(JSContext *js, JSValue this, JSValue val)
|
||||||
|
{
|
||||||
|
return str2js(tex_get_path(js2texture(this)));
|
||||||
|
}
|
||||||
|
static const JSCFunctionListEntry js_texture_funcs[] = {
|
||||||
|
MIST_CFUNC_DEF("width", 0, texture_get_width),
|
||||||
|
MIST_CFUNC_DEF("height", 0, texture_get_height),
|
||||||
|
MIST_CFUNC_DEF("path", 0, texture_get_path)
|
||||||
|
};
|
||||||
|
|
||||||
JSValue constraint_set_max_force (JSContext *js, JSValue this, JSValue val) {
|
JSValue constraint_set_max_force (JSContext *js, JSValue this, JSValue val) {
|
||||||
cpConstraintSetMaxForce(js2constraint(this)->c, js2number(val));
|
cpConstraintSetMaxForce(js2constraint(this)->c, js2number(val));
|
||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
|
@ -2165,11 +1974,6 @@ JSValue duk_cmd_points(JSContext *js, JSValueConst this, int argc, JSValueConst
|
||||||
|
|
||||||
const char *STRTEST = "TEST STRING";
|
const char *STRTEST = "TEST STRING";
|
||||||
|
|
||||||
JSValue duk_performance_js2num(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
JSValue duk_performance(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
JSValue duk_performance(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||||
{
|
{
|
||||||
int cmd = js2int(argv[0]);
|
int cmd = js2int(argv[0]);
|
||||||
|
@ -2242,7 +2046,6 @@ void ffi_load() {
|
||||||
DUK_FUNC(set_body, 3)
|
DUK_FUNC(set_body, 3)
|
||||||
DUK_FUNC(q_body, 2)
|
DUK_FUNC(q_body, 2)
|
||||||
DUK_FUNC(sys_cmd, 1)
|
DUK_FUNC(sys_cmd, 1)
|
||||||
DUK_FUNC(make_sprite, 1)
|
|
||||||
DUK_FUNC(spline_cmd, 6)
|
DUK_FUNC(spline_cmd, 6)
|
||||||
DUK_FUNC(make_circle2d, 1)
|
DUK_FUNC(make_circle2d, 1)
|
||||||
DUK_FUNC(cmd_circle2d, 6)
|
DUK_FUNC(cmd_circle2d, 6)
|
||||||
|
@ -2265,7 +2068,7 @@ void ffi_load() {
|
||||||
JS_FreeValue(js,globalThis);
|
JS_FreeValue(js,globalThis);
|
||||||
|
|
||||||
QJSCLASSPREP(ptr);
|
QJSCLASSPREP(ptr);
|
||||||
QJSCLASSPREP(gameobject);
|
QJSCLASSPREP_FUNCS(gameobject);
|
||||||
QJSCLASSPREP_FUNCS(dsp_node);
|
QJSCLASSPREP_FUNCS(dsp_node);
|
||||||
|
|
||||||
sound_proto = JS_NewObject(js);
|
sound_proto = JS_NewObject(js);
|
||||||
|
@ -2275,7 +2078,8 @@ void ffi_load() {
|
||||||
QJSCLASSPREP_FUNCS(emitter);
|
QJSCLASSPREP_FUNCS(emitter);
|
||||||
QJSCLASSPREP_FUNCS(warp_gravity);
|
QJSCLASSPREP_FUNCS(warp_gravity);
|
||||||
QJSCLASSPREP_FUNCS(warp_damp);
|
QJSCLASSPREP_FUNCS(warp_damp);
|
||||||
|
QJSCLASSPREP_FUNCS(sprite);
|
||||||
|
QJSCLASSPREP_FUNCS(texture);
|
||||||
QJSCLASSPREP_FUNCS(constraint);
|
QJSCLASSPREP_FUNCS(constraint);
|
||||||
|
|
||||||
QJSGLOBALCLASS(os);
|
QJSGLOBALCLASS(os);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
void ffi_load();
|
void ffi_load();
|
||||||
void ffi_stop();
|
void ffi_stop();
|
||||||
|
|
||||||
JSValue vec2js(HMM_Vec2 v);
|
JSValue vec22js(HMM_Vec2 v);
|
||||||
HMM_Vec2 js2vec2(JSValue v);
|
HMM_Vec2 js2vec2(JSValue v);
|
||||||
|
|
||||||
JSValue bitmask2js(cpBitmask mask);
|
JSValue bitmask2js(cpBitmask mask);
|
||||||
|
|
|
@ -99,7 +99,7 @@ emitter *make_emitter() {
|
||||||
sampler_add(&e->color, 0, (HMM_Vec4){1,1,1,1});
|
sampler_add(&e->color, 0, (HMM_Vec4){1,1,1,1});
|
||||||
e->scale = 1;
|
e->scale = 1;
|
||||||
e->speed = 20;
|
e->speed = 20;
|
||||||
e->texture = texture_pullfromfile("glass_chunk2.gif");
|
e->texture = texture_from_file("glass_chunk2.gif");
|
||||||
arrpush(emitters,e);
|
arrpush(emitters,e);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
extern struct rgba color_white;
|
extern struct rgba color_white;
|
||||||
extern struct rgba color_black;
|
extern struct rgba color_black;
|
||||||
|
extern struct rgba color_clear;
|
||||||
|
|
||||||
extern int renderMode;
|
extern int renderMode;
|
||||||
|
|
||||||
|
@ -105,16 +106,9 @@ struct boundingbox {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rect {
|
struct rect {
|
||||||
float h, w, x, y;
|
float x,y,w,h;
|
||||||
};
|
|
||||||
|
|
||||||
/* Normalized S,T coordinates for rendering */
|
|
||||||
struct glrect {
|
|
||||||
float s0;
|
|
||||||
float s1;
|
|
||||||
float t0;
|
|
||||||
float t1;
|
|
||||||
};
|
};
|
||||||
|
typedef struct rect rect;
|
||||||
|
|
||||||
struct boundingbox cwh2bb(HMM_Vec2 c, HMM_Vec2 wh);
|
struct boundingbox cwh2bb(HMM_Vec2 c, HMM_Vec2 wh);
|
||||||
float *rgba2floats(float *r, struct rgba c);
|
float *rgba2floats(float *r, struct rgba c);
|
||||||
|
|
|
@ -295,7 +295,7 @@ void callee_int(struct callee c, int i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void callee_vec2(struct callee c, HMM_Vec2 vec) {
|
void callee_vec2(struct callee c, HMM_Vec2 vec) {
|
||||||
JSValue v = vec2js(vec);
|
JSValue v = vec22js(vec);
|
||||||
js_callee_exec(&c, 1, &v);
|
js_callee_exec(&c, 1, &v);
|
||||||
JS_FreeValue(js, v);
|
JS_FreeValue(js, v);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,17 @@
|
||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
|
|
||||||
#include "datastream.h"
|
|
||||||
#include "font.h"
|
|
||||||
#include "gameobject.h"
|
#include "gameobject.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "stb_ds.h"
|
#include "stb_ds.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include "HandmadeMath.h"
|
#include "HandmadeMath.h"
|
||||||
#include "freelist.h"
|
|
||||||
|
|
||||||
#include "sprite.sglsl.h"
|
#include "sprite.sglsl.h"
|
||||||
#include "9slice.sglsl.h"
|
#include "9slice.sglsl.h"
|
||||||
|
|
||||||
struct TextureOptions TEX_SPRITE = {1};
|
static sprite **sprites = NULL;
|
||||||
|
|
||||||
static struct sprite *sprites = NULL;
|
|
||||||
|
|
||||||
static sg_shader shader_sprite;
|
static sg_shader shader_sprite;
|
||||||
static sg_pipeline pip_sprite;
|
static sg_pipeline pip_sprite;
|
||||||
|
@ -51,89 +43,70 @@ struct slice9_vert {
|
||||||
struct rgba color;
|
struct rgba color;
|
||||||
};
|
};
|
||||||
|
|
||||||
int make_sprite(gameobject *go) {
|
sprite *sprite_make()
|
||||||
struct sprite sprite = {
|
{
|
||||||
.t = t2d_unit,
|
sprite *sp = calloc(sizeof(*sp), 1);
|
||||||
.color = color_white,
|
sp->pos = (HMM_Vec2){0,0};
|
||||||
.emissive = {0,0,0,0},
|
sp->scale = (HMM_Vec2){1,1};
|
||||||
.tex = texture_pullfromfile(NULL),
|
sp->angle = 0;
|
||||||
.go = go,
|
sp->color = color_white;
|
||||||
.next = -1,
|
sp->emissive = color_clear;
|
||||||
.enabled = 1,
|
|
||||||
.drawmode = DRAW_SIMPLE,
|
|
||||||
.parallax = 1
|
|
||||||
};
|
|
||||||
int id;
|
|
||||||
freelist_grab(id, sprites);
|
|
||||||
sprites[id] = sprite;
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sprite_delete(int id) {
|
|
||||||
struct sprite *sp = id2sprite(id);
|
|
||||||
sp->go = NULL;
|
sp->go = NULL;
|
||||||
sp->enabled = 0;
|
sp->tex = texture_from_file(NULL);
|
||||||
freelist_kill(sprites,id);
|
sp->frame = ST_UNIT;
|
||||||
|
sp->drawmode = DRAW_SIMPLE;
|
||||||
|
sp->enabled = 1;
|
||||||
|
sp->parallax = 1;
|
||||||
|
|
||||||
|
arrpush(sprites,sp);
|
||||||
|
|
||||||
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sprite_enabled(int id, int e) { sprites[id].enabled = e; }
|
void sprite_free(sprite *sprite)
|
||||||
|
{
|
||||||
struct sprite *id2sprite(int id) {
|
YughWarn("Freeing sprite %p.", sprite);
|
||||||
if (id < 0) return NULL;
|
|
||||||
return &sprites[id];
|
free(sprite);
|
||||||
|
for (int i = arrlen(sprites)-1; i >= 0; i--)
|
||||||
|
if (sprites[i] == sprite) {
|
||||||
|
arrdelswap(sprites,i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sprite_count = 0;
|
static int sprite_count = 0;
|
||||||
|
|
||||||
void sprite_flush() { sprite_count = 0; }
|
void sprite_flush() { sprite_count = 0; }
|
||||||
|
|
||||||
int sprite_sort(int *a, int *b)
|
int sprite_sort(sprite **sa, sprite **sb)
|
||||||
{
|
{
|
||||||
struct gameobject *goa = sprites[*a].go;
|
sprite *a = *sa;
|
||||||
struct gameobject *gob = sprites[*b].go;
|
sprite *b = *sb;
|
||||||
|
struct gameobject *goa = a->go;
|
||||||
|
struct gameobject *gob= b->go;
|
||||||
|
if (!goa && !gob) return 0;
|
||||||
|
if (!goa) return -1;
|
||||||
|
if (!gob) return 1;
|
||||||
if (goa->drawlayer == gob->drawlayer) return 0;
|
if (goa->drawlayer == gob->drawlayer) return 0;
|
||||||
if (goa->drawlayer > gob->drawlayer) return 1;
|
if (goa->drawlayer > gob->drawlayer) return 1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sprite_draw_all() {
|
void sprite_draw_all() {
|
||||||
|
if (arrlen(sprites) == 0) return;
|
||||||
|
|
||||||
sg_apply_pipeline(pip_sprite);
|
sg_apply_pipeline(pip_sprite);
|
||||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection));
|
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(projection));
|
||||||
int *layers = NULL;
|
|
||||||
if (layers) arrfree(layers);
|
|
||||||
|
|
||||||
for (int i = 0; i < freelist_len(sprites); i++)
|
qsort(sprites, arrlen(sprites), sizeof(*sprites), sprite_sort);
|
||||||
if (sprites[i].next == -1 && sprites[i].go != NULL && sprites[i].enabled)
|
|
||||||
arrpush(layers, i);
|
|
||||||
|
|
||||||
if (!layers || arrlen(layers) == 0) return;
|
for (int i = 0; i < arrlen(sprites); i++)
|
||||||
if (arrlen(layers) > 1)
|
sprite_draw(sprites[i]);
|
||||||
qsort(layers, arrlen(layers), sizeof(*layers), sprite_sort);
|
|
||||||
|
|
||||||
for (int i = 0; i < arrlen(layers); i++)
|
|
||||||
sprite_draw(&sprites[layers[i]]);
|
|
||||||
|
|
||||||
arrfree(layers);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sprite_loadtex(struct sprite *sprite, const char *path, struct glrect frame) {
|
|
||||||
if (!sprite) {
|
|
||||||
YughWarn("NO SPRITE!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sprite->tex = texture_pullfromfile(path);
|
|
||||||
sprite_setframe(sprite, &frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sprite_settex(struct sprite *sprite, struct Texture *tex) {
|
|
||||||
sprite->tex = tex;
|
|
||||||
sprite_setframe(sprite, &ST_UNIT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sprite_initialize() {
|
void sprite_initialize() {
|
||||||
freelist_size(sprites, 500);
|
|
||||||
|
|
||||||
shader_sprite = sg_make_shader(sprite_shader_desc(sg_query_backend()));
|
shader_sprite = sg_make_shader(sprite_shader_desc(sg_query_backend()));
|
||||||
|
|
||||||
pip_sprite = sg_make_pipeline(&(sg_pipeline_desc){
|
pip_sprite = sg_make_pipeline(&(sg_pipeline_desc){
|
||||||
|
@ -179,15 +152,15 @@ void sprite_initialize() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba color, int wrap, HMM_Vec2 wrapoffset, HMM_Vec2 wrapscale, struct rgba emissive, float parallax) {
|
void tex_draw(struct texture *tex, HMM_Mat3 m, struct rect r, struct rgba color, int wrap, HMM_Vec2 wrapoffset, HMM_Vec2 wrapscale, struct rgba emissive, float parallax) {
|
||||||
struct sprite_vert verts[4];
|
struct sprite_vert verts[4];
|
||||||
float w = tex->width*st_s_w(r);
|
float w = tex->width*r.w;
|
||||||
float h = tex->height*st_s_h(r);
|
float h = tex->height*r.h;
|
||||||
|
|
||||||
HMM_Vec2 sposes[4] = {
|
HMM_Vec2 sposes[4] = {
|
||||||
{0.0,0.0},
|
{0,0},
|
||||||
{w,0.0},
|
{w,0},
|
||||||
{0.0,h},
|
{0,h},
|
||||||
{w,h}
|
{w,h}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -198,18 +171,18 @@ void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba colo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wrap) {
|
if (wrap) {
|
||||||
r.s1 *= wrapscale.x;
|
r.w *= wrapscale.x;
|
||||||
r.t1 *= wrapscale.y;
|
r.h *= wrapscale.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
verts[0].uv.X = r.s0;
|
verts[0].uv.X = r.x;
|
||||||
verts[0].uv.Y = r.t1;
|
verts[0].uv.Y = r.y+r.h;
|
||||||
verts[1].uv.X = r.s1;
|
verts[1].uv.X = r.x+r.w;
|
||||||
verts[1].uv.Y = r.t1;
|
verts[1].uv.Y = r.y+r.h;
|
||||||
verts[2].uv.X = r.s0;
|
verts[2].uv.X = r.x;
|
||||||
verts[2].uv.Y = r.t0;
|
verts[2].uv.Y = r.y;
|
||||||
verts[3].uv.X = r.s1;
|
verts[3].uv.X = r.x+r.w;
|
||||||
verts[3].uv.Y = r.t0;
|
verts[3].uv.Y = r.y;
|
||||||
|
|
||||||
bind_sprite.fs.images[0] = tex->id;
|
bind_sprite.fs.images[0] = tex->id;
|
||||||
|
|
||||||
|
@ -220,64 +193,31 @@ void tex_draw(struct Texture *tex, HMM_Mat3 m, struct glrect r, struct rgba colo
|
||||||
sprite_count++;
|
sprite_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transform2d sprite2t(sprite *s)
|
||||||
|
{
|
||||||
|
return (transform2d){
|
||||||
|
.pos = s->pos,
|
||||||
|
.scale = s->scale,
|
||||||
|
.angle = s->angle
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void sprite_draw(struct sprite *sprite) {
|
void sprite_draw(struct sprite *sprite) {
|
||||||
if (!sprite->tex) return;
|
if (!sprite->tex) return;
|
||||||
transform2d t = go2t(sprite->go);
|
transform2d t;
|
||||||
|
if (!sprite->go) t = t2d_unit;
|
||||||
|
else t = go2t(sprite->go);
|
||||||
|
|
||||||
t.pos.x += (cam_pos().x - (cam_pos().x/sprite->parallax));
|
t.pos.x += (cam_pos().x - (cam_pos().x/sprite->parallax));
|
||||||
t.pos.y += (cam_pos().y - (cam_pos().y/sprite->parallax));
|
t.pos.y += (cam_pos().y - (cam_pos().y/sprite->parallax));
|
||||||
HMM_Mat3 m = transform2d2mat(t);
|
HMM_Mat3 m = transform2d2mat(t);
|
||||||
HMM_Mat3 sm = transform2d2mat(sprite->t);
|
HMM_Mat3 sm = transform2d2mat(sprite2t(sprite));
|
||||||
|
tex_draw(sprite->tex, HMM_MulM3(m,sm), sprite->frame, sprite->color, sprite->drawmode, (HMM_Vec2){0,0}, sprite->scale, sprite->emissive, sprite->parallax);
|
||||||
tex_draw(sprite->tex, HMM_MulM3(m, sm), sprite->frame, sprite->color, sprite->drawmode, (HMM_Vec2){0,0}, sprite->t.scale, sprite->emissive, sprite->parallax);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gui_draw_img(const char *img, transform2d t, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color) {
|
void gui_draw_img(const char *img, transform2d t, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color) {
|
||||||
sg_apply_pipeline(pip_sprite);
|
sg_apply_pipeline(pip_sprite);
|
||||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(hudproj));
|
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(hudproj));
|
||||||
struct Texture *tex = texture_pullfromfile(img);
|
struct texture *tex = texture_from_file(img);
|
||||||
tex_draw(tex, transform2d2mat(t), ST_UNIT, color, wrap, wrapoffset, (HMM_Vec2){wrapscale,wrapscale}, (struct rgba){0,0,0,0}, 0);
|
tex_draw(tex, transform2d2mat(t), ST_UNIT, color, wrap, wrapoffset, (HMM_Vec2){wrapscale,wrapscale}, (struct rgba){0,0,0,0}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void slice9_draw(const char *img, HMM_Vec2 pos, HMM_Vec2 dimensions, struct rgba color)
|
|
||||||
{
|
|
||||||
sg_apply_pipeline(slice9_pipe);
|
|
||||||
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(hudproj));
|
|
||||||
struct Texture *tex = texture_pullfromfile(img);
|
|
||||||
|
|
||||||
struct glrect r = ST_UNIT;
|
|
||||||
|
|
||||||
struct slice9_vert verts[4];
|
|
||||||
|
|
||||||
HMM_Vec2 sposes[4] = {
|
|
||||||
{0.0,0.0},
|
|
||||||
{1.0,0.0},
|
|
||||||
{0.0,1.0},
|
|
||||||
{1.0,1.0},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
verts[i].pos = HMM_MulV2(sposes[i], dimensions);
|
|
||||||
//verts[i].uv =z sposes[i];
|
|
||||||
verts[i].color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
verts[0].uv.u = r.s0 * USHRT_MAX;
|
|
||||||
verts[0].uv.v = r.t1 * USHRT_MAX;
|
|
||||||
verts[1].uv.u = r.s1 * USHRT_MAX;
|
|
||||||
verts[1].uv.v = r.t1 * USHRT_MAX;
|
|
||||||
verts[2].uv.u = r.s0 * USHRT_MAX;
|
|
||||||
verts[2].uv.v = r.t0 * USHRT_MAX;
|
|
||||||
verts[3].uv.u = r.s1 * USHRT_MAX;
|
|
||||||
verts[3].uv.v = r.t0 * USHRT_MAX;
|
|
||||||
|
|
||||||
bind_sprite.fs.images[0] = tex->id;
|
|
||||||
sg_append_buffer(bind_sprite.vertex_buffers[0], SG_RANGE_REF(verts));
|
|
||||||
sg_apply_bindings(&bind_sprite);
|
|
||||||
|
|
||||||
sg_draw(sprite_count * 4, 4, 1);
|
|
||||||
sprite_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sprite_setframe(struct sprite *sprite, struct glrect *frame) {
|
|
||||||
sprite->frame = *frame;
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,29 +11,29 @@
|
||||||
#define DRAW_TILE 1
|
#define DRAW_TILE 1
|
||||||
|
|
||||||
struct sprite {
|
struct sprite {
|
||||||
transform2d t;
|
HMM_Vec2 pos;
|
||||||
|
HMM_Vec2 scale;
|
||||||
|
float angle;
|
||||||
struct rgba color;
|
struct rgba color;
|
||||||
struct rgba emissive;
|
struct rgba emissive;
|
||||||
gameobject *go;
|
gameobject *go;
|
||||||
struct Texture *tex;
|
texture *tex;
|
||||||
struct glrect frame;
|
struct rect frame;
|
||||||
int enabled;
|
int enabled;
|
||||||
int next;
|
|
||||||
int drawmode;
|
int drawmode;
|
||||||
float parallax;
|
float parallax;
|
||||||
|
unsigned int next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct sprite sprite;
|
||||||
|
|
||||||
|
sprite *sprite_make();
|
||||||
int make_sprite(gameobject *go);
|
int make_sprite(gameobject *go);
|
||||||
struct sprite *id2sprite(int id);
|
void sprite_free(sprite *sprite);
|
||||||
void sprite_delete(int id);
|
void sprite_delete(int id);
|
||||||
void sprite_enabled(int id, int e);
|
|
||||||
void sprite_loadtex(struct sprite *sprite, const char *path, struct glrect rect);
|
|
||||||
void sprite_settex(struct sprite *sprite, struct Texture *tex);
|
|
||||||
void sprite_setframe(struct sprite *sprite, struct glrect *frame);
|
|
||||||
void sprite_initialize();
|
void sprite_initialize();
|
||||||
void sprite_draw(struct sprite *sprite);
|
void sprite_draw(struct sprite *sprite);
|
||||||
void sprite_draw_all();
|
void sprite_draw_all();
|
||||||
unsigned int incrementAnimFrame(unsigned int interval, struct sprite *sprite);
|
|
||||||
void sprite_flush();
|
void sprite_flush();
|
||||||
|
|
||||||
void gui_draw_img(const char *img, transform2d t, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color);
|
void gui_draw_img(const char *img, transform2d t, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color);
|
||||||
|
|
|
@ -21,15 +21,15 @@
|
||||||
#include "nanosvgrast.h"
|
#include "nanosvgrast.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct glrect ST_UNIT = {0.f, 1.f, 0.f, 1.f};
|
struct rect ST_UNIT = {0.f, 0.f, 1.f, 1.f};
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
char *key;
|
char *key;
|
||||||
struct Texture *value;
|
struct texture *value;
|
||||||
} *texhash = NULL;
|
} *texhash = NULL;
|
||||||
|
|
||||||
struct Texture *tex_default;
|
struct texture *tex_default;
|
||||||
struct Texture *texture_notex() { return texture_pullfromfile("icons/no_tex.gif"); }
|
struct texture *texture_notex() { return texture_from_file("icons/no_tex.gif"); }
|
||||||
|
|
||||||
unsigned int next_pow2(unsigned int v)
|
unsigned int next_pow2(unsigned int v)
|
||||||
{
|
{
|
||||||
|
@ -72,18 +72,18 @@ int mip_wh(int w, int h, int *mw, int *mh, int lvl)
|
||||||
|
|
||||||
int gif_nframes(const char *path)
|
int gif_nframes(const char *path)
|
||||||
{
|
{
|
||||||
struct Texture *t = texture_pullfromfile(path);
|
struct texture *t = texture_from_file(path);
|
||||||
return t->frames;
|
return t->frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
int *gif_delays(const char *path)
|
int *gif_delays(const char *path)
|
||||||
{
|
{
|
||||||
struct Texture *t = texture_pullfromfile(path);
|
struct texture *t = texture_from_file(path);
|
||||||
return t->delays;
|
return t->delays;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If an empty string or null is put for path, loads default texture */
|
/* If an empty string or null is put for path, loads default texture */
|
||||||
struct Texture *texture_pullfromfile(const char *path) {
|
struct texture *texture_from_file(const char *path) {
|
||||||
if (!path) return texture_notex();
|
if (!path) return texture_notex();
|
||||||
if (shlen(texhash) == 0) sh_new_arena(texhash);
|
if (shlen(texhash) == 0) sh_new_arena(texhash);
|
||||||
|
|
||||||
|
@ -98,8 +98,7 @@ struct Texture *texture_pullfromfile(const char *path) {
|
||||||
|
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
|
|
||||||
struct Texture *tex = calloc(1, sizeof(*tex));
|
struct texture *tex = calloc(1, sizeof(*tex));
|
||||||
tex->opts.sprite = 1;
|
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
@ -152,12 +151,7 @@ struct Texture *texture_pullfromfile(const char *path) {
|
||||||
|
|
||||||
tex->data = data;
|
tex->data = data;
|
||||||
|
|
||||||
int filter;
|
int filter = SG_FILTER_NEAREST;
|
||||||
if (tex->opts.sprite) {
|
|
||||||
filter = SG_FILTER_NEAREST;
|
|
||||||
} else {
|
|
||||||
filter = SG_FILTER_LINEAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
sg_image_data sg_img_data;
|
sg_image_data sg_img_data;
|
||||||
|
|
||||||
|
@ -199,13 +193,18 @@ struct Texture *texture_pullfromfile(const char *path) {
|
||||||
|
|
||||||
for (int i = 1; i < mips; i++)
|
for (int i = 1; i < mips; i++)
|
||||||
free(mipdata[i]);
|
free(mipdata[i]);
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void texture_sync(const char *path) { YughWarn("Need to implement texture sync."); }
|
void texture_sync(const char *path) { YughWarn("Need to implement texture sync."); }
|
||||||
|
|
||||||
char *tex_get_path(struct Texture *tex) {
|
void texture_free(texture *tex)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
char *tex_get_path(struct texture *tex) {
|
||||||
for (int i = 0; i < shlen(texhash); i++) {
|
for (int i = 0; i < shlen(texhash); i++) {
|
||||||
if (tex == texhash[i].value) {
|
if (tex == texhash[i].value) {
|
||||||
YughInfo("Found key %s", texhash[i].key);
|
YughInfo("Found key %s", texhash[i].key);
|
||||||
|
@ -216,10 +215,9 @@ char *tex_get_path(struct Texture *tex) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Texture *texture_fromdata(void *raw, long size)
|
struct texture *texture_fromdata(void *raw, long size)
|
||||||
{
|
{
|
||||||
struct Texture *tex = calloc(1, sizeof(*tex));
|
struct texture *tex = calloc(1, sizeof(*tex));
|
||||||
tex->opts.sprite = 1;
|
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
void *data = stbi_load_from_memory(raw, size, &tex->width, &tex->height, &n, 4);
|
void *data = stbi_load_from_memory(raw, size, &tex->width, &tex->height, &n, 4);
|
||||||
|
@ -234,12 +232,7 @@ struct Texture *texture_fromdata(void *raw, long size)
|
||||||
|
|
||||||
tex->data = data;
|
tex->data = data;
|
||||||
|
|
||||||
int filter;
|
int filter = SG_FILTER_NEAREST;
|
||||||
if (tex->opts.sprite) {
|
|
||||||
filter = SG_FILTER_NEAREST;
|
|
||||||
} else {
|
|
||||||
filter = SG_FILTER_LINEAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
sg_image_data sg_img_data;
|
sg_image_data sg_img_data;
|
||||||
|
|
||||||
|
@ -283,9 +276,7 @@ struct Texture *texture_fromdata(void *raw, long size)
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Texture *texture_loadfromfile(const char *path) { return texture_pullfromfile(path); }
|
HMM_Vec2 tex_get_dimensions(struct texture *tex) {
|
||||||
|
|
||||||
HMM_Vec2 tex_get_dimensions(struct Texture *tex) {
|
|
||||||
if (!tex) return (HMM_Vec2){0,0};
|
if (!tex) return (HMM_Vec2){0,0};
|
||||||
HMM_Vec2 d;
|
HMM_Vec2 d;
|
||||||
d.x = tex->width;
|
d.x = tex->width;
|
||||||
|
@ -293,10 +284,6 @@ HMM_Vec2 tex_get_dimensions(struct Texture *tex) {
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
float st_s_w(struct glrect st) { return (st.s1 - st.s0); }
|
|
||||||
|
|
||||||
float st_s_h(struct glrect st) { return (st.t1 - st.t0); }
|
|
||||||
|
|
||||||
static double fade (double t) { return t*t*t*(t*(t*6-15)+10); }
|
static double fade (double t) { return t*t*t*(t*(t*6-15)+10); }
|
||||||
double grad (int hash, double x, double y, double z)
|
double grad (int hash, double x, double y, double z)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,26 +14,20 @@
|
||||||
#define FILTER_NONE SG_FILTER_NONE
|
#define FILTER_NONE SG_FILTER_NONE
|
||||||
#define FILTER_LINEAR SG_FILTER_LINEAR
|
#define FILTER_LINEAR SG_FILTER_LINEAR
|
||||||
|
|
||||||
float st_s_w(struct glrect st);
|
extern struct rect ST_UNIT;
|
||||||
float st_s_h(struct glrect st);
|
|
||||||
|
|
||||||
extern struct glrect ST_UNIT;
|
|
||||||
|
|
||||||
struct TextureOptions {
|
|
||||||
int sprite;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Represents an actual texture on the GPU */
|
/* Represents an actual texture on the GPU */
|
||||||
struct Texture {
|
struct texture {
|
||||||
sg_image id; /* ID reference for the GPU memory location of the texture */
|
sg_image id; /* ID reference for the GPU memory location of the texture */
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
struct TextureOptions opts;
|
|
||||||
int frames;
|
int frames;
|
||||||
int *delays;
|
int *delays;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct texture texture;
|
||||||
|
|
||||||
typedef struct img_sampler{
|
typedef struct img_sampler{
|
||||||
int wrap_u;
|
int wrap_u;
|
||||||
int wrap_v;
|
int wrap_v;
|
||||||
|
@ -43,21 +37,21 @@ typedef struct img_sampler{
|
||||||
int mip_filter;
|
int mip_filter;
|
||||||
} img_sampler;
|
} img_sampler;
|
||||||
|
|
||||||
typedef struct Texture texture;
|
struct texture *texture_from_file(const char *path); // Create texture from image
|
||||||
|
struct texture *texture_fromdata(void *raw, long size);
|
||||||
|
|
||||||
struct Texture *texture_pullfromfile(const char *path); // Create texture from image
|
void texture_free(texture *tex);
|
||||||
struct Texture *texture_fromdata(void *raw, long size);
|
|
||||||
|
|
||||||
/* Hot reloads a texture, if needed */
|
/* Hot reloads a texture, if needed */
|
||||||
void texture_sync(const char *path);
|
void texture_sync(const char *path);
|
||||||
|
|
||||||
char * tex_get_path(struct Texture *tex); // Get image path for texture
|
char * tex_get_path(struct texture *tex); // Get image path for texture
|
||||||
|
|
||||||
int gif_nframes(const char *path);
|
int gif_nframes(const char *path);
|
||||||
int *gif_delays(const char *path);
|
int *gif_delays(const char *path);
|
||||||
|
|
||||||
struct glrect tex_get_rect(struct Texture *tex);
|
struct glrect tex_get_rect(struct texture *tex);
|
||||||
HMM_Vec2 tex_get_dimensions(struct Texture *tex);
|
HMM_Vec2 tex_get_dimensions(struct texture *tex);
|
||||||
|
|
||||||
double perlin(double x, double y, double z);
|
double perlin(double x, double y, double z);
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ struct window mainwin;
|
||||||
|
|
||||||
static struct window *windows = NULL;
|
static struct window *windows = NULL;
|
||||||
|
|
||||||
struct Texture *icon = NULL;
|
struct texture *icon = NULL;
|
||||||
|
|
||||||
void window_resize(int width, int height)
|
void window_resize(int width, int height)
|
||||||
{
|
{
|
||||||
|
@ -52,7 +52,7 @@ void window_suspended(int s)
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_set_icon(const char *png) {
|
void window_set_icon(const char *png) {
|
||||||
icon = texture_pullfromfile(png);
|
icon = texture_from_file(png);
|
||||||
window_seticon(&mainwin, icon);
|
window_seticon(&mainwin, icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ void window_togglefullscreen(struct window *w) {
|
||||||
mainwin.fullscreen = sapp_is_fullscreen();
|
mainwin.fullscreen = sapp_is_fullscreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_seticon(struct window *w, struct Texture *tex)
|
void window_seticon(struct window *w, struct texture *tex)
|
||||||
{
|
{
|
||||||
struct isize {
|
struct isize {
|
||||||
int size;
|
int size;
|
||||||
|
|
|
@ -16,7 +16,7 @@ struct window {
|
||||||
int focus;
|
int focus;
|
||||||
int shown;
|
int shown;
|
||||||
};
|
};
|
||||||
struct Texture;
|
struct texture;
|
||||||
extern struct window mainwin;
|
extern struct window mainwin;
|
||||||
|
|
||||||
void window_resize(int width, int height);
|
void window_resize(int width, int height);
|
||||||
|
@ -29,7 +29,7 @@ void window_togglefullscreen(struct window *w);
|
||||||
void window_unfullscreen(struct window *w);
|
void window_unfullscreen(struct window *w);
|
||||||
|
|
||||||
void window_set_icon(const char *png);
|
void window_set_icon(const char *png);
|
||||||
void window_seticon(struct window *w, struct Texture *icon);
|
void window_seticon(struct window *w, struct texture *icon);
|
||||||
|
|
||||||
void window_render(struct window *w);
|
void window_render(struct window *w);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue