123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using UnityEditor.EditorTools;
- using UnityEngine;
- using Object = UnityEngine.Object;
-
- namespace UnityEditor.Tilemaps
- {
- /// <summary>
- /// GridPaintingState controls the state of objects for painting with a Tile Palette.
- /// </summary>
- /// <remarks>
- /// Utilize this class to get and set the current painting target and brush for painting
- /// with the Tile Palette.
- /// </remarks>
- public class GridPaintingState : ScriptableSingleton<GridPaintingState>
- {
- [SerializeField] private GameObject m_EditModeScenePaintTarget; // Which GameObject in scene was the last painting target in EditMode
- [SerializeField] private GameObject m_ScenePaintTarget; // Which GameObject in scene is considered as painting target
- [SerializeField] private EditorTool[] m_BrushTools;
- [SerializeField] private GridBrushBase m_Brush; // Which brush will handle painting callbacks
- [SerializeField] private PaintableGrid m_ActiveGrid; // Grid that has painting focus (can be palette, too)
- [SerializeField] private PaintableGrid m_LastActiveGrid; // Grid that last had painting focus (can be palette, too)
- [SerializeField] private HashSet<Object> m_InterestedPainters = new HashSet<Object>(); // A list of objects that can paint using the GridPaintingState
-
- private GameObject[] m_CachedPaintTargets;
- private bool m_FlushPaintTargetCache;
- private Editor m_CachedEditor;
- private bool m_SavingPalette;
- private float m_BrushToolbarSize;
-
- /// <summary>
- /// Callback when the Tile Palette's active target has changed
- /// </summary>
- public static event Action<GameObject> scenePaintTargetChanged;
- /// <summary>
- /// Callback when the Tile Palette's active brush has changed.
- /// </summary>
- public static event Action<GridBrushBase> brushChanged;
- /// <summary>
- /// Callback when the Tile Palette's active palette GameObject has changed.
- /// </summary>
- public static event Action<GameObject> paletteChanged;
-
- private void OnEnable()
- {
- EditorApplication.hierarchyChanged += HierarchyChanged;
- EditorApplication.playModeStateChanged += PlayModeStateChanged;
- Selection.selectionChanged += OnSelectionChange;
- m_FlushPaintTargetCache = true;
- }
-
- private void OnDisable()
- {
- m_InterestedPainters.Clear();
- EditorApplication.hierarchyChanged -= HierarchyChanged;
- EditorApplication.playModeStateChanged -= PlayModeStateChanged;
- Selection.selectionChanged -= OnSelectionChange;
- FlushCache();
- }
-
- private void OnSelectionChange()
- {
- if (hasInterestedPainters && ValidatePaintTarget(Selection.activeGameObject))
- {
- scenePaintTarget = Selection.activeGameObject;
- }
- }
-
- private void PlayModeStateChanged(PlayModeStateChange state)
- {
- if (state == PlayModeStateChange.ExitingEditMode)
- {
- m_EditModeScenePaintTarget = scenePaintTarget;
- }
- else if (state == PlayModeStateChange.EnteredEditMode)
- {
- if (GridPaintActiveTargetsPreferences.restoreEditModeSelection && m_EditModeScenePaintTarget != null)
- {
- scenePaintTarget = m_EditModeScenePaintTarget;
- }
- }
- }
-
- private void HierarchyChanged()
- {
- if (hasInterestedPainters)
- {
- m_FlushPaintTargetCache = true;
- if (validTargets == null || validTargets.Length == 0 || !validTargets.Contains(scenePaintTarget))
- {
- // case 1102618: Try to use current Selection as scene paint target if possible
- if (Selection.activeGameObject != null && hasInterestedPainters && ValidatePaintTarget(Selection.activeGameObject))
- {
- scenePaintTarget = Selection.activeGameObject;
- }
- else
- {
- AutoSelectPaintTarget();
- }
- }
- }
- }
-
- private GameObject[] GetValidTargets()
- {
- if (m_FlushPaintTargetCache)
- {
- m_CachedPaintTargets = null;
- if (activeBrushEditor != null)
- m_CachedPaintTargets = activeBrushEditor.validTargets;
- if (m_CachedPaintTargets == null || m_CachedPaintTargets.Length == 0)
- scenePaintTarget = null;
- else
- {
- var comparer = GridPaintActiveTargetsPreferences.GetTargetComparer();
- if (comparer != null)
- Array.Sort(m_CachedPaintTargets, comparer);
- }
-
- m_FlushPaintTargetCache = false;
- }
- return m_CachedPaintTargets;
- }
-
- internal static void AutoSelectPaintTarget()
- {
- if (activeBrushEditor != null)
- {
- if (validTargets != null && validTargets.Length > 0)
- {
- scenePaintTarget = validTargets[0];
- }
- }
- }
-
- /// <summary>
- /// The currently active target for the Tile Palette
- /// </summary>
- public static GameObject scenePaintTarget
- {
- get { return instance.m_ScenePaintTarget; }
- set
- {
- if (value != instance.m_ScenePaintTarget)
- {
- instance.m_ScenePaintTarget = value;
- if (scenePaintTargetChanged != null)
- scenePaintTargetChanged(instance.m_ScenePaintTarget);
- RepaintGridPaintPaletteWindow();
- }
- }
- }
-
- /// <summary>
- /// The currently active brush for the Tile Palette
- /// </summary>
- public static GridBrushBase gridBrush
- {
- get
- {
- if (instance.m_Brush == null)
- {
- instance.m_Brush = GridPaletteBrushes.instance.GetLastUsedBrush();
- UpdateBrushToolbar();
- }
- return instance.m_Brush;
- }
- set
- {
- if (instance.m_Brush != value)
- {
- instance.m_Brush = value;
- instance.m_FlushPaintTargetCache = true;
-
- if (value != null)
- {
- GridPaletteBrushes.instance.StoreLastUsedBrush(value);
- UpdateBrushToolbar();
- }
-
- // Ensure that current scenePaintTarget is still a valid target after a brush change
- if (scenePaintTarget != null && !ValidatePaintTarget(scenePaintTarget))
- scenePaintTarget = null;
-
- // Use Selection if previous scenePaintTarget was not valid
- if (scenePaintTarget == null)
- scenePaintTarget = ValidatePaintTarget(Selection.activeGameObject) ? Selection.activeGameObject : null;
-
- // Auto select a valid target if there is still no scenePaintTarget
- if (scenePaintTarget == null)
- AutoSelectPaintTarget();
-
- if (null != brushChanged)
- brushChanged(value);
-
- RepaintGridPaintPaletteWindow();
- }
- }
- }
-
- /// <summary>
- /// Returns all available brushes for the Tile Palette
- /// </summary>
- public static IList<GridBrushBase> brushes
- {
- get { return GridPaletteBrushes.brushes; }
- }
-
- internal static GridBrush defaultBrush
- {
- get { return gridBrush as GridBrush; }
- set { gridBrush = value; }
- }
-
- /// <summary>
- /// The currently active palette GameObject for the Tile Palette
- /// </summary>
- public static GameObject palette
- {
- get
- {
- if (GridPaintPaletteWindow.instances.Count > 0)
- return GridPaintPaletteWindow.instances[0].palette;
- return null;
- }
- set
- {
- if (value == null || !GridPalettes.palettes.Contains(value))
- throw new ArgumentException(L10n.Tr("Unable to set invalid palette"));
- if (GridPaintPaletteWindow.instances.Count > 0 && GridPaintPaletteWindow.instances[0].palette != value)
- {
- GridPaintPaletteWindow.instances[0].palette = value;
- }
- }
- }
-
- /// <summary>
- /// Checks if target GameObject is part of the active Palette.
- /// </summary>
- /// <param name="target">GameObject to check.</param>
- /// <returns>True if the target GameObject is part of the active palette. False if not.</returns>
- public static bool IsPartOfActivePalette(GameObject target)
- {
- if (GridPaintPaletteWindow.instances.Count > 0 && target == GridPaintPaletteWindow.instances[0].paletteInstance)
- return true;
- if (target == palette)
- return true;
- var parent = target.transform.parent;
- return parent != null && IsPartOfActivePalette(parent.gameObject);
- }
-
- /// <summary>
- /// Returns all available Palette GameObjects for the Tile Palette
- /// </summary>
- public static IList<GameObject> palettes
- {
- get { return GridPalettes.palettes; }
- }
-
- /// <summary>
- /// The currently active editor for the active brush for the Tile Palette
- /// </summary>
- public static GridBrushEditorBase activeBrushEditor
- {
- get
- {
- Editor.CreateCachedEditor(gridBrush, null, ref instance.m_CachedEditor);
- GridBrushEditorBase baseEditor = instance.m_CachedEditor as GridBrushEditorBase;
- return baseEditor;
- }
- }
-
- internal static Editor fallbackEditor
- {
- get
- {
- Editor.CreateCachedEditor(gridBrush, null, ref instance.m_CachedEditor);
- return instance.m_CachedEditor;
- }
- }
-
- internal static PaintableGrid activeGrid
- {
- get { return instance.m_ActiveGrid; }
- set
- {
- instance.m_ActiveGrid = value;
- if (instance.m_ActiveGrid != null)
- instance.m_LastActiveGrid = value;
- }
- }
-
- internal static PaintableGrid lastActiveGrid
- {
- get { return instance.m_LastActiveGrid; }
- }
-
- internal static EditorTool[] activeBrushTools
- {
- get { return instance.m_BrushTools; }
- set { instance.m_BrushTools = value; }
- }
-
- internal static float activeBrushToolbarSize
- {
- get
- {
- if (instance.m_BrushToolbarSize == 0.0f)
- CalculateToolbarSize();
- return instance.m_BrushToolbarSize;
- }
- set { instance.m_BrushToolbarSize = value; }
- }
-
- private static void CalculateToolbarSize()
- {
- GUIStyle toolbarStyle = "Command";
- activeBrushToolbarSize = activeBrushTools.Sum(x => toolbarStyle.CalcSize(x.toolbarIcon).x);
- }
-
- internal static void SetBrushTools(EditorTool[] editorTools)
- {
- activeBrushTools = editorTools;
- activeBrushToolbarSize = 0.0f;
- }
-
- private static bool ValidatePaintTarget(GameObject candidate)
- {
- if (candidate == null)
- return false;
-
- // Case 1327021: Do not allow disabled GameObjects as a paint target
- if (!candidate.activeInHierarchy)
- return false;
-
- if (candidate.GetComponentInParent<Grid>() == null && candidate.GetComponent<Grid>() == null)
- return false;
-
- if (validTargets != null && validTargets.Length > 0 && !validTargets.Contains(candidate))
- return false;
-
- if (PrefabUtility.IsPartOfPrefabAsset(candidate))
- return false;
-
- return true;
- }
-
- internal static void FlushCache()
- {
- if (instance.m_CachedEditor != null)
- {
- DestroyImmediate(instance.m_CachedEditor);
- instance.m_CachedEditor = null;
- }
- instance.m_FlushPaintTargetCache = true;
- }
-
- /// <summary>
- /// A list of all valid targets that can be set as an active target for the Tile Palette
- /// </summary>
- public static GameObject[] validTargets
- {
- get { return instance.GetValidTargets(); }
- }
-
- internal static bool savingPalette
- {
- get { return instance.m_SavingPalette; }
- set { instance.m_SavingPalette = value; }
- }
-
- internal static void OnPaletteChanged(GameObject palette)
- {
- if (null != paletteChanged)
- paletteChanged(palette);
- }
-
- internal static void UpdateBrushToolbar()
- {
- BrushToolsAttribute toolAttribute = null;
- if (instance.m_Brush != null)
- toolAttribute = (BrushToolsAttribute)instance.m_Brush.GetType().GetCustomAttribute(typeof(BrushToolsAttribute), false);
- TilemapEditorTool.UpdateEditorTools(toolAttribute);
- }
-
- internal static void UpdateActiveGridPalette()
- {
- if (GridPaintPaletteWindow.instances.Count > 0)
- GridPaintPaletteWindow.instances[0].DelayedResetPreviewInstance();
- }
-
- internal static void RepaintGridPaintPaletteWindow()
- {
- if (GridPaintPaletteWindow.instances.Count > 0)
- GridPaintPaletteWindow.instances[0].Repaint();
- }
-
- internal static void UnlockGridPaintPaletteClipboardForEditing()
- {
- if (GridPaintPaletteWindow.instances.Count > 0)
- GridPaintPaletteWindow.instances[0].clipboardView.UnlockAndEdit();
- }
-
- internal static void RegisterPainterInterest(Object painter)
- {
- instance.m_InterestedPainters.Add(painter);
- }
-
- internal static void UnregisterPainterInterest(Object painter)
- {
- instance.m_InterestedPainters.Remove(painter);
- }
-
- private bool hasInterestedPainters
- {
- get { return m_InterestedPainters.Count > 0; }
- }
- }
- }
|