// Copyright (c) Wojciech Figat. All rights reserved.
using System;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.CompilerServices;
using FlaxEngine.GUI;
namespace FlaxEngine
{
///
/// Interface for control references access.
///
public interface IControlReference
{
///
/// Gets or sets the reference to actor.
///
public UIControl UIControl { get; set; }
///
/// Gets the type of the control the interface uses.
///
public Type ControlType { get; }
///
/// Sets control ref by force - used during loading when is not loaded yet.
///
/// The reference.
internal void Load(UIControl control);
}
///
/// UI Control reference utility. References UI Control actor with a typed control type.
///
/// Type of the UI control object.
#if FLAX_EDITOR
[TypeConverter(typeof(TypeConverters.ControlReferenceConverter))]
#endif
public struct ControlReference : IControlReference, IComparable, IComparable>, IEquatable> where T : Control
{
private UIControl _uiControl;
///
/// Gets the typed UI control object owned by the referenced actor.
///
[HideInEditor]
public T Control
{
get
{
var control = _uiControl?.Control;
if (control == null)
return null;
if (control is T t)
return t;
Debug.Write(LogType.Warning, $"Trying to get Control from ControlReference but UIControl.Control is not correct type. It should be {typeof(T)} but is {control.GetType()}.");
return null;
}
}
///
public UIControl UIControl
{
get => _uiControl;
set
{
var control = value?.Control;
if (value == null)
{
_uiControl = null;
}
else if (control is T)
{
_uiControl = value;
}
else
{
Debug.Write(LogType.Warning, $"Trying to set UIControl but UIControl.Control is not the correct type. It should be {typeof(T)} but is {control.GetType()}.");
}
}
}
///
public Type ControlType => typeof(T);
///
public void Load(UIControl value)
{
_uiControl = value;
}
///
public override string ToString()
{
return _uiControl?.ToString() ?? "null";
}
///
public override int GetHashCode()
{
return _uiControl?.GetHashCode() ?? 0;
}
///
public int CompareTo(object obj)
{
if (obj is IControlReference other)
return Json.JsonSerializer.SceneObjectEquals(_uiControl, other.UIControl) ? 0 : 1;
return 1;
}
///
public int CompareTo(ControlReference other)
{
return Json.JsonSerializer.SceneObjectEquals(_uiControl, other._uiControl) ? 0 : 1;
}
///
public bool Equals(ControlReference other)
{
return Json.JsonSerializer.SceneObjectEquals(_uiControl, other._uiControl);
}
///
public override bool Equals(object obj)
{
return obj is ControlReference other && Json.JsonSerializer.SceneObjectEquals(_uiControl, other._uiControl);
}
///
/// The implicit operator for the Control.
///
/// The control reference.
/// The control object.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator T(ControlReference reference) => reference.Control;
///
/// The implicit operator for the UIControl.
///
/// The control reference.
/// The control actor.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator UIControl(ControlReference reference) => reference.UIControl;
///
/// Checks if the object exists (reference is not null and the unmanaged object pointer is valid).
///
/// The object to check.
/// True if object is valid, otherwise false.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator bool(ControlReference obj) => obj._uiControl;
///
/// Checks whether the two objects are equal.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(ControlReference left, ControlReference right) => Json.JsonSerializer.SceneObjectEquals(left._uiControl, right._uiControl);
///
/// Checks whether the two objects are not equal.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(ControlReference left, ControlReference right) => !Json.JsonSerializer.SceneObjectEquals(left._uiControl, right._uiControl);
}
}
#if FLAX_EDITOR
namespace FlaxEngine.TypeConverters
{
internal class ControlReferenceConverter : TypeConverter
{
///
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (value is string valueStr)
{
var result = Activator.CreateInstance(destinationType);
if (result is IControlReference control)
{
Json.JsonSerializer.ParseID(valueStr, out var id);
control.Load(Object.Find(ref id));
}
return result;
}
return base.ConvertTo(context, culture, value, destinationType);
}
///
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType.Name.StartsWith("ControlReference", StringComparison.Ordinal))
return true;
return base.CanConvertTo(context, destinationType);
}
}
}
#endif