diff --git a/src/assets/asset_manager.jai b/src/assets/asset_manager.jai new file mode 100644 index 0000000..79eeb0c --- /dev/null +++ b/src/assets/asset_manager.jai @@ -0,0 +1,83 @@ +#scope_file + +hash :: #import "Hash"; + +MAX_FILE_SIZE :: 2_000_000_000; +buf : [MAX_FILE_SIZE]u8; + +Pack_Request :: struct { + name : string; + shouldBlock : bool; + loading : bool = false; + shouldBlockEngine : bool; // Means that the engine loop should do nothing while this is loading... +} + +Loaded_Pack :: struct { + nameHash : u32 = 0; + content : Load_Package; +} + +Asset_Manager :: struct { + packQueue : [..]Pack_Request; + loadedPacks : [..]Loaded_Pack; +} + +g_asset_manager : Asset_Manager; + +packcb :: (res: *sfetch_response_t) #c_call { + push_context,defer_pop default_context; + mem : []u8; + mem.count = res.data.size.(s64); + mem.data = res.data.ptr; + pack: Loaded_Pack; + pack.nameHash = hash.get_hash(g_asset_manager.packQueue[0].name); + success := init_from_memory(*pack.content, mem, sprint("%", g_asset_manager.packQueue[0].name)); + if !success then print("Failed to load pack!!\n"); + array_add(*g_asset_manager.loadedPacks, pack); + array_unordered_remove_by_index(*g_asset_manager.packQueue, 0); +} + +#scope_export + +// Pack management: + +mandatory_loads_done :: () -> bool { + for g_asset_manager.packQueue { + if it.shouldBlockEngine return false; + } + return true; +} + +show_loading_screen :: () -> bool { + for g_asset_manager.packQueue { + if it.shouldBlock return true; + } + return false; +} + +asset_manager_tick :: () { + if g_asset_manager.packQueue.count > 0 && !g_asset_manager.packQueue[0].loading { + sfetch_send(*(sfetch_request_t.{ + path = to_c_string(tprint("./packs/%.pack", g_asset_manager.packQueue[0].name)), + callback = packcb, + buffer = .{ + ptr = buf.data, + size = buf.count + } + })); + g_asset_manager.packQueue[0].loading = true; + } + sfetch_dowork(); +} + +load_pack :: (name: string, shouldBlock: bool = true, shouldBlockEngine: bool = false) { + array_add(*g_asset_manager.packQueue, .{ + name = name, + shouldBlock = shouldBlock, + shouldBlockEngine = shouldBlockEngine + }); +} + +// Asset management: + + diff --git a/src/audio/mixer.jai b/src/audio/mixer.jai index bd62e08..d888288 100644 --- a/src/audio/mixer.jai +++ b/src/audio/mixer.jai @@ -17,19 +17,22 @@ Mixer_Play_Task :: struct { audio : *Audio_Data; bus : Mixer_Bus; mode : Play_Mode; - curSample : s64; + curSample : s64 = 0; - startTime : float64; - delay : float64; - silenceBeforeRepeat : float64; + startTime : float64 = 0; + delay : float64 = 0; + silenceBeforeRepeat : float64 = 0; } Mixer_Config :: struct { + musicVolume : float = 0.5; @Slider,0,1,0.1 masterVolume : float = 0.5; @Slider,0,1,0.1 dialogueVolume : float = 0.5; @Slider,0,1,0.1 soundEffectVolume : float = 0.5; @Slider,0,1,0.1 } +g_mixer : Mixer; + Mixer :: struct { #if OS != .WASM { // If we are on WASM, the Thread module mutex does not work. @@ -50,23 +53,22 @@ Mixer :: struct { // Removes tasks from the mixer's task list that // no longer have a reason to be on the task list. // Eg. a sound that is .ONESHOT but has already been played. -mixer_clean_tasks :: (mixer: *Mixer) { - mixer_lock(mixer); - defer mixer_unlock(mixer); +mixer_clean_tasks :: () { + mixer_lock(*g_mixer); + defer mixer_unlock(*g_mixer); } -mixer_add_task :: (mixer: *Mixer, task: Mixer_Play_Task) { - mixer_lock(mixer); - defer mixer_unlock(mixer); +mixer_add_task :: (task: Mixer_Play_Task) { + mixer_lock(*g_mixer); + defer mixer_unlock(*g_mixer); } -mixer_get_samples :: (mixer: *Mixer, samples: *float, sampleCount: s32, channelCount: s32) { - mixer_lock(mixer); - defer mixer_unlock(mixer); - - +mixer_get_samples :: (samples: *float, sampleCount: s32, channelCount: s32) { + mixer_lock(*g_mixer); + defer mixer_unlock(*g_mixer); + } mixer_lock :: (mixer: *Mixer) { diff --git a/src/load.jai b/src/load.jai index 6952f77..02023d6 100644 --- a/src/load.jai +++ b/src/load.jai @@ -1,45 +1,9 @@ g_asset_pack : Load_Package; -#scope_file - -MAX_FILE_SIZE :: 2_000_000_000; -buf : [MAX_FILE_SIZE]u8; - - -mandatory_loads_left : s32 = 0; - -packcb :: (res: *sfetch_response_t) #c_call { - push_context,defer_pop default_context; - mem : []u8; - mem.count = res.data.size.(s64); - mem.data = res.data.ptr; - print("Mem count %\n", mem.count); - - success := init_from_memory(*g_asset_pack, mem, "main_asset_pack"); - print("Succesfully loaded main asset pack!\n"); - mandatory_loads_left -= 1; -} - #scope_export init_after_mandatory_done : bool = false; -mandatory_loads_done :: () -> bool { - return mandatory_loads_left <= 0; -} - -init_asset_pack_load :: () { - mandatory_loads_left += 1; - sfetch_send(*(sfetch_request_t.{ - path = "./packs/assets.pack".data, - callback = packcb, - buffer = .{ - ptr = buf.data, - size = buf.count - } - })); -} - add_font_from_pack :: (path: string) { ok, entry := table_find(*g_asset_pack.lookup, path); if !ok { diff --git a/src/main.jai b/src/main.jai index 626661b..157956b 100644 --- a/src/main.jai +++ b/src/main.jai @@ -28,6 +28,7 @@ stbi :: #import "stb_image"; #load "world.jai"; #load "utils.jai"; #load "audio/audio.jai"; +#load "assets/asset_manager.jai"; #if USE_SAMPLE_GAME { #load "../sample_game/game.jai"; @@ -107,9 +108,10 @@ init :: () { state.pass_action_clear_gbuf.colors[0] = .{ load_action = .CLEAR, clear_value = .{ r = 0, g = 0, b = 1000, a = 0 } }; state.pass_action.colors[0] = .{ load_action = .LOAD }; - init_asset_pack_load(); useless_mem : [1]u8; debug_font = get_font_at_size(useless_mem, 15); + load_pack("assets", true, true); + } init_after_asset_pack :: () { @@ -153,8 +155,7 @@ frame :: () { delta_time = get_time() - last_frame_time; last_frame_time = get_time(); - - sfetch_dowork(); + asset_manager_tick(); if mandatory_loads_done() && !init_after_mandatory_done { init_after_asset_pack(); @@ -162,6 +163,7 @@ frame :: () { } if !mandatory_loads_done() then return; + fonsClearState(state.fons); frame_start_time := get_time();