Singularity/Library/PackageCache/com.unity.2d.tilemap.extras.../Editor/Tiles/RuleOverrideTile/RuleOverrideTileEditor.cs

435 lines
16 KiB
C#
Raw Normal View History

2024-05-06 14:45:45 -04:00
using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEditorInternal;
using System.Collections.Generic;
namespace UnityEditor
{
/// <summary>
/// The Editor for a RuleOverrideTileEditor.
/// </summary>
[CustomEditor(typeof(RuleOverrideTile))]
public class RuleOverrideTileEditor : Editor
{
private static class Styles
{
public static readonly GUIContent overrideTile = EditorGUIUtility.TrTextContent("Tile"
, "The Rule Tile to override.");
}
/// <summary>
/// The RuleOverrideTile being edited
/// </summary>
public RuleOverrideTile overrideTile => target as RuleOverrideTile;
/// <summary>
/// The RuleTileEditor for the overridden instance of the RuleTile
/// </summary>
public RuleTileEditor ruleTileEditor
{
get
{
if (m_RuleTileEditorTarget != overrideTile.m_Tile)
{
DestroyImmediate(m_RuleTileEditor);
m_RuleTileEditor = Editor.CreateEditor(overrideTile.m_InstanceTile) as RuleTileEditor;
m_RuleTileEditorTarget = overrideTile.m_Tile;
}
return m_RuleTileEditor;
}
}
RuleTileEditor m_RuleTileEditor;
RuleTile m_RuleTileEditorTarget;
/// <summary>
/// List of Sprites and overriding Sprites
/// </summary>
public List<KeyValuePair<Sprite, Sprite>> m_Sprites = new List<KeyValuePair<Sprite, Sprite>>();
/// <summary>
/// List of GameObjects and overriding GameObjects
/// </summary>
public List<KeyValuePair<GameObject, GameObject>> m_GameObjects = new List<KeyValuePair<GameObject, GameObject>>();
private ReorderableList m_SpriteList;
private ReorderableList m_GameObjectList;
private int m_MissingOriginalSpriteIndex;
private int m_MissingOriginalGameObjectIndex;
/// <summary>
/// Height for a Sprite Element
/// </summary>
public static float k_SpriteElementHeight = 48;
/// <summary>
/// Height for a GameObject Element
/// </summary>
public static float k_GameObjectElementHeight = 16;
/// <summary>
/// Padding between Rule Elements
/// </summary>
public static float k_PaddingBetweenRules = 4;
/// <summary>
/// OnEnable for the RuleOverrideTileEditor
/// </summary>
public virtual void OnEnable()
{
if (m_SpriteList == null)
{
m_SpriteList = new ReorderableList(m_Sprites, typeof(KeyValuePair<Sprite, Sprite>), false, true, false, false);
m_SpriteList.drawHeaderCallback = DrawSpriteListHeader;
m_SpriteList.drawElementCallback = DrawSpriteElement;
m_SpriteList.elementHeightCallback = GetSpriteElementHeight;
}
if (m_GameObjectList == null)
{
m_GameObjectList = new ReorderableList(m_GameObjects, typeof(KeyValuePair<Sprite, Sprite>), false, true, false, false);
m_GameObjectList.drawHeaderCallback = DrawGameObjectListHeader;
m_GameObjectList.drawElementCallback = DrawGameObjectElement;
m_GameObjectList.elementHeightCallback = GetGameObjectElementHeight;
}
}
/// <summary>
/// OnDisable for the RuleOverrideTileEditor
/// </summary>
public virtual void OnDisable()
{
DestroyImmediate(ruleTileEditor);
m_RuleTileEditorTarget = null;
}
/// <summary>
/// Draws the Inspector GUI for the RuleOverrideTileEditor
/// </summary>
public override void OnInspectorGUI()
{
serializedObject.UpdateIfRequiredOrScript();
DrawTileField();
DrawCustomFields();
overrideTile.GetOverrides(m_Sprites, ref m_MissingOriginalSpriteIndex);
overrideTile.GetOverrides(m_GameObjects, ref m_MissingOriginalGameObjectIndex);
EditorGUI.BeginChangeCheck();
m_SpriteList.DoLayoutList();
if (EditorGUI.EndChangeCheck())
{
overrideTile.ApplyOverrides(m_Sprites);
SaveTile();
}
EditorGUI.BeginChangeCheck();
m_GameObjectList.DoLayoutList();
if (EditorGUI.EndChangeCheck())
{
overrideTile.ApplyOverrides(m_GameObjects);
SaveTile();
}
}
/// <summary>
/// Draws the header for the Sprite list
/// </summary>
/// <param name="rect">GUI Rect to draw the header at</param>
public void DrawSpriteListHeader(Rect rect)
{
float xMax = rect.xMax;
rect.xMax = rect.xMax / 2.0f;
GUI.Label(rect, "Original Sprite", EditorStyles.label);
rect.xMin = rect.xMax;
rect.xMax = xMax;
GUI.Label(rect, "Override Sprite", EditorStyles.label);
}
/// <summary>
/// Draws the header for the GameObject list
/// </summary>
/// <param name="rect">GUI Rect to draw the header at</param>
public void DrawGameObjectListHeader(Rect rect)
{
float xMax = rect.xMax;
rect.xMax = rect.xMax / 2.0f;
GUI.Label(rect, "Original GameObject", EditorStyles.label);
rect.xMin = rect.xMax;
rect.xMax = xMax;
GUI.Label(rect, "Override GameObject", EditorStyles.label);
}
/// <summary>
/// Gets the GUI element height for a Sprite element with the given index
/// </summary>
/// <param name="index">Index of the Sprite element</param>
/// <returns>GUI element height for the Sprite element</returns>
public float GetSpriteElementHeight(int index)
{
float height = k_SpriteElementHeight + k_PaddingBetweenRules;
bool isMissing = index >= m_MissingOriginalSpriteIndex;
if (isMissing)
height += 16;
return height;
}
/// <summary>
/// Gets the GUI element height for a GameObject element with the given index
/// </summary>
/// <param name="index">Index of the GameObject element</param>
/// <returns>GUI element height for the GameObject element</returns>
public float GetGameObjectElementHeight(int index)
{
float height = k_GameObjectElementHeight + k_PaddingBetweenRules;
bool isMissing = index >= m_MissingOriginalGameObjectIndex;
if (isMissing)
height += 16;
return height;
}
/// <summary>
/// Draws the Sprite element for the RuleOverride list
/// </summary>
/// <param name="rect">Rect to draw the Sprite Element in</param>
/// <param name="index">Index of the Sprite Element to draw</param>
/// <param name="active">Whether the Sprite Element is active</param>
/// <param name="focused">Whether the Sprite Element is focused</param>
public void DrawSpriteElement(Rect rect, int index, bool active, bool focused)
{
bool isMissing = index >= m_MissingOriginalSpriteIndex;
if (isMissing)
{
EditorGUI.HelpBox(new Rect(rect.xMin, rect.yMin, rect.width, 16), "Original Sprite missing", MessageType.Warning);
rect.yMin += 16;
}
Sprite originalSprite = m_Sprites[index].Key;
Sprite overrideSprite = m_Sprites[index].Value;
rect.y += 2;
rect.height -= k_PaddingBetweenRules;
rect.xMax = rect.xMax / 2.0f;
using (new EditorGUI.DisabledScope(true))
EditorGUI.ObjectField(new Rect(rect.xMin, rect.yMin, rect.height, rect.height), originalSprite, typeof(Sprite), false);
rect.xMin = rect.xMax;
rect.xMax *= 2.0f;
EditorGUI.BeginChangeCheck();
overrideSprite = EditorGUI.ObjectField(new Rect(rect.xMin, rect.yMin, rect.height, rect.height), overrideSprite, typeof(Sprite), false) as Sprite;
if (EditorGUI.EndChangeCheck())
m_Sprites[index] = new KeyValuePair<Sprite, Sprite>(originalSprite, overrideSprite);
}
/// <summary>
/// Draws the GameObject element for the RuleOverride list
/// </summary>
/// <param name="rect">Rect to draw the GameObject Element in</param>
/// <param name="index">Index of the GameObject Element to draw</param>
/// <param name="active">Whether the GameObject Element is active</param>
/// <param name="focused">Whether the GameObject Element is focused</param>
public void DrawGameObjectElement(Rect rect, int index, bool active, bool focused)
{
bool isMissing = index >= m_MissingOriginalGameObjectIndex;
if (isMissing)
{
EditorGUI.HelpBox(new Rect(rect.xMin, rect.yMin, rect.width, 16), "Original GameObject missing", MessageType.Warning);
rect.yMin += 16;
}
GameObject originalGameObject = m_GameObjects[index].Key;
GameObject overrideGameObject = m_GameObjects[index].Value;
rect.y += 2;
rect.height -= k_PaddingBetweenRules;
rect.xMax = rect.xMax / 2.0f;
using (new EditorGUI.DisabledScope(true))
EditorGUI.ObjectField(new Rect(rect.xMin, rect.yMin, rect.width, rect.height), originalGameObject, typeof(GameObject), false);
rect.xMin = rect.xMax;
rect.xMax *= 2.0f;
EditorGUI.BeginChangeCheck();
overrideGameObject = EditorGUI.ObjectField(new Rect(rect.xMin, rect.yMin, rect.width, rect.height), overrideGameObject, typeof(GameObject), false) as GameObject;
if (EditorGUI.EndChangeCheck())
m_GameObjects[index] = new KeyValuePair<GameObject, GameObject>(originalGameObject, overrideGameObject);
}
/// <summary>
/// Draws a field for the RuleTile be overridden
/// </summary>
public void DrawTileField()
{
EditorGUI.BeginChangeCheck();
RuleTile tile = EditorGUILayout.ObjectField(Styles.overrideTile, overrideTile.m_Tile, typeof(RuleTile), false) as RuleTile;
if (EditorGUI.EndChangeCheck())
{
if (!LoopCheck(tile))
{
overrideTile.m_Tile = tile;
SaveTile();
}
else
{
Debug.LogWarning("Circular tile reference");
}
}
bool LoopCheck(RuleTile checkTile)
{
if (!overrideTile.m_InstanceTile)
return false;
HashSet<RuleTile> renferenceTils = new HashSet<RuleTile>();
Add(overrideTile.m_InstanceTile);
return renferenceTils.Contains(checkTile);
void Add(RuleTile ruleTile)
{
if (renferenceTils.Contains(ruleTile))
return;
renferenceTils.Add(ruleTile);
var overrideTiles = RuleTileEditor.FindAffectedOverrideTiles(ruleTile);
foreach (var overrideTile in overrideTiles)
Add(overrideTile.m_InstanceTile);
}
}
}
/// <summary>
/// Draw editor fields for custom properties for the RuleOverrideTile
/// </summary>
public void DrawCustomFields()
{
if (ruleTileEditor)
{
ruleTileEditor.target.hideFlags = HideFlags.None;
ruleTileEditor.DrawCustomFields(true);
ruleTileEditor.target.hideFlags = HideFlags.NotEditable;
}
}
private void SaveInstanceTileAsset()
{
bool assetChanged = false;
if (overrideTile.m_InstanceTile)
{
if (!overrideTile.m_Tile || overrideTile.m_InstanceTile.GetType() != overrideTile.m_Tile.GetType())
{
DestroyImmediate(overrideTile.m_InstanceTile, true);
overrideTile.m_InstanceTile = null;
assetChanged = true;
}
}
if (!overrideTile.m_InstanceTile)
{
if (overrideTile.m_Tile)
{
var t = overrideTile.m_Tile.GetType();
RuleTile instanceTile = ScriptableObject.CreateInstance(t) as RuleTile;
instanceTile.hideFlags = HideFlags.NotEditable;
AssetDatabase.AddObjectToAsset(instanceTile, overrideTile);
overrideTile.m_InstanceTile = instanceTile;
assetChanged = true;
}
}
if (overrideTile.m_InstanceTile)
{
string instanceTileName = overrideTile.m_Tile.name + " (Override)";
if (overrideTile.m_InstanceTile.name != instanceTileName)
{
overrideTile.m_InstanceTile.name = instanceTileName;
assetChanged = true;
}
}
if (assetChanged)
{
EditorUtility.SetDirty(overrideTile.m_InstanceTile);
#if UNITY_2021_1
AssetDatabase.SaveAssets();
#else
AssetDatabase.SaveAssetIfDirty(overrideTile.m_InstanceTile);
#endif
}
}
/// <summary>
/// Saves any changes to the RuleOverrideTile
/// </summary>
public void SaveTile()
{
EditorUtility.SetDirty(target);
SceneView.RepaintAll();
SaveInstanceTileAsset();
if (overrideTile.m_InstanceTile)
{
overrideTile.Override();
RuleTileEditor.UpdateAffectedOverrideTiles(overrideTile.m_InstanceTile);
}
if (ruleTileEditor && ruleTileEditor.m_PreviewTilemaps != null)
{
foreach (var tilemap in ruleTileEditor.m_PreviewTilemaps)
tilemap.RefreshAllTiles();
}
}
/// <summary>
/// Renders a static preview Texture2D for a RuleOverrideTile asset
/// </summary>
/// <param name="assetPath">Asset path of the RuleOverrideTile</param>
/// <param name="subAssets">Arrays of assets from the given Asset path</param>
/// <param name="width">Width of the static preview</param>
/// <param name="height">Height of the static preview </param>
/// <returns>Texture2D containing static preview for the RuleOverrideTile asset</returns>
public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height)
{
if (ruleTileEditor)
return ruleTileEditor.RenderStaticPreview(assetPath, subAssets, width, height);
return base.RenderStaticPreview(assetPath, subAssets, width, height);
}
/// <summary>
/// Whether the RuleOverrideTile has a preview GUI
/// </summary>
/// <returns>True if RuleOverrideTile has a preview GUI. False if not.</returns>
public override bool HasPreviewGUI()
{
if (ruleTileEditor)
return ruleTileEditor.HasPreviewGUI();
return false;
}
/// <summary>
/// Updates preview settings for the RuleOverrideTile.
/// </summary>
public override void OnPreviewSettings()
{
if (ruleTileEditor)
ruleTileEditor.OnPreviewSettings();
}
/// <summary>
/// Draws the preview GUI for the RuleTile
/// </summary>
/// <param name="rect">Rect to draw the preview GUI</param>
/// <param name="background">The GUIStyle of the background for the preview</param>
public override void OnPreviewGUI(Rect rect, GUIStyle background)
{
if (ruleTileEditor)
ruleTileEditor.OnPreviewGUI(rect, background);
}
}
}