// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus). // It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE) using UnityEditor; using UnityEditorInternal; using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEditor.Callbacks; namespace Fungus { [CustomEditor (typeof(LuaBindings))] public class LuaBindingsEditor : Editor { protected ReorderableList boundObjectsList; protected SerializedProperty allLuaEnvironmentsProp; protected SerializedProperty luaEnvironmentProp; protected SerializedProperty tableNameProp; protected SerializedProperty registerTypesProp; protected SerializedProperty boundObjectsProp; protected SerializedProperty showInheritedProp; protected string bindingHelpItem = ""; protected string bindingHelpDetail = ""; protected virtual void OnEnable() { allLuaEnvironmentsProp = serializedObject.FindProperty("allEnvironments"); luaEnvironmentProp = serializedObject.FindProperty("luaEnvironment"); tableNameProp = serializedObject.FindProperty("tableName"); registerTypesProp = serializedObject.FindProperty("registerTypes"); boundObjectsProp = serializedObject.FindProperty("boundObjects"); showInheritedProp = serializedObject.FindProperty("showInherited"); CreateBoundObjectsList(); } protected void CreateBoundObjectsList() { boundObjectsList = new ReorderableList(serializedObject, boundObjectsProp, true, true, true, true); boundObjectsList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => { var element = boundObjectsList.serializedProperty.GetArrayElementAtIndex(index); rect.y += 2; float widthA = rect.width * 0.25f; float widthB = rect.width * 0.75f * 0.5f; float widthC = rect.width * 0.75f * 0.5f; SerializedProperty keyProp = element.FindPropertyRelative("key"); SerializedProperty objectProp = element.FindPropertyRelative("obj"); EditorGUI.BeginChangeCheck(); EditorGUI.PropertyField( new Rect(rect.x, rect.y, widthA - 5, EditorGUIUtility.singleLineHeight), keyProp, GUIContent.none); if (EditorGUI.EndChangeCheck()) { // Force the key to be a valid Lua variable name LuaBindings luaBindings = target as LuaBindings; keyProp.stringValue = GetUniqueKey(luaBindings, keyProp.stringValue, index); } EditorGUI.BeginChangeCheck(); EditorGUI.PropertyField( new Rect(rect.x + widthA, rect.y, widthB - 5, EditorGUIUtility.singleLineHeight), objectProp, GUIContent.none); if (EditorGUI.EndChangeCheck()) { // Use the object name as the key string keyName = objectProp.objectReferenceValue.name; LuaBindings luaBindings = target as LuaBindings; element.FindPropertyRelative("key").stringValue = GetUniqueKey(luaBindings, keyName.ToLower(), index); // Auto select any Flowchart component in the object GameObject go = objectProp.objectReferenceValue as GameObject; if (go != null) { Component flowchart = go.GetComponent("Fungus.Flowchart"); if (flowchart != null) { SerializedProperty componentProp = element.FindPropertyRelative("component"); componentProp.objectReferenceValue = flowchart; } } } if (objectProp.objectReferenceValue != null) { GameObject go = objectProp.objectReferenceValue as GameObject; if (go != null) { SerializedProperty componentProp = element.FindPropertyRelative("component"); int selected = 0; List options = new List(); options.Add(""); int count = 1; Component[] componentList = go.GetComponents(); foreach (Component component in componentList) { if (componentProp.objectReferenceValue == component) { selected = count; } if (component == null || component.GetType() == null) { // Missing script? continue; } string componentName = component.GetType().ToString().Replace("UnityEngine.", ""); options.Add(componentName); count++; } int i = EditorGUI.Popup( new Rect(rect.x + widthA + widthB, rect.y, widthC, EditorGUIUtility.singleLineHeight), selected, options.ToArray()); if (i == 0) { componentProp.objectReferenceValue = null; } else { componentProp.objectReferenceValue = componentList[i - 1]; } } } boundObjectsList.onAddCallback = (ReorderableList l) => { // Add a new item. This copies last item in the list, so clear new items values. boundObjectsProp.InsertArrayElementAtIndex(boundObjectsProp.arraySize); SerializedProperty newItem = boundObjectsProp.GetArrayElementAtIndex(boundObjectsProp.arraySize - 1); newItem.FindPropertyRelative("key").stringValue = ""; newItem.FindPropertyRelative("obj").objectReferenceValue = null; newItem.FindPropertyRelative("component").objectReferenceValue = null; }; }; boundObjectsList.drawHeaderCallback = (Rect rect) => { float widthA = rect.width * 0.25f; float widthB = rect.width * 0.75f * 0.5f; float widthC = rect.width * 0.75f * 0.5f; EditorGUI.LabelField(new Rect(rect.x+ 12, rect.y, widthA, EditorGUIUtility.singleLineHeight), "Key"); EditorGUI.LabelField(new Rect(rect.x + widthA + 12, rect.y, widthB, EditorGUIUtility.singleLineHeight), "Object"); EditorGUI.LabelField(new Rect(rect.x + widthA + widthB + 6, rect.y, widthC, EditorGUIUtility.singleLineHeight), "Component"); }; } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.PropertyField(allLuaEnvironmentsProp); if (!allLuaEnvironmentsProp.boolValue) { EditorGUILayout.PropertyField(luaEnvironmentProp); } EditorGUILayout.PropertyField(tableNameProp); EditorGUILayout.PropertyField(registerTypesProp); EditorGUILayout.LabelField("Object Bindings"); boundObjectsList.DoLayoutList(); EditorGUILayout.Space(); ShowBindingMemberInfo(); // Update the bound types on every tick to make sure they're up to date. // This could be a bit heavy on performance if the bound object list is long, but // I couldn't get it to work reliably by only updating when the list has changed. // This only happens when inspecting a Fungus Bindings component so I think it'll be ok. PopulateBoundTypes(target as LuaBindings, serializedObject); serializedObject.ApplyModifiedProperties(); } protected virtual void ShowBindingMemberInfo() { List items = new List(); items.Add("