123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine.Scripting.APIUpdating;
- using UnityEngine.U2D.Common;
-
- namespace UnityEngine.U2D.Animation
- {
- /// <summary>
- /// Component that holds a Sprite Library Asset. The component is used by SpriteResolver Component to query for Sprite based on Category and Index.
- /// </summary>
- [DisallowMultipleComponent]
- [AddComponentMenu("2D Animation/Sprite Library")]
- [IconAttribute(IconUtility.IconPath + "Animation.SpriteLibrary.png")]
- [MovedFrom("UnityEngine.Experimental.U2D.Animation")]
- [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/index.html?subfolder=/manual/SL-component.html")]
- public class SpriteLibrary : MonoBehaviour, IPreviewable
- {
- struct CategoryEntrySprite
- {
- public string category;
- public string entry;
- public Sprite sprite;
- }
-
- [SerializeField]
- List<SpriteLibCategory> m_Library = new List<SpriteLibCategory>();
-
- [SerializeField]
- SpriteLibraryAsset m_SpriteLibraryAsset;
-
- // Cache for combining data in sprite library asset and main library
- Dictionary<int, CategoryEntrySprite> m_CategoryEntryHashCache = null;
- Dictionary<string, HashSet<string>> m_CategoryEntryCache = null;
- int m_PreviousSpriteLibraryAsset;
- long m_PreviousModificationHash;
-
- /// <summary>Get or Set the current SpriteLibraryAsset to use.</summary>
- public SpriteLibraryAsset spriteLibraryAsset
- {
- set
- {
- if (m_SpriteLibraryAsset != value)
- {
- m_SpriteLibraryAsset = value;
- CacheOverrides();
- RefreshSpriteResolvers();
- }
- }
- get { return m_SpriteLibraryAsset; }
- }
-
- void OnEnable()
- {
- CacheOverrides();
- }
-
- /// <summary>
- /// Empty method. Implemented for the IPreviewable interface.
- /// </summary>
- public void OnPreviewUpdate() { }
-
- /// <summary>
- /// Return the Sprite that is registered for the given Category and Label for the SpriteLibrary.
- /// </summary>
- /// <param name="category">Category name.</param>
- /// <param name="label">Label name.</param>
- /// <returns>Sprite associated to the name and index.</returns>
- public Sprite GetSprite(string category, string label)
- {
- return GetSprite(GetHashForCategoryAndEntry(category, label));
- }
-
- Sprite GetSprite(int hash)
- {
- if (m_CategoryEntryHashCache.ContainsKey(hash))
- return m_CategoryEntryHashCache[hash].sprite;
- return null;
- }
-
- void UpdateCacheOverridesIfNeeded()
- {
- if(m_CategoryEntryCache == null ||
- m_PreviousSpriteLibraryAsset != m_SpriteLibraryAsset?.GetInstanceID() ||
- m_PreviousModificationHash != m_SpriteLibraryAsset?.modificationHash)
- CacheOverrides();
- }
-
- internal bool GetCategoryAndEntryNameFromHash(int hash, out string category, out string entry)
- {
- UpdateCacheOverridesIfNeeded();
- if (m_CategoryEntryHashCache.ContainsKey(hash))
- {
- category = m_CategoryEntryHashCache[hash].category;
- entry = m_CategoryEntryHashCache[hash].entry;
- return true;
- }
-
- category = null;
- entry = null;
- return false;
- }
-
- internal static int GetHashForCategoryAndEntry(string category, string entry)
- {
- return SpriteLibraryUtility.GetStringHash($"{category}_{entry}");
- }
-
- internal Sprite GetSpriteFromCategoryAndEntryHash(int hash, out bool validEntry)
- {
- UpdateCacheOverridesIfNeeded();
- if (m_CategoryEntryHashCache.ContainsKey(hash))
- {
- validEntry = true;
- return m_CategoryEntryHashCache[hash].sprite;
- }
- validEntry = false;
- return null;
- }
-
- List<SpriteCategoryEntry> GetEntries(string category, bool addIfNotExist)
- {
- var index = m_Library.FindIndex(x => x.name == category);
- if (index < 0)
- {
- if (!addIfNotExist)
- return null;
- m_Library.Add(new SpriteLibCategory()
- {
- name = category,
- categoryList = new List<SpriteCategoryEntry>()
- });
- index = m_Library.Count - 1;
- }
-
- return m_Library[index].categoryList;
- }
-
- static SpriteCategoryEntry GetEntry(List<SpriteCategoryEntry> entries, string entry, bool addIfNotExist)
- {
- var index = entries.FindIndex(x => x.name == entry);
- if (index < 0)
- {
- if (!addIfNotExist)
- return null;
- entries.Add(new SpriteCategoryEntry()
- {
- name = entry,
- });
- index = entries.Count - 1;
- }
-
- return entries[index];
- }
-
- /// <summary>
- /// Add or replace an override when querying for the given Category and Label from a SpriteLibraryAsset.
- /// </summary>
- /// <param name="spriteLib">Sprite Library Asset to query.</param>
- /// <param name="category">Category name from the Sprite Library Asset to add override.</param>
- /// <param name="label">Label name to add override.</param>
- public void AddOverride(SpriteLibraryAsset spriteLib, string category, string label)
- {
- var sprite = spriteLib.GetSprite(category, label);
- var entries = GetEntries(category, true);
- var entry = GetEntry(entries, label, true);
- entry.sprite = sprite;
- CacheOverrides();
- }
-
- /// <summary>
- /// Add or replace an override when querying for the given Category. All the categories in the Category will be added.
- /// </summary>
- /// <param name="spriteLib">Sprite Library Asset to query.</param>
- /// <param name="category">Category name from the Sprite Library Asset to add override.</param>
- public void AddOverride(SpriteLibraryAsset spriteLib, string category)
- {
- var categoryHash = SpriteLibraryUtility.GetStringHash(category);
- var cat = spriteLib.categories.FirstOrDefault(x => x.hash == categoryHash);
- if (cat != null)
- {
- var entries = GetEntries(category, true);
- for (var i = 0; i < cat.categoryList.Count; ++i)
- {
- var ent = cat.categoryList[i];
- GetEntry(entries, ent.name, true).sprite = ent.sprite;
- }
- CacheOverrides();
- }
- }
-
- /// <summary>
- /// Add or replace an override when querying for the given Category and Label.
- /// </summary>
- /// <param name="sprite">Sprite to override to.</param>
- /// <param name="category">Category name to override.</param>
- /// <param name="label">Label name to override.</param>
- public void AddOverride(Sprite sprite, string category, string label)
- {
- GetEntry(GetEntries(category, true), label, true).sprite = sprite;
- CacheOverrides();
- RefreshSpriteResolvers();
- }
-
- /// <summary>
- /// Remove all Sprite Library override for a given category.
- /// </summary>
- /// <param name="category">Category overrides to remove.</param>
- public void RemoveOverride(string category)
- {
- var index = m_Library.FindIndex(x => x.name == category);
- if (index >= 0)
- {
- m_Library.RemoveAt(index);
- CacheOverrides();
- RefreshSpriteResolvers();
- }
- }
-
- /// <summary>
- /// Remove Sprite Library override for a given category and label.
- /// </summary>
- /// <param name="category">Category to remove.</param>
- /// <param name="label">Label to remove.</param>
- public void RemoveOverride(string category, string label)
- {
- var entries = GetEntries(category, false);
- if (entries != null)
- {
- var index = entries.FindIndex(x => x.name == label);
- if (index >= 0)
- {
- entries.RemoveAt(index);
- CacheOverrides();
- RefreshSpriteResolvers();
- }
- }
- }
-
- /// <summary>
- /// Method to check if a Category and Label pair has an override.
- /// </summary>
- /// <param name="category">Category name.</param>
- /// <param name="label">Label name.</param>
- /// <returns>True if override exist, false otherwise.</returns>
- public bool HasOverride(string category, string label)
- {
- var catOverride = GetEntries(category, false);
- if (catOverride != null)
- return GetEntry(catOverride, label, false) != null;
- return false;
- }
-
- /// <summary>
- /// Request SpriteResolver components that are in the same hierarchy to refresh.
- /// </summary>
- public void RefreshSpriteResolvers()
- {
- var spriteResolvers = GetComponentsInChildren<SpriteResolver>();
- foreach (var sr in spriteResolvers)
- {
- sr.ResolveSpriteToSpriteRenderer();
- #if UNITY_EDITOR
- sr.spriteLibChanged = true;
- #endif
- }
- }
-
- internal IEnumerable<string> categoryNames
- {
- get
- {
- UpdateCacheOverridesIfNeeded();
- return m_CategoryEntryCache.Keys;
- }
- }
-
- internal IEnumerable<string> GetEntryNames(string category)
- {
- UpdateCacheOverridesIfNeeded();
- if (m_CategoryEntryCache.ContainsKey(category))
- return m_CategoryEntryCache[category];
- return null;
- }
-
- internal void CacheOverrides()
- {
- m_PreviousSpriteLibraryAsset = 0;
- m_PreviousModificationHash = 0;
- m_CategoryEntryHashCache = new Dictionary<int, CategoryEntrySprite>();
- m_CategoryEntryCache = new Dictionary<string, HashSet<string>>();
- if (m_SpriteLibraryAsset)
- {
- m_PreviousSpriteLibraryAsset = m_SpriteLibraryAsset.GetInstanceID();
- m_PreviousModificationHash = m_SpriteLibraryAsset.modificationHash;
- foreach (var category in m_SpriteLibraryAsset.categories)
- {
- var catName = category.name;
- m_CategoryEntryCache.Add(catName, new HashSet<string>());
- var cacheEntryName = m_CategoryEntryCache[catName];
- foreach (var entry in category.categoryList)
- {
- m_CategoryEntryHashCache.Add(GetHashForCategoryAndEntry(catName, entry.name), new CategoryEntrySprite()
- {
- category = catName,
- entry = entry.name,
- sprite = entry.sprite
- });
- cacheEntryName.Add(entry.name);
- }
- }
- }
-
- foreach (var category in m_Library)
- {
- var catName = category.name;
- if(!m_CategoryEntryCache.ContainsKey(catName))
- m_CategoryEntryCache.Add(catName, new HashSet<string>());
- var cacheEntryName = m_CategoryEntryCache[catName];
-
- foreach (var ent in category.categoryList)
- {
- if (!cacheEntryName.Contains(ent.name))
- cacheEntryName.Add(ent.name);
-
- var hash = GetHashForCategoryAndEntry(catName, ent.name);
- if (!m_CategoryEntryHashCache.ContainsKey(hash))
- {
- m_CategoryEntryHashCache.Add(hash, new CategoryEntrySprite()
- {
- category = catName,
- entry = ent.name,
- sprite = ent.sprite
- });
- }
- else
- {
- var e = m_CategoryEntryHashCache[hash];
- e.sprite = ent.sprite;
- m_CategoryEntryHashCache[hash] = e;
- }
- }
- }
- }
- }
- }
|