using UnityEngine;
using System;
using System.Collections.Generic;
namespace PixelCrushers
{
///
/// Saves an animator's state.
///
[AddComponentMenu("")] // Use wrapper.
[RequireComponent(typeof(Animator))]
public class AnimatorSaver : Saver
{
[Serializable]
public class LayerData
{
public int hash;
public float time;
}
// Credit: Trigger saving contributed by Magique.
[Serializable]
public class TriggerData
{
public string name;
public bool isTriggered;
}
[Serializable]
public class Data
{
public LayerData[] layers = null;
public List bools = new List();
public List floats = new List();
public List ints = new List();
public List strings = new List();
public List triggers = new List();
}
private Data m_data = new Data();
private Animator m_animator;
private Animator animator
{
get
{
if (m_animator == null) m_animator = GetComponent();
return m_animator;
}
}
private void CheckAnimator()
{
if (animator == null) return;
if (m_data == null) m_data = new Data();
if (m_data.layers == null || m_data.layers.Length != animator.layerCount)
{
m_data.layers = new LayerData[animator.layerCount];
for (int i = 0; i < animator.layerCount; i++)
{
m_data.layers[i] = new LayerData();
}
}
}
public override string RecordData()
{
if (animator == null) return string.Empty;
CheckAnimator();
// Record layer states:
for (int i = 0; i < animator.layerCount; i++)
{
var state = animator.GetCurrentAnimatorStateInfo(i);
m_data.layers[i].hash = state.fullPathHash;
m_data.layers[i].time = state.normalizedTime;
}
// Record parameter values:
int numBools = 0;
int numFloats = 0;
int numInts = 0;
int numTriggers = 0;
for (int i = 0; i < animator.parameterCount; i++)
{
var parameter = animator.parameters[i];
switch (parameter.type)
{
case AnimatorControllerParameterType.Bool:
var boolValue = animator.GetBool(parameter.name);
if (numBools < m_data.bools.Count)
{
m_data.bools[numBools] = boolValue;
}
else
{
m_data.bools.Add(boolValue);
}
numBools++;
break;
case AnimatorControllerParameterType.Float:
var floatValue = animator.GetFloat(parameter.name);
if (numFloats < m_data.floats.Count)
{
m_data.floats[numFloats] = floatValue;
}
else
{
m_data.floats.Add(floatValue);
}
numFloats++;
break;
case AnimatorControllerParameterType.Int:
var intValue = animator.GetInteger(parameter.name);
if (numInts < m_data.ints.Count)
{
m_data.ints[numInts] = intValue;
}
else
{
m_data.ints.Add(intValue);
}
numInts++;
break;
case AnimatorControllerParameterType.Trigger:
var triggerValue = animator.GetCurrentAnimatorStateInfo(0).IsName(parameter.name);
if (numTriggers < m_data.triggers.Count)
{
m_data.triggers[numTriggers].isTriggered = triggerValue;
m_data.triggers[numTriggers].name = parameter.name;
}
else
{
m_data.triggers.Add(new TriggerData() { isTriggered = triggerValue, name = parameter.name });
}
numTriggers++;
break;
}
}
return SaveSystem.Serialize(m_data);
}
public override void ApplyData(string s)
{
if (string.IsNullOrEmpty(s) || animator == null) return;
m_data = SaveSystem.Deserialize(s, m_data);
if (m_data == null)
{
m_data = new Data();
}
else if (m_data.layers != null)
{
// Apply layer states:
for (int i = 0; i < animator.layerCount; i++)
{
if (i < m_data.layers.Length)
{
animator.Play(m_data.layers[i].hash, i, m_data.layers[i].time);
}
}
// Set or Reset triggers
foreach (var trigger in m_data.triggers)
{
if (trigger.isTriggered)
{
animator.SetTrigger(trigger.name);
}
else
{
animator.ResetTrigger(trigger.name);
}
}
// Apply parameter values:
int numBools = 0;
int numFloats = 0;
int numInts = 0;
for (int i = 0; i < animator.parameterCount; i++)
{
var parameter = animator.parameters[i];
switch (parameter.type)
{
case AnimatorControllerParameterType.Bool:
if (numBools < m_data.bools.Count)
{
animator.SetBool(parameter.name, m_data.bools[numBools++]);
}
break;
case AnimatorControllerParameterType.Float:
if (numFloats < m_data.floats.Count)
{
animator.SetFloat(parameter.name, m_data.floats[numFloats++]);
}
break;
case AnimatorControllerParameterType.Int:
if (numInts < m_data.ints.Count)
{
animator.SetInteger(parameter.name, m_data.ints[numInts++]);
}
break;
}
}
}
}
}
}