Refactor Asset::GetReferences to support file path references

This commit is contained in:
Wojtek Figat
2024-05-08 15:54:37 +02:00
parent b91f51fb46
commit 66b828ae92
29 changed files with 121 additions and 135 deletions

View File

@@ -10,47 +10,26 @@
#include "Engine/Content/Assets/Shader.h"
#include "Engine/Content/Cache/AssetsCache.h"
bool CollectAssetsStep::Process(CookingData& data, Asset* asset)
{
// Skip virtual/temporary assets
if (asset->IsVirtual())
return false;
// Keep reference to the asset
AssetReference<Asset> ref(asset);
// Asset should have loaded data
if (asset->WaitForLoaded())
return false;
// Gather asset references
_references.Clear();
asset->Locker.Lock();
asset->GetReferences(_references);
asset->Locker.Unlock();
_assetsQueue.Add(_references);
return false;
}
bool CollectAssetsStep::Perform(CookingData& data)
{
LOG(Info, "Searching for assets to include in a build. Using {0} root assets.", data.RootAssets.Count());
data.StepProgress(TEXT("Collecting assets"), 0);
// Initialize assets queue
_assetsQueue.Clear();
_assetsQueue.EnsureCapacity(1024);
Array<Guid> assetsQueue;
assetsQueue.Clear();
assetsQueue.EnsureCapacity(1024);
for (auto i = data.RootAssets.Begin(); i.IsNotEnd(); ++i)
_assetsQueue.Add(i->Item);
assetsQueue.Add(i->Item);
// Iterate through the assets graph
AssetInfo assetInfo;
while (_assetsQueue.HasItems())
Array<Guid> references;
Array<String> files;
while (assetsQueue.HasItems())
{
BUILD_STEP_CANCEL_CHECK;
const auto assetId = _assetsQueue.Dequeue();
const auto assetId = assetsQueue.Dequeue();
// Skip already processed or invalid assets
if (!assetId.IsValid()
@@ -69,14 +48,26 @@ bool CollectAssetsStep::Perform(CookingData& data)
}
// Load asset
const auto asset = Content::LoadAsync<Asset>(assetId);
AssetReference<Asset> asset = Content::LoadAsync<Asset>(assetId);
if (asset == nullptr)
continue;
// Process that asset
LOG_STR(Info, asset->GetPath());
data.Assets.Add(assetId);
Process(data, asset);
// Skip virtual/temporary assets
if (asset->IsVirtual())
continue;
// Asset should have loaded data
if (asset->WaitForLoaded())
continue;
// Gather asset references
references.Clear();
asset->Locker.Lock();
asset->GetReferences(references, files);
asset->Locker.Unlock();
assetsQueue.Add(references);
}
data.Stats.TotalAssets = data.Assets.Count();

View File

@@ -12,15 +12,7 @@ class Asset;
/// <seealso cref="GameCooker::BuildStep" />
class CollectAssetsStep : public GameCooker::BuildStep
{
private:
Array<Guid> _assetsQueue;
Array<Guid> _references;
bool Process(CookingData& data, Asset* asset);
public:
// [BuildStep]
bool Perform(CookingData& data) override;
};

View File

@@ -232,12 +232,12 @@ void BehaviorTree::OnScriptsReloadEnd()
Graph.Setup(this);
}
void BehaviorTree::GetReferences(Array<Guid>& output) const
void BehaviorTree::GetReferences(Array<Guid>& assets, Array<String>& files) const
{
// Base
BinaryAsset::GetReferences(output);
BinaryAsset::GetReferences(assets, files);
Graph.GetReferences(output);
Graph.GetReferences(assets);
// Extract refs from serialized nodes data
for (const BehaviorTreeGraphNode& n : Graph.Nodes)
@@ -246,7 +246,7 @@ void BehaviorTree::GetReferences(Array<Guid>& output) const
continue;
const Variant& data = n.Values[1];
if (data.Type == VariantType::Blob)
JsonAssetBase::GetReferences(StringAnsiView((char*)data.AsBlob.Data, data.AsBlob.Length), output);
JsonAssetBase::GetReferences(StringAnsiView((char*)data.AsBlob.Data, data.AsBlob.Length), assets);
}
}

