TigerProject/Assets/Test/NavMeshComponents/Editor/NavMeshModifierTilemapEditor.cs

199 lines
7.9 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.Tilemaps;
//***********************************************************************************
// Contributed by author jl-randazzo github.com/jl-randazzo
//***********************************************************************************
namespace NavMeshPlus.Components.Editors
{
[CanEditMultipleObjects]
[CustomEditor(typeof(NavMeshModifierTilemap))]
class NavMeshModifierTilemapEditor : Editor
{
SerializedProperty m_AffectedAgents;
SerializedProperty m_TileModifiers;
void OnEnable()
{
m_AffectedAgents = serializedObject.FindProperty("m_AffectedAgents");
m_TileModifiers = serializedObject.FindProperty("m_TileModifiers");
}
public override void OnInspectorGUI()
{
NavMeshModifierTilemap modifierTilemap = target as NavMeshModifierTilemap;
serializedObject.Update();
NavMeshComponentsGUIUtility.AgentMaskPopup("Affected Agents", m_AffectedAgents);
EditorGUILayout.PropertyField(m_TileModifiers);
if (modifierTilemap.HasDuplicateTileModifiers())
{
EditorGUILayout.HelpBox("There are duplicate Tile entries in the tilemap modifiers! Only the first will be used.", MessageType.Warning);
}
EditorGUILayout.Space();
Tilemap tilemap = modifierTilemap.GetComponent<Tilemap>();
if (tilemap)
{
if (GUILayout.Button("Add Used Tiles"))
{
AddUsedTiles(tilemap, modifierTilemap);
}
}
else
{
EditorGUILayout.HelpBox("Missing required component 'Tilemap'", MessageType.Error);
}
if (serializedObject.ApplyModifiedProperties())
{
modifierTilemap.CacheModifiers();
}
}
private void AddUsedTiles(Tilemap tilemap, NavMeshModifierTilemap modifierTilemap)
{
Dictionary<TileBase, NavMeshModifierTilemap.TileModifier> tileModifiers = modifierTilemap.GetModifierMap();
BoundsInt bounds = tilemap.cellBounds;
for (int i = bounds.xMin; i <= bounds.xMax; i++)
{
for (int j = bounds.yMin; j <= bounds.yMax; j++)
{
for (int k = bounds.zMin; k <= bounds.zMax; k++)
{
if (tilemap.GetTile(new Vector3Int(i, j, k)) is TileBase tileBase)
{
if (!tileModifiers.ContainsKey(tileBase))
{
tileModifiers.Add(tileBase, new NavMeshModifierTilemap.TileModifier());
int idx = m_TileModifiers.arraySize;
m_TileModifiers.InsertArrayElementAtIndex(idx);
var newElem = m_TileModifiers.GetArrayElementAtIndex(idx);
var tileProperty = newElem.FindPropertyRelative(nameof(NavMeshModifierTilemap.TileModifier.tile));
tileProperty.objectReferenceValue = tileBase;
}
}
}
}
}
}
[CustomPropertyDrawer(typeof(NavMeshModifierTilemap.TileModifier))]
class TileModifierPropertyDrawer : PropertyDrawer
{
private static Dictionary<Object, Texture2D> Previews;
private Rect ClaimAdvance(ref Rect position, float height)
{
Rect retVal = position;
retVal.height = height;
position.y += height;
position.height -= height;
return retVal;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
Rect expandRect = ClaimAdvance(ref position, 20);
property.isExpanded = EditorGUI.Foldout(expandRect, property.isExpanded, label);
if (property.isExpanded)
{
var tileProperty = property.FindPropertyRelative(nameof(NavMeshModifierTilemap.TileModifier.tile));
Rect tileRect = ClaimAdvance(ref position, 40);
tileRect.width -= 40;
Rect previewRect = tileRect;
previewRect.width = 40;
previewRect.x += tileRect.width;
tileRect.height /= 2;
// Adding the tile selector and a preview image.
EditorGUI.PropertyField(tileRect, tileProperty);
TileBase tileBase = tileProperty.objectReferenceValue as TileBase;
TileData tileData = new TileData();
Texture textureToDraw;
try
{
tileBase?.GetTileData(Vector3Int.zero, null, ref tileData);
textureToDraw = tileData.sprite?.texture;
}
catch
{
try
{
textureToDraw = GetPreview(tileBase);
}
catch
{
textureToDraw = EditorGUIUtility.IconContent("console.erroricon.sml").image;
}
}
if (textureToDraw)
{
EditorGUI.DrawPreviewTexture(previewRect, textureToDraw, null, ScaleMode.ScaleToFit, 0);
}
Rect toggleRect = ClaimAdvance(ref position, 20);
var overrideAreaProperty = property.FindPropertyRelative(nameof(NavMeshModifierTilemap.TileModifier.overrideArea));
EditorGUI.PropertyField(toggleRect, overrideAreaProperty);
if (overrideAreaProperty.boolValue)
{
Rect areaRect = ClaimAdvance(ref position, 20);
var areaProperty = property.FindPropertyRelative(nameof(NavMeshModifierTilemap.TileModifier.area));
EditorGUI.indentLevel++;
EditorGUI.PropertyField(areaRect, areaProperty);
EditorGUI.indentLevel--;
}
}
}
static Texture2D GetPreview(Object objectToPreview)
{
int maxResolution = 128;
Previews ??= new Dictionary<Object, Texture2D>();
if (!Previews.TryGetValue(objectToPreview, out var preview) || preview == null)
{
var path = AssetDatabase.GetAssetPath(objectToPreview);
if (objectToPreview)
{
var editor = CreateEditor(objectToPreview);
preview = editor.RenderStaticPreview(path, null, maxResolution, maxResolution);
preview.Apply();
DestroyImmediate(editor);
Previews[objectToPreview] = preview;
}
}
return preview;
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (property.isExpanded)
{
var overrideAreaProperty = property.FindPropertyRelative(nameof(NavMeshModifierTilemap.TileModifier.overrideArea));
if (overrideAreaProperty.boolValue)
{
return 100;
}
return 80;
}
return 20;
}
}
}
}