Keine Beschreibung
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

SpriteLibrary.cs 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using UnityEngine.Scripting.APIUpdating;
  4. using UnityEngine.U2D.Common;
  5. namespace UnityEngine.U2D.Animation
  6. {
  7. /// <summary>
  8. /// Component that holds a Sprite Library Asset. The component is used by SpriteResolver Component to query for Sprite based on Category and Index.
  9. /// </summary>
  10. [DisallowMultipleComponent]
  11. [AddComponentMenu("2D Animation/Sprite Library")]
  12. [IconAttribute(IconUtility.IconPath + "Animation.SpriteLibrary.png")]
  13. [MovedFrom("UnityEngine.Experimental.U2D.Animation")]
  14. [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/index.html?subfolder=/manual/SL-component.html")]
  15. public class SpriteLibrary : MonoBehaviour, IPreviewable
  16. {
  17. struct CategoryEntrySprite
  18. {
  19. public string category;
  20. public string entry;
  21. public Sprite sprite;
  22. }
  23. [SerializeField]
  24. List<SpriteLibCategory> m_Library = new List<SpriteLibCategory>();
  25. [SerializeField]
  26. SpriteLibraryAsset m_SpriteLibraryAsset;
  27. // Cache for combining data in sprite library asset and main library
  28. Dictionary<int, CategoryEntrySprite> m_CategoryEntryHashCache = null;
  29. Dictionary<string, HashSet<string>> m_CategoryEntryCache = null;
  30. int m_PreviousSpriteLibraryAsset;
  31. long m_PreviousModificationHash;
  32. /// <summary>Get or Set the current SpriteLibraryAsset to use.</summary>
  33. public SpriteLibraryAsset spriteLibraryAsset
  34. {
  35. set
  36. {
  37. if (m_SpriteLibraryAsset != value)
  38. {
  39. m_SpriteLibraryAsset = value;
  40. CacheOverrides();
  41. RefreshSpriteResolvers();
  42. }
  43. }
  44. get { return m_SpriteLibraryAsset; }
  45. }
  46. void OnEnable()
  47. {
  48. CacheOverrides();
  49. }
  50. /// <summary>
  51. /// Empty method. Implemented for the IPreviewable interface.
  52. /// </summary>
  53. public void OnPreviewUpdate() { }
  54. /// <summary>
  55. /// Return the Sprite that is registered for the given Category and Label for the SpriteLibrary.
  56. /// </summary>
  57. /// <param name="category">Category name.</param>
  58. /// <param name="label">Label name.</param>
  59. /// <returns>Sprite associated to the name and index.</returns>
  60. public Sprite GetSprite(string category, string label)
  61. {
  62. return GetSprite(GetHashForCategoryAndEntry(category, label));
  63. }
  64. Sprite GetSprite(int hash)
  65. {
  66. if (m_CategoryEntryHashCache.ContainsKey(hash))
  67. return m_CategoryEntryHashCache[hash].sprite;
  68. return null;
  69. }
  70. void UpdateCacheOverridesIfNeeded()
  71. {
  72. if(m_CategoryEntryCache == null ||
  73. m_PreviousSpriteLibraryAsset != m_SpriteLibraryAsset?.GetInstanceID() ||
  74. m_PreviousModificationHash != m_SpriteLibraryAsset?.modificationHash)
  75. CacheOverrides();
  76. }
  77. internal bool GetCategoryAndEntryNameFromHash(int hash, out string category, out string entry)
  78. {
  79. UpdateCacheOverridesIfNeeded();
  80. if (m_CategoryEntryHashCache.ContainsKey(hash))
  81. {
  82. category = m_CategoryEntryHashCache[hash].category;
  83. entry = m_CategoryEntryHashCache[hash].entry;
  84. return true;
  85. }
  86. category = null;
  87. entry = null;
  88. return false;
  89. }
  90. internal static int GetHashForCategoryAndEntry(string category, string entry)
  91. {
  92. return SpriteLibraryUtility.GetStringHash($"{category}_{entry}");
  93. }
  94. internal Sprite GetSpriteFromCategoryAndEntryHash(int hash, out bool validEntry)
  95. {
  96. UpdateCacheOverridesIfNeeded();
  97. if (m_CategoryEntryHashCache.ContainsKey(hash))
  98. {
  99. validEntry = true;
  100. return m_CategoryEntryHashCache[hash].sprite;
  101. }
  102. validEntry = false;
  103. return null;
  104. }
  105. List<SpriteCategoryEntry> GetEntries(string category, bool addIfNotExist)
  106. {
  107. var index = m_Library.FindIndex(x => x.name == category);
  108. if (index < 0)
  109. {
  110. if (!addIfNotExist)
  111. return null;
  112. m_Library.Add(new SpriteLibCategory()
  113. {
  114. name = category,
  115. categoryList = new List<SpriteCategoryEntry>()
  116. });
  117. index = m_Library.Count - 1;
  118. }
  119. return m_Library[index].categoryList;
  120. }
  121. static SpriteCategoryEntry GetEntry(List<SpriteCategoryEntry> entries, string entry, bool addIfNotExist)
  122. {
  123. var index = entries.FindIndex(x => x.name == entry);
  124. if (index < 0)
  125. {
  126. if (!addIfNotExist)
  127. return null;
  128. entries.Add(new SpriteCategoryEntry()
  129. {
  130. name = entry,
  131. });
  132. index = entries.Count - 1;
  133. }
  134. return entries[index];
  135. }
  136. /// <summary>
  137. /// Add or replace an override when querying for the given Category and Label from a SpriteLibraryAsset.
  138. /// </summary>
  139. /// <param name="spriteLib">Sprite Library Asset to query.</param>
  140. /// <param name="category">Category name from the Sprite Library Asset to add override.</param>
  141. /// <param name="label">Label name to add override.</param>
  142. public void AddOverride(SpriteLibraryAsset spriteLib, string category, string label)
  143. {
  144. var sprite = spriteLib.GetSprite(category, label);
  145. var entries = GetEntries(category, true);
  146. var entry = GetEntry(entries, label, true);
  147. entry.sprite = sprite;
  148. CacheOverrides();
  149. }
  150. /// <summary>
  151. /// Add or replace an override when querying for the given Category. All the categories in the Category will be added.
  152. /// </summary>
  153. /// <param name="spriteLib">Sprite Library Asset to query.</param>
  154. /// <param name="category">Category name from the Sprite Library Asset to add override.</param>
  155. public void AddOverride(SpriteLibraryAsset spriteLib, string category)
  156. {
  157. var categoryHash = SpriteLibraryUtility.GetStringHash(category);
  158. var cat = spriteLib.categories.FirstOrDefault(x => x.hash == categoryHash);
  159. if (cat != null)
  160. {
  161. var entries = GetEntries(category, true);
  162. for (var i = 0; i < cat.categoryList.Count; ++i)
  163. {
  164. var ent = cat.categoryList[i];
  165. GetEntry(entries, ent.name, true).sprite = ent.sprite;
  166. }
  167. CacheOverrides();
  168. }
  169. }
  170. /// <summary>
  171. /// Add or replace an override when querying for the given Category and Label.
  172. /// </summary>
  173. /// <param name="sprite">Sprite to override to.</param>
  174. /// <param name="category">Category name to override.</param>
  175. /// <param name="label">Label name to override.</param>
  176. public void AddOverride(Sprite sprite, string category, string label)
  177. {
  178. GetEntry(GetEntries(category, true), label, true).sprite = sprite;
  179. CacheOverrides();
  180. RefreshSpriteResolvers();
  181. }
  182. /// <summary>
  183. /// Remove all Sprite Library override for a given category.
  184. /// </summary>
  185. /// <param name="category">Category overrides to remove.</param>
  186. public void RemoveOverride(string category)
  187. {
  188. var index = m_Library.FindIndex(x => x.name == category);
  189. if (index >= 0)
  190. {
  191. m_Library.RemoveAt(index);
  192. CacheOverrides();
  193. RefreshSpriteResolvers();
  194. }
  195. }
  196. /// <summary>
  197. /// Remove Sprite Library override for a given category and label.
  198. /// </summary>
  199. /// <param name="category">Category to remove.</param>
  200. /// <param name="label">Label to remove.</param>
  201. public void RemoveOverride(string category, string label)
  202. {
  203. var entries = GetEntries(category, false);
  204. if (entries != null)
  205. {
  206. var index = entries.FindIndex(x => x.name == label);
  207. if (index >= 0)
  208. {
  209. entries.RemoveAt(index);
  210. CacheOverrides();
  211. RefreshSpriteResolvers();
  212. }
  213. }
  214. }
  215. /// <summary>
  216. /// Method to check if a Category and Label pair has an override.
  217. /// </summary>
  218. /// <param name="category">Category name.</param>
  219. /// <param name="label">Label name.</param>
  220. /// <returns>True if override exist, false otherwise.</returns>
  221. public bool HasOverride(string category, string label)
  222. {
  223. var catOverride = GetEntries(category, false);
  224. if (catOverride != null)
  225. return GetEntry(catOverride, label, false) != null;
  226. return false;
  227. }
  228. /// <summary>
  229. /// Request SpriteResolver components that are in the same hierarchy to refresh.
  230. /// </summary>
  231. public void RefreshSpriteResolvers()
  232. {
  233. var spriteResolvers = GetComponentsInChildren<SpriteResolver>();
  234. foreach (var sr in spriteResolvers)
  235. {
  236. sr.ResolveSpriteToSpriteRenderer();
  237. #if UNITY_EDITOR
  238. sr.spriteLibChanged = true;
  239. #endif
  240. }
  241. }
  242. internal IEnumerable<string> categoryNames
  243. {
  244. get
  245. {
  246. UpdateCacheOverridesIfNeeded();
  247. return m_CategoryEntryCache.Keys;
  248. }
  249. }
  250. internal IEnumerable<string> GetEntryNames(string category)
  251. {
  252. UpdateCacheOverridesIfNeeded();
  253. if (m_CategoryEntryCache.ContainsKey(category))
  254. return m_CategoryEntryCache[category];
  255. return null;
  256. }
  257. internal void CacheOverrides()
  258. {
  259. m_PreviousSpriteLibraryAsset = 0;
  260. m_PreviousModificationHash = 0;
  261. m_CategoryEntryHashCache = new Dictionary<int, CategoryEntrySprite>();
  262. m_CategoryEntryCache = new Dictionary<string, HashSet<string>>();
  263. if (m_SpriteLibraryAsset)
  264. {
  265. m_PreviousSpriteLibraryAsset = m_SpriteLibraryAsset.GetInstanceID();
  266. m_PreviousModificationHash = m_SpriteLibraryAsset.modificationHash;
  267. foreach (var category in m_SpriteLibraryAsset.categories)
  268. {
  269. var catName = category.name;
  270. m_CategoryEntryCache.Add(catName, new HashSet<string>());
  271. var cacheEntryName = m_CategoryEntryCache[catName];
  272. foreach (var entry in category.categoryList)
  273. {
  274. m_CategoryEntryHashCache.Add(GetHashForCategoryAndEntry(catName, entry.name), new CategoryEntrySprite()
  275. {
  276. category = catName,
  277. entry = entry.name,
  278. sprite = entry.sprite
  279. });
  280. cacheEntryName.Add(entry.name);
  281. }
  282. }
  283. }
  284. foreach (var category in m_Library)
  285. {
  286. var catName = category.name;
  287. if(!m_CategoryEntryCache.ContainsKey(catName))
  288. m_CategoryEntryCache.Add(catName, new HashSet<string>());
  289. var cacheEntryName = m_CategoryEntryCache[catName];
  290. foreach (var ent in category.categoryList)
  291. {
  292. if (!cacheEntryName.Contains(ent.name))
  293. cacheEntryName.Add(ent.name);
  294. var hash = GetHashForCategoryAndEntry(catName, ent.name);
  295. if (!m_CategoryEntryHashCache.ContainsKey(hash))
  296. {
  297. m_CategoryEntryHashCache.Add(hash, new CategoryEntrySprite()
  298. {
  299. category = catName,
  300. entry = ent.name,
  301. sprite = ent.sprite
  302. });
  303. }
  304. else
  305. {
  306. var e = m_CategoryEntryHashCache[hash];
  307. e.sprite = ent.sprite;
  308. m_CategoryEntryHashCache[hash] = e;
  309. }
  310. }
  311. }
  312. }
  313. }
  314. }