using UnityEngine; using UnityEngine.Tilemaps; using UnityEditorInternal; using System.Collections.Generic; namespace UnityEditor { /// /// The Editor for an AdvancedRuleOverrideTileEditor. /// [CustomEditor(typeof(AdvancedRuleOverrideTile))] public class AdvancedRuleOverrideTileEditor : RuleOverrideTileEditor { private static class Styles { public static readonly GUIContent defaultSprite = EditorGUIUtility.TrTextContent("Default Sprite" , "Overrides the default Sprite for the original Rule Tile."); public static readonly GUIContent defaultGameObject = EditorGUIUtility.TrTextContent("Default GameObject" , "Overrides the default GameObject for the original Rule Tile."); public static readonly GUIContent defaultCollider = EditorGUIUtility.TrTextContent("Default Collider" , "Overrides the default Collider for the original Rule Tile."); } /// /// The AdvancedRuleOverrideTile being edited. /// public new AdvancedRuleOverrideTile overrideTile => target as AdvancedRuleOverrideTile; List> m_Rules = new List>(); private ReorderableList m_RuleList; private int m_MissingOriginalRuleIndex; private HashSet m_UniqueIds = new HashSet(); static float k_DefaultElementHeight { get { return RuleTileEditor.k_DefaultElementHeight; } } static float k_SingleLineHeight { get { return RuleTileEditor.k_SingleLineHeight; } } /// /// OnEnable for the AdvancedRuleOverrideTileEditor /// public override void OnEnable() { if (m_RuleList == null) { m_RuleList = new ReorderableList(m_Rules, typeof(KeyValuePair), false, true, false, false); m_RuleList.drawHeaderCallback = DrawRulesHeader; m_RuleList.drawElementCallback = DrawRuleElement; m_RuleList.elementHeightCallback = GetRuleElementHeight; } } /// /// Draws the Inspector GUI for the AdvancedRuleOverrideTileEditor /// public override void OnInspectorGUI() { serializedObject.UpdateIfRequiredOrScript(); DrawTileField(); EditorGUI.BeginChangeCheck(); overrideTile.m_DefaultSprite = EditorGUILayout.ObjectField(Styles.defaultSprite, overrideTile.m_DefaultSprite, typeof(Sprite), false) as Sprite; overrideTile.m_DefaultGameObject = EditorGUILayout.ObjectField(Styles.defaultGameObject, overrideTile.m_DefaultGameObject, typeof(GameObject), false) as GameObject; overrideTile.m_DefaultColliderType = (Tile.ColliderType)EditorGUILayout.EnumPopup(Styles.defaultCollider, overrideTile.m_DefaultColliderType); if (EditorGUI.EndChangeCheck()) SaveTile(); DrawCustomFields(); if (overrideTile.m_Tile) { ValidateRuleTile(overrideTile.m_Tile); overrideTile.GetOverrides(m_Rules, ref m_MissingOriginalRuleIndex); } m_RuleList.DoLayoutList(); } private void ValidateRuleTile(RuleTile ruleTile) { // Ensure that each Tiling Rule in the RuleTile has a unique ID m_UniqueIds.Clear(); var startId = 0; foreach (var rule in ruleTile.m_TilingRules) { if (m_UniqueIds.Contains(rule.m_Id)) { do { rule.m_Id = startId++; } while (m_UniqueIds.Contains(rule.m_Id)); EditorUtility.SetDirty(ruleTile); } m_UniqueIds.Add(rule.m_Id); startId++; } } /// /// Draws the Header for the Rule list /// /// Rect to draw the header in public void DrawRulesHeader(Rect rect) { GUI.Label(rect, "Tiling Rules", EditorStyles.label); } /// /// Draws the Rule element for the Rule list /// /// Rect to draw the Rule Element in /// Index of the Rule Element to draw /// Whether the Rule Element is active /// Whether the Rule Element is focused public void DrawRuleElement(Rect rect, int index, bool active, bool focused) { RuleTile.TilingRule originalRule = m_Rules[index].Key; if (originalRule == null) return; RuleTile.TilingRuleOutput overrideRule = m_Rules[index].Value; bool isMissing = index >= m_MissingOriginalRuleIndex; DrawToggleInternal(new Rect(rect.xMin, rect.yMin, 16, rect.height)); DrawRuleInternal(new Rect(rect.xMin + 16, rect.yMin, rect.width - 16, rect.height)); void DrawToggleInternal(Rect r) { EditorGUI.BeginChangeCheck(); bool enabled = EditorGUI.Toggle(new Rect(r.xMin, r.yMin, r.width, k_SingleLineHeight), overrideRule != null); if (EditorGUI.EndChangeCheck()) { if (enabled) overrideTile[originalRule] = originalRule; else overrideTile[originalRule] = null; SaveTile(); } } void DrawRuleInternal(Rect r) { EditorGUI.BeginChangeCheck(); DrawRule(r, overrideRule ?? originalRule, overrideRule != null, originalRule, isMissing); if (EditorGUI.EndChangeCheck()) SaveTile(); } } /// /// Draw a Rule Override for the AdvancedRuleOverrideTileEditor /// /// Rect to draw the Rule in /// The Rule Override to draw /// Whether the original Rule is being overridden /// Original Rule to override /// Whether the original Rule is missing public void DrawRule(Rect rect, RuleTile.TilingRuleOutput rule, bool isOverride, RuleTile.TilingRule originalRule, bool isMissing) { if (isMissing) { EditorGUI.HelpBox(new Rect(rect.xMin, rect.yMin, rect.width, 16), "Original Tiling Rule missing", MessageType.Warning); rect.yMin += 16; } using (new EditorGUI.DisabledScope(!isOverride)) { float yPos = rect.yMin + 2f; float height = rect.height - k_PaddingBetweenRules; float matrixWidth = k_DefaultElementHeight; BoundsInt ruleBounds = originalRule.GetBounds(); BoundsInt ruleGuiBounds = ruleTileEditor.GetRuleGUIBounds(ruleBounds, originalRule); Vector2 matrixSize = ruleTileEditor.GetMatrixSize(ruleGuiBounds); Vector2 matrixSizeRate = matrixSize / Mathf.Max(matrixSize.x, matrixSize.y); Vector2 matrixRectSize = new Vector2(matrixWidth * matrixSizeRate.x, k_DefaultElementHeight * matrixSizeRate.y); Vector2 matrixRectPosition = new Vector2(rect.xMax - matrixWidth * 2f - 10f, yPos); matrixRectPosition.x += (matrixWidth - matrixRectSize.x) * 0.5f; matrixRectPosition.y += (k_DefaultElementHeight - matrixRectSize.y) * 0.5f; Rect inspectorRect = new Rect(rect.xMin, yPos, rect.width - matrixWidth * 2f - 20f, height); Rect matrixRect = new Rect(matrixRectPosition, matrixRectSize); Rect spriteRect = new Rect(rect.xMax - matrixWidth - 5f, yPos, matrixWidth, k_DefaultElementHeight); ruleTileEditor.RuleInspectorOnGUI(inspectorRect, rule); ruleTileEditor.SpriteOnGUI(spriteRect, rule); if (!isMissing) using (new EditorGUI.DisabledScope(true)) ruleTileEditor.RuleMatrixOnGUI(overrideTile.m_InstanceTile, matrixRect, ruleGuiBounds, originalRule); } } /// /// Returns the height for an indexed Rule Element /// /// Index of the Rule Element /// Height of the indexed Rule Element public float GetRuleElementHeight(int index) { var originalRule = m_Rules[index].Key; var overrideRule = m_Rules[index].Value; float height = overrideRule != null ? ruleTileEditor.GetElementHeight(overrideRule) : ruleTileEditor.GetElementHeight(originalRule); bool isMissing = index >= m_MissingOriginalRuleIndex; if (isMissing) height += 16; return height; } } }