using System; using System.Collections.Generic; using UnityEditor.EditorTools; using UnityEditor.ShortcutManagement; using UnityEngine; namespace UnityEditor.Tilemaps { /// /// A base class for Editor Tools which work with the Tile Palette /// and GridBrushes /// public abstract class TilemapEditorTool : EditorTool { /// /// Context to determine if TilemapEditorTools can be triggered through shortcuts /// public class ShortcutContext : IShortcutToolContext { public bool active { get; set; } } private static Dictionary s_TilemapEditorToolsMap; private static EditorTool[] s_DefaultTilemapEditorTools; /// /// Types for all the Default Editor Tools /// internal static Type[] s_DefaultToolTypes = new[] { typeof(SelectTool), typeof(MoveTool), typeof(PaintTool), typeof(BoxTool), typeof(PickingTool), typeof(EraseTool), typeof(FillTool) }; /// /// All currently active Editor Tools which work with the Tile Palette /// public static EditorTool[] tilemapEditorTools { get { if (IsCachedEditorToolsInvalid()) InstantiateEditorTools(); return GridPaintingState.activeBrushTools; } } /// /// The horizontal size of a Toolbar with all the TilemapEditorTools /// public static float tilemapEditorToolsToolbarSize { get { if (IsCachedEditorToolsInvalid()) InstantiateEditorTools(); return GridPaintingState.activeBrushToolbarSize; } } /// /// Tooltip String format which accepts a shortcut combination as the parameter /// protected abstract string tooltipStringFormat { get; } /// /// Shortcut Id for this tool /// protected abstract string shortcutId { get; } /// /// Gets the text for the tooltip given a tooltip string format /// and the shortcut combination for a tooltip /// /// String format which accepts a shortcut combination as the parameter /// Shortcut Id for this tool /// The final text for the tooltip protected static string GetTooltipText(string tooltipStringFormat, string shortcutId) { return String.Format(tooltipStringFormat, GetKeysFromToolName(shortcutId)); } /// /// Gets the key combination for triggering the shortcut for this tool /// /// The shortcut id for this tool /// The key combination for triggering the shortcut for this tool protected static string GetKeysFromToolName(string id) { return ShortcutIntegration.instance.GetKeyCombinationFor(id); } /// /// Updates the tooltip whenever there is a change in shortcut combinations /// protected void UpdateTooltip() { toolbarIcon.tooltip = GetTooltipText(tooltipStringFormat, shortcutId); } /// /// Method called when the Tool is being used. /// Override this to have custom behaviour when the Tool is used. /// /// Whether the tool is the hot control /// GridLayout the tool is being used on /// Target GameObject the tool is being used on /// Grid Cell position of the Mouse on the GridLayout /// Whether the tool has been used and modified the brushTarget public virtual bool HandleTool(bool isHotControl, GridLayout gridLayout, GameObject brushTarget, Vector3Int gridMousePosition) { return false; } /// /// Gets whether the tool is available for use /// /// Whether the tool is available for use public override bool IsAvailable() { return (GridPaintPaletteWindow.instances.Count > 0) && GridPaintingState.gridBrush; } internal static void UpdateTooltips() { if (IsCachedEditorToolsInvalid()) InstantiateEditorTools(); foreach (var editorTool in GridPaintingState.activeBrushTools) { var tilemapEditorTool = editorTool as TilemapEditorTool; if (tilemapEditorTool == null) return; tilemapEditorTool.UpdateTooltip(); } } /// /// Toggles the state of active editor tool with the type passed in. /// /// /// This will change the current active editor tool if the type passed in /// is not the same as the current active editor tool. Otherwise, it will /// set the View Mode tool as the current active editor tool. /// /// /// The type of editor tool. This must be inherited from EditorTool. /// public static void ToggleActiveEditorTool(Type type) { if (ToolManager.activeToolType != type) { SetActiveEditorTool(type); } else { ToolManager.RestorePreviousPersistentTool(); } } /// /// Sets the current active editor tool to the type passed in /// /// The type of editor tool. This must be inherited from TilemapEditorTool /// Throws this if an invalid type parameter is set public static void SetActiveEditorTool(Type type) { if (type == null || !type.IsSubclassOf(typeof(TilemapEditorTool))) throw new ArgumentException("The tool to set must be valid and derive from TilemapEditorTool."); EditorTool selectedTool = null; foreach (var tool in tilemapEditorTools) { if (tool.GetType() == type) { selectedTool = tool; break; } } if (selectedTool != null) { ToolManager.SetActiveTool(selectedTool); } } internal static bool IsActive(Type toolType) { return ToolManager.activeToolType != null && ToolManager.activeToolType == toolType; } private static bool IsCachedEditorToolsInvalid() { return s_TilemapEditorToolsMap == null || s_DefaultTilemapEditorTools == null || s_DefaultTilemapEditorTools.Length == 0 || s_DefaultTilemapEditorTools[0] == null; } private static void InstantiateEditorTools() { s_DefaultTilemapEditorTools = TilemapEditorToolPreferences.CreateDefaultTilePaletteEditorTools(); s_TilemapEditorToolsMap = new Dictionary(s_DefaultTilemapEditorTools.Length); foreach (var editorTool in s_DefaultTilemapEditorTools) { s_TilemapEditorToolsMap.Add(editorTool.GetType(), editorTool); } GridPaintingState.UpdateBrushToolbar(); } internal static void UpdateEditorTools(BrushToolsAttribute brushToolsAttribute) { if (IsCachedEditorToolsInvalid()) InstantiateEditorTools(); EditorTool[] editorTools; if (brushToolsAttribute?.toolList == null || brushToolsAttribute.toolList.Count == 0) { editorTools = s_DefaultTilemapEditorTools; } else { editorTools = new EditorTool[brushToolsAttribute.toolList.Count]; for (int i = 0; i < brushToolsAttribute.toolList.Count; ++i) { var toolType = brushToolsAttribute.toolList[i]; if (!s_TilemapEditorToolsMap.TryGetValue(toolType, out EditorTool editorTool)) { editorTool = (EditorTool)ScriptableObject.CreateInstance(toolType); s_TilemapEditorToolsMap.Add(toolType, editorTool); } editorTools[i] = editorTool; } } GridPaintingState.SetBrushTools(editorTools); } internal static bool IsCustomTilemapEditorToolActive() { if (EditorToolManager.activeTool == null || !(EditorToolManager.activeTool is TilemapEditorTool)) return false; if (s_DefaultTilemapEditorTools == null) return false; var activeToolType = EditorToolManager.activeTool.GetType(); foreach (var toolType in s_DefaultToolTypes) { if (toolType == activeToolType) return false; } return true; } } }