From 0c16435b8f832f8d35158630c1f501134bd4747b Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Thu, 15 Jul 2021 15:55:30 -0500 Subject: [PATCH] restructuring the project a little bit --- {src => data}/test_console.onyx | 0 src/app.onyx | 351 ++++++++++++++++++++++++++++ src/build.onyx | 6 +- src/main.onyx | 393 +------------------------------- src/ui/window.onyx | 2 +- src/wasm.onyx | 87 +++++++ 6 files changed, 452 insertions(+), 387 deletions(-) rename {src => data}/test_console.onyx (100%) create mode 100644 src/app.onyx create mode 100644 src/wasm.onyx diff --git a/src/test_console.onyx b/data/test_console.onyx similarity index 100% rename from src/test_console.onyx rename to data/test_console.onyx diff --git a/src/app.onyx b/src/app.onyx new file mode 100644 index 0000000..cc78e11 --- /dev/null +++ b/src/app.onyx @@ -0,0 +1,351 @@ +package app + +use package core + +#private_file events :: package js_events +#private_file gl :: package gl +#private_file gfx :: package immediate_mode +#private_file ui :: package ui +#private_file config :: package config +#private_file wasm :: package wasm_utils + +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); + +analyzer_state : Wasm_Analyzer_State; + +init :: () { + debug_init(); + + gl.init("main_canvas"); + events.init(); + gfx.immediate_renderer_init(); + + ui.init_ui(); + + map.init(^on_file_load_callbacks); + + color_file := events.request_file(config.color_scheme_file); + map.put(^on_file_load_callbacks, color_file, load_colors); + + load_background_tile_texture(); + load_fonts(); + + search_buffer = string.buffer_make(memory.make_slice(u8, 256)); + + gl.enable(gl.BLEND); + gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + + analyzer_state->init(); + + load_background_tile_texture :: () { + background_tile_texture = gfx.load_texture(32, 32, #file_contents "res/images/background_tile.data", gl.RGB, gl.RGB); + gl.bindTexture(gl.TEXTURE_2D, background_tile_texture.texture); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); + + gl.bindTexture(gl.TEXTURE_2D, -1); + } + + load_colors :: (event: ^events.Event) { + json :: package json + + assert(event.kind == .FileRequest, "Bad event type"); + assert(event.file.status == .Success, "Failed to load color file"); + + color_data := memory.make_slice(u8, event.file.size); + defer if color_data.count > 0 do cfree(color_data.data); + events.get_requested_file_data(event.file.file_id, color_data); + + arena := alloc.arena.make(context.allocator, 4096); + defer alloc.arena.free(^arena); + colors := json.decode(color_data, alloc.arena.make_allocator(^arena)); + defer json.free(colors); + + config.Colors.dark_background = decode_color(colors.root["dark_background"]); + config.Colors.background = decode_color(colors.root["background"]); + config.Colors.foreground = decode_color(colors.root["foreground"]); + + config.Colors.keyword = decode_color(colors.root["keyword"]); + config.Colors.value = decode_color(colors.root["value"]); + config.Colors.jumppoint = decode_color(colors.root["jumppoint"]); + + config.Colors.primary = decode_color(colors.root["primary"]); + config.Colors.primary_light = decode_color(colors.root["primary_light"]); + config.Colors.primary_dark = decode_color(colors.root["primary_dark"]); + config.Colors.primary_text = decode_color(colors.root["primary_text"]); + + config.Colors.secondary = decode_color(colors.root["secondary"]); + config.Colors.secondary_light = decode_color(colors.root["secondary_light"]); + config.Colors.secondary_dark = decode_color(colors.root["secondary_dark"]); + config.Colors.secondary_text = decode_color(colors.root["secondary_text"]); + + decode_color :: (v: ^json.Value) -> gfx.Color4 { + return .{ + r = ~~v[0]->as_float(), + g = ~~v[1]->as_float(), + b = ~~v[2]->as_float(), + }; + } + + analyzer_state->init(); + + debug_log(.Info, "Successfully loaded colorscheme.", null); + } + + load_fonts :: () { + use type_info; + + // Dumb check to see if the array is uninitialized + if fonts_loading.capacity == 0 do array.init(^fonts_loading, 4); + + fonts_info := cast(^Type_Info_Struct) get_type_info(config.Fonts_Container); + for ^member: fonts_info.members { + info := cast(^Type_Info_Struct) get_type_info(member.type); + + font_name := member.name; + + font_index := *cast(^i32) info.parameters[0].data; + fnt_file_name := *cast(^str) info.parameters[1].data; + tex_file_name := *cast(^str) info.parameters[2].data; + + debug_log(.Info, "Loading font '{}' with index {} from '{}' and '{}'\n", font_name, font_index, fnt_file_name, tex_file_name); + + fnt_file_id := events.request_file(fnt_file_name); + tex_file_id := events.request_file(tex_file_name); + + map.put(^on_file_load_callbacks, fnt_file_id, font_file_loaded); + map.put(^on_file_load_callbacks, tex_file_id, font_file_loaded); + + array.push(^fonts_loading, .{ font_index, font_name, fnt_file_id, tex_file_id }); + } + + Loading_Font :: struct { + font_index : u32; + font_name : str; + + fnt_file_id : u32; + tex_file_id : u32; + + fnt_file_size := cast(u32) 0; + tex_file_size := cast(u32) 0; + } + #persist fonts_loading : [..] Loading_Font; + + font_file_loaded :: (ev: ^events.Event) { + lf: ^Loading_Font = null; + + for ^entry: fonts_loading { + if entry.fnt_file_id == ev.file.file_id { entry.fnt_file_size = ev.file.size; lf = entry; } + if entry.tex_file_id == ev.file.file_id { entry.tex_file_size = ev.file.size; lf = entry; } + } + + assert(lf != null, "Loaded a file for a font that was not registered."); + + if lf.fnt_file_size > 0 && lf.tex_file_size > 0 { + fnt_data := memory.make_slice(u8, lf.fnt_file_size); + tex_data := memory.make_slice(u8, lf.tex_file_size); + defer { + cfree(fnt_data.data); + cfree(tex_data.data); + } + + @ErrorHandling + assert(events.get_requested_file_data(lf.fnt_file_id, fnt_data), "Failed to get bmfont file data."); + assert(events.get_requested_file_data(lf.tex_file_id, tex_data), "Failed to get texture data."); + + font := ui.create_font(fnt_data, tex_data); + ui.register_font(lf.font_index, font); + + debug_log(.Info, "Successfully loaded font '{}'.", lf.font_name); + + ui.use_font(lf.font_index); + } + } + } +} + +handle_event :: (event: ^events.Event) { + switch event.kind { + case .MouseDown do switch event.mouse.button { + case .Left do ui.button_pressed(.Left); + case .Right do ui.button_pressed(.Right); + case .Middle do ui.button_pressed(.Middle); + } + + case .MouseUp do switch event.mouse.button { + case .Left do ui.button_released(.Left); + case .Right do ui.button_released(.Right); + case .Middle do ui.button_released(.Middle); + } + + case .MouseMove do ui.update_mouse_position(~~ event.mouse.pos_x, ~~ event.mouse.pos_y); + + case .MouseWheel do switch event.mouse.button { + case .WheelUp do ui.button_pressed(.WheelUp); + case .WheelDown do ui.button_pressed(.WheelDown); + } + + case .KeyDown, .KeyUp { + modifiers : ui.Keyboard_State.Key_Event.Modifiers; + if event.keyboard.modifiers & .CTRL do modifiers |= .CTRL; + if event.keyboard.modifiers & .ALT do modifiers |= .ALT; + if event.keyboard.modifiers & .META do modifiers |= .META; + if event.keyboard.modifiers & .SHIFT do modifiers |= .SHIFT; + + if event.kind == .KeyDown { + ui.key_down(event.keyboard.keycode, modifiers); @KeycodeIsWrong // .keycode is apparently not browser independent... + + if event.keyboard->get_name() == "F5" { + refresh :: () -> void #foreign "decompiler" "refresh" --- + refresh(); + break; + } + + if event.keyboard->get_name() == "F7" { + debug_log_y_offset_target = 1 - debug_log_y_offset_target; + break; + } + + if event.keyboard->get_name() == "Tab" { + toggle_sidebar(^analyzer_state); + break; + } + + } else { + ui.key_up(event.keyboard.keycode, modifiers); @KeycodeIsWrong // see above + } + } + + case .Resize { + gl.setSize(event.resize.width, event.resize.height); + gfx.set_window_size(event.resize.width, event.resize.height); + } + + case .FileRequest { + if f := map.get(^on_file_load_callbacks, event.file.file_id); f != null_proc { + f(event); + + } else { + printf("Warning: No callback set for file id {}.\n", event.file.file_id); + } + } + + case .FileDropped { + debug_log(.Info, "File with size {} and status {} was dropped.\n", event.file.size, event.file.status); + + wasm_data := memory.make_slice(u8, event.file.size); + events.get_requested_file_data(event.file.file_id, wasm_data); + + // This transfers ownership of wasm_data to the analyzer_state + load_wasm_binary(^analyzer_state, wasm_data); + } + } +} + +update :: (dt: f32) { +} + +draw :: () { + bg_color := config.Colors.background; + gl.clearColor(bg_color.r, bg_color.g, bg_color.b, bg_color.a); + gl.clear(gl.COLOR_BUFFER_BIT); + + window_width, window_height := gfx.get_window_size(); + window_rectangle := ui.Rectangle.{ 0, 0, ~~window_width, ~~window_height }; + menu_bar, main_area := ui.Flow.split_horizontal(window_rectangle, top_height=32); + + ui.workspace_start(main_area); + draw_background_lines(~~window_width, ~~window_height, line_color=config.Colors.background); + + ui.draw_rect(0, 0, 20, 20, color=.{1,0,0}); + + ui.workspace_end(); + + draw_sidebar(^analyzer_state); + + // Menu bar drawing + { + gfx.push_matrix(); + defer gfx.pop_matrix(); + + gfx.identity(); + 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); + } + } + + 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 + + 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 background_tile_texture : gfx.Texture; diff --git a/src/build.onyx b/src/build.onyx index a651694..0ad8357 100644 --- a/src/build.onyx +++ b/src/build.onyx @@ -13,11 +13,15 @@ #load "modules/bmfont/module" #load "src/main" + + #load "src/app" + #load "src/wasm" + #load "src/ui/window" #load "src/debug_log" } #if (package runtime).Runtime == (package runtime).Runtime_Wasi { - #load "src/test_console" + #load "data/test_console" } diff --git a/src/main.onyx b/src/main.onyx index 6974ab9..1500686 100644 --- a/src/main.onyx +++ b/src/main.onyx @@ -1,74 +1,19 @@ -use package core - #private_file events :: package js_events -#private_file gl :: package gl -#private_file gfx :: package immediate_mode -#private_file ui :: package ui #private_file config :: package config -#private_file wasm :: package wasm_utils - -use package debug { init as debug_init, debug_log, draw_debug_log } - -search_buffer: string.String_Buffer; -background_tile_texture : gfx.Texture; -on_file_load_callbacks : map.Map(u32, (file_event: ^events.Event) -> void); - -wasm_data : [] u8; - -debug_log_y_offset := 0.0f; -debug_log_y_scroll := 0.0f; -debug_log_y_offset_target := 0.0f; +#private_file app :: package app main :: (args: [] cstr) { - init(); + app.init(); start_loop :: () -> void #foreign "decompiler" "start_loop" --- start_loop(); } -init :: () { - debug_init(); - - gl.init("main_canvas"); - events.init(); - gfx.immediate_renderer_init(); - - ui.init_ui(); - - map.init(^on_file_load_callbacks); - - color_file := events.request_file(config.color_scheme_file); - map.put(^on_file_load_callbacks, color_file, load_colors); - - load_fonts(); - - search_buffer = string.buffer_make(memory.make_slice(u8, 256)); - - gl.enable(gl.BLEND); - gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - - { - background_tile_texture = gfx.load_texture(32, 32, #file_contents "res/images/background_tile.data", gl.RGB, gl.RGB); - gl.bindTexture(gl.TEXTURE_2D, background_tile_texture.texture); - - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); - - gl.bindTexture(gl.TEXTURE_2D, -1); - } - - test_window.size = .{ 800, 800 }; - test_window.border_width = 8.0f; -} - - -last_time := 0; #export "loop" () { time_now :: () -> i32 #foreign "decompiler" "time_now" --- ; + #persist last_time := 0; if last_time == 0 do last_time = time_now(); now := time_now(); @@ -77,346 +22,24 @@ last_time := 0; #if #defined(config.ONLY_UPDATE_ON_EVENTS) { if poll_events() { - update(dt); - draw(); + app.update(dt); + app.draw(); } } else { poll_events(); - update(dt); - draw(); + app.update(dt); + app.draw(); } } -@Temporary window_width := 0 -@Temporary window_height := 0 - poll_events :: () -> bool { had_event := false; for event: events.consume() { had_event = true; - switch event.kind { - case .MouseDown do switch event.mouse.button { - case .Left do ui.button_pressed(.Left); - case .Right do ui.button_pressed(.Right); - case .Middle do ui.button_pressed(.Middle); - } - - case .MouseUp do switch event.mouse.button { - case .Left do ui.button_released(.Left); - case .Right do ui.button_released(.Right); - case .Middle do ui.button_released(.Middle); - } - - case .MouseMove do ui.update_mouse_position(~~ event.mouse.pos_x, ~~ event.mouse.pos_y); - - case .MouseWheel do switch event.mouse.button { - case .WheelUp do ui.button_pressed(.WheelUp); - case .WheelDown do ui.button_pressed(.WheelDown); - } - - case .KeyDown, .KeyUp { - modifiers : ui.Keyboard_State.Key_Event.Modifiers; - if event.keyboard.modifiers & .CTRL do modifiers |= .CTRL; - if event.keyboard.modifiers & .ALT do modifiers |= .ALT; - if event.keyboard.modifiers & .META do modifiers |= .META; - if event.keyboard.modifiers & .SHIFT do modifiers |= .SHIFT; - - if event.kind == .KeyDown { - ui.key_down(event.keyboard.keycode, modifiers); @KeycodeIsWrong // .keycode is apparently not browser independent... - - if event.keyboard->get_name() == "F5" { - refresh :: () -> void #foreign "decompiler" "refresh" --- - refresh(); - } - - if event.keyboard->get_name() == "F7" { - debug_log_y_offset_target = 1 - debug_log_y_offset_target; - } - - } else { - ui.key_up(event.keyboard.keycode, modifiers); @KeycodeIsWrong // see above - } - } - - case .Resize { - window_width = event.resize.width; - window_height = event.resize.height; - - gl.setSize(event.resize.width, event.resize.height); - gfx.set_window_size(event.resize.width, event.resize.height); - } - - case .FileRequest { - if f := map.get(^on_file_load_callbacks, event.file.file_id); f != null_proc { - f(event); - - } else { - printf("Warning: No callback set for file id {}.\n", event.file.file_id); - } - } - - case .FileDropped { - debug_log(.Info, "File with size {} and status {} was dropped.\n", event.file.size, event.file.status); - - if wasm_data.count > 0 do memory.free_slice(^wasm_data); - - wasm_data = memory.make_slice(u8, event.file.size); - events.get_requested_file_data(event.file.file_id, wasm_data); - - wasm_module := wasm.load(wasm_data); - defer wasm.free(^wasm_module); - - for ^entry: wasm_module.sections.entries { - debug_log(.Info, "Section: {}\nOffset: {}\n", entry.key, entry.value); - } - - wasm_sections := wasm.parse_sections(^wasm_module); - for instr: wasm.instruction_iterator(^wasm_module, ^wasm_sections.code_section[1]) { - debug_log(.Info, "{}\n", instr); - } - } - } + app.handle_event(event); } return had_event; } - -update :: (dt: f32) { - t += dt; - - if ui.is_key_just_down(~~#char "L") { - color_file := events.request_file(config.color_scheme_file); - map.put(^on_file_load_callbacks, color_file, load_colors); - - debug_log(.Info, "Requested updated colorscheme.", null); - } -} - -t := 0.0f; -test_window : ui.Window_State; - -draw :: () { - bg_color := config.Colors.background; - gl.clearColor(bg_color.r, bg_color.g, bg_color.b, bg_color.a); - gl.clear(gl.COLOR_BUFFER_BIT); - - window_rectangle := ui.Rectangle.{ 0, 0, ~~window_width, ~~window_height }; - menu_bar, main_area := ui.Flow.split_horizontal(window_rectangle, top_height=32); - - ui.workspace_start(main_area); - draw_background_lines(~~window_width, ~~window_height, line_color=config.Colors.background); - - ui.draw_rect(0, 0, 20, 20, color=.{1,0,0}); - - { - test_window.position = .{ 200, 200 }; - - ui.window_start(^test_window); - defer ui.window_end(); - - test_button_theme := ui.default_button_theme; - test_button_theme.font = config.Fonts.Calibri.index; - - if ui.button(.{ 0, 0, 400, 300 }, "Top-Left", theme=^test_button_theme) do search_buffer.count = 0; - ui.textbox(.{ 0, 300, 400, 350 }, ^search_buffer); - } - - ui.workspace_end(); - - { - gfx.push_matrix(); - defer gfx.pop_matrix(); - - gfx.identity(); - draw_menu_bar(^menu_bar); - } - - { - 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); - } - } - - gfx.flush(); - ui.end_frame(); -} - -#private_file -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); -} - -#private_file -draw_background_lines :: (width: f32, height: f32, line_color := gfx.Color4.{0.2, 0.2, 0.2}, line_spacing := 32.0f) { - gl :: package gl - - 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(); -} - - -@Relocate -#private_file -load_colors :: (event: ^events.Event) { - json :: package json - - assert(event.kind == .FileRequest, "Bad event type"); - assert(event.file.status == .Success, "Failed to load color file"); - - color_data := memory.make_slice(u8, event.file.size); - defer if color_data.count > 0 do cfree(color_data.data); - events.get_requested_file_data(event.file.file_id, color_data); - - arena := alloc.arena.make(context.allocator, 4096); - defer alloc.arena.free(^arena); - colors := json.decode(color_data, alloc.arena.make_allocator(^arena)); - defer json.free(colors); - - config.Colors.dark_background = decode_color(colors.root["dark_background"]); - config.Colors.background = decode_color(colors.root["background"]); - config.Colors.foreground = decode_color(colors.root["foreground"]); - - config.Colors.keyword = decode_color(colors.root["keyword"]); - config.Colors.value = decode_color(colors.root["value"]); - config.Colors.jumppoint = decode_color(colors.root["jumppoint"]); - - config.Colors.primary = decode_color(colors.root["primary"]); - config.Colors.primary_light = decode_color(colors.root["primary_light"]); - config.Colors.primary_dark = decode_color(colors.root["primary_dark"]); - config.Colors.primary_text = decode_color(colors.root["primary_text"]); - - config.Colors.secondary = decode_color(colors.root["secondary"]); - config.Colors.secondary_light = decode_color(colors.root["secondary_light"]); - config.Colors.secondary_dark = decode_color(colors.root["secondary_dark"]); - config.Colors.secondary_text = decode_color(colors.root["secondary_text"]); - - decode_color :: (v: ^json.Value) -> gfx.Color4 { - return .{ - r = ~~v[0]->as_float(), - g = ~~v[1]->as_float(), - b = ~~v[2]->as_float(), - }; - } - - @Temporary - test_window.border_color = config.Colors.primary; - test_window.background_color = config.Colors.dark_background; - test_window.active_color = config.Colors.background; - - debug_log(.Info, "Successfully loaded colorscheme.", null); -} - -@Relocate -#private_file -load_fonts :: () { - use type_info; - - // Dumb check to see if the array is uninitialized - if fonts_loading.capacity == 0 do array.init(^fonts_loading, 4); - - fonts_info := cast(^Type_Info_Struct) get_type_info(config.Fonts_Container); - for ^member: fonts_info.members { - info := cast(^Type_Info_Struct) get_type_info(member.type); - - font_name := member.name; - - font_index := *cast(^i32) info.parameters[0].data; - fnt_file_name := *cast(^str) info.parameters[1].data; - tex_file_name := *cast(^str) info.parameters[2].data; - - debug_log(.Info, "Loading font '{}' with index {} from '{}' and '{}'\n", font_name, font_index, fnt_file_name, tex_file_name); - - fnt_file_id := events.request_file(fnt_file_name); - tex_file_id := events.request_file(tex_file_name); - - map.put(^on_file_load_callbacks, fnt_file_id, font_file_loaded); - map.put(^on_file_load_callbacks, tex_file_id, font_file_loaded); - - array.push(^fonts_loading, .{ font_index, font_name, fnt_file_id, tex_file_id }); - } - - Loading_Font :: struct { - font_index : u32; - font_name : str; - - fnt_file_id : u32; - tex_file_id : u32; - - fnt_file_size := cast(u32) 0; - tex_file_size := cast(u32) 0; - } - #persist fonts_loading : [..] Loading_Font; - - font_file_loaded :: (ev: ^events.Event) { - lf: ^Loading_Font = null; - - for ^entry: fonts_loading { - if entry.fnt_file_id == ev.file.file_id { entry.fnt_file_size = ev.file.size; lf = entry; } - if entry.tex_file_id == ev.file.file_id { entry.tex_file_size = ev.file.size; lf = entry; } - } - - assert(lf != null, "Loaded a file for a font that was not registered."); - - if lf.fnt_file_size > 0 && lf.tex_file_size > 0 { - fnt_data := memory.make_slice(u8, lf.fnt_file_size); - tex_data := memory.make_slice(u8, lf.tex_file_size); - defer { - cfree(fnt_data.data); - cfree(tex_data.data); - } - - @ErrorHandling - assert(events.get_requested_file_data(lf.fnt_file_id, fnt_data), "Failed to get bmfont file data."); - assert(events.get_requested_file_data(lf.tex_file_id, tex_data), "Failed to get texture data."); - - font := ui.create_font(fnt_data, tex_data); - ui.register_font(lf.font_index, font); - - debug_log(.Info, "Successfully loaded font '{}'.", lf.font_name); - - ui.use_font(lf.font_index); - } - } -} \ No newline at end of file diff --git a/src/ui/window.onyx b/src/ui/window.onyx index 221cfbc..7e76953 100644 --- a/src/ui/window.onyx +++ b/src/ui/window.onyx @@ -49,7 +49,7 @@ window_start :: (use state: ^Window_State, site := #callsite, increment := 0) { gfx.push_scissor(x, y, w, h); gfx.push_matrix(); - gfx.apply_transform(.{ translation = position, scale = .{ 1, 1 } }); + gfx.apply_transform(.{ translation = .{ x, y }, scale = .{ 1, 1 } }); } window_end :: () { diff --git a/src/wasm.onyx b/src/wasm.onyx new file mode 100644 index 0000000..1ef66c9 --- /dev/null +++ b/src/wasm.onyx @@ -0,0 +1,87 @@ +package app + +use package core + +#private_file ui :: package ui +#private_file gfx :: package immediate_mode +#private_file config :: package config +#private_file wasm :: package wasm_utils + +use package core.intrinsics.onyx { __initialize } + +Wasm_Analyzer_State :: struct { + allocator := context.allocator; + + wasm_data : [] u8; + wasm_binary : wasm.WasmBinary; + wasm_sections : wasm.WasmSections; + + windows : map.Map(u32, ui.Window_State); + + sidebar_window := ui.Window_State.{ .{0,0}, .{400,400} }; + sidebar_expansion := 0.0f; + sidebar_expansion_target := 0.0f; + + init :: (use state: ^Wasm_Analyzer_State) { + __initialize(state); + + sidebar_window.border_width = 0; + sidebar_window.border_color = .{ 0, 0, 0 }; + sidebar_window.background_color = config.Colors.dark_background; + sidebar_window.active_color = config.Colors.background; + } +} + +load_wasm_binary :: (use state: ^Wasm_Analyzer_State, @transfers_ownership data: [] u8) { + if wasm_data.count > 0 do memory.free_slice(^wasm_data); + + wasm_data = data; + wasm_binary = wasm.load(wasm_data, allocator); + wasm_sections = wasm.parse_sections(^wasm_binary, allocator); +} + +toggle_sidebar :: (use state: ^Wasm_Analyzer_State) { + sidebar_expansion_target = 1 - sidebar_expansion_target; +} + +draw_sidebar :: (use state: ^Wasm_Analyzer_State, y_offset := 32.0f) { + ui.move_towards(^sidebar_expansion, sidebar_expansion_target, 0.08f); + if sidebar_expansion <= 0.0f do return; + + window_width, window_height := gfx.get_window_size(); + sidebar_window.position = .{ (sidebar_expansion - 1) * sidebar_window.size.x, y_offset }; + sidebar_window.size.y = ~~window_height - y_offset; + + sidebar_rectangle := ui.Rectangle.{ 0, 0, sidebar_window.size.x, sidebar_window.size.y }; + + ui.window_start(^sidebar_window); + defer ui.window_end(); + + #persist x_scroll := 0.0f; + #persist y_scroll := 0.0f; + + ui.scrollable_region_start(sidebar_rectangle, ^x_scroll, ^y_scroll); + defer ui.scrollable_region_stop(); + + if wasm_data.count == 0 { + ui.draw_text(.{ 0, 0, sidebar_window.size.x, 50 }, "No loaded WASM binary."); + return; + } + + @HACK @HACK @HACK + sidebar_rectangle.y1 += 100000.0f; + + text_buffer : [512] u8; + text_rect : ui.Rectangle; + button_rect : ui.Rectangle; + + text_rect, sidebar_rectangle = ui.Flow.split_horizontal(sidebar_rectangle, top_height=50); + s := conv.str_format("Function count: {}\n", ~~text_buffer, wasm_sections.code_section.count); + ui.draw_text(text_rect, s); + + for i: wasm_sections.code_section.count { + button_rect, sidebar_rectangle = ui.Flow.split_horizontal(sidebar_rectangle, top_height=40); + ui.button(button_rect, conv.str_format("Function {}", ~~text_buffer, i), increment=i); + } +} + -- 2.25.1