Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 Unitraxx · Nov 28, 2014 at 07:19 PM · guieditoreditorwindow

EditorWindow: Window works, why does ModalWindow not?

The code beneath works perfectly when I replace GUI.ModalWindow by GUI.Window.

     public class Test2Window : EditorWindow
     {
         Rect window_position = new Rect(100, 100, 100, 100);
 
         [MenuItem("SCCD/Open Test")]
         public static void Init()
         {
             Test2Window window = (Test2Window) EditorWindow.GetWindow(typeof(Test2Window), false);
             window.title = "Editor Window";
         }
 
         private void WindowFunction(int id)
         {
             GUILayout.Button("test");
         }
 
         public void OnGUI() {
             this.BeginWindows();
             GUI.ModalWindow(0, this.window_position, WindowFunction, "");
             this.EndWindows();
         }
     }

With GUI.ModalWindow however I get the errors:

 ArgumentException: Getting control 0's position in a group with only 0 controls when doing mouseDrag

(mouseDrag is replaced by the current event, so most of the time it's just mouseMove)

So is this a bug? Or what magic do I have to perform to get a simple modal window working in an EditorWindow?

EDIT: if I use GUI instead of GUILayout to position the button inside the window, then I do not get the error anymore, however I do not get a window either.

Comment
Add comment · Show 3
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 Unitraxx · Nov 28, 2014 at 11:12 PM 0
Share

Apparently someone on the forums had the same problem: http://forum.unity3d.com/threads/gui-modalwindow-in-an-editorwindow-throws-errors.193364/. No fix though.

avatar image Unitraxx · Dec 02, 2014 at 09:00 PM 0
Share

One day I will get an answer!

avatar image Bunny83 · Dec 06, 2014 at 05:16 PM 0
Share

@Unitraxx: I doubt it ^^
$$anonymous$$odalWindow is a quite new thing and ment for the runtime. It is ment to prevent any other GUI interaction while active. The most common example would be dialog boxes. However EditorWindows work a bit different compared to the Unity runtime. That's why you actually have to use BeginWindows and EndWindows. Since there's no layout version of the $$anonymous$$odalWindow they might haven't made it compatible with the layout system.

As workaround you could simply use a normal Window and disable everything else (GUI.enabled = false). For that i would implemeent a custom popup class that wraps such an modal window and simply implement a Stack / List of those windows. If the Stack / List is empty enable the usual GUI. If there is one or more windows on the Stack disable everything except the topmost window object.

1 Reply

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

Answer by Bunny83 · Dec 06, 2014 at 06:38 PM

Here's a workaround modal window system for editor windows ^^

 using UnityEngine;
 using UnityEditor;
 using System.Collections;
 using System.Collections.Generic;
 
 public class ModalWindow
 {
     private static int m_WinIDManager = 1337;
     protected int m_WinID = m_WinIDManager++;
     protected bool enabled = true;
 
     public event System.Action<ModalWindow> OnWindow;
     public string title;
     public Rect position;
     public bool ShouldClose = false;    
     public int ID { get { return m_WinID; } }
     public ModalWindow(Rect aInitialPos, string aTitle)
     {
         position = aInitialPos;
         title = aTitle;
     }
     public ModalWindow(Rect aInitialPos, string aTitle, System.Action<ModalWindow> aCallback)
     {
         position = aInitialPos;
         title = aTitle;
         OnWindow += aCallback;
     }
     public virtual void OnGUI()
     {
         // For some strange reason Unity only disables the window border but not the content
         // so we save the enabled state and use it inside the window callback down below.
         enabled = GUI.enabled;
         position = GUI.Window(m_WinID, position, DrawWindow, title);
     }
 
     protected virtual void DrawWindow(int id)
     {
         // restore the enabled state
         GUI.enabled = enabled;
         if (OnWindow != null)
             OnWindow(this);
     }
     public virtual void Close()
     {
         ShouldClose = true;
     }
 }
 
 public class ModalSystem
 {
     private List<ModalWindow> m_List = new List<ModalWindow>();
     public bool IsWindowOpen { get { return m_List.Count > 0; } }
     public ModalWindow Top
     {
         get { return IsWindowOpen ? m_List[m_List.Count - 1] : null; }
     }
     public void Draw()
     {
         // remove closed windows
         if (Event.current.type == EventType.Layout)
         {
             for (int i = m_List.Count - 1; i >= 0; i--)
                 if (m_List[i].ShouldClose)
                     m_List.RemoveAt(i);
         }
         if (m_List.Count > 0)
         {
             // draw all windows
             for (int i = 0; i < m_List.Count; i++)
             {
                 GUI.enabled = (i == m_List.Count - 1); // disable all except the last
                 GUI.BringWindowToFront(m_List[i].ID); // order them from back to front
                 GUI.FocusWindow(m_List[i].ID);       //               ||
                 m_List[i].OnGUI();
             }
         }
     }
     public void Add(ModalWindow aWindow)
     {
         m_List.Add(aWindow);
     }
 }
 
 public class EditorWindowTest : EditorWindow
 {
     [MenuItem("Tools/TestWindow")]
     public static void Init()
     {
         GetWindow<EditorWindowTest>();
     }
 
     ModalSystem modalWindows = new ModalSystem();
 
     void OpenPopup(string aTitle)
     {
         var win = new ModalWindow(new Rect(30, 30, position.width - 60, position.height - 60), aTitle, (w) =>
         {
             if (GUILayout.Button("Open another popup"))
                 OpenPopup(aTitle + "->subwindow");
             if (GUILayout.Button("Close"))
                 w.Close();
             GUI.DragWindow();
         });
         modalWindows.Add(win);
     }
 
     void OnGUI()
     {
         GUI.enabled = !modalWindows.IsWindowOpen;
         if (GUILayout.Button("Open Popup"))
         {
             OpenPopup("First");
         }
         if (GUILayout.Button("Some other GUI stuff"))
         {
             Debug.Log("Doing stuff...");
         }
         BeginWindows();
         modalWindows.Draw();
         EndWindows();
     }
 }


It's just quickly hacked together. Some things could be done in a better way. Since windows in general have some very strange things ongoing in the background you might even drop them all together ^^. If you manually disabling all other content (like in my system above) there should be no issue with overlapping. So you could draw each "window" simply as layout group with a box / window style. Of course window dragging has to be done manually if needed, but that's not that difficult to implement ^^.

This is just ment as example. The window ID generation is sufficient for most cases.

Keep in mind that those classes don't support serialization at the moment. So when you change playmode or scripts are recompiled the ModalSystem will be recreated and all open windows would vanish.

Comment
Add comment · Show 6 · 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 Unitraxx · Dec 06, 2014 at 07:43 PM 0
Share

Nice to see an answer, thank you! I will see if I can make this work. What follows is a description of the stuff I tried out this last week and it contains a few questions that maybe you can answer (and solutions that you maybe find interesting?) : I was currently using an extra EditorWindow in combination with ShowPopup() and OnLostFocus(){Focus()}). This was sort of working but the sizing of the window isn't really working out. Currently I throw all content of the popupwindow in a BeginVertical() and then using GUILayoutUtility.GetLastRect() I set the size of the popupwindow. For this to work properly I need to add the border offsets of the popupwindow to the GetLastRect result. (Do you maybe have an idea which GUI style is used, when showing an EditorWindow using ShowPopup()? This would make it a bit easier to do the border correction.) Anyway even with this approach I still have the problem that the width of the popup window isn't satisfactory. The strings in my selection grid aren't fully visible. I kinda assumed that GUILayout would take care of size and allow all labels to be fully visible. Any idea regarding that?

