/* --------------------------------------- * Author: Martin Pane (martintayx@gmail.com) (@tayx94) * Contributors: https://github.com/Tayx94/graphy/graphs/contributors * Project: Graphy - Ultimate Stats Monitor * Date: 02-Jan-18 * Studio: Tayx * * Git repo: https://github.com/Tayx94/graphy * * This project is released under the MIT license. * Attribution is not required, but it is always welcomed! * -------------------------------------*/ using System; using UnityEngine; using System.Collections.Generic; using System.IO; using UnityEditor; namespace Tayx.Graphy { [CustomEditor(typeof(GraphyDebugger))] internal class GraphyDebuggerEditor : Editor { /* ----- TODO: ---------------------------- * Add summaries to the variables. * Add summaries to the functions. * Finish spacing on "OnInspectorGUI". * Add sections to "OnInspectorGUI". * Fix the use of Space to be consistent with "GraphyManagerEditor". * --------------------------------------*/ #region Variables -> Private private GraphyDebugger m_target; private int m_newDebugPacketListSize = 0; private int m_previouslySelectedDebugPacketIndex = 0; private int m_currentlySelectedDebugPacketIndex = 0; private int m_selectedDebugPacketCondition = 0; #endregion #region Methods -> Unity Callbacks private void OnEnable() { m_target = (GraphyDebugger) target; } #endregion #region Methods -> Public Override public override void OnInspectorGUI() { if (m_target == null && target == null) { base.OnInspectorGUI(); return; } float defaultLabelWidth = EditorGUIUtility.labelWidth; float defaultFieldWidth = EditorGUIUtility.fieldWidth; //===== CONTENT REGION ======================================================================== GUILayout.Space(20); #region Section -> Logo if (GraphyEditorStyle.DebuggerLogoTexture != null) { GUILayout.Label ( image: GraphyEditorStyle.DebuggerLogoTexture, style: new GUIStyle(GUI.skin.GetStyle("Label")) { alignment = TextAnchor.UpperCenter } ); GUILayout.Space(10); } else { EditorGUILayout.LabelField ( label: "[ GRAPHY - DEBUGGER ]", style: GraphyEditorStyle.HeaderStyle1 ); } #endregion GUILayout.Space(5); //Extra pixels added when the logo is used. #region Section -> Settings SerializedObject serObj = serializedObject; SerializedProperty debugPacketList = serObj.FindProperty("m_debugPackets"); // Find the List in our script and create a refrence of it //Update our list serObj.Update(); EditorGUILayout.LabelField("Current [Debug Packets] list size: " + debugPacketList.arraySize); EditorGUIUtility.fieldWidth = 32; EditorGUILayout.BeginHorizontal(); m_newDebugPacketListSize = EditorGUILayout.IntField ( label: "Define a new list size", value: m_newDebugPacketListSize ); if (GUILayout.Button("Resize List")) { if (EditorUtility.DisplayDialog ( title: "Resize List", message: "Are you sure you want to resize the entire List?\n\n" + "Current List Size -> " + debugPacketList.arraySize + "\n" + "New List Size -> " + m_newDebugPacketListSize + "\n" + "This will add default entries if the value is greater than the list size, or erase the bottom values until the new size specified.", ok: "Resize", cancel: "Cancel") ) { m_currentlySelectedDebugPacketIndex = 0; if (m_newDebugPacketListSize != debugPacketList.arraySize) { while (m_newDebugPacketListSize > debugPacketList.arraySize) { debugPacketList.InsertArrayElementAtIndex(debugPacketList.arraySize); SetDefaultDebugPacketValues(debugPacketList); } while (m_newDebugPacketListSize < debugPacketList.arraySize) { debugPacketList.DeleteArrayElementAtIndex(debugPacketList.arraySize - 1); } } } } EditorGUILayout.EndHorizontal(); EditorGUILayout.LabelField("NOT RECOMMENDED (Only use for first initialization)", EditorStyles.centeredGreyMiniLabel); EditorGUILayout.Space(); EditorGUILayout.Space(); if (debugPacketList.arraySize < 1) { m_previouslySelectedDebugPacketIndex = 0; m_currentlySelectedDebugPacketIndex = 0; m_selectedDebugPacketCondition = 0; serializedObject.ApplyModifiedProperties(); return; } GraphyEditorStyle.HeaderStyle2.contentOffset = Vector2.down * 3f; EditorGUILayout.LabelField("Selected debug packet:"); EditorGUILayout.BeginHorizontal(); List debugPacketNames = new List(); for (int i = 0; i < debugPacketList.arraySize; i++) { SerializedProperty listItem = debugPacketList.GetArrayElementAtIndex(i); // NOTE: If the Popup detects two equal strings, it just paints 1, that's why I always add the "i" char checkMark = listItem.FindPropertyRelative("Active").boolValue ? '\u2714' : '\u2718'; debugPacketNames.Add ( (i + 1) + " (" + checkMark + ") " + " - ID: " + listItem.FindPropertyRelative("Id").intValue + " (Conditions: " + listItem.FindPropertyRelative("DebugConditions").arraySize + ")" ); } m_currentlySelectedDebugPacketIndex = EditorGUILayout.Popup(m_currentlySelectedDebugPacketIndex, debugPacketNames.ToArray()); if (m_currentlySelectedDebugPacketIndex != m_previouslySelectedDebugPacketIndex) { m_selectedDebugPacketCondition = 0; m_previouslySelectedDebugPacketIndex = m_currentlySelectedDebugPacketIndex; } Color defaultGUIColor = GUI.color; GUI.color = new Color(0.7f, 1f, 0.0f, 1f); //Or add a new item to the List<> with a button if (GUILayout.Button("Add", GUILayout.Width(60))) { debugPacketList.InsertArrayElementAtIndex(debugPacketList.arraySize); SetDefaultDebugPacketValues(debugPacketList); } GUI.color = new Color(1f, 0.7f, 0.0f, 1f); //Remove this index from the List if (GUILayout.Button("Remove", GUILayout.Width(60))) { debugPacketList.DeleteArrayElementAtIndex(m_currentlySelectedDebugPacketIndex); if (m_currentlySelectedDebugPacketIndex > 0) { m_currentlySelectedDebugPacketIndex--; } if (debugPacketList.arraySize < 1) { serializedObject.ApplyModifiedProperties(); return; } } GUI.color = defaultGUIColor; EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUILayout.Space(); EditorGUILayout.Space(); //Display our list to the inspector window SerializedProperty listItemSelected = debugPacketList.GetArrayElementAtIndex(m_currentlySelectedDebugPacketIndex); SerializedProperty Active = listItemSelected.FindPropertyRelative("Active"); SerializedProperty Id = listItemSelected.FindPropertyRelative("Id"); SerializedProperty ExecuteOnce = listItemSelected.FindPropertyRelative("ExecuteOnce"); SerializedProperty InitSleepTime = listItemSelected.FindPropertyRelative("InitSleepTime"); SerializedProperty ExecuteSleepTime = listItemSelected.FindPropertyRelative("ExecuteSleepTime"); SerializedProperty ConditionEvaluation = listItemSelected.FindPropertyRelative("ConditionEvaluation"); SerializedProperty DebugConditions = listItemSelected.FindPropertyRelative("DebugConditions"); SerializedProperty MessageType = listItemSelected.FindPropertyRelative("MessageType"); SerializedProperty Message = listItemSelected.FindPropertyRelative("Message"); SerializedProperty TakeScreenshot = listItemSelected.FindPropertyRelative("TakeScreenshot"); SerializedProperty ScreenshotFileName = listItemSelected.FindPropertyRelative("ScreenshotFileName"); SerializedProperty DebugBreak = listItemSelected.FindPropertyRelative("DebugBreak"); SerializedProperty UnityEvents = listItemSelected.FindPropertyRelative("UnityEvents"); #endregion EditorGUILayout.LabelField ( label: "[ PACKET ] - ID: " + Id.intValue + " (Conditions: " + DebugConditions.arraySize + ")", style: GraphyEditorStyle.HeaderStyle2 ); EditorGUIUtility.labelWidth = 150; EditorGUIUtility.fieldWidth = 35; Active.boolValue = EditorGUILayout.Toggle ( new GUIContent ( text: "Active", tooltip: "If false, it will not be checked" ), value: Active.boolValue ); Id.intValue = EditorGUILayout.IntField ( new GUIContent ( text: "ID", tooltip: "Optional Id. It's used to get or remove DebugPackets in runtime" ), value: Id.intValue ); ExecuteOnce.boolValue = EditorGUILayout.Toggle ( new GUIContent ( text: "Execute once", tooltip: "If true, once the actions are executed, this DebugPacket will delete itself" ), value: ExecuteOnce.boolValue ); InitSleepTime.floatValue = EditorGUILayout.FloatField ( new GUIContent ( text: "Init sleep time", tooltip: "Time to wait before checking if conditions are met (use this to avoid low fps drops triggering the conditions when loading the game)" ), value: InitSleepTime.floatValue ); ExecuteSleepTime.floatValue = EditorGUILayout.FloatField ( new GUIContent ( text: "Sleep time after execute", tooltip: "Time to wait before checking if conditions are met again (once they have already been met and if ExecuteOnce is false)" ), value: ExecuteSleepTime.floatValue ); EditorGUIUtility.labelWidth = defaultLabelWidth; EditorGUIUtility.fieldWidth = defaultFieldWidth; EditorGUILayout.Space(); EditorGUILayout.Space(); EditorGUILayout.LabelField("[ CONDITIONS ] (" + DebugConditions.arraySize + ")", GraphyEditorStyle.HeaderStyle2); EditorGUILayout.PropertyField ( ConditionEvaluation, new GUIContent("Condition evaluation") ); EditorGUILayout.Space(); if (DebugConditions.arraySize < 1) { DebugConditions.InsertArrayElementAtIndex(DebugConditions.arraySize); m_selectedDebugPacketCondition = 0; } EditorGUILayout.BeginHorizontal(); List debugPacketConditionNames = new List(); for (int i = 0; i < DebugConditions.arraySize; i++) { SerializedProperty listItem = DebugConditions.GetArrayElementAtIndex(i); // NOTE: If the Popup detects two equal strings, it just paints 1, that's why I always add the "i" string conditionName = (i + 1).ToString() + " - "; conditionName += GetComparerStringFromDebugVariable((GraphyDebugger.DebugVariable)listItem.FindPropertyRelative("Variable").intValue) + " "; conditionName += GetComparerStringFromDebugComparer((GraphyDebugger.DebugComparer)listItem.FindPropertyRelative("Comparer").intValue) + " "; conditionName += listItem.FindPropertyRelative("Value").floatValue.ToString(); debugPacketConditionNames.Add(conditionName); } m_selectedDebugPacketCondition = EditorGUILayout.Popup(m_selectedDebugPacketCondition, debugPacketConditionNames.ToArray()); GUI.color = new Color(0.7f, 1f, 0.0f, 1f); if (GUILayout.Button("Add", GUILayout.Width(60))) { DebugConditions.InsertArrayElementAtIndex(DebugConditions.arraySize); } if (DebugConditions.arraySize > 1) { GUI.color = new Color(1f, 0.7f, 0.0f, 1f); } else { GUI.color = new Color(1f, 0.7f, 0.0f, 0.5f); } //Remove this index from the List if (GUILayout.Button("Remove", GUILayout.Width(60))) { if (DebugConditions.arraySize > 1) { DebugConditions.DeleteArrayElementAtIndex(m_selectedDebugPacketCondition); if (m_selectedDebugPacketCondition > 0) { m_selectedDebugPacketCondition--; } } } GUI.color = defaultGUIColor; EditorGUILayout.EndHorizontal(); SerializedProperty conditionListItemSelected = DebugConditions.GetArrayElementAtIndex(m_selectedDebugPacketCondition); SerializedProperty Variable = conditionListItemSelected.FindPropertyRelative("Variable"); SerializedProperty Comparer = conditionListItemSelected.FindPropertyRelative("Comparer"); SerializedProperty Value = conditionListItemSelected.FindPropertyRelative("Value"); EditorGUILayout.PropertyField ( Variable, new GUIContent("Variable") ); EditorGUILayout.PropertyField ( Comparer, new GUIContent("Comparer") ); EditorGUILayout.PropertyField ( Value, new GUIContent("Value") ); EditorGUILayout.Space(); EditorGUILayout.Space(); EditorGUILayout.LabelField("[ ACTIONS ]", GraphyEditorStyle.HeaderStyle2); EditorGUIUtility.labelWidth = 140; EditorGUIUtility.fieldWidth = 35; EditorGUILayout.PropertyField ( MessageType, new GUIContent("Message type") ); EditorGUILayout.PropertyField(Message); TakeScreenshot.boolValue = EditorGUILayout.Toggle ( new GUIContent ( text: "Take screenshot", tooltip: "If true, it takes a screenshot and stores it. The location where the image is written to can include a directory/folder list. With no directory/folder list the image will be written into the Project folder. On mobile platforms the filename is appended to the persistent data path." ), value: TakeScreenshot.boolValue ); if (TakeScreenshot.boolValue) { EditorGUILayout.PropertyField ( ScreenshotFileName, new GUIContent ( text: "Screenshot file name", tooltip: "Avoid this characters: * . \" / \\ [ ] : ; | = , \n\nIt will have the date appended at the end to avoid overwriting." ) ); } DebugBreak.boolValue = EditorGUILayout.Toggle ( new GUIContent ( text: "Debug Break", tooltip: "If true, it pauses the editor" ), DebugBreak.boolValue ); EditorGUILayout.PropertyField(UnityEvents); EditorGUIUtility.labelWidth = defaultLabelWidth; EditorGUIUtility.fieldWidth = defaultFieldWidth; serializedObject.ApplyModifiedProperties(); } #endregion #region Methods -> Private private void SetDefaultDebugPacketValues(SerializedProperty debugPacketSerializedProperty) { GraphyDebugger.DebugPacket debugPacket = new GraphyDebugger.DebugPacket(); debugPacketSerializedProperty.GetArrayElementAtIndex(debugPacketSerializedProperty.arraySize - 1) .FindPropertyRelative("Active") .boolValue = debugPacket.Active; debugPacketSerializedProperty.GetArrayElementAtIndex(debugPacketSerializedProperty.arraySize - 1) .FindPropertyRelative("Id") .intValue = debugPacketSerializedProperty.arraySize; debugPacketSerializedProperty.GetArrayElementAtIndex(debugPacketSerializedProperty.arraySize - 1) .FindPropertyRelative("ExecuteOnce") .boolValue = debugPacket.ExecuteOnce; debugPacketSerializedProperty.GetArrayElementAtIndex(debugPacketSerializedProperty.arraySize - 1) .FindPropertyRelative("InitSleepTime") .floatValue = debugPacket.InitSleepTime; debugPacketSerializedProperty.GetArrayElementAtIndex(debugPacketSerializedProperty.arraySize - 1) .FindPropertyRelative("ExecuteSleepTime") .floatValue = debugPacket.ExecuteSleepTime; } private string GetComparerStringFromDebugVariable(GraphyDebugger.DebugVariable debugVariable) { switch (debugVariable) { case GraphyDebugger.DebugVariable.Fps: return "FPS Current"; case GraphyDebugger.DebugVariable.Fps_Min: return "FPS Min"; case GraphyDebugger.DebugVariable.Fps_Max: return "FPS Max"; case GraphyDebugger.DebugVariable.Fps_Avg: return "FPS Avg"; case GraphyDebugger.DebugVariable.Ram_Allocated: return "Ram Allocated"; case GraphyDebugger.DebugVariable.Ram_Reserved: return "Ram Reserved"; case GraphyDebugger.DebugVariable.Ram_Mono: return "Ram Mono"; case GraphyDebugger.DebugVariable.Audio_DB: return "Audio DB"; default: return null; } } private string GetComparerStringFromDebugComparer(GraphyDebugger.DebugComparer debugComparer) { switch (debugComparer) { case GraphyDebugger.DebugComparer.Less_than: return "<"; case GraphyDebugger.DebugComparer.Equals_or_less_than: return "<="; case GraphyDebugger.DebugComparer.Equals: return "=="; case GraphyDebugger.DebugComparer.Equals_or_greater_than: return ">="; case GraphyDebugger.DebugComparer.Greater_than: return ">"; default: return null; } } #endregion } }