// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik // using UnityEngine; using System; using System.Runtime.CompilerServices; using Object = UnityEngine.Object; namespace Animancer { /// /// A which holds a /// based on its . /// /// https://kybernetik.com.au/animancer/api/Animancer/StringAsset [AnimancerHelpUrl(typeof(StringAsset))] [CreateAssetMenu( menuName = Strings.MenuPrefix + "String Asset", order = Strings.AssetMenuOrder + 2)] public class StringAsset : ScriptableObject, IComparable, IConvertable, IConvertable, IEquatable, IEquatable, IEquatable, IHasKey { /************************************************************************************************************************/ private StringReference _Name; /// A to the . /// /// This value is gathered when first accessed, but will not be automatically updated after that /// because doing so causes some garbage allocation (except in the Unity Editor for convenience). /// public StringReference Name { #if UNITY_EDITOR // Don't do this at runtime because it allocates garbage every time. // But in the Unity Editor things could get renamed at any time. get => _Name = this ? name : ""; #else get => _Name ??= name; #endif set => _Name = name = value; } /// public object Key => Name; /************************************************************************************************************************/ #region Equality /************************************************************************************************************************/ /// Compares the s. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Compare(StringAsset a, StringAsset b) => a == b ? 0 : a ? a.CompareTo(b) : -1; /// Compares the s. [MethodImpl(MethodImplOptions.AggressiveInlining)] public int CompareTo(StringAsset other) => other ? Name.String.CompareTo(other.Name.String) : 1; /************************************************************************************************************************/ /// Is the equal to the `other`? [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(StringAsset other) => other is not null && Name == other.Name; /// Is the equal to the `other`? /// Uses . [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(StringReference other) => Name == other; /// Is the equal to the `value`? /// Checks regular string equality because the `value` might not be interned. [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(string value) => Name.String == value; /// Is the equal to the `other`? [MethodImpl(MethodImplOptions.AggressiveInlining)] public override bool Equals(object other) { if (other is StringAsset asset) return Equals(asset); if (other is StringReference reference) return Equals(reference); if (other is string value) return Equals(value); return false; } /************************************************************************************************************************/ /// Are the s equal? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(StringAsset a, StringAsset b) => a is null ? b is null : a.Equals(b); /// Are the s not equal? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(StringAsset a, StringAsset b) => a is null ? b is not null : !a.Equals(b); /************************************************************************************************************************/ /// Is the equal to `b`? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(StringAsset a, StringReference b) => a?.Name == b; /// Is the not equal to `b`? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(StringAsset a, StringReference b) => a?.Name != b; /// Is the equal to `a`? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(StringReference a, StringAsset b) => a == b?.Name; /// Is the not equal to `a`? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(StringReference a, StringAsset b) => a != b?.Name; /************************************************************************************************************************/ /// Is the equal to `b`? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(StringAsset a, string b) => a?.Name.String == b; /// Is the not equal to `b`? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(StringAsset a, string b) => a?.Name.String != b; /// Is the equal to `a`? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator ==(string a, StringAsset b) => b?.Name.String == a; /// Is the not equal to `a`? [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(string a, StringAsset b) => b?.Name.String != a; /************************************************************************************************************************/ /// Returns the hash code of the . [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() => Name.GetHashCode(); /************************************************************************************************************************/ #endregion /************************************************************************************************************************/ #region Conversion /************************************************************************************************************************/ /// Returns the . public override string ToString() => Name; /// StringReference IConvertable.Convert() => Name; /// string IConvertable.Convert() => Name; /************************************************************************************************************************/ /// Returns the . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator string(StringAsset key) => key?.Name; /// Returns the . [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator StringReference(StringAsset key) => key?.Name; /************************************************************************************************************************/ /// Creates a new array containing the s. public static StringReference[] ToStringReferences(params StringAsset[] keys) { if (keys == null) return null; if (keys.Length == 0) return Array.Empty(); var strings = new StringReference[keys.Length]; for (int i = 0; i < keys.Length; i++) strings[i] = keys[i]; return strings; } /// Creates a new array containing the s. public static string[] ToStrings(params StringAsset[] keys) { if (keys == null) return null; if (keys.Length == 0) return Array.Empty(); var strings = new string[keys.Length]; for (int i = 0; i < keys.Length; i++) strings[i] = keys[i]; return strings; } /************************************************************************************************************************/ #endregion /************************************************************************************************************************/ #if UNITY_EDITOR /************************************************************************************************************************/ [Tooltip("An unused Editor-Only field where you can explain what this asset is used for")] [SerializeField, TextArea(2, 25)] private string _EditorComment; /// [Editor-Only] [] /// An unused Editor-Only field where you can explain what this asset is used for. /// public ref string EditorComment => ref _EditorComment; /************************************************************************************************************************/ #endif } }