Some more interesting stuff: after a lot of digging around in the API I found PopupWindow. This really looked promising until I started using it with a simple example. I remember it working somewhat O$$anonymous$$, but it was constantly throwing exceptions. $$anonymous$$y main question here is: where do I find the progress on features? Or the ability to report/follow up bugs? I found a page with feature requests where you can vote on, but that didn't really help me unfortunately.

When I get some more time to fool around with the example you provided, it's very likely I'll post some more comments here. And thank you again!

avatar image Bunny83 · Dec 06, 2014 at 08:51 PM 0
Share

@Unitraxx: EditorWindows are quite complicated. Usual Floating windows have on the top a ContainerWindow which has a SplitView in it. The SplitView contains a DockArea and the DockArea the actual EditorWindow object.

Popup windows (ShowPopup) have the layout ContainerWindow->HostView->EditorWindow. The DockArea is derived from HostView. It is responsible for displaying the tabs at the top. The ordinary HostView can contain only one EditorWindow. When the HostView is drawn it encloses the OnGUI call of your EditorWindow with a GUILayout.BeginVertical with a custom GUIStyle.

It uses the "hostview" style like this:

 background = "hostview";
 background.padding.top = 0;

where background is a GUIStyle.

The PopupWindow class (and the PopupWindowContent) are pretty pointless ^^. It's just an ordinary EditorWindow shown with ShowAsDropDown.

