説明なし
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

SpriteResolver.cs 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. using System;
  2. using UnityEngine.Scripting.APIUpdating;
  3. namespace UnityEngine.U2D.Animation
  4. {
  5. /// <summary>
  6. /// Updates a SpriteRenderer's Sprite reference on the Category and Label value it is set
  7. /// </summary>
  8. /// <Description>
  9. /// By setting the SpriteResolver's Category and Label value, it will request for a Sprite from
  10. /// a SpriteLibrary Component the Sprite that is registered for the Category and Label.
  11. /// If a SpriteRenderer is present in the same GameObject, the SpriteResolver will update the
  12. /// SpriteRenderer's Sprite reference to the corresponding Sprite.
  13. /// </Description>
  14. [ExecuteInEditMode]
  15. [DisallowMultipleComponent]
  16. [AddComponentMenu("2D Animation/Sprite Resolver")]
  17. [DefaultExecutionOrder(-2)]
  18. [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/index.html?subfolder=/manual/SLAsset.html%23sprite-resolver-component")]
  19. [MovedFrom("UnityEngine.Experimental.U2D.Animation")]
  20. public class SpriteResolver : MonoBehaviour, ISerializationCallbackReceiver
  21. {
  22. // SpriteKey is the new animation key.
  23. // We are keeping the old ones so that the animation clip doesn't break
  24. // These are for animation
  25. [SerializeField]
  26. float m_CategoryHash = 0;
  27. [SerializeField]
  28. float m_labelHash = 0;
  29. [SerializeField]
  30. float m_SpriteKey = 0;
  31. // For comparing hash values
  32. int m_CategoryHashInt;
  33. int m_LabelHashInt;
  34. int m_SpriteKeyInt;
  35. // For OnUpdate during animation playback
  36. int m_PreviousCategoryHash;
  37. int m_PreviousLabelHash;
  38. int m_PreviousSpriteKeyInt;
  39. #if UNITY_EDITOR
  40. bool m_SpriteLibChanged;
  41. /// <summary>
  42. /// Raised when object is deserialized in the Editor.
  43. /// </summary>
  44. public event Action onDeserializedCallback = () => { };
  45. #endif
  46. void Reset()
  47. {
  48. // If the Sprite referred to by the SpriteRenderer exist in the library,
  49. // we select the Sprite
  50. if(spriteRenderer)
  51. SetSprite(spriteRenderer.sprite);
  52. }
  53. void SetSprite(Sprite sprite)
  54. {
  55. var sl = spriteLibrary;
  56. if (sl != null && sprite != null)
  57. {
  58. foreach (var cat in sl.categoryNames)
  59. {
  60. var entries = sl.GetEntryNames(cat);
  61. foreach (var ent in entries)
  62. {
  63. if (sl.GetSprite(cat, ent) == sprite)
  64. {
  65. spriteKeyInt = SpriteLibrary.GetHashForCategoryAndEntry(cat, ent);
  66. return;
  67. }
  68. }
  69. }
  70. }
  71. }
  72. void OnEnable()
  73. {
  74. m_CategoryHashInt = SpriteLibraryUtility.Convert32BitTo30BitHash(ConvertFloatToInt(m_CategoryHash));
  75. m_PreviousCategoryHash = m_CategoryHashInt;
  76. m_LabelHashInt = SpriteLibraryUtility.Convert32BitTo30BitHash(ConvertFloatToInt(m_labelHash));
  77. m_PreviousLabelHash = m_LabelHashInt;
  78. m_SpriteKeyInt = SpriteLibraryUtility.Convert32BitTo30BitHash(ConvertFloatToInt(m_SpriteKey));
  79. if (m_SpriteKeyInt == 0)
  80. {
  81. m_SpriteKey = ConvertCategoryLabelHashToSpriteKey(spriteLibrary, m_CategoryHashInt, m_LabelHashInt);
  82. m_SpriteKeyInt = SpriteLibraryUtility.Convert32BitTo30BitHash(ConvertFloatToInt(m_SpriteKey));
  83. }
  84. m_PreviousSpriteKeyInt = m_SpriteKeyInt;
  85. ResolveSpriteToSpriteRenderer();
  86. }
  87. SpriteRenderer spriteRenderer => GetComponent<SpriteRenderer>();
  88. /// <summary>
  89. /// Set the Category and label to use
  90. /// </summary>
  91. /// <param name="category">Category to use</param>
  92. /// <param name="label">Label to use</param>
  93. public void SetCategoryAndLabel(string category, string label)
  94. {
  95. spriteKeyInt = SpriteLibrary.GetHashForCategoryAndEntry(category, label);
  96. m_PreviousSpriteKeyInt = spriteKeyInt;
  97. ResolveSpriteToSpriteRenderer();
  98. }
  99. /// <summary>
  100. /// Get the Category set for the SpriteResolver
  101. /// </summary>
  102. /// <returns>The Category's name</returns>
  103. public string GetCategory()
  104. {
  105. var returnString = "";
  106. var sl = spriteLibrary;
  107. if (sl)
  108. {
  109. sl.GetCategoryAndEntryNameFromHash(spriteKeyInt, out returnString, out _);
  110. }
  111. return returnString;
  112. }
  113. /// <summary>
  114. /// Get the Label set for the SpriteResolver
  115. /// </summary>
  116. /// <returns>The Label's name</returns>
  117. public string GetLabel()
  118. {
  119. var returnString = "";
  120. var sl = spriteLibrary;
  121. if (sl)
  122. sl.GetCategoryAndEntryNameFromHash(spriteKeyInt, out _, out returnString);
  123. return returnString;
  124. }
  125. /// <summary>
  126. /// Property to get the SpriteLibrary the SpriteResolver is resolving from
  127. /// </summary>
  128. public SpriteLibrary spriteLibrary => gameObject.GetComponentInParent<SpriteLibrary>(true);
  129. void LateUpdate()
  130. {
  131. m_SpriteKeyInt = SpriteLibraryUtility.Convert32BitTo30BitHash(ConvertFloatToInt(m_SpriteKey));
  132. if (m_SpriteKeyInt != m_PreviousSpriteKeyInt)
  133. {
  134. m_PreviousSpriteKeyInt = m_SpriteKeyInt;
  135. ResolveSpriteToSpriteRenderer();
  136. }
  137. else
  138. {
  139. m_CategoryHashInt = SpriteLibraryUtility.Convert32BitTo30BitHash(ConvertFloatToInt(m_CategoryHash));
  140. m_LabelHashInt = SpriteLibraryUtility.Convert32BitTo30BitHash(ConvertFloatToInt(m_labelHash));
  141. if (m_LabelHashInt != m_PreviousLabelHash || m_CategoryHashInt != m_PreviousCategoryHash)
  142. {
  143. if (spriteLibrary != null)
  144. {
  145. m_PreviousCategoryHash = m_CategoryHashInt;
  146. m_PreviousLabelHash = m_LabelHashInt;
  147. m_SpriteKey = ConvertCategoryLabelHashToSpriteKey(spriteLibrary, m_CategoryHashInt, m_LabelHashInt);
  148. m_SpriteKeyInt = SpriteLibraryUtility.Convert32BitTo30BitHash(ConvertFloatToInt(m_SpriteKey));
  149. m_PreviousSpriteKeyInt = m_SpriteKeyInt;
  150. ResolveSpriteToSpriteRenderer();
  151. }
  152. }
  153. }
  154. }
  155. internal static float ConvertCategoryLabelHashToSpriteKey(SpriteLibrary library, int categoryHash, int labelHash)
  156. {
  157. if (library != null)
  158. {
  159. foreach(var category in library.categoryNames)
  160. {
  161. if (categoryHash == SpriteLibraryUtility.GetStringHash(category))
  162. {
  163. var entries = library.GetEntryNames(category);
  164. if (entries != null)
  165. {
  166. foreach (var entry in entries)
  167. {
  168. if (labelHash == SpriteLibraryUtility.GetStringHash(entry))
  169. {
  170. var spriteKey = SpriteLibrary.GetHashForCategoryAndEntry(category, entry);
  171. return ConvertIntToFloat(spriteKey);
  172. }
  173. }
  174. }
  175. }
  176. }
  177. }
  178. return 0;
  179. }
  180. internal Sprite GetSprite(out bool validEntry)
  181. {
  182. var lib = spriteLibrary;
  183. if (lib != null)
  184. {
  185. return lib.GetSpriteFromCategoryAndEntryHash(m_SpriteKeyInt, out validEntry);
  186. }
  187. validEntry = false;
  188. return null;
  189. }
  190. /// <summary>
  191. /// Set the Sprite in SpriteResolver to the SpriteRenderer component that is in the same GameObject.
  192. /// </summary>
  193. public void ResolveSpriteToSpriteRenderer()
  194. {
  195. m_PreviousSpriteKeyInt = m_SpriteKeyInt;
  196. var sprite = GetSprite(out var validEntry);
  197. var sr = spriteRenderer;
  198. if (sr != null && (sprite != null || validEntry))
  199. sr.sprite = sprite;
  200. }
  201. void OnTransformParentChanged()
  202. {
  203. ResolveSpriteToSpriteRenderer();
  204. #if UNITY_EDITOR
  205. spriteLibChanged = true;
  206. #endif
  207. }
  208. int spriteKeyInt
  209. {
  210. get => m_SpriteKeyInt;
  211. set
  212. {
  213. m_SpriteKeyInt = value;
  214. m_SpriteKey = ConvertIntToFloat(m_SpriteKeyInt);
  215. }
  216. }
  217. internal static unsafe int ConvertFloatToInt(float f)
  218. {
  219. var fp = &f;
  220. var i = (int*)fp;
  221. return *i;
  222. }
  223. internal static unsafe float ConvertIntToFloat(int f)
  224. {
  225. var fp = &f;
  226. var i = (float*)fp;
  227. return *i;
  228. }
  229. #if UNITY_EDITOR
  230. internal bool spriteLibChanged
  231. {
  232. get => m_SpriteLibChanged;
  233. set => m_SpriteLibChanged = value;
  234. }
  235. #endif
  236. /// <summary>
  237. /// Called before object is serialized.
  238. /// </summary>
  239. void ISerializationCallbackReceiver.OnBeforeSerialize()
  240. {
  241. }
  242. /// <summary>
  243. /// Called after object is deserialized.
  244. /// </summary>
  245. void ISerializationCallbackReceiver.OnAfterDeserialize()
  246. {
  247. #if UNITY_EDITOR
  248. onDeserializedCallback();
  249. #endif
  250. }
  251. }
  252. }