2024-06-23 19:12:22 +01:00

211 lines
8.8 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.Linq;
using System.Reflection;
using MBT;
namespace MBTEditor
{
[CustomEditor(typeof(Blackboard))]
public class BlackboardEditor : Editor
{
const double CONSTANT_REPAINT_INTERVAL = 0.5d;
readonly string[] varOptions = new string[]{"Delete"};
SerializedProperty variables;
SerializedProperty masterBlackboardProperty;
GUIStyle popupStyle;
string newVariableKey = "";
string[] variableTypesNames = new string[0];
Type[] variableTypes = new Type[0];
int selectedVariableType = 0;
Blackboard blackboard;
GameObject blackboardGameObject;
bool showVariables = true;
private double lastRepaint;
void OnEnable()
{
// Set hide flags in case object was duplicated or turned into prefab
if (target != null)
{
Blackboard bb = (Blackboard) target;
// Sample one variable and check if its hidden. Hide all varialbes if sample is visible.
if (bb.TryGetComponent<BlackboardVariable>(out BlackboardVariable bv) && bv.hideFlags != HideFlags.HideInInspector)
{
BlackboardVariable[] vars = bb.GetComponents<BlackboardVariable>();
for (int i = 0; i < vars.Length; i++)
{
vars[i].hideFlags = HideFlags.HideInInspector;
}
}
}
// Init
variables = serializedObject.FindProperty("variables");
masterBlackboardProperty = serializedObject.FindProperty("masterBlackboard");
blackboard = target as Blackboard;
blackboardGameObject = blackboard.gameObject;
SetupVariableTypes();
}
void OnDestroy()
{
// Remove all variables in case Blackboard was removed
if (Application.isEditor && (Blackboard)target == null && blackboardGameObject != null)
{
// Additional check to avoid errors when exiting playmode
if (Application.IsPlaying(blackboardGameObject) || blackboardGameObject.GetComponent<Blackboard>() != null)
{
return;
}
BlackboardVariable[] blackboardVariables = blackboardGameObject.GetComponents<BlackboardVariable>();
for (int i = 0; i < blackboardVariables.Length; i++)
{
Undo.DestroyObjectImmediate(blackboardVariables[i]);
}
}
}
public override bool RequiresConstantRepaint()
{
return Application.isPlaying && EditorApplication.timeSinceStartup > lastRepaint + CONSTANT_REPAINT_INTERVAL;
}
private void SetupVariableTypes()
{
List<Type> types = new List<Type>();
List<string> names = new List<string>();
// Find all types
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
IEnumerable<Type> enumerable = assembly.GetTypes()
.Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(BlackboardVariable)));
foreach (Type type in enumerable)
{
names.Add(type.Name);
types.Add(type);
}
}
variableTypesNames = names.ToArray();
variableTypes = types.ToArray();
}
public override void OnInspectorGUI()
{
// Update repaint timer
lastRepaint = EditorApplication.timeSinceStartup;
// Init styles
if (popupStyle == null) {
popupStyle = new GUIStyle(GUI.skin.GetStyle("PaneOptions"));
popupStyle.imagePosition = ImagePosition.ImageOnly;
popupStyle.margin.top += 3;
}
EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(masterBlackboardProperty);
EditorGUILayout.Space();
if (EditorGUI.EndChangeCheck()) {
serializedObject.ApplyModifiedProperties();
}
// Fields used to add variables
EditorGUILayout.LabelField("Create Variable", EditorStyles.boldLabel);
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
GUILayout.Label("Key", GUILayout.MaxWidth(80));
newVariableKey = EditorGUILayout.TextField(newVariableKey);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
GUILayout.Label("Type", GUILayout.MaxWidth(80));
selectedVariableType = EditorGUILayout.Popup(selectedVariableType, variableTypesNames);
GUI.SetNextControlName("AddButton");
if (GUILayout.Button("Add", EditorStyles.miniButton)) {
CreateVariableAndResetInput();
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
// DrawDefaultInspector();
// EditorGUILayout.Space();
// serializedObject.Update();
// EditorGUI.BeginChangeCheck();
showVariables = EditorGUILayout.BeginFoldoutHeaderGroup(showVariables, "Variables");
if(showVariables){
SerializedProperty vars = variables.Copy();
if (vars.isArray) {
// xxx: Why this line existed? Why EventType.DragPerform is not allowed here? (maybe BeginChangeCheck)
// if (vars.isArray && Event.current.type != EventType.DragPerform) {
for (int i = 0; i < vars.arraySize; i++)
{
EditorGUI.BeginChangeCheck();
int popupOption = -1;
SerializedProperty serializedV = vars.GetArrayElementAtIndex(i);
SerializedObject serializedVariable = new SerializedObject(serializedV.objectReferenceValue);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(
new GUIContent(serializedVariable.FindProperty("key").stringValue,
serializedVariable.targetObject.GetType().Name)
);
int v = EditorGUILayout.Popup(popupOption, varOptions, popupStyle, GUILayout.MaxWidth(20));
EditorGUILayout.PropertyField(serializedVariable.FindProperty("val"), GUIContent.none);
EditorGUILayout.EndHorizontal();
if (EditorGUI.EndChangeCheck()) {
serializedVariable.ApplyModifiedProperties();
}
// Delete on change
if (v != popupOption) {
DeleteVariabe(serializedV.objectReferenceValue as BlackboardVariable);
}
}
}
}
EditorGUILayout.EndFoldoutHeaderGroup();
EditorGUILayout.Space();
// if (EditorGUI.EndChangeCheck()) {
// serializedObject.ApplyModifiedProperties();
// }
}
private void DeleteVariabe(BlackboardVariable blackboardVariable)
{
Undo.RecordObject(blackboard, "Delete Blackboard Variable");
blackboard.variables.Remove(blackboardVariable);
Undo.DestroyObjectImmediate(blackboardVariable);
}
private void CreateVariableAndResetInput()
{
// Validate field. Key "None" is not allowed.
if (string.IsNullOrEmpty(newVariableKey) || newVariableKey.Equals("None")) {
return;
}
string k = new string( newVariableKey.ToCharArray().Where(c => !Char.IsWhiteSpace(c)).ToArray() );
// Check for key duplicates
for (int i = 0; i < blackboard.variables.Count; i++)
{
if (blackboard.variables[i].key == k) {
Debug.LogWarning("Variable '"+k+"' already exists.");
return;
}
}
// Add variable
Undo.RecordObject(blackboard, "Create Blackboard Variable");
BlackboardVariable var = Undo.AddComponent(blackboard.gameObject, variableTypes[selectedVariableType]) as BlackboardVariable;
var.hideFlags = HideFlags.HideInInspector;
var.key = k;
blackboard.variables.Add(var);
// Reset field
newVariableKey = "";
GUI.FocusControl("Clear");
}
}
}