rework hot reload
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
var actor = {};
|
||||
|
||||
var actor_urs = {};
|
||||
var script_times = {};
|
||||
|
||||
var actor_spawns = {};
|
||||
|
||||
@@ -17,7 +16,6 @@ globalThis.class_use = function (script, config, base, callback) {
|
||||
if (!actor_urs[file]) {
|
||||
var newur = Object.create(base);
|
||||
actor_urs[file] = newur;
|
||||
script_times[file] = io.mod(file);
|
||||
actor_spawns[file] = [];
|
||||
}
|
||||
|
||||
@@ -61,28 +59,23 @@ actor.__stats = function () {
|
||||
return stats;
|
||||
};
|
||||
|
||||
actor.hotreload = function () {
|
||||
for (var i in script_times) {
|
||||
if (io.mod(i) > script_times[i]) {
|
||||
script_times[i] = io.mod(i);
|
||||
var script = Resources.replstrs(i);
|
||||
script = `(function() {
|
||||
var self = this;
|
||||
var $ = this.__proto__;
|
||||
${script};
|
||||
})`;
|
||||
var fn = os.eval(i, script);
|
||||
actor.hotreload = function (file) {
|
||||
var script = Resources.replstrs(file);
|
||||
script = `(function() {
|
||||
var self = this;
|
||||
var $ = this.__proto__;
|
||||
${script};
|
||||
})`;
|
||||
var fn = os.eval(file, script);
|
||||
|
||||
for (var obj of actor_spawns[i]) {
|
||||
var a = obj;
|
||||
a.timers.forEachRight(t=>t());
|
||||
a.timers = [];
|
||||
var save = json.decode(json.encode(a));
|
||||
fn.call(a);
|
||||
Object.merge(a, save);
|
||||
check_registers(a);
|
||||
}
|
||||
}
|
||||
for (var obj of actor_spawns[file]) {
|
||||
var a = obj;
|
||||
a.timers.forEachRight(t=>t());
|
||||
a.timers = [];
|
||||
var save = json.decode(json.encode(a));
|
||||
fn.call(a);
|
||||
Object.merge(a, save);
|
||||
check_registers(a);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ Resources.rm_fn = function rm_fn(fn, text) {
|
||||
};
|
||||
Resources.rm_fn.doc = "Remove calls to a given function from a given text script.";
|
||||
|
||||
// Normalizes paths for use in prosperon
|
||||
Resources.replpath = function replpath(str, path) {
|
||||
if (!str) return str;
|
||||
if (str[0] === "/") return str.rm(0);
|
||||
@@ -70,6 +71,7 @@ Resources.replpath = function replpath(str, path) {
|
||||
return str;
|
||||
};
|
||||
|
||||
// Given a script path, loads it, and replaces certain function calls to conform to environment
|
||||
Resources.replstrs = function replstrs(path) {
|
||||
if (!path) return;
|
||||
var script = io.slurp(path);
|
||||
@@ -160,7 +162,6 @@ function find_ext(file, ext, root = "") {
|
||||
}
|
||||
|
||||
var all_files = io.glob(`**/${file}.*`);
|
||||
all_files = all_files.filter(x => !x.startsWith('.'));
|
||||
var find = undefined;
|
||||
for (var e of ext) {
|
||||
var finds = all_files.filter(x => x.ext() === e);
|
||||
@@ -328,9 +329,9 @@ io.exists = function(path)
|
||||
var tmpslurp = io.slurp;
|
||||
io.slurp = function(path)
|
||||
{
|
||||
path = Resources.replpath(path);
|
||||
var ret = tmpslurp(path, true) || core_db.slurp(path, true);
|
||||
if (!ret) console.info(`could not slurp ${path}`);
|
||||
var findpath = Resources.replpath(path);
|
||||
var ret = tmpslurp(findpath, true) || core_db.slurp(findpath, true);
|
||||
if (!ret) console.info(`could not slurp path ${path} as ${findpath}`)
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -410,13 +411,4 @@ bare_use("preconfig.js");
|
||||
if (!profile.enabled) use = stripped_use;
|
||||
|
||||
Object.assign(globalThis, use("prosperon.js"));
|
||||
|
||||
/*app.interval(_ => {
|
||||
profile.report("hotreload");
|
||||
actor.hotreload();
|
||||
render.hotreload();
|
||||
game.tex_hotreload();
|
||||
repl.hotreload();
|
||||
profile.endreport("hotreload");
|
||||
}, 1);
|
||||
*/
|
||||
|
||||
|
||||
@@ -178,21 +178,42 @@ game.doc.pause = "Pause game simulation.";
|
||||
game.doc.play = "Resume or start game simulation.";
|
||||
game.doc.camera = "Current camera.";
|
||||
|
||||
game.tex_hotreload = function () {
|
||||
return;
|
||||
for (var path in game.texture.cache) {
|
||||
if (io.mod(path) > game.texture.time_cache[path]) {
|
||||
var tex = game.texture.cache[path];
|
||||
game.texture.time_cache[path] = io.mod(path);
|
||||
SpriteAnim.hotreload(path);
|
||||
os.texture_swap(path, game.texture.cache[path]);
|
||||
for (var sprite of Object.values(allsprites)) {
|
||||
if (sprite.texture == tex) {
|
||||
sprite.tex_sync();
|
||||
}
|
||||
game.tex_hotreload = function (file) {
|
||||
if (!(file in game.texture.cache)) return;
|
||||
var data = io.slurpbytes(file);
|
||||
var tex;
|
||||
if (file.endsWith('.gif')) {
|
||||
var anim = os.make_gif(data);
|
||||
if (anim.frames.length !== 1) return;
|
||||
console.info(json.encode(anim));
|
||||
tex = anim.frames[0].texture;
|
||||
} else if (file.endsWith('.ase') || file.endsWith('.aseprite')) {
|
||||
var anim = os.make_aseprite(data);
|
||||
if (anim.texture) // single picture
|
||||
tex = anim.texture;
|
||||
else {
|
||||
var oldanim = game.texture.cache[file];
|
||||
// load all into gpu
|
||||
for (var a in anim) {
|
||||
oldanim[a] = anim[a];
|
||||
for (let frame of anim[a].frames)
|
||||
frame.texture.load_gpu();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else
|
||||
tex = os.make_texture(data);
|
||||
|
||||
var img = game.texture.cache[file];
|
||||
tex.load_gpu();
|
||||
console.info(`replacing ${json.encode(img)}`)
|
||||
img.texture = tex;
|
||||
img.rect = {
|
||||
x:0,
|
||||
y:0,
|
||||
width:1,
|
||||
height:1
|
||||
};
|
||||
};
|
||||
|
||||
var image = {};
|
||||
@@ -303,6 +324,7 @@ game.is_image = function(obj)
|
||||
|
||||
// Any request to it returns an image, which is a texture and rect. But they can
|
||||
game.texture = function (path) {
|
||||
if (typeof path !== 'string') throw new Error('need a string for game.texture')
|
||||
var parts = path.split(':');
|
||||
path = Resources.find_image(parts[0]);
|
||||
|
||||
@@ -343,8 +365,16 @@ game.texture = function (path) {
|
||||
var ext = path.ext();
|
||||
|
||||
if (ext === 'ase' || ext === 'aseprite') {
|
||||
anim = os.make_aseprite(path);
|
||||
console.info(`making out of an aseprite for ${path}`);
|
||||
anim = os.make_aseprite(io.slurpbytes(path));
|
||||
console.info(`raw anim is ${json.encode(anim)}`)
|
||||
if (!anim) return;
|
||||
if (anim.texture) {
|
||||
// it was a single image
|
||||
anim.texture.load_gpu();
|
||||
game.texture.cache[path] = anim;
|
||||
return anim;
|
||||
}
|
||||
// load all into gpu
|
||||
for (var a in anim)
|
||||
for (let frame of anim[a].frames)
|
||||
@@ -357,7 +387,7 @@ game.texture = function (path) {
|
||||
}
|
||||
|
||||
if (ext === 'gif') {
|
||||
anim = os.make_gif(io.slurp(path));
|
||||
anim = os.make_gif(io.slurpbytes(path));
|
||||
if (!anim) return;
|
||||
if (anim.frames.length === 1) {
|
||||
// in this case, it's just a single image
|
||||
|
||||
@@ -1433,17 +1433,11 @@ try{
|
||||
profile.report("imgui");
|
||||
if (debug.show) imgui_fn();
|
||||
profile.endreport("imgui");
|
||||
|
||||
// render.end_pass();
|
||||
|
||||
// render.commit();
|
||||
// profile.report_frame(profile.secs(profile.now()) - frame_t);
|
||||
|
||||
// endframe();
|
||||
} catch(e) {
|
||||
throw e;
|
||||
} finally {
|
||||
render.end_pass();
|
||||
profile.report_frame(profile.secs(profile.now()) - frame_t);
|
||||
render.commit();
|
||||
endframe();
|
||||
}
|
||||
@@ -1455,6 +1449,12 @@ function dmon_cb(e)
|
||||
{
|
||||
if (e.file.startsWith('.')) return;
|
||||
console.info(json.encode(e))
|
||||
if (e.file.endsWith('.js'))
|
||||
actor.hotreload(e.file);
|
||||
else if (Resources.is_image(e.file))
|
||||
game.tex_hotreload(e.file);
|
||||
else if (e.file.endsWith('.cg')) // shader
|
||||
render.hotreload(e.file);
|
||||
}
|
||||
|
||||
prosperon.process = function process() {
|
||||
|
||||
@@ -235,7 +235,7 @@ Cmdline.register_order(
|
||||
else global.app = actor.spawn("nogame.js");
|
||||
|
||||
var icon = game.texture(project.icon);
|
||||
if (icon) window.set_icon(game.texture(icon.texture));
|
||||
if (icon) window.set_icon(icon.texture);
|
||||
game.camera = world.spawn("camera2d");
|
||||
});
|
||||
},
|
||||
|
||||
@@ -2393,21 +2393,20 @@ JSC_CCALL(os_obj_size,
|
||||
JSC_CCALL(os_make_texture,
|
||||
size_t len;
|
||||
void *raw = JS_GetArrayBuffer(js, &len, argv[0]);
|
||||
if (!raw) {
|
||||
JS_ThrowReferenceError(js, "could not load texture with array buffer");
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
ret = texture2js(texture_fromdata(raw, len));
|
||||
if (!raw) return JS_ThrowReferenceError(js, "could not load texture with array buffer");
|
||||
|
||||
texture *tex = texture_fromdata(raw, len);
|
||||
if (!tex) return JS_ThrowReferenceError(js, "unable to make texture from the given array buffer");
|
||||
|
||||
ret = texture2js(tex);
|
||||
JS_SetPropertyStr(js, ret, "path", JS_DupValue(js,argv[0]));
|
||||
)
|
||||
|
||||
JSC_CCALL(os_make_gif,
|
||||
size_t rawlen;
|
||||
void *raw = JS_GetArrayBuffer(js, &rawlen, argv[0]);
|
||||
if (!raw) {
|
||||
JS_ThrowReferenceError(js, "could not load gif from supplied array buffer");
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
if (!raw) return JS_ThrowReferenceError(js, "could not load gif from supplied array buffer");
|
||||
|
||||
int n;
|
||||
texture *tex = calloc(1,sizeof(*tex));
|
||||
int frames;
|
||||
@@ -2442,20 +2441,43 @@ JSC_CCALL(os_make_gif,
|
||||
ret = gif;
|
||||
)
|
||||
|
||||
JSValue aseframe2js(JSContext *js, ase_frame_t aframe)
|
||||
{
|
||||
JSValue frame = JS_NewObject(js);
|
||||
texture *tex = calloc(1,sizeof(*tex));
|
||||
tex->width = aframe.ase->w;
|
||||
tex->height = aframe.ase->h;
|
||||
tex->data = malloc(tex->width*tex->height*4);
|
||||
memcpy(tex->data, aframe.pixels, tex->width*tex->height*4);
|
||||
js_setpropstr(frame, "texture", texture2js(tex));
|
||||
js_setpropstr(frame, "rect", rect2js((rect){.x=0,.y=0,.w=1,.h=1}));
|
||||
js_setpropstr(frame, "time", number2js((float)aframe.duration_milliseconds/1000.0));
|
||||
return frame;
|
||||
}
|
||||
|
||||
JSC_CCALL(os_make_aseprite,
|
||||
size_t rawlen;
|
||||
void *raw = JS_GetArrayBuffer(js,&rawlen,argv[0]);
|
||||
if (!raw) return JS_UNDEFINED;
|
||||
if (!raw) return JS_ThrowReferenceError(js, "could not load aseprite from supplied array buffer");
|
||||
|
||||
ase_t *ase = cute_aseprite_load_from_memory(raw, rawlen, NULL);
|
||||
|
||||
JSValue obj = JS_NewObject(js);
|
||||
|
||||
int w = ase->w;
|
||||
int h = ase->h;
|
||||
|
||||
int pixels = w*h;
|
||||
|
||||
if (ase->tag_count == 0) {
|
||||
// we're dealing with a single frame image, or single animation
|
||||
if (ase->frame_count == 1) {
|
||||
JSValue obj = aseframe2js(js,ase->frames[0]);
|
||||
cute_aseprite_free(ase);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
JSValue obj = JS_NewObject(js);
|
||||
|
||||
for (int t = 0; t < ase->tag_count; t++) {
|
||||
ase_tag_t tag = ase->tags[t];
|
||||
JSValue anim = JS_NewObject(js);
|
||||
@@ -2475,17 +2497,7 @@ JSC_CCALL(os_make_aseprite,
|
||||
int _frame = 0;
|
||||
JSValue frames = JS_NewArray(js);
|
||||
for (int f = tag.from_frame; f <= tag.to_frame; f++) {
|
||||
ase_frame_t aframe = ase->frames[f];
|
||||
JSValue frame = JS_NewObject(js);
|
||||
|
||||
texture *tex = calloc(1,sizeof(*tex));
|
||||
tex->width = w;
|
||||
tex->height = h;
|
||||
tex->data = malloc(w*h*4);
|
||||
memcpy(tex->data, aframe.pixels, w*h*4);
|
||||
js_setpropstr(frame, "texture", texture2js(tex));
|
||||
js_setpropstr(frame, "rect", rect2js((rect){.x=0,.y=0,.w=1,.h=1}));
|
||||
js_setpropstr(frame, "time", number2js((float)aframe.duration_milliseconds/1000.0));
|
||||
JSValue frame = aseframe2js(js,ase->frames[f]);
|
||||
js_setprop_num(frames, _frame, frame);
|
||||
_frame++;
|
||||
}
|
||||
@@ -2498,13 +2510,6 @@ JSC_CCALL(os_make_aseprite,
|
||||
cute_aseprite_free(ase);
|
||||
)
|
||||
|
||||
JSC_SCALL(os_texture_swap,
|
||||
texture *old = js2texture(argv[1]);
|
||||
texture *tex = texture_from_file(str);
|
||||
JS_SetOpaque(argv[1], tex);
|
||||
texture_free(old);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_make_tex_data,
|
||||
ret = texture2js(texture_empty(js2number(argv[0]), js2number(argv[1])))
|
||||
)
|
||||
@@ -2788,7 +2793,6 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
MIST_FUNC_DEF(os, make_texture, 1),
|
||||
MIST_FUNC_DEF(os, make_gif, 1),
|
||||
MIST_FUNC_DEF(os, make_aseprite, 1),
|
||||
MIST_FUNC_DEF(os, texture_swap, 2),
|
||||
MIST_FUNC_DEF(os, make_tex_data, 3),
|
||||
MIST_FUNC_DEF(os, make_font, 2),
|
||||
MIST_FUNC_DEF(os, make_transform, 0),
|
||||
|
||||
@@ -69,7 +69,19 @@ static uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filen
|
||||
|
||||
void script_startup() {
|
||||
rt = JS_NewRuntime();
|
||||
js = JS_NewContext(rt);
|
||||
js = JS_NewContextRaw(rt);
|
||||
JS_AddIntrinsicBaseObjects(js);
|
||||
JS_AddIntrinsicEval(js);
|
||||
JS_AddIntrinsicRegExp(js);
|
||||
JS_AddIntrinsicJSON(js);
|
||||
JS_AddIntrinsicMapSet(js);
|
||||
JS_AddIntrinsicTypedArrays(js);
|
||||
JS_AddIntrinsicPromise(js);
|
||||
JS_AddIntrinsicProxy(js);
|
||||
JS_AddIntrinsicBigInt(js);
|
||||
JS_AddIntrinsicBigFloat(js);
|
||||
JS_AddIntrinsicBigDecimal(js);
|
||||
JS_AddIntrinsicOperators(js);
|
||||
|
||||
ffi_load();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user