View File

@@ -98,7 +98,7 @@ public:
// [BinaryAsset]
void OnScriptingDispose() override;
#if USE_EDITOR
void GetReferences(Array<Guid>& output) const override;
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
#endif
protected:

View File

@@ -75,16 +75,16 @@ bool SceneAnimation::SaveTimeline(const BytesContainer& data)
#if USE_EDITOR
void SceneAnimation::GetReferences(Array<Guid>& output) const
void SceneAnimation::GetReferences(Array<Guid>& assets, Array<String>& files) const
{
// Base
BinaryAsset::GetReferences(output);
BinaryAsset::GetReferences(assets, files);
for (int32 i = 0; i < Tracks.Count(); i++)
{
const auto& track = Tracks[i];
if (track.Asset)
output.Add(track.Asset->GetID());
assets.Add(track.Asset->GetID());
}
}

View File

@@ -464,7 +464,7 @@ public:
public:
// [BinaryAsset]
#if USE_EDITOR
void GetReferences(Array<Guid>& output) const override;
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
#endif
protected:

View File

@@ -536,6 +536,14 @@ void Asset::CancelStreaming()
#if USE_EDITOR
void Asset::GetReferences(Array<Guid>& assets, Array<String>& files) const
{
// Fallback to the old API
PRAGMA_DISABLE_DEPRECATION_WARNINGS;
GetReferences(assets);
PRAGMA_ENABLE_DEPRECATION_WARNINGS;
}
void Asset::GetReferences(Array<Guid>& output) const
{
// No refs by default
@@ -544,7 +552,8 @@ void Asset::GetReferences(Array<Guid>& output) const
Array<Guid> Asset::GetReferences() const
{
Array<Guid> result;
GetReferences(result);
Array<String> files;
GetReferences(result, files);
return result;
}

View File

@@ -179,10 +179,13 @@ public:
/// For some asset types (e.g. scene or prefab) it may contain invalid asset ids due to not perfect gather method,
/// which is optimized to perform scan very quickly. Before using those ids perform simple validation via Content cache API.
/// The result collection contains only 1-level-deep references (only direct ones) and is invalid if asset is not loaded.
/// Also the output data may have duplicated asset ids or even invalid ids (Guid::Empty).
/// Also, the output data may have duplicated asset ids or even invalid ids (Guid::Empty).
/// </remarks>
/// <param name="output">The output collection of the asset ids referenced by this asset.</param>
virtual void GetReferences(Array<Guid, HeapAllocation>& output) const;
/// <param name="assets">The output collection of the asset ids referenced by this asset.</param>
/// <param name="files">The output list of file paths referenced by this asset. Files might come from project Content folder (relative path is preserved in cooked game), or external location (copied into Content root folder of cooked game).</param>
virtual void GetReferences(Array<Guid, HeapAllocation>& assets, Array<String, HeapAllocation>& files) const;
// [Deprecated in v1.9]
DEPRECATED virtual void GetReferences(Array<Guid, HeapAllocation>& output) const;
/// <summary>
/// Gets the asset references. Supported only in Editor.
@@ -191,7 +194,7 @@ public:
/// For some asset types (e.g. scene or prefab) it may contain invalid asset ids due to not perfect gather method,
/// which is optimized to perform scan very quickly. Before using those ids perform simple validation via Content cache API.
/// The result collection contains only 1-level-deep references (only direct ones) and is invalid if asset is not loaded.
/// Also the output data may have duplicated asset ids or even invalid ids (Guid::Empty).
/// Also, the output data may have duplicated asset ids or even invalid ids (Guid::Empty).
/// </remarks>
/// <returns>The collection of the asset ids referenced by this asset.</returns>
API_FUNCTION() Array<Guid, HeapAllocation> GetReferences() const;

View File

@@ -222,12 +222,10 @@ void AnimationGraph::FindDependencies(AnimGraphBase* graph)
}
}
void AnimationGraph::GetReferences(Array<Guid>& output) const
void AnimationGraph::GetReferences(Array<Guid>& assets, Array<String>& files) const
{
// Base
BinaryAsset::GetReferences(output);
Graph.GetReferences(output);
BinaryAsset::GetReferences(assets, files);
Graph.GetReferences(assets);
}
#endif

