// 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