#private_file ui :: package ui
#private_file config :: package config
#private_file wasm :: package wasm_utils
+#private_file debug :: package debug
use package debug { init as debug_init, debug_log, draw_debug_log }
use package core.intrinsics.onyx { __initialize }
@Relocate search_buffer: string.String_Buffer;
-debug_log_y_offset := 0.0f;
-debug_log_y_scroll := 0.0f;
-debug_log_y_offset_target := 0.0f;
-
background_tile_texture : gfx.Texture;
on_file_load_callbacks : map.Map(u32, (file_event: ^events.Event) -> void);
+// The global application state.
+state : Application_State;
+
Application_State :: struct {
- _: i32;
+ has_active_file := false;
+ file := Active_File.{};
+}
+
+Active_File :: struct {
+ name := (#type [] u8).{ null, 0 };
+ data := (#type [] u8).{ null, 0 };
}
init :: () {
debug_init();
+ __initialize(^state);
+
gl.init("main_canvas");
events.init();
gfx.immediate_renderer_init();
{
use type_info;
+ // Look through all the types in the program
for type: type_table {
if type.kind != .Struct do continue;
ts := cast(^Type_Info_Struct) type;
if !string.starts_with(ts.name, "Feature_") do continue;
+ // Any types that are a structure and start with "Feature_" will be dynamically loaded
+
debug_log(.Info, "Found feature '{}'", string.advance(ts.name, 8));
for ^member: ts.members {
}
if event.keyboard->get_name() == "F7" {
- debug_log_y_offset_target = 1 - debug_log_y_offset_target;
+ debug.debug_log_toggle();
break;
}
}
case .FileDropped {
- wasm_data := memory.make_slice(u8, event.file.size);
- name := memory.make_slice(u8, event.file.name_length, context.temp_allocator);
- events.get_requested_file_data(event.file.file_id, wasm_data, name);
+ data := memory.make_slice(u8, event.file.size);
+ name := memory.make_slice(u8, event.file.name_length);
+ events.get_requested_file_data(event.file.file_id, data, name);
debug_log(.Info, "File with size {} and name {} was dropped.\n", event.file.size, name);
- if !string.ends_with(name, ".wasm") {
- debug_log(.Warning, "A non-WASM file was dropped. Ignoring.", null);
- break;
+ if state.has_active_file {
+ memory.free_slice(^state.file.name);
+ memory.free_slice(^state.file.data);
}
+ state.has_active_file = true;
+ state.file.name = name;
+ state.file.data = data;
+
// This transfers ownership of wasm_data to the analyzer_state
// load_wasm_binary(^analyzer_state, wasm_data);
}
}
needs_redraw :: () -> bool {
- return ui.has_active_animation() || debug_log_y_offset != debug_log_y_offset_target;
+ return ui.has_active_animation() || debug.debug_log_transitioning();
}
update :: (dt: f32) {
+ debug.debug_log_update(dt);
}
draw :: () {
ui.draw_rect(0, 0, 20, 20, color=.{1,0,0});
+ {
+ #persist window_state := ui.Window_State.{ position=gfx.Vector2.{100, 100}, size=gfx.Vector2.{800, 600} };
+ ui.window_start(^window_state);
+ defer ui.window_end();
+
+ if state.has_active_file {
+ buffer: [512] u8;
+ name_text := conv.str_format("File name: {}", ~~buffer, state.file.name);
+ ui.draw_text(.{ 0, 0, 300, 200 }, name_text);
+
+ size_text := conv.str_format("File size: {} bytes", ~~buffer, state.file.data.count);
+ ui.draw_text(.{ 0, 32, 300, 200 }, size_text);
+
+ } else {
+ ui.draw_text(.{ 0, 0, 300, 200 }, "No file loaded.");
+ }
+ }
+
ui.workspace_end();
// draw_sidebar(^analyzer_state);
// Menu bar drawing
{
- gfx.push_matrix();
- defer gfx.pop_matrix();
+ #insert gfx.save_matrix;
gfx.identity();
ui.menubar(menu_bar, ^search_buffer, ~~ui.Menu_Bar_Option.[
.{ label = "File" },
.{ label = "Test" },
]);
- //draw_menu_bar(^menu_bar);
}
// Debug log drawing
- {
- ui.move_towards(^debug_log_y_offset, debug_log_y_offset_target, 0.07f);
-
- if debug_log_y_offset > 0.0f {
- top_half, _ := ui.Flow.split_horizontal(window_rectangle, top_percent=.5);
- height := ui.Rectangle.height(top_half);
- top_half.y0 -= height * (1 - debug_log_y_offset);
- top_half.y1 -= height * (1 - debug_log_y_offset);
- draw_debug_log(top_half, ^debug_log_y_scroll);
- }
- }
+ draw_debug_log(window_rectangle);
gfx.flush();
ui.end_frame();
- draw_menu_bar :: (menu_bar_: ^ui.Rectangle) {
- menu_bar := *menu_bar_;
- ui.draw_rect(menu_bar, color=config.Colors.background);
-
- menu_button_theme := ui.default_button_theme;
- menu_button_theme.border_width = 2;
- menu_button_theme.font_size = .9;
- menu_button_theme.font = 0;
-
- menu_textbox_theme := ui.default_textbox_theme;
- menu_textbox_theme.border_width = 2;
- menu_textbox_theme.font_size = .9;
-
- button_rect : ui.Rectangle;
-
- button_rect, menu_bar = ui.Flow.split_vertical(menu_bar, left_width=100);
- ui.button(button_rect, "File", theme=^menu_button_theme);
- button_rect, menu_bar = ui.Flow.split_vertical(menu_bar, left_width=100);
- ui.button(button_rect, "Edit", theme=^menu_button_theme);
- button_rect, menu_bar = ui.Flow.split_vertical(menu_bar, left_width=100);
- ui.button(button_rect, "View", theme=^menu_button_theme);
- button_rect, menu_bar = ui.Flow.split_vertical(menu_bar, left_width=100);
- ui.button(button_rect, "Help", theme=^menu_button_theme);
-
- _, search_rect := ui.Flow.split_vertical(menu_bar, right_width=300);
- ui.textbox(search_rect, ^search_buffer, "Search", theme=^menu_textbox_theme);
- }
-
draw_background_lines :: (width: f32, height: f32, line_color := gfx.Color4.{0.2, 0.2, 0.2}, line_spacing := 32.0f) {
gl :: package gl
+ #insert gfx.save_matrix;
+
trans := gfx.global_renderer->get_transform();
sx := trans.scale.x * line_spacing;
sy := trans.scale.y * line_spacing;
tx := -trans.translation.x / sx;
ty := -trans.translation.y / sy;
- gfx.push_matrix();
gfx.identity();
gfx.set_texture(^background_tile_texture);
gfx.textured_rect(.{ 0, 0 }, .{ width, height }, .{ tx, ty }, .{ width / sx, height / sy }, color=line_color);
gfx.set_texture();
- gfx.pop_matrix();
}
}
#private_file gfx :: package immediate_mode
#private_file config :: package config
+#private y_scroll := 0.0f;
+#private debug_log_y_offset := 0.0f;
+#private debug_log_y_offset_target := 0.0f;
+
init :: () {
log_buffer.line_arena = alloc.arena.make(context.allocator, 4096);
log_buffer.lines = array.make(str);
minimum_severity := Severity.Debug;
+debug_log_toggle :: () {
+ debug_log_y_offset_target = 1 - debug_log_y_offset;
+}
+
+debug_log_transitioning :: () -> bool {
+ return debug_log_y_offset != debug_log_y_offset_target;
+}
+
+debug_log_update :: (dt: f32) {
+ ui.move_towards(^debug_log_y_offset, debug_log_y_offset_target, 4 * dt);
+}
+
+debug_log_clear :: () {
+ array.clear(^log_buffer.lines);
+ alloc.arena.free(^log_buffer.line_arena);
+
+ log_buffer.line_arena = alloc.arena.make(context.allocator, 4096);
+}
+
debug_log :: (severity: Severity, format: str, args: ..any) {
if severity < minimum_severity do return;
}
}
-draw_debug_log :: (r: ui.Rectangle, y_scroll: ^f32 = null, site := #callsite) {
+draw_debug_log :: (window_rectangle: ui.Rectangle, site := #callsite) {
+ if debug_log_y_offset == 0.0f do return;
+
+ r, _ := ui.Flow.split_horizontal(window_rectangle, top_percent=.5);
+ height := ui.Rectangle.height(r);
+ r.y0 -= height * (1 - debug_log_y_offset);
+ r.y1 -= height * (1 - debug_log_y_offset);
+
hash := ui.get_site_hash(site);
mx, my := ui.get_mouse_position();
if ui.Rectangle.contains(r, mx, my) {
- ui.set_hot_item(hash);
+ ui.set_hot_item(hash, false);
}
line_spacing := 28.0f;
- if ui.is_hot_item(hash) && y_scroll != null {
- if ui.mouse_state.dwheel > 0 do *y_scroll -= 20.0f;
- if ui.mouse_state.dwheel < 0 do *y_scroll += 20.0f;
+ if ui.is_hot_item(hash) {
+ if ui.mouse_state.dwheel > 0 do y_scroll -= 20.0f;
+ if ui.mouse_state.dwheel < 0 do y_scroll += 20.0f;
- if ui.is_key_down(38) do *y_scroll -= 20.0f;
- if ui.is_key_down(40) do *y_scroll += 20.0f;
+ if ui.is_key_down(38) do y_scroll -= 20.0f;
+ if ui.is_key_down(40) do y_scroll += 20.0f;
}
x, y := ui.Rectangle.bottom_left(r);
ui.draw_rect(r, color=background_color);
scale :: 0.75f;
- y_offset := line_spacing * scale + *y_scroll;
+ y_offset := line_spacing * scale + y_scroll;
while i := log_buffer.lines.count - 1; cast(i32) i >= 0 {
defer i -= 1;
ui.draw_text_raw(log_buffer.lines[i], x, y - y_offset, color=.{ 0.2, 0.7, 0.2 }, font=1, size=scale);
y_offset += line_spacing * scale;
}
+
+ clear_button_rect := ui.Rectangle.{
+ x0 = r.x0, x1 = r.x0 + 200,
+ y0 = r.y0, y1 = r.y0 + 50,
+ };
+
+ if ui.button(clear_button_rect, "Clear log") {
+ debug_log_clear();
+ }
}
#private_file log_buffer : struct {