Compare commits

...

5 commits

34 changed files with 1038 additions and 1060 deletions

View file

@ -66,7 +66,7 @@ else ifeq ($(OPT), 1)
CPPFLAGS += -O3 -flto CPPFLAGS += -O3 -flto
INFO :=$(INFO)_opt INFO :=$(INFO)_opt
else else
CPPFLAGS += -O0 CPPFLAGS += -O2
endif endif
CPPFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) -MD $(WARNING_FLAGS) -I. -DVER=\"$(SEM)\" -DCOM=\"$(COM)\" -DINFO=\"$(INFO)\" #-DENABLE_SINC_MEDIUM_CONVERTER -DENABLE_SINC_FAST_CONVERTER -DCP_COLLISION_TYPE_TYPE=uintptr_t -DCP_BITMASK_TYPE=uintptr_t CPPFLAGS += -DHAVE_CEIL -DCP_USE_CGTYPES=0 -DCP_USE_DOUBLES=0 -DHAVE_FLOOR -DHAVE_FMOD -DHAVE_LRINT -DHAVE_LRINTF $(includeflag) -MD $(WARNING_FLAGS) -I. -DVER=\"$(SEM)\" -DCOM=\"$(COM)\" -DINFO=\"$(INFO)\" #-DENABLE_SINC_MEDIUM_CONVERTER -DENABLE_SINC_FAST_CONVERTER -DCP_COLLISION_TYPE_TYPE=uintptr_t -DCP_BITMASK_TYPE=uintptr_t

View file

@ -820,6 +820,12 @@ Object.defineProperty(String.prototype, 'splice', {
} }
}); });
Object.defineProperty(String.prototype, 'sub', {
value: function(index, str) {
return this.slice(0,index) + str + this.slice(index+str.length);
}
});
Object.defineProperty(String.prototype, 'rm', { Object.defineProperty(String.prototype, 'rm', {
value: function(index, endidx = index+1) { return this.slice(0,index) + this.slice(endidx); } value: function(index, endidx = index+1) { return this.slice(0,index) + this.slice(endidx); }
}); });
@ -1551,10 +1557,63 @@ Math.sortpointsccw = function(points)
return ccw.map(function(x) { return x.add(cm); }); return ccw.map(function(x) { return x.add(cm); });
} }
var yaml = {};
yaml.tojson = function(yaml)
{
yaml = yaml.replace(/(\w+):/g, '"$1":');
yaml = yaml.replace(/: ([\w\.]+)/g, ': "$1"');
yaml = yaml.split("\n");
var cont = {};
var cur = 0;
for (var i = 0; i < yaml.length; i++) {
var line = yaml[i];
var indent = line.search(/\S/);
if (indent > cur) {
if (line[indent] == "-") {
cont[indent] = "array";
yaml[i] = line.sub(indent, '[');
} else {
cont[indent] = "obj";
yaml[i] = line.sub(indent-1, '{');
}
}
if (indent < cur) {
while (cur > indent) {
if (cont[cur] === "obj")
yaml[i-1] = yaml[i-1] + "}";
else if (cont[cur] === "array")
yaml[i-1] = yaml[i-1] + "]";
delete cont[cur];
cur--;
}
}
if (indent === cur) {
if (yaml[i][indent] === '-')
yaml[i] = yaml[i].sub(indent,',');
else
yaml[i-1] = yaml[i-1] + ',';
}
cur = indent;
}
yaml = "{" + yaml.join("\n") + "}";
yaml = yaml.replace(/\s/g, '');
yaml = yaml.replace(/,}/g, '}');
yaml = yaml.replace(/,]/g, ']');
return yaml;
}
return { return {
convert, convert,
time, time,
json, json,
Vector, Vector,
bbox bbox,
yaml
}; };

View file

@ -13,6 +13,10 @@ this.view2world = function(pos) {
pos = pos.scale(this.zoom); pos = pos.scale(this.zoom);
pos = pos.add(this.pos); pos = pos.add(this.pos);
} }
if (window.mode === window.modetypes.expand) {
pos = pos.sub(window.size.scale(0.5));
pos = pos.scale([window.rendersize.x/window.size.x, window.rendersize.y/window.size.y]);
}
return pos; return pos;
}; };
this.world2view = function(pos) { this.world2view = function(pos) {
@ -25,6 +29,9 @@ this.world2view = function(pos) {
pos = pos.sub(this.pos); pos = pos.sub(this.pos);
pos = pos.scale(1/this.zoom); pos = pos.scale(1/this.zoom);
pos = pos.add(window.size.scale(0.5)); pos = pos.add(window.size.scale(0.5));
}
if (window.mode === window.modetypes.expand) {
} }
return pos; return pos;
}; };

View file

