actor cleanup

This commit is contained in:
2025-01-18 18:15:15 -06:00
parent aa38fd2c19
commit a142b6d1f4
11 changed files with 179 additions and 269 deletions

View File

@@ -11,7 +11,7 @@ var script_fn = function script_fn(file) {
script = `(function use_${file.name()}() { var self = this; var $ = this.__proto__; ${script}; })`; script = `(function use_${file.name()}() { var self = this; var $ = this.__proto__; ${script}; })`;
var fn = os.eval(file,script); var fn = os.eval(file,script);
return fn; return fn;
}.hashify(); }
globalThis.actor_use = function actor_use(script) globalThis.actor_use = function actor_use(script)
{ {
@@ -38,20 +38,23 @@ globalThis.class_use = function class_use(script, config, base, callback) {
if (!actor_urs[file]) { if (!actor_urs[file]) {
var newur = Object.create(base); var newur = Object.create(base);
actor_urs[file] = newur; actor_urs[file] = newur;
newur._file = file;
newur._root = file.dir();
actor_spawns[file] = []; actor_spawns[file] = [];
newur._script = script_fn(file)
} }
var padawan = Object.create(actor_urs[file]); var padawan = Object.create(actor_urs[file]);
actor_spawns[file].push(padawan); actor_spawns[file].push(padawan);
padawan._file = file;
padawan._root = file.dir();
if (callback) callback(padawan); if (callback) callback(padawan);
script_fn(file).call(padawan); actor_urs[file]._script.call(padawan)
if (typeof config === "object") Object.merge(padawan, config); if (typeof config === "object") Object.merge(padawan, config);
if (!actor_urs[file].__reggies) actor_urs[file].__reggies = pull_registers(padawan);
return padawan; return padawan;
}; };

View File

@@ -21,7 +21,7 @@ frog = {
} }
*/ */
globalThis.sprite_qt = os.make_rtree(); if (!globalThis.sprite_qt) globalThis.sprite_qt = os.make_rtree();
//globalThis.sprite_qt = os.make_quadtree({x:-2000,y:2000,w:4000,h:4000}); //globalThis.sprite_qt = os.make_quadtree({x:-2000,y:2000,w:4000,h:4000});
var sprite = { var sprite = {
@@ -35,10 +35,8 @@ var sprite = {
anim_speed: 1, anim_speed: 1,
play(str, loop = true, reverse = false, fn) { play(str, loop = true, reverse = false, fn) {
if (!this.animset) { if (!this.animset) {
// console.warn(`Sprite has no animset when trying to play ${str}`);
fn?.(); fn?.();
return; return;
// return parseq.imm();
} }
if (typeof str === 'string') { if (typeof str === 'string') {
@@ -94,12 +92,6 @@ var sprite = {
stop = self.gameobject.delay(advance, playing.frames[f].time/self.anim_speed); stop = self.gameobject.delay(advance, playing.frames[f].time/self.anim_speed);
advance(); advance();
}, },
tex_sync() {
if (this.anim) this.stop();
this.play();
this.transform.scale = [this.image.texture.width, this.image.texture.height];
this._sprite.set_image(this.image);
},
stop() { stop() {
this.del_anim?.(); this.del_anim?.();
}, },
@@ -112,7 +104,8 @@ var sprite = {
this._p = p; this._p = p;
this.del_anim?.(); this.stop();
if (image.texture) if (image.texture)
this.image = image; this.image = image;
else if (image.frames) { else if (image.frames) {
@@ -120,6 +113,7 @@ var sprite = {
this.anim = image; this.anim = image;
this.image = image.frames[0]; this.image = image.frames[0];
this.animset = [this.anim] this.animset = [this.anim]
this.play();
} else { } else {
// Maybe an animset; try to grab the first one // Maybe an animset; try to grab the first one
for (var anim in image) { for (var anim in image) {
@@ -127,12 +121,14 @@ var sprite = {
this.anim = image[anim]; this.anim = image[anim];
this.image = image[anim].frames[0]; this.image = image[anim].frames[0];
this.animset = image; this.animset = image;
this.play();
break; break;
} }
} }
} }
this.tex_sync(); this.transform.scale = [this.image.texture.width, this.image.texture.height];
this._sprite.set_image(this.image);
}, },
get path() { get path() {
return this._p; return this._p;
@@ -226,57 +222,44 @@ sprite.inputs.kp1 = function () {
this.setanchor("ul"); this.setanchor("ul");
}; };
var changed_ts = [];
function bulkupdate()
{
for (var t of changed_ts) {
var sprite = t.sprite;
sprite_qt.remove(sprite);
sprite.rect = t.torect();
sprite.set_affine(t)
sprite_qt.insert(sprite)
}
// changed_ts.clear();
changed_ts = [];
}
Register.registries.prerender.register(bulkupdate)
function sprite_t_hook()
{
changed_ts.push(this);
}
component.sprite = function (obj) { component.sprite = function (obj) {
var sp = Object.create(sprite); var sp = Object.create(sprite);
var msp = os.make_sprite();
sp._sprite = msp;
msp.color = Color.white;
sp.gameobject = obj; sp.gameobject = obj;
sp.transform = os.make_transform(); sp.transform = os.make_transform();
sp.transform.parent = obj.transform; sp.transform.parent = obj.transform;
sp.transform.change_hook = function() { sp.transform.change_hook = sprite_t_hook;
sprite_qt.remove(msp);
msp.rect = sp.transform.torect(); var msp = os.make_sprite();
msp.set_affine(sp.transform); sp._sprite = msp;
sprite_qt.insert(msp); msp.color = Color.white;
sp.transform.sprite = msp; // or msp
/* sprite_qt.remove(sp)
sp.rect = sp.transform.torect()
sprite_qt.insert(sp)
*/
}
return sp; return sp;
}; };
component.makesprite = function(obj = world, data)
{
var sp = Object.create(sprite);
var msp = os.make_sprite();
sp._sprite = msp;
msp.color = Color.white;
sp.gameobject = obj;
sp.transform = os.make_transform();
sp.transform.parent = obj.transform;
sp.transform.change_hook = function() {
sprite_qt.remove(msp);
msp.rect = sp.transform.torect();
msp.set_affine(sp.transform);
sprite_qt.insert(msp);
/* sprite_qt.remove(sp)
sp.rect = sp.transform.torect()
sprite_qt.insert(sp)
*/
}
return sp;
}
sprite.shade = [1, 1, 1, 1];
return {component}; return {component};
Object.mixin(os.make_seg2d(), { Object.mixin(os.make_seg2d(), {

View File

@@ -56,11 +56,6 @@ var entity = {
this.objects = {}; this.objects = {};
}, },
sync() {
for (var c of Object.values(this.components)) c.sync?.();
for (var o of Object.values(this.objects)) o.sync();
},
delay(fn, seconds) { prosperon.add_timer(this, fn, seconds); }, delay(fn, seconds) { prosperon.add_timer(this, fn, seconds); },
cry(file) { cry(file) {
@@ -125,17 +120,17 @@ var entity = {
spawn(text, config, callback) { spawn(text, config, callback) {
var ent = class_use(text, config, entity, function (ent) { var ent = class_use(text, config, entity, function (ent) {
ent.transform = os.make_transform(); ent.transform = os.make_transform();
ent.guid = prosperon.guid(); // ent.guid = prosperon.guid();
ent.components = {}; ent.components = {};
ent.objects = {}; ent.objects = {};
ent.timers = []; ent.timers = [];
ent.ur = {}; // ent.ur = {};
ent.urname = text; // ent.urname = text;
}); });
/* /*
if (!text) if (!text)
ent.ur = emptyur; ent.ur = emptyur;
else if (text instanceof Object) {// assume it's an ur else if (typeof text === 'object') {// 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();
@@ -179,24 +174,22 @@ var entity = {
check_registers(ent); check_registers(ent);
if (ent.awake instanceof Function) ent.awake(); if (typeof ent.awake === 'function') ent.awake();
if (sim.playing()) { if (sim.playing()) {
ent._started = true; ent._started = true;
if (ent.start instanceof Function) ent.start(); if (typeof ent.start === 'function') ent.start();
} }
ent._ed = { /* ent._ed = {
selectable: true, selectable: true,
dirty: false, dirty: false,
inst: false, inst: false,
urdiff: {}, urdiff: {},
}; };
*/
// Object.hide(ent, "ur", "components", "objects", "timers", "guid", "master", "guid", "_ed"); // Object.hide(ent, "ur", "components", "objects", "timers", "guid", "master", "guid", "_ed");
ent.sync(); /* if (!Object.empty(ent.objects)) {
if (!Object.empty(ent.objects)) {
var o = ent.objects; var o = ent.objects;
delete ent.objects; delete ent.objects;
ent.objects = {}; ent.objects = {};
@@ -208,7 +201,7 @@ var entity = {
ent.rename_obj(n.toString(), i); ent.rename_obj(n.toString(), i);
} }
} }
*/
if (ent.tag) game.tag_add(ent.tag, ent); if (ent.tag) game.tag_add(ent.tag, ent);
if (callback) callback(ent); if (callback) callback(ent);
@@ -360,7 +353,7 @@ var entity = {
delete this.components; delete this.components;
this.clear(); this.clear();
if (this.stop instanceof Function) this.stop(); if (typeof this.stop === 'function') this.stop();
if (typeof this.garbage === "function") this.garbage(); if (typeof this.garbage === "function") this.garbage();
if (typeof this.then === "function") this.then(); if (typeof this.then === "function") this.then();
@@ -368,8 +361,8 @@ var entity = {
rmactor(this); rmactor(this);
for (var i in this) // for (var i in this)
if (this[i] instanceof Object || this[i] instanceof Function) delete this[i]; // delete this[i]
}, },
make_objs(objs) { make_objs(objs) {

View File

@@ -326,7 +326,8 @@ var Player = {
}, },
}; };
input.do_uncontrol = function (pawn) { input.do_uncontrol = function input_do_uncontrol(pawn) {
if (!pawn.inputs) return;
Player.players.forEach(function (p) { Player.players.forEach(function (p) {
p.pawns = p.pawns.filter(x => x !== pawn); p.pawns = p.pawns.filter(x => x !== pawn);
}); });

View File

@@ -1,15 +1,39 @@
globalThis.gamestate = {}; globalThis.gamestate = {};
global.check_registers = function check_registers(obj) { global.pull_registers = function(obj)
{
var reggies = [];
for (var reg in Register.registries) { for (var reg in Register.registries) {
if (!Register.registries[reg].register) return; if (!Register.registries[reg].register) return;
if (typeof obj[reg] === "function") { if (typeof obj[reg] === "function")
var fn = obj[reg].bind(obj); reggies.push(reg);
fn.layer = obj[reg].layer; }
var name = obj.ur ? obj.ur.name : obj.toString(); return reggies;
obj.timers.push(Register.registries[reg].register(fn, name)); }
if (!obj[reg].name) Object.defineProperty(obj[reg], 'name', {value:`${obj._file}_${reg}`});
} function register_obj(obj, reg)
{
var fn = obj[reg].bind(obj);
fn.layer = obj[reg].layer;
var name = obj.ur ? obj.ur.name : obj.toString();
obj.timers.push(Register.registries[reg].register(fn, name));
if (!obj[reg].name) Object.defineProperty(obj[reg], 'name', {value:`${obj._file}_${reg}`});
}
global.check_registers = function check_registers(obj) {
if (obj.__reggies) {
if (obj.__reggies.length == 0) return;
// fast path
for (var reg of obj.__reggies)
register_obj(obj,reg);
return;
}
for (var reg in Register.registries) {
if (!Register.registries[reg].register) return;
if (typeof obj[reg] === "function")
register_obj(obj,reg);
} }
/* for (var k in obj) { /* for (var k in obj) {
@@ -285,124 +309,12 @@ game.texture = function texture(path) {
throw new Error('need a string for game.texture') throw new Error('need a string for game.texture')
} }
var parts = path.split(':'); var parts = path.split(':');
path = Resources.find_image(parts[0]); var ipath = Resources.find_image(parts[0]);
game.texture.cache[path] ??= create_image(path); game.texture.cache[ipath] ??= create_image(ipath);
return game.texture.cache[path]; return game.texture.cache[ipath];
}
// Look for a cached version
var frame;
var anim_str;
if (parts.length > 1) {
// it's an animation
parts = parts[1].split('_'); // For a gif, it might be 'water.gif:3', but for an ase it might be 'water.ase:run_3', meaning the third frame of the 'run' animation
if (parts.length === 1)
frame = Number(parts[0]);
else {
anim_str = parts[0];
frame = Number(parts[1]);
}
} else
parts = undefined;
var ret;
if (ret = game.texture.cache[path]) {
if (ret.texture) return ret;
if (!parts) return ret;
return ret[anim_str].frames[frame];
}
if (!path) return game.texture("no_tex.gif");
if (!io.exists(path)) {
console.error(`Missing texture: ${path}`);
game.texture.cache[path] = game.texture("core/icons/no_tex.gif");
game.texture.time_cache[path] = io.mod(path);
return game.texture.cache[path];
}
// Cache not found; add to the spritesheet
var ext = path.ext();
if (ext === 'ase' || ext === 'aseprite') {
anim = os.make_aseprite(io.slurpbytes(path));
if (!anim) return;
if (anim.texture) {
// it was a single image
anim.texture.load_gpu();
game.texture.cache[path] = anim;
anim.size = calc_image_size(anim);
return anim;
}
// load all into gpu
for (var a in anim)
for (let frame of anim[a].frames) {
frame.texture.load_gpu();
frame.size = calc_image_size(img);
}
game.texture.cache[path] = anim;
ret = game.texture.cache[path];
if (!parts) return ret;
return ret[anim_str].frames[frame];
}
if (ext === 'gif') {
anim = os.make_gif(io.slurpbytes(path));
if (!anim) return;
if (anim.frames.length === 1) {
// in this case, it's just a single image
anim.texture = anim.frames[0].texture;
anim.rect = anim.frames[0].rect;
anim.frames = undefined;
anim.texture.load_gpu();
anim.size = calc_image_size(anim);
game.texture.cache[path] = anim;
return anim;
}
game.texture.cache[path] = anim;
anim.frames[0].size = calc_image_size(anim.frames[0]);
anim.frames[0].texture.load_gpu();
return anim;
}
var tex = os.make_texture(io.slurpbytes(path));
if (!tex) throw new Error(`Could not make texture from ${path}`);
tex.path = path;
var image;
var anim;
if (!anim) {
image = {
texture: tex,
rect:{x:0,y:0,width:1,height:1}
};
pack_into_sheet([image]);
} else if (Object.keys(anim).length === 1) {
image = Object.values(anim)[0];
image.frames.forEach(x => x.texture = tex);
pack_into_sheet(image.frames);
} else {
var allframes = [];
for (var a in anim)
allframes = allframes.concat(anim[a].frames);
for (var frame of allframes) frame.texture = tex;
pack_into_sheet(allframes);
image = anim;
}
game.texture.cache[path] = image;
game.texture.time_cache[path] = io.mod(path);
image.size = calc_image_size(image);
tex.load_gpu();
return game.texture.cache[path];
};
game.texture.cache = {}; game.texture.cache = {};
game.texture.time_cache = {}; game.texture.time_cache = {};
@@ -476,10 +388,10 @@ global.mixin("geometry");
Factory for creating registries. Register one with 'X.register', Factory for creating registries. Register one with 'X.register',
which returns a function that, when invoked, cancels the registry. which returns a function that, when invoked, cancels the registry.
*/ */
var Register = { globalThis.Register = {
registries: [], registries: [],
add_cb(name, e_event = false, flush = undefined) { add_cb(name) {
var n = {}; var n = {};
var fns = []; var fns = [];
@@ -514,23 +426,11 @@ var Register = {
}; };
}; };
if (!flush) { prosperon[name] = function (...args) {
prosperon[name] = function (...args) { // tracy.fiber_enter(vector.fib);
// tracy.fiber_enter(vector.fib); fns.forEach(fn => fn(...args));
fns.forEach(fn => fn(...args)); // tracy.fiber_leave(vector.fib);
// tracy.fiber_leave(vector.fib); };
};
} else
prosperon[name] = function (...args) {
var layer = undefined;
for (var fn of fns) {
if (layer !== fn.layer) {
flush();
layer = fn.layer;
}
fn();
}
};
Object.defineProperty(prosperon[name], 'name', {value:name}); Object.defineProperty(prosperon[name], 'name', {value:name});
prosperon[name].fns = fns; prosperon[name].fns = fns;
@@ -545,14 +445,17 @@ var Register = {
}, },
}; };
Register.add_cb("appupdate", true); Register.add_cb("appupdate");
Register.add_cb("update", true).doc = "Called once per frame."; Register.add_cb("update").doc = "Called once per frame.";
Register.add_cb("physupdate", true); Register.add_cb("physupdate");
Register.add_cb("gui", true); Register.add_cb("gui");
Register.add_cb("hud", true, render.flush); Register.add_cb("hud");
Register.add_cb("draw", true, render.flush); Register.add_cb("draw");
Register.add_cb("imgui", true, render.flush); Register.add_cb("imgui");
Register.add_cb("app", true, render.flush); Register.add_cb("app");
Register.add_cb("prerender");
global.mixin("components");
var Event = { var Event = {
events: {}, events: {},
@@ -609,7 +512,7 @@ prosperon.add_timer = function(obj, fn, seconds)
} }
global.mixin("spline"); global.mixin("spline");
global.mixin("components");
global.mixin("actor"); global.mixin("actor");
global.mixin("entity"); global.mixin("entity");
@@ -651,7 +554,6 @@ function make_spritesheet(paths, width, height)
} }
return { return {
Register,
sim, sim,
frame_t, frame_t,
physlag, physlag,

View File

@@ -675,6 +675,8 @@ prosperon.camera.screen2world = function(pos)
var swaps = []; var swaps = [];
function gpupresent() function gpupresent()
{ {
os.clean_transforms();
prosperon.prerender();
try{ try{
var cmds = render._main.acquire_cmd_buffer(); var cmds = render._main.acquire_cmd_buffer();
render_queue = sprites_to_queue().concat(render_queue); render_queue = sprites_to_queue().concat(render_queue);

View File

@@ -3,8 +3,6 @@ os.env.doc = "Return the value of the environment variable v.";
if (os.sys() === "windows") os.user = os.env("USERNAME"); if (os.sys() === "windows") os.user = os.env("USERNAME");
else os.user = os.env("USER"); else os.user = os.env("USER");
console.log(os.user)
/*var ignore; /*var ignore;
if (ignore = io.slurp('.prosperonignore')) { if (ignore = io.slurp('.prosperonignore')) {
ignore = ignore.split('\n'); ignore = ignore.split('\n');

View File

@@ -53,6 +53,10 @@ typedef struct rtree rtree;
static JSAtom width_atom; static JSAtom width_atom;
static JSAtom height_atom; static JSAtom height_atom;
static JSAtom l_atom;
static JSAtom r_atom;
static JSAtom t_atom;
static JSAtom b_atom;
static JSAtom x_atom; static JSAtom x_atom;
static JSAtom y_atom; static JSAtom y_atom;
static JSAtom anchor_x_atom; static JSAtom anchor_x_atom;
@@ -239,25 +243,15 @@ double js_getnum(JSContext *js, JSValue v, JSAtom prop)
return ret; return ret;
} }
#define JS_PULLPROPSTR(JS,VALUE,STR, TYPE) { \
JSValue __v = JS_GetPropertyStr(JS,VALUE,#STR); \
STR = js2##TYPE(JS, __v); \
JS_FreeValue(JS, __v); }
#define JS_GETPROPSTR(JS, VALUE, TARGET, STR, TYPE) {\
JSValue STR##__v = JS_GetPropertyStr(JS,VALUE,#STR); \
TARGET.STR = js2##TYPE(JS, STR##__v); \
JS_FreeValue(JS,STR##__v); }\
#define JS_GETPROP(JS, TARGET, VALUE, PROP, TYPE) {\ #define JS_GETPROP(JS, TARGET, VALUE, PROP, TYPE) {\
JSValue VALUE##__##PROP##__v = JS_GetPropertyStr(JS,VALUE,#PROP); \ JSValue __##PROP##__v = JS_GetPropertyStr(JS,VALUE,#PROP); \
TARGET = js2##TYPE(JS, VALUE##__##PROP##__v); \ TARGET = js2##TYPE(JS, __##PROP##__v); \
JS_FreeValue(JS,VALUE##__##PROP##__v); }\ JS_FreeValue(JS,__##PROP##__v); }\
#define JS_GETATOM(JS, TARGET, VALUE, ATOM, TYPE) {\ #define JS_GETATOM(JS, TARGET, VALUE, ATOM, TYPE) {\
JSValue VALUE##__##PROP##__v = JS_GetProperty(JS,VALUE,ATOM); \ JSValue __##PROP##__v = JS_GetProperty(JS,VALUE,ATOM); \
TARGET = js2##TYPE(JS, VALUE##__##PROP##__v); \ TARGET = js2##TYPE(JS, __##PROP##__v); \
JS_FreeValue(JS,VALUE##__##PROP##__v); }\ JS_FreeValue(JS,__##PROP##__v); }\
int JS_GETBOOL(JSContext *js, JSValue v, const char *prop) int JS_GETBOOL(JSContext *js, JSValue v, const char *prop)
{ {
@@ -1031,10 +1025,10 @@ typedef struct lrtb lrtb;
lrtb js2lrtb(JSContext *js, JSValue v) lrtb js2lrtb(JSContext *js, JSValue v)
{ {
lrtb ret = {0}; lrtb ret = {0};
JS_GETPROPSTR(js,v,ret,l,number) JS_GETATOM(js,ret.l,v,l_atom,number)
JS_GETPROPSTR(js,v,ret,b,number) JS_GETATOM(js,ret.r,v,r_atom,number)
JS_GETPROPSTR(js,v,ret,t,number) JS_GETATOM(js,ret.b,v,b_atom,number)
JS_GETPROPSTR(js,v,ret,r,number) JS_GETATOM(js,ret.t,v,t_atom,number)
return ret; return ret;
} }
@@ -1122,6 +1116,7 @@ static void js_transform_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark
transform *t = JS_GetOpaque(val, js_transform_id); transform *t = JS_GetOpaque(val, js_transform_id);
if (!t) return; if (!t) return;
// Mark the JSValue references stored in your struct // Mark the JSValue references stored in your struct
JS_MarkValue(rt, t->self, mark_func);
JS_MarkValue(rt, t->change_hook, mark_func); JS_MarkValue(rt, t->change_hook, mark_func);
JS_MarkValue(rt, t->jsparent, mark_func); JS_MarkValue(rt, t->jsparent, mark_func);
// Mark the array elements // Mark the array elements
@@ -1441,14 +1436,10 @@ JSValue vecarr2js(JSContext *js,HMM_Vec2 *points, int n) {
rect js2rect(JSContext *js,JSValue v) { rect js2rect(JSContext *js,JSValue v) {
if (JS_IsUndefined(v)) return (rect){0,0,1,1}; if (JS_IsUndefined(v)) return (rect){0,0,1,1};
rect rect; rect rect;
rect.w = js_getnum(js,v,width_atom); JS_GETATOM(js,rect.x,v,x_atom,number)
rect.h = js_getnum(js,v,height_atom); JS_GETATOM(js,rect.y,v,y_atom,number)
JSValue xv = JS_GetProperty(js,v,x_atom); JS_GETATOM(js,rect.w,v,width_atom,number)
rect.x = js2number(js,xv); JS_GETATOM(js,rect.h,v,height_atom,number)
JS_FreeValue(js,xv);
JSValue yv = JS_GetProperty(js,v,y_atom);
rect.y = js2number(js,yv);
JS_FreeValue(js,yv);
float anchor_x = js_getnum(js,v, anchor_x_atom); float anchor_x = js_getnum(js,v, anchor_x_atom);
float anchor_y = js_getnum(js,v, anchor_y_atom); float anchor_y = js_getnum(js,v, anchor_y_atom);
@@ -4131,6 +4122,8 @@ JSC_CCALL(gpu_make_sprite_queue,
JS_GETATOM(js,sp.layer,sub,layer_atom,number) JS_GETATOM(js,sp.layer,sub,layer_atom,number)
JS_GETATOM(js,sp.uv,sub,src_atom,rect) JS_GETATOM(js,sp.uv,sub,src_atom,rect)
sp.image = JS_GetProperty(js,sub,image_atom); sp.image = JS_GetProperty(js,sub,image_atom);
JS_GETATOM(js,sp.tex,sp.image,texture_atom,SDL_GPUTexture)
arrput(sprites,sp); arrput(sprites,sp);
} }
JS_FreeValue(js, sub); JS_FreeValue(js, sub);
@@ -4899,8 +4892,8 @@ JSC_CCALL(gpu_slice9,
JSC_CCALL(gpu_tile, JSC_CCALL(gpu_tile,
HMM_Vec2 size; HMM_Vec2 size;
JSValue jstex = argv[0]; JSValue jstex = argv[0];
JS_GETPROP(js,size.x,jstex,width,number) JS_GETATOM(js,size.x,jstex,width_atom,number)
JS_GETPROP(js, size.y, jstex, height, number) JS_GETATOM(js, size.y, jstex, height_atom, number)
rect src_pixels = js2rect(js, argv[1]); // 'src' as pixel dimensions rect src_pixels = js2rect(js, argv[1]); // 'src' as pixel dimensions
rect dst = js2rect(js, argv[2]); // 'dst' as screen coords rect dst = js2rect(js, argv[2]); // 'dst' as screen coords
@@ -5095,7 +5088,7 @@ JSC_CCALL(cmd_render_pass,
JSValue depthval = JS_GetPropertyStr(js, passObj, "depth_stencil"); JSValue depthval = JS_GetPropertyStr(js, passObj, "depth_stencil");
if (!JS_IsUndefined(depthval)) { if (!JS_IsUndefined(depthval)) {
has_depth = 1; has_depth = 1;
JS_GETPROPSTR(js, depthval, depthtar, texture, SDL_GPUTexture) JS_GETPROP(js, depthtar.texture, depthval, texture, SDL_GPUTexture)
JS_GETPROP(js, depthtar.load_op, depthval, load, SDL_GPULoadOp) JS_GETPROP(js, depthtar.load_op, depthval, load, SDL_GPULoadOp)
JS_GETPROP(js, depthtar.store_op, depthval, store, SDL_GPUStoreOp) JS_GETPROP(js, depthtar.store_op, depthval, store, SDL_GPUStoreOp)
JS_GETPROP(js, depthtar.stencil_load_op, depthval, stencil_load, SDL_GPULoadOp) JS_GETPROP(js, depthtar.stencil_load_op, depthval, stencil_load, SDL_GPULoadOp)
@@ -6582,7 +6575,11 @@ JSC_CCALL(os_make_font,
JS_SetPropertyStr(js, ret, "surface", SDL_Surface2js(js,f->surface)); JS_SetPropertyStr(js, ret, "surface", SDL_Surface2js(js,f->surface));
) )
JSC_CCALL(os_make_transform, return transform2js(js,make_transform())) JSC_CCALL(os_make_transform,
transform *t = make_transform();
ret = transform2js(js,t);
t->self = JS_DupValue(js,ret);
)
JSC_CCALL(os_make_sprite, return sprite2js(js,make_sprite())) JSC_CCALL(os_make_sprite, return sprite2js(js,make_sprite()))
JSC_SCALL(os_system, return number2js(js,system(str)); ) JSC_SCALL(os_system, return number2js(js,system(str)); )
@@ -7248,9 +7245,14 @@ JSC_CCALL(os_on,
on_exception = JS_DupValue(js,argv[1]); on_exception = JS_DupValue(js,argv[1]);
) )
JSC_CCALL(os_clean_transforms,
clean_all();
)
static const JSCFunctionListEntry js_os_funcs[] = { static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, turbulence, 4), MIST_FUNC_DEF(os, turbulence, 4),
MIST_FUNC_DEF(os, model_buffer, 1), MIST_FUNC_DEF(os, model_buffer, 1),
MIST_FUNC_DEF(os, clean_transforms, 0),
MIST_FUNC_DEF(os, fbm, 4), MIST_FUNC_DEF(os, fbm, 4),
MIST_FUNC_DEF(os, ridge, 5), MIST_FUNC_DEF(os, ridge, 5),
MIST_FUNC_DEF(os, perlin, 3), MIST_FUNC_DEF(os, perlin, 3),
@@ -7365,8 +7367,10 @@ JSC_CCALL(rtree_insert,
max[1] = r.y+r.h; max[1] = r.y+r.h;
JSValue *ins = malloc(sizeof(*ins)); JSValue *ins = malloc(sizeof(*ins));
*ins = JS_DupValue(js,v); *ins = JS_DupValue(js,v);
if (!rtree_insert(tree, min, max, ins)) if (!rtree_insert(tree, min, max, ins)) {
JS_FreeValue(js,*ins);
return JS_ThrowOutOfMemory(js); return JS_ThrowOutOfMemory(js);
}
) )
int rtree_cmp(const JSValue *a, const JSValue *b, JSContext *js) int rtree_cmp(const JSValue *a, const JSValue *b, JSContext *js)
@@ -7708,6 +7712,11 @@ void ffi_load(JSContext *js) {
parent_atom = JS_NewAtom(js,"parent"); parent_atom = JS_NewAtom(js,"parent");
rect_atom = JS_NewAtom(js,"rect"); rect_atom = JS_NewAtom(js,"rect");
l_atom = JS_NewAtom(js,"l");
r_atom = JS_NewAtom(js,"r");
b_atom = JS_NewAtom(js,"b");
t_atom = JS_NewAtom(js,"t");
fill_event_atoms(js); fill_event_atoms(js);
global_js = js; global_js = js;

View File

@@ -85,6 +85,7 @@ JSValue js_##ID##_get_##ENTRY (JSContext *js, JSValue self) { \
static JSClassID js_##TYPE##_id;\ static JSClassID js_##TYPE##_id;\
static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\ static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\
TYPE *n = JS_GetOpaque(val, js_##TYPE##_id);\ TYPE *n = JS_GetOpaque(val, js_##TYPE##_id);\
TracyCFreeN(n, #TYPE); \
TYPE##_free(rt,n);}\ TYPE##_free(rt,n);}\
static JSClassDef js_##TYPE##_class = {\ static JSClassDef js_##TYPE##_class = {\
#TYPE,\ #TYPE,\
@@ -98,12 +99,14 @@ JSValue TYPE##2js(JSContext *js, TYPE *n) { \
JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\ JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\
JS_SetOpaque(j,n);\ JS_SetOpaque(j,n);\
__VA_ARGS__ \ __VA_ARGS__ \
TracyCAllocN(n, 1, #TYPE); \
return j; }\ return j; }\
\ \
#define QJSCLASSMARK(TYPE, ...)\ #define QJSCLASSMARK(TYPE, ...)\
static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\ static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\
TYPE *n = JS_GetOpaque(val, js_##TYPE##_id);\ TYPE *n = JS_GetOpaque(val, js_##TYPE##_id);\
TracyCFreeN(n, #TYPE); \
TYPE##_free(rt,n);}\ TYPE##_free(rt,n);}\
static JSClassDef js_##TYPE##_class = {\ static JSClassDef js_##TYPE##_class = {\
#TYPE,\ #TYPE,\
@@ -118,6 +121,7 @@ JSValue TYPE##2js(JSContext *js, TYPE *n) { \
JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\ JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\
JS_SetOpaque(j,n);\ JS_SetOpaque(j,n);\
__VA_ARGS__ \ __VA_ARGS__ \
TracyCAllocN(n, 1, #TYPE); \
return j; }\ return j; }\
\ \

View File

@@ -2,9 +2,10 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include "script.h" #include "script.h"
#include "stb_ds.h" #include "stb_ds.h"
static transform **dirties;
static transform model = { static transform model = {
.pos = {0,0,0}, .pos = {0,0,0},
.scale = {1,1,1}, .scale = {1,1,1},
@@ -25,6 +26,7 @@ transform *make_transform()
} }
void transform_free(JSRuntime *rt, transform *t) { void transform_free(JSRuntime *rt, transform *t) {
JS_FreeValueRT(rt,t->self);
JS_FreeValueRT(rt,t->change_hook); JS_FreeValueRT(rt,t->change_hook);
JS_FreeValueRT(rt,t->jsparent); JS_FreeValueRT(rt,t->jsparent);
for (int i = 0; i < arrlen(t->jschildren); i++) for (int i = 0; i < arrlen(t->jschildren); i++)
@@ -33,6 +35,10 @@ void transform_free(JSRuntime *rt, transform *t) {
arrfree(t->jschildren); arrfree(t->jschildren);
arrfree(t->children); arrfree(t->children);
free(t); free(t);
for (int i = arrlen(dirties)-1; i >= 0; i--) {
if (dirties[i] == t) arrdelswap(dirties, i);
}
} }
void transform_clean(transform *t) void transform_clean(transform *t)
@@ -51,11 +57,17 @@ void transform_clean(transform *t)
} }
if (!JS_IsUndefined(t->change_hook)) { if (!JS_IsUndefined(t->change_hook)) {
JSValue ret = JS_Call(global_js, t->change_hook, JS_UNDEFINED, 0, NULL); JSValue ret = JS_Call(global_js, t->change_hook, JS_DupValue(global_js,t->self), 0, NULL);
JS_FreeValue(global_js,ret); JS_FreeValue(global_js,ret);
} }
} }
void clean_all()
{
for (int i = 0; i < arrlen(dirties); i++)
transform_clean(dirties[i]);
}
void transform_move(transform *t, HMM_Vec3 v) void transform_move(transform *t, HMM_Vec3 v)
{ {
t->pos = HMM_AddV3(t->pos, v); t->pos = HMM_AddV3(t->pos, v);
@@ -124,7 +136,7 @@ rect transform2rect(transform *t)
void transform_apply(transform *t) void transform_apply(transform *t)
{ {
t->dirty = 1; t->dirty = 1;
transform_clean(t); arrput(dirties,t);
} }
HMM_Quat angle2rotation(float angle) HMM_Quat angle2rotation(float angle)

View File

@@ -12,6 +12,7 @@ typedef struct transform {
HMM_Mat4 cache; HMM_Mat4 cache;
HMM_Mat4 gcache; HMM_Mat4 gcache;
int dirty; int dirty;
JSValue self;
struct transform *parent; struct transform *parent;
JSValue jsparent; JSValue jsparent;
struct transform **children; struct transform **children;
@@ -19,6 +20,8 @@ typedef struct transform {
JSValue change_hook; JSValue change_hook;
} transform; } transform;
void clean_all();
transform *make_transform(); transform *make_transform();
void transform_free(JSRuntime *rt,transform *t); void transform_free(JSRuntime *rt,transform *t);