rntviewer/src/render.cpp

392 lines
16 KiB
C++
Raw Normal View History

2024-07-11 12:59:59 +00:00
internal
void accum_dt_ms(Delta_Time_Accum &accum, f32 dt)
{
if (accum.count < accum.max) {
assert(accum.start == 0);
accum.base[accum.count++] = dt;
} else {
accum.base[accum.start++] = dt;
if (accum.start == accum.max)
accum.start = 0;
}
}
internal
f32 calc_avg_dt_ms(const Delta_Time_Accum &accum)
{
f32 res = 0;
for (u16 idx = 0; idx < accum.count; ++idx)
res += accum.base[idx];
if (accum.count) res /= accum.count;
return res;
}
2024-07-11 13:27:38 +00:00
internal
String8 to_pretty_size(Arena *arena, u64 bytes)
{
if (bytes >= GiB(1)) return push_str8f(arena, "%.1f GiB", (f32)bytes / GiB(1));
if (bytes >= MiB(1)) return push_str8f(arena, "%.1f MiB", (f32)bytes / MiB(1));
if (bytes >= KiB(1)) return push_str8f(arena, "%.1f KiB", (f32)bytes / KiB(1));
return push_str8f(arena, "%zu B", bytes);
}
2024-07-10 19:47:37 +00:00
internal
2024-07-15 09:29:32 +00:00
u32 mem_edit_bg_color_fn(const u8 *, u64 off, void *user_data)
2024-07-11 12:00:43 +00:00
{
2024-07-15 09:29:32 +00:00
App_State *app = reinterpret_cast<App_State *>(user_data);
2024-07-12 09:58:55 +00:00
const RNTuple_Data &rdata = app->rndata;
2024-07-18 13:32:32 +00:00
const TFile_Data &tdata = app->tfile_data;
2024-07-16 10:04:38 +00:00
u64 rblob_sz = rdata.rblob_header_size; // @Incomplete
2024-07-19 14:31:48 +00:00
i64 hilite_cluster = app->viewer.highlight_cluster ? app->viewer.highlighted_cluster : -1;
2024-07-11 12:27:19 +00:00
2024-07-16 12:34:51 +00:00
off += app->viewer.base_display_addr;
2024-07-12 08:07:27 +00:00
2024-07-11 12:59:59 +00:00
#define COL(c) (ImColor((c)[0], (c)[1], (c)[2]))
2024-07-15 13:54:22 +00:00
// TFile start
2024-07-18 13:32:32 +00:00
if (off <= tdata.root_file_header_size) return COL(app->viewer.col_tfile_header);
if (tdata.rng_root_file_obj.start <= off && off < tdata.rng_root_file_obj.end()) return COL(app->viewer.col_tfile_obj);
2024-07-18 13:56:55 +00:00
if (tdata.rng_root_file_info.start <= off && off < tdata.rng_root_file_info.end()) return COL(app->viewer.col_tfile_info);
if (tdata.rng_root_file_free.start <= off && off < tdata.rng_root_file_free.end()) return COL(app->viewer.col_tfile_free);
2024-07-15 09:29:32 +00:00
2024-07-15 13:54:22 +00:00
// Handle pages
// fast case: `off` is in the same page info as previous `off`.
2024-07-16 10:04:38 +00:00
if (app->last_pinfo->range.start < off && off < app->last_pinfo->range.end()) {
2024-07-19 14:31:48 +00:00
if (hilite_cluster >= 0 && app->last_pinfo->cluster_id == (u64)hilite_cluster)
return COL(app->viewer.col_highlight);
2024-07-16 10:04:38 +00:00
if (off >= app->last_pinfo->range.end() - app->last_pinfo->checksum_size())
2024-07-16 12:34:51 +00:00
return COL(app->viewer.col_checksum);
return COL(app->viewer.col_page);
2024-07-16 10:04:38 +00:00
}
2024-07-15 09:29:32 +00:00
2024-07-15 13:54:22 +00:00
// still fast case: `off is in the next page info as the previous.
2024-07-16 10:04:38 +00:00
if (app->last_pinfo->next) // don't check if it's checksum, since it's the first byte of the page
2024-07-15 13:54:22 +00:00
app->last_pinfo = app->last_pinfo->next;
if (app->last_pinfo && app->last_pinfo->range.start <= off && off < app->last_pinfo->range.end()) {
2024-07-19 14:31:48 +00:00
if (hilite_cluster >= 0 && app->last_pinfo->cluster_id == (u64)hilite_cluster)
return COL(app->viewer.col_highlight);
2024-07-15 13:54:22 +00:00
if (off == app->last_pinfo->range.start)
2024-07-16 12:34:51 +00:00
return COL(app->viewer.col_page_start);
2024-07-16 10:04:38 +00:00
if (off >= app->last_pinfo->range.end() - app->last_pinfo->checksum_size())
2024-07-16 12:34:51 +00:00
return COL(app->viewer.col_checksum);
return COL(app->viewer.col_page);
2024-07-15 13:54:22 +00:00
}
2024-07-16 12:34:51 +00:00
if (rdata.rng_anchor_key.start <= off && off < rdata.rng_anchor_key.end()) return COL(app->viewer.col_key);
if (rdata.rng_anchor.start <= off && off < rdata.rng_anchor.end() - 8) return COL(app->viewer.col_anchor);
if (rdata.rng_anchor.end() - 8 <= off && off < rdata.rng_anchor.end()) return COL(app->viewer.col_checksum);
if (rdata.rng_header.start - rblob_sz <= off && off < rdata.rng_header.start) return COL(app->viewer.col_key);
if (rdata.rng_header.start <= off && off < rdata.rng_header.end() - 8) return COL(app->viewer.col_header);
if (rdata.rng_header.end() - 8 <= off && off < rdata.rng_header.end()) return COL(app->viewer.col_checksum);
if (rdata.rng_footer.start - rblob_sz <= off && off < rdata.rng_footer.start) return COL(app->viewer.col_key);
if (rdata.rng_footer.start <= off && off < rdata.rng_footer.end() - 8) return COL(app->viewer.col_footer);
if (rdata.rng_footer.end() - 8 <= off && off < rdata.rng_footer.end()) return COL(app->viewer.col_checksum);
2024-07-23 08:41:55 +00:00
if (rdata.rng_tkeys_list.start <= off && off < rdata.rng_tkeys_list.end()) return COL(app->viewer.col_tkeys_list);
2024-07-16 12:34:51 +00:00
// @Speed
for (u64 cg_idx = 0; cg_idx < rdata.n_cluster_groups; ++cg_idx) {
Cluster_Group_Info &cg_info = rdata.cluster_groups[cg_idx];
if (cg_info.rng_page_list.start -rblob_sz <= off && off < cg_info.rng_page_list.start) return COL(app->viewer.col_page_list);
if (cg_info.rng_page_list.start <= off && off < cg_info.rng_page_list.end() - 8) return COL(app->viewer.col_page_list);
if (cg_info.rng_page_list.end() - 8 <= off && off < cg_info.rng_page_list.end()) return COL(app->viewer.col_checksum);
}
2024-07-12 16:29:35 +00:00
2024-07-15 13:54:22 +00:00
// Slow page group lookup, ideally only done once per render when last_pinfo is invalid.
2024-07-15 09:29:32 +00:00
for (Page_Info_Chunk *chunk = rdata.page_chunks; chunk; chunk = chunk->next) {
2024-07-16 12:34:51 +00:00
if (chunk->range.start - rblob_sz <= off && off < chunk->range.start) return COL(app->viewer.col_key);
if (chunk->range.start <= off && off < chunk->range.end()) {
2024-07-15 09:29:32 +00:00
for (u64 group_idx = chunk->first_group; group_idx < rdata.n_page_groups; ++group_idx) {
const Page_Info_Group &group = rdata.page_groups[group_idx];
if (off < group.range.start || off >= group.range.end())
2024-07-15 09:29:32 +00:00
continue;
for (Page_Info_Node *pinfo = group.first; pinfo; pinfo = pinfo->next) {
if (pinfo->range.start <= off && off < pinfo->range.end()) {
2024-07-15 09:29:32 +00:00
app->last_pinfo = pinfo;
2024-07-19 14:31:48 +00:00
if (hilite_cluster >= 0 && pinfo->cluster_id == (u64)hilite_cluster) return COL(app->viewer.col_highlight);
if (pinfo->range.start == off) return COL(app->viewer.col_page_start);
if (off >= pinfo->range.end() - pinfo->checksum_size()) return COL(app->viewer.col_checksum);
2024-07-16 12:34:51 +00:00
return COL(app->viewer.col_page);
2024-07-15 09:29:32 +00:00
}
}
}
2024-07-15 09:54:45 +00:00
fprintf(stderr, "Offset 0x%lX is in chunk 0x%lX - 0x%lX, but found in no page_info range!\n",
off, chunk->range.start, chunk->range.end());
assert(false);
2024-07-12 16:29:35 +00:00
}
}
2024-07-11 12:59:59 +00:00
#undef COL
2024-07-11 12:00:43 +00:00
return IM_COL32(0, 0, 0, 0);
}
internal
2024-07-15 09:29:32 +00:00
MemoryEditor make_memory_editor(App_State &app)
{
MemoryEditor mem_edit;
mem_edit.Cols = 32;
2024-07-11 12:27:19 +00:00
mem_edit.OptShowDataPreview = true;
2024-07-19 14:31:48 +00:00
// Do nothing on write.
// Note that we don't use ReadOnly = true because that disables selecting bytes
mem_edit.WriteFn = [] (ImU8*, size_t, ImU8) {};
2024-07-11 12:00:43 +00:00
mem_edit.BgColorFn = mem_edit_bg_color_fn;
2024-07-11 12:27:19 +00:00
mem_edit.BgColorFnUserData = &app;
return mem_edit;
}
2024-07-11 12:59:59 +00:00
internal
2024-07-16 12:34:51 +00:00
void make_viewer(App_State &app)
2024-07-11 12:27:19 +00:00
{
2024-07-16 12:34:51 +00:00
Viewer viewer {};
viewer.mem_edit = make_memory_editor(app);
#define COL(c, r, g, b) viewer.c[0] = r/255.0, viewer.c[1] = g/255.0, viewer.c[2] = b/255.0
2024-07-11 14:29:44 +00:00
COL(col_anchor, 150, 150, 0);
2024-07-11 12:27:19 +00:00
COL(col_header, 150, 0, 50);
COL(col_footer, 50, 0, 150);
2024-07-11 14:29:44 +00:00
COL(col_key, 0, 100, 50);
2024-07-18 13:32:32 +00:00
COL(col_tfile_header, 90, 90, 90);
COL(col_tfile_obj, 120, 120, 120);
2024-07-18 13:56:55 +00:00
COL(col_tfile_info, 95, 76, 76);
COL(col_tfile_free, 60, 60, 90);
2024-07-12 16:29:35 +00:00
COL(col_page, 125, 0, 125);
COL(col_page_start, 200, 0, 200);
2024-07-16 10:04:38 +00:00
COL(col_checksum, 134, 65, 25);
2024-07-16 12:34:51 +00:00
COL(col_page_list, 60, 110, 120);
2024-07-23 08:41:55 +00:00
COL(col_tkeys_list, 100, 140, 100);
2024-07-19 19:02:27 +00:00
COL(col_highlight, 190, 190, 190);
2024-07-11 12:27:19 +00:00
#undef COL
2024-07-16 12:34:51 +00:00
app.viewer = viewer;
}
internal
void viewer_jump_to(Viewer &viewer, u64 addr)
{
viewer.base_display_addr = addr;
viewer.mem_edit.GotoAddr = 0;
2024-07-11 12:27:19 +00:00
}
2024-07-15 16:02:55 +00:00
internal
2024-07-16 12:34:51 +00:00
void viewer_jump_to_page(App_State &app, u64 page_idx)
2024-07-15 16:02:55 +00:00
{
assert(app.rndata.n_pages > 0);
page_idx = (page_idx + app.rndata.n_pages) % app.rndata.n_pages;
// @Speed
Page_Info_Node *page = app.rndata.pages;
for (u64 i = 0; i < page_idx; ++i) {
page = page->next;
assert(page);
}
2024-07-16 12:34:51 +00:00
app.viewer.latest_page_gone_to = page_idx;
viewer_jump_to(app.viewer, page->range.start);
2024-07-15 16:02:55 +00:00
}
2024-07-18 15:43:44 +00:00
internal
void viewer_jump_to_page_list(App_State &app, u64 page_list_idx)
{
assert(app.rndata.n_cluster_groups > 0);
page_list_idx = (page_list_idx + app.rndata.n_cluster_groups) % app.rndata.n_cluster_groups;
Cluster_Group_Info &cg_info = app.rndata.cluster_groups[page_list_idx];
app.viewer.latest_page_list_gone_to = page_list_idx;
viewer_jump_to(app.viewer, cg_info.rng_page_list.start);
}
2024-07-19 14:31:48 +00:00
internal
void viewer_jump_to_cluster(App_State &app, u64 cluster_idx)
{
assert(app.rndata.n_clusters > 0);
cluster_idx = (cluster_idx + app.rndata.n_clusters) % app.rndata.n_clusters;
2024-07-23 08:43:28 +00:00
// @Speed: this is slow! Consider an acceleration structure, or maybe we can reuse
// Page_Info_Groups + binary search? (depends on whether cluster_idx are sorted)
2024-07-19 14:31:48 +00:00
Page_Info_Node *page = app.rndata.pages;
for (u64 i = 0; i < app.rndata.n_pages; ++i) {
if (page->cluster_id == cluster_idx)
break;
page = page->next;
assert(page);
}
app.viewer.highlighted_cluster = cluster_idx;
viewer_jump_to(app.viewer, page->range.start);
}
2024-07-10 19:47:37 +00:00
internal
2024-07-11 12:59:59 +00:00
void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
2024-07-10 17:38:16 +00:00
{
2024-07-11 14:29:44 +00:00
accum_dt_ms(app.delta_time_accum, delta_time_ms);
2024-07-11 12:00:43 +00:00
2024-07-10 17:38:16 +00:00
ImGui::SetNextWindowPos({ 0, 0 });
ImGui::SetNextWindowSize({ (f32)app.win_data.width, (f32)app.win_data.height });
2024-07-10 18:11:42 +00:00
Temp scratch = scratch_begin(&arena, 1);
defer { scratch_end(scratch); };
2024-07-10 18:11:42 +00:00
2024-07-11 12:27:19 +00:00
const auto main_win_flags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoDecoration;
if (ImGui::Begin("main", nullptr, main_win_flags)) {
2024-07-11 12:59:59 +00:00
2024-07-12 09:58:55 +00:00
String8 ntpl_desc = rntuple_description(scratch.arena, app.rndata);
2024-07-18 13:32:32 +00:00
ImGui::Text("RNTuple '%s' (%s) from file \"%s\"", app.ntpl_name.c(), ntpl_desc.c(), app.inspected_file.name.c());
2024-07-11 12:59:59 +00:00
2024-07-11 13:27:38 +00:00
// Draw stats
2024-07-11 12:59:59 +00:00
{
ImGui::SameLine();
f32 avg_dt = calc_avg_dt_ms(app.delta_time_accum);
2024-07-12 09:58:55 +00:00
String8 mem_used = to_pretty_size(scratch.arena, arena->mem_used);
String8 mem_peak = to_pretty_size(scratch.arena, arena->mem_peak_used);
String8 stat_txt = push_str8f(scratch.arena, "mem used: %s (peak: %s) | avg dt: %.1f",
mem_used.c(), mem_peak.c(), avg_dt);
2024-07-11 13:27:38 +00:00
f32 pos_x = (ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(stat_txt.c()).x
2024-07-11 12:59:59 +00:00
- ImGui::GetScrollX() - 2 * ImGui::GetStyle().ItemSpacing.x);
if (pos_x > ImGui::GetCursorPosX())
ImGui::SetCursorPosX(pos_x);
2024-07-11 13:27:38 +00:00
ImGui::Text("%s", stat_txt.c());
2024-07-11 12:59:59 +00:00
}
2024-07-11 12:27:19 +00:00
ImGui::Separator();
2024-07-11 12:59:59 +00:00
// Draw main content
2024-07-11 12:27:19 +00:00
{
2024-07-19 14:31:48 +00:00
const i64 step_i64 = 1;
2024-07-18 15:43:44 +00:00
ImGui::BeginTable("Hex View", 2, ImGuiTableFlags_Resizable);
2024-07-11 12:27:19 +00:00
ImGui::TableNextColumn();
2024-07-12 08:07:27 +00:00
2024-07-16 12:34:51 +00:00
assert(app.viewer.base_display_addr < app.inspected_file.size);
void *content = app.inspected_file.mem + app.viewer.base_display_addr;
u64 content_size = app.inspected_file.size - app.viewer.base_display_addr;
2024-07-15 09:54:45 +00:00
app.last_pinfo = &invalid_pinfo;
app.viewer.mem_edit.DrawContents(content, content_size, app.viewer.base_display_addr);
2024-07-11 12:27:19 +00:00
ImGui::TableNextColumn();
2024-07-12 08:07:27 +00:00
ImGuiColorEditFlags flags = ImGuiColorEditFlags_NoInputs|ImGuiColorEditFlags_NoLabel;
2024-07-18 13:32:32 +00:00
ImGui::ColorEdit3("_TFile Header", app.viewer.col_tfile_header, flags);
2024-07-12 08:07:27 +00:00
ImGui::SameLine();
2024-07-18 13:32:32 +00:00
if (ImGui::Button("TFile Header")) viewer_jump_to(app.viewer, 0);
ImGui::ColorEdit3("_TFile Object", app.viewer.col_tfile_obj, flags);
ImGui::SameLine();
if (ImGui::Button("TFile Object")) viewer_jump_to(app.viewer, app.tfile_data.rng_root_file_obj.start);
2024-07-18 15:43:44 +00:00
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.tfile_data.rng_root_file_obj.len).c());
2024-07-12 08:07:27 +00:00
2024-07-18 13:56:55 +00:00
ImGui::ColorEdit3("_TFile Info", app.viewer.col_tfile_info, flags);
ImGui::SameLine();
if (ImGui::Button("TFile Info")) viewer_jump_to(app.viewer, app.tfile_data.rng_root_file_info.start);
2024-07-18 15:43:44 +00:00
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.tfile_data.rng_root_file_info.len).c());
2024-07-18 13:56:55 +00:00
ImGui::ColorEdit3("_TFile FreeList", app.viewer.col_tfile_free, flags);
ImGui::SameLine();
if (ImGui::Button("TFile FreeList")) viewer_jump_to(app.viewer, app.tfile_data.rng_root_file_free.start);
2024-07-18 15:43:44 +00:00
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.tfile_data.rng_root_file_free.len).c());
2024-07-18 13:56:55 +00:00
2024-07-16 12:34:51 +00:00
ImGui::ColorEdit3("_RNTuple Anchor", app.viewer.col_anchor, flags);
ImGui::SameLine();
if (ImGui::Button("RNTuple Anchor")) viewer_jump_to(app.viewer, app.rndata.rng_anchor.start);
2024-07-12 08:07:27 +00:00
ImGui::SameLine();
2024-07-16 12:34:51 +00:00
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.rng_anchor.len).c());
2024-07-12 08:07:27 +00:00
2024-07-16 12:34:51 +00:00
ImGui::ColorEdit3("_RNTuple Header", app.viewer.col_header, flags);
2024-07-12 08:07:27 +00:00
ImGui::SameLine();
2024-07-16 12:34:51 +00:00
if (ImGui::Button("RNTuple Header")) viewer_jump_to(app.viewer, app.rndata.rng_header.start);
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.rng_header.len).c());
2024-07-12 08:07:27 +00:00
2024-07-16 12:34:51 +00:00
ImGui::ColorEdit3("_RNTuple Footer", app.viewer.col_footer, flags);
ImGui::SameLine();
if (ImGui::Button("RNTuple Footer")) viewer_jump_to(app.viewer, app.rndata.rng_footer.start);
2024-07-12 08:07:27 +00:00
ImGui::SameLine();
2024-07-16 12:34:51 +00:00
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.rng_footer.len).c());
2024-07-12 08:07:27 +00:00
2024-07-16 12:34:51 +00:00
ImGui::ColorEdit3("_TKey Header", app.viewer.col_key, flags);
2024-07-12 08:07:27 +00:00
ImGui::SameLine();
2024-07-15 13:54:22 +00:00
if (ImGui::Button("TKey Header")) {} // TODO jump to next key
2024-07-16 12:34:51 +00:00
ImGui::ColorEdit3("_Page Start", app.viewer.col_page_start, flags);
2024-07-15 13:54:22 +00:00
ImGui::SameLine();
2024-07-16 12:34:51 +00:00
if (ImGui::Button("Page Start")) viewer_jump_to_page(app, 0);
2024-07-15 13:54:22 +00:00
2024-07-16 12:34:51 +00:00
ImGui::ColorEdit3("_Page", app.viewer.col_page, flags);
ImGui::SameLine();
if (ImGui::Button("Page")) viewer_jump_to_page(app, app.viewer.latest_page_gone_to);
2024-07-15 16:02:55 +00:00
ImGui::SameLine();
{
2024-07-19 14:31:48 +00:00
const i64 step_fast_i64 = app.rndata.n_pages / 100;
i64 page_to_go_to = app.viewer.latest_page_gone_to;
2024-07-15 16:02:55 +00:00
ImGui::PushItemWidth(100.f);
2024-07-19 14:31:48 +00:00
if (ImGui::InputScalar("##page_viewed", ImGuiDataType_S64, &page_to_go_to, &step_i64, &step_fast_i64, "%u"))
2024-07-16 12:34:51 +00:00
viewer_jump_to_page(app, page_to_go_to);
2024-07-15 16:02:55 +00:00
ImGui::PopItemWidth();
}
2024-07-16 12:34:51 +00:00
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.tot_page_size).c());
2024-07-11 12:27:19 +00:00
2024-07-16 12:34:51 +00:00
ImGui::ColorEdit3("_Checksum", app.viewer.col_checksum, flags);
2024-07-16 10:04:38 +00:00
ImGui::SameLine();
if (ImGui::Button("Checksum")) {} // TODO jump to next checksum
2024-07-16 12:34:51 +00:00
ImGui::ColorEdit3("_Page List", app.viewer.col_page_list, flags);
ImGui::SameLine();
2024-07-18 15:43:44 +00:00
if (ImGui::Button("Page List")) viewer_jump_to_page_list(app, app.viewer.latest_page_list_gone_to);
ImGui::SameLine();
{
2024-07-19 14:31:48 +00:00
i64 page_list_to_go_to = app.viewer.latest_page_list_gone_to;
2024-07-18 15:43:44 +00:00
ImGui::PushItemWidth(80.f);
2024-07-19 14:31:48 +00:00
if (ImGui::InputScalar("##page_list_viewed", ImGuiDataType_S64, &page_list_to_go_to, &step_i64, nullptr, "%u"))
2024-07-18 15:43:44 +00:00
viewer_jump_to_page_list(app, page_list_to_go_to);
ImGui::PopItemWidth();
}
2024-07-16 12:34:51 +00:00
ImGui::SameLine();
ImGui::Text("%s", to_pretty_size(scratch.arena, app.rndata.tot_page_list_size).c());
2024-07-23 08:41:55 +00:00
ImGui::ColorEdit3("_TKey List", app.viewer.col_tkeys_list, flags);
ImGui::SameLine();
if (ImGui::Button("TKey List")) viewer_jump_to(app.viewer, app.rndata.rng_tkeys_list.start);
// -------------------------------
2024-07-12 16:29:35 +00:00
ImGui::Separator();
2024-07-18 13:32:32 +00:00
String8 root_version_str = push_str8f(scratch.arena, "%u.%u.%u",
app.tfile_data.root_version_major,
app.tfile_data.root_version_minor,
app.tfile_data.root_version_patch);
ImGui::Text("ROOT version: %s", root_version_str.c());
2024-07-18 13:56:55 +00:00
ImGui::Text("TFile compression: %u", app.tfile_data.compression);
2024-07-12 16:29:35 +00:00
ImGui::Text("Num pages: %lu", app.rndata.n_pages);
ImGui::Text("Num elements: %lu", app.rndata.n_elems);
2024-07-19 14:31:48 +00:00
{
const i64 step_fast_i64 = app.rndata.n_clusters / 100;
i64 cluster_to_highlight = app.viewer.highlighted_cluster;
ImGui::PushItemWidth(100.f);
if (ImGui::InputScalar("##highlighted_cluster", ImGuiDataType_S64, &cluster_to_highlight, &step_i64, &step_fast_i64, "%u")) {
viewer_jump_to_cluster(app, cluster_to_highlight);
}
ImGui::PopItemWidth();
ImGui::SameLine();
ImGui::Checkbox("Highlight cluster", &app.viewer.highlight_cluster);
}
2024-07-11 12:27:19 +00:00
ImGui::EndTable();
}
2024-07-11 12:00:43 +00:00
2024-07-10 17:38:16 +00:00
ImGui::End();
}
}