98teg / NativeDialogs

Native Dialogs is a plugin for Godot that allows you to interact with OS-specific dialogs, such as notifications, messages and file dialogs.
MIT License
156 stars 8 forks source link

Disable main window #7

Open Zettexe opened 1 year ago

Zettexe commented 1 year ago

How would I disable interactions on the main game window while a dialog is open? I can't seem to find a way to do it with Godot.

98teg commented 1 year ago

The best solution is to create a control node that occupies the entire screen, setting its mouse filter flag to stop. Then, make this node visible whenever you want the user to not interact with the UI, and hide it again to give control back to the user. I found this trick here

Zettexe commented 1 year ago

That would work, however, I am looking for something like the Windows Notepad Save File as dialogue where it completely blocks access to the main window until the save dialog is finished.

98teg commented 1 year ago

Not sure if that is possible, sorry

Zettexe commented 1 year ago

I looked into other solutions and Godot 4's new Window class with the Exclusive and Popup flags set actually works exactly how I would want it. Is there any possibility to include some if not all of the new Window class flags into this project for Godot 4? I can manage all this from my own game of course but would be nice if it was built in.

98teg commented 1 year ago

Oh, I didn't know that! I would need to look into it to see if it is possible to integrate it nicely with this plugin. But even if it can't I can add an explanation to the documentation, so it would be nice if you keep me updated with your findings.

Zettexe commented 1 year ago

My current solution is to simply open a new Window 1x1px in size at position x: -1, y: -1 making it invisible and disabling all rendering related things on it. Its not a perfect solution since it doesn't force the dialogs to the top when you click the main window but hopefully I can find a solution to that soon, might be some way to associate the dialogs to the new window.

98teg commented 1 year ago

The only thing I can think of is to detect the user focusing on your program's main window to call the show method again. The library I use for this plugin doesn't have the option to make the windows it creates to be always on top, unfortunately.

98teg commented 1 year ago

Here is how you may achieve that:

var window: Window = get_viewport()
window.connect("focus_entered", show)
Zettexe commented 1 year ago

Tried it and it doesn't really work as intended, it just ends up creating an infinite loop of reopening the dialog if you close it.

I did however find something else, create a sub-window with the properties "transient, exclusive and popup_window" set it never forces the Godot window above any other application except for tabbing into it, including the dialogs. Effectively this completely disables any input into the main game window as long as the popup is open.

One caveat though is that the option embed_subwindows must be disabled on the parent window for the OS controls (only tested on Window btw) to be disabled on the window, otherwise it simply disables any standard Godot inputs. Not sure if there would be a better solution with a different plugin perhaps, this seems to be about as much as I can do with the current setup.

98teg commented 1 year ago

Glad you found a solution! I'm not sure how I may improve this plugin to better fit that case though. There is probably a way to create these native windows and set them to be always on top. However, the library I'm using doesn't allow it, and it would require me to find an alternative and rewrite most of this plugin. Since I don't really have the time, I would try to explain your solution in the documentation.

Zettexe commented 1 year ago

Unless you can input Godots window handles into the plugin I think this is the best we can do. You could potentially change the type of the classes to inherit from a Window instead of a Node, set some default settings, and handle the visibility from the GDExtension if someone wants to block normal inputs to the main window (which I imagine is preferable) without much effort from what I could tell.

The built in Popup class that already inherits from Window is a good reference.

98teg commented 1 year ago

The problem with inheriting from Window is that it could make people think that every property a Godot's Window has would work with these native dialogs, which would not be the case. This functionality may work as a boolean you can enable, and the node would automatically instantiate the fake window, but this would still require the user to set the embedded windows flag to false.

Zettexe commented 1 year ago

From what I saw in the Popup class, they disable some of the window properties so I imagine you would be able to do so with any property.

Also I think in this case the embedded subwindows option on the parent is more negative than positive since it completely disables OS controls, including dragging the window around, resizing, and using the OS buttons. Leaving it true (default) only prevents normal Godot inputs.

I do think that there may be a bit too many inconsistencies with implementing such a thing though, say someone did change embedded subwindows to false then this addons functionality would change along with it and there is also a potential performance draw from just inheriting from Window in the first place.

98teg commented 1 year ago

Yeah, that's why I think documenting this workaround is the best option. Just inform people about this solution and let them judge if it fits their use case.