diff --git a/.nvim.lua b/.nvim.lua index b563699..23ec855 100644 --- a/.nvim.lua +++ b/.nvim.lua @@ -1,2 +1,2 @@ -vim.opt_global.makeprg = "./build_hot_reload.sh" +vim.opt_global.makeprg = "./build.sh" vim.opt.errorformat = "%f(%l:%c)\\ %m" diff --git a/builder/builder.odin b/builder/builder.odin index d139c29..6f097e5 100644 --- a/builder/builder.odin +++ b/builder/builder.odin @@ -199,20 +199,24 @@ setup_emsdk_env :: proc() { set_env("EMSDK", absolute_path("./libs/emsdk")) } -setup_bin_dir :: proc(path: string, files_to_copy: []string) { +setup_bin_dir :: proc(opts: Options, path: string, files_to_copy: []string) { mkdir_all(path) for file in files_to_copy { - copy_file(file, temp_path_join(path, filepath.base(file))) + dst := temp_path_join(path, filepath.base(file)) + + if !os.is_file(dst) || opts.force { + copy_file(file, dst) + } } } main :: proc() { context.logger = log.create_console_logger() opts := Options { - tracy = true, - debug = true, - run = true, + tracy = true, + debug = true, + optimize = true, } flags.parse_or_exit(&opts, os.args, .Unix, context.temp_allocator) if opts.variant == .Web { @@ -230,10 +234,10 @@ main :: proc() { switch opts.variant { case .Hot_Reload: - setup_bin_dir("./build/hotreload", shared_dep_paths) + setup_bin_dir(opts, "./build/hotreload", shared_dep_paths) - is_main_built := os.is_file("./build/hotreload/game.bin") - if !is_main_built || opts.force { + is_running := process_exists("game.bin") + if !is_running { run_cmd( temp_concat( []string { @@ -244,72 +248,32 @@ main :: proc() { }, debug_flag, tracy_flag, - optimize_flag, COMMON_FLAGS, ), "", ) } - build_game_cmd := temp_concat( - []string { - "odin", - "build", - "game", - "-define:RAYLIB_SHARED=true", - "-define:PHYSFS_SHARED=true", - "-build-mode:dll", - "-out:./build/hotreload/game_tmp.so", - }, - tracy_flag, - debug_flag, - optimize_flag, - COMMON_FLAGS, + build_game_cmd := run_cmd( + temp_concat( + []string { + "odin", + "build", + "game", + "-define:RAYLIB_SHARED=true", + "-define:PHYSFS_SHARED=true", + "-build-mode:dll", + "-out:./build/hotreload/game_tmp.so", + }, + tracy_flag, + debug_flag, + optimize_flag, + COMMON_FLAGS, + ), + "", ) - build_game_lib :: proc(build_cmd: []string) { - run_cmd(build_cmd, "") - rename("./build/hotreload/game_tmp.so", "./build/hotreload/game.so") - } - build_game_lib(build_game_cmd) - - if opts.run && !process_exists("game.bin") { - Watcher_Context :: struct { - run: bool, - build_game_cmd: []string, - } - watcher_ctx := Watcher_Context { - run = true, - build_game_cmd = build_game_cmd, - } - thread_ctx := context - thread_ctx.user_ptr = &watcher_ctx - thrd := thread.create_and_start(proc() { - watcher_ctx := (cast(^Watcher_Context)context.user_ptr) - input := os.to_reader(os.stdin) - - buf: [1024]u8 - for { - n, err := io.read(input, buf[:]) - - for cmd in buf[0:n] { - switch cmd { - case 'r', 'R': - build_game_lib(watcher_ctx.build_game_cmd) - case: - } - } - - if err == .EOF { - break - } - - handle_error(err) - } - }, thread_ctx) - - run_cmd({"./build/hotreload/game.bin"}, "") - } + rename("./build/hotreload/game_tmp.so", "./build/hotreload/game.so") case .Desktop: - setup_bin_dir("./build/desktop", shared_dep_paths) + setup_bin_dir(opts, "./build/desktop", shared_dep_paths) cmd := slice.concatenate( [][]string { diff --git a/builder/helpers.odin b/builder/helpers.odin index b387d08..e07e405 100644 --- a/builder/helpers.odin +++ b/builder/helpers.odin @@ -20,9 +20,11 @@ Run_Error :: union #shared_nil { os.Error, } +@(private = "file") run_cmd_internal :: proc( cmd: []string, cwd: string, + capture: bool, loc := #caller_location, ) -> ( result: string, @@ -70,7 +72,9 @@ run_cmd_internal :: proc( buf: [1024]u8 if has_data { n = handle_error1(os.read(r, buf[:])) - strings.write_bytes(&b, buf[0:n]) + if capture { + strings.write_bytes(&b, buf[0:n]) + } handle_error1(os.write(os.stderr, buf[0:n])) } @@ -106,10 +110,11 @@ run_cmd_internal :: proc( run_cmd :: proc( cmd: []string, cwd: string, + capture := true, expr := #caller_expression, loc := #caller_location, ) -> string { - result, err := run_cmd_internal(cmd, cwd, loc) + result, err := run_cmd_internal(cmd, cwd, capture, loc) handle_error(err, "", expr, loc) return result } diff --git a/game/assets/assets.odin b/game/assets/assets.odin index 65913d7..2bbf201 100644 --- a/game/assets/assets.odin +++ b/game/assets/assets.odin @@ -577,8 +577,6 @@ get_convex :: proc(assetman: ^Asset_Manager, path: cstring) -> (result: Loaded_C } } - log.debugf("num verts: %v", len(vertices)) - center := (max_pos + min_pos) * 0.5 extent := (max_pos - min_pos) * 0.5 diff --git a/game/game.odin b/game/game.odin index 9e4ef6a..23a8d3b 100644 --- a/game/game.odin +++ b/game/game.odin @@ -1302,6 +1302,7 @@ game_init :: proc() { g_mem.ui_context.default_style.font_size = 20 g_mem.ui_context.text_size = ui.rl_measure_text_2d + log.debugf("game_init") game_hot_reloaded(g_mem) } @@ -1340,6 +1341,7 @@ game_hot_reloaded :: proc(mem: rawptr) { ui.rl_init() g_mem.runtime_world.orbit_camera.distance = 4 + log.debugf("hot reloaded") } @(export) diff --git a/main_hot_reload/main_hot_reload.odin b/main_hot_reload/main_hot_reload.odin index 4d8350c..5f77b4d 100644 --- a/main_hot_reload/main_hot_reload.odin +++ b/main_hot_reload/main_hot_reload.odin @@ -52,8 +52,14 @@ Game_API :: struct { api_version: int, } -load_game_api :: proc(api_version: int) -> (api: Game_API, ok: bool) { - mod_time, mod_time_error := os.last_write_time_by_name("game" + DLL_EXT) +load_game_api :: proc(bin_dir: string, api_version: int) -> (api: Game_API, ok: bool) { + // NOTE: this needs to be a relative path for Linux to work. + game_dll_name := fmt.tprintf("game_{0}" + DLL_EXT, api_version) + game_dll_path := filepath.join({bin_dir, game_dll_name}, context.temp_allocator) + + mod_time, mod_time_error := os.last_write_time_by_name( + filepath.join({bin_dir, "game" + DLL_EXT}, context.temp_allocator), + ) if mod_time_error != os.ERROR_NONE { fmt.printfln( "Failed getting last write time of game" + DLL_EXT + ", error code: {1}", @@ -62,14 +68,9 @@ load_game_api :: proc(api_version: int) -> (api: Game_API, ok: bool) { return } - // NOTE: this needs to be a relative path for Linux to work. - game_dll_name := fmt.tprintf("game_{0}" + DLL_EXT, api_version) - bin_dir := filepath.dir(os.args[0], context.temp_allocator) copy_dll(bin_dir, game_dll_name) or_return - game_dll_path := filepath.join({bin_dir, game_dll_name}, context.temp_allocator) - // This proc matches the names of the fields in Game_API to symbols in the // game DLL. It actually looks for symbols starting with `game_`, which is // why the argument `"game_"` is there. @@ -85,15 +86,13 @@ load_game_api :: proc(api_version: int) -> (api: Game_API, ok: bool) { return } -unload_game_api :: proc(api: ^Game_API) { +unload_game_api :: proc(bin_dir: string, api: ^Game_API) { if api.lib != nil { if !dynlib.unload_library(api.lib) { fmt.printfln("Failed unloading lib: {0}", dynlib.last_error()) } } - bin_dir := filepath.dir(os.args[0], context.temp_allocator) - game_dll_path := filepath.join( {bin_dir, fmt.tprintf("game_{0}" + DLL_EXT, api.api_version)}, context.temp_allocator, @@ -137,7 +136,7 @@ main :: proc() { } game_api_version := 0 - game_api, game_api_ok := load_game_api(game_api_version) + game_api, game_api_ok := load_game_api(bin_dir, game_api_version) if !game_api_ok { fmt.println("Failed to load Game API") @@ -165,7 +164,7 @@ main :: proc() { } if reload { - new_game_api, new_game_api_ok := load_game_api(game_api_version) + new_game_api, new_game_api_ok := load_game_api(bin_dir, game_api_version) if new_game_api_ok { force_restart = @@ -194,11 +193,11 @@ main :: proc() { reset_tracking_allocator(&tracking_allocator) for &g in old_game_apis { - unload_game_api(&g) + unload_game_api(bin_dir, &g) } clear(&old_game_apis) - unload_game_api(&game_api) + unload_game_api(bin_dir, &game_api) game_api = new_game_api game_api.init() } @@ -232,13 +231,13 @@ main :: proc() { } for &g in old_game_apis { - unload_game_api(&g) + unload_game_api(bin_dir, &g) } delete(old_game_apis) game_api.shutdown_window() - unload_game_api(&game_api) + unload_game_api(bin_dir, &game_api) mem.tracking_allocator_destroy(&tracking_allocator) }