I'm trying to implement a series of nested menus. Basically, each menu is in a PanelContainer. When a button is pressed, I'd like to then spawn a submenu. And this submenu will have buttons that can spawn further submenus. When a submenu is closed, I want control to revert back to the parent menu that spawned it. When a child panel is open, it should not possible to interact with the panel that spawned it until that child panel closes.

In many programming UIs, like Qt or Java Swing, this is handled automatically through what are called modal panels. Godot does not seem to have this. When I open a child control, I am still able to interact with the controls of the parent that spawned it. If I try using PopupPanels, they close automatically if I click anywhere outside of them. I would like to be able to create panels that work like modal panels, but as far as I can tell, I have to manually track which menu is currently open and disable all their controls in code when I spawn a child panel.

Does Godot support modal panels as they're typically used in most programming UIs, or do I need to implement this functionality myself?

  • Toxe replied to this.

    Toxe Yes, I've tried using the Popup class before, but not been able to get it to work. Right now the windows will automatically close if I click anywhere outside the popped up panel.

      I think you just want to use regular panels and handle the modality as a simple design paradigm. Basically extend the base panel to build your own modal panel container or such. Probably best to do it as a plugin though for prototyping it's not necessary. For deployment it likely makes things easier tho.

      I've experienced mixed results in trying to create modal controls.

      I have one project in which a FileDialog works (is modal) but a Popup dialog fails to be modal. I couldn't figure out why one is modal and the other isn't.

      In Godot 4.2, I created a class that inherits ConfirmationDialog, like FileDialog, and it's modal.

      spaceyjase I've tried creating a popup with exclusive and transient enabled but it still automatically closes if I click outside of the control area. Same if call the popup_exclusive() method to create it. The docs say that my menu will get exclusive control of input, but that does me no good if it keeps automatically closing.

        There must a clue here about why the first is modal and second is not:

        ConfirmationDialog < AcceptDialog < Window < Viewport < Node < Object

        Popup < Window < Viewport < Node < Object

        But I can't find it.

          kitfox I tried using a Window as the base instead of a Popup. While it does block events going to the parent, there does not seem to be a way to close it. I've tried both hide() and queue_free(), but my Window remains. When my window is open, it's also not possible to click the X button in the top right of the system bar.

          DaveTheCoder I'm starting to think that Popup is what makes it non exclusive and that you need to extend Window instead. But I can't find a way to hide or delete a Window once it's opened.

            kitfox got a minimal test example? I tried to create one (and have a few games that use a modal pop up) but couldn’t.

              kitfox I thought this was an interesting problem and a good opportunity to learn about handling windows so I tried to come up with a solution myself.

              It's not perfect but I am getting somewhere. I'll probably post something tomorrow.

              Also unless I am missing something I found the Godot documentation to be lacking a lot in this area. Maybe if I can figure out something that works I might try to contribute to the docs.

              spaceyjase

              godot.zip
              2MB

              Here's something that demonstrates the problem. I've created several different ways of spawning menus that I want to be modal, but every one has the problem that they close automatically when you click outside of them or allow button clicks to other components.

                kitfox but every one has the problem that they close automatically when you click outside of them or allow button clicks to other components.

                Stupid question… I don't understand the problem… can someone explain why you can't make a popup menu on the whole window, so that the (semi)transparent background blocks clicks to another area of the screen?

                  In the case I mentioned above, the Popup fills the app window, so there's nowhere to click outside of it within the app, but clicking outside the app causes the Popup to close. That doesn't happen with a ConfirmationDialog.

                    Tomcat I've tried adding an empty control to the popup to absorb clicks outside of the menu area, but it still causes the menu to close if you click outside the area.

                      kitfox but it still causes the menu to close if you click outside the area.

                      DaveTheCoder but clicking outside the app causes the Popup to close.

                      Yeah, I checked and it is. But it means the panel behaves like the system properties menu (RMB) in Windows. I doubt it can be corrected by the engine methods.

                      12 days later