AsyncLoadTools = AsyncLoadTools or {} AsyncLoadTools.LoadedResources = {} AsyncLoadTools.PreLoadedWeaponMeshes = {} AsyncLoadTools.PreLoadedWeaponIcons = {} AsyncLoadTools.PreLoadedEffects = {} AsyncLoadTools.PreLoadWeaponMeshesCompleted = false AsyncLoadTools.PreLoadWeaponIconsCompleted = false AsyncLoadTools.PreLoadEffectsCompleted = false AsyncLoadTools.PendingPreLoadedMeshNum = 0 AsyncLoadTools.PendingPreLoadedIconNum = 0 AsyncLoadTools.PendingPreLoadedEffectNum = 0 AsyncLoadTools.PendingLoadSoftPaths = {} AsyncLoadTools.PendingCallbacks = {} function AsyncLoadTools:Init() -- self:PreLoadWeaponIcons() -- self:PreLoadWeaponMeshes() self:PreLoadEffects() end function AsyncLoadTools:UnInit() self.LoadedResources = nil self.PreLoadedWeaponMeshes = nil self.PreLoadedWeaponIcons = nil self.PreLoadedEffects = nil self:Release() end function AsyncLoadTools:Release() local GameState = UGCGameSystem.GameState local AsyncDelegates = GameState.AsyncDelegate if AsyncDelegates then for _, Delegate in pairs(AsyncDelegates) do ObjectExtend.DestroyDelegate(Delegate) end end GameState.AsyncDelegate = nil end function AsyncLoadTools:LoadObject(SourcePath, CallBack) local GameState = UGCGameSystem.GameState if GameState == nil or UE.IsValid(GameState) == false then UE.Log("[AsyncLoadTools:LoadObject] GameState is invalid") return end if CallBack == nil or type(CallBack) ~= "function" then UE.Log("[AsyncLoadTools:LoadObject] CallBack is invalid") return end if SourcePath == nil or type(SourcePath) ~= "string" then UE.Log("[AsyncLoadTools:LoadObject] SourcePath is invalid") return end SourcePath = GetFullPath(SourcePath) local CachedResource = self.LoadedResources[SourcePath] if CachedResource and UE.IsValid(CachedResource) then UE.Log("[AsyncLoadTools:LoadObject] Has Cached Resource! SourcePath = "..SourcePath) CallBack(CachedResource) return end if self.PendingCallbacks[SourcePath] == nil then self.PendingCallbacks[SourcePath] = {} end if table.hasValue(self.PendingLoadSoftPaths, SourcePath) then table.insert(self.PendingCallbacks[SourcePath], CallBack) UE.Log("[AsyncLoadTools:LoadObject] SourcePath: %s has requested AsyncLoading, Callback has added to wait-list", SourcePath) return end table.insert(self.PendingLoadSoftPaths, SourcePath) table.insert(self.PendingCallbacks[SourcePath], CallBack) if GameState.AsyncDelegate == nil then GameState.AsyncDelegate = {} GameState.AsyncDelegateIndex = 0 end local softObjPath = KismetSystemLibrary.MakeSoftObjectPath(SourcePath) UE.Log("[AsyncLoadTools:LoadObject] SourcePath: %s request asyncLoading. ", SourcePath) GameState.AsyncDelegateIndex = GameState.AsyncDelegateIndex + 1 local AsyncDelegateIndex = GameState.AsyncDelegateIndex GameState.AsyncDelegate[AsyncDelegateIndex] = ObjectExtend.CreateDelegate(GameState, function (Asset) local GameState = UGCGameSystem.GameState if GameState == nil or UE.IsValid(GameState) == false then return end if Asset ~= nil then local CallBackList = self.PendingCallbacks[SourcePath] if type(CallBackList) == "table" and table.getCount(CallBackList) > 0 then for _, PendingCallback in pairs(CallBackList) do PendingCallback(Asset) end self.PendingCallbacks[SourcePath] = nil end self.LoadedResources[SourcePath] = Asset else UE.Log("[AsyncLoadTools:LoadObject] Error:"..SourcePath) end table.removeValue(self.PendingLoadSoftPaths, SourcePath) if GameState.AsyncDelegate[AsyncDelegateIndex] then ObjectExtend.DestroyDelegate(GameState.AsyncDelegate[AsyncDelegateIndex]) GameState.AsyncDelegate[AsyncDelegateIndex] = nil end end ) STExtraBlueprintFunctionLibrary.GetAssetByAssetReferenceAsync(softObjPath, GameState.AsyncDelegate[AsyncDelegateIndex], true) end function AsyncLoadTools:LoadObjectBySoftPath(SourcePath, CallBack) local GameState = UGCGameSystem.GameState if GameState == nil or UE.IsValid(GameState) == false then UE.Log("[AsyncLoadTools:LoadObjectBySoftPath] GameState is invalid") return end if CallBack == nil or type(CallBack) ~= "function" then UE.Log("[AsyncLoadTools:LoadObjectBySoftPath] CallBack is invalid") return end if SourcePath == nil or SourcePath.AssetPathName == nil then UE.Log("[AsyncLoadTools:LoadObjectBySoftPath] SourcePath is invalid") return end local CachedResource = self.LoadedResources[SourcePath] if CachedResource and UE.IsValid(CachedResource) then UE.Log("[AsyncLoadTools:LoadObjectBySoftPath] Has Cached Resource! SourcePath = "..SourcePath.AssetPathName) CallBack(CachedResource) return end if self.PendingCallbacks[SourcePath] == nil then self.PendingCallbacks[SourcePath] = {} end if table.hasValue(self.PendingLoadSoftPaths, SourcePath) then table.insert(self.PendingCallbacks[SourcePath], CallBack) UE.Log("[AsyncLoadTools:LoadObjectBySoftPath] SourcePath: %s has requested AsyncLoading, Callback has added to wait-list", SourcePath.AssetPathName) return end table.insert(self.PendingLoadSoftPaths, SourcePath) table.insert(self.PendingCallbacks[SourcePath], CallBack) if GameState.AsyncDelegate == nil then GameState.AsyncDelegate = {} GameState.AsyncDelegateIndex = 0 end GameState.AsyncDelegateIndex = GameState.AsyncDelegateIndex + 1 local AsyncDelegateIndex = GameState.AsyncDelegateIndex GameState.AsyncDelegate[AsyncDelegateIndex] = ObjectExtend.CreateDelegate(GameState, function (Asset) local GameState = UGCGameSystem.GameState if GameState == nil or UE.IsValid(GameState) == false then return end if Asset ~= nil then local CallBackList = self.PendingCallbacks[SourcePath] if type(CallBackList) == "table" and table.getCount(CallBackList) > 0 then for _, PendingCallback in pairs(CallBackList) do PendingCallback(Asset) end self.PendingCallbacks[SourcePath] = nil end self.LoadedResources[SourcePath] = Asset else UE.Log("[AsyncLoadTools:LoadObjectBySoftPath] Error:"..SourcePath.AssetPathName) end table.removeValue(self.PendingLoadSoftPaths, SourcePath) if GameState.AsyncDelegate[AsyncDelegateIndex] then ObjectExtend.DestroyDelegate(GameState.AsyncDelegate[AsyncDelegateIndex]) GameState.AsyncDelegate[AsyncDelegateIndex] = nil end end ) STExtraBlueprintFunctionLibrary.GetAssetByAssetReferenceAsync(SourcePath, GameState.AsyncDelegate[AsyncDelegateIndex], true) end function AsyncLoadTools:GetResource(SourcePath) SourcePath = GetFullPath(SourcePath) return self.LoadedResources[SourcePath] end function AsyncLoadTools:PreLoadWeaponMeshes() local GameState = UGCGameSystem.GameState if GameState.AsyncDelegate == nil then GameState.AsyncDelegate = {} GameState.AsyncDelegateIndex = 0 end self.PreLoadWeaponMeshesCompleted = false self.PendingPreLoadedMeshNum = 0 if table.isEmpty(GameDataManager.WeaponConstructTable) then GameDataManager:LoadWeaponConstructTable() end local MeshDataTable = {} local TotalMeshNum = 0 for i, Data in pairs(GameDataManager.WeaponConstructTable) do local RowName = tonumber(i) local MeshData = { MainMesh = nil, PartMesh = {}, } MeshData.ID = RowName MeshData.MainMesh = Data.MainMesh local PartMeshInfo = Data.PartMeshInfo for i, v in pairs(PartMeshInfo) do local SocketName = v.SocketName local PartMesh = v.PartMesh table.insert(MeshData.PartMesh, {Mesh = PartMesh, Socket = SocketName}) TotalMeshNum = TotalMeshNum + 1 end TotalMeshNum = TotalMeshNum + 1 MeshDataTable[RowName] = MeshData table.insert(self.PreLoadedWeaponMeshes, MeshData) end self.PendingPreLoadedMeshNum = TotalMeshNum local MainMeshCallback = function(Asset, DataIndex, PartMeshIndex) for _, MeshData in pairs(self.PreLoadedWeaponMeshes) do if MeshData.ID == DataIndex then MeshData.MainMesh = Asset return end end end local PartMeshCallback = function(Asset, DataIndex, PartMeshIndex) for _, MeshData in pairs(self.PreLoadedWeaponMeshes) do if MeshData.ID == DataIndex then local PartMeshData = MeshData.PartMesh[PartMeshIndex] if PartMeshData then PartMeshData.Mesh = Asset end end end end for i, MeshData in pairs(MeshDataTable) do local TargetIndex = i local MainMeshPath = MeshData.MainMesh local PartMeshInfo = MeshData.PartMesh self:PushAsyncLoadMeshPath(MainMeshPath, TargetIndex, MainMeshCallback) for j, PartMeshData in pairs(PartMeshInfo) do self:PushAsyncLoadMeshPath(PartMeshData.Mesh, TargetIndex, PartMeshCallback, j) end end end function AsyncLoadTools:PushAsyncLoadMeshPath(MeshPath, DataIndex, CallBack, PartMeshIndex) local GameState = UGCGameSystem.GameState GameState.AsyncDelegateIndex = GameState.AsyncDelegateIndex + 1 local AsyncDelegateIndex = GameState.AsyncDelegateIndex GameState.AsyncDelegate[AsyncDelegateIndex] = ObjectExtend.CreateDelegate(GameState, function (Asset) local GameState = UGCGameSystem.GameState if GameState == nil or UE.IsValid(GameState) == false then return end if Asset ~= nil then CallBack(Asset, DataIndex, PartMeshIndex) else UE.Log("[AsyncLoadTools:PushAsyncLoadMeshPath] Error:"..MeshPath.AssetPathName) end self.PendingPreLoadedMeshNum = self.PendingPreLoadedMeshNum - 1 if self.PendingPreLoadedMeshNum <= 0 then self.PreLoadWeaponMeshesCompleted = true EventSystem:SendEvent(EventType.AsyncLoadWeaponMeshesCompleted) end if GameState.AsyncDelegate[AsyncDelegateIndex] then ObjectExtend.DestroyDelegate(GameState.AsyncDelegate[AsyncDelegateIndex]) GameState.AsyncDelegate[AsyncDelegateIndex] = nil end end) STExtraBlueprintFunctionLibrary.GetAssetByAssetReferenceAsync(MeshPath, GameState.AsyncDelegate[AsyncDelegateIndex], true) end function AsyncLoadTools.GetWeaponMeshInfo(ID) for _, MeshData in pairs(AsyncLoadTools.PreLoadedWeaponMeshes) do if MeshData.ID == ID then UE.Log("[AsyncLoadTools][GetWeaponMeshInfo] Found ID = "..tostring(ID)) return MeshData end end UE.Log("[AsyncLoadTools][GetWeaponMeshInfo] invalid ID = "..tostring(ID)) return nil end function AsyncLoadTools:PreLoadWeaponIcons() local GameState = UGCGameSystem.GameState if GameState.AsyncDelegate == nil then GameState.AsyncDelegate = {} GameState.AsyncDelegateIndex = 0 end self.PreLoadWeaponIconsCompleted = false if table.isEmpty(GameDataManager.WeaponConstructTable) then GameDataManager:LoadWeaponConstructTable() end self.PendingPreLoadedIconNum = 0 local PendingIcons = {} for i, Data in pairs(GameDataManager.WeaponConstructTable) do local RowName = tonumber(i) local IconPath = Data.Icon PendingIcons[RowName] = IconPath self.PendingPreLoadedIconNum = self.PendingPreLoadedIconNum + 1 end for index, SoftPath in pairs(PendingIcons) do GameState.AsyncDelegateIndex = GameState.AsyncDelegateIndex + 1 local AsyncDelegateIndex = GameState.AsyncDelegateIndex GameState.AsyncDelegate[AsyncDelegateIndex] = ObjectExtend.CreateDelegate(GameState, function (Asset) local GameState = UGCGameSystem.GameState if GameState == nil or UE.IsValid(GameState) == false then return end if Asset ~= nil then self.PreLoadedWeaponIcons[index] = Asset else UE.Log("[AsyncLoadTools:PreLoadWeaponIcons] Error:"..SoftPath.AssetPathName) end self.PendingPreLoadedIconNum = self.PendingPreLoadedIconNum - 1 if self.PendingPreLoadedIconNum <= 0 then self.PreLoadWeaponIconsCompleted = true EventSystem:SendEvent(EventType.AsyncLoadWeaponIconsCompleted) end if GameState.AsyncDelegate[AsyncDelegateIndex] then ObjectExtend.DestroyDelegate(GameState.AsyncDelegate[AsyncDelegateIndex]) GameState.AsyncDelegate[AsyncDelegateIndex] = nil end end ) STExtraBlueprintFunctionLibrary.GetAssetByAssetReferenceAsync(SoftPath, GameState.AsyncDelegate[AsyncDelegateIndex], true) end end function AsyncLoadTools.GetWeaponIcon(ID) return AsyncLoadTools.PreLoadedWeaponIcons[ID] end function AsyncLoadTools:PreLoadEffects() local GameState = UGCGameSystem.GameState if GameState.AsyncDelegate == nil then GameState.AsyncDelegate = {} GameState.AsyncDelegateIndex = 0 end self.PreLoadEffectsCompleted = false local EffectTables = require("Script.Global.EffectTables") local EffectPaths = EffectTables.Paths self.PendingPreLoadedEffectNum = 0 local PendingEffectPaths = {} for index, value in pairs(EffectPaths) do PendingEffectPaths[index] = value self.PendingPreLoadedEffectNum = self.PendingPreLoadedEffectNum + 1 end for index, EffectPath in pairs(PendingEffectPaths) do GameState.AsyncDelegateIndex = GameState.AsyncDelegateIndex + 1 local AsyncDelegateIndex = GameState.AsyncDelegateIndex GameState.AsyncDelegate[AsyncDelegateIndex] = ObjectExtend.CreateDelegate(GameState, function (Particle) local GameState = UGCGameSystem.GameState if GameState == nil or UE.IsValid(GameState) == false then return end if Particle ~= nil then self.PreLoadedEffects[index] = Particle else UE.Log("[AsyncLoadTools:PreLoadEffects] Error:"..EffectPath) end self.PendingPreLoadedEffectNum = self.PendingPreLoadedEffectNum - 1 if self.PendingPreLoadedEffectNum <= 0 then self.PreLoadEffectsCompleted = true end if GameState.AsyncDelegate[AsyncDelegateIndex] then ObjectExtend.DestroyDelegate(GameState.AsyncDelegate[AsyncDelegateIndex]) GameState.AsyncDelegate[AsyncDelegateIndex] = nil end end ) local softObjPath = KismetSystemLibrary.MakeSoftObjectPath(EffectPath) STExtraBlueprintFunctionLibrary.GetAssetByAssetReferenceAsync(softObjPath, GameState.AsyncDelegate[AsyncDelegateIndex], true) end end function AsyncLoadTools.GetEffectByIndex(Index) return AsyncLoadTools.PreLoadedEffects[Index] end return AsyncLoadTools