From 9cd0692e565e132eb65445a15e94ede59694c03a Mon Sep 17 00:00:00 2001 From: Ed_ Date: Wed, 22 May 2024 03:28:16 -0400 Subject: [PATCH] Got it to compile with sokol changes (UNTESTED) --- code/host/host.odin | 2 - code/sectr/app/state.odin | 3 + ...client_api.odin => client_api_raylib.odin} | 3 + code/sectr/engine/client_api_sokol.odin | 465 ++++++++++++++++++ .../engine/client_api_sokol_callbacks.odin | 115 +++++ code/sectr/{grime => engine}/logger.odin | 3 +- code/sectr/grime/stack.odin | 5 + scripts/update_deps.ps1 | 7 + 8 files changed, 600 insertions(+), 3 deletions(-) rename code/sectr/engine/{client_api.odin => client_api_raylib.odin} (99%) create mode 100644 code/sectr/engine/client_api_sokol.odin create mode 100644 code/sectr/engine/client_api_sokol_callbacks.odin rename code/sectr/{grime => engine}/logger.odin (96%) diff --git a/code/host/host.odin b/code/host/host.odin index 1a5dad9..d8ae4ae 100644 --- a/code/host/host.odin +++ b/code/host/host.odin @@ -351,7 +351,5 @@ main :: proc() log("Succesfuly closed") file_close( logger.file ) - // TODO(Ed) : Add string interning!!!!!!!!! - // file_rename( logger.file_path, path_logger_finalized ) file_rename( str_fmt_buffer( fmt_backing[:], "%s/sectr.log", Path_Logs), path_logger_finalized ) } diff --git a/code/sectr/app/state.odin b/code/sectr/app/state.odin index c2613e8..6c5ce8a 100644 --- a/code/sectr/app/state.odin +++ b/code/sectr/app/state.odin @@ -249,6 +249,9 @@ State :: struct { // The camera is considered the "context" for coodrinate space operations in rendering cam_context : Camera, + + // sokol_relay : SokolRelay, + sokol_context : runtime.Context, } get_state :: #force_inline proc "contextless" () -> ^ State { diff --git a/code/sectr/engine/client_api.odin b/code/sectr/engine/client_api_raylib.odin similarity index 99% rename from code/sectr/engine/client_api.odin rename to code/sectr/engine/client_api_raylib.odin index 408503f..96de5ce 100644 --- a/code/sectr/engine/client_api.odin +++ b/code/sectr/engine/client_api_raylib.odin @@ -12,6 +12,7 @@ import "core:time" import "core:prof/spall" import rl "vendor:raylib" +when false { Path_Assets :: "../assets/" Path_Shaders :: "../shaders/" Path_Input_Replay :: "scratch.sectr_replay" @@ -418,3 +419,5 @@ clean_frame :: proc() verify( alloc_error == .None, "Failed to allocate transient slab" ) } } + +} // when false \ No newline at end of file diff --git a/code/sectr/engine/client_api_sokol.odin b/code/sectr/engine/client_api_sokol.odin new file mode 100644 index 0000000..a42c151 --- /dev/null +++ b/code/sectr/engine/client_api_sokol.odin @@ -0,0 +1,465 @@ +package sectr + +import "base:runtime" +import c "core:c/libc" +import "core:dynlib" +import "core:mem" +import "core:mem/virtual" +import "core:os" +import "core:slice" +import "core:strings" +import "core:time" +import "core:prof/spall" + +import sokol_app "thirdparty:sokol/app" +import rl "vendor:raylib" + +Path_Assets :: "../assets/" +Path_Shaders :: "../shaders/" +Path_Input_Replay :: "scratch.sectr_replay" + +Persistent_Slab_DBG_Name := "Peristent Slab" +Frame_Slab_DBG_Name := "Frame Slab" +Transient_Slab_DBG_Name := "Transient Slab" + +ModuleAPI :: struct { + lib : dynlib.Library, + write_time : FileTime, + lib_version : i32, + + startup : type_of( startup ), + shutdown : type_of( sectr_shutdown ), + reload : type_of( reload ), + tick : type_of( tick ), + clean_frame : type_of( clean_frame ), +} + +@export +startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem, files_buffer_mem : ^VArena, host_logger : ^Logger ) +{ + spall.SCOPED_EVENT( & prof.ctx, & prof.buffer, #procedure ) + Memory_App.profiler = prof + + startup_tick := time.tick_now() + + logger_init( & Memory_App.logger, "Sectr", host_logger.file_path, host_logger.file ) + context.logger = to_odin_logger( & Memory_App.logger ) + + // Setup memory for the first time + { + using Memory_App; + persistent = persistent_mem + frame = frame_mem + transient = transient_mem + files_buffer = files_buffer_mem + + context.allocator = persistent_allocator() + context.temp_allocator = transient_allocator() + // TODO(Ed) : Put on the transient allocator a slab allocator (transient slab) + } + + state := new( State, persistent_allocator() ) + Memory_App.state = state + using state + + // Setup Persistent Slabs & String Cache + { + alignment := uint(mem.DEFAULT_ALIGNMENT) + + policy_ptr := & default_slab_policy + push( policy_ptr, SlabSizeClass { 128 * Kilobyte, 1 * Kilobyte, alignment }) + push( policy_ptr, SlabSizeClass { 256 * Kilobyte, 2 * Kilobyte, alignment }) + push( policy_ptr, SlabSizeClass { 512 * Kilobyte, 4 * Kilobyte, alignment }) + push( policy_ptr, SlabSizeClass { 1 * Megabyte, 16 * Kilobyte, alignment }) + push( policy_ptr, SlabSizeClass { 1 * Megabyte, 32 * Kilobyte, alignment }) + push( policy_ptr, SlabSizeClass { 1 * Megabyte, 64 * Kilobyte, alignment }) + push( policy_ptr, SlabSizeClass { 2 * Megabyte, 128 * Kilobyte, alignment }) + push( policy_ptr, SlabSizeClass { 2 * Megabyte, 256 * Kilobyte, alignment }) + push( policy_ptr, SlabSizeClass { 2 * Megabyte, 512 * Kilobyte, alignment }) + push( policy_ptr, SlabSizeClass { 2 * Megabyte, 1 * Megabyte, alignment }) + push( policy_ptr, SlabSizeClass { 2 * Megabyte, 2 * Megabyte, alignment }) + push( policy_ptr, SlabSizeClass { 4 * Megabyte, 4 * Megabyte, alignment }) + push( policy_ptr, SlabSizeClass { 8 * Megabyte, 8 * Megabyte, alignment }) + push( policy_ptr, SlabSizeClass { 16 * Megabyte, 16 * Megabyte, alignment }) + push( policy_ptr, SlabSizeClass { 32 * Megabyte, 32 * Megabyte, alignment }) + push( policy_ptr, SlabSizeClass { 64 * Megabyte, 64 * Megabyte, alignment }) + // push( policy_ptr, SlabSizeClass { 128 * Megabyte, 128 * Megabyte, alignment }) + // push( policy_ptr, SlabSizeClass { 256 * Megabyte, 256 * Megabyte, alignment }) + // push( policy_ptr, SlabSizeClass { 512 * Megabyte, 512 * Megabyte, alignment }) + + alloc_error : AllocatorError + persistent_slab, alloc_error = slab_init( policy_ptr, allocator = persistent_allocator(), dbg_name = Persistent_Slab_DBG_Name ) + verify( alloc_error == .None, "Failed to allocate the persistent slab" ) + + transient_slab, alloc_error = slab_init( & default_slab_policy, allocator = transient_allocator(), dbg_name = Transient_Slab_DBG_Name ) + verify( alloc_error == .None, "Failed to allocate transient slab" ) + + transient_clear_time = 120 // Seconds, 2 Minutes + + string_cache = str_cache_init() + } + + // Setup input frame poll references + input = & input_data[1] + input_prev = & input_data[0] + for & input in input_data { + using input + error : AllocatorError + keyboard_events.keys_pressed, error = array_init_reserve(KeyCode, persistent_slab_allocator(), Kilo) + ensure(error == AllocatorError.None, "Failed to allocate input.keyboard_events.keys_pressed array") + keyboard_events.chars_pressed, error = array_init_reserve(rune, persistent_slab_allocator(), Kilo) + ensure(error == AllocatorError.None, "Failed to allocate input.keyboard_events.chars_pressed array") + } + + // Configuration Load + // TODO(Ed): Make this actually load from an ini + { + using config + resolution_width = 1000 + resolution_height = 600 + refresh_rate = 0 + + cam_min_zoom = 0.10 + cam_max_zoom = 30.0 + cam_zoom_mode = .Smooth + cam_zoom_smooth_snappiness = 4.0 + cam_zoom_sensitivity_digital = 0.2 + cam_zoom_sensitivity_smooth = 4.0 + + engine_refresh_hz = 0 + + timing_fps_moving_avg_alpha = 0.9 + + ui_resize_border_width = 5 + + color_theme = App_Thm_Dusk + } + + Desired_OS_Scheduler_MS :: 1 + sleep_is_granular = set__scheduler_granularity( Desired_OS_Scheduler_MS ) + + // Setup for sokol_app + { + sokol_context = context + desc := sokol_app.Desc { + init_cb = sokol_app_init_callback, + frame_cb = sokol_app_frame_callback, + cleanup_cb = sokol_app_cleanup_callback, + event_cb = sokol_app_event_callback, + + width = cast(c.int) config.resolution_width, + height = cast(c.int) config.resolution_height, + + sample_count = 0, + // swap_interval = config.monitor_refresh_hz, + + high_dpi = false, + fullscreen = false, + alpha = false, + + window_title = "Sectr Prototype", + // icon = { sokol_app.sokol_default }, + + enable_clipboard = false, // TODO(Ed): Implmeent this + enable_dragndrop = false, // TODO(Ed): Implmeent this + + logger = { sokol_app_log_callback, nil }, + allocator = { sokol_app_alloc, sokol_app_free, nil }, + } + + sokol_app.pre_client_init(desc) + sokol_app.client_init() + + // rl.Odin_SetMalloc( RL_MALLOC ) + + // rl.SetConfigFlags( { + // rl.ConfigFlag.WINDOW_RESIZABLE, + // rl.ConfigFlag.WINDOW_TOPMOST, + // }) + + // window_width : i32 = cast(i32) config.resolution_width + // window_height : i32 = cast(i32) config.resolution_height + // win_title : cstring = "Sectr Prototype" + // rl.InitWindow( window_width, window_height, win_title ) + // log( "Raylib initialized and window opened" ) + + // window := & state.app_window + // window.extent.x = f32(window_width) * 0.5 + // window.extent.y = f32(window_height) * 0.5 + + // We do not support non-uniform DPI. + // window.dpi_scale = rl.GetWindowScaleDPI().x + // window.ppcm = os_default_ppcm * window.dpi_scale + + // Determining current monitor and setting the target frametime based on it.. + // monitor_id = rl.GetCurrentMonitor() + // monitor_refresh_hz = rl.GetMonitorRefreshRate( monitor_id ) + + // if config.engine_refresh_hz == 0 { + // config.engine_refresh_hz = uint(monitor_refresh_hz) + // } + } + + // Basic Font Setup + if false + { + font_provider_startup() + // path_rec_mono_semicasual_reg := strings.concatenate( { Path_Assets, "RecMonoSemicasual-Regular-1.084.ttf" }) + // font_rec_mono_semicasual_reg = font_load( path_rec_mono_semicasual_reg, 24.0, "RecMonoSemiCasual_Regular" ) + + // path_squidgy_slimes := strings.concatenate( { Path_Assets, "Squidgy Slimes.ttf" } ) + // font_squidgy_slimes = font_load( path_squidgy_slimes, 24.0, "Squidgy_Slime" ) + + path_firacode := strings.concatenate( { Path_Assets, "FiraCode-Regular.ttf" }, transient_allocator() ) + font_firacode = font_load( path_firacode, 24.0, "FiraCode" ) + default_font = font_firacode + log( "Default font loaded" ) + } + + // Setup the screen ui state + if false + { + ui_startup( & screen_ui.base, cache_allocator = persistent_slab_allocator() ) + ui_floating_startup( & screen_ui.floating, persistent_slab_allocator(), 1 * Kilobyte, 1 * Kilobyte, "screen ui floating manager" ) + + using screen_ui + menu_bar.pos = { -60, 0 } + // menu_bar.pos = Vec2(app_window.extent) * { -1, 1 } + menu_bar.size = {140, 40} + + settings_menu.min_size = {250, 200} + } + + // Demo project setup + // TODO(Ed): This will eventually have to occur when the user either creates or loads a workspace. I don't know + if false + { + using project + path = str_intern("./") + name = str_intern( "First Project" ) + workspace.name = str_intern( "First Workspace" ) + { + using project.workspace + cam = { + target = { 0, 0 }, + offset = transmute(Vec2) app_window.extent, + rotation = 0, + zoom = 1.0, + } + // cam = { + // position = { 0, 0, -100 }, + // target = { 0, 0, 0 }, + // up = { 0, 1, 0 }, + // fovy = 90, + // projection = rl.CameraProjection.ORTHOGRAPHIC, + // } + + // Setup workspace UI state + ui_startup( & workspace.ui, cache_allocator = persistent_slab_allocator() ) + } + + debug.path_lorem = str_fmt_alloc("C:/projects/SectrPrototype/examples/Lorem Ipsum.txt", allocator = persistent_slab_allocator()) + + alloc_error : AllocatorError; success : bool + debug.lorem_content, success = os.read_entire_file( debug.path_lorem, persistent_slab_allocator() ) + + debug.lorem_parse, alloc_error = pws_parser_parse( transmute(string) debug.lorem_content, persistent_slab_allocator() ) + verify( alloc_error == .None, "Faield to parse due to allocation failure" ) + + // Render texture test + // debug.viewport_rt = rl.LoadRenderTexture( 1280, 720 ) + + // debug.proto_text_shader = rl.LoadShader( "C:/projects/SectrPrototype/code/shaders/text_shader.vs", "C:/projects/SectrPrototype/code/shaders/text_shader.fs" ) + } + + startup_ms := duration_ms( time.tick_lap_time( & startup_tick)) + log( str_fmt_tmp("Startup time: %v ms", startup_ms) ) + + // Make sure to cleanup transient before continuing... + // From here on, tarnsinet usage has to be done with care. + // For most cases, the frame allocator should be more than enough. +} + +// For some reason odin's symbols conflict with native foreign symbols... +@export +sectr_shutdown :: proc() +{ + context.logger = to_odin_logger( & Memory_App.logger ) + + if Memory_App.persistent == nil { + return + } + state := get_state() + + // Replay + { + file_close( Memory_App.replay.active_file ) + } + + // font_provider_shutdown() + + sokol_app.post_client_cleanup() + + log("Module shutdown complete") +} + +@export +reload :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem, files_buffer_mem : ^VArena, host_logger : ^ Logger ) +{ + spall.SCOPED_EVENT( & prof.ctx, & prof.buffer, #procedure ) + Memory_App.profiler = prof + + context.logger = to_odin_logger( & Memory_App.logger ) + using Memory_App; + + persistent = persistent_mem + frame = frame_mem + transient = transient_mem + files_buffer = files_buffer_mem + + context.allocator = persistent_allocator() + context.temp_allocator = transient_allocator() + + Memory_App.state = get_state() + using state + + // Procedure Addresses are not preserved on hot-reload. They must be restored for persistent data. + // The only way to alleviate this is to either do custom handles to allocators + // Or as done below, correct containers using allocators on reload. + // Thankfully persistent dynamic allocations are rare, and thus we know exactly which ones they are. + + slab_reload( persistent_slab, persistent_allocator() ) + + hmap_chained_reload( font_provider_data.font_cache, persistent_allocator()) + + slab_reload( string_cache.slab, persistent_allocator() ) + zpl_hmap_reload( & string_cache.table, persistent_slab_allocator()) + + slab_reload( frame_slab, frame_allocator()) + slab_reload( transient_slab, transient_allocator()) + + ui_reload( & get_state().project.workspace.ui, cache_allocator = persistent_slab_allocator() ) + + log("Module reloaded") +} + +@export +tick :: proc( host_delta_time : f64, host_delta_ns : Duration ) -> b32 +{ + should_close : b32 + + profile_begin("sokol_app: pre_client_tick") + should_close |= cast(b32) sokol_app.pre_client_frame() + profile_end() + + profile( "Client Tick" ) + context.logger = to_odin_logger( & Memory_App.logger ) + state := get_state(); using state + + client_tick := time.tick_now() + { + profile("Work frame") + + // Setup Frame Slab + { + alloc_error : AllocatorError + frame_slab, alloc_error = slab_init( & default_slab_policy, bucket_reserve_num = 0, + allocator = frame_allocator(), + dbg_name = Frame_Slab_DBG_Name, + should_zero_buckets = true ) + verify( alloc_error == .None, "Failed to allocate frame slab" ) + } + + context.allocator = frame_slab_allocator() + context.temp_allocator = transient_allocator() + + // rl.PollInputEvents() + + debug.draw_ui_box_bounds_points = false + debug.draw_UI_padding_bounds = false + debug.draw_ui_content_bounds = false + + // config.color_theme = App_Thm_Light + // config.color_theme = App_Thm_Dusk + config.color_theme = App_Thm_Dark + + // should_close |= update( host_delta_time ) + // render() + + // rl.SwapScreenBuffer() + } + + // Timing + { + // profile("Client tick timing processing") + // config.engine_refresh_hz = uint(monitor_refresh_hz) + // config.engine_refresh_hz = 6 + frametime_target_ms = 1.0 / f64(config.engine_refresh_hz) * S_To_MS + sub_ms_granularity_required := frametime_target_ms <= Frametime_High_Perf_Threshold_MS + + frametime_delta_ns = time.tick_lap_time( & client_tick ) + frametime_delta_ms = duration_ms( frametime_delta_ns ) + frametime_delta_seconds = duration_seconds( frametime_delta_ns ) + frametime_elapsed_ms = frametime_delta_ms + host_delta_time + + if frametime_elapsed_ms < frametime_target_ms + { + sleep_ms := frametime_target_ms - frametime_elapsed_ms + pre_sleep_tick := time.tick_now() + + if sleep_ms > 0 { + thread_sleep( cast(Duration) sleep_ms * MS_To_NS ) + // thread__highres_wait( sleep_ms ) + } + + sleep_delta_ns := time.tick_lap_time( & pre_sleep_tick) + sleep_delta_ms := duration_ms( sleep_delta_ns ) + + if sleep_delta_ms < sleep_ms { + // log( str_fmt_tmp("frametime sleep was off by: %v ms", sleep_delta_ms - sleep_ms )) + } + + frametime_elapsed_ms += sleep_delta_ms + for ; frametime_elapsed_ms < frametime_target_ms; { + sleep_delta_ns = time.tick_lap_time( & pre_sleep_tick) + sleep_delta_ms = duration_ms( sleep_delta_ns ) + + frametime_elapsed_ms += sleep_delta_ms + } + } + + config.timing_fps_moving_avg_alpha = 0.99 + frametime_avg_ms = mov_avg_exp( f64(config.timing_fps_moving_avg_alpha), frametime_elapsed_ms, frametime_avg_ms ) + fps_avg = 1 / (frametime_avg_ms * MS_To_S) + + if frametime_elapsed_ms > 60.0 { + log( str_fmt_tmp("Big tick! %v ms", frametime_elapsed_ms), LogLevel.Warning ) + } + + profile_begin("sokol_app: post_client_tick") + sokol_app.post_client_frame() + profile_end() + } + return should_close +} + +@export +clean_frame :: proc() +{ + // profile( #procedure) + state := get_state(); using state + context.logger = to_odin_logger( & Memory_App.logger ) + + free_all( frame_allocator() ) + + transient_clear_elapsed += frametime_delta32() + if transient_clear_elapsed >= transient_clear_time && ! transinet_clear_lock + { + transient_clear_elapsed = 0 + free_all( transient_allocator() ) + + alloc_error : AllocatorError + transient_slab, alloc_error = slab_init( & default_slab_policy, allocator = transient_allocator(), dbg_name = Transient_Slab_DBG_Name ) + verify( alloc_error == .None, "Failed to allocate transient slab" ) + } +} diff --git a/code/sectr/engine/client_api_sokol_callbacks.odin b/code/sectr/engine/client_api_sokol_callbacks.odin new file mode 100644 index 0000000..7529bc5 --- /dev/null +++ b/code/sectr/engine/client_api_sokol_callbacks.odin @@ -0,0 +1,115 @@ +package sectr + +import "base:runtime" +import str "core:strings" + +import sokol_app "thirdparty:sokol/app" + +// SokolLogEntry :: struct { +// tag: cstring, +// log_level: u32, +// log_item_id: u32, +// message_or_null: cstring, +// line_nr: u32, +// filename_or_null : cstring, +// } + +// SokolRelay :: struct { +// logs : StackFixed(SokolLogEntry, 512), +// } + +// sokol_relay :: #force_inline proc "contextless" () -> ^SokolRelay { +// return & get_state().sokol_relay +// } + +sokol_app_init_callback :: proc "c" () { + context = get_state().sokol_context + log("sokol_app: Confirmed initialization") + // stack_push_contextless( & sokol_relay().logs, { "", 3, 0, "sokol_app: Confirmed initialization", 29, #file }) +} + +// This is being filled in but we're directly controlling the lifetime of sokol_app's execution. +// Thus we have no need for it todo frame callbacks +sokol_app_frame_callback :: proc "c" () { + context = get_state().sokol_context + log("sokol_app: SHOULD NOT HAVE CALLED THE FRAME CALLABCK") + // stack_push_contextless( & sokol_relay().logs, { "", 3, 0, "sokol_app: SHOULD NOT HAVE CALLED THE FRAME CALLBACK", 29, #file }) +} + +sokol_app_cleanup_callback :: proc "c" () { + context = get_state().sokol_context + log("sokol_app: Confirmed cleanup") + // stack_push_contextless( & sokol_relay().logs, { "", 3, 0, "sokol_app: Confirmed cleanup", 29, #file }) +} + +sokol_app_alloc :: proc "c" ( size : u64, user_data : rawptr ) -> rawptr { + context = get_state().sokol_context + block, error := alloc( int(size), allocator = persistent_slab_allocator() ) + ensure(error != AllocatorError.None, "sokol_app allocation failed") + return block +} + +sokol_app_free :: proc "c" ( data : rawptr, user_data : rawptr ) { + context = get_state().sokol_context + free(data, allocator = persistent_slab_allocator() ) +} + +sokol_app_log_callback :: proc "c" ( + tag: cstring, + log_level: u32, + log_item_id: u32, + message_or_null: cstring, + line_nr: u32, + filename_or_null: cstring, + user_data: rawptr) { + context = get_state().sokol_context + + odin_level : LogLevel + switch log_level { + case 0: odin_level = .Fatal + case 1: odin_level = .Error + case 2: odin_level = .Warning + case 3: odin_level = .Info + } + + cloned_msg : string = "" + if message_or_null != nil { + cloned_msg = str.clone_from_cstring(message_or_null, context.temp_allocator) + } + cloned_fname : string = "" + if filename_or_null != nil { + cloned_fname = str.clone_from_cstring(filename_or_null, context.temp_allocator) + } + + logf( "%-80s %v : %s::%s", cloned_msg, cloned_fname, str.clone_from_cstring(tag), level = odin_level ) + // push( & sokol_relay().logs, {tag, log_level, log_item_id, message_or_null, line_nr, filename_or_null, user_data }) +} + +// sokol_app_relay_update :: proc() +// { +// logs := & sokol_relay().logs +// for ; logs.idx != 0; pop( logs ) { +// odin_level : LogLevel +// switch log_level { +// case 0: odin_level = .Fatal +// case 1: odin_level = .Error +// case 2: odin_level = .Warning +// case 3: odin_level = .Info +// } + +// cloned_msg : string = "" +// if message != nil { +// cloned_msg = str.clone_from_cstring(message, context.temp_allocator) +// } +// cloned_fname : string = "" +// if filename_or_null { +// cloned_fname = str.clone_from_cstring(filename_or_null, context.temp_allocator) +// } + +// logf( "%-80s %v : %s::%s", cloned_msg, cloned_fname, str.clone_from_cstring(tag), level = odin_level ) +// } +// } + +sokol_app_event_callback :: proc "c" (event : ^sokol_app.Event) { + +} diff --git a/code/sectr/grime/logger.odin b/code/sectr/engine/logger.odin similarity index 96% rename from code/sectr/grime/logger.odin rename to code/sectr/engine/logger.odin index 0499a42..42e1452 100644 --- a/code/sectr/grime/logger.odin +++ b/code/sectr/engine/logger.odin @@ -65,7 +65,8 @@ logger_interface :: proc( first_line_length := len(text) > Max_Logger_Message_Width ? Max_Logger_Message_Width : len(text) first_line := transmute(string) text[ 0 : first_line_length ] - str_fmt_builder( & builder, "%-*s ", Max_Logger_Message_Width, first_line ) + // str_fmt_builder( & builder, "%-s ", Max_Logger_Message_Width, first_line ) + str_fmt_builder( & builder, "%-180s ", first_line ) // Signature { diff --git a/code/sectr/grime/stack.odin b/code/sectr/grime/stack.odin index 504e294..c19c291 100644 --- a/code/sectr/grime/stack.odin +++ b/code/sectr/grime/stack.odin @@ -41,6 +41,11 @@ stack_peek :: #force_inline proc "contextless" ( using stack : ^StackFixed( $ Ty return items[last] } +stack_push_contextless :: #force_inline proc "contextless" ( stack : ^StackFixed( $Type, $Size), value : Type ) { + items[idx] = value + idx += 1 +} + //endregion Fixed Stack //region Stack Allocator diff --git a/scripts/update_deps.ps1 b/scripts/update_deps.ps1 index 7aaa5a1..11cf1c2 100644 --- a/scripts/update_deps.ps1 +++ b/scripts/update_deps.ps1 @@ -106,10 +106,17 @@ else $path_vendor = join-path $path_odin 'vendor' $path_vendor_raylib = join-path $path_vendor 'raylib' +$path_sokol_dlls = join-path $path_thirdparty 'sokol' $path_raylib_dlls = join-path $path_vendor_raylib 'windows' if ( $binaries_dirty -or $true ) { + $third_party_dlls = Get-ChildItem -Path $path_sokol_dlls -Filter '*.dll' + foreach ($dll in $third_party_dlls) { + $destination = join-path $path_build $dll.Name + Copy-Item $dll.FullName -Destination $destination -Force + } + $third_party_dlls = Get-ChildItem -Path $path_raylib_dlls -Filter '*.dll' foreach ($dll in $third_party_dlls) { $destination = join-path $path_build $dll.Name