View File

@@ -64,7 +64,7 @@ private:
public:
// [BinaryAsset]
#if USE_EDITOR
void GetReferences(Array<Guid>& output) const override;
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
#endif
protected:

View File

@@ -45,3 +45,13 @@ MaterialInstance* MaterialBase::CreateVirtualInstance()
instance->SetBaseMaterial(this);
return instance;
}
#if USE_EDITOR
void MaterialBase::GetReferences(Array<Guid>& assets, Array<String>& files) const
{
BinaryAsset::GetReferences(assets, files);
Params.GetReferences(assets);
}
#endif

View File

@@ -25,7 +25,7 @@ public:
Action ParamsChanged;
/// <summary>
/// Returns true if material is an material instance.
/// Returns true if material is a material instance.
/// </summary>
virtual bool IsMaterialInstance() const = 0;
@@ -77,12 +77,6 @@ public:
public:
// [BinaryAsset]
#if USE_EDITOR
void GetReferences(Array<Guid>& output) const override
{
// Base
BinaryAsset::GetReferences(output);
Params.GetReferences(output);
}
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
#endif
};

View File

@@ -123,13 +123,11 @@ bool MaterialInstance::IsMaterialInstance() const
#if USE_EDITOR
void MaterialInstance::GetReferences(Array<Guid>& output) const
void MaterialInstance::GetReferences(Array<Guid>& assets, Array<String>& files) const
{
// Base
MaterialBase::GetReferences(output);
MaterialBase::GetReferences(assets, files);
if (_baseMaterial)
output.Add(_baseMaterial->GetID());
assets.Add(_baseMaterial->GetID());
}
#endif

View File

@@ -50,7 +50,7 @@ public:
// [MaterialBase]
bool IsMaterialInstance() const override;
#if USE_EDITOR
void GetReferences(Array<Guid>& output) const override;
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
#endif
// [IMaterial]

View File

@@ -788,15 +788,13 @@ void Model::CancelStreaming()
#if USE_EDITOR
void Model::GetReferences(Array<Guid>& output) const
void Model::GetReferences(Array<Guid>& assets, Array<String>& files) const
{
// Base
BinaryAsset::GetReferences(output);
BinaryAsset::GetReferences(assets, files);
for (int32 i = 0; i < MaterialSlots.Count(); i++)
{
output.Add(MaterialSlots[i].Material.GetID());
}
assets.Add(MaterialSlots[i].Material.GetID());
}
#endif

View File

@@ -251,7 +251,7 @@ public:
void InitAsVirtual() override;
void CancelStreaming() override;
#if USE_EDITOR
void GetReferences(Array<Guid>& output) const override;
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
#endif
// [StreamableResource]

View File

@@ -68,12 +68,10 @@ private:
public:
// [BinaryAsset]
#if USE_EDITOR
void GetReferences(Array<Guid>& output) const override
void GetReferences(Array<Guid>& assets, Array<String>& files) const override
{
// Base
BinaryAsset::GetReferences(output);
output.Add(Skeleton.GetID());
BinaryAsset::GetReferences(assets, files);
assets.Add(Skeleton.GetID());
}
#endif

View File

