// 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);
};