@ -177,7 +177,7 @@ Object.mixin(os.sprite(true), {
height() { return this.dimensions().y; }, height() { return this.dimensions().y; },
}); });
globalThis.allsprites = {}; globalThis.allsprites = {};
os.sprite(true).make = function(go) os.sprite().make = function(go)
{ {
var sp = os.sprite(); var sp = os.sprite();
sp.go = go; sp.go = go;

View file

@ -344,7 +344,7 @@ var editor = {
root = root ? root + "." : root; root = root ? root + "." : root;
Object.entries(obj.objects).forEach(function(x) { Object.entries(obj.objects).forEach(function(x) {
var p = root + x[0]; var p = root + x[0];
render.text(p, x[1].screenpos(), 1, editor.color_depths[depth]); render.text(p, x[1].this2screen(), 1, editor.color_depths[depth]);
editor.draw_objects_names(x[1], p, depth+1); editor.draw_objects_names(x[1], p, depth+1);
}); });
}, },
@ -402,7 +402,7 @@ var editor = {
if (this.comp_info && this.sel_comp) if (this.comp_info && this.sel_comp)
render.text(input.print_pawn_kbm(this.sel_comp,false), [100,700],1); render.text(input.print_pawn_kbm(this.sel_comp,false), [100,700],1);
render.cross(editor.edit_level.screenpos(),3,Color.blue); render.cross(editor.edit_level.this2screen(),3,Color.blue);
var thiso = editor.get_this(); var thiso = editor.get_this();
var clvl = thiso; var clvl = thiso;
@ -447,16 +447,16 @@ var editor = {
render.text("$$$$$$", [0,ypos],1,editor.color_depths[depth]); render.text("$$$$$$", [0,ypos],1,editor.color_depths[depth]);
this.selectlist.forEach(function(x) { this.selectlist.forEach(function(x) {
render.text(x.urstr(), x.screenpos().add([0, render.font.linegap*2]), 1, Color.editor.ur); render.text(x.urstr(), x.this2screen().add([0, render.font.linegap*2]), 1, Color.editor.ur);
render.text(x.pos.map(function(x) { return Math.round(x); }), x.screenpos()); render.text(x.pos.map(function(x) { return Math.round(x); }), x.this2screen());
render.cross(x.screenpos(), 10, Color.blue); render.cross(x.this2screen(), 10, Color.blue);
}); });
Object.entries(thiso.objects).forEach(function(x) { Object.entries(thiso.objects).forEach(function(x) {
var p = x[1].namestr(); var p = x[1].namestr();
render.text(p, x[1].screenpos().add([0,render.font.linegap]),1,editor.color_depths[depth]); render.text(p, x[1].this2screen().add([0,render.font.linegap]),1,editor.color_depths[depth]);
render.point(x[1].screenpos(),5,Color.blue.alpha(0.3)); render.point(x[1].this2screen(),5,Color.blue.alpha(0.3));
render.point(x[1].screenpos(), 1, Color.red); render.point(x[1].this2screen(), 1, Color.red);
}); });
var mg = physics.pos_query(input.mouse.worldpos()); var mg = physics.pos_query(input.mouse.worldpos());
@ -474,7 +474,7 @@ var editor = {
for (var key in this.selectlist[0].components) { for (var key in this.selectlist[0].components) {
var selected = this.sel_comp === this.selectlist[0].components[key]; var selected = this.sel_comp === this.selectlist[0].components[key];
var str = (selected ? ">" : " ") + key + " [" + this.selectlist[0].components[key].toString() + "]"; var str = (selected ? ">" : " ") + key + " [" + this.selectlist[0].components[key].toString() + "]";
render.text(str, this.selectlist[0].screenpos().add([0,-render.font.linegap*(i++)])); render.text(str, this.selectlist[0].this2screen().add([0,-render.font.linegap*(i++)]));
} }
if (this.sel_comp) { if (this.sel_comp) {
@ -879,7 +879,7 @@ editor.inputs['C-s'] = function() {
} }
var savejs = saveobj.json_obj(); var savejs = saveobj.json_obj();
var tur = saveobj.get_ur(); var tur = saveobj.ur;
if (!tur) { if (!tur) {
console.warn(`Can't save object because it has no ur.`); console.warn(`Can't save object because it has no ur.`);
return; return;

View file

@ -289,7 +289,6 @@ game.engine_start = function(s) {
gggstart(function() { gggstart(function() {
global.mixin("scripts/sound.js"); global.mixin("scripts/sound.js");
world_start(); world_start();
go_init();
window.set_icon(os.make_texture("icons/moon.gif")) window.set_icon(os.make_texture("icons/moon.gif"))
Object.readonly(window.__proto__, 'vsync'); Object.readonly(window.__proto__, 'vsync');
Object.readonly(window.__proto__, 'enable_dragndrop'); Object.readonly(window.__proto__, 'enable_dragndrop');
@ -330,9 +329,9 @@ function process()
} }
var st = profile.now(); var st = profile.now();
if (!game.camera) if (!game.camera)
prosperon.window_render(world, 1); prosperon.window_render(world.transform, 1);
else else
prosperon.window_render(game.camera, game.camera.zoom); prosperon.window_render(game.camera.transform, game.camera.zoom);
render.set_camera(); render.set_camera();
@ -627,7 +626,8 @@ global.mixin("scripts/actor");
global.mixin("scripts/entity"); global.mixin("scripts/entity");
function world_start() { function world_start() {
globalThis.world = os.make_gameobject(); globalThis.world = Object.create(entity);
world.transform = os.make_transform2d();
world.objects = {}; world.objects = {};
world.toString = function() { return "world"; }; world.toString = function() { return "world"; };
world.ur = "world"; world.ur = "world";

View file

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

View file

@ -124,9 +124,9 @@ render.text = function(str, pos, size = 1, color = Color.white, wrap = -1, ancho
}; };
render.image = function(tex, pos, rotation = 0, color = Color.white, dimensions = [tex.width, tex.height]) { render.image = function(tex, pos, rotation = 0, color = Color.white, dimensions = [tex.width, tex.height]) {
var scale = [dimensions.x/tex.width, dimensions.y/tex.height]; //var scale = [dimensions.x/tex.width, dimensions.y/tex.height];
gui.img(tex,pos, scale, 0.0, false, [0.0,0.0], color); //gui.img(tex,pos, scale, 0.0, false, [0.0,0.0], color);
return bbox.fromcwh([0,0], [tex.width,tex.height]); //return bbox.fromcwh([0,0], [tex.width,tex.height]);
} }
render.fontcache = {}; render.fontcache = {};

View file

@ -476,9 +476,54 @@ Cmdline.register_cmd("l", function(n) {
console.level = n; console.level = n;
}, "Set log level."); }, "Set log level.");
function convertYAMLtoJSON(yamlString) {
const lines = yamlString.split('\n');
const jsonObj = {};
let currentKey = '';
let currentValue = '';
let currentDepth = 0;
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (!line || line.startsWith('#')) {
continue;
}
const depth = (line.match(/^\s+/g) || [''])[0].length;
const keyValue = line.split(':');
const key = keyValue[0].trim();
const value = keyValue[1].trim();
if (depth > currentDepth) {
jsonObj[currentKey] = convertYAMLtoJSON(currentValue);
currentKey = key;
currentValue = value;
} else if (depth === currentDepth) {
jsonObj[currentKey] = convertYAMLtoJSON(currentValue);
currentKey = key;
currentValue = value;
} else {
jsonObj[currentKey] = convertYAMLtoJSON(currentValue);
currentKey = '';
currentValue = '';
i--; // To reprocess the current line with updated values
}
currentDepth = depth;
}
if (currentKey) {
jsonObj[currentKey] = convertYAMLtoJSON(currentValue);
}
return jsonObj;
}
return { return {
Resources, Resources,
Cmdline, Cmdline,
cmd_args cmd_args,
convertYAMLtoJSON
}; };

View file

@ -5,9 +5,6 @@
#include "stb_ds.h" #include "stb_ds.h"
#include "gameobject.h" #include "gameobject.h"
//#include "diffuse.sglsl.h"
#include "unlit.sglsl.h"
#include "render.h" #include "render.h"
#include "HandmadeMath.h" #include "HandmadeMath.h"
@ -30,50 +27,8 @@ static void processnode();
static void processmesh(); static void processmesh();
static void processtexture(); static void processtexture();
static sg_shader model_shader; static cgltf_data *cdata;
static sg_pipeline model_pipe; static char *cpath;
struct bone_weights {
char b1;
char b2;
char b3;
char b4;
};
struct joints {
char j1;
char j2;
char j3;
char j4;
};
void model_init() {
model_shader = sg_make_shader(unlit_shader_desc(sg_query_backend()));
model_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = model_shader,
.layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT3,
[1].format = SG_VERTEXFORMAT_USHORT2N,
[1].buffer_index = 1,
[2].format = SG_VERTEXFORMAT_UINT10_N2,
[2].buffer_index = 2,
[3] = {
.format = SG_VERTEXFORMAT_UBYTE4N,
.buffer_index = 3
},
[4] = {
.format = SG_VERTEXFORMAT_UBYTE4,
.buffer_index = 4
}
},
},
.index_type = SG_INDEXTYPE_UINT16,
.cull_mode = SG_CULLMODE_FRONT,
.depth.write_enabled = true,
.depth.compare = SG_COMPAREFUNC_LESS_EQUAL
});
}
cgltf_attribute *get_attr_type(cgltf_primitive *p, cgltf_attribute_type t) cgltf_attribute *get_attr_type(cgltf_primitive *p, cgltf_attribute_type t)
{ {
@ -109,17 +64,21 @@ void mesh_add_material(primitive *prim, cgltf_material *mat)
{ {
if (!mat) return; if (!mat) return;
if (mat->has_pbr_metallic_roughness) { prim->mat = calloc(sizeof(*prim->mat), 1);
material *pmat = prim->mat;
if (mat->has_pbr_metallic_roughness && mat->pbr_metallic_roughness.base_color_texture.texture) {
cgltf_image *img = mat->pbr_metallic_roughness.base_color_texture.texture->image; cgltf_image *img = mat->pbr_metallic_roughness.base_color_texture.texture->image;
if (img->buffer_view) { if (img->buffer_view) {
cgltf_buffer_view *buf = img->buffer_view; cgltf_buffer_view *buf = img->buffer_view;
prim->bind.fs.images[0] = texture_fromdata(buf->buffer->data, buf->size)->id; pmat->diffuse = texture_fromdata(buf->buffer->data, buf->size);
} else {
char *path = makepath(dirname(cpath), img->uri);
pmat->diffuse = texture_from_file(path);
free(path);
}
} else } else
prim->bind.fs.images[0] = texture_from_file(img->uri)->id; pmat->diffuse = texture_from_file("icons/moon.gif");
} else
prim->bind.fs.images[0] = texture_from_file("icons/moon.gif")->id;
prim->bind.fs.samplers[0] = std_sampler;
} }
sg_buffer texcoord_floats(float *f, int verts, int comp) sg_buffer texcoord_floats(float *f, int verts, int comp)
@ -147,6 +106,24 @@ sg_buffer normal_floats(float *f, int verts, int comp)
}); });
} }
sg_buffer ubyten_buffer(float *f, int v, int c)
{
unsigned char b[v*c];
for (int i = 0; i < (v*c); i++)
b[i] = f[i]*255;
return sg_make_buffer(&(sg_buffer_desc){.data=SG_RANGE(b)});
}
sg_buffer ubyte_buffer(float *f, int v, int c)
{
unsigned char b[v*c];
for (int i = 0; i < (v*c); i++)
b[i] = f[i];
return sg_make_buffer(&(sg_buffer_desc){.data=SG_RANGE(b)});
}
sg_buffer joint_buf(float *f, int v, int c) sg_buffer joint_buf(float *f, int v, int c)
{ {
char joints[v*c]; char joints[v*c];
@ -183,7 +160,7 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
idxs[i] = fidx[i]; idxs[i] = fidx[i];
retp.bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){ retp.idx = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = idxs, .data.ptr = idxs,
.data.size = sizeof(*idxs) * n, .data.size = sizeof(*idxs) * n,
.type = SG_BUFFERTYPE_INDEXBUFFER, .type = SG_BUFFERTYPE_INDEXBUFFER,
@ -201,7 +178,7 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
for (int z = 0; z < c; z++) for (int z = 0; z < c; z++)
idxs[z] = z; idxs[z] = z;
retp.bind.index_buffer = sg_make_buffer(&(sg_buffer_desc){ retp.idx = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = idxs, .data.ptr = idxs,
.data.size = sizeof(uint16_t) * c, .data.size = sizeof(uint16_t) * c,
.type = SG_BUFFERTYPE_INDEXBUFFER}); .type = SG_BUFFERTYPE_INDEXBUFFER});
@ -211,7 +188,6 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
printf("adding material\n"); printf("adding material\n");
mesh_add_material(&retp, prim->material); mesh_add_material(&retp, prim->material);
int has_norm = 0;
for (int k = 0; k < prim->attributes_count; k++) { for (int k = 0; k < prim->attributes_count; k++) {
cgltf_attribute attribute = prim->attributes[k]; cgltf_attribute attribute = prim->attributes[k];
@ -224,7 +200,7 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
switch (attribute.type) { switch (attribute.type) {
case cgltf_attribute_type_position: case cgltf_attribute_type_position:
retp.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ retp.pos = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = vs, .data.ptr = vs,
.data.size = sizeof(float) * n, .data.size = sizeof(float) * n,
.label = "mesh vert buffer" .label = "mesh vert buffer"
@ -232,26 +208,26 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
break; break;
case cgltf_attribute_type_normal: case cgltf_attribute_type_normal:
has_norm = 1; retp.norm = normal_floats(vs, verts, comp);
retp.bind.vertex_buffers[2] = normal_floats(vs, verts, comp);
break; break;
case cgltf_attribute_type_tangent: case cgltf_attribute_type_tangent:
break; break;
case cgltf_attribute_type_color: case cgltf_attribute_type_color:
retp.color = ubyten_buffer(vs,verts,comp);
break; break;
case cgltf_attribute_type_weights: case cgltf_attribute_type_weights:
retp.bind.vertex_buffers[3] = weight_buf(vs, verts, comp); retp.weight = ubyten_buffer(vs, verts, comp);
break; break;
case cgltf_attribute_type_joints: case cgltf_attribute_type_joints:
retp.bind.vertex_buffers[4] = joint_buf(vs, verts, comp); retp.bone = ubyte_buffer(vs, verts, comp);
break; break;
case cgltf_attribute_type_texcoord: case cgltf_attribute_type_texcoord:
retp.bind.vertex_buffers[1] = texcoord_floats(vs, verts, comp); retp.uv = texcoord_floats(vs, verts, comp);
break; break;
case cgltf_attribute_type_invalid: case cgltf_attribute_type_invalid:
YughWarn("Invalid type."); YughWarn("Invalid type.");
@ -259,12 +235,31 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
case cgltf_attribute_type_custom: case cgltf_attribute_type_custom:
break; break;
case cgltf_attribute_type_max_enum: case cgltf_attribute_type_max_enum:
break; break;
} }
} }
if (!has_norm) { if (!retp.bone.id) {
char joints[retp.idx_count*4];
memset(joints, 0, retp.idx_count*4);
retp.bone = sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(joints)});
}
if (!retp.weight.id) {
char weights[retp.idx_count*4];
memset(weights,0,retp.idx_count*4);
retp.weight = sg_make_buffer(&(sg_buffer_desc){ .data = SG_RANGE(weights)});
}
if (!retp.color.id) {
char colors[retp.idx_count*4];
memset(colors,0,retp.idx_count*4);
retp.color = sg_make_buffer(&(sg_buffer_desc) { .data = SG_RANGE(colors) });
}
if (!retp.norm.id) {
YughInfo("Making normals."); YughInfo("Making normals.");
cgltf_attribute *pa = get_attr_type(prim, cgltf_attribute_type_position); cgltf_attribute *pa = get_attr_type(prim, cgltf_attribute_type_position);
int n = cgltf_accessor_unpack_floats(pa->data, NULL,0); int n = cgltf_accessor_unpack_floats(pa->data, NULL,0);
@ -283,7 +278,7 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
face_norms[i] = face_norms[i+1] = face_norms[i+2] = packed_norm; face_norms[i] = face_norms[i+1] = face_norms[i+2] = packed_norm;
} }
retp.bind.vertex_buffers[2] = sg_make_buffer(&(sg_buffer_desc){ retp.norm = sg_make_buffer(&(sg_buffer_desc){
.data.ptr = face_norms, .data.ptr = face_norms,
.data.size = sizeof(uint32_t) * verts}); .data.size = sizeof(uint32_t) * verts});
} }
@ -291,7 +286,7 @@ struct primitive mesh_add_primitive(cgltf_primitive *prim)
return retp; return retp;
} }
static cgltf_data *cdata;
void model_add_cgltf_mesh(mesh *m, cgltf_mesh *gltf_mesh) void model_add_cgltf_mesh(mesh *m, cgltf_mesh *gltf_mesh)
{ {
@ -382,7 +377,7 @@ void model_add_cgltf_skin(model *model, cgltf_skin *skin)
sk.root = model->nodes+(skin->skeleton-cdata->nodes); sk.root = model->nodes+(skin->skeleton-cdata->nodes);
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
sk.binds[i] = HMM_M4D(1); sk.binds[i] = MAT1;
for (int i = 0; i < skin->joints_count; i++) { for (int i = 0; i < skin->joints_count; i++) {
int offset = skin->joints[i]-cdata->nodes; int offset = skin->joints[i]-cdata->nodes;
@ -417,6 +412,7 @@ void model_process_node(model *model, cgltf_node *node)
struct model *model_make(const char *path) struct model *model_make(const char *path)
{ {
YughInfo("Making the model from %s.", path); YughInfo("Making the model from %s.", path);
cpath = path;
cgltf_options options = {0}; cgltf_options options = {0};
cgltf_data *data = NULL; cgltf_data *data = NULL;
cgltf_result result = cgltf_parse_file(&options, path, &data); cgltf_result result = cgltf_parse_file(&options, path, &data);
@ -458,8 +454,28 @@ void model_free(model *m)
} }
sg_bindings primitive_bind(primitive *p)
{
sg_bindings b = {0};
b.vertex_buffers[MAT_POS] = p->pos;
b.vertex_buffers[MAT_UV] = p->uv;
b.vertex_buffers[MAT_NORM] = p->norm;
b.vertex_buffers[MAT_BONE] = p->bone;
b.vertex_buffers[MAT_WEIGHT] = p->weight;
b.vertex_buffers[MAT_COLOR] = p->color;
b.index_buffer = p->idx;
b.fs.images[0] = p->mat->diffuse->id;
b.fs.samplers[0] = tex_sampler;
return b;
}
void model_draw_go(model *model, gameobject *go, gameobject *cam) void model_draw_go(model *model, gameobject *go, gameobject *cam)
{ {
HMM_Mat4 view = t3d_go2world(cam);
HMM_Mat4 proj = HMM_Perspective_RH_NO(20, 1, 0.01, 10000);
HMM_Mat4 vp = HMM_MulM4(proj, view);
HMM_Mat4 gom = transform3d2mat(go2t3(go));
animation_run(&model->anim, apptime()); animation_run(&model->anim, apptime());
skin *sk = &model->skin; skin *sk = &model->skin;
@ -470,34 +486,21 @@ void model_draw_go(model *model, gameobject *go, gameobject *cam)
local = HMM_MulM4(md->parent->t, local); local = HMM_MulM4(md->parent->t, local);
md->t = local; md->t = local;
sk->binds[i] = HMM_MulM4(md->t, sk->invbind[i]); sk->binds[i] = HMM_MulM4(md->t, sk->invbind[i]);
//printf("TRANSLATION OF %d IS " HMMFMT_VEC3 "\n", i, HMMPRINT_VEC3(md->pos));
} }
/*sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_skinv, &(sg_range){
HMM_Mat4 view = t3d_go2world(cam);
HMM_Mat4 proj = HMM_Perspective_RH_NO(20, 1, 0.01, 10000);
HMM_Mat4 vp = HMM_MulM4(proj, view);
HMM_Mat4 gom = transform3d2mat(go2t3(go));
sg_apply_pipeline(model_pipe);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vs_p, SG_RANGE_REF(vp.e));
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_skinv, &(sg_range){
.ptr = sk->binds, .ptr = sk->binds,
.size = sizeof(*sk->binds)*50 .size = sizeof(*sk->binds)*50
}); });
float ambient[4] = {1.0,1.0,1.0,1.0}; */
sg_apply_uniforms(SG_SHADERSTAGE_FS, SLOT_lightf, SG_RANGE_REF(ambient));
for (int i = 0; i < arrlen(model->meshes); i++) { for (int i = 0; i < arrlen(model->meshes); i++) {
HMM_Mat4 mod = *model->meshes[i].m; HMM_Mat4 mod = *model->meshes[i].m;
mod = HMM_MulM4(mod, gom); mod = HMM_MulM4(mod, gom);
mesh msh = model->meshes[i]; mesh msh = model->meshes[i];
for (int j = 0; j < arrlen(msh.primitives); j++) { for (int j = 0; j < arrlen(msh.primitives); j++) {
sg_apply_bindings(&(msh.primitives[j].bind)); sg_bindings b = primitive_bind(msh.primitives+j);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vmodel, &(sg_range){ sg_apply_bindings(&b);
.ptr = mod.em, sg_draw(0, msh.primitives[j].idx_count, 1);
.size = sizeof(mod)
});
sg_draw(0, model->meshes[i].primitives[j].idx_count, 1);
} }
} }
} }

View file

@ -8,7 +8,13 @@
#include "anim.h" #include "anim.h"
#include "texture.h" #include "texture.h"
extern HMM_Vec3 eye; #define MAT_POS 0
#define MAT_UV 1
#define MAT_NORM 2
#define MAT_BONE 3
#define MAT_WEIGHT 4
#define MAT_COLOR 5
#define MAT_TAN 6
typedef struct material { typedef struct material {
texture *diffuse; texture *diffuse;
@ -26,7 +32,14 @@ typedef struct material {
struct model; struct model;
typedef struct primitive { typedef struct primitive {
sg_bindings bind; sg_buffer pos;
sg_buffer norm;
sg_buffer uv;
sg_buffer bone;
sg_buffer weight;
sg_buffer color;
sg_buffer idx;
material *mat;
uint32_t idx_count; uint32_t idx_count;
} primitive; } primitive;
@ -60,6 +73,7 @@ typedef struct skin {
typedef struct model { typedef struct model {
struct mesh *meshes; struct mesh *meshes;
md5joint *nodes; md5joint *nodes;
material *mats;
skin skin; skin skin;
struct animation anim; struct animation anim;
} model; } model;
@ -70,8 +84,6 @@ void model_free(model *m);
void model_draw_go(model *m, gameobject *go, gameobject *cam); void model_draw_go(model *m, gameobject *go, gameobject *cam);
void model_init();
material *material_make(); material *material_make();
void material_free(material *mat); void material_free(material *mat);

View file

@ -221,6 +221,7 @@ typedef union HMM_Vec2 {
}; };
float Elements[2]; float Elements[2];
float e[2];
cpVect cp; cpVect cp;
@ -279,6 +280,7 @@ typedef union HMM_Vec3 {
}; };
float Elements[3]; float Elements[3];
float e[3];
} HMM_Vec3; } HMM_Vec3;
@ -403,6 +405,7 @@ typedef union HMM_Mat3 {
typedef union HMM_Mat4 { typedef union HMM_Mat4 {
float Elements[4][4]; float Elements[4][4];
HMM_Vec4 Columns[4]; HMM_Vec4 Columns[4];
HMM_Vec4 col[4];
float e[4][4]; float e[4][4];
float em[16]; float em[16];
} HMM_Mat4; } HMM_Mat4;
@ -421,6 +424,8 @@ static const HMM_Vec3 vBKWD = {0,0,-1};
static const HMM_Vec3 vLEFT = {-1,0,0}; static const HMM_Vec3 vLEFT = {-1,0,0};
static const HMM_Vec3 vRIGHT = {1,0,0}; static const HMM_Vec3 vRIGHT = {1,0,0};
static const HMM_Mat4 MAT1 = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
/* /*
* Angle unit conversion functions * Angle unit conversion functions
*/ */

View file

@ -11,7 +11,6 @@
#include <window.h> #include <window.h>
#include "resources.h" #include "resources.h"
#include "debugdraw.h" #include "debugdraw.h"
#include "text.sglsl.h"
#include "render.h" #include "render.h"
#include "stb_image_write.h" #include "stb_image_write.h"
@ -22,9 +21,7 @@
struct sFont *use_font; struct sFont *use_font;
static sg_shader fontshader;
static sg_bindings bind_text; static sg_bindings bind_text;
static sg_pipeline pipe_text;
struct text_vert { struct text_vert {
struct draw_p pos; struct draw_p pos;
struct draw_p wh; struct draw_p wh;
@ -36,26 +33,6 @@ struct text_vert {
static struct text_vert *text_buffer; static struct text_vert *text_buffer;
void font_init() { void font_init() {
fontshader = sg_make_shader(text_shader_desc(sg_query_backend()));
pipe_text = sg_make_pipeline(&(sg_pipeline_desc){
.shader = fontshader,
.layout = {
.attrs = {
[ATTR_vs_vert].format = SG_VERTEXFORMAT_FLOAT2,
[ATTR_vs_vert].buffer_index = 1,
[ATTR_vs_pos].format = SG_VERTEXFORMAT_FLOAT2,
[ATTR_vs_wh].format = SG_VERTEXFORMAT_FLOAT2,
[ATTR_vs_uv].format = SG_VERTEXFORMAT_USHORT2N,
[ATTR_vs_st].format = SG_VERTEXFORMAT_USHORT2N,
[ATTR_vs_vColor].format = SG_VERTEXFORMAT_UBYTE4N,
},
.buffers[0].step_func = SG_VERTEXSTEP_PER_INSTANCE
},
.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
.colors[0].blend = blend_trans,
.label = "text",
});
bind_text.vertex_buffers[1] = sprite_quad; bind_text.vertex_buffers[1] = sprite_quad;
bind_text.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ bind_text.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
@ -201,7 +178,7 @@ void draw_char_box(struct Character c, HMM_Vec2 cursor, float scale, struct rgba
draw_box(b, wh, color); draw_box(b, wh, color);
} }
void text_flush(HMM_Mat4 *proj) { void text_flush() {
if (arrlen(text_buffer) == 0) return; if (arrlen(text_buffer) == 0) return;
sg_range verts; sg_range verts;
@ -217,9 +194,7 @@ void text_flush(HMM_Mat4 *proj) {
sg_append_buffer(bind_text.vertex_buffers[0], &verts); sg_append_buffer(bind_text.vertex_buffers[0], &verts);
sg_apply_pipeline(pipe_text);
sg_apply_bindings(&bind_text); sg_apply_bindings(&bind_text);
sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, SG_RANGE_REF(*proj));
sg_draw(0, 4, arrlen(text_buffer)); sg_draw(0, 4, arrlen(text_buffer));
arrsetlen(text_buffer, 0); arrsetlen(text_buffer, 0);
} }
@ -377,7 +352,7 @@ int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, f
if (*wordstart == '\e') if (*wordstart == '\e')
wordstart = esc_color(wordstart, &usecolor, color); wordstart = esc_color(wordstart, &usecolor, color);
sdrawCharacter(use_font->Characters[*wordstart], HMM_AddV2(cursor, HMM_MulV2F((HMM_Vec2){1,-1},scale)), scale, (rgba){0,0,0,255}); //sdrawCharacter(use_font->Characters[*wordstart], HMM_AddV2(cursor, HMM_MulV2F((HMM_Vec2){1,-1},scale)), scale, (rgba){0,0,0,255});
sdrawCharacter(use_font->Characters[*wordstart], cursor, scale, usecolor); sdrawCharacter(use_font->Characters[*wordstart], cursor, scale, usecolor);
cursor.X += use_font->Characters[*wordstart].Advance * tracking * scale; cursor.X += use_font->Characters[*wordstart].Advance * tracking * scale;

View file

@ -40,7 +40,6 @@ void text_settype(struct sFont *font);
struct boundingbox text_bb(const char *text, float scale, float lw, float tracking); struct boundingbox text_bb(const char *text, float scale, float lw, float tracking);
int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, float lw, int caret, float tracking); int renderText(const char *text, HMM_Vec2 pos, float scale, struct rgba color, float lw, int caret, float tracking);
// void text_frame(); void text_flush();
void text_flush(HMM_Mat4 *proj);
#endif #endif

View file

@ -204,9 +204,3 @@ HMM_Vec3 go_pos3d(gameobject *go)
HMM_Vec2 pos2d = go_pos(go); HMM_Vec2 pos2d = go_pos(go);
return (HMM_Vec3){pos2d.x, pos2d.y, go->drawlayer}; return (HMM_Vec3){pos2d.x, pos2d.y, go->drawlayer};
} }
void gameobject_draw_debug(gameobject *go) {
if (!go || !go->body) return;
cpBodyEachShape(go->body, body_draw_shapes_dbg, NULL);
}

View file

@ -61,7 +61,10 @@ const char *js2str(JSValue v) {
return JS_ToCString(js, v); return JS_ToCString(js, v);
} }
void jsfreestr(const char *s) { JS_FreeCString(js, s); }
QJSCLASS(gameobject) QJSCLASS(gameobject)
QJSCLASS(transform3d)
QJSCLASS(transform2d)
QJSCLASS(emitter) QJSCLASS(emitter)
QJSCLASS(dsp_node) QJSCLASS(dsp_node)
QJSCLASS(texture) QJSCLASS(texture)
@ -140,6 +143,7 @@ JSValue ptr2js(void *ptr) {
} }
int js_arrlen(JSValue v) { int js_arrlen(JSValue v) {
if (JS_IsUndefined(v)) return 0;
int len; int len;
JS_ToInt32(js, &len, js_getpropstr( v, "length")); JS_ToInt32(js, &len, js_getpropstr( v, "length"));
return len; return len;
@ -331,6 +335,22 @@ JSValue vec32js(HMM_Vec3 v)
return array; return array;
} }
HMM_Vec4 js2vec4(JSValue v)
{
HMM_Vec4 v4;
for (int i = 0; i < 4; i++)
v4.e[i] = js2number(js_getpropidx(v,i));
return v4;
}
JSValue vec42js(HMM_Vec4 v)
{
JSValue array = JS_NewArray(js);
for (int i = 0; i < 4; i++)
js_setprop_num(array,i,number2js(v.e[i]));
return array;
}
cpBitmask js2bitmask(JSValue v) { cpBitmask js2bitmask(JSValue v) {
cpBitmask a; cpBitmask a;
JS_ToUint32(js, &a, v); JS_ToUint32(js, &a, v);
@ -605,7 +625,10 @@ JSC_CCALL(render_line3d,
); );
JSC_CCALL(render_emitters, emitters_draw(&useproj)) JSC_CCALL(render_emitters, emitters_draw(&useproj))
JSC_CCALL(render_flush, debug_flush(&useproj); text_flush(&useproj); ) JSC_CCALL(render_flush, debug_flush(&useproj); )
JSC_CCALL(render_flushtext, text_flush())
JSC_CCALL(render_end_pass, JSC_CCALL(render_end_pass,
sg_end_pass(); sg_end_pass();
sg_commit(); sg_commit();
@ -623,8 +646,199 @@ JSC_CCALL(render_clear_color,
pass_action.colors[0].clear_value = c; pass_action.colors[0].clear_value = c;
) )
JSC_CCALL(render_set_sprite_tex, sprite_tex(js2texture(argv[0]))) sg_shader js2shader(JSValue v)
JSC_CCALL(render_sprite_flush, sprite_flush()) {
sg_shader_desc desc = {0};
JSValue prog = v;
JSValue vs = js_getpropstr(prog, "vs");
JSValue fs = js_getpropstr(prog, "fs");
char *vsf = js2str(js_getpropstr(vs, "code"));
char *fsf = js2str(js_getpropstr(fs, "code"));
desc.vs.source = vsf;
desc.fs.source = fsf;
char *vsmain = js2str(js_getpropstr(vs, "entry_point"));
char *fsmain = js2str(js_getpropstr(fs, "entry_point"));
desc.vs.entry = vsmain;
desc.fs.entry = fsmain;
JSValue vsu = js_getpropstr(vs, "uniform_blocks");
int unin = js_arrlen(vsu);
for (int i = 0; i < unin; i++) {
JSValue u = js_getpropidx(vsu, i);
int slot = js2number(js_getpropstr(u, "slot"));
desc.vs.uniform_blocks[slot].size = js2number(js_getpropstr(u, "size"));
desc.vs.uniform_blocks[slot].layout = SG_UNIFORMLAYOUT_STD140;
}
JSValue fsu = js_getpropstr(fs, "uniform_blocks");
unin = js_arrlen(fsu);
for (int i = 0; i < unin; i++) {
JSValue u = js_getpropidx(fsu, i);
int slot = js2number(js_getpropstr(u, "slot"));
desc.fs.uniform_blocks[slot].size = js2number(js_getpropstr(u, "size"));
desc.fs.uniform_blocks[slot].layout = SG_UNIFORMLAYOUT_STD140;
}
JSValue imgs = js_getpropstr(fs, "images");
unin = js_arrlen(imgs);
for (int i = 0; i < unin; i++) {
JSValue u = js_getpropidx(imgs, i);
int slot = js2number(js_getpropstr(u, "slot"));
desc.fs.images[i].used = true;
desc.fs.images[i].multisampled = js2boolean(js_getpropstr(u, "multisampled"));
desc.fs.images[i].image_type = SG_IMAGETYPE_2D;
desc.fs.images[i].sample_type = SG_IMAGESAMPLETYPE_FLOAT;
}
JSValue samps = js_getpropstr(fs, "samplers");
unin = js_arrlen(samps);
for (int i = 0; i < unin; i++) {
desc.fs.samplers[0].used = true;
desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_FILTERING;
}
JSValue pairs = js_getpropstr(fs, "image_sampler_pairs");
unin = js_arrlen(pairs);
for (int i = 0; i < unin; i++) {
desc.fs.image_sampler_pairs[0].used = true;
desc.fs.image_sampler_pairs[0].image_slot = 0;
desc.fs.image_sampler_pairs[0].sampler_slot = 0;
}
sg_shader sh = sg_make_shader(&desc);
jsfreestr(vsf);
jsfreestr(fsf);
jsfreestr(vsmain);
jsfreestr(fsmain);
return sh;
}
JSC_CCALL(render_pipeline3d,
sg_shader sgshader = js2shader(argv[0]);
sg_pipeline_desc p = {0};
p.shader = sgshader;
sg_vertex_layout_state st = {0};
st.attrs[MAT_POS].format = SG_VERTEXFORMAT_FLOAT3;
st.attrs[MAT_UV].format = SG_VERTEXFORMAT_USHORT2N;
st.attrs[MAT_UV].buffer_index = MAT_UV;
st.attrs[MAT_NORM].format = SG_VERTEXFORMAT_UINT10_N2;
st.attrs[MAT_NORM].buffer_index = MAT_NORM;
st.attrs[MAT_WEIGHT].format = SG_VERTEXFORMAT_UBYTE4N;
st.attrs[MAT_WEIGHT].buffer_index = MAT_WEIGHT;
st.attrs[MAT_BONE].format = SG_VERTEXFORMAT_UBYTE4;
st.attrs[MAT_BONE].buffer_index = MAT_BONE;
st.attrs[MAT_COLOR].format = SG_VERTEXFORMAT_UBYTE4N;
st.attrs[MAT_COLOR].buffer_index = MAT_COLOR;
p.layout = st;
p.index_type = SG_INDEXTYPE_UINT16;
p.depth.write_enabled = true;
p.depth.compare = SG_COMPAREFUNC_LESS_EQUAL;
p.cull_mode = SG_CULLMODE_FRONT;
sg_pipeline pipe = sg_make_pipeline(&p);
return number2js(pipe.id);
)
JSC_CCALL(render_pipelinetext,
sg_shader fontshader = js2shader(argv[0]);
sg_pipeline_desc p = {0};
p.shader = fontshader;
sg_vertex_layout_state st = {0};
st.attrs[0].format = SG_VERTEXFORMAT_FLOAT2;
st.attrs[0].buffer_index = 1;
st.attrs[1].format = SG_VERTEXFORMAT_FLOAT2;
st.attrs[2].format = SG_VERTEXFORMAT_FLOAT2;
st.attrs[3].format = SG_VERTEXFORMAT_USHORT2N;
st.attrs[4].format = SG_VERTEXFORMAT_USHORT2N;
st.attrs[5].format = SG_VERTEXFORMAT_UBYTE4N;
st.buffers[0].step_func = SG_VERTEXSTEP_PER_INSTANCE;
p.layout = st;
p.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP;
p.colors[0].blend = blend_trans;
sg_pipeline pipe = sg_make_pipeline(&p);
return number2js(pipe.id);
)
JSC_CCALL(render_pipeline,
sg_shader sgshader = js2shader(argv[0]);
sg_pipeline_desc pdesc = {0};
pdesc.shader = sgshader;
pdesc.cull_mode = SG_CULLMODE_FRONT;
pdesc.layout.attrs[0].format = SG_VERTEXFORMAT_FLOAT2;
pdesc.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP;
if (js2boolean(js_getpropstr(argv[0], "blend")))
pdesc.colors[0].blend = blend_trans;
sg_pipeline pipe = sg_make_pipeline(&pdesc);
return number2js(pipe.id);
)
JSC_CCALL(render_setuniv,
float f = js2number(argv[2]);
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(f));
)
JSC_CCALL(render_setuniv2,
HMM_Vec2 v = js2vec2(argv[2]);
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(v.e));
)
JSC_CCALL(render_setuniv3,
HMM_Vec3 v = js2vec3(argv[2]);
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(v.e));
)
JSC_CCALL(render_setuniv4,
HMM_Vec4 v = js2vec4(argv[2]);
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(v.e));
)
JSC_CCALL(render_setuniproj,
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(useproj));
)
JSC_CCALL(render_setunim4,
HMM_Mat4 m = MAT1;
if (JS_IsArray(js, argv[2])) {
JSValue arr = argv[2];
int n = js_arrlen(arr);
if (n == 1)
m = transform2d2mat4(js2transform2d(js_getpropidx(arr,0)));
else {
for (int i = 0; i < n; i++) {
HMM_Mat4 p = transform2d2mat4(js2transform2d(js_getpropidx(arr, i)));
m = HMM_MulM4(p,m);
}
}
} else
m = transform2d2mat4(js2transform2d(argv[2]));
sg_apply_uniforms(js2number(argv[0]), js2number(argv[1]), SG_RANGE_REF(m.e));
);
JSC_CCALL(render_spdraw,
sg_bindings bind = {0};
bind.vertex_buffers[0] = sprite_quad;
for (int i = 0; i < js_arrlen(argv[0]); i++) {
bind.fs.images[i] = js2texture(js_getpropidx(argv[0], i))->id;
bind.fs.samplers[i] = std_sampler;
}
sg_apply_bindings(&bind);
sg_draw(0,4,1);
)
JSC_CCALL(render_setpipeline,
sg_pipeline p = {0};
p.id = js2number(argv[0]);
sg_apply_pipeline(p);
)
static const JSCFunctionListEntry js_render_funcs[] = { static const JSCFunctionListEntry js_render_funcs[] = {
MIST_FUNC_DEF(render, grid, 3), MIST_FUNC_DEF(render, grid, 3),
@ -634,14 +848,24 @@ static const JSCFunctionListEntry js_render_funcs[] = {
MIST_FUNC_DEF(render, line, 3), MIST_FUNC_DEF(render, line, 3),
MIST_FUNC_DEF(render, line3d, 2), MIST_FUNC_DEF(render, line3d, 2),
MIST_FUNC_DEF(render, emitters, 0), MIST_FUNC_DEF(render, emitters, 0),
MIST_FUNC_DEF(render, flushtext, 0),
MIST_FUNC_DEF(render, flush, 0), MIST_FUNC_DEF(render, flush, 0),
MIST_FUNC_DEF(render, end_pass, 0), MIST_FUNC_DEF(render, end_pass, 0),
MIST_FUNC_DEF(render, text_size, 3), MIST_FUNC_DEF(render, text_size, 3),
MIST_FUNC_DEF(render, set_camera, 0), MIST_FUNC_DEF(render, set_camera, 0),
MIST_FUNC_DEF(render, hud_res, 1), MIST_FUNC_DEF(render, hud_res, 1),
MIST_FUNC_DEF(render, clear_color, 1), MIST_FUNC_DEF(render, clear_color, 1),
MIST_FUNC_DEF(render, set_sprite_tex, 1), MIST_FUNC_DEF(render, pipeline, 1),
MIST_FUNC_DEF(render, sprite_flush, 0), MIST_FUNC_DEF(render, pipeline3d, 1),
MIST_FUNC_DEF(render, pipelinetext, 1),
MIST_FUNC_DEF(render, setuniv3, 2),
MIST_FUNC_DEF(render, setuniv, 2),
MIST_FUNC_DEF(render, spdraw, 2),
MIST_FUNC_DEF(render, setuniproj, 2),
MIST_FUNC_DEF(render, setunim4, 3),
MIST_FUNC_DEF(render, setuniv2, 2),
MIST_FUNC_DEF(render, setuniv4, 2),
MIST_FUNC_DEF(render, setpipeline, 1)
}; };
JSC_CCALL(gui_flush, text_flush(&useproj)); JSC_CCALL(gui_flush, text_flush(&useproj));
@ -659,21 +883,12 @@ JSC_CCALL(gui_text,
return ret; return ret;
) )
JSC_CCALL(gui_img,
transform2d t;
t.pos = js2vec2(argv[1]);
t.scale = js2vec2(argv[2]);
t.angle = js2number(argv[3]);
gui_draw_img(js2texture(argv[0]), t, js2boolean(argv[4]), js2vec2(argv[5]), 1.0, js2color(argv[6]));
)
JSC_CCALL(gui_font_set, font_set(js2font(argv[0]))) JSC_CCALL(gui_font_set, font_set(js2font(argv[0])))
static const JSCFunctionListEntry js_gui_funcs[] = { static const JSCFunctionListEntry js_gui_funcs[] = {
MIST_FUNC_DEF(gui, flush, 0), MIST_FUNC_DEF(gui, flush, 0),
MIST_FUNC_DEF(gui, scissor, 4), MIST_FUNC_DEF(gui, scissor, 4),
MIST_FUNC_DEF(gui, text, 6), MIST_FUNC_DEF(gui, text, 6),
MIST_FUNC_DEF(gui, img, 7),
MIST_FUNC_DEF(gui, font_set,1) MIST_FUNC_DEF(gui, font_set,1)
}; };
@ -745,7 +960,7 @@ static const JSCFunctionListEntry js_input_funcs[] = {
JSC_CCALL(prosperon_emitters_step, emitters_step(js2number(argv[0]))) JSC_CCALL(prosperon_emitters_step, emitters_step(js2number(argv[0])))
JSC_CCALL(prosperon_phys2d_step, phys2d_update(js2number(argv[0]))) JSC_CCALL(prosperon_phys2d_step, phys2d_update(js2number(argv[0])))
JSC_CCALL(prosperon_window_render, openglRender(&mainwin, js2gameobject(argv[0]), js2number(argv[1]))) JSC_CCALL(prosperon_window_render, openglRender(&mainwin, js2transform2d(argv[0]), js2number(argv[1])))
JSC_CCALL(prosperon_guid, JSC_CCALL(prosperon_guid,
uint8_t bytes[16]; uint8_t bytes[16];
for (int i = 0; i < 16; i++) bytes[i] = rand()%256; for (int i = 0; i < 16; i++) bytes[i] = rand()%256;
@ -893,6 +1108,7 @@ JSC_SCALL(io_save_qoa, save_qoa(str))
JSC_SCALL(io_pack_start, pack_start(str)) JSC_SCALL(io_pack_start, pack_start(str))
JSC_SCALL(io_pack_add, pack_add(str)) JSC_SCALL(io_pack_add, pack_add(str))
JSC_CCALL(io_pack_end, pack_end()) JSC_CCALL(io_pack_end, pack_end())
JSC_SCALL(io_mod, ret = number2js(file_mod_secs(str));)
static const JSCFunctionListEntry js_io_funcs[] = { static const JSCFunctionListEntry js_io_funcs[] = {
MIST_FUNC_DEF(io, exists,1), MIST_FUNC_DEF(io, exists,1),
@ -909,11 +1125,10 @@ static const JSCFunctionListEntry js_io_funcs[] = {
MIST_FUNC_DEF(io, save_qoa,1), MIST_FUNC_DEF(io, save_qoa,1),
MIST_FUNC_DEF(io, pack_start, 1), MIST_FUNC_DEF(io, pack_start, 1),
MIST_FUNC_DEF(io, pack_add, 1), MIST_FUNC_DEF(io, pack_add, 1),
MIST_FUNC_DEF(io, pack_end, 0) MIST_FUNC_DEF(io, pack_end, 0),
MIST_FUNC_DEF(io, mod,1)
}; };
JSC_CCALL(debug_draw_gameobject, gameobject_draw_debug(js2gameobject(argv[0]));)
JSC_GETSET_GLOBAL(disabled_color, color) JSC_GETSET_GLOBAL(disabled_color, color)
JSC_GETSET_GLOBAL(sleep_color, color) JSC_GETSET_GLOBAL(sleep_color, color)
JSC_GETSET_GLOBAL(dynamic_color, color) JSC_GETSET_GLOBAL(dynamic_color, color)
@ -921,7 +1136,6 @@ JSC_GETSET_GLOBAL(kinematic_color, color)
JSC_GETSET_GLOBAL(static_color, color) JSC_GETSET_GLOBAL(static_color, color)
static const JSCFunctionListEntry js_debug_funcs[] = { static const JSCFunctionListEntry js_debug_funcs[] = {
MIST_FUNC_DEF(debug, draw_gameobject, 1),
CGETSET_ADD(global, disabled_color), CGETSET_ADD(global, disabled_color),
CGETSET_ADD(global, sleep_color), CGETSET_ADD(global, sleep_color),
CGETSET_ADD(global, dynamic_color), CGETSET_ADD(global, dynamic_color),
@ -1033,6 +1247,8 @@ static const JSCFunctionListEntry js_physics_funcs[] = {
MIST_FUNC_DEF(physics, make_gravity, 0), MIST_FUNC_DEF(physics, make_gravity, 0),
}; };
JSC_CCALL(model_draw_go, JSC_CCALL(model_draw_go,
model_draw_go(js2model(this), js2gameobject(argv[0]), js2gameobject(argv[1])) model_draw_go(js2model(this), js2gameobject(argv[0]), js2gameobject(argv[1]))
); );
@ -1065,6 +1281,16 @@ static const JSCFunctionListEntry js_emitter_funcs[] = {
CGETSET_ADD(emitter, texture), CGETSET_ADD(emitter, texture),
}; };
JSC_GETSET(transform2d, pos, vec2)
JSC_GETSET(transform2d, scale, vec2)
JSC_GETSET(transform2d, angle, number)
static const JSCFunctionListEntry js_transform2d_funcs[] = {
CGETSET_ADD(transform2d, pos),
CGETSET_ADD(transform2d, scale),
CGETSET_ADD(transform2d, angle)
};
JSC_GETSET(dsp_node, pass, boolean) JSC_GETSET(dsp_node, pass, boolean)
JSC_GETSET(dsp_node, off, boolean) JSC_GETSET(dsp_node, off, boolean)
JSC_GETSET(dsp_node, gain, number) JSC_GETSET(dsp_node, gain, number)
@ -1317,22 +1543,12 @@ static const JSCFunctionListEntry js_pshape_funcs[] = {
JSC_GETSET(sprite, color, color) JSC_GETSET(sprite, color, color)
JSC_GETSET(sprite, emissive, color) JSC_GETSET(sprite, emissive, color)
JSC_GETSET(sprite, pos, vec2)
JSC_GETSET(sprite, scale, vec2)
JSC_GETSET(sprite, angle, number)
JSC_GETSET(sprite, spriteoffset, vec2) JSC_GETSET(sprite, spriteoffset, vec2)
JSC_GETSET(sprite, spritesize, vec2)
JSC_CCALL(sprite_draw, sprite_draw(js2sprite(this), js2gameobject(argv[0])))
static const JSCFunctionListEntry js_sprite_funcs[] = { static const JSCFunctionListEntry js_sprite_funcs[] = {
CGETSET_ADD(sprite,pos),
CGETSET_ADD(sprite,scale),
CGETSET_ADD(sprite,angle),
CGETSET_ADD(sprite,color), CGETSET_ADD(sprite,color),
CGETSET_ADD(sprite,emissive), CGETSET_ADD(sprite,emissive),
CGETSET_ADD(sprite, spriteoffset), CGETSET_ADD(sprite, spriteoffset),
CGETSET_ADD(sprite, spritesize),
MIST_FUNC_DEF(sprite, draw, 1)
}; };
JSC_GET(texture, width, number) JSC_GET(texture, width, number)
@ -1536,11 +1752,22 @@ JSC_SCALL(os_make_texture,
JSC_CCALL(os_make_font, return font2js(MakeFont(js2str(argv[0]), js2number(argv[1])))) JSC_CCALL(os_make_font, return font2js(MakeFont(js2str(argv[0]), js2number(argv[1]))))
JSC_SCALL(os_system, system(str); ) JSC_CCALL(os_make_transform2d,
if (JS_IsUndefined(argv[0]))
return transform2d2js(make_transform2d());
JSC_SCALL(os_make_model, return model2js(model_make(str))) int n = js2number(argv[0]);
transform2d *t = calloc(sizeof(transform2d), n);
JSValue arr = JS_NewArray(js);
for (int i = 0; i < n; i++)
js_setprop_num(arr, i, transform2d2js(t+i));
JSC_CCALL(os_sprite_pipe, sprite_pipe()) return arr;
)
JSC_SCALL(os_system, return number2js(system(str)); )
JSC_SCALL(os_make_model, ret = model2js(model_make(str)))
static const JSCFunctionListEntry js_os_funcs[] = { static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os,sprite,1), MIST_FUNC_DEF(os,sprite,1),
@ -1561,7 +1788,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, make_texture, 1), MIST_FUNC_DEF(os, make_texture, 1),
MIST_FUNC_DEF(os, make_font, 2), MIST_FUNC_DEF(os, make_font, 2),
MIST_FUNC_DEF(os, make_model, 1), MIST_FUNC_DEF(os, make_model, 1),
MIST_FUNC_DEF(os, sprite_pipe, 0) MIST_FUNC_DEF(os, make_transform2d, 1),
}; };
#include "steam.h" #include "steam.h"
@ -1570,10 +1797,13 @@ void ffi_load() {
globalThis = JS_GetGlobalObject(js); globalThis = JS_GetGlobalObject(js);
QJSCLASSPREP(ptr); QJSCLASSPREP(ptr);
QJSCLASSPREP(transform3d);
QJSGLOBALCLASS(os); QJSGLOBALCLASS(os);
QJSCLASSPREP_FUNCS(gameobject); QJSCLASSPREP_FUNCS(gameobject);
QJSCLASSPREP_FUNCS(transform2d);
QJSCLASSPREP_FUNCS(dsp_node); QJSCLASSPREP_FUNCS(dsp_node);
QJSCLASSPREP_FUNCS(emitter); QJSCLASSPREP_FUNCS(emitter);
QJSCLASSPREP_FUNCS(warp_gravity); QJSCLASSPREP_FUNCS(warp_gravity);

View file

@ -135,4 +135,9 @@ JSValue str2js(const char *c, ...);
void nota_int(char *blob); void nota_int(char *blob);
JSValue js_getpropidx(JSValue v, uint32_t i);
JSValue js_getpropstr(JSValue v, const char *str);
const char *js2str(JSValue v);
void jsfreestr(const char *str);
#endif #endif

View file

@ -33,6 +33,7 @@ float camzoom = 1;
sg_buffer sprite_quad; sg_buffer sprite_quad;
sg_sampler std_sampler; sg_sampler std_sampler;
sg_sampler tex_sampler;
static struct { static struct {
sg_swapchain swap; sg_swapchain swap;
@ -242,6 +243,13 @@ void render_init() {
}); });
std_sampler = sg_make_sampler(&(sg_sampler_desc){}); std_sampler = sg_make_sampler(&(sg_sampler_desc){});
tex_sampler = sg_make_sampler(&(sg_sampler_desc){
.min_filter = SG_FILTER_LINEAR,
.mag_filter = SG_FILTER_LINEAR,
.mipmap_filter = SG_FILTER_LINEAR,
.wrap_u = SG_WRAP_REPEAT,
.wrap_v = SG_WRAP_REPEAT
});
#ifndef NDEBUG #ifndef NDEBUG
sg_trace_hooks hh = sg_install_trace_hooks(&hooks); sg_trace_hooks hh = sg_install_trace_hooks(&hooks);
@ -249,9 +257,6 @@ void render_init() {
font_init(); font_init();
debugdraw_init(); debugdraw_init();
sprite_initialize();
model_init();
sg_color c = (sg_color){0,0,0,1}; sg_color c = (sg_color){0,0,0,1};
pass_action = (sg_pass_action){ pass_action = (sg_pass_action){
@ -290,6 +295,9 @@ void render_init() {
1, 1, 1, 1 1, 1, 1, 1
}; };
sg_limits ll = sg_query_limits();
printf("attribute limits %d\n", ll.max_vertex_attrs);
sg_gif.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){ sg_gif.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
.size = sizeof(gif_quad), .size = sizeof(gif_quad),
.data = gif_quad, .data = gif_quad,
@ -330,7 +338,7 @@ HMM_Mat4 useproj = {0};
#define MODE_EXPAND 4 #define MODE_EXPAND 4
#define MODE_FULL 5 #define MODE_FULL 5
void openglRender(struct window *window, gameobject *cam, float zoom) { void openglRender(struct window *window, transform2d *cam, float zoom) {
sg_swapchain sch = sglue_swapchain(); sg_swapchain sch = sglue_swapchain();
sg_begin_pass(&(sg_pass){ sg_begin_pass(&(sg_pass){
.action = pass_action, .action = pass_action,
@ -365,7 +373,7 @@ void openglRender(struct window *window, gameobject *cam, float zoom) {
} }
// 2D projection // 2D projection
campos = go_pos(cam); campos = cam->pos;
camzoom = zoom; camzoom = zoom;
projection = HMM_Orthographic_RH_NO( projection = HMM_Orthographic_RH_NO(

View file

@ -14,6 +14,7 @@
#include "sokol/sokol_gfx.h" #include "sokol/sokol_gfx.h"
#include "HandmadeMath.h" #include "HandmadeMath.h"
#include "gameobject.h" #include "gameobject.h"
#include "transform.h"
#define RGBA_MAX 255 #define RGBA_MAX 255
@ -34,6 +35,7 @@ extern sg_pass_action pass_action;
extern sg_buffer sprite_quad; extern sg_buffer sprite_quad;
extern sg_sampler std_sampler; extern sg_sampler std_sampler;
extern sg_sampler tex_sampler;
struct draw_p { struct draw_p {
float x; float x;
@ -60,7 +62,7 @@ void render_init();
extern HMM_Vec2 campos; extern HMM_Vec2 campos;
extern float camzoom; extern float camzoom;
void openglRender(struct window *window, gameobject *cam, float zoom); void openglRender(struct window *window, transform2d *cam, float zoom);
void opengl_rendermode(enum RenderMode r); void opengl_rendermode(enum RenderMode r);
void openglInit3d(struct window *window); void openglInit3d(struct window *window);

View file

@ -126,6 +126,17 @@ char *dirname(const char *path)
return dir; return dir;
} }
char *makepath(char *dir, char *file)
{
int d = strlen(dir) + strlen(file) + 2;
char *path = malloc(d);
path[0] = 0;
strncat(path, dir, d);
strncat(path, "/", d);
strncat(path, file, d);
return path;
}
char *seprint(char *fmt, ...) char *seprint(char *fmt, ...)
{ {
va_list args; va_list args;

View file

@ -11,7 +11,8 @@ extern int LOADED_GAME;
void resources_init(); void resources_init();
char *get_filename_from_path(char *path, int extension); char *get_filename_from_path(char *path, int extension);
char *get_directory_from_path(char *path); char *dirname(const char *path);
char *makepath(char *dir, char *file);
char *str_replace_ext(const char *s, const char *newext); char *str_replace_ext(const char *s, const char *newext);
FILE *res_open(char *path, const char *tag); FILE *res_open(char *path, const char *tag);
char **ls(const char *path); char **ls(const char *path);
@ -22,8 +23,6 @@ void pack_start(const char *name);
void pack_add(const char *path); void pack_add(const char *path);
void pack_end(); void pack_end();
char *dirname(const char *path);
void *slurp_file(const char *filename, size_t *size); void *slurp_file(const char *filename, size_t *size);
char *slurp_text(const char *filename, size_t *size); char *slurp_text(const char *filename, size_t *size);
int slurp_write(const char *txt, const char *filename, size_t len); int slurp_write(const char *txt, const char *filename, size_t len);

View file

@ -7,182 +7,13 @@
#include "texture.h" #include "texture.h"
#include "HandmadeMath.h" #include "HandmadeMath.h"
#include "sprite.sglsl.h"
#include "9slice.sglsl.h"
static sg_shader shader_sprite;
static sg_pipeline pip_sprite;
sg_bindings bind_sprite;
static sg_shader slice9_shader;
static sg_pipeline slice9_pipe;
static sg_bindings slice9_bind;
struct slice9_vert {
HMM_Vec2 pos;
struct uv_n uv;
unsigned short border[4];
HMM_Vec2 scale;
struct rgba color;
};
sprite *sprite_make() sprite *sprite_make()
{ {
sprite *sp = calloc(sizeof(*sp), 1); sprite *sp = calloc(sizeof(*sp), 1);
sp->pos = v2zero;
sp->scale = v2one;
sp->angle = 0;
sp->color = color_white; sp->color = color_white;
sp->emissive = color_clear; sp->emissive = color_clear;
sp->spritesize = v2one; sp->rect = (HMM_Vec4){0,0,1,1};
sp->spriteoffset = v2zero;
return sp; return sp;
} }
void sprite_free(sprite *sprite) { free(sprite); } void sprite_free(sprite *sprite) { free(sprite); }
static texture *loadedtex;
static int sprite_count = 0;
void sprite_flush() {
return;
if (!loadedtex) return;
/*
int flushed = arrlen(spverts)/4;
sg_apply_bindings(&bind_sprite);
sg_range data = (sg_range){
.ptr = spverts,
.size = sizeof(sprite_vert)*arrlen(spverts)
};
if (sg_query_buffer_will_overflow(bind_sprite.vertex_buffers[0], data.size))
bind_sprite.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
.size = data.size,
.type = SG_BUFFERTYPE_VERTEXBUFFER,
.usage = SG_USAGE_STREAM,
.label = "sprite vertex buffer"
});
sg_update_buffer(bind_sprite.vertex_buffers[0], &data);
sg_draw(sprite_count * 4, 4, flushed);
sprite_count += flushed;
*/
}
void sprite_initialize() {
shader_sprite = sg_make_shader(sprite_shader_desc(sg_query_backend()));
pip_sprite = sg_make_pipeline(&(sg_pipeline_desc){
.shader = shader_sprite,
.layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT2
},
},
.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
.label = "sprite pipeline",
.colors[0].blend = blend_trans,
});
bind_sprite.vertex_buffers[0] = sprite_quad;
bind_sprite.fs.samplers[0] = std_sampler;
slice9_shader = sg_make_shader(slice9_shader_desc(sg_query_backend()));
slice9_pipe = sg_make_pipeline(&(sg_pipeline_desc){
.shader = slice9_shader,
.layout = {
.attrs = {
[0].format = SG_VERTEXFORMAT_FLOAT2,
[1].format = SG_VERTEXFORMAT_FLOAT2,
[2].format = SG_VERTEXFORMAT_USHORT4N,
[3].format = SG_VERTEXFORMAT_FLOAT2,
[4].format = SG_VERTEXFORMAT_UBYTE4N
}},
.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP,
});
slice9_bind.vertex_buffers[0] = sprite_quad;
}
void sprite_pipe()
{
sg_apply_pipeline(pip_sprite);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vp, SG_RANGE_REF(useproj));
sg_apply_bindings(&bind_sprite);
}
void tex_draw(HMM_Mat3 m, struct rect r, struct rgba color, int wrap, HMM_Vec2 wrapoffset, HMM_Vec2 wrapscale, struct rgba emissive) {
/*
struct sprite_vert verts[4];
float w = loadedtex->width*r.w;
float h = loadedtex->height*r.h;
HMM_Vec2 sposes[4] = {
{0,0},
{w,0},
{0,h},
{w,h}
};
for (int i = 0; i < 4; i++)
verts[i].pos = mat_t_pos(m, sposes[i]);
if (wrap) {
r.w *= wrapscale.x;
r.h *= wrapscale.y;
}
verts[0].uv.X = r.x;
verts[0].uv.Y = r.y+r.h;
verts[1].uv.X = r.x+r.w;
verts[1].uv.Y = r.y+r.h;
verts[2].uv.X = r.x;
verts[2].uv.Y = r.y;
verts[3].uv.X = r.x+r.w;
verts[3].uv.Y = r.y;
for (int i = 0; i < 4; i++)
arrput(spverts, verts[i]);
*/
}
transform2d sprite2t(sprite *s)
{
return (transform2d){
.pos = s->pos,
.scale = HMM_MulV2(s->scale, (HMM_Vec2){loadedtex->width, loadedtex->height}),
.angle = HMM_TurnToRad*s->angle
};
}
void sprite_tex(texture *t)
{
loadedtex = t;
bind_sprite.fs.images[0] = t->id;
}
void sprite_draw(struct sprite *sprite, gameobject *go) {
HMM_Mat4 m = transform2d2mat4(go2t(go));
HMM_Mat4 sm = transform2d2mat4(sprite2t(sprite));
struct spriteuni spv;
rgba2floats(&spv.color.e, sprite->color);
rgba2floats(spv.emissive.e, sprite->emissive);
spv.size = sprite->spritesize;
spv.offset = sprite->spriteoffset;
spv.model = HMM_MulM4(m,sm);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_sprite, SG_RANGE_REF(spv));
sg_draw(0,4,1);
}
void gui_draw_img(texture *tex, transform2d t, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color) {
sg_apply_pipeline(pip_sprite);
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_vp, SG_RANGE_REF(useproj));
sprite_tex(tex);
tex_draw(transform2d2mat(t), ST_UNIT, color, wrap, wrapoffset, (HMM_Vec2){wrapscale,wrapscale}, (struct rgba){0,0,0,0});
}
void slice9_draw(texture *tex, transform2d *t, HMM_Vec4 border, struct rgba color)
{
}

View file

@ -7,37 +7,14 @@
#include "transform.h" #include "transform.h"
#include "gameobject.h" #include "gameobject.h"
struct sprite { typedef struct sprite {
HMM_Vec2 pos;
HMM_Vec2 scale;
float angle;
struct rgba color; struct rgba color;
struct rgba emissive; struct rgba emissive;
HMM_Vec2 spritesize; HMM_Vec4 rect;
HMM_Vec2 spriteoffset; HMM_Vec2 spriteoffset;
}; } sprite;
struct spriteuni {
HMM_Vec4 color;
HMM_Vec4 emissive;
HMM_Vec2 size;
HMM_Vec2 offset;
HMM_Mat4 model;
};
typedef struct sprite sprite;
extern sg_bindings bind_sprite;
sprite *sprite_make(); sprite *sprite_make();
void sprite_free(sprite *sprite); void sprite_free(sprite *sprite);
void sprite_tex(texture *t);
void sprite_initialize();
void sprite_draw(struct sprite *sprite, gameobject *go);
void sprite_pipe();
void sprite_draw_all();
void sprite_flush();
void gui_draw_img(texture *tex, transform2d t, int wrap, HMM_Vec2 wrapoffset, float wrapscale, struct rgba color);
#endif #endif

View file

@ -122,11 +122,9 @@ struct texture *texture_from_file(const char *path) {
unsigned int nw = next_pow2(tex->width); unsigned int nw = next_pow2(tex->width);
unsigned int nh = next_pow2(tex->height); unsigned int nh = next_pow2(tex->height);
int filter = SG_FILTER_NEAREST;
sg_image_data sg_img_data; sg_image_data sg_img_data;
sg_img_data.subimage[0][0] = (sg_range){.ptr = data, .size=tex->width*tex->height*4}; sg_img_data.subimage[0][0] = (sg_range){.ptr = data, .size=tex->width*tex->height*4};
/*
int mips = mip_levels(tex->width, tex->height)+1; int mips = mip_levels(tex->width, tex->height)+1;
YughInfo("Has %d mip levels, from wxh %dx%d, pow2 is %ux%u.", mips, tex->width, tex->height,nw,nh); YughInfo("Has %d mip levels, from wxh %dx%d, pow2 is %ux%u.", mips, tex->width, tex->height,nw,nh);
@ -151,18 +149,18 @@ struct texture *texture_from_file(const char *path) {
mipw = w; mipw = w;
miph = h; miph = h;
} }
*/
tex->id = sg_make_image(&(sg_image_desc){ tex->id = sg_make_image(&(sg_image_desc){
.type = SG_IMAGETYPE_2D, .type = SG_IMAGETYPE_2D,
.width = tex->width, .width = tex->width,
.height = tex->height, .height = tex->height,
.usage = SG_USAGE_IMMUTABLE, .usage = SG_USAGE_IMMUTABLE,
//.num_mipmaps = mips, .num_mipmaps = mips,
.data = sg_img_data .data = sg_img_data
}); });
/*for (int i = 1; i < mips; i++) for (int i = 1; i < mips; i++)
free(mipdata[i]);*/ free(mipdata[i]);
return tex; return tex;
} }
@ -191,8 +189,6 @@ struct texture *texture_fromdata(void *raw, long size)
tex->data = data; tex->data = data;
int filter = SG_FILTER_NEAREST;
sg_image_data sg_img_data; sg_image_data sg_img_data;
int mips = mip_levels(tex->width, tex->height)+1; int mips = mip_levels(tex->width, tex->height)+1;

View file

@ -18,7 +18,8 @@ extern struct rect ST_UNIT;
/* 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;

View file

@ -1,5 +1,6 @@
#include "transform.h" #include "transform.h"
#include <string.h> #include <string.h>
#include <stdio.h>
const transform2d t2d_unit = { const transform2d t2d_unit = {
.pos = {0,0}, .pos = {0,0},
@ -7,6 +8,23 @@ const transform2d t2d_unit = {
.angle = 0 .angle = 0
}; };
transform3d *make_transform3d()
{
transform3d *t = calloc(sizeof(transform3d),1);
return t;
}
void transform3d_free(transform3d *t) { free(t); }
transform2d *make_transform2d()
{
transform2d *t = calloc(sizeof(transform2d),1);
t->scale = (HMM_Vec2){1,1};
return t;
}
void transform2d_free(transform2d *t) { free(t); }
HMM_Vec3 trans_forward(const transform3d *const trans) { return HMM_QVRot(vFWD, trans->rotation); } HMM_Vec3 trans_forward(const transform3d *const trans) { return HMM_QVRot(vFWD, trans->rotation); }
HMM_Vec3 trans_back(const transform3d *trans) { return HMM_QVRot(vBKWD, trans->rotation); } HMM_Vec3 trans_back(const transform3d *trans) { return HMM_QVRot(vBKWD, trans->rotation); }
HMM_Vec3 trans_up(const transform3d *trans) { return HMM_QVRot(vUP, trans->rotation); } HMM_Vec3 trans_up(const transform3d *trans) { return HMM_QVRot(vUP, trans->rotation); }
@ -40,13 +58,19 @@ HMM_Mat3 transform2d2mat(transform2d trn) {
return HMM_MulM3(HMM_Translate2D(trn.pos), HMM_MulM3(HMM_RotateM3(trn.angle), HMM_ScaleM3(trn.scale))); return HMM_MulM3(HMM_Translate2D(trn.pos), HMM_MulM3(HMM_RotateM3(trn.angle), HMM_ScaleM3(trn.scale)));
} }
HMM_Mat4 transform2d2mat4(transform2d trn) HMM_Mat4 transform2d2mat4(transform2d *t)
{ {
transform3d t3d; HMM_Mat4 T = {0};
t3d.pos.xy = trn.pos; float c = cosf(t->angle);
t3d.scale.xy = trn.scale; float s = sinf(t->angle);
t3d.rotation = HMM_QFromAxisAngle_RH((HMM_Vec3){0,0,-1}, trn.angle); T.col[0].x = c*t->scale.x;
return transform3d2mat(t3d); T.col[0].y = s*t->scale.y;
T.col[1].x = -s*t->scale.x;
T.col[1].y = c*t->scale.y;
T.col[3].xy = t->pos;
T.col[2].z = 1;
T.col[3].w = 1;
return T;
} }
transform2d mat2transform2d(HMM_Mat3 m) transform2d mat2transform2d(HMM_Mat3 m)

View file

@ -9,12 +9,18 @@ typedef struct transform3d {
HMM_Quat rotation; HMM_Quat rotation;
} transform3d; } transform3d;
transform3d *make_transform3d();
void transform3d_free(transform3d *t);
typedef struct { typedef struct {
HMM_Vec2 pos; HMM_Vec2 pos;
HMM_Vec2 scale; HMM_Vec2 scale;
float angle; float angle;
} transform2d; } transform2d;
transform2d *make_transform2d();
void transform2d_free(transform2d *t);
extern const transform2d t2d_unit; extern const transform2d t2d_unit;
#define VEC2_FMT "[%g,%g]" #define VEC2_FMT "[%g,%g]"
@ -27,7 +33,7 @@ HMM_Vec3 trans_down(const transform3d *trans);
HMM_Vec3 trans_right(const transform3d *trans); HMM_Vec3 trans_right(const transform3d *trans);
HMM_Vec3 trans_left(const transform3d *trans); HMM_Vec3 trans_left(const transform3d *trans);
HMM_Mat4 transform2d2mat4(transform2d trn); HMM_Mat4 transform2d2mat4(transform2d *t);
/* Transform a position via the matrix */ /* Transform a position via the matrix */
HMM_Vec2 mat_t_pos(HMM_Mat3 m, HMM_Vec2 pos); HMM_Vec2 mat_t_pos(HMM_Mat3 m, HMM_Vec2 pos);

View file

@ -1,65 +0,0 @@
@vs vs9
in vec2 vert;
in vec2 vuv;
in vec4 vborder;
in vec2 vscale;
in vec4 vcolor;
out vec2 uv;
out vec4 border;
out vec2 scale;
out vec4 fcolor;
uniform vs9_params { mat4 projection; };
void main()
{
gl_Position = projection * vec4(vert, 0.0, 1.0);
uv = vuv;
border = vborder;
scale = vscale;
fcolor = vcolor;
}
@end
@fs fs9
in vec2 uv; /* image uv */
in vec4 border; /* uv length of border, normalized to image dimensions; left, bottom, right, top */
in vec2 scale; /* polygon dimensions ~ texture dimensions */
in vec4 fcolor;
out vec4 color;
uniform texture2D image;
uniform sampler smp;
float map(float value, float min1, float max1, float min2, float max2)
{
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
}
float processAxis(float coord, float texBorder, float winBorder)
{
if (coord < winBorder)
return map(coord, 0, winBorder, 0, texBorder);
if (coord < 1 - winBorder)
return map(coord, winBorder, 1 - winBorder, texBorder, 1 - texBorder);
return map(coord, 1 - winBorder, 1, 1 - texBorder, 1);
}
vec2 uv9slice(vec2 uv, vec2 s, vec4 b)
{
vec2 t = clamp((s * uv - b.xy) / (s - b.xy - b.zw), 0.0, 1.0);
return mix(uv * s, 1.0 - s * (1.0 - uv), t);
}
void main()
{
vec2 nuv = uv9slice(uv, scale, border);
color = fcolor * texture(sampler2D(image,smp), nuv);
}
@end
@program slice9 vs9 fs9

View file

@ -1,14 +0,0 @@
#version 330
in vec2 TexCoords;
out vec4 color;
uniform sampler2DArray image;
uniform float frame;
uniform vec3 spriteColor;
void main()
{
color = vec4(spriteColor, 1.f) * texture(image, vec3(TexCoords,frame));
if (color.a < 0.1)
discard;
}

View file

@ -1,17 +0,0 @@
#version 330 core
layout (location = 0) in vec2 vertex; // <vec2 position, vec2 texCoords>
out vec2 TexCoords;
layout (std140) uniform Projection
{
mat4 projection;
};
uniform mat4 model;
void main()
{
TexCoords = vertex.xy;
gl_Position = projection * model * vec4(vertex.xy, 0.0, 1.0);
}

View file

@ -1,53 +0,0 @@
@vs vs
in vec2 vertex;
out vec2 texcoords;
out vec4 fcolor;
out vec4 femissive;
uniform app {
float time;
vec2 window;
};
uniform vp {
mat4 proj;
};
uniform sprite {
vec4 vcolor;
vec4 vemissive;
vec2 spritesize;
vec2 spriteoff;
mat4 model;
};
void main()
{
texcoords = vertex;
texcoords.y = 1 - texcoords.y;
gl_Position = proj * model * vec4(vertex, 0, 1.0);
fcolor = vcolor;
femissive = vemissive;
}
@end
@fs fs
in vec2 texcoords;
in vec4 fcolor;
in vec4 femissive;
out vec4 color;
uniform texture2D image;
uniform sampler smp;
void main()
{
color = texture(sampler2D(image,smp), texcoords);
color *= fcolor;
color.xyz = mix(color.xyz, femissive.xyz, femissive.a);
}
@end
@program sprite vs fs

View file

@ -1,12 +0,0 @@
#version 330 core
in vec2 texcoords;
out vec4 color;
uniform sampler2D image;
uniform vec3 spriteColor;
void main()
{
color = vec4(spriteColor, 1.f) * texture(image, texcoords);
color.a = 1.f;
}

View file

@ -1,42 +0,0 @@
@vs vs
in vec2 vert;
in vec2 pos;
in vec2 wh;
in vec2 uv;
in vec2 st;
in vec4 vColor;
out vec2 TexCoords;
out vec4 fColor;
uniform vs_params { mat4 projection; };
void main()
{
gl_Position = projection * vec4(pos + (vert * wh), 0.0, 1.0);
TexCoords = uv + vec2(vert.x*st.x, st.y - vert.y*st.y);
fColor = vColor;
}
@end
@fs fs
in vec2 TexCoords;
in vec4 fColor;
out vec4 color;
uniform texture2D text;
uniform sampler smp;
void main()
{
float lettera = texture(sampler2D(text,smp),TexCoords).r;
if (lettera < 0.1f) discard;
color = fColor;
}
@end
@program text vs fs

View file

@ -1,30 +1,45 @@
@vs vs @block vptr
in vec3 a_pos; in vec3 a_pos;
in vec2 a_tex_coords; in vec2 a_uv;
in vec4 a_norm; in vec4 a_norm;
in vec4 a_weight;
in vec4 a_joint;
out vec2 tex_coords; out vec2 tex_coords;
out vec3 normal; out vec3 normal;
uniform vs_p { uniform mat4 vp; }; uniform vs_p { uniform mat4 vp; };
uniform vmodel { uniform mat4 model; }; uniform vmodel { uniform mat4 model; };
@end
@vs vs
@include_block vptr
in vec4 a_bone;
in vec4 a_weight;
uniform skinv { uniform mat4 bones[50]; }; uniform skinv { uniform mat4 bones[50]; };
void main() { void main() {
mat4 skin = bones[int(a_joint.x)] * a_weight.x; mat4 tt = vp;
skin += bones[int(a_joint.y)] * a_weight.y; mat4 mm = model;
skin += bones[int(a_joint.z)] * a_weight.z; mat4 skin = bones[int(a_bone.x)] * a_weight.x;
skin += bones[int(a_joint.w)] * a_weight.w; skin += bones[int(a_bone.y)] * a_weight.y;
mat4 skinm = model * skin; skin += bones[int(a_bone.z)] * a_weight.z;
gl_Position = vp * skinm * vec4(a_pos,1.0); skin += bones[int(a_bone.w)] * a_weight.w;
tex_coords = a_tex_coords; mat4 skinm = mm * skin;
gl_Position = tt * skinm * vec4(a_pos,1.0);
tex_coords = a_uv;
normal = (skinm * vec4(a_norm.xyz*2-1,0)).xyz; normal = (skinm * vec4(a_norm.xyz*2-1,0)).xyz;
} }
@end @end
@vs vs_st
@include_block vptr
void main() {
gl_Position = vp * model * vec4(a_pos,1.0);
tex_coords = a_uv;
normal = (model * vec4(a_norm.xyz*2-1,0)).xyz;
}
@end
@fs fs @fs fs
in vec2 tex_coords; in vec2 tex_coords;
in vec3 normal; in vec3 normal;
@ -45,3 +60,4 @@ void main() {
@end @end
@program unlit vs fs @program unlit vs fs
@program unlit_st vs_st fs