123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text.RegularExpressions;
- using UnityEditorInternal;
- using UnityEngine;
- using Object = UnityEngine.Object;
-
- namespace UnityEditor.Tilemaps
- {
- /// <summary>
- /// A ScriptableObject that stores picks for a particular GridBrushBase type.
- /// The picks include a list of picks defined by the user and a limited list
- /// of picks which were last made by the user. The picks can be loaded onto
- /// the active Brush in the TilePalette.
- /// </summary>
- public class GridBrushPickStore : ScriptableObject
- {
- private static readonly string s_LibraryPickPath = "Library/GridBrush/Pick";
- private static readonly string s_LastPickPath = "Library/GridBrush/Last";
- private static readonly string s_UserPickPath = "Library/GridBrush/User";
-
- private static readonly string s_LibraryAssetName = "Default";
- private static readonly string s_AssetExtension = ".asset";
-
- private static readonly string k_GridBrushPickLastSavedMaxCountPref = "GridBrushPickLastSavedMaxCount";
- private static readonly string k_GridBrushPickUserSavedMaxCountPref = "GridBrushPickUserSavedMaxCount";
- private static readonly string k_GridBrushPickLastIndexPref = "GridBrushPickLastIndex";
- private static readonly string k_GridBrushPickLastSavedCountPref = "GridBrushPickLastSavedCount";
-
- internal static int gridBrushPickLastSavedMaxCount
- {
- get => EditorPrefs.GetInt(k_GridBrushPickLastSavedMaxCountPref, 5);
- set => EditorPrefs.SetInt(k_GridBrushPickLastSavedMaxCountPref, value);
- }
-
- internal static int gridBrushPickUserSavedMaxCount
- {
- get => EditorPrefs.GetInt(k_GridBrushPickUserSavedMaxCountPref, 50);
- set => EditorPrefs.SetInt(k_GridBrushPickUserSavedMaxCountPref, value);
- }
-
- internal static int gridBrushPickLastIndex
- {
- get => EditorPrefs.GetInt(k_GridBrushPickLastIndexPref, -1);
- set => EditorPrefs.SetInt(k_GridBrushPickLastIndexPref, value);
- }
-
- internal static int gridBrushPickLastSavedCount
- {
- get => EditorPrefs.GetInt(k_GridBrushPickLastSavedCountPref, 0);
- set => EditorPrefs.SetInt(k_GridBrushPickLastSavedCountPref, value);
- }
-
- [HideInInspector]
- [SerializeField]
- private int m_UserSavedCount;
- private Type m_FilteredBrushType;
- [HideInInspector]
- [SerializeField]
- private string m_FilteredBrushText;
-
- private List<GridBrushBase> m_LastSavedBrushes = new List<GridBrushBase>();
-
- [SerializeField]
- private List<GridBrushBase> m_UserSavedBrushes = new List<GridBrushBase>();
- private List<GridBrushBase> m_FilteredUserSavedBrushes = new List<GridBrushBase>();
-
- /// <summary>
- /// The index of the latest last pick that was made.
- /// </summary>
- public int lastIndex => gridBrushPickLastIndex;
-
- /// <summary>
- /// A list of GridBrushBases which represent the last picks made.
- /// </summary>
- public List<GridBrushBase> lastSavedBrushes
- {
- get => m_LastSavedBrushes;
- }
-
- /// <summary>
- /// A list of GridBrushBases which represent the user picks made.
- /// </summary>
- public List<GridBrushBase> userSavedBrushes
- {
- get => m_UserSavedBrushes;
- }
-
- /// <summary>
- /// A list of GridBrushBases which represent the user picks made
- /// filtered by the current filter type.
- /// </summary>
- public List<GridBrushBase> filteredUserSavedBrushes
- {
- get => m_FilteredUserSavedBrushes;
- }
-
- private void OnDestroy()
- {
- foreach (var brush in m_LastSavedBrushes)
- {
- if (!EditorUtility.IsPersistent(brush))
- DestroyImmediate(brush);
- }
- m_LastSavedBrushes.Clear();
- foreach (var brush in m_UserSavedBrushes)
- {
- if (!EditorUtility.IsPersistent(brush))
- DestroyImmediate(brush);
- }
- m_UserSavedBrushes.Clear();
- }
-
- internal int GetIndexOfLastSavedBrush(GridBrushBase brush)
- {
- return m_LastSavedBrushes.IndexOf(brush);
- }
-
- internal int GetIndexOfUserBrush(GridBrushBase brush)
- {
- return m_UserSavedBrushes.IndexOf(brush);
- }
-
- internal int GetIndexOfUserBrushFromFilteredIdx(int filteredIdx)
- {
- if (filteredIdx < 0 || filteredIdx >= filteredUserSavedBrushes.Count)
- return -1;
- return GetIndexOfUserBrush(filteredUserSavedBrushes[filteredIdx]);
- }
-
- internal bool IsValid()
- {
- return (lastSavedBrushes.Count == 0 || lastSavedBrushes[0] != null)
- && (userSavedBrushes.Count == 0 || userSavedBrushes[0] != null)
- && (filteredUserSavedBrushes.Count == 0 || filteredUserSavedBrushes[0] != null);
- }
-
- /// <summary>
- /// Adds the specified Brush as a new last pick.
- /// </summary>
- /// <description>
- /// This will add a copy of the Brush as a new last pick. If this new copy is over
- /// the limit of the number of last picks, the oldest last pick will be erased.
- /// The last index of the GridBrushPickStore will be changed to this new addition.
- /// </description>
- /// <param name="brush">Brush to save as a new last pick.</param>
- public void AddNewLastSavedBrush(GridBrushBase brush)
- {
- if (brush == null)
- return;
-
- var clone = Instantiate(brush);
- var name = brush.name;
- if (String.IsNullOrWhiteSpace(name))
- name = brush.GetType().Name;
- clone.name = name;
-
- var nextIndex = (lastIndex + 1) % gridBrushPickLastSavedMaxCount;
- if (nextIndex < m_LastSavedBrushes.Count)
- m_LastSavedBrushes[nextIndex] = clone;
- else
- m_LastSavedBrushes.Add(clone);
- SaveLibraryGridBrushAsset(clone, nextIndex, false);
-
- gridBrushPickLastIndex = nextIndex;
- gridBrushPickLastSavedCount = m_LastSavedBrushes.Count;
-
- GridPaintingState.InvokeBrushPickStoreChanged();
- }
-
- /// <summary>
- /// Clears the Brush at the index of the last pick list.
- /// </summary>
- /// <description>
- /// This will clear the pick at the index, but will not change the size of the
- /// pick list.
- /// </description>
- /// <param name="index">The index of the Brush of the last pick list to clear.</param>
- public void ClearLastSavedBrush(int index)
- {
- if (index < 0 || index >= m_LastSavedBrushes.Count)
- return;
-
- m_LastSavedBrushes[index] = null;
-
- FilterBrushes();
- SaveGridBrushPickStoreAsset();
- var gridBrushPath = GenerateGridBrushInstanceLibraryPath(index, false);
- FileUtil.DeleteFileOrDirectory(gridBrushPath);
- }
-
- /// <summary>
- /// Adds the specified Brush as a new user pick.
- /// </summary>
- /// <param name="brush">Brush to save as a new user pick.</param>
- public void AddNewUserSavedBrush(GridBrushBase brush)
- {
- if (brush == null)
- return;
-
- var clone = Instantiate(brush);
- var name = brush.name;
- if (String.IsNullOrWhiteSpace(name))
- name = brush.GetType().Name;
- clone.name = name;
- m_UserSavedBrushes.Add(clone);
- m_UserSavedCount = m_UserSavedBrushes.Count;
- EditorUtility.SetDirty(this);
-
- FilterBrushes();
- SaveLibraryGridBrushAsset(clone, m_UserSavedCount - 1, true);
- SaveGridBrushPickStoreAsset();
- }
-
- /// <summary>
- /// Swaps the position of the specified Brush
- /// </summary>
- /// <param name="oldIdx">Index of the Brush to swap.</param>
- /// <param name="newIdx">Index to swap the Brush to.</param>
- public void SwapUserSavedBrushes(int oldIdx, int newIdx)
- {
- if (oldIdx < 0 || oldIdx >= userSavedBrushes.Count)
- return;
-
- if (newIdx < 0 || newIdx >= userSavedBrushes.Count)
- return;
-
- var brush = userSavedBrushes[oldIdx];
- userSavedBrushes.RemoveAt(oldIdx);
- userSavedBrushes.Insert(newIdx, brush);
-
- if (AssetDatabase.IsNativeAsset(this))
- {
- SaveGridBrushPickStoreAsset();
- }
- else
- {
- SaveUserSavedBrushFromIndex(oldIdx < newIdx ? oldIdx : newIdx);
- }
- }
-
- private void SaveUserSavedBrushFromIndex(int index)
- {
- if (index < 0 || index >= m_UserSavedBrushes.Count)
- return;
-
- for (int i = index; i < m_UserSavedCount; ++i)
- SaveLibraryGridBrushAsset(m_UserSavedBrushes[i], i, true);
-
- FilterBrushes();
- }
-
- /// <summary>
- /// Saves over a brush in the user pick with the given index with
- /// the specified Brush.
- /// </summary>
- /// <param name="index">The index of the Brush of the user pick list to save over.</param>
- /// <param name="brush">Brush to save over as a user pick.</param>
- public void SaveUserSavedBrush(int index, GridBrushBase brush)
- {
- if (brush == null)
- return;
-
- if (index < 0 || index >= m_UserSavedBrushes.Count)
- return;
-
- if (m_UserSavedBrushes[index] != brush)
- {
- var clone = Instantiate(brush);
- clone.name = brush.name;
- m_UserSavedBrushes[index] = clone;
- brush = clone;
- }
- m_UserSavedCount = m_UserSavedBrushes.Count;
- EditorUtility.SetDirty(this);
-
- FilterBrushes();
- SaveLibraryGridBrushAsset(brush, index, true);
- SaveGridBrushPickStoreAsset();
- }
-
- /// <summary>
- /// Removes the Brush at the index of the last pick list.
- /// </summary>
- /// <param name="index">The index of the Brush of the user pick list to remove.</param>
- /// <returns>Whether the Brush was removed.</returns>
- public bool RemoveUserSavedBrush(int index)
- {
- if (index < 0 || index >= m_UserSavedBrushes.Count)
- return false;
-
- var brush = m_UserSavedBrushes[index];
- m_UserSavedBrushes.RemoveAt(index);
- m_UserSavedCount = m_UserSavedBrushes.Count;
- EditorUtility.SetDirty(this);
-
- FilterBrushes();
- SaveGridBrushPickStoreAsset();
-
- if (brush != null && AssetDatabase.IsNativeAsset(brush))
- {
- AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(brush));
- }
- else
- {
- for (int i = index; i < m_UserSavedCount; ++i)
- SaveLibraryGridBrushAsset(m_UserSavedBrushes[i], i, true);
- }
-
- return true;
- }
-
- /// <summary>
- /// Sets the type to filter all user brushes by.
- /// </summary>
- /// <param name="filterType">Type to filter user brushes.</param>
- /// <param name="filterText">Text to filter user brush names.</param>
- public void SetUserBrushFilterType(Type filterType, string filterText)
- {
- m_FilteredBrushType = filterType;
- m_FilteredBrushText = filterText;
- FilterBrushes();
- }
-
- private void FilterBrushes()
- {
- m_FilteredUserSavedBrushes.Clear();
-
- foreach (var brush in m_UserSavedBrushes)
- {
- var validBrush = brush != null;
- var hasFilteredBrushType = m_FilteredBrushType != null;
- var hasFilteredBrushText = !String.IsNullOrWhiteSpace(m_FilteredBrushText);
-
- if (hasFilteredBrushType
- && validBrush && brush.GetType() != m_FilteredBrushType)
- {
- continue;
- }
- if (hasFilteredBrushText
- && validBrush
- && !Regex.IsMatch(brush.name, m_FilteredBrushText
- , RegexOptions.Singleline | RegexOptions.IgnoreCase))
- {
- continue;
- }
-
- // Show brush only if valid or there is no filter for an invalid brush
- if (validBrush || (!hasFilteredBrushType && !hasFilteredBrushText))
- m_FilteredUserSavedBrushes.Add(brush);
- }
- }
-
- private void SaveGridBrushPickStoreAsset()
- {
- if (AssetDatabase.IsNativeAsset(this))
- {
- EditorUtility.SetDirty(this);
- AssetDatabase.SaveAssetIfDirty(this);
- }
- else
- {
- var pickPath = GenerateGridBrushPickLibraryPath(s_LibraryAssetName);
- var folderPath = Path.GetDirectoryName(pickPath);
- if (!Directory.Exists(folderPath))
- {
- Directory.CreateDirectory(folderPath);
- }
- InternalEditorUtility.SaveToSerializedFileAndForget(new Object[] { this }, pickPath, EditorSettings.serializationMode != SerializationMode.ForceBinary);
- }
- GridPaintingState.InvokeBrushPickStoreChanged();
- }
-
- internal static GridBrushPickStore LoadOrCreateLibraryGridBrushPickAsset()
- {
- var pickStore = GridBrushPickStoreSettingsProvider.GetUserBrushPickStore();
- if (pickStore == null)
- {
- // Load library Grid Brush Pick Store
- var serializedObjects = InternalEditorUtility.LoadSerializedFileAndForget(GenerateGridBrushPickLibraryPath(s_LibraryAssetName));
- if (serializedObjects != null && serializedObjects.Length > 0)
- {
- pickStore = serializedObjects[0] as GridBrushPickStore;
- if (pickStore != null)
- {
- var count = pickStore.m_UserSavedCount;
- var userBrushes = new List<GridBrushBase>();
- for (int i = 0; i < count; ++i)
- {
- var brush = LoadLibraryGridBrushAsset(i, true);
- if (brush != null)
- {
- userBrushes.Add(brush);
- }
- else
- {
- userBrushes.Add(null);
- }
- }
- pickStore.m_UserSavedBrushes = userBrushes;
- }
- }
- }
-
- if (pickStore != null)
- {
- var index = gridBrushPickLastIndex;
- var count = gridBrushPickLastSavedCount;
- var brushes = new List<GridBrushBase>();
- for (int i = 0; i < count; ++i)
- {
- var brush = LoadLibraryGridBrushAsset(i, false);
- if (brush != null)
- {
- brushes.Add(brush);
- }
- else if (index >= brushes.Count)
- {
- index--;
- }
- }
- gridBrushPickLastIndex = index;
- gridBrushPickLastSavedCount = brushes.Count;
- pickStore.m_LastSavedBrushes = brushes;
- pickStore.FilterBrushes();
- return pickStore;
- }
-
- return CreateLibraryGridBrushPickAsset();
- }
-
- private void SaveLibraryGridBrushAsset(GridBrushBase brush, int index, bool user)
- {
- if (brush == null)
- return;
-
- if (user && AssetDatabase.IsNativeAsset(brush))
- {
- var assetPath = AssetDatabase.GetAssetPath(brush);
- var fileName = FileUtil.UnityGetFileNameWithoutExtension(assetPath);
- if (fileName != brush.name)
- {
- var newName = brush.name;
- brush.name = fileName;
- AssetDatabase.SaveAssetIfDirty(brush);
- AssetDatabase.RenameAsset(assetPath, newName);
- }
- else
- {
- AssetDatabase.SaveAssetIfDirty(brush);
- }
- }
- else if (user && AssetDatabase.IsNativeAsset(this))
- {
- var assetPath = AssetDatabase.GetAssetPath(this);
- var folderPath = Path.GetDirectoryName(assetPath);
- var gridBrushPath = FileUtil.CombinePaths(folderPath, $"{brush.name}{s_AssetExtension}");
- gridBrushPath = AssetDatabase.GenerateUniqueAssetPath(gridBrushPath);
- AssetDatabase.CreateAsset(brush, gridBrushPath);
- }
- else
- {
- var gridBrushPath = GenerateGridBrushInstanceLibraryPath(index, user);
- var folderPath = Path.GetDirectoryName(gridBrushPath);
- if (!Directory.Exists(folderPath))
- {
- Directory.CreateDirectory(folderPath);
- }
- InternalEditorUtility.SaveToSerializedFileAndForget(new Object[] { brush }, gridBrushPath, EditorSettings.serializationMode != SerializationMode.ForceBinary);
- }
- }
-
- private static GridBrushBase LoadLibraryGridBrushAsset(int index, bool user)
- {
- var gridBrushPath = GenerateGridBrushInstanceLibraryPath(index, user);
- var serializedObjects = InternalEditorUtility.LoadSerializedFileAndForget(gridBrushPath);
- if (serializedObjects != null && serializedObjects.Length > 0)
- {
- var brush = serializedObjects[0] as GridBrushBase;
- if (brush != null)
- return brush;
- }
- return null;
- }
-
- private static GridBrushPickStore CreateLibraryGridBrushPickAsset()
- {
- var pickStore = CreateInstance<GridBrushPickStore>();
- pickStore.hideFlags = HideFlags.DontSave;
- pickStore.name = s_LibraryAssetName;
- pickStore.SaveGridBrushPickStoreAsset();
- return pickStore;
- }
-
- private static string GenerateGridBrushPickLibraryPath(string name)
- {
- var path = FileUtil.CombinePaths(s_LibraryPickPath, name + s_AssetExtension);
- path = FileUtil.NiceWinPath(path);
- return path;
- }
-
- private static string GenerateGridBrushInstanceLibraryPath(int index, bool user)
- {
- var path = FileUtil.CombinePaths(user ? s_UserPickPath : s_LastPickPath, index.ToString() + s_AssetExtension);
- path = FileUtil.NiceWinPath(path);
- return path;
- }
- }
- }
|