Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by RobAnthem · Jan 29, 2017 at 06:17 PM · editorscriptableobjecteditorwindoweditorguilayoutorganization

Organizing Recursive EditorGUI elements

I am trying to make a dialog editor for my Dialog class, and after getting my dialog initially instantiated and visible in the editor, I hit a wall. I could not conceive of how to organize it without creating a bool inside the dialog class itself. Here is what I have so far, any ideas? Whatever it takes to organize this crap, preferably without adding extra crap to my Dialog class.

This is the Dialog Class.

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using UnityEngine;
 namespace SpaceScoundrels
 {
     public class Dialog : ScriptableObject
     {
         public string Entry;
         public Dialog[] Responses;
         public Dialog Next(int choice)
         {
             return Responses[choice];
         }
         public virtual string GetEntry()
         {
             return Entry;
         }
     }
 }


A section from my Editor class, it is like 1k lines of code so I onl took out the dialog part.

         if (ActiveState == WindowState.DialogEditor)
         {
             if (activeDialog == null)
             {
                 if (GUILayout.Button("Create Dialog"))
                 {
                     activeDialog = CreateInstance<Dialog>();
                 }
             }
             else
             {
                 activeDialog.name = EditorGUILayout.TextField("Name", activeDialog.name);
                 activeDialog.Entry = EditorGUILayout.TextArea(activeDialog.Entry, GUILayout.Height(100));
                 dialogCount = EditorGUILayout.IntField("Dialog Options", dialogCount);
                 if (GUILayout.Button("Add Dialogs") && dialogCount > 0)
                 {
                     activeDialog.Responses = new Dialog[dialogCount];
                     for (int i = 0; i < activeDialog.Responses.Length; i++)
                     {
                         activeDialog.Responses[i] = CreateInstance<Dialog>();
                     }
                 }
                 dialogHierarchy = 1;
                 IterateDialog(activeDialog);
                 if (GUILayout.Button("Save Dialog"))
                 {
                     AssetDatabase.CreateAsset(activeDialog, "Assets/GameKit/Dialog/" + activeDialog.name + ".asset");
                     newItem = null;
                 }
 
             }
         }

The recursion method.

     void IterateDialog(Dialog dialog)
     {
         if (dialog.Responses != null)
         {
             foreach (Dialog section in dialog.Responses)
             {
                 if (section != null)
                 {
 
                     EditorGUILayout.BeginHorizontal();
                     GUILayout.Space(10 * dialogHierarchy);
                     section.Entry = EditorGUILayout.TextField("Entry", section.Entry);
                     if (GUILayout.Button("Add Dialogs"))
                     {
                         section.Responses = new Dialog[3];
                         for (int i = 0; i < section.Responses.Length; i++)
                         {
                             section.Responses[i] = CreateInstance<Dialog>();
                         }
                     }
                     EditorGUILayout.EndHorizontal();
                     IterateDialog(section);
                     dialogHierarchy += 1;
                 }
             }
         }
     }


Finally... my result. Result

results.png (56.5 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Bunny83 · Jan 29, 2017 at 06:57 PM

Well, it's not really clear how you want it to be organised. The boolean you talked about, what is it for? Just for expanding / collapsing child dialogs? You can "store" those booleans inside the editor class itself. Of course when you close the editor the settings would be gone.

As of how to improve the layout, there are several things you might change:

First use a fix size for things that have a fix-sized content, like your "Add Dialogs" button

 if (GUILayout.Button("Add Dialogs", GUILayout.Width(80))); // 80 might be tweaked to get the best result

Doing this will preserve as much of the flexible space as possible for the dynamic elements. Personally i wouldn't use the auto-labelled version of "TextField". Just using a seperate Label and a simple TextField. That way you can better control the size of each element.

Next problem is that the way you handle your indention makes not much sense. You only increase dialogHierarchy but never decrease it. So elements on the same layer wouldn't be at the same indent-level since your recursive method might increase the value for it's childs but when it returns you stay at that level.

So you either do this:

 dialogHierarchy ++;
 IterateDialog(section);
 dialogHierarchy --;

inside your recursive method, or, what would be the better solution, pass the depth on as parameter

 IterateDialog(section, depth + 1);

That way you don't need a class variable for information that is only relevant during the iteration.

To store additional information for each Dialog, you might use a Dictionary<Dialog, "AdditionalStuff">. So you can easily store whatever you want. For example using a seperate class that holds that additional information for each Dialog. In the case of the "expanding / collapsing" bool you can store a single boolean for each Dialog to indicate if it's children are expanded or not.

 public Dictionary<Dialog, EditorDialog> editorDialogs = new public Dictionary<Dialog, EditorDialog>();
 public class EditorDialog
 {
     public bool childsExpanded = false;
     // ...
 
 }
 EditorDialog GetEditorDialog(Dialog aDialog)
 {
     EditorDialog result;
     if (!editorDialogs.TryGetValue(aDialog, out result))
     {
         result = new EditorDialog();
         editorDialogs.Add(aDialog, result);
     }
     return result;
 }

With that you can simply add this line:

 var editorDialog = GetEditorDialog( dialog );

and set / get the "childsExpanded" as you need.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image RobAnthem · Jan 29, 2017 at 07:04 PM 0
Share

Sorry for the lack of info on what I was envisioning, but this is basically the answer I needed. Thanks so much, I can't believe I didn't think of making another Editor-Only class to handle the dialogs more, because its only for editing purposes I could literally add any amount of data I needed. Also the dictionary idea is excellent, and the dialogHierarchy was a poor attempt at your much better idea of ++, iterate, --. Essentially you covered everything I was unable to think of at the moment. I was desperately trying to figure this out yesterday so I could get my $$anonymous$$m on making quests and dialogs, but I had to call it a day after taxing my brain for so many hours. Thanks again Bunny83, you always have a good answer.

avatar image Bunny83 · Jan 29, 2017 at 07:15 PM 0
Share

ps: you might want to wrap your initial call of your recursive method in a ScrollView.

It's in general difficult how to manage tree structures in the most usable way. What most implementations do is to seperate the tree from the additional data. Examples are Unity's Hierarchy view and inspector view or if you look at things like the windows registry editor, it's splitted into a treeview on the left and the actual details view on the right.

Another common way to approach this is using seperate editor windows. So one window simply edits one Dialog. It might "show" details of the direct children but not more. You can add a button to each child which will open a seperate window for that child dialog. This can be also be done with a single window if you additionally display the current tree-path somewhere. This is how the windows explorer works (since Windows 7 i think). So clicking on the child buttons would move "into" the depth of the tree. Clicking one of the "parent" buttons of the current tree path would allow to move back up to the root.

Since a tree grows two dimensional it's quite common to display each dialog as a node in a 2d node graph (like Unity's mecanim).

avatar image RobAnthem Bunny83 · Jan 29, 2017 at 11:30 PM 0
Share

Not sure how I would easily accomplish the node editing but I can't image it would be too difficult. From all your wondrous input, I managed to make this for far. Which my guys can at least work with. alt text

results-new.png (50.6 kB)

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

74 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Keep equal width for panels in EditorGUILayout.HorizontalScope 0 Answers

Save ScriptableObject On Unity Application Quit? 1 Answer

Referencing / linking a .asset / .prefab file in another .asset / .prefab file programmatically. 2 Answers

Serialization depth limit 7 exceeded 1 Answer

Unity editor extension - create drag and drop (similar to Buildbox) 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges