#if ENABLE_PROPERTY_VARIANTS || PACKAGE_DOCS_GENERATION using System; using System.Collections.Generic; using UnityEngine.Localization.SmartFormat; namespace UnityEngine.Localization.PropertyVariants.TrackedProperties { /// /// Interface for accessing a tracked property`s values. /// /// The property data type. public interface ITrackedPropertyValue : ITrackedProperty { /// /// Attempts to find a value for the provided LocaleIdentifier. /// /// The LocaleIdentifier to check for. /// The value found for the LocaleIdentifier. /// if a value was found and if one was not. bool GetValue(LocaleIdentifier localeIdentifier, out T foundValue); /// /// Attempts to find a value for the provided LocaleIdentifier or fallback. /// /// The LocaleIdentifier to check for. /// The LocaleIdentifier to fallback to if one could not be found for . /// The value found for the LocaleIdentifier or fallback. /// if a value was found and if one was not. bool GetValue(LocaleIdentifier localeIdentifier, LocaleIdentifier fallback, out T foundValue); /// /// Assigns a value for the chosen LocaleIdentifier. /// /// The LocaleIdentifier the variant should be applied to /// The variant value for the LocaleIdentifier. void SetValue(LocaleIdentifier localeIdentifier, T value); } internal interface ITrackedPropertyRemoveVariant { void RemoveVariant(LocaleIdentifier localeIdentifier); } /// /// Represents a property for a primitive data type. /// /// The primitive data type. [Serializable] public class TrackedProperty : ITrackedPropertyValue, IStringProperty, ISerializationCallbackReceiver, ITrackedPropertyRemoveVariant { [Serializable] internal class LocaleIdentifierValuePair { public LocaleIdentifier localeIdentifier; public TPrimitive value; } [SerializeField] string m_PropertyPath; [SerializeField] List m_VariantData = new List(); internal Dictionary m_VariantLookup = new Dictionary(); /// /// The property's serialized property path. /// public string PropertyPath { get => m_PropertyPath; set => m_PropertyPath = value; } public bool HasVariant(LocaleIdentifier localeIdentifier) => m_VariantLookup.ContainsKey(localeIdentifier); public void RemoveVariant(LocaleIdentifier localeIdentifier) => m_VariantLookup.Remove(localeIdentifier); public bool GetValue(LocaleIdentifier localeIdentifier, out TPrimitive foundValue) { if (m_VariantLookup.TryGetValue(localeIdentifier, out var pair)) { foundValue = pair.value; return true; } foundValue = default; return false; } public bool GetValue(LocaleIdentifier localeIdentifier, LocaleIdentifier fallback, out TPrimitive foundValue) { if (m_VariantLookup.TryGetValue(localeIdentifier, out var pair) || m_VariantLookup.TryGetValue(fallback, out pair)) { foundValue = pair.value; return true; } foundValue = default; return false; } public void SetValue(LocaleIdentifier localeIdentifier, TPrimitive value) { if (!m_VariantLookup.TryGetValue(localeIdentifier, out var pair)) { pair = new LocaleIdentifierValuePair { localeIdentifier = localeIdentifier }; m_VariantLookup[localeIdentifier] = pair; } pair.value = value; } public string GetValueAsString(LocaleIdentifier localeIdentifier) => GetValue(localeIdentifier, out var foundValue) ? ConvertToString(foundValue) : null; public string GetValueAsString(LocaleIdentifier localeIdentifier, LocaleIdentifier fallback) => GetValue(localeIdentifier, fallback, out var foundValue) ? ConvertToString(foundValue) : null; public void SetValueFromString(LocaleIdentifier localeIdentifier, string stringValue) { var convertedValue = ConvertFromString(stringValue); SetValue(localeIdentifier, convertedValue); } protected virtual string ConvertToString(TPrimitive value) => Convert.ToString(value); protected virtual TPrimitive ConvertFromString(string value) => (TPrimitive)Convert.ChangeType(value, typeof(TPrimitive)); public void OnBeforeSerialize() { m_VariantData.Clear(); foreach (var pair in m_VariantLookup.Values) { m_VariantData.Add(pair); } } public void OnAfterDeserialize() { m_VariantLookup.Clear(); foreach (var pair in m_VariantData) { m_VariantLookup[pair.localeIdentifier] = pair; } } public override string ToString() => Smart.Format("{GetType().Name}({PropertyPath}) - {1:list:{Key}({Value.value})|, |, }", this, m_VariantLookup); } [Serializable] public class ByteTrackedProperty : TrackedProperty {} [Serializable] public class SByteTrackedProperty : TrackedProperty {} [Serializable] public class CharTrackedProperty : TrackedProperty {} [Serializable] public class ShortTrackedProperty : TrackedProperty {} [Serializable] public class UShortTrackedProperty : TrackedProperty {} [Serializable] public class IntTrackedProperty : TrackedProperty {} [Serializable] public class UIntTrackedProperty : TrackedProperty {} [Serializable] public class LongTrackedProperty : TrackedProperty {} [Serializable] public class ULongTrackedProperty : TrackedProperty {} [Serializable] public class FloatTrackedProperty : TrackedProperty {} [Serializable] public class DoubleTrackedProperty : TrackedProperty {} [Serializable] public class ArraySizeTrackedProperty : UIntTrackedProperty {} // Same as Int but we use a custom property drawer which resolves the Enum type in the inspector. [Serializable] public class EnumTrackedProperty : IntTrackedProperty {} [Serializable] public class BoolTrackedProperty : TrackedProperty { protected override bool ConvertFromString(string value) { // Support bool in the form "0" or "1". if (int.TryParse(value, out var result)) return (bool)Convert.ChangeType(result, typeof(bool)); // Support bool in the form "false" or "true". return base.ConvertFromString(value); } protected override string ConvertToString(bool value) { return value ? "1" : "0"; } } [Serializable] public class StringTrackedProperty : TrackedProperty { protected override string ConvertFromString(string value) => value; protected override string ConvertToString(string value) => value; } } #endif