Add option *Select actors using this asset* to content menu
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user