add some lodash

This commit is contained in:
John Alanbrook 2024-09-26 19:28:54 -05:00
parent f35c77c4a9
commit 6f9137746a
5 changed files with 109 additions and 42 deletions

View file

@ -1554,10 +1554,23 @@ Math.sign = function (n) {
return n >= 0 ? 1 : -1; return n >= 0 ? 1 : -1;
}; };
var lodash = {};
lodash.get = function(obj, path, defValue) {
if (!path) return undefined
// Check if path is string or array. Regex : ensure that we do not have '.' and brackets.
var pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g)
var result = pathArray.reduce(
(prevObj, key) => prevObj && prevObj[key],
obj
)
return result === undefined ? defValue : result
}
return { return {
convert, convert,
time, time,
Vector, Vector,
bbox, bbox,
yaml, yaml,
lodash
}; };

View file

@ -49,9 +49,8 @@ profile.ms = function (t) {
var callgraph = {}; var callgraph = {};
profile.rawstacks = {}; profile.rawstacks = {};
profile.cpu_cg = callgraph;
function add_callgraph(fn, line, time) { function add_callgraph(fn, line, time, alone) {
var cc = callgraph[line]; var cc = callgraph[line];
if (!cc) { if (!cc) {
var cc = {}; var cc = {};
@ -60,9 +59,18 @@ function add_callgraph(fn, line, time) {
cc.hits = 0; cc.hits = 0;
cc.fn = fn; cc.fn = fn;
cc.line = line; cc.line = line;
cc.alone = {
time: 0,
hits: 0
}
} }
cc.time += time; cc.time += time;
cc.hits++; cc.hits++;
if (alone) {
cc.alone.time += time;
cc.alone.hits++;
}
} }
var hittar = 500; // number of call instructions before getting a new frame var hittar = 500; // number of call instructions before getting a new frame
@ -73,9 +81,11 @@ profile.cpu_start = undefined;
profile.clear_cpu = function () { profile.clear_cpu = function () {
callgraph = {}; callgraph = {};
profile.cpu_instr = undefined;
}; };
profile.start_cpu_gather = function (gathertime = 5) { profile.start_cpu_gather = function (gathertime = 5) {
profile.clear_cpu();
// gather cpu frames for 'time' seconds // gather cpu frames for 'time' seconds
if (profile.cpu_start) return; if (profile.cpu_start) return;
profile.cpu_start = profile.now(); profile.cpu_start = profile.now();
@ -100,7 +110,8 @@ profile.start_cpu_gather = function (gathertime = 5) {
var lines = stack.map(x => x[1]).filter(x => x); var lines = stack.map(x => x[1]).filter(x => x);
lines = lines.map(x => x.slice(1, x.length - 1)); lines = lines.map(x => x.slice(1, x.length - 1));
for (var i = 0; i < fns.length; i++) add_callgraph(fns[i], lines[i], time); add_callgraph(fns[0], lines[0], time, true);
for (var i = 1; i < fns.length; i++) add_callgraph(fns[i], lines[i], time, false);
st = profile.now(); st = profile.now();
if (profile.secs(st - profile.cpu_start) < gathertime) profile.gather_rate(Math.variate(hittar, hitpct)); if (profile.secs(st - profile.cpu_start) < gathertime) profile.gather_rate(Math.variate(hittar, hitpct));
@ -108,21 +119,30 @@ profile.start_cpu_gather = function (gathertime = 5) {
profile.gather_stop(); profile.gather_stop();
profile.cpu_start = undefined; profile.cpu_start = undefined;
var e = Object.values(callgraph); var e = Object.values(callgraph);
e = e.sort((a, b) => { e = e.filter( x=> x.line);
if (a.time > b.time) return -1;
return 1;
});
for (var x of e) { for (var x of e) {
var ffs = x.line.split(":"); var ffs = x.line.split(":");
x.timestr = profile.best_t(x.time); x.timestr = profile.best_t(x.time);
var pct = (profile.secs(x.time) / gathertime) * 100;
x.timeper = x.time / x.hits; x.timeper = x.time / x.hits;
x.timeperstr = profile.best_t(x.timeper); x.timeperstr = profile.best_t(x.timeper);
x.pct = (profile.secs(x.time) / gathertime) * 100;
x.alone.timestr = profile.best_t(x.alone.time);
x.alone.timeper = x.alone.time/x.alone.hits;
x.alone.timeperstr = profile.best_t(x.alone.timeper);
x.alone.pct = (profile.secs(x.alone.time)/gathertime*100);
x.fncall = get_line(ffs[0], ffs[1]); x.fncall = get_line(ffs[0], ffs[1]);
x.log = `${x.line}::${x.fn}:: ${x.timestr} (${pct.toPrecision(3)}%) (${x.hits} hits) --> ${get_line(ffs[0], ffs[1])}`; x.log = x.line + " " + x.fn + " " + x.fncall;
x.incl = {
time: x.time,
timestr: x.timestr,
timeper: x.timeper,
timeperstr: x.timeperstr,
hits: x.hits,
pct: x.pct,
};
} }
profile.cpu_instr = e; profile.cpu_instr = e;
} }
}); });
@ -179,17 +199,12 @@ profile.best_t = function (t) {
return `${t.toPrecision(4)} ${t_units[qq]}`; return `${t.toPrecision(4)} ${t_units[qq]}`;
}; };
profile.report = function (start, msg = "[undefined report]") {
console.info(`${msg} in ${profile.best_t(profile.now() - start)}`);
};
/* /*
Frame averages are an instrumented profiling technique. Place frame() calls Frame averages are an instrumented profiling technique. Place frame() calls
in your code to get a call graph for things you are interested in. in your code to get a call graph for things you are interested in.
*/ */
var frame_avg = false; var frame_avg = false;
profile.frame_avg_t = 72000;
profile.start_frame_avg = function () { profile.start_frame_avg = function () {
if (frame_avg) return; if (frame_avg) return;
@ -219,6 +234,7 @@ var pframe = 0;
var profile_stack = []; var profile_stack = [];
profile.frame = function profile_frame(title) { profile.frame = function profile_frame(title) {
return;
if (profile.cpu_start) return; if (profile.cpu_start) return;
if (!frame_avg) return; if (!frame_avg) return;
@ -236,29 +252,12 @@ profile.frame = function profile_frame(title) {
}; };
profile.endframe = function profile_endframe() { profile.endframe = function profile_endframe() {
return;
if (!frame_avg) return; if (!frame_avg) return;
profile_cframe.time = profile.now() - profile_cframe.time; profile_cframe.time = profile.now() - profile_cframe.time;
profile_cframe = profile_frame_ts.pop(); profile_cframe = profile_frame_ts.pop();
}; };
var print_frame = function (frame, indent, title) {
say(indent + `${title} ::::: ${profile.best_t(Math.mean(frame._times))} ± ${profile.best_t(Math.ci(frame._times))} (${frame._times.length} hits)`);
for (var i in frame) {
if (i === "_times") continue;
print_frame(frame[i], indent + " ", i);
}
};
profile.print_frame_avg = function () {
say("===FRAME AVERAGES===\n");
var indent = "";
for (var i in profile_frames) print_frame(profile_frames[i], "", "frame");
say("\n");
};
/* /*
Cache reporting is to measure how long specific events take, that are NOT every frame Cache reporting is to measure how long specific events take, that are NOT every frame
Useful to measure things like how long it takes to make a specific creature Useful to measure things like how long it takes to make a specific creature
@ -329,6 +328,18 @@ function printreport(cache, name) {
profile.data = {}; profile.data = {};
profile.curframe = 0; profile.curframe = 0;
profile.snapshot = {};
var fps = [];
profile.report_frame = function(t)
{
fps.push(t);
if (fps.length > 15) {
profile.snapshot.fps = Math.mean(fps);
fps = [];
}
}
function prof_add_stats(obj, stat) { function prof_add_stats(obj, stat) {
for (var i in stat) { for (var i in stat) {
obj[i] ??= []; obj[i] ??= [];
@ -337,10 +348,13 @@ function prof_add_stats(obj, stat) {
} }
profile.pushdata = function (arr, val) { profile.pushdata = function (arr, val) {
if (arr.last() !== val) arr[profile.curframe] = val; if (arr.last() !== val) arr[profile.curframe] = val;
}; };
profile.capturing = false;
profile.capture_data = function () { profile.capture_data = function () {
if (!profile.capturing && profile.data.memory.malloc_size) return;
prof_add_stats(profile.data.memory, os.mem()); prof_add_stats(profile.data.memory, os.mem());
prof_add_stats(profile.data.gfx, imgui.framestats()); prof_add_stats(profile.data.gfx, imgui.framestats());
prof_add_stats(profile.data.actors, actor.__stats()); prof_add_stats(profile.data.actors, actor.__stats());

View file

@ -758,7 +758,7 @@ function flush_img() {
function img_e() { function img_e() {
img_idx++; img_idx++;
if (img_idx > img_cache.length) { if (img_idx > img_cache.length) {
e = { var e = {
transform: os.make_transform(), transform: os.make_transform(),
shade: Color.white, shade: Color.white,
rect: [0, 0, 1, 1], rect: [0, 0, 1, 1],
@ -766,12 +766,10 @@ function img_e() {
img_cache.push(e); img_cache.push(e);
return e; return e;
} }
var e = img_cache[img_idx - 1]; return img_cache[img_idx - 1];
e.transform.unit();
return e;
} }
render.image = function (tex, pos, scale, rotation = 0, color = Color.white) { render.image = function image(tex, pos, scale, rotation = 0, color = Color.white) {
if (typeof tex === "string") { if (typeof tex === "string") {
tex = game.texture(tex); tex = game.texture(tex);
scale.x ??= tex.width; scale.x ??= tex.width;
@ -790,8 +788,7 @@ render.image = function (tex, pos, scale, rotation = 0, color = Color.white) {
} }
var e = img_e(); var e = img_e();
e.transform.move(pos); e.transform.trs(pos, undefined, scale ? scale.div([tex.width, tex.height]) : undefined);
if (scale) e.transform.scale = scale.div([tex.width, tex.height]);
e.shade = color; e.shade = color;
return; return;
@ -978,7 +975,11 @@ prosperon.make_camera = function () {
var screencolor; var screencolor;
globalThis.imtoggle = function (name, obj, field) { globalThis.imtoggle = function (name, obj, field) {
var changed = false;
var old = obj[field];
obj[field] = imgui.checkbox(name, obj[field]); obj[field] = imgui.checkbox(name, obj[field]);
if (old !== obj[field]) return true;
return false;
}; };
var replstr = ""; var replstr = "";
@ -1120,6 +1121,9 @@ prosperon.render = function () {
profile.endframe(); profile.endframe();
render.end_pass(); render.end_pass();
profile.report_frame(profile.secs(profile.now())-frame_t);
render.commit(); render.commit();
endframe(); endframe();
@ -1179,6 +1183,7 @@ prosperon.process = function process() {
profile.endframe(); profile.endframe();
profile.capture_data(); profile.capture_data();
}; };
return { render }; return { render };

View file

@ -450,14 +450,39 @@ JSC_SCALL(imgui_context,
) )
JSC_SCALL(imgui_table, JSC_SCALL(imgui_table,
if (ImGui::BeginTable(str, js2number(argv[1]))) { int flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingStretchProp;
bool sort = false;
if (!JS_IsUndefined(argv[3])) sort = true;
if (sort) flags |= ImGuiTableFlags_Sortable;
if (ImGui::BeginTable(str, js2number(argv[1]), flags)) {
script_call_sym(argv[2],0,NULL); script_call_sym(argv[2],0,NULL);
if (sort) {
ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs();
if (sort_specs && sort_specs->SpecsDirty) {
for (int i = 0; i < sort_specs->SpecsCount; i++)
{
const ImGuiTableColumnSortSpecs* spec = &sort_specs->Specs[i];
JSValue send[2];
send[0] = number2js(spec->ColumnIndex);
send[1] = boolean2js(spec->SortDirection == ImGuiSortDirection_Ascending);
script_call_sym(argv[3], 2, send);
JS_FreeValue(js, send[0]);
JS_FreeValue(js, send[1]);
}
sort_specs->SpecsDirty = false;
}
}
ImGui::EndTable(); ImGui::EndTable();
} }
) )
JSC_CCALL(imgui_tablenextrow, ImGui::TableNextRow()) JSC_CCALL(imgui_tablenextrow, ImGui::TableNextRow())
JSC_CCALL(imgui_tablenextcolumn, ImGui::TableNextColumn()) JSC_CCALL(imgui_tablenextcolumn, ImGui::TableNextColumn())
JSC_SCALL(imgui_tablesetupcolumn, ImGui::TableSetupColumn(str))
JSC_CCALL(imgui_tableheadersrow, ImGui::TableHeadersRow())
JSC_SCALL(imgui_dnd, JSC_SCALL(imgui_dnd,
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) { if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {
@ -883,9 +908,11 @@ static const JSCFunctionListEntry js_imgui_funcs[] = {
MIST_FUNC_DEF(imgui, popup, 2), MIST_FUNC_DEF(imgui, popup, 2),
MIST_FUNC_DEF(imgui, close_popup,0), MIST_FUNC_DEF(imgui, close_popup,0),
MIST_FUNC_DEF(imgui, context,2), MIST_FUNC_DEF(imgui, context,2),
MIST_FUNC_DEF(imgui, table, 3), MIST_FUNC_DEF(imgui, table, 4),
MIST_FUNC_DEF(imgui, tablenextcolumn,0), MIST_FUNC_DEF(imgui, tablenextcolumn,0),
MIST_FUNC_DEF(imgui, tablenextrow,0), MIST_FUNC_DEF(imgui, tablenextrow,0),
MIST_FUNC_DEF(imgui, tableheadersrow, 0),
MIST_FUNC_DEF(imgui, tablesetupcolumn, 1),
MIST_FUNC_DEF(imgui, dnd, 3), MIST_FUNC_DEF(imgui, dnd, 3),
MIST_FUNC_DEF(imgui, dndtarget, 2), MIST_FUNC_DEF(imgui, dndtarget, 2),
MIST_FUNC_DEF(imgui, color, 2), MIST_FUNC_DEF(imgui, color, 2),

View file

@ -2013,10 +2013,18 @@ JSC_CCALL(transform_unit,
t->scale = v3one; t->scale = v3one;
) )
JSC_CCALL(transform_trs,
transform *t = js2transform(self);
t->pos = JS_IsUndefined(argv[0]) ? v3zero : js2vec3(argv[0]);
t->rotation = JS_IsUndefined(argv[1]) ? QUAT1 : js2quat(argv[1]);
t->scale = JS_IsUndefined(argv[2]) ? v3one : js2vec3(argv[1]);
)
static const JSCFunctionListEntry js_transform_funcs[] = { static const JSCFunctionListEntry js_transform_funcs[] = {
CGETSET_ADD(transform, pos), CGETSET_ADD(transform, pos),
CGETSET_ADD(transform, scale), CGETSET_ADD(transform, scale),
CGETSET_ADD(transform, rotation), CGETSET_ADD(transform, rotation),
MIST_FUNC_DEF(transform, trs, 3),
MIST_FUNC_DEF(transform, phys2d, 3), MIST_FUNC_DEF(transform, phys2d, 3),
MIST_FUNC_DEF(transform, move, 1), MIST_FUNC_DEF(transform, move, 1),
MIST_FUNC_DEF(transform, rotate, 2), MIST_FUNC_DEF(transform, rotate, 2),