$$anonymous$$ay i ask what you actually need a modal window for? $$anonymous$$y solution shows the modal window just inside the EditorWindow. Unity-wide modal windows doesn't make much sense since it would prevent the user from doing and intermediate actions. Such an approach should be avoided. Editor extensions that would enforce something like that wouldn't last long in my projects ^^.

However Unity has an internal method called "$$anonymous$$ake$$anonymous$$odal" (inside EditorWindow) which can make a ContainerWindow modal. It's used for the SaveAssets dialog. But as i said it's internal so you can only use it with reflection. $$anonymous$$eep in $$anonymous$$d if you mess up something in your window Unity is unusable if you can't close the window.

avatar image Unitraxx · Dec 06, 2014 at 09:07 PM 0
Share

In my tool I basically want to pop up a list of options and the user has to make a choice before being able to advance. Anyway, how do you know all this? Where do you find out this ContainerWindow->HostView->EditorWindow structure? Is there more documentation I'm not aware of? Or can you look into all this directly with the pro version?

A modal window inside the EditorWindow would indeed be preferred so I'm definitely going to try out what you proposed. I however work with a different formalism/program$$anonymous$$g methodology. (I use a higher level of abstraction to develop my tool, it's the subject of my $$anonymous$$asters thesis. $$anonymous$$odularity is key and so far this method hasn't been used with game engines so far. I built a compiler that generates C# code from my formalism. The tool I'm building is actually going to provide a visual editing environment for this formalism.)

Anyway thank you for your information, I'll keep you updated!

avatar image Bunny83 · Dec 07, 2014 at 06:09 AM 0
Share

@Unitraxx:
Sounds interesting :)

I use ILSpy but any .NET reflector clone will do. Just open the UnityEditor.dll (and UnityEngine.dll) found at

 Unity/Editor/Data/$$anonymous$$anaged/

There are several visual scripting approaches out there for Unity. As far as i remember the antares universe project also partially generates C# code similar to Visual Studio's form editor. However i'm not a friend of such editors :) Such editors usually change the way you work with Unity completely but every now and then you hit a border and you're required to write custom nodes.

avatar image Unitraxx · Dec 07, 2014 at 04:00 PM 0
Share

I understand those limitations and that's also why I try to avoid the term visual scripting. It isn't aimed at solely using visual elements to develop, it will actually require a large amount of code to still be written. It takes care of events, hierarchy, parallelism and stuff like that. This method (Domain Specific Language and Visual $$anonymous$$odelling if you would want to look up things) is actually already used for the development of critical software like power plants, air planes, car electronics etc. $$anonymous$$y thesis is aimed specifically at proving the usability of this for the creation of complex game AI in commercial game engines. The concept of custom nodes simply doesn't apply. Anyway it's still in research we can't predict if it will be of any use. What's likely to happen is that people expect it to be a tool for non-programmers, while that's not at all the target audience. Also since it's just a masters thesis subject, it's pretty likely that it will never get completely finished.

Show more comments

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

27 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

Related Questions

How to force Unity to Repaint an EditorWindow? 1 Answer

Editor GUI Foldout header style customization 0 Answers

Custom Curve Editor? 0 Answers

How to draw button in editor window rotated by 90 degrees? 0 Answers

display editor script in the game window 0 Answers


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