// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
using System;
using System.Linq;
using FlaxEditor.Content;
using FlaxEditor.CustomEditors.Elements;
using FlaxEditor.GUI;
using FlaxEditor.GUI.Drag;
using FlaxEditor.SceneGraph;
using FlaxEditor.Scripting;
using FlaxEngine;
using FlaxEngine.GUI;
using Object = FlaxEngine.Object;
namespace FlaxEditor.CustomEditors.Editors
{
///
/// A custom control type used to pick reference to .
///
///
public class FlaxObjectRefPickerControl : Control
{
private ScriptType _type;
private Object _value;
private string _valueName;
private bool _supportsPickDropDown;
private bool _isMouseDown;
private Vector2 _mouseDownPos;
private Vector2 _mousePos;
private bool _hasValidDragOver;
private DragActors _dragActors;
private DragActors _dragActorsWithScript;
private DragAssets _dragAssets;
private DragScripts _dragScripts;
private DragHandlers _dragHandlers;
///
/// Gets or sets the allowed objects type (given type and all sub classes). Must be type of any subclass.
///
public ScriptType Type
{
get => _type;
set
{
if (_type == value)
return;
if (value == ScriptType.Null || (value.Type != typeof(Object) && !value.IsSubclassOf(new ScriptType(typeof(Object)))))
throw new ArgumentException(string.Format("Invalid type for FlaxObjectRefEditor. Input type: {0}", value != ScriptType.Null ? value.TypeName : "null"));
_type = value;
_supportsPickDropDown = new ScriptType(typeof(Actor)).IsAssignableFrom(value) || new ScriptType(typeof(Script)).IsAssignableFrom(value);
// Deselect value if it's not valid now
if (!IsValid(_value))
Value = null;
}
}
///
/// Gets or sets the selected object value.
///
public Object Value
{
get => _value;
set
{
if (_value == value)
return;
if (!IsValid(value))
throw new ArgumentException("Invalid object type.");
// Special case for missing objects (eg. referenced actor in script that is deleted in editor)
if (value != null && (Object.GetUnmanagedPtr(value) == IntPtr.Zero || value.ID == Guid.Empty))
value = null;
_value = value;
var type = TypeUtils.GetObjectType(_value);
// Get name to display
if (_value is Script script)
{
_valueName = script.Actor ? $"{type.Name} ({script.Actor.Name})" : type.Name;
}
else if (_value != null)
{
_valueName = _value.ToString();
}
else
{
_valueName = string.Empty;
}
// Update tooltip
if (_value is SceneObject sceneObject)
{
var str = sceneObject is Actor actor ? actor.Name : type.Name;
var o = sceneObject.Parent;
while (o)
{
str = o.Name + " -> " + str;
o = o.Parent;
}
TooltipText = str;
}
else
{
TooltipText = string.Empty;
}
OnValueChanged();
}
}
///
/// Gets or sets the selected object value by identifier.
///
public Guid ValueID
{
get => _value ? _value.ID : Guid.Empty;
set => Value = Object.Find