Singularity/Library/PackageCache/com.unity.2d.animation@7.0.10/Runtime/SpriteLib/SpriteResolver.cs
2024-05-06 11:45:45 -07:00

293 lines
10 KiB
C#

using System;
using UnityEngine.Scripting.APIUpdating;
namespace UnityEngine.U2D.Animation
{
/// <summary>
/// Updates a SpriteRenderer's Sprite reference on the Category and Label value it is set
/// </summary>
/// <Description>
/// By setting the SpriteResolver's Category and Label value, it will request for a Sprite from
/// a SpriteLibrary Component the Sprite that is registered for the Category and Label.
/// If a SpriteRenderer is present in the same GameObject, the SpriteResolver will update the
/// SpriteRenderer's Sprite reference to the corresponding Sprite.
/// </Description>
[ExecuteInEditMode]
[DisallowMultipleComponent]
[AddComponentMenu("2D Animation/Sprite Resolver")]
[DefaultExecutionOrder(-2)]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/index.html?subfolder=/manual/SLAsset.html%23sprite-resolver-component")]
[MovedFrom("UnityEngine.Experimental.U2D.Animation")]
public class SpriteResolver : MonoBehaviour, ISerializationCallbackReceiver
{
// SpriteKey is the new animation key.
// We are keeping the old ones so that the animation clip doesn't break
// These are for animation
[SerializeField]
float m_CategoryHash = 0;
[SerializeField]
float m_labelHash = 0;
[SerializeField]
float m_SpriteKey = 0;
// For comparing hash values
int m_CategoryHashInt;
int m_LabelHashInt;
int m_SpriteKeyInt;
// For OnUpdate during animation playback
int m_PreviousCategoryHash;
int m_PreviousLabelHash;
int m_PreviousSpriteKeyInt;
#if UNITY_EDITOR
bool m_SpriteLibChanged;
/// <summary>
/// Raised when object is deserialized in the Editor.
/// </summary>
public event Action onDeserializedCallback = () => { };
#endif
void Reset()
{
// If the Sprite referred to by the SpriteRenderer exist in the library,
// we select the Sprite
if(spriteRenderer)
SetSprite(spriteRenderer.sprite);
}
void SetSprite(Sprite sprite)
{
var sl = spriteLibrary;
if (sl != null && sprite != null)
{
foreach (var cat in sl.categoryNames)
{
var entries = sl.GetEntryNames(cat);
foreach (var ent in entries)
{
if (sl.GetSprite(cat, ent) == sprite)
{
spriteKeyInt = SpriteLibrary.GetHashForCategoryAndEntry(cat, ent);
return;
}
}
}
}
}
void OnEnable()
{
m_CategoryHashInt = ConvertFloatToInt(m_CategoryHash);
m_PreviousCategoryHash = m_CategoryHashInt;
m_LabelHashInt = ConvertFloatToInt(m_labelHash);
m_PreviousLabelHash = m_LabelHashInt;
m_SpriteKeyInt = SpriteLibraryUtility.Convert32BitTo30BitHash(ConvertFloatToInt(m_SpriteKey));
if (m_SpriteKeyInt == 0)
{
m_SpriteKey = ConvertCategoryLabelHashToSpriteKey(spriteLibrary, SpriteLibraryUtility.Convert32BitTo30BitHash(m_CategoryHashInt), SpriteLibraryUtility.Convert32BitTo30BitHash(m_LabelHashInt));
m_SpriteKeyInt = SpriteLibraryUtility.Convert32BitTo30BitHash(ConvertFloatToInt(m_SpriteKey));
}
string newCat, newLab;
if (spriteLibrary != null && spriteLibrary.GetCategoryAndEntryNameFromHash(m_SpriteKeyInt, out newCat, out newLab))
{
// Populate back in case user is using animating with old animation clip
m_CategoryHashInt = SpriteLibraryUtility.GetStringHash(newCat);
m_LabelHashInt = SpriteLibraryUtility.GetStringHash(newLab);
m_CategoryHash = ConvertIntToFloat(m_CategoryHashInt);
m_labelHash = ConvertIntToFloat(m_LabelHashInt);
}
m_PreviousSpriteKeyInt = m_SpriteKeyInt;
ResolveSpriteToSpriteRenderer();
}
SpriteRenderer spriteRenderer => GetComponent<SpriteRenderer>();
/// <summary>
/// Set the Category and label to use
/// </summary>
/// <param name="category">Category to use</param>
/// <param name="label">Label to use</param>
public void SetCategoryAndLabel(string category, string label)
{
spriteKeyInt = SpriteLibrary.GetHashForCategoryAndEntry(category, label);
m_PreviousSpriteKeyInt = spriteKeyInt;
ResolveSpriteToSpriteRenderer();
}
/// <summary>
/// Get the Category set for the SpriteResolver
/// </summary>
/// <returns>The Category's name</returns>
public string GetCategory()
{
var returnString = "";
var sl = spriteLibrary;
if (sl)
{
sl.GetCategoryAndEntryNameFromHash(spriteKeyInt, out returnString, out _);
}
return returnString;
}
/// <summary>
/// Get the Label set for the SpriteResolver
/// </summary>
/// <returns>The Label's name</returns>
public string GetLabel()
{
var returnString = "";
var sl = spriteLibrary;
if (sl)
sl.GetCategoryAndEntryNameFromHash(spriteKeyInt, out _, out returnString);
return returnString;
}
/// <summary>
/// Property to get the SpriteLibrary the SpriteResolver is resolving from
/// </summary>
public SpriteLibrary spriteLibrary => gameObject.GetComponentInParent<SpriteLibrary>(true);
void LateUpdate()
{
m_SpriteKeyInt = SpriteLibraryUtility.Convert32BitTo30BitHash(ConvertFloatToInt(m_SpriteKey));
if (m_SpriteKeyInt != m_PreviousSpriteKeyInt)
{
m_PreviousSpriteKeyInt = m_SpriteKeyInt;
ResolveSpriteToSpriteRenderer();
}
else
{
m_CategoryHashInt = ConvertFloatToInt(m_CategoryHash);
m_LabelHashInt = ConvertFloatToInt(m_labelHash);
if (m_LabelHashInt != m_PreviousLabelHash || m_CategoryHashInt != m_PreviousCategoryHash)
{
if (spriteLibrary != null)
{
m_PreviousCategoryHash = m_CategoryHashInt;
m_PreviousLabelHash = m_LabelHashInt;
m_SpriteKey = ConvertCategoryLabelHashToSpriteKey(spriteLibrary, SpriteLibraryUtility.Convert32BitTo30BitHash(m_CategoryHashInt), SpriteLibraryUtility.Convert32BitTo30BitHash(m_LabelHashInt));
m_SpriteKeyInt = SpriteLibraryUtility.Convert32BitTo30BitHash(ConvertFloatToInt(m_SpriteKey));
m_PreviousSpriteKeyInt = m_SpriteKeyInt;
ResolveSpriteToSpriteRenderer();
}
}
}
}
internal static float ConvertCategoryLabelHashToSpriteKey(SpriteLibrary library, int categoryHash, int labelHash)
{
if (library != null)
{
foreach(var category in library.categoryNames)
{
if (categoryHash == SpriteLibraryUtility.GetStringHash(category))
{
var entries = library.GetEntryNames(category);
if (entries != null)
{
foreach (var entry in entries)
{
if (labelHash == SpriteLibraryUtility.GetStringHash(entry))
{
var spriteKey = SpriteLibrary.GetHashForCategoryAndEntry(category, entry);
return ConvertIntToFloat(spriteKey);
}
}
}
}
}
}
return 0;
}
internal Sprite GetSprite(out bool validEntry)
{
var lib = spriteLibrary;
if (lib != null)
{
return lib.GetSpriteFromCategoryAndEntryHash(m_SpriteKeyInt, out validEntry);
}
validEntry = false;
return null;
}
/// <summary>
/// Set the Sprite in SpriteResolver to the SpriteRenderer component that is in the same GameObject.
/// </summary>
public void ResolveSpriteToSpriteRenderer()
{
m_PreviousSpriteKeyInt = m_SpriteKeyInt;
var sprite = GetSprite(out var validEntry);
var sr = spriteRenderer;
if (sr != null && (sprite != null || validEntry))
sr.sprite = sprite;
}
void OnTransformParentChanged()
{
ResolveSpriteToSpriteRenderer();
#if UNITY_EDITOR
spriteLibChanged = true;
#endif
}
int spriteKeyInt
{
get => m_SpriteKeyInt;
set
{
m_SpriteKeyInt = value;
m_SpriteKey = ConvertIntToFloat(m_SpriteKeyInt);
}
}
internal static unsafe int ConvertFloatToInt(float f)
{
var fp = &f;
var i = (int*)fp;
return *i;
}
internal static unsafe float ConvertIntToFloat(int f)
{
var fp = &f;
var i = (float*)fp;
return *i;
}
#if UNITY_EDITOR
internal bool spriteLibChanged
{
get => m_SpriteLibChanged;
set => m_SpriteLibChanged = value;
}
#endif
/// <summary>
/// Called before object is serialized.
/// </summary>
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
}
/// <summary>
/// Called after object is deserialized.
/// </summary>
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
#if UNITY_EDITOR
onDeserializedCallback();
#endif
}
}
}