Search Unity

How can I give a title to each Conversation with a number ?

Discussion in 'Scripting' started by DubiDuboni, Jul 12, 2019.

  1. DubiDuboni

    DubiDuboni

    Joined:
    Feb 5, 2019
    Posts:
    131
    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEditor;
    5. using UnityEditorInternal;
    6. using UnityEngine;
    7.  
    8. [CustomEditor(typeof(ConversationTrigger))]
    9. public class ConversationTriggerEditor : Editor
    10. {
    11.     private ConversationTrigger _conversationTrigger;
    12.  
    13.     [SerializeField] private ReorderableList conversationsList;
    14.  
    15.     private SerializedProperty _conversations;
    16.  
    17.     private int _currentlySelectedConversationIndex = -1;
    18.     private int newSize = 0;
    19.     private Vector2 scrollPos;
    20.     private SerializedProperty conversationsCounter;
    21.  
    22.     private readonly Dictionary<string, ReorderableList> _dialoguesListDict = new Dictionary<string, ReorderableList>();
    23.     private readonly Dictionary<string, ReorderableList> _sentencesListDict = new Dictionary<string, ReorderableList>();
    24.  
    25.     private void OnEnable()
    26.     {
    27.         _conversationTrigger = (ConversationTrigger)target;
    28.         _conversations = serializedObject.FindProperty("conversations");
    29.  
    30.         conversationsList = new ReorderableList(serializedObject, _conversations)
    31.         {
    32.             displayAdd = true,
    33.             displayRemove = true,
    34.             draggable = true,
    35.            
    36.             drawHeaderCallback = DrawConversationsHeader,
    37.  
    38.             drawElementCallback = DrawConversationsElement,
    39.  
    40.             onAddCallback = (list) =>
    41.             {
    42.                 SerializedProperty addedElement;
    43.                 // if something is selected add after that element otherwise on the end
    44.                 if (_currentlySelectedConversationIndex >= 0)
    45.                 {
    46.                     list.serializedProperty.InsertArrayElementAtIndex(_currentlySelectedConversationIndex + 1);
    47.                     addedElement = list.serializedProperty.GetArrayElementAtIndex(_currentlySelectedConversationIndex + 1);
    48.                 }
    49.                 else
    50.                 {
    51.                     list.serializedProperty.arraySize++;
    52.                     addedElement = list.serializedProperty.GetArrayElementAtIndex(list.serializedProperty.arraySize - 1);
    53.                 }
    54.  
    55.                 var name = addedElement.FindPropertyRelative("Name");
    56.                 var foldout = addedElement.FindPropertyRelative("Foldout");
    57.                 var dialogues = addedElement.FindPropertyRelative("Dialogues");
    58.  
    59.                 name.stringValue = "";
    60.                 foldout.boolValue = false;
    61.                 dialogues.arraySize = 0;
    62.  
    63.                 conversationsCounter = addedElement.FindPropertyRelative("ConversationIndex");
    64.             },
    65.            
    66.             elementHeightCallback = (index) =>
    67.             {
    68.                 return GetConversationHeight(_conversations.GetArrayElementAtIndex(index));
    69.             }
    70.         };
    71.     }
    72.  
    73.     public override void OnInspectorGUI()
    74.     {
    75.         serializedObject.Update();
    76.  
    77.         // if there are no elements reset _currentlySelectedConversationIndex
    78.         if (conversationsList.serializedProperty.arraySize - 1 < _currentlySelectedConversationIndex) _currentlySelectedConversationIndex = -1;
    79.  
    80.         EditorGUILayout.LabelField("Conversations", EditorStyles.boldLabel);
    81.         EditorGUI.BeginChangeCheck();
    82.         {
    83.             newSize = EditorGUILayout.IntField(_conversations.arraySize);
    84.         }
    85.         if (EditorGUI.EndChangeCheck())
    86.         {
    87.             if (newSize > _conversations.arraySize)
    88.             {
    89.                 conversationsCounter.intValue = newSize;
    90.                 // elements have to be added -> how many?
    91.                 var toAdd = newSize - _conversations.arraySize - 1;
    92.                 // why -1 ? -> We add the first element and set its values to default
    93.                 // now if we simply increase the arraySize for the rest of the elements
    94.                 // they will be all a copy of the first -> all defaults ;)
    95.  
    96.                 // first add one element
    97.                 _conversations.arraySize++;
    98.                 // then get that element
    99.                 var newIndex = _conversations.arraySize - 1;
    100.                 var newElement = _conversations.GetArrayElementAtIndex(newIndex);
    101.  
    102.                 // now reset all properties like
    103.                 var name = newElement.FindPropertyRelative("Name");
    104.                 name.stringValue = "";
    105.  
    106.                 // now for the rest simply increase arraySize
    107.                 _conversations.arraySize += toAdd;
    108.             }
    109.             else
    110.             {
    111.                 // for removing just make sure the arraySize is not under 0
    112.                 _conversations.arraySize = Mathf.Max(newSize, 0);
    113.             }
    114.         }
    115.  
    116.         scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.Height(250));
    117.  
    118.         GUILayout.Space(10);
    119.         conversationsList.DoLayoutList();
    120.  
    121.         EditorGUILayout.EndScrollView();
    122.  
    123.         if (GUILayout.Button("Save Conversations"))
    124.         {
    125.             _conversationTrigger.SaveConversations();
    126.         }
    127.  
    128.         if (GUILayout.Button("Load Conversations"))
    129.         {
    130.             Undo.RecordObject(_conversationTrigger, "Loaded conversations from JSON");
    131.             _conversationTrigger.LoadConversations();
    132.         }
    133.  
    134.         serializedObject.ApplyModifiedProperties();
    135.     }
    136.  
    137.     #region Drawers
    138.  
    139.     #region List Headers
    140.  
    141.     private void DrawConversationsHeader(Rect rect)
    142.     {
    143.         //EditorGUI.LabelField(rect, "Conversations");
    144.     }
    145.  
    146.     private void DrawDialoguesHeader(Rect rect)
    147.     {
    148.         EditorGUI.LabelField(rect, "Dialogues");
    149.     }
    150.  
    151.     private void DrawSentencesHeader(Rect rect)
    152.     {
    153.         EditorGUI.LabelField(rect, "Sentences");
    154.     }
    155.  
    156.     #endregion List Headers
    157.  
    158.     #region Elements
    159.  
    160.     private void DrawConversationsElement(Rect rect, int index, bool isActive, bool isFocused)
    161.     {
    162.         if (isActive) _currentlySelectedConversationIndex = index;
    163.  
    164.         var conversation = _conversations.GetArrayElementAtIndex(index);
    165.  
    166.         var position = new Rect(rect);
    167.  
    168.         var name = conversation.FindPropertyRelative("Name");
    169.         var foldout = conversation.FindPropertyRelative("Foldout");
    170.         var dialogues = conversation.FindPropertyRelative("Dialogues");
    171.         string dialoguesListKey = conversation.propertyPath;
    172.  
    173.         EditorGUI.indentLevel++;
    174.         {
    175.             // make the label be a foldout
    176.             //GUI.TextField(new Rect(position.x, position.y, 15, EditorGUIUtility.singleLineHeight), itemscounter.ToString());
    177.             foldout.boolValue = EditorGUI.Foldout(new Rect(position.x, position.y, 10, EditorGUIUtility.singleLineHeight), foldout.boolValue, foldout.boolValue ? "" : name.stringValue, true);
    178.  
    179.             if (foldout.boolValue)
    180.             {
    181.                 // draw the name field
    182.                 name.stringValue = EditorGUI.TextField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), name.stringValue);
    183.                 position.y += EditorGUIUtility.singleLineHeight;
    184.  
    185.                 if (!_dialoguesListDict.ContainsKey(dialoguesListKey))
    186.                 {
    187.                     // create reorderabl list and store it in dict
    188.                     var dialoguesList = new ReorderableList(conversation.serializedObject, dialogues)
    189.                     {
    190.                         displayAdd = true,
    191.                         displayRemove = true,
    192.                         draggable = true,
    193.                        
    194.                         drawHeaderCallback = DrawDialoguesHeader,
    195.                        
    196.                         drawElementCallback = (convRect, convIndex, convActive, convFocused) => { DrawDialoguesElement(_dialoguesListDict[dialoguesListKey], convRect, convIndex, convActive, convFocused); },
    197.  
    198.                         elementHeightCallback = (dialogIndex) =>
    199.                         {
    200.                             return GetDialogueHeight(_dialoguesListDict[dialoguesListKey].serializedProperty.GetArrayElementAtIndex(dialogIndex));
    201.                         },
    202.  
    203.                         onAddCallback = (list) =>
    204.                         {
    205.                             list.serializedProperty.arraySize++;
    206.                             var addedElement = list.serializedProperty.GetArrayElementAtIndex(list.serializedProperty.arraySize - 1);
    207.  
    208.                             var newDialoguesName = addedElement.FindPropertyRelative("Name");
    209.                             var newDialoguesFoldout = addedElement.FindPropertyRelative("Foldout");
    210.                             var sentences = addedElement.FindPropertyRelative("Sentences");
    211.  
    212.                             newDialoguesName.stringValue = "";
    213.                             newDialoguesFoldout.boolValue = true;
    214.                             sentences.arraySize = 0;
    215.                         }
    216.                     };
    217.                     _dialoguesListDict[dialoguesListKey] = dialoguesList;
    218.                 }
    219.  
    220.                 _dialoguesListDict[dialoguesListKey].DoList(new Rect(position.x, position.y, position.width, position.height - EditorGUIUtility.singleLineHeight));
    221.             }
    222.  
    223.         }
    224.         EditorGUI.indentLevel--;
    225.     }
    226.  
    227.     private void DrawDialoguesElement(ReorderableList list, Rect rect, int index, bool isActive, bool isFocused)
    228.     {
    229.         if (list == null) return;
    230.  
    231.         var dialog = list.serializedProperty.GetArrayElementAtIndex(index);
    232.  
    233.         var position = new Rect(rect);
    234.  
    235.         var foldout = dialog.FindPropertyRelative("Foldout");
    236.         var name = dialog.FindPropertyRelative("Name");
    237.  
    238.         {
    239.             // make the label be a foldout
    240.             foldout.boolValue = EditorGUI.Foldout(new Rect(position.x, position.y, 10, EditorGUIUtility.singleLineHeight), foldout.boolValue, foldout.boolValue ? "" : name.stringValue);
    241.            
    242.             var sentencesListKey = dialog.propertyPath;
    243.             var sentences = dialog.FindPropertyRelative("Sentences");
    244.  
    245.             if (foldout.boolValue)
    246.             {
    247.                 // draw the name field
    248.                 name.stringValue = EditorGUI.TextField(new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight), name.stringValue);
    249.                 position.y += EditorGUIUtility.singleLineHeight;
    250.  
    251.                 if (!_sentencesListDict.ContainsKey(sentencesListKey))
    252.                 {
    253.                     // create reorderabl list and store it in dict
    254.                     var sentencesList = new ReorderableList(sentences.serializedObject, sentences)
    255.                     {
    256.                         displayAdd = true,
    257.                         displayRemove = true,
    258.                         draggable = true,
    259.  
    260.                         // header for the dialog list
    261.                         drawHeaderCallback = DrawSentencesHeader,
    262.  
    263.                         // how a sentence is displayed
    264.                         drawElementCallback = (sentenceRect, sentenceIndex, sentenceIsActive, sentenceIsFocused) =>
    265.                         {
    266.                             var sentence = sentences.GetArrayElementAtIndex(sentenceIndex);
    267.  
    268.                             // draw simple textArea for sentence
    269.                             sentence.stringValue = EditorGUI.TextArea(sentenceRect, sentence.stringValue);
    270.                         },
    271.  
    272.                         // Sentences have simply a fixed height of 2 lines
    273.                         elementHeight = EditorGUIUtility.singleLineHeight * 2,
    274.  
    275.                         // when a sentence is added
    276.                         onAddCallback = (sentList) =>
    277.                         {
    278.                             sentList.serializedProperty.arraySize++;
    279.                             var addedElement = sentList.serializedProperty.GetArrayElementAtIndex(sentList.serializedProperty.arraySize - 1);
    280.  
    281.                             addedElement.stringValue = "";
    282.                         }
    283.                     };
    284.  
    285.                     // store the created ReorderableList
    286.                     _sentencesListDict[sentencesListKey] = sentencesList;
    287.                 }
    288.  
    289.                 // Draw the list
    290.                 _sentencesListDict[sentencesListKey].DoList(new Rect(position.x, position.y, position.width, position.height - EditorGUIUtility.singleLineHeight));
    291.             }
    292.         }
    293.     }
    294.  
    295.     #endregion Elements
    296.  
    297.     #endregion Drawers
    298.  
    299.  
    300.     #region Helpers
    301.  
    302.     #region HeightGetter
    303.  
    304.     /// <summary>
    305.     /// Returns the height of given Conversation property
    306.     /// </summary>
    307.     /// <param name="conversation"></param>
    308.     /// <returns>height of given Conversation property</returns>
    309.     private float GetConversationHeight(SerializedProperty conversation)
    310.     {
    311.         var foldout = conversation.FindPropertyRelative("Foldout");
    312.  
    313.         // if not foldout the height is simply 1 line
    314.         var height = EditorGUIUtility.singleLineHeight;
    315.  
    316.         // otherwise we sum up every controls and child heights
    317.         if (foldout.boolValue)
    318.         {
    319.             // we need some more lines:
    320.             //  for the Name field,
    321.             // the list header,
    322.             // the list buttons and a bit buffer
    323.             height += EditorGUIUtility.singleLineHeight * 5;
    324.  
    325.  
    326.             var dialogues = conversation.FindPropertyRelative("Dialogues");
    327.  
    328.             for (var d = 0; d < dialogues.arraySize; d++)
    329.             {
    330.                 var dialog = dialogues.GetArrayElementAtIndex(d);
    331.                 height += GetDialogueHeight(dialog);
    332.             }
    333.         }
    334.  
    335.         return height;
    336.     }
    337.  
    338.     /// <summary>
    339.     /// Returns the height of given Dialogue property
    340.     /// </summary>
    341.     /// <param name="dialog"></param>
    342.     /// <returns>height of given Dialogue property</returns>
    343.     private float GetDialogueHeight(SerializedProperty dialog)
    344.     {
    345.         var foldout = dialog.FindPropertyRelative("Foldout");
    346.  
    347.         // same game for the dialog if not foldout it is only a single line
    348.         var height = EditorGUIUtility.singleLineHeight;
    349.  
    350.         // otherwise sum up controls and child heights
    351.         if (foldout.boolValue)
    352.         {
    353.             // we need some more lines:
    354.             //  for the Name field,
    355.             // the list header,
    356.             // the list buttons and a bit buffer
    357.             height += EditorGUIUtility.singleLineHeight * 4;
    358.  
    359.             var sentences = dialog.FindPropertyRelative("Sentences");
    360.  
    361.             // the sentences are easier since they always have the same height
    362.             // in this example 2 lines so simply do
    363.             // at least have space for 1 sentences even if there is none
    364.             height += EditorGUIUtility.singleLineHeight * Mathf.Max(1, sentences.arraySize) * 2;
    365.         }
    366.  
    367.         return height;
    368.     }
    369.  
    370.     #endregion
    371.  
    372.     #endregion Helpers
    373. }
    374.  
    I'm using the variable :

    Code (csharp):
    1.  
    2. private SerializedProperty conversationsCounter;
    3.  
    To get the int variable ConversationIndex from the Conversation class :

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. [System.Serializable]
    7. public class Conversation
    8. {
    9.     [Tooltip("Conversation Name")]
    10.     public string Name;
    11.     public bool Foldout;
    12.     public int ConversationIndex;
    13.     public List<Dialogue> Dialogues = new List<Dialogue>();
    14. }
    15.  
    Then inside the OnEnable inside the onAddCallback I'm doing :

    Code (csharp):
    1.  
    2. conversationsCounter = addedElement.FindPropertyRelative("ConversationIndex");
    3.  
    Now after that I could add a line for example :

    Code (csharp):
    1.  
    2. conversationsCounter.intValue += 1;
    3.  
    And then inside the DrawConversationsElement method I could switch the foldout line :

    Code (csharp):
    1.  
    2. foldout.boolValue = EditorGUI.Foldout(new Rect(position.x, position.y, 10, EditorGUIUtility.singleLineHeight), foldout.boolValue, foldout.boolValue ? "" : name.stringValue, true);
    3.  
    With this :

    Code (csharp):
    1.  
    2. foldout.boolValue = EditorGUI.Foldout(new Rect(position.x, position.y, 10, EditorGUIUtility.singleLineHeight), foldout.boolValue, "Conversation " + conversationsCounter.intValue.ToString(),true);
    3.  
    The problem is that DrawConversationsElement is being called every frame so the value of the conversationsCounter.intValue is getting much bigger instead 1,2,3,4,5 each click it's getting to 400 and over.


    What I want to do is simple that the Conversations will looks like :

    Conversation 1
    Conversation 2
    Conversation 3
    Conversation 4
    .....
    Conversation 70

    But I can't figure out how to number them.