// Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2023 Kybernetik // using System; using System.Reflection; #if UNITY_EDITOR using Animancer.Editor; using UnityEditor; #endif namespace Animancer { /// [Editor-Conditional] Specifies the default value of a field and a secondary fallback. /// https://kybernetik.com.au/animancer/api/Animancer/DefaultValueAttribute /// [AttributeUsage(AttributeTargets.Field)] [System.Diagnostics.Conditional(Strings.UnityEditor)] public class DefaultValueAttribute : Attribute { /************************************************************************************************************************/ /// The main default value. public virtual object Primary { get; protected set; } /************************************************************************************************************************/ /// The fallback value to use if the target value was already equal to the . public virtual object Secondary { get; protected set; } /************************************************************************************************************************/ /// Creates a new . public DefaultValueAttribute(object primary, object secondary = null) { Primary = primary; Secondary = secondary; } /************************************************************************************************************************/ /// Creates a new . protected DefaultValueAttribute() { } /************************************************************************************************************************/ #if UNITY_EDITOR /************************************************************************************************************************/ /// [Editor-Only] /// If the field represented by the `property` has a , this method sets /// the `value` to its value. If it was already at the value, it sets it to the /// value instead. And if the field has no attribute, it uses the default for the type. /// public static void SetToDefault(ref T value, SerializedProperty property) { var accessor = property.GetAccessor(); var field = accessor.GetField(property); if (field == null) accessor.SetValue(property, null); else SetToDefault(ref value, field); } /************************************************************************************************************************/ /// [Editor-Only] /// If the field represented by the `property` has a , this method sets /// the `value` to its value. If it was already at the value, it sets it to the /// value instead. And if the field has no attribute, it uses the default for the type. /// public static void SetToDefault(ref T value, FieldInfo field) { var defaults = field.GetAttribute(); if (defaults != null) defaults.SetToDefault(ref value); else value = default; } /************************************************************************************************************************/ /// [Editor-Only] /// Sets the `value` equal to the value. If it was already at the value, it sets it equal /// to the value instead. /// public void SetToDefault(ref T value) { var primary = Primary; if (!Equals(value, primary)) { value = (T)primary; return; } var secondary = Secondary; if (secondary != null || !typeof(T).IsValueType) { value = (T)secondary; return; } } /************************************************************************************************************************/ /// [Editor-Only] /// Sets the `value` equal to the `primary` value. If it was already at the value, it sets it equal to the /// `secondary` value instead. /// public static void SetToDefault(ref T value, T primary, T secondary) { if (!Equals(value, primary)) value = primary; else value = secondary; } /************************************************************************************************************************/ #endif /************************************************************************************************************************/ } }