// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Scripting/ScriptingType.h" #include "AssetInfo.h" #include "Asset.h" #include "Config.h" class Engine; class FlaxFile; class IAssetFactory; class AssetsCache; // Content and assets statistics container. API_STRUCT() struct FLAXENGINE_API ContentStats { DECLARE_SCRIPTING_TYPE_MINIMAL(ContentStats); // Amount of asset objects in memory. API_FIELD() int32 AssetsCount = 0; // Amount of loaded assets. API_FIELD() int32 LoadedAssetsCount = 0; // Amount of loading assets. Zero if all assets are loaded in. API_FIELD() int32 LoadingAssetsCount = 0; // Amount of virtual assets (don't have representation in file). API_FIELD() int32 VirtualAssetsCount = 0; }; /// /// Loads and manages assets. /// API_CLASS(Static) class FLAXENGINE_API Content { DECLARE_SCRIPTING_TYPE_NO_SPAWN(Content); friend Engine; friend Asset; public: /// /// The time between content pool updates. /// static TimeSpan AssetsUpdateInterval; /// /// The time after asset with no references will be unloaded. /// static TimeSpan AssetsUnloadInterval; public: /// /// Gets the assets registry. /// /// The assets cache. static AssetsCache* GetRegistry(); public: /// /// Finds the asset info by id. /// /// The asset id. /// The output asset info. Filled with valid values only if method returns true. /// True if found any asset, otherwise false. API_FUNCTION() static bool GetAssetInfo(const Guid& id, API_PARAM(Out) AssetInfo& info); /// /// Finds the asset info by path. /// /// The asset path. /// The output asset info. Filled with valid values only if method returns true. /// True if found any asset, otherwise false. API_FUNCTION() static bool GetAssetInfo(const StringView& path, API_PARAM(Out) AssetInfo& info); /// /// Finds the asset path by id. In editor it returns the actual asset path, at runtime it returns the mapped asset path. /// /// The asset id. /// The asset path, or empty if failed to find. API_FUNCTION() static String GetEditorAssetPath(const Guid& id); /// /// Finds all the asset IDs. Uses asset registry. /// /// The list of all asset IDs. API_FUNCTION() static Array GetAllAssets(); /// /// Finds all the asset IDs by type (exact type, without inheritance checks). Uses asset registry. /// /// The asset type. /// The list of asset IDs that match the given type. API_FUNCTION() static Array GetAllAssetsByType(const MClass* type); public: /// /// Gets the asset factory used by the given asset type id. /// /// The asset type name identifier. /// Asset factory or null if not found. static IAssetFactory* GetAssetFactory(const StringView& typeName); /// /// Gets the asset factory used by the given asset type id. /// /// The asset info. /// Asset factory or null if not found. static IAssetFactory* GetAssetFactory(const AssetInfo& assetInfo); public: /// /// Generates temporary asset path. /// /// Asset path for a temporary usage. API_FUNCTION() static String CreateTemporaryAssetPath(); public: /// /// Gets content statistics. /// API_PROPERTY() static ContentStats GetStats(); /// /// Gets the assets (loaded or during load). /// /// The collection of assets. API_PROPERTY() static Array GetAssets(); /// /// Gets the raw dictionary of assets (loaded or during load). /// /// The collection of assets. static const Dictionary& GetAssetsRaw(); /// /// Loads asset and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async. /// /// Asset unique ID /// The asset type. If loaded object has different type (excluding types derived from the given) the loading fails. /// Loaded asset or null if cannot API_FUNCTION() static Asset* LoadAsync(const Guid& id, API_PARAM(Attributes="TypeReference(typeof(Asset))") const MClass* type); /// /// Loads asset and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async. /// /// Asset unique ID /// The asset type. If loaded object has different type (excluding types derived from the given) the loading fails. /// Loaded asset or null if cannot static Asset* LoadAsync(const Guid& id, const ScriptingTypeHandle& type); /// /// Loads asset and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async. /// /// Asset unique ID /// Type of the asset to load. Includes any asset types derived from the type. /// Loaded asset or null if cannot template FORCE_INLINE static T* LoadAsync(const Guid& id) { return static_cast(LoadAsync(id, T::TypeInitializer)); } /// /// Loads asset and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async. /// /// The path of the asset (absolute or relative to the current workspace directory). /// The asset type. If loaded object has different type (excluding types derived from the given) the loading fails. /// Loaded asset or null if cannot API_FUNCTION(Attributes="HideInEditor") static Asset* LoadAsync(const StringView& path, const MClass* type); /// /// Loads asset and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async. /// /// The path of the asset (absolute or relative to the current workspace directory). /// The asset type. If loaded object has different type (excluding types derived from the given) the loading fails. /// Loaded asset or null if cannot static Asset* LoadAsync(const StringView& path, const ScriptingTypeHandle& type); /// /// Loads asset and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async. /// /// The path of the asset (absolute or relative to the current workspace directory). /// Type of the asset to load. Includes any asset types derived from the type. /// Loaded asset or null if cannot template FORCE_INLINE static T* LoadAsync(const StringView& path) { return static_cast(LoadAsync(path, T::TypeInitializer)); } /// /// Loads internal engine asset and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async. /// /// The path of the asset relative to the engine internal content (excluding the extension). /// The asset type. If loaded object has different type (excluding types derived from the given) the loading fails. /// The loaded asset or null if failed. API_FUNCTION(Attributes="HideInEditor") static Asset* LoadAsyncInternal(const StringView& internalPath, const MClass* type); /// /// Loads internal engine asset and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async. /// /// The path of the asset relative to the engine internal content (excluding the extension). /// The asset type. If loaded object has different type (excluding types derived from the given) the loading fails. /// The loaded asset or null if failed. static Asset* LoadAsyncInternal(const StringView& internalPath, const ScriptingTypeHandle& type); /// /// Loads internal engine asset and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async. /// /// The path of the asset relative to the engine internal content (excluding the extension). /// The asset type. If loaded object has different type (excluding types derived from the given) the loading fails. /// The loaded asset or null if failed. static Asset* LoadAsyncInternal(const Char* internalPath, const ScriptingTypeHandle& type); /// /// Loads internal engine asset and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async. /// /// The path of the asset relative to the engine internal content (excluding the extension). /// The loaded asset or null if failed. template FORCE_INLINE static T* LoadAsyncInternal(const Char* internalPath) { return static_cast(LoadAsyncInternal(internalPath, T::TypeInitializer)); } /// /// Loads asset to the Content Pool and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async. /// Waits until asset will be loaded. It's equivalent to LoadAsync + WaitForLoaded. /// /// Asset unique ID. /// Custom timeout value in milliseconds. /// Type of the asset to load. Includes any asset types derived from the type. /// Asset instance if loaded, null otherwise. template static T* Load(const Guid& id, double timeoutInMilliseconds = 30000.0) { auto asset = LoadAsync(id); if (asset && !asset->WaitForLoaded(timeoutInMilliseconds)) return asset; return nullptr; } /// /// Loads asset to the Content Pool and holds it until it won't be referenced by any object. Returns null if asset is missing. Actual asset data loading is performed on a other thread in async. /// Waits until asset will be loaded. It's equivalent to LoadAsync + WaitForLoaded. /// /// The path of the asset (absolute or relative to the current workspace directory). /// Custom timeout value in milliseconds. /// Type of the asset to load. Includes any asset types derived from the type. /// Asset instance if loaded, null otherwise. template static T* Load(const StringView& path, double timeoutInMilliseconds = 30000.0) { auto asset = LoadAsync(path); if (asset && !asset->WaitForLoaded(timeoutInMilliseconds)) return asset; return nullptr; } /// /// Determines whether input asset type name identifier is invalid. /// /// The requested type of the asset to be. /// The actual type of the asset. /// true if asset type identifier is invalid otherwise, false. static bool IsAssetTypeIdInvalid(const ScriptingTypeHandle& type, const ScriptingTypeHandle& assetType); public: /// /// Finds the asset with at given path. Checks all loaded assets. /// /// The path. /// The found asset or null if not loaded. API_FUNCTION() static Asset* GetAsset(const StringView& path); /// /// Finds the asset with given ID. Checks all loaded assets. /// /// The id. /// The found asset or null if not loaded. API_FUNCTION() static Asset* GetAsset(const Guid& id); public: /// /// Deletes the specified asset. /// /// The asset. API_FUNCTION() static void DeleteAsset(Asset* asset); /// /// Deletes the asset at the specified path. /// /// The asset path. API_FUNCTION(Attributes="HideInEditor") static void DeleteAsset(const StringView& path); public: #if USE_EDITOR /// /// Renames the asset. /// /// The old asset path. /// The new asset path. /// True if failed, otherwise false. API_FUNCTION() static bool RenameAsset(const StringView& oldPath, const StringView& newPath); /// /// Performs the fast temporary asset clone to the temporary folder. /// /// The source path. /// The result path. /// True if failed, otherwise false. static bool FastTmpAssetClone(const StringView& path, String& resultPath); /// /// Clones the asset file. /// /// The destination path. /// The source path. /// The destination id. /// True if failed, otherwise false. static bool CloneAssetFile(const StringView& dstPath, const StringView& srcPath, const Guid& dstId); #endif /// /// Unloads the specified asset. /// /// The asset. API_FUNCTION() static void UnloadAsset(Asset* asset); /// /// Creates temporary and virtual asset of the given type. /// /// Created asset or null if failed. template FORCE_INLINE static T* CreateVirtualAsset() { return static_cast(CreateVirtualAsset(T::TypeInitializer));; } /// /// Creates temporary and virtual asset of the given type. /// /// The asset type klass. /// Created asset or null if failed. API_FUNCTION() static Asset* CreateVirtualAsset(API_PARAM(Attributes="TypeReference(typeof(Asset))") const MClass* type); /// /// Creates temporary and virtual asset of the given type. /// /// The asset type. /// Created asset or null if failed. static Asset* CreateVirtualAsset(const ScriptingTypeHandle& type); /// /// Occurs when asset is being disposed and will be unloaded (by force). All references to it should be released. /// API_EVENT() static Delegate AssetDisposing; /// /// Occurs when asset is being reloaded and will be unloaded (by force) to be loaded again (e.g. after reimport). Always called from the main thread. /// API_EVENT() static Delegate AssetReloading; private: static void tryCallOnLoaded(Asset* asset); static void onAssetLoaded(Asset* asset); static void onAssetUnload(Asset* asset); static void onAssetChangeId(Asset* asset, const Guid& oldId, const Guid& newId); private: static void deleteFileSafety(const StringView& path, const Guid& id); };