@@ -974,15 +974,13 @@ void SkinnedModel::CancelStreaming()
#if USE_EDITOR
void SkinnedModel::GetReferences(Array<Guid>& output) const
void SkinnedModel::GetReferences(Array<Guid>& assets, Array<String>& files) const
{
// Base
BinaryAsset::GetReferences(output);
BinaryAsset::GetReferences(assets, files);
for (int32 i = 0; i < MaterialSlots.Count(); i++)
{
output.Add(MaterialSlots[i].Material.GetID());
}
assets.Add(MaterialSlots[i].Material.GetID());
}
#endif

View File

@@ -323,7 +323,7 @@ public:
void InitAsVirtual() override;
void CancelStreaming() override;
#if USE_EDITOR
void GetReferences(Array<Guid>& output) const override;
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
#endif
// [StreamableResource]

View File

@@ -277,12 +277,10 @@ public:
public:
// [BinaryAsset]
#if USE_EDITOR
void GetReferences(Array<Guid>& output) const override
void GetReferences(Array<Guid>& assets, Array<String>& files) const override
{
// Base
BinaryAsset::GetReferences(output);
Graph.GetReferences(output);
BinaryAsset::GetReferences(assets, files);
Graph.GetReferences(assets);
}
#endif

View File

@@ -109,20 +109,20 @@ uint64 JsonAssetBase::GetMemoryUsage() const
#if USE_EDITOR
void FindIds(ISerializable::DeserializeStream& node, Array<Guid>& output)
void FindIds(ISerializable::DeserializeStream& node, Array<Guid>& output, Array<String>& files)
{
if (node.IsObject())
{
for (auto i = node.MemberBegin(); i != node.MemberEnd(); ++i)
{
FindIds(i->value, output);
FindIds(i->value, output, files);
}
}
else if (node.IsArray())
{
for (rapidjson::SizeType i = 0; i < node.Size(); i++)
{
FindIds(node[i], output);
FindIds(node[i], output, files);
}
}
else if (node.IsString())
@@ -137,13 +137,14 @@ void FindIds(ISerializable::DeserializeStream& node, Array<Guid>& output)
}
}
void JsonAssetBase::GetReferences(const StringAnsiView& json, Array<Guid>& output)
void JsonAssetBase::GetReferences(const StringAnsiView& json, Array<Guid>& assets)
{
ISerializable::SerializeDocument document;
document.Parse(json.Get(), json.Length());
if (document.HasParseError())
return;
FindIds(document, output);
Array<String> files;
FindIds(document, assets, files);
}
bool JsonAssetBase::Save(const StringView& path) const
@@ -207,7 +208,7 @@ bool JsonAssetBase::Save(JsonWriter& writer) const
return false;
}
void JsonAssetBase::GetReferences(Array<Guid>& output) const
void JsonAssetBase::GetReferences(Array<Guid>& assets, Array<String>& files) const
{
if (Data == nullptr)
return;
@@ -219,7 +220,7 @@ void JsonAssetBase::GetReferences(Array<Guid>& output) const
// It produces many invalid ids (like refs to scene objects).
// But it's super fast, super low-memory and doesn't involve any advanced systems integration.
FindIds(*Data, output);
FindIds(*Data, assets, files);
}
#endif

View File

@@ -70,8 +70,8 @@ public:
/// Parses Json string to find any object references inside it. It can produce list of references to assets and/or scene objects. Supported only in Editor.
/// </summary>
/// <param name="json">The Json string.</param>
/// <param name="output">The output list of object IDs references by the asset (appended, not cleared).</param>
API_FUNCTION() static void GetReferences(const StringAnsiView& json, API_PARAM(Out) Array<Guid, HeapAllocation>& output);
/// <param name="assets">The output list of object IDs references by the asset (appended, not cleared).</param>
API_FUNCTION() static void GetReferences(const StringAnsiView& json, API_PARAM(Out) Array<Guid, HeapAllocation>& assets);
/// <summary>
/// Saves this asset to the file. Supported only in Editor.
@@ -97,7 +97,7 @@ public:
const String& GetPath() const override;
uint64 GetMemoryUsage() const override;
#if USE_EDITOR
void GetReferences(Array<Guid, HeapAllocation>& output) const override;
void GetReferences(Array<Guid, HeapAllocation>& assets, Array<String, HeapAllocation>& files) const override;
#endif
protected:

