Add option *Select actors using this asset* to content menu

This commit is contained in:
Wojtek Figat
2021-10-06 12:06:56 +02:00
parent 6d72bfe149
commit 352abd1e41
5 changed files with 92 additions and 3 deletions

View File

@@ -245,6 +245,79 @@ namespace FlaxEditor.Modules
}
}
private static bool SelectActorsUsingAsset(Guid assetId, ref Guid id, Dictionary<Guid, bool> scannedAssets)
{
// Check for asset match or try to use cache
if (assetId == id)
return true;
if (scannedAssets.TryGetValue(id, out var result))
return result;
if (id == Guid.Empty || !FlaxEngine.Content.GetAssetInfo(id, out var assetInfo))
return false;
scannedAssets.Add(id, false);
// Skip scene assets
if (assetInfo.TypeName == "FlaxEngine.SceneAsset")
return false;
// Recursive check if this asset contains direct or indirect reference to the given asset
var asset = FlaxEngine.Content.Load<Asset>(assetInfo.ID, 1000);
if (asset)
{
var references = asset.GetReferences();
for (var i = 0; i < references.Length; i++)
{
if (SelectActorsUsingAsset(assetId, ref references[i], scannedAssets))
{
scannedAssets[id] = true;
return true;
}
}
}
return false;
}
private static void SelectActorsUsingAsset(Guid assetId, SceneGraphNode node, List<SceneGraphNode> selection, Dictionary<Guid, bool> scannedAssets)
{
if (node is ActorNode actorNode && actorNode.Actor)
{
// To detect if this actor uses the given asset simply serialize it to json and check used asset ids
// TODO: check scripts too
var json = actorNode.Actor.ToJson();
JsonAssetBase.GetReferences(json, out var ids);
for (var i = 0; i < ids.Length; i++)
{
if (SelectActorsUsingAsset(assetId, ref ids[i], scannedAssets))
{
selection.Add(actorNode);
break;
}
}
}
// Recursive check for children
for (int i = 0; i < node.ChildNodes.Count; i++)
SelectActorsUsingAsset(assetId, node.ChildNodes[i], selection, scannedAssets);
}
/// <summary>
/// Selects the actors using the given asset.
/// </summary>
/// <param name="assetId">The asset ID.</param>
/// <param name="additive">if set to <c>true</c> will use additive mode, otherwise will clear previous selection.</param>
public void SelectActorsUsingAsset(Guid assetId, bool additive = false)
{
// TODO: make it async action with progress
Profiler.BeginEvent("SelectActorsUsingAsset");
var selection = new List<SceneGraphNode>();
var scannedAssets = new Dictionary<Guid, bool>();
SelectActorsUsingAsset(assetId, Editor.Scene.Root, selection, scannedAssets);
Profiler.EndEvent();
Select(selection, additive);
}
/// <summary>
/// Spawns the specified actor to the game (with undo).
/// </summary>

View File

@@ -99,6 +99,7 @@ namespace FlaxEditor.Windows
if (item is AssetItem assetItem)
{
cm.AddButton("Copy asset ID", () => Clipboard.Text = JsonSerializer.GetStringID(assetItem.ID));
cm.AddButton("Select actors using this asset", () => Editor.SceneEditing.SelectActorsUsingAsset(assetItem.ID));
}
if (Editor.CanExport(item.Path))

View File

@@ -114,10 +114,7 @@ void BinaryAsset::Reimport() const
void BinaryAsset::GetImportMetadata(String& path, String& username) const
{
if (Metadata.IsInvalid())
{
LOG(Warning, "Missing asset metadata.");
return;
}
// Parse metadata and try to get import info
rapidjson_flax::Document document;

View File

@@ -83,6 +83,15 @@ void FindIds(ISerializable::DeserializeStream& node, Array<Guid>& output)
}
}
void JsonAssetBase::GetReferences(const StringAnsiView& json, Array<Guid>& output)
{
ISerializable::SerializeDocument document;
document.Parse(json.Get(), json.Length());
if (document.HasParseError())
return;
FindIds(document, output);
}
void JsonAssetBase::GetReferences(Array<Guid>& output) const
{
if (Data == nullptr)

View File

@@ -53,6 +53,15 @@ public:
/// </summary>
API_PROPERTY() String GetData() const;
#if USE_EDITOR
/// <summary>
/// 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);
#endif
public:
// [Asset]