Compare commits
No commits in common. "master" and "grouped" have entirely different histories.
9 changed files with 174 additions and 237 deletions
|
@ -10,7 +10,8 @@ $ git clone --recurse-submodules <repo_url>
|
|||
```
|
||||
|
||||
### Dependencies
|
||||
rntviewer currently only fully works on Linux, with the terminal-only version working on MacOS as well.
|
||||
rntviewer currently only fully works on Linux, with the terminal-only version working
|
||||
on MacOS as well (PRs welcome).
|
||||
|
||||
The dependencies are:
|
||||
- GLFW3 (`libglfw3-dev` on debian, `glfw-devel` on fedora, `glfw` on arch)
|
||||
|
@ -19,7 +20,7 @@ The dependencies are:
|
|||
|
||||
Other than those, rntviewer depends on Dear ImGui and GLAD (both included in the source tree).
|
||||
|
||||
For the graphical version, the OS must support OpenGL 3.3 or higher.
|
||||
The machine must support OpenGL 3.3 or higher.
|
||||
|
||||
For the terminal-only version you don't need GLFW3, ImGui or OpenGL support.
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ struct Inspected_File {
|
|||
|
||||
String8 name;
|
||||
|
||||
// @Platform: inotify file descriptor
|
||||
// @Platform: inotify file descriptor
|
||||
int inot;
|
||||
};
|
||||
|
||||
|
@ -29,8 +29,8 @@ struct App_State {
|
|||
Viewer viewer;
|
||||
#endif
|
||||
|
||||
String8 ntpl_name;
|
||||
u64 base_display_addr;
|
||||
String8 ntpl_name;
|
||||
u64 base_display_addr;
|
||||
|
||||
Delta_Time_Accum delta_time_accum;
|
||||
|
||||
|
@ -44,6 +44,6 @@ size_t file_size(FILE *f)
|
|||
fseek(f, 0, SEEK_END);
|
||||
size_t res = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ struct Defer_Guard {
|
|||
F _f;
|
||||
};
|
||||
struct Defer_Guard_Helper {
|
||||
template <typename F>
|
||||
Defer_Guard<F> operator+(F&& f) { return Defer_Guard<F>(static_cast<F &&>(f)); }
|
||||
template <typename F>
|
||||
Defer_Guard<F> operator+(F&& f) { return Defer_Guard<F>(static_cast<F &&>(f)); }
|
||||
};
|
||||
|
||||
#define CONCAT_STR_INTERNAL(A, B) A##B
|
||||
|
|
136
src/hover.cpp
136
src/hover.cpp
|
@ -124,15 +124,12 @@ using Display_Range_Fn = String8_Node *(*)(Arena *, String8_Node *, const char *
|
|||
|
||||
enum Hover_Section_Flags {
|
||||
HoverSec_None = 0,
|
||||
// Hide = don't show at all, even the title
|
||||
HoverSec_HideIfNotHovered = 1,
|
||||
// Collapse = only show the title
|
||||
HoverSec_CollapseIfNotHovered = 2,
|
||||
};
|
||||
|
||||
// Functor used by get_section_hover_info to describe the structure of a section and print data about it.
|
||||
struct Sec_Hover_Fn {
|
||||
u64 off; // the hovered offset relative to the start of `data`
|
||||
u64 off; // the offset relative to the start of `data`
|
||||
const u8 *data; // the entire file data
|
||||
const Section §ion;
|
||||
Arena *arena;
|
||||
|
@ -142,20 +139,6 @@ struct Sec_Hover_Fn {
|
|||
u8 cur_section_nesting = 0;
|
||||
u8 innermost_section_highlighted = 0;
|
||||
|
||||
template <typename T>
|
||||
b8 read(T *val, u64 offset, u64 *size = nullptr) const
|
||||
{
|
||||
u64 nb = size ? *size : sizeof(T);
|
||||
if (offset + nb > section.range.end()) {
|
||||
fprintf(stderr, "Trying to read bytes 0x%" PRIX64 "-0x%" PRIX64 " which are past the end of the section 0x%" PRIX64 "!\n",
|
||||
offset, offset + nb, section.range.end());
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(val, data + offset, nb);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void titled_section(const char *title, F &&sec_body_fn, u64 flags = 0)
|
||||
{
|
||||
|
@ -167,19 +150,11 @@ struct Sec_Hover_Fn {
|
|||
|
||||
sec_body_fn();
|
||||
|
||||
// assert(cur_field_off >= sec_start);
|
||||
if (cur_field_off < sec_start) {// TEMP DEBUG
|
||||
fprintf(stderr, "Something wrong going on in %s!\n", title);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(cur_field_off >= sec_start);
|
||||
b8 hovered = off >= sec_start && off <= cur_field_off;
|
||||
|
||||
if (!hovered) {
|
||||
if (flags & HoverSec_HideIfNotHovered)
|
||||
pop_str8_node_child(prev_desc, info.desc);
|
||||
else if (flags & HoverSec_CollapseIfNotHovered)
|
||||
info.desc->first_child = info.desc->last_child = nullptr;
|
||||
if (!hovered & (flags & HoverSec_HideIfNotHovered)) {
|
||||
pop_str8_node_child(prev_desc, info.desc);
|
||||
} else if (display_grouped) {
|
||||
// if we're in display_grouped mode, we want to highlight the entire range of the section;
|
||||
u64 sec_len = cur_field_off - sec_start;
|
||||
|
@ -211,9 +186,7 @@ struct Sec_Hover_Fn {
|
|||
b8 hovered = cur_field_off <= off && off < cur_field_off + field_len;
|
||||
|
||||
T val;
|
||||
if (!read(&val, cur_field_off))
|
||||
return false;
|
||||
|
||||
memcpy(&val, (u8 *)data + cur_field_off, field_len);
|
||||
String8_Node *desc = display_val(arena, info.desc, desc_fmt, val);
|
||||
if (hovered && !display_grouped)
|
||||
info.highlighted_desc = desc;
|
||||
|
@ -232,9 +205,7 @@ struct Sec_Hover_Fn {
|
|||
{
|
||||
// String size can be stored as different types, like u8 (by ROOT I/O) or u32 (by RNTuple).
|
||||
TStrSize str_size;
|
||||
if (!read(&str_size, cur_field_off))
|
||||
return;
|
||||
|
||||
memcpy(&str_size, data + cur_field_off, sizeof(TStrSize));
|
||||
// DEBUG
|
||||
if (str_size > 1000) {
|
||||
printf("read str_size = %u at offset 0x%lX!\n", str_size, cur_field_off);
|
||||
|
@ -244,10 +215,7 @@ struct Sec_Hover_Fn {
|
|||
b8 hovered = cur_field_off <= off && off < cur_field_off + field_len;
|
||||
|
||||
u8 *buf = arena_push_array_nozero<u8>(arena, str_size + 1);
|
||||
u64 size_to_read = str_size;
|
||||
if (!read(buf, cur_field_off + sizeof(TStrSize), &size_to_read))
|
||||
return;
|
||||
|
||||
memcpy(buf, data + cur_field_off + sizeof(TStrSize), str_size);
|
||||
buf[str_size] = 0;
|
||||
String8 s = { buf, str_size };
|
||||
String8_Node *desc = display_val(arena, info.desc, desc_fmt, s);
|
||||
|
@ -276,8 +244,6 @@ struct Sec_Hover_Fn {
|
|||
void range(const char *desc, u64 range_len, Display_Range_Fn display_val = hover_display_generic_range)
|
||||
{
|
||||
b8 hovered = cur_field_off <= off && off < cur_field_off + range_len;
|
||||
if (cur_field_off + range_len > section.range.end())
|
||||
return;
|
||||
String8_Node *dsc = display_val(arena, info.desc, desc, data + cur_field_off, range_len);
|
||||
if (hovered && !display_grouped)
|
||||
info.highlighted_desc = dsc;
|
||||
|
@ -291,15 +257,13 @@ struct Sec_Hover_Fn {
|
|||
// Returns true if `was_zipped` was read.
|
||||
b8 maybe_rootzip(b8 *was_zipped = nullptr)
|
||||
{
|
||||
// TODO boundary checks
|
||||
const u64 range_len = 9;
|
||||
if (cur_field_off + range_len > section.range.end())
|
||||
return false;
|
||||
|
||||
b8 hovered = cur_field_off <= off && off < cur_field_off + range_len;
|
||||
if (display_val_rootzip(arena, info.desc, "Zipped Block", data + cur_field_off)) {
|
||||
if (was_zipped)
|
||||
*was_zipped = true;
|
||||
if (display_grouped || hovered) {
|
||||
if (was_zipped)
|
||||
*was_zipped = true;
|
||||
info.rng = { cur_field_off, range_len };
|
||||
if (hovered)
|
||||
info.highlighted_desc = info.desc;
|
||||
|
@ -316,9 +280,7 @@ struct Sec_Hover_Fn {
|
|||
{
|
||||
titled_section(title, [this] {
|
||||
u16 version_be;
|
||||
if (!read(&version_be, cur_field_off + 4))
|
||||
return;
|
||||
|
||||
memcpy(&version_be, data + cur_field_off + 4, sizeof(u16));
|
||||
u32 version = bswap(version_be);
|
||||
b8 is_big = version > 1000;
|
||||
|
||||
|
@ -356,7 +318,7 @@ struct Sec_Hover_Fn {
|
|||
range("Envelope size: %s", 6, [] (Arena *arena, String8_Node *prev, const char *fmt, const u8 *payload, u64) {
|
||||
u64 size;
|
||||
memcpy(&size, payload, 6);
|
||||
return push_str8_node_child(arena, prev, fmt, to_pretty_size(arena, size).c());
|
||||
return push_str8_node_child(arena, prev, fmt, to_pretty_size(arena, size));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -364,12 +326,7 @@ struct Sec_Hover_Fn {
|
|||
enum Frame_Type {
|
||||
Frame_INVALID,
|
||||
Frame_Record,
|
||||
Frame_List,
|
||||
Frame_COUNT
|
||||
};
|
||||
|
||||
static constexpr const char *frame_type_str[Frame_COUNT] = {
|
||||
"INVALID", "Record", "List"
|
||||
Frame_List
|
||||
};
|
||||
|
||||
Frame_Type frame_header(u64 &size, u32 *n_items = nullptr, const char *title = nullptr)
|
||||
|
@ -378,11 +335,7 @@ struct Sec_Hover_Fn {
|
|||
Frame_Type frame_type = Frame_INVALID;
|
||||
titled_section(titlestr.c(), [this, &frame_type, &frame_size = size, n_items] {
|
||||
i64 size;
|
||||
if (!read(&size, cur_field_off)) {
|
||||
frame_size = 0;
|
||||
frame_type = Frame_INVALID;
|
||||
return;
|
||||
}
|
||||
memcpy(&size, data + cur_field_off, sizeof(size));
|
||||
// Sanity check
|
||||
if (size > 1000000) {
|
||||
fprintf(stderr, "Frame size read at 0x%" PRIX64 " looks bogus"
|
||||
|
@ -404,11 +357,7 @@ struct Sec_Hover_Fn {
|
|||
frame_type = Frame_INVALID;
|
||||
} else {
|
||||
frame_type = Frame_List;
|
||||
if (!read(n_items, cur_field_off + sizeof(i64))) {
|
||||
frame_size = 0;
|
||||
frame_type = Frame_INVALID;
|
||||
return;
|
||||
}
|
||||
memcpy(n_items, data + cur_field_off + sizeof(i64), sizeof(u32));
|
||||
field<i64>("List frame size: %" PRIi64 " B", hover_display_val_le_abs<i64>);
|
||||
field_le<u32>("List frame n.items: %u");
|
||||
}
|
||||
|
@ -450,7 +399,7 @@ struct Sec_Hover_Fn {
|
|||
field_str8<u32>("Type Name: %s");
|
||||
field_str8<u32>("Type Alias: %s");
|
||||
field_str8<u32>("Description: %s");
|
||||
});
|
||||
}, HoverSec_HideIfNotHovered);
|
||||
}
|
||||
|
||||
void column_desc(const char *title)
|
||||
|
@ -475,15 +424,13 @@ struct Sec_Hover_Fn {
|
|||
field_le<double>("Value Min: %f");
|
||||
field_le<double>("Value Max: %f");
|
||||
}
|
||||
});
|
||||
}, HoverSec_HideIfNotHovered);
|
||||
}
|
||||
|
||||
void schema_description(const char *title)
|
||||
{
|
||||
titled_section(title, [this] {
|
||||
frame<Frame_List>("Fields", [this] (u32 idx) {
|
||||
field_desc(push_str8f(arena, "Field %u", idx).c());
|
||||
});
|
||||
frame<Frame_List>("Fields", [this] (u32 idx) { field_desc(push_str8f(arena, "Field %u", idx).c()); });
|
||||
frame<Frame_List>("Columns", [this] (u32 idx) { column_desc(push_str8f(arena, "Column %u", idx).c()); });
|
||||
frame<Frame_List>("Alias Columns", [this] (u32 idx) {
|
||||
frame<Frame_Record>(push_str8f(arena, "Alias Column %u", idx).c(), [this] {
|
||||
|
@ -557,7 +504,7 @@ struct Sec_Hover_Fn {
|
|||
|
||||
void cluster_group()
|
||||
{
|
||||
frame<Frame_Record>("Cluster Group", [this] {
|
||||
frame<Frame_List>("Cluster Group", [this] (u32) {
|
||||
field_le<u64>("Min Entry: %" PRIu64);
|
||||
field_le<u64>("Entry Span: %" PRIu64);
|
||||
field_le<u32>("N Clusters: %u");
|
||||
|
@ -598,7 +545,7 @@ struct Sec_Hover_Fn {
|
|||
b8 has_checksum = n_elems < 0;
|
||||
push_str8_node_child(arena, info.desc, "Has Checksum: %s", has_checksum ? "yes" : "no");
|
||||
locator("Element Locator");
|
||||
});
|
||||
}, HoverSec_HideIfNotHovered);
|
||||
}
|
||||
|
||||
i64 n_cols;
|
||||
|
@ -614,12 +561,12 @@ struct Sec_Hover_Fn {
|
|||
if (n_cols >= 0)
|
||||
field_le<i32>("Compression Settings: %d");
|
||||
});
|
||||
});
|
||||
}, HoverSec_HideIfNotHovered);
|
||||
});
|
||||
}
|
||||
|
||||
template <Frame_Type FType, typename F>
|
||||
void frame(const char *title, F &&frame_body_fn, u64 sec_flags = HoverSec_CollapseIfNotHovered)
|
||||
void frame(const char *title, F &&frame_body_fn, u64 sec_flags = 0)
|
||||
{
|
||||
u64 start_off = cur_field_off;
|
||||
u64 size;
|
||||
|
@ -627,11 +574,8 @@ struct Sec_Hover_Fn {
|
|||
titled_section(title, [this, title, start_off, &size, &frame_body_fn] {
|
||||
u32 n_items = 0;
|
||||
Frame_Type ftype = frame_header(size, &n_items);
|
||||
if (ftype != FType) {
|
||||
fprintf(stderr, "Frame %s was supposed to be of type %s but it's of type %s\n",
|
||||
title, frame_type_str[FType], frame_type_str[ftype]);
|
||||
if (ftype != FType)
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (FType == Frame_List) {
|
||||
// Sadness here.
|
||||
|
@ -681,8 +625,7 @@ struct Sec_Hover_Fn {
|
|||
{
|
||||
titled_section("TFile Header", [this] {
|
||||
u32 root_version_be;
|
||||
if (!read(&root_version_be, cur_field_off + 4))
|
||||
return;
|
||||
memcpy(&root_version_be, data + cur_field_off + 4, sizeof(u32));
|
||||
u32 root_version = bswap(root_version_be);
|
||||
b8 is_big = root_version > 1000'000;
|
||||
|
||||
|
@ -722,8 +665,7 @@ struct Sec_Hover_Fn {
|
|||
field_str8<u8>("File Title: %s");
|
||||
|
||||
u16 version_be;
|
||||
if (!read(&version_be, cur_field_off))
|
||||
return;
|
||||
memcpy(&version_be, data + cur_field_off, sizeof(u16));
|
||||
u16 version = bswap(version_be);
|
||||
b8 is_big = version > 1000;
|
||||
|
||||
|
@ -779,8 +721,7 @@ struct Sec_Hover_Fn {
|
|||
titled_section("TFile FreeList", [this] {
|
||||
tkey();
|
||||
u16 version_be;
|
||||
if (!read(&version_be, cur_field_off))
|
||||
return;
|
||||
memcpy(&version_be, data + cur_field_off, sizeof(u16));
|
||||
u32 version = bswap(version_be);
|
||||
b8 is_big = version > 1000;
|
||||
|
||||
|
@ -853,6 +794,7 @@ struct Sec_Hover_Fn {
|
|||
if (zipped) {
|
||||
// XXX: why -1?
|
||||
range("Compressed payload", section.range.len - section.post_size - sizeof(u64) - 1);
|
||||
field_le<u64>("Checksum: 0x%" PRIX64);
|
||||
} else {
|
||||
envelope_preamble();
|
||||
// NOTE: flags in principle require a more complex handling, but for now they are unused,
|
||||
|
@ -862,8 +804,8 @@ struct Sec_Hover_Fn {
|
|||
field_str8<u32>("Description: %s");
|
||||
field_str8<u32>("ROOT version: %s");
|
||||
schema_description("Schema Description");
|
||||
field_le<u64>("Checksum: 0x%" PRIX64);
|
||||
}
|
||||
field_le<u64>("Checksum: 0x%" PRIX64);
|
||||
}, HoverSec_HideIfNotHovered);
|
||||
});
|
||||
}
|
||||
|
@ -880,23 +822,20 @@ struct Sec_Hover_Fn {
|
|||
if (zipped) {
|
||||
// XXX: why -1?
|
||||
range("Payload", section.range.len - section.post_size - sizeof(u64) - 1);
|
||||
field_le<u64>("Checksum: 0x%" PRIX64);
|
||||
} else {
|
||||
envelope_preamble();
|
||||
// TODO: flags in principle require a more complex handling, but for now they are unused,
|
||||
// NOTE: flags in principle require a more complex handling, but for now they are unused,
|
||||
// so they're always occupying only 8 bytes.
|
||||
field_le<u64>("Flags: 0x%" PRIX64);
|
||||
field_le<u64>("Header checksum: 0x%" PRIX64);
|
||||
frame<Frame_Record>("Schema Extension", [this] {
|
||||
schema_description("Schema Extension");
|
||||
});
|
||||
frame<Frame_List>("Column Groups", [this] (u32) {
|
||||
field_le<u32>("Column Id: %u");
|
||||
});
|
||||
frame<Frame_List>("Cluster Groups", [this] (u32) {
|
||||
cluster_group();
|
||||
});
|
||||
schema_description("Schema Extension");
|
||||
// NOTE: Column groups are currently unused, so this should always be empty
|
||||
frame<Frame_List>("Column Groups", [] (u32) {});
|
||||
frame<Frame_List>("Cluster Groups", [this] (u32) { cluster_group(); });
|
||||
range("Payload", section.range.len - cur_field_off);
|
||||
field_le<u64>("Checksum: 0x%" PRIX64);
|
||||
}
|
||||
field_le<u64>("Checksum: 0x%" PRIX64);
|
||||
}, HoverSec_HideIfNotHovered);
|
||||
});
|
||||
}
|
||||
|
@ -924,13 +863,13 @@ struct Sec_Hover_Fn {
|
|||
if (zipped) {
|
||||
// XXX: why -1?
|
||||
range("Payload", section.range.len - section.post_size - sizeof(u64) - 1);
|
||||
field_le<u64>("Checksum: 0x%" PRIX64);
|
||||
} else {
|
||||
envelope_preamble();
|
||||
field_le<u64>("Header checksum: 0x%" PRIX64);
|
||||
frame<Frame_List>("Cluster Summaries", [this] (u32) { cluster_summary(); });
|
||||
frame<Frame_List>("Clusters", [this] (u32) { cluster(); });
|
||||
}
|
||||
field_le<u64>("Checksum: 0x%" PRIX64);
|
||||
}, HoverSec_HideIfNotHovered);
|
||||
});
|
||||
}
|
||||
|
@ -999,7 +938,6 @@ Sec_Hover_Info get_section_hover_info(Arena *arena, Section section, u64 off, co
|
|||
break;
|
||||
|
||||
case Sec_TKey_List:
|
||||
printf("0x%lX - 0x%lX (pre %lu)\n", section.range.start, section.range.end(), section.pre_size);
|
||||
hover.tkey_list();
|
||||
break;
|
||||
|
||||
|
|
182
src/mainloop.cpp
182
src/mainloop.cpp
|
@ -1,63 +1,63 @@
|
|||
internal
|
||||
b8 init_imgui(GLFWwindow* window) {
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void) io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.IniFilename = nullptr;
|
||||
io.LogFilename = nullptr;
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void) io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.IniFilename = nullptr;
|
||||
io.LogFilename = nullptr;
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 330");
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 330");
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal
|
||||
void glfw_error_callback(i32 error, const char *description) {
|
||||
fprintf(stderr, "GLFW error %d: %s\n", error, description);
|
||||
fprintf(stderr, "GLFW error %d: %s\n", error, description);
|
||||
}
|
||||
|
||||
internal
|
||||
GLFWwindow *init_glfw(i32 desired_win_width, i32 desired_win_height)
|
||||
{
|
||||
glfwSetErrorCallback(glfw_error_callback);
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_DECORATED, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_DEPTH_BITS, 32);
|
||||
glfwSetErrorCallback(glfw_error_callback);
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_DECORATED, GLFW_TRUE);
|
||||
glfwWindowHint(GLFW_DEPTH_BITS, 32);
|
||||
#ifndef NDEBUG
|
||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
|
||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
|
||||
#endif
|
||||
|
||||
GLFWwindow *window = glfwCreateWindow(
|
||||
desired_win_width, desired_win_height,
|
||||
"RNTuple Viewer " V_MAJOR "." V_MINOR,
|
||||
nullptr,
|
||||
nullptr
|
||||
);
|
||||
GLFWwindow *window = glfwCreateWindow(
|
||||
desired_win_width, desired_win_height,
|
||||
"RNTuple Viewer " V_MAJOR "." V_MINOR,
|
||||
nullptr,
|
||||
nullptr
|
||||
);
|
||||
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
return window;
|
||||
return window;
|
||||
}
|
||||
|
||||
internal
|
||||
void monitor_key(GLFWwindow *window, u8 *key_state, i32 glfw_key, Input_Key key) {
|
||||
u8 &state = key_state[key];
|
||||
if (glfwGetKey(window, glfw_key) == GLFW_PRESS) {
|
||||
if (!(state & KEY_STATE_IS_DOWN)) state |= KEY_STATE_JUST_PRESSED;
|
||||
state |= KEY_STATE_IS_DOWN;
|
||||
} else if (glfwGetKey(window, glfw_key) == GLFW_RELEASE) {
|
||||
if (state & KEY_STATE_IS_DOWN) state |= KEY_STATE_JUST_RELEASED;
|
||||
state &= ~KEY_STATE_IS_DOWN;
|
||||
}
|
||||
u8 &state = key_state[key];
|
||||
if (glfwGetKey(window, glfw_key) == GLFW_PRESS) {
|
||||
if (!(state & KEY_STATE_IS_DOWN)) state |= KEY_STATE_JUST_PRESSED;
|
||||
state |= KEY_STATE_IS_DOWN;
|
||||
} else if (glfwGetKey(window, glfw_key) == GLFW_RELEASE) {
|
||||
if (state & KEY_STATE_IS_DOWN) state |= KEY_STATE_JUST_RELEASED;
|
||||
state &= ~KEY_STATE_IS_DOWN;
|
||||
}
|
||||
}
|
||||
|
||||
internal
|
||||
|
@ -85,75 +85,75 @@ void run_main_loop(GLFWwindow *window, Arena *arena, App_State &app)
|
|||
app.delta_time_accum.base = arena_push_array<f32>(arena, app.delta_time_accum.max);
|
||||
|
||||
while (!app.should_quit) {
|
||||
chr::time_point frame_start = chr::high_resolution_clock::now();
|
||||
u64 time_since_prev_frame_us = chr::duration_cast<chr::microseconds>(frame_start - last_saved_time).count();
|
||||
delta_time_ms = time_since_prev_frame_us * 0.001f;
|
||||
last_saved_time = frame_start;
|
||||
chr::time_point frame_start = chr::high_resolution_clock::now();
|
||||
u64 time_since_prev_frame_us = chr::duration_cast<chr::microseconds>(frame_start - last_saved_time).count();
|
||||
delta_time_ms = time_since_prev_frame_us * 0.001f;
|
||||
last_saved_time = frame_start;
|
||||
|
||||
for (u32 i = 0; i < MOUSE_BTN_COUNT; ++i)
|
||||
app.user_input.mouse_btn_state[i] &= ~(MOUSE_BTN_STATE_JUST_PRESSED|MOUSE_BTN_STATE_JUST_RELEASED);
|
||||
for (u32 i = 0; i < MOUSE_BTN_COUNT; ++i)
|
||||
app.user_input.mouse_btn_state[i] &= ~(MOUSE_BTN_STATE_JUST_PRESSED|MOUSE_BTN_STATE_JUST_RELEASED);
|
||||
|
||||
glfwPollEvents();
|
||||
glfwPollEvents();
|
||||
|
||||
// Update window size
|
||||
{
|
||||
Window_Data &wdata = app.win_data;
|
||||
// Update window size
|
||||
{
|
||||
Window_Data &wdata = app.win_data;
|
||||
|
||||
i32 prev_width = wdata.width;
|
||||
i32 prev_height = wdata.height;
|
||||
i32 prev_width = wdata.width;
|
||||
i32 prev_height = wdata.height;
|
||||
|
||||
glfwGetWindowSize(window, &wdata.width, &wdata.height);
|
||||
glfwGetWindowSize(window, &wdata.width, &wdata.height);
|
||||
|
||||
wdata.size_just_changed = prev_width != wdata.width || prev_height != wdata.height;
|
||||
}
|
||||
wdata.size_just_changed = prev_width != wdata.width || prev_height != wdata.height;
|
||||
}
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Check if the inspected file changed
|
||||
{
|
||||
char buf[sizeof(inotify_event) + NAME_MAX + 1];
|
||||
ssize_t nbytes = read(app.inspected_file.inot, buf, sizeof(buf));
|
||||
if (nbytes)
|
||||
app.inspected_file.size = file_size(app.inspected_file.stream);
|
||||
}
|
||||
// Check if the inspected file changed
|
||||
{
|
||||
char buf[sizeof(inotify_event) + NAME_MAX + 1];
|
||||
ssize_t nbytes = read(app.inspected_file.inot, buf, sizeof(buf));
|
||||
if (nbytes)
|
||||
app.inspected_file.size = file_size(app.inspected_file.stream);
|
||||
}
|
||||
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS || glfwWindowShouldClose(window)) {
|
||||
app.should_quit = true;
|
||||
break;
|
||||
}
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS || glfwWindowShouldClose(window)) {
|
||||
app.should_quit = true;
|
||||
break;
|
||||
}
|
||||
|
||||
b32 focused = glfwGetWindowAttrib(window, GLFW_FOCUSED);
|
||||
if (focused) {
|
||||
// Update keyboard
|
||||
u8 *key_state = app.user_input.key_state;
|
||||
monitor_key(window, key_state, GLFW_KEY_Q, KEY_Q);
|
||||
monitor_key(window, key_state, GLFW_KEY_UP, KEY_UP);
|
||||
monitor_key(window, key_state, GLFW_KEY_DOWN, KEY_DOWN);
|
||||
monitor_key(window, key_state, GLFW_KEY_LEFT, KEY_LEFT);
|
||||
monitor_key(window, key_state, GLFW_KEY_RIGHT, KEY_RIGHT);
|
||||
monitor_key(window, key_state, GLFW_KEY_LEFT_ALT, KEY_ALT);
|
||||
monitor_key(window, key_state, GLFW_KEY_TAB, KEY_TAB);
|
||||
monitor_key(window, key_state, GLFW_KEY_LEFT_SHIFT, KEY_SHIFT);
|
||||
b32 focused = glfwGetWindowAttrib(window, GLFW_FOCUSED);
|
||||
if (focused) {
|
||||
// Update keyboard
|
||||
u8 *key_state = app.user_input.key_state;
|
||||
monitor_key(window, key_state, GLFW_KEY_Q, KEY_Q);
|
||||
monitor_key(window, key_state, GLFW_KEY_UP, KEY_UP);
|
||||
monitor_key(window, key_state, GLFW_KEY_DOWN, KEY_DOWN);
|
||||
monitor_key(window, key_state, GLFW_KEY_LEFT, KEY_LEFT);
|
||||
monitor_key(window, key_state, GLFW_KEY_RIGHT, KEY_RIGHT);
|
||||
monitor_key(window, key_state, GLFW_KEY_LEFT_ALT, KEY_ALT);
|
||||
monitor_key(window, key_state, GLFW_KEY_TAB, KEY_TAB);
|
||||
monitor_key(window, key_state, GLFW_KEY_LEFT_SHIFT, KEY_SHIFT);
|
||||
|
||||
// Update mouse
|
||||
f64 mposx, mposy;
|
||||
glfwGetCursorPos(window, &mposx, &mposy);
|
||||
// Update mouse
|
||||
f64 mposx, mposy;
|
||||
glfwGetCursorPos(window, &mposx, &mposy);
|
||||
|
||||
u8 *mouse_btn_state = app.user_input.mouse_btn_state;
|
||||
monitor_mouse_btn(window, mouse_btn_state, GLFW_MOUSE_BUTTON_LEFT, MOUSE_BTN_LEFT);
|
||||
monitor_mouse_btn(window, mouse_btn_state, GLFW_MOUSE_BUTTON_RIGHT, MOUSE_BTN_RIGHT);
|
||||
u8 *mouse_btn_state = app.user_input.mouse_btn_state;
|
||||
monitor_mouse_btn(window, mouse_btn_state, GLFW_MOUSE_BUTTON_LEFT, MOUSE_BTN_LEFT);
|
||||
monitor_mouse_btn(window, mouse_btn_state, GLFW_MOUSE_BUTTON_RIGHT, MOUSE_BTN_RIGHT);
|
||||
|
||||
app.user_input.mouse_pos.x = static_cast<i32>(mposx);
|
||||
app.user_input.mouse_pos.y = static_cast<i32>(mposy);
|
||||
}
|
||||
app.user_input.mouse_pos.x = static_cast<i32>(mposx);
|
||||
app.user_input.mouse_pos.y = static_cast<i32>(mposy);
|
||||
}
|
||||
|
||||
update_and_render(arena, app, delta_time_ms);
|
||||
update_and_render(arena, app, delta_time_ms);
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
}
|
||||
|
|
18
src/prof.h
18
src/prof.h
|
@ -1,14 +1,14 @@
|
|||
struct Prof_Scope_Print {
|
||||
Prof_Scope_Print(const char *name) : scope_name { name }, scope_start_t { std::chrono::high_resolution_clock::now() } {}
|
||||
~Prof_Scope_Print() {
|
||||
using namespace std::chrono;
|
||||
time_point scope_end_t = high_resolution_clock::now();
|
||||
duration scope_duration = duration_cast<microseconds>(scope_end_t - scope_start_t);
|
||||
fprintf(stderr, "[profile] %s took %.4f ms\n", scope_name, scope_duration.count() * 0.001f);
|
||||
}
|
||||
Prof_Scope_Print(const char *name) : scope_name { name }, scope_start_t { std::chrono::high_resolution_clock::now() } {}
|
||||
~Prof_Scope_Print() {
|
||||
using namespace std::chrono;
|
||||
time_point scope_end_t = high_resolution_clock::now();
|
||||
duration scope_duration = duration_cast<microseconds>(scope_end_t - scope_start_t);
|
||||
fprintf(stderr, "[profile] %s took %.4f ms\n", scope_name, scope_duration.count() * 0.001f);
|
||||
}
|
||||
|
||||
const char *scope_name;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> scope_start_t;
|
||||
const char *scope_name;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> scope_start_t;
|
||||
};
|
||||
|
||||
#define TIMED_SCOPE() const Prof_Scope_Print CONCAT_STR(_prof, __LINE__) { __func__ }
|
||||
|
|
|
@ -618,9 +618,7 @@ Section find_section(App_State &app, u64 off, i64 hilite_cluster = -1)
|
|||
if (rdata.rng_tkeys_list.start <= off && off < rdata.rng_tkeys_list.end()) {
|
||||
sec.id = Sec_TKey_List;
|
||||
sec.range = rdata.rng_tkeys_list;
|
||||
// FIXME!
|
||||
// sec.range.len += rblob_sz;
|
||||
// printf("with rblob_sz: 0x%lX\n", sec.range.end());
|
||||
sec.pre_size = rblob_sz;
|
||||
return sec;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,10 +32,10 @@ String8 str8_from_c(const char *str)
|
|||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
internal
|
||||
|
|
46
src/window.h
46
src/window.h
|
@ -1,26 +1,26 @@
|
|||
enum Input_Key {
|
||||
KEY_UP,
|
||||
KEY_DOWN,
|
||||
KEY_LEFT,
|
||||
KEY_RIGHT,
|
||||
KEY_Q,
|
||||
KEY_ALT,
|
||||
KEY_TAB,
|
||||
KEY_SHIFT,
|
||||
KEY_UP,
|
||||
KEY_DOWN,
|
||||
KEY_LEFT,
|
||||
KEY_RIGHT,
|
||||
KEY_Q,
|
||||
KEY_ALT,
|
||||
KEY_TAB,
|
||||
KEY_SHIFT,
|
||||
|
||||
KEY_COUNT
|
||||
KEY_COUNT
|
||||
};
|
||||
|
||||
enum Key_State : u8 {
|
||||
KEY_STATE_IS_DOWN = 0x1,
|
||||
KEY_STATE_JUST_PRESSED = 0x2,
|
||||
KEY_STATE_JUST_RELEASED = 0x4,
|
||||
KEY_STATE_IS_DOWN = 0x1,
|
||||
KEY_STATE_JUST_PRESSED = 0x2,
|
||||
KEY_STATE_JUST_RELEASED = 0x4,
|
||||
};
|
||||
|
||||
enum Mouse_Button {
|
||||
MOUSE_BTN_LEFT,
|
||||
MOUSE_BTN_RIGHT,
|
||||
MOUSE_BTN_COUNT
|
||||
MOUSE_BTN_LEFT,
|
||||
MOUSE_BTN_RIGHT,
|
||||
MOUSE_BTN_COUNT
|
||||
};
|
||||
|
||||
enum Mouse_Button_State : u8 {
|
||||
|
@ -30,18 +30,18 @@ enum Mouse_Button_State : u8 {
|
|||
};
|
||||
|
||||
struct User_Input {
|
||||
u8 key_state[KEY_COUNT];
|
||||
u8 mouse_btn_state[MOUSE_BTN_COUNT];
|
||||
u8 key_state[KEY_COUNT];
|
||||
u8 mouse_btn_state[MOUSE_BTN_COUNT];
|
||||
|
||||
struct { i32 x; i32 y; } mouse_pos;
|
||||
struct { i32 x; i32 y; } mouse_pos;
|
||||
};
|
||||
|
||||
struct Window_Data {
|
||||
// Real width and height of the window
|
||||
i32 width;
|
||||
i32 height;
|
||||
bool size_just_changed;
|
||||
// Real width and height of the window
|
||||
i32 width;
|
||||
i32 height;
|
||||
bool size_just_changed;
|
||||
|
||||
f32 desired_aspect_ratio;
|
||||
f32 desired_aspect_ratio;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue