/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.StateSystem
{
using Opsive.Shared.Utility;
using System;
using System.Collections.Generic;
using UnityEngine;
///
/// Allows the Preset component to serialized the property value.
///
public class PersistablePreset : Preset
{
[Tooltip("The serialized properties.")]
[SerializeField] protected Serialization m_Data;
public Serialization Data { get { return m_Data; } set { m_Data = value; } }
///
/// Creates a persistable preset based off of the specified component.
///
/// The object to retrieve the property values of.
/// The created preset. Null if no properties have been found to create the preset with.
public static PersistablePreset CreatePreset(object obj)
{
return CreatePreset(obj, MemberVisibility.None);
}
///
/// Creates a persistable preset based off of the specified component and visibility.
///
/// The object to retrieve the property values of.
/// Specifies the visibility of the field/properties that should be retrieved.
/// The created preset. Null if no properties have been found to create the preset with.
public static PersistablePreset CreatePreset(object obj, MemberVisibility visibility)
{
var data = new Serialization();
data.Serialize(obj, false, visibility);
var preset = CreateInstance();
preset.Data = data;
return preset;
}
///
/// Initializes the preset with the specified visiblity. The preset must be initialized before the preset values are applied so the delegates can be created.
///
/// The object to map the delegates to.
/// Specifies the visibility of the field/properties that should be retrieved.
public override void Initialize(object obj, MemberVisibility visibility)
{
m_Delegates = new BaseDelegate[m_Data.ValueHashes.Length];
var valuePositionMap = new Dictionary(m_Data.ValueHashes.Length);
for (int i = 0; i < m_Data.ValueHashes.Length; ++i) {
valuePositionMap.Add(m_Data.ValueHashes[i], i);
}
var valueCount = 0;
var properties = Serialization.GetSerializedProperties(obj.GetType(), visibility);
for (int i = 0; i < properties.Length; ++i) {
var hash = Serialization.StringHash(properties[i].PropertyType.FullName) + Serialization.StringHash(properties[i].Name);
int position;
if (!valuePositionMap.TryGetValue(hash, out position)) {
continue;
}
// Create a generic delegate based on the property type.
var genericDelegateType = typeof(GenericDelegate<>).MakeGenericType(properties[i].PropertyType);
m_Delegates[valueCount] = Activator.CreateInstance(genericDelegateType) as BaseDelegate;
// Initialize the delegate.
if (m_Delegates[valueCount] != null) {
m_Delegates[valueCount].Initialize(obj, properties[i], valuePositionMap, m_Data, visibility);
} else {
Debug.LogWarning("Warning: Unable to create preset of type " + properties[i].PropertyType);
}
valueCount++;
}
// The delegate length may not match if a property has been added but no longer exists.
if (m_Delegates.Length != valueCount) {
Array.Resize(ref m_Delegates, valueCount);
}
}
}
}