// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Utilities;
namespace FlaxEditor.GUI
{
///
/// Popup that shows the list of scene objects to pick. Supports searching and basic type filtering.
///
///
public class SceneObjectSearchPopup : ItemsListContextMenu
{
///
/// The scene object item.
///
///
public class SceneObjectItemView : Item
{
private SceneObject _object;
///
/// Gets the scene object.
///
public SceneObject Object => _object;
///
/// Initializes a new instance of the class.
///
/// The object.
public SceneObjectItemView(SceneObject obj)
{
_object = obj;
Category = obj is Actor ? "Actors" : "Scripts";
if (obj is Script script)
{
var type = TypeUtils.GetObjectType(script);
Name = script.Actor ? $"{type.Name} ({script.Actor.Name})" : type.Name;
}
else if (obj is Actor actor)
{
Name = actor.Name;
}
else
{
Name = obj.ToString();
}
TooltipText = Utilities.Utils.GetTooltip(obj);
}
///
public override void OnDestroy()
{
_object = null;
base.OnDestroy();
}
}
///
/// Validates if the given scene object item can be used to pick it.
///
/// The scene object.
/// True if is valid.
public delegate bool IsValidDelegate(SceneObject obj);
private IsValidDelegate _isValid;
private Action _selected;
private SceneObjectSearchPopup(IsValidDelegate isValid, Action selected, CustomEditors.IPresenterOwner context)
{
_isValid = isValid;
_selected = selected;
ItemClicked += OnItemClicked;
if (context is PropertiesWindow || context == null)
{
// TODO: use async thread to search scenes
for (int i = 0; i < Level.ScenesCount; i++)
{
Find(Level.GetScene(i));
}
}
else if (context is PrefabWindow prefabWindow)
{
Find(prefabWindow.Graph.MainActor);
}
SortItems();
}
private void OnItemClicked(Item item)
{
_selected(((SceneObjectItemView)item).Object);
}
private void Find(Actor actor)
{
if (!actor)
return;
if (_isValid(actor))
AddItem(new SceneObjectItemView(actor));
for (int i = 0; i < actor.ScriptsCount; i++)
{
var script = actor.GetScript(i);
if (_isValid(script))
AddItem(new SceneObjectItemView(script));
}
for (int i = 0; i < actor.ChildrenCount; i++)
{
Find(actor.GetChild(i));
}
}
///
/// Shows the popup.
///
/// The show target.
/// The show target location.
/// Event called to check if a given scene object item is valid to be used.
/// Event called on scene object item pick.
/// The presenter owner context (i.e. PrefabWindow, PropertiesWindow).
/// The dialog.
public static SceneObjectSearchPopup Show(Control showTarget, Float2 showTargetLocation, IsValidDelegate isValid, Action selected, CustomEditors.IPresenterOwner context)
{
var popup = new SceneObjectSearchPopup(isValid, selected, context);
popup.Show(showTarget, showTargetLocation);
return popup;
}
///
public override void OnDestroy()
{
_isValid = null;
_selected = null;
base.OnDestroy();
}
}
}