#if UNITY_EDITOR
using DTT.Utils.Exceptions;
using DTT.Utils.Optimization;
using System;
using System.Collections.Generic;
using UnityEditor;
namespace DTT.Utils.EditorUtilities
{
///
/// Provides storage of 's from a instance,
/// creating them when they are first used. It also provides implementations access to them by property name
/// instead of by magic string.
///
public class RelativePropertyCache : LazyDictionaryBase
{
#region Variables
#region Protected
///
/// The property used for initializing relative property values the first time.
///
protected SerializedProperty p_serializedProperty;
#endregion
#region Private
///
/// The stored properties, accessable by name.
///
private Dictionary _relativeProperties = new Dictionary();
///
/// The prefix used for private variables.
///
private const string PRIVATE_PREFIX = "_";
#endregion
#endregion
#region Constructors
///
/// Creates a new instance, initializing the stored properties
/// of the given .
///
/// The object of which to store the properties.
public RelativePropertyCache(SerializedProperty serializedProperty)
{
if (serializedProperty == null)
throw new LazyDictionaryException("Serialized property can't be null");
p_serializedProperty = serializedProperty;
}
#endregion
#region Methods
#region Public
///
/// Updates the serialized object representation. Call this before drawing
/// your properties and eventuall changes.
///
public void UpdateObjectRepresentation() => p_serializedProperty.serializedObject.Update();
///
/// Applies modified changes of properties to the serialized object.
/// Call this after a has returned true.
///
public void ApplyChangesToObject() => p_serializedProperty.serializedObject.ApplyModifiedProperties();
#endregion
#region Protected
///
/// Tries retrieving a relative property value from the cache based on given name.
///
/// The property name.
/// The property value.
protected override SerializedProperty GetValue(string nameOfProperty)
{
// Null or empty property names aren't allowed.
if (string.IsNullOrEmpty(nameOfProperty))
throw new NullReferenceException($"Property name is null or empty.");
if (!_relativeProperties.ContainsKey(nameOfProperty))
{
// Find a property using the given name.
SerializedProperty property = p_serializedProperty.FindPropertyRelative(nameOfProperty);
if (property == null)
{
// If the property wasn't found, try finding it might be using a private prefix.
string privatePrefixed = PRIVATE_PREFIX + nameOfProperty;
property = p_serializedProperty.FindPropertyRelative(privatePrefixed);
if (property == null)
throw new InvalidOperationException($"{nameOfProperty} and {privatePrefixed} don't match a property.");
}
_relativeProperties.Add(nameOfProperty, property);
}
return _relativeProperties[nameOfProperty];
}
#endregion
#endregion
}
}
#endif