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;
};
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 {
convert,
time,
Vector,
bbox,
yaml,
lodash
};

View file

@ -49,9 +49,8 @@ profile.ms = function (t) {
var callgraph = {};
profile.rawstacks = {};
profile.cpu_cg = callgraph;
function add_callgraph(fn, line, time) {
function add_callgraph(fn, line, time, alone) {
var cc = callgraph[line];
if (!cc) {
var cc = {};
@ -60,9 +59,18 @@ function add_callgraph(fn, line, time) {
cc.hits = 0;
cc.fn = fn;
cc.line = line;
cc.alone = {
time: 0,
hits: 0
}
}
cc.time += time;
cc.hits++;
if (alone) {
cc.alone.time += time;
cc.alone.hits++;
}
}
var hittar = 500; // number of call instructions before getting a new frame
@ -73,9 +81,11 @@ profile.cpu_start = undefined;
profile.clear_cpu = function () {
callgraph = {};
profile.cpu_instr = undefined;
};
profile.start_cpu_gather = function (gathertime = 5) {
profile.clear_cpu();
// gather cpu frames for 'time' seconds
if (profile.cpu_start) return;
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);
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();
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.cpu_start = undefined;
var e = Object.values(callgraph);
e = e.sort((a, b) => {
if (a.time > b.time) return -1;
return 1;
});
e = e.filter( x=> x.line);
for (var x of e) {
var ffs = x.line.split(":");
x.timestr = profile.best_t(x.time);
var pct = (profile.secs(x.time) / gathertime) * 100;
x.timeper = x.time / x.hits;
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.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;
}
});
@ -179,17 +199,12 @@ profile.best_t = function (t) {
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
in your code to get a call graph for things you are interested in.
*/
var frame_avg = false;
profile.frame_avg_t = 72000;
profile.start_frame_avg = function () {
if (frame_avg) return;
@ -219,6 +234,7 @@ var pframe = 0;
var profile_stack = [];
profile.frame = function profile_frame(title) {
return;
if (profile.cpu_start) return;
if (!frame_avg) return;
@ -236,29 +252,12 @@ profile.frame = function profile_frame(title) {
};
profile.endframe = function profile_endframe() {
return;
if (!frame_avg) return;
profile_cframe.time = profile.now() - profile_cframe.time;
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
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.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) {
for (var i in stat) {
obj[i] ??= [];
@ -337,10 +348,13 @@ function prof_add_stats(obj, stat) {
}
profile.pushdata = function (arr, val) {
if (arr.last() !== val) arr[profile.curframe] = val;
};
profile.capturing = false;
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.gfx, imgui.framestats());
prof_add_stats(profile.data.actors, actor.__stats());

View file

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

View file

@ -450,14 +450,39 @@ JSC_SCALL(imgui_context,
)
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);
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();
}
)
JSC_CCALL(imgui_tablenextrow, ImGui::TableNextRow())
JSC_CCALL(imgui_tablenextcolumn, ImGui::TableNextColumn())
JSC_SCALL(imgui_tablesetupcolumn, ImGui::TableSetupColumn(str))
JSC_CCALL(imgui_tableheadersrow, ImGui::TableHeadersRow())
JSC_SCALL(imgui_dnd,
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, close_popup,0),
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, tablenextrow,0),
MIST_FUNC_DEF(imgui, tableheadersrow, 0),
MIST_FUNC_DEF(imgui, tablesetupcolumn, 1),
MIST_FUNC_DEF(imgui, dnd, 3),
MIST_FUNC_DEF(imgui, dndtarget, 2),
MIST_FUNC_DEF(imgui, color, 2),

View file

@ -2013,10 +2013,18 @@ JSC_CCALL(transform_unit,
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[] = {
CGETSET_ADD(transform, pos),
CGETSET_ADD(transform, scale),
CGETSET_ADD(transform, rotation),
MIST_FUNC_DEF(transform, trs, 3),
MIST_FUNC_DEF(transform, phys2d, 3),
MIST_FUNC_DEF(transform, move, 1),
MIST_FUNC_DEF(transform, rotate, 2),