From 188fe7526c2c7729eb41b3c62fda4f3cd5646859 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Thu, 14 Mar 2024 14:10:06 -0500 Subject: [PATCH] Move console and time to c; consoleout and colors --- scripts/base.js | 30 +++--- scripts/debug.js | 98 ++++++------------- scripts/engine.js | 66 +++++++++++-- scripts/std.js | 79 --------------- scripts/test.js | 33 ++++--- source/engine/2dphysics.c | 2 +- source/engine/debug/log.c | 19 +++- source/engine/debug/log.h | 2 + source/engine/jsffi.c | 196 +++++++++++++++++++------------------- source/engine/render.c | 4 +- source/engine/yugine.c | 8 +- source/engine/yugine.h | 3 +- 12 files changed, 247 insertions(+), 293 deletions(-) diff --git a/scripts/base.js b/scripts/base.js index e201401..90c5f63 100644 --- a/scripts/base.js +++ b/scripts/base.js @@ -62,12 +62,12 @@ convert.buf2hex = function(buffer) { // buffer is an ArrayBuffer } /* Time values are always expressed in terms of real earth-seconds */ -var time = { - get hour2minute() { return this.hour/this.minute; }, - get day2hour() { return this.day/this.hour; }, - get minute2second() { return this.minute/this.second; }, - get week2day() { return this.week/this.day; }, -}; +Object.assign(time, { + hour2minute() { return this.hour/this.minute; }, + day2hour() { return this.day/this.hour; }, + minute2second() { return this.minute/this.second; }, + week2day() { return this.week/this.day; }, +}); time.strparse = { yyyy: "year", @@ -105,8 +105,6 @@ time.doc = { number: "Return the number representation of a given time.", text: "Return a text formatted time." }; - - time.second = 1; time.minute = 60; @@ -117,9 +115,6 @@ time.weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday time.monthstr = ["January", "February", "March", 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; time.epoch = 1970; -time.now = function() { return cmd(210);} -time.computer_zone = function() { return cmd(211)/this.hour; } -time.computer_dst = function() { return cmd(212); } time.isleap = function(year) { return this.yearsize(year) === 366; } time.isleap.doc = "Return true if the given year is a leapyear."; @@ -129,6 +124,13 @@ time.yearsize = function(y) { return 365; } +time.timecode = function(t, fps = 24) +{ + var s = Math.trunc(t); + t -= s; + return `${s}:${Math.trunc(fps*s)}`; +} + time.monthdays = [31,28,31,30,31,30,31,31,30,31,30,31]; time.zones = {}; time.zones['-12'] = 'IDLW'; @@ -215,9 +217,9 @@ time.number = function(rec) c += this.day*this.yearsize(i); c += (this.yearsize(year)-yday-1)*this.day; - c += (this.day2hour-hour-1)*this.hour; - c += (this.hour2minute-minute-1)*this.minute; - c += (this.minute2second-second); + c += (this.day2hour()-hour-1)*this.hour; + c += (this.hour2minute()-minute-1)*this.minute; + c += (this.minute2second()-second); c += zone*this.hour; c *= -1; return c; diff --git a/scripts/debug.js b/scripts/debug.js index dc5196e..1e51f4a 100644 --- a/scripts/debug.js +++ b/scripts/debug.js @@ -63,7 +63,7 @@ var Debug = { if (Debug.Options.gif.rec) { GUI.text("REC", [0,40], 1); - GUI.text(Time.seconds_to_timecode(Time.time - Debug.Options.gif.start_time, Debug.Options.gif.fps), [0,30], 1); + GUI.text(time.timecode(time.timenow() - Debug.Options.gif.start_time, Debug.Options.gif.fps), [0,30], 1); } GUI.text(Game.playing() ? "PLAYING" @@ -98,54 +98,52 @@ var Gizmos = { }, }; -Object.assign(performance, { - tick_now() { return cmd(127); }, - ns(ticks) { return cmd(128, ticks); }, - us(ticks) { return cmd(129, ticks); }, - ms(ticks) { return cmd(130, ticks); }, - best_t(ns) { - var e = ns; +Object.assign(profile, { + best_t(t) { var qq = 'ns'; - if (e > 1000) { - e /= 1000; + if (t > 1000) { + t /= 1000; qq = 'us'; - if (e > 1000) { - e /= 1000; + if (t > 1000) { + t /= 1000; qq = 'ms'; } } - return { - time: e, - unit: qq - }; + return `${t.toPrecision(4)} ${qq}`; }, cpu(fn, times, q) { times ??= 1; q ??= "unnamed"; - var start = performance.tick_now(); + var start = profile.now(); for (var i = 0; i < times; i++) fn(); - var elapsed = performance.tick_now() - start; - var avgt = performance.best_t(elapsed/times); - var totalt = performance.best_t(elapsed); + var elapsed = profile.now() - start; + var avgt = profile.best_t(elapsed/times); + var totalt = profile.best_t(elapsed); - say(`performance [${q}]: ${avgt.time.toFixed(3)} ${avgt.unit} average [${totalt.time.toFixed(3)} ${totalt.unit} for ${times} loops]`); + say(`profile [${q}]: ${profile.best_t(avgt)} average [${profile.best_t(totalt)} for ${times} loops]`); }, - get fps() { return sys_cmd(8); }, + time(fn) { + var start = profile.now(); + fn(); + return profile.lap(start); + }, + + lap(t) { + return profile.best_t(profile.now()-t); + }, measure(fn, str) { str ??= 'unnamed'; - var start = performance.tick_now(); + var start = profile.now(); fn(); - var elapsed = performance.tick_now()-start; - elapsed = performance.best_t(elapsed); - say(`performance [${str}]: ${elapsed.time.toFixed(3)} ${elapsed.unit}`); + say(`profile [${str}]: ${profile.lap(start)}`); }, }); -performance.now = performance.tick_now; + performance.test = { barecall() { performance(0); }, @@ -160,7 +158,7 @@ performance.test = { performance.test.call_fn_n.doc = "Calls fn1 n times, and then fn2."; -performance.cpu.doc = `Output the time it takes to do a given function n number of times. Provide 'q' as "ns", "us", or "ms" to output the time taken in the requested resolution.`; +//performance.cpu.doc = `Output the time it takes to do a given function n number of times. Provide 'q' as "ns", "us", or "ms" to output the time taken in the requested resolution.`; /* These controls are available during editing, and during play of debug builds */ Debug.inputs = {}; @@ -200,7 +198,7 @@ Debug.Options.gif = { cmd(131, w, h, this.cpf, this.depth); this.rec = true; this.fps = (1/this.cpf)*100; - this.start_time = Time.time; + this.start_time = time.now(); timer.oneshot(this.stop.bind(this), this.secs, this, true); }, @@ -233,46 +231,6 @@ Debug.inputs['M-2'] = render.wireframe; Debug.inputs['C-M-f'] = function() {}; Debug.inputs['C-M-f'].doc = "Enter camera fly mode."; -var Time = { - set timescale(x) { cmd(3, x); }, - get timescale() { return cmd(121); }, - set updateMS(x) { cmd(6, x); }, - set physMS(x) { cmd(7, x); }, - set renderMS(x) { cmd(5, x); }, - - get time() { return cmd(133); }, - - seconds_to_timecode(secs, fps) - { - var s = Math.trunc(secs); - secs -= s; - var f = Math.trunc(fps * secs); - return `${s}:${f}`; - }, - - pause() { - Time.stash = Time.timescale; - Time.timescale = 0; - }, - - play() { - if (!Time.stash) { - console.warn("Tried to resume time without calling Time.pause first."); - return; - } - Time.timescale = Time.stash; - }, -}; - -Time.doc = {}; -Time.doc.timescale = "Get and set the timescale. 1 is normal time; 0.5 is half speed; etc."; -Time.doc.updateMS = "Set the ms per game update."; -Time.doc.physMS = "Set the ms per physics update."; -Time.doc.renderMS = "Set the ms per render update."; -Time.doc.time = "Seconds elapsed since the game started."; -Time.doc.pause = "Pause the game by setting the timescale to 0; remembers the current timescale on play."; -Time.doc.play = "Resume the game after using Time.pause."; - Debug.api = {}; Debug.api.doc_entry = function(obj, key) { @@ -351,8 +309,6 @@ Debug.api.print_doc = function(name) return { Debug, - Time, Gizmos, - performance, assert } diff --git a/scripts/engine.js b/scripts/engine.js index 9c5afb4..3a8374f 100644 --- a/scripts/engine.js +++ b/scripts/engine.js @@ -1,11 +1,67 @@ "use math"; + +Object.assign(console, { + say(msg) { console.print(msg + "\n"); }, + + pprint(msg, lvl = 0) { + if (typeof msg === 'object') + msg = JSON.stringify(msg, null, 2); + + var file = "nofile"; + var line = 0; + + var caller = (new Error()).stack.split('\n')[2]; + if (caller) { + var m = caller.match(/\((.*)\:/)[1]; + if (m) file = m; + m = caller.match(/\:(\d*)\)/)[1]; + if (m) line = m; + } + + console.rec(lvl, msg, file, line); + }, + + spam(msg) { console.pprint(msg,0); }, + debug(msg) { console.pprint(msg,1); }, + info(msg) { console.pprint(msg, 2); }, + warn(msg) { console.pprint(msg, 3); }, + error(msg) { console.pprint(msg + "\n" + console.stackstr(2), 4);}, + panic(msg) { console.pprint(msg + "\n" + console.stackstr(2), 5); }, + + stackstr(skip=0) { + var err = new Error(); + var stack = err.stack.split('\n'); + return stack.slice(skip,stack.length).join('\n'); + }, + + stack(skip = 0) { + console.log(console.stackstr(skip+1)); + }, +}); + +console.log = console.say; +var say = console.say; +var print = console.print; + +console.doc = { + level: "Set level to output logging to console.", + info: "Output info level message.", + warn: "Output warn level message.", + error: "Output error level message, and print stacktrace.", + critical: "Output critical level message, and exit game immediately.", + write: "Write raw text to console.", + say: "Write raw text to console, plus a newline.", + stack: "Output a stacktrace to console.", + console: "Output directly to in game console.", + clear: "Clear console." +}; + globalThis.global = globalThis; function use(file) { if (use.files[file]) return use.files[file]; - if (globalThis.console) - console.info(`running ${file}`); + console.info(`running ${file}`); var c = io.slurp(file); @@ -19,7 +75,7 @@ use.files = {}; function include(file,that) { if (!that) return; - if (globalThis.console) console.info(`running ${file}`); + console.info(`running ${file}`); var c = io.slurp(file); eval_env(c, that, file); } @@ -28,7 +84,7 @@ function eval_env(script, env, file) { env ??= {}; file ??= "SCRIPT"; - if (globalThis.console) console.info(`eval ${file}`); + console.info(`eval ${file}`); script = `(function() { ${script}; }).call(this);\n`; return cmd(123,script,env,file); } @@ -159,7 +215,6 @@ Game.doc.dt = "Current frame dt."; Game.doc.view_camera = "Set the camera for the current view."; Game.doc.camera = "Current camera."; -global.prosperon = {}; prosperon.version = cmd(255); prosperon.revision = cmd(256); @@ -225,7 +280,6 @@ prosperon.clipboardpaste = function(str){}; global.mixin("scripts/input.js"); global.mixin("scripts/std.js"); -console.level = 1; global.mixin("scripts/diff.js"); global.mixin("scripts/color.js"); global.mixin("scripts/gui.js"); diff --git a/scripts/std.js b/scripts/std.js index 4cc9fb0..95c24e7 100644 --- a/scripts/std.js +++ b/scripts/std.js @@ -120,82 +120,6 @@ Resources.replstrs = function(path) return script; } -var console = { - print(msg) { cmd(91, msg); }, - say(msg) { console.print(msg + "\n"); }, - - pprint(msg, lvl) { - var lg; - if (typeof msg === 'object') { - lg = JSON.stringify(msg, null, 2); - } else { - lg = msg; - } - - var stack = (new Error()).stack; - var n = stack.next('\n',0)+1; - n = stack.next('\n', n)+1; - var nnn = stack.slice(n); - var fmatch = nnn.match(/\(.*\:/); - var file = fmatch ? fmatch[0].shift(1).shift(-1) : "nofile"; - var lmatch = nnn.match(/\:\d*\)/); - var line = lmatch ? lmatch[0].shift(1).shift(-1) : "0"; - - yughlog(lvl, lg, file, line); - }, - - spam(msg) { - console.pprint(msg,0); - }, - - /* this always prints to stdout */ - debug(msg) { - console.pprint(msg,1); - }, - - info(msg) { - console.pprint(msg, 2); - }, - - warn(msg) { - console.pprint(msg, 3); - }, - - error(msg) { - console.pprint(msg + "\n" + console.stackstr(3), 4); - }, - - panic(msg) { - console.pprint(msg + "\n" + console.stackstr(1), 5); - }, - - stackstr(skip=0) { - var err = new Error(); - var stack = err.stack.split('\n'); - return stack.slice(skip,stack.length-10).join('\n'); - }, - - stack(skip = 0) { - console.log(stackstr(skip+1)); - }, -}; - -console.log = console.say; -var say = console.say; -var print = console.print; - -console.doc = { - level: "Set level to output logging to console.", - info: "Output info level message.", - warn: "Output warn level message.", - error: "Output error level message, and print stacktrace.", - critical: "Output critical level message, and exit game immediately.", - write: "Write raw text to console.", - say: "Write raw text to console, plus a newline.", - stack: "Output a stacktrace to console.", - console: "Output directly to in game console.", - clear: "Clear console." -}; /* io path rules. Starts with, meaning: @@ -608,10 +532,7 @@ Cmdline.register_cmd("l", function(n) { }, "Set log level."); return { - console, Resources, - say, - print, Cmdline, cmd_args, steam diff --git a/scripts/test.js b/scripts/test.js index 5d40d01..13b5cb3 100644 --- a/scripts/test.js +++ b/scripts/test.js @@ -3,29 +3,36 @@ var tests = []; var pass = 0; var fail = 0; +var failed = []; var test = function(name, fn) { - tests.push(function() { - print(`${pass+fail}/${tests.length}: ${name} ... `); - var result = fn(); - if (result) print(`pass`); - else print(`fail`); - return result; - }); + var func = function() { + print(`${pass+fail+1}/${tests.length}: ${name} ... `); + var p = profile.now(); + var b = fn(); + p = profile.lap(p); + print(`${b ? "pass" : "fail"} [${p}]`); + return b; + }; + func.testname = name; + tests.push(func); } -test("Pass test", _=>1); -test("Fail test", _=>0); - say(`Testing ${tests.length} tests.`); for (var t of tests) { if (t()) pass++; - else + else { fail++; + failed.push(t.testname); + } print("\n"); } -say(`Passed ${pass} tests and failed ${fail}`); -Game.quit(); \ No newline at end of file +say(`Passed ${pass} tests and failed ${fail} [${(pass*100/(pass+fail)).toPrecision(4)}%].`); +say(`Failed tests are:`); +for (var f of failed) + say(f); + +Game.quit(); diff --git a/source/engine/2dphysics.c b/source/engine/2dphysics.c index 4f54874..4652361 100644 --- a/source/engine/2dphysics.c +++ b/source/engine/2dphysics.c @@ -592,7 +592,7 @@ int shape_get_sensor(struct phys2d_shape *shape) { if (!shape->shape) { struct phys2d_edge *edge = shape->data; if (arrlen(edge->shapes) > 0) return cpShapeGetSensor(edge->shapes[0]); - YughInfo("Attempted to get the sensor of an edge with no shapes. It has %d points.", arrlen(edge->points)); + YughWarn("Attempted to get the sensor of an edge with no shapes. It has %d points.", arrlen(edge->points)); return 0; } diff --git a/source/engine/debug/log.c b/source/engine/debug/log.c index f6996a1..dac15c6 100644 --- a/source/engine/debug/log.c +++ b/source/engine/debug/log.c @@ -12,12 +12,27 @@ #include "script.h" +#define ESC "\033[" +#define BLACK 30 +#define RED 31 +#define GREEN 32 +#define YELLOW 33 +#define BLUE 34 +#define MAGENTA 35 +#define CYAN 36 +#define WHITE 37 + +#define COLOR(TXT, _C) ESC #_C "m" #TXT ESC "0m" + char *logstr[] = { "spam", "debug", "info", "warn", "error", "panic"}; +char *logcolor[] = { COLOR(spam,37), COLOR(debug,32), COLOR(info,36), COLOR(warn,33), COLOR(error,31), COLOR(panic,45) }; char *catstr[] = {"engine", "script", "render"}; static FILE *logout; /* where logs are written to */ static FILE *writeout; /* where console is written to */ +int stdout_lvl = LOG_PANIC; + void log_init() { #ifndef NDEBUG @@ -49,8 +64,8 @@ void mYughLog(int category, int priority, int line, const char *file, const char va_end(args); fprintf(logout, "\n"); - if (priority == LOG_DEBUG) { - printf(logfmt, file, line, timebuf, logstr[priority], catstr[category]); + if (priority == LOG_DEBUG || priority > stdout_lvl) { + printf(logfmt, file, line, timebuf, logcolor[priority], catstr[category]); va_list args; va_start(args,message); vprintf(message, args); diff --git a/source/engine/debug/log.h b/source/engine/debug/log.h index 88d0eb7..b438b7e 100644 --- a/source/engine/debug/log.h +++ b/source/engine/debug/log.h @@ -18,6 +18,8 @@ void log_init(); void log_shutdown(); +extern int stdout_lvl; + #ifndef NDEBUG #define YughLog(cat, pri, msg, ...) mYughLog(cat, pri, __LINE__, __FILE__, msg, ##__VA_ARGS__) #define YughSpam(msg, ...) mYughLog(0, LOG_SPAM, __LINE__, __FILE__, msg, ##__VA_ARGS__); diff --git a/source/engine/jsffi.c b/source/engine/jsffi.c index c2e1879..25e509b 100644 --- a/source/engine/jsffi.c +++ b/source/engine/jsffi.c @@ -27,8 +27,11 @@ #include #include +#include +#include #include #include + #include #include @@ -129,32 +132,10 @@ JS_SetClassProto(js, js_##TYPE##_id, TYPE##_proto); \ void js_setprop_str(JSValue obj, const char *prop, JSValue v) { JS_SetPropertyStr(js, obj, prop, v); } -JSValue jstzone() -{ - time_t t = time(NULL); - time_t local_t = mktime(localtime(&t)); - double diff = difftime(t, local_t); - return number2js(diff/3600); -} - int js2bool(JSValue v) { return JS_ToBool(js, v); } JSValue bool2js(int b) { return JS_NewBool(js,b); } -JSValue jsdst() -{ - time_t t = time(NULL); - return bool2js(localtime(&t)->tm_isdst); -} - -JSValue jscurtime() -{ - time_t t; - time(&t); - JSValue jst = number2js(t); - return jst; -} - void js_setprop_num(JSValue obj, uint32_t i, JSValue v) { JS_SetPropertyUint32(js, obj, i, v); } JSValue gos2ref(gameobject **go) @@ -689,21 +670,10 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) ret = JS_NewInt64(js, script_dofile(str)); break; - case 3: - set_timescale(js2number(argv[1])); - break; - case 4: debug_draw_phys(JS_ToBool(js, argv[1])); break; - case 6: - updateMS = js2number(argv[1]); - break; - - case 7: - physMS = js2number(argv[1]); - break; case 15: gameobject_draw_debug(js2gameobject(argv[1])); @@ -845,11 +815,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) window_set_icon(str); break; - case 91: - str = JS_ToCString(js, argv[1]); - log_print(str); - break; - case 97: str = js2str(argv[1]); cursor_img(str); @@ -886,10 +851,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) ret = JS_NewInt64(js, file_mod_secs(str)); break; - case 121: - ret = number2js(get_timescale()); - break; - case 122: str = JS_ToCString(js, argv[1]); ret = file_eval_env(str, argv[2]); @@ -906,23 +867,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) pack_engine(str); break; - - case 127: - ret = JS_NewInt64(js, stm_now()); - break; - - case 128: - ret = JS_NewFloat64(js, stm_ns(js2int64(argv[1]))); - break; - - case 129: - ret = JS_NewFloat64(js, stm_us(js2int64(argv[1]))); - break; - - case 130: - ret = JS_NewFloat64(js, stm_ms(js2int64(argv[1]))); - break; - case 131: gif_rec_start(js2int(argv[1]), js2int(argv[2]), js2int(argv[3]), js2int(argv[4])); break; @@ -930,10 +874,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) str = JS_ToCString(js, argv[1]); gif_rec_end(str); break; - case 133: - ret = JS_NewFloat64(js, apptime()); - break; - + case 135: ret = number2js(cam_zoom()); break; @@ -959,11 +900,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) text_flush(&hudproj); break; - case 142: - str = JS_ToCString(js, argv[1]); - log_print(str); - break; - case 149: ((struct drawmodel *)js2ptr(argv[1]))->model = GetExistingModel(js2str(argv[2])); break; @@ -1057,15 +993,6 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) case 207: ret = dsp_node2js(dsp_fwd_delay(js2number(argv[1]), js2number(argv[2]))); break; - case 210: - ret = jscurtime(); - break; - case 211: - ret = jstzone(); - break; - case 212: - ret = jsdst(); - break; case 213: free_drawmodel(js2ptr(argv[1])); break; @@ -1242,9 +1169,6 @@ JSValue duk_sys_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *ar case 6: return JS_NewBool(js, sim_paused()); - - case 8: - return JS_NewInt64(js, frame_fps()); } return JS_UNDEFINED; @@ -1254,20 +1178,6 @@ JSValue duk_make_gameobject(JSContext *js, JSValueConst this, int argc, JSValueC return gameobject2js(MakeGameobject()); } -JSValue duk_yughlog(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { - int cmd = js2int(argv[0]); - const char *s = JS_ToCString(js, argv[1]); - const char *f = JS_ToCString(js, argv[2]); - int line = js2int(argv[3]); - - mYughLog(LOG_SCRIPT, cmd, line, f, s); - - JS_FreeCString(js, s); - JS_FreeCString(js, f); - - return JS_UNDEFINED; -} - JSValue duk_set_body(JSContext *js, JSValueConst this, int argc, JSValueConst *argv) { int cmd = js2int(argv[0]); gameobject *go = js2gameobject(argv[1]); @@ -1490,10 +1400,14 @@ GETSET_PAIR(warp_gravity, planar_force, vec3) #define MIST_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE, JS_DEF_CFUNC, 0, .u = { .func = { length, JS_CFUNC_generic, { .generic = func1 } } } } +#define MIST_FUNC_DEF(TYPE, FN, LEN) MIST_CFUNC_DEF(#FN, LEN, js_##TYPE##_##FN) + #define MIST_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE, JS_DEF_CGETSET, 0, .u = { .getset = { .get = { .getter = fgetter }, .set = { .setter = fsetter } } } } #define CGETSET_ADD(ID, ENTRY) MIST_CGETSET_DEF(#ENTRY, ID##_get_##ENTRY, ID##_set_##ENTRY) +#define GGETSET_ADD(ENTRY) + static const JSCFunctionListEntry js_warp_gravity_funcs [] = { CGETSET_ADD(warp_gravity, strength), CGETSET_ADD(warp_gravity, decay), @@ -1582,9 +1496,92 @@ JSValue js_os_sys(JSContext *js, JSValueConst this, int argc, JSValue *argv) } static const JSCFunctionListEntry js_os_funcs[] = { - MIST_CFUNC_DEF("cwd", 0, js_os_cwd), - MIST_CFUNC_DEF("env", 1, js_os_env), - MIST_CFUNC_DEF("sys", 0, js_os_sys), + MIST_FUNC_DEF(os, cwd, 0), + MIST_FUNC_DEF(os, env, 1), + MIST_FUNC_DEF(os, sys, 0) +}; + +#define GETSET_GLOBAL(ENTRY, TYPE) \ +JSValue global_set_##ENTRY (JSContext *js, JSValue this, JSValue val) { \ + ENTRY = js2##TYPE (val); \ + return JS_UNDEFINED; \ +} \ +\ +JSValue global_get_##ENTRY (JSContext *js, JSValue this) { \ + return TYPE##2js(ENTRY); \ +} \ + +GETSET_GLOBAL(physMS, number) +GETSET_GLOBAL(timescale, number) +GETSET_GLOBAL(updateMS, number) + +static const JSCFunctionListEntry js_prosperon_funcs[] = { + CGETSET_ADD(global, updateMS), + CGETSET_ADD(global, physMS), + CGETSET_ADD(global, timescale), +}; + +JSValue js_time_now(JSContext *js, JSValue this) { + struct timeval ct; + gettimeofday(&ct, NULL); + return number2js((double)ct.tv_sec+(double)(ct.tv_usec/1000000.0)); +} + +JSValue js_time_computer_dst(JSContext *js, JSValue this) { + time_t t = time(NULL); + return bool2js(localtime(&t)->tm_isdst); +} + +JSValue js_time_computer_zone(JSContext *js, JSValue this) { + time_t t = time(NULL); + time_t local_t = mktime(localtime(&t)); + double diff = difftime(t, local_t); + return number2js(diff/3600); +} + +static const JSCFunctionListEntry js_time_funcs[] = { + MIST_FUNC_DEF(time, now, 0), + MIST_FUNC_DEF(time, computer_dst, 0), + MIST_FUNC_DEF(time, computer_zone, 0) +}; + +JSValue js_console_print(JSContext *js, JSValue this, int argc, JSValue *argv) +{ + char *s = JS_ToCString(js,argv[0]); + log_print(s); + JS_FreeCString(js,s); + return JS_UNDEFINED; +} + +JSValue js_console_rec(JSContext *js, JSValue this, int argc, JSValue *argv) +{ + int level = js2int(argv[0]); + const char *msg = JS_ToCString(js, argv[1]); + const char *file = JS_ToCString(js, argv[2]); + int line = js2int(argv[3]); + + mYughLog(LOG_SCRIPT, level, line, file, msg); + + JS_FreeCString(js, msg); + JS_FreeCString(js, file); + + return JS_UNDEFINED; +} + +GETSET_GLOBAL(stdout_lvl, number) + +static const JSCFunctionListEntry js_console_funcs[] = { + MIST_FUNC_DEF(console,print,1), + MIST_FUNC_DEF(console,rec,4), + CGETSET_ADD(global, stdout_lvl) +}; + +JSValue js_profile_now(JSContext *js, JSValue this) { return number2js(stm_now()); } +JSValue js_profile_fps(JSContext *js, JSValue this) { return number2js(frame_fps()); } + +static const JSCFunctionListEntry js_profile_funcs[] = { + MIST_FUNC_DEF(profile,now,0), + MIST_FUNC_DEF(profile,fps,0) }; JSValue js_io_exists(JSContext *js, JSValueConst this, int argc, JSValue *argv) @@ -2050,7 +2047,6 @@ void ffi_load() { JS_SetPropertyFunctionList(js, nota, nota_funcs, countof(nota_funcs)); JS_SetPropertyStr(js, globalThis, "nota", nota); - DUK_FUNC(yughlog, 4) DUK_FUNC(make_gameobject, 0) DUK_FUNC(set_body, 3) DUK_FUNC(q_body, 2) @@ -2094,6 +2090,10 @@ void ffi_load() { QJSGLOBALCLASS(os); QJSGLOBALCLASS(io); + QJSGLOBALCLASS(prosperon); + QJSGLOBALCLASS(time); + QJSGLOBALCLASS(console); + QJSGLOBALCLASS(profile); JS_SetPropertyStr(js, globalThis, "Window", window2js(&mainwin)); diff --git a/source/engine/render.c b/source/engine/render.c index 5289698..22339e8 100644 --- a/source/engine/render.c +++ b/source/engine/render.c @@ -217,7 +217,7 @@ void trace_make_pipeline(const sg_pipeline_desc *d, sg_pipeline id, void *data) void trace_apply_pipeline(sg_pipeline pip, void *data) { - YughSpam("Applying pipeline %u %s.", pip, sg_query_pipeline_desc(pip).label); +// YughSpam("Applying pipeline %u %s.", pip, sg_query_pipeline_desc(pip).label); } void trace_fail_pipeline(sg_pipeline pip, void *data) @@ -232,7 +232,7 @@ void trace_make_attachments(const sg_attachment_desc *d, sg_attachments result, void trace_begin_pass(sg_pass pass, const sg_pass_action *action, void *data) { - YughSpam("Begin pass %s", pass.label); +// YughSpam("Begin pass %s", pass.label); } static sg_trace_hooks hooks = { diff --git a/source/engine/yugine.c b/source/engine/yugine.c index 3819ebe..39b03d1 100644 --- a/source/engine/yugine.c +++ b/source/engine/yugine.c @@ -73,7 +73,7 @@ static int phys_step = 0; uint64_t start_t; uint64_t frame_t; -static float timescale = 1.f; +double timescale = 1.f; #define SIM_PLAY 0 #define SIM_PAUSE 1 @@ -267,8 +267,6 @@ void sim_start() { sim_play = SIM_PLAY; } void sim_pause() { sim_play = SIM_PAUSE; } int phys_stepping() { return sim_play == SIM_STEP; } void sim_step() { sim_play = SIM_STEP; } -void set_timescale(float val) { timescale = val; } -double get_timescale() { return timescale; } static sapp_desc start_desc = { .width = 720, @@ -302,7 +300,7 @@ int main(int argc, char **argv) { #endif resources_init(); - + stm_setup(); /* time */ script_startup(); int argsize = 0; @@ -333,7 +331,7 @@ int main(int argc, char **argv) { void engine_start(JSValue fn) { c_init_fn = fn; - stm_setup(); /* time */ + start_t = frame_t = stm_now(); physlast = updatelast = start_t; sound_init(); diff --git a/source/engine/yugine.h b/source/engine/yugine.h index bbb8df9..09111d9 100644 --- a/source/engine/yugine.h +++ b/source/engine/yugine.h @@ -10,15 +10,14 @@ void sim_pause(); void sim_stop(); void sim_step(); int phys_stepping(); -void set_timescale(float val); void print_stacktrace(); void engine_start(JSValue fn); /* fn runs after the engine starts */ int frame_fps(); -double get_timescale(); void quit(); double apptime(); +extern double timescale; extern double renderMS; extern double physMS; extern double updateMS;