View File

@@ -1042,12 +1042,12 @@ void MaterialParams::Save(BytesContainer& data, const Array<SerializedMaterialPa
#if USE_EDITOR
void MaterialParams::GetReferences(Array<Guid>& output) const
void MaterialParams::GetReferences(Array<Guid>& assets) const
{
for (int32 i = 0; i < Count(); i++)
{
if (At(i)._asAsset)
output.Add(At(i)._asAsset->GetID());
assets.Add(At(i)._asAsset->GetID());
}
}

View File

@@ -417,13 +417,11 @@ public:
public:
#if USE_EDITOR
/// <summary>
/// Gets the asset references (see Asset.GetReferences for more info).
/// </summary>
/// <param name="output">The output.</param>
void GetReferences(Array<Guid>& output) const;
/// <param name="assets">The output assets.</param>
void GetReferences(Array<Guid>& assets) const;
#endif
bool HasContentLoaded() const;

View File

@@ -127,7 +127,8 @@ Array<Guid> Scene::GetAssetReferences() const
const auto asset = Content::Load<SceneAsset>(GetID());
if (asset)
{
asset->GetReferences(result);
Array<String> files;
asset->GetReferences(result, files);
}
else
{

View File

@@ -172,12 +172,10 @@ public:
public:
// [BinaryAsset]
#if USE_EDITOR
void GetReferences(Array<Guid>& output) const override
void GetReferences(Array<Guid>& assets, Array<String>& files) const override
{
// Base
BinaryAsset::GetReferences(output);
Graph.GetReferences(output);
BinaryAsset::GetReferences(assets, files);
Graph.GetReferences(assets);
}
#endif

View File

@@ -181,19 +181,19 @@ void ParticleSystem::InitAsVirtual()
#if USE_EDITOR
void ParticleSystem::GetReferences(Array<Guid>& output) const
void ParticleSystem::GetReferences(Array<Guid>& assets, Array<String>& files) const
{
// Base
BinaryAsset::GetReferences(output);
BinaryAsset::GetReferences(assets, files);
for (int32 i = 0; i < Emitters.Count(); i++)
output.Add(Emitters[i].GetID());
assets.Add(Emitters[i].GetID());
for (auto i = EmittersParametersOverrides.Begin(); i.IsNotEnd(); ++i)
{
const auto id = (Guid)i->Value;
if (id.IsValid())
output.Add(id);
assets.Add(id);
}
}

View File

@@ -13,6 +13,7 @@
API_CLASS(NoSpawn) class FLAXENGINE_API ParticleSystem : public BinaryAsset
{
DECLARE_BINARY_ASSET_HEADER(ParticleSystem, 1);
public:
/// <summary>
/// The particle system timeline track data.
@@ -173,7 +174,7 @@ public:
/// Spawns the particles at the given location.
/// </summary>
/// <param name="position">The spawn position.</param>
/// <param name="autoDestroy">If set to <c>true</c> effect be be auto-destroyed after duration.</param>
/// <param name="autoDestroy">If set to <c>true</c> effect be auto-destroyed after duration.</param>
/// <returns>The spawned effect.</returns>
API_FUNCTION() ParticleEffect* Spawn(const Vector3& position, bool autoDestroy = false)
{
@@ -185,7 +186,7 @@ public:
/// </summary>
/// <param name="position">The spawn position.</param>
/// <param name="rotation">The spawn rotation.</param>
/// <param name="autoDestroy">If set to <c>true</c> effect be be auto-destroyed after duration.</param>
/// <param name="autoDestroy">If set to <c>true</c> effect be auto-destroyed after duration.</param>
/// <returns>The spawned effect.</returns>
API_FUNCTION() ParticleEffect* Spawn(const Vector3& position, const Quaternion& rotation, bool autoDestroy = false)
{
@@ -196,9 +197,9 @@ public:
/// Spawns the particles at the given location.
/// </summary>
/// <param name="transform">The spawn transform.</param>
/// <param name="autoDestroy">If set to <c>true</c> effect be be auto-destroyed after duration.</param>
/// <param name="autoDestroy">If set to <c>true</c> effect be auto-destroyed after duration.</param>
/// <returns>The spawned effect.</returns>
API_FUNCTION() ParticleEffect* Spawn(Transform transform, bool autoDestroy = false)
API_FUNCTION() ParticleEffect* Spawn(const Transform& transform, bool autoDestroy = false)
{
return Spawn(nullptr, transform, autoDestroy);
}
@@ -208,7 +209,7 @@ public:
/// </summary>
/// <param name="parent">The parent actor (can be null to link it to the first loaded scene).</param>
/// <param name="position">The spawn position.</param>
/// <param name="autoDestroy">If set to <c>true</c> effect be be auto-destroyed after duration.</param>
/// <param name="autoDestroy">If set to <c>true</c> effect be auto-destroyed after duration.</param>
/// <returns>The spawned effect.</returns>
API_FUNCTION() ParticleEffect* Spawn(Actor* parent, const Vector3& position, bool autoDestroy = false)
{
@@ -221,7 +222,7 @@ public:
/// <param name="parent">The parent actor (can be null to link it to the first loaded scene).</param>
/// <param name="position">The spawn position.</param>
/// <param name="rotation">The spawn rotation.</param>
/// <param name="autoDestroy">If set to <c>true</c> effect be be auto-destroyed after duration.</param>
/// <param name="autoDestroy">If set to <c>true</c> effect be auto-destroyed after duration.</param>
/// <returns>The spawned effect.</returns>
API_FUNCTION() ParticleEffect* Spawn(Actor* parent, Vector3 position, Quaternion rotation, bool autoDestroy = false)
{
@@ -233,7 +234,7 @@ public:
/// </summary>
/// <param name="parent">The parent actor (can be null to link it to the first loaded scene).</param>
/// <param name="transform">The spawn transform.</param>
/// <param name="autoDestroy">If set to <c>true</c> effect be be auto-destroyed after duration.</param>
/// <param name="autoDestroy">If set to <c>true</c> effect be auto-destroyed after duration.</param>
/// <returns>The spawned effect.</returns>
API_FUNCTION() ParticleEffect* Spawn(Actor* parent, const Transform& transform, bool autoDestroy = false);
@@ -241,7 +242,7 @@ public:
// [BinaryAsset]
void InitAsVirtual() override;
#if USE_EDITOR
void GetReferences(Array<Guid>& output) const override;
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
#endif
protected:

View File

@@ -529,15 +529,15 @@ public:
/// Gets the asset references.
/// </summary>
/// </remarks>
/// <param name="output">The output collection of the asset ids referenced by this object.</param>
virtual void GetReferences(Array<Guid>& output) const
/// <param name="assets">The output collection of the asset ids referenced by this object.</param>
virtual void GetReferences(Array<Guid>& assets) const
{
for (int32 i = 0; i < Parameters.Count(); i++)
{
const auto& p = Parameters[i];
const Guid id = (Guid)p.Value;
if (id.IsValid())
output.Add(id);
assets.Add(id);
}
for (int32 i = 0; i < Nodes.Count(); i++)
@@ -547,7 +547,7 @@ public:
{
const Guid id = (Guid)n.Values[j];
if (id.IsValid())
output.Add(id);
assets.Add(id);
}
}
}