// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. #pragma once #include "CoreMinimal.h" #include "Engine/AssetManager.h" #include "OLSAssetManager.generated.h" DECLARE_LOG_CATEGORY_EXTERN(LogOLSAssetManager, Verbose, All); struct FOLSBundles { static const FName Equipped; }; /** * UOLSAssetManager * * Game implementation of the asset manager that overrides functionality and stores game-specific types. * It is expected that most games will want to override AssetManager as it provides a good place for game-specific loading logic. * Thi */ UCLASS(Config = Game) class OLS_API UOLSAssetManager : public UAssetManager { GENERATED_BODY() public: UOLSAssetManager(); // Returns the AssetManager singleton object. static UOLSAssetManager& Get(); // Returns the asset referenced by a TSoftObjectPtr. This will synchronously load the asset if it's not already loaded. template static AssetType* GetAsset(const TSoftObjectPtr& assetPointer, bool shouldKeepInMemory = true) { AssetType* loadedAsset = nullptr; const FSoftObjectPath& assetPath = assetPointer.ToSoftObjectPath(); if (assetPath.IsValid()) { loadedAsset = assetPointer.Get(); if (!loadedAsset) { loadedAsset = Cast(SynchronousLoadAsset(assetPath)); ensureAlwaysMsgf(loadedAsset, TEXT("Failed to load asset [%s]"), *assetPointer.ToString()); } if (loadedAsset && shouldKeepInMemory) { // Added to loaded asset list. Get().AddLoadedAsset(Cast(loadedAsset)); } } return loadedAsset; } // Returns the subclass referenced by a TSoftClassPtr. This will synchronously load the asset if it's not already loaded. template static TSubclassOf GetSubclass(const TSoftClassPtr& assetPointer, bool shouldKeepInMemory = true) { TSubclassOf loadedSubclass = nullptr; const FSoftObjectPath& assetPath = assetPointer.ToSoftObjectPath(); if (assetPath.IsValid()) { loadedSubclass = assetPointer.Get(); if (!loadedSubclass) { loadedSubclass = Cast(SynchronousLoadAsset(assetPath)); ensureAlwaysMsgf(loadedSubclass, TEXT("Failed to load asset class [%s]"), *assetPointer.ToString()); } if (loadedSubclass && shouldKeepInMemory) { // Added to loaded asset list. Get().AddLoadedAsset(Cast(loadedSubclass)); } } return loadedSubclass; } // Logs all assets currently loaded and tracked by the asset manager. static void DumpLoadedAssets(); const class UOLSGameDataAsset& GetGameData(); const class UOLSPawnDataAsset* GetDefaultPawnData() const; protected: template const GameDataClass& GetOrLoadTypedGameData(const TSoftObjectPtr& dataPath); static UObject* SynchronousLoadAsset(const FSoftObjectPath& assetPath); static bool ShouldLogAssetLoads(); // Thread safe way of adding a loaded asset to keep in memory. void AddLoadedAsset(const UObject* Asset); //~UAssetManager interface virtual void StartInitialLoading() override; #if WITH_EDITOR virtual void PreBeginPIE(bool shouldStartSimulate) override; #endif //~End of UAssetManager interface class UPrimaryDataAsset* LoadGameDataOfClass( TSubclassOf dataClass, const TSoftObjectPtr& dataClassPath, FPrimaryAssetType primaryAssetType); private: // Flushes the StartupJobs array. Processes all startup work. void DoAllStartupJobs(); // Sets up the ability system void InitializeGameplayCueManager(); // Called periodically during loads, could be used to feed the status to a loading screen void UpdateInitialGameContentLoadPercent(float gameContentPercent); protected: // Global game data asset to use. UPROPERTY(Config) TSoftObjectPtr OLSGameDataPath; // Loaded version of the game data UPROPERTY(Transient) TMap, TObjectPtr> GameDataMap; // Pawn data used when spawning player pawns if there isn't one set on the player state. UPROPERTY(Config) TSoftObjectPtr DefaultPawnData; private: // Assets loaded and tracked by the asset manager. UPROPERTY() TSet> LoadedAssets; // Used for a scope lock when modifying the list of load assets. FCriticalSection LoadedAssetsCritical; private: // The list of tasks to execute on startup. Used to track startup progress. TArray StartupJobs; };