Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add built-in GUI to display license notices #79599

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Calinou
Copy link
Member

@Calinou Calinou commented Jul 18, 2023

Press Ctrl/Cmd + Shift + L (ui_toggle_licenses_dialog built-in action) to show/hide the notices dialog.

The dialog can be shown via script using SceneTree.licenses_dialog_visible = true|false. Since the default shortcut is not usable on mobile platforms, it is recommended to create a button that sets SceneTree.licenses_dialog_visible to true when pressed in your project's menus.

PS: I believe this is the first built-in high-level GUI component we make available in projects. It'll be interesting to see what can be done in the future with this approach.

Fun fact: This is the first time I add a new node to Godot in C++ 🙂

Testing project: test_licenses_dialog.zip

Preview

Screenshot_20230718_062434

TODO

  • Try using Label instead of RichTextLabel, so that this works in builds using disable_advanced_gui=yes. I've purposefully avoided advanced GUI nodes for this dialog, but had to switch to RichTextLabel because Label was extremely slow to shape the text.
    • I don't even need RichTextLabel BBCode here, and I'm surprised RichTextLabel is so much faster in this use case (easily 100× faster in a debug build). cc @bruvzg

@Calinou Calinou requested review from a team as code owners July 18, 2023 05:02
@Calinou Calinou added this to the 4.x milestone Jul 18, 2023
@Calinou Calinou force-pushed the add-license-notices-gui branch 3 times, most recently from dfff79d to 7ec3b9e Compare July 18, 2023 05:39
@Sauermann
Copy link
Contributor

Instead of basing the new node-type on CanvasLayer, I suggest to base the node on Window or Popup or one of their descendants.
The reason for this is, that when there is a different Window open, then it will overlap the license notices.
Also when a different CanvasLayer with a layer > the layer of your node, then your node will be hidden behind the nodes of the other CanvasLayer.
I'm basing this on the assumption, that the license notices should be visible, no matter what other content is currently displayed.

@KoBeWi
Copy link
Member

KoBeWi commented Jul 18, 2023

Any reason the new class is exposed? It doesn't need to, the relevant documentation can be inside licenses_dialog_visible description.
If we could somehow get rid of the unhandled_input override, we wouldn't need any new class at all, but I think it's not possible.

@Sauermann
Copy link
Contributor

Sauermann commented Jul 18, 2023

How about using AcceptDialog? It already handles input events for closing.

@KoBeWi
Copy link
Member

KoBeWi commented Jul 18, 2023

Ah for some reason I though the method is used for the shortcut. Yeah, it can be replaced with a plain AcceptDialog. If you need to do something extra in set_licenses_dialog_visible(false), you can connect close_requested/confirmed or visibility_changed changed signal.

@MewPurPur
Copy link
Contributor

MewPurPur commented Jul 18, 2023

SVG for the dialog that's 1 kB smaller:

<svg height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M1.3 12.362a1.041 1.041 0 0 0 0 1.465l.865.874a1.041 1.041 0 0 0 1.465 0l2.935-2.944a1.041 1.041 0 0 0 0-1.505l2.07-2.07 1.02 1.02a.38.38 0 0 0 .549 0l-.242.242a.784.784 0 0 0 0 1.1l.457.457a.784.784 0 0 0 1.097 0l3.3-3.3a.784.784 0 0 0 0-1.1l-.457-.457a.784.784 0 0 0-1.1 0l-.242.242a.38.38 0 0 0 0-.549l-2.815-2.815a.38.38 0 0 0-.549 0l.242-.242a.784.784 0 0 0 0-1.1l-.457-.457a.784.784 0 0 0-1.1 0l-3.3 3.3a.784.784 0 0 0 0 1.1l.457.457a.784.784 0 0 0 1.1 0l.242-.242a.38.38 0 0 0 0 .55l1.019 1.02-2.07 2.07a1.041 1.041 0 0 0-1.553 0z" fill="#8eef97"/></svg>

@Calinou
Copy link
Member Author

Calinou commented Jul 18, 2023

Any reason the new class is exposed? It doesn't need to, the relevant documentation can be inside licenses_dialog_visible description.

I thought I was required to expose it, but it looks like it works fine if it's not exposed. I've unexposed the class as a result.

How about using AcceptDialog? It already handles input events for closing.

It requires advanced GUI functionality, which is disabled when building Godot with disable_advanced_gui=yes. My goal is to have this dialog working in every Godot build, even if you disable advanced GUI which is frequently done for custom mobile/web builds to optimize binary size.

These are the nodes that are unavailable when building with disable_advanced_gui=yes:

#ifndef ADVANCED_GUI_DISABLED
GDREGISTER_CLASS(FileDialog);
GDREGISTER_CLASS(PopupMenu);
GDREGISTER_CLASS(Tree);
GDREGISTER_CLASS(TextEdit);
GDREGISTER_CLASS(CodeEdit);
GDREGISTER_CLASS(SyntaxHighlighter);
GDREGISTER_CLASS(CodeHighlighter);
GDREGISTER_ABSTRACT_CLASS(TreeItem);
GDREGISTER_CLASS(OptionButton);
GDREGISTER_CLASS(SpinBox);
GDREGISTER_CLASS(ColorPicker);
GDREGISTER_CLASS(ColorPickerButton);
GDREGISTER_CLASS(RichTextLabel);
GDREGISTER_CLASS(RichTextEffect);
GDREGISTER_CLASS(CharFXTransform);
GDREGISTER_CLASS(AcceptDialog);
GDREGISTER_CLASS(ConfirmationDialog);
GDREGISTER_CLASS(SubViewportContainer);
GDREGISTER_CLASS(SplitContainer);
GDREGISTER_CLASS(HSplitContainer);
GDREGISTER_CLASS(VSplitContainer);
GDREGISTER_CLASS(GraphNode);
GDREGISTER_CLASS(GraphEdit);
OS::get_singleton()->yield(); // may take time to init
bool swap_cancel_ok = false;
if (DisplayServer::get_singleton()) {
swap_cancel_ok = GLOBAL_DEF_NOVAL("gui/common/swap_cancel_ok", bool(DisplayServer::get_singleton()->get_swap_cancel_ok()));
}
AcceptDialog::set_swap_cancel_ok(swap_cancel_ok);
#endif

Window and Popup base classes are available though.

SVG for the dialog that's 1 kB smaller:

Thanks 🙂 I've incorporated it and added you as a co-author.

@Calinou Calinou force-pushed the add-license-notices-gui branch 2 times, most recently from 085fed9 to 3e201fe Compare July 18, 2023 17:24
@KoBeWi
Copy link
Member

KoBeWi commented Jul 18, 2023

Window and Popup base classes are available though.

Then it could be a Window. Although it doesn't really matter if the class is not exposed.

@Calinou Calinou force-pushed the add-license-notices-gui branch 3 times, most recently from b85fa26 to 201064e Compare July 19, 2023 01:56
@KoBeWi
Copy link
Member

KoBeWi commented Jul 19, 2023

I don't even need RichTextLabel BBCode here, and I'm surprised RichTextLabel is so much faster in this use case (easily 100× faster in a debug build).

Pretty sure they are both as fast, but RTL is shaped in thread. If you could divide the whole text into smaller labels, you could add them one by one inside NOTIFICATION_PROCESS.

scene/gui/licenses_dialog.h Outdated Show resolved Hide resolved
scene/gui/licenses_dialog.h Outdated Show resolved Hide resolved
@Calinou Calinou force-pushed the add-license-notices-gui branch from 201064e to 7b66d8b Compare July 19, 2023 14:05
Copy link
Contributor

@Sauermann Sauermann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using CanvasLayer as base means, that the licenses will always be hidden behind embedded Windows.
image

scene/gui/licenses_dialog.cpp Show resolved Hide resolved
@Calinou Calinou force-pushed the add-license-notices-gui branch from 7b66d8b to d8c25a8 Compare July 19, 2023 19:55
@Calinou Calinou force-pushed the add-license-notices-gui branch from d8c25a8 to 7338f11 Compare July 19, 2023 20:52
@bruvzg
Copy link
Member

bruvzg commented Jul 19, 2023

using Label instead of RichTextLabel, so that this works in builds using disable_advanced_gui=yes. I've purposefully avoided advanced GUI nodes for this dialog, but had to switch to RichTextLabel because Label was extremely slow to shape the text.

RTL processes text as multiple separate paragraphs, Label as a single paragraph, this is likely the reason. It should not be too hard to fix, but I'm not sure if huge text is an intended use of Label.

Since Label does not have a scrollbar of its own, a vbox with multiple Labels might work as a workaround (split text at two consecutive line breaks).

@KoBeWi
Copy link
Member

KoBeWi commented Aug 19, 2023

Then it could be a Window. Although it doesn't really matter if the class is not exposed.

I don't know why I wrote this comment (xd), but as noted by Sauermann, the class could be changed to inherit Window instead, to ensure that it appears on top. Although it's probably not relevant for most games.

Copy link
Member

@KoBeWi KoBeWi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine code-wise.

@Calinou Calinou force-pushed the add-license-notices-gui branch from 3a53622 to 29be92e Compare September 10, 2023 16:08
@akien-mga akien-mga self-requested a review September 11, 2023 12:02
@Calinou Calinou force-pushed the add-license-notices-gui branch from 29be92e to 47ad666 Compare October 24, 2024 00:38
@Calinou
Copy link
Member Author

Calinou commented Oct 24, 2024

Rebased and tested again, it works as expected.

It compiles with disable_advanced_gui=yes, which surprises me. This SCons option defines ADVANCED_GUI_DISABLED, which disables registering classes such as RichTextLabel. However, it does not prevent the source files from being compiled, so you can still use the classes from C++ even if they aren't exposed to scripting. Doing so will increase binary size somewhat if it's the first use of the class, which is what is happening here.

Here are Linux x86_64 release export template binary sizes with optimize=speed lto=full:

67,264,064  `master`
64,626,016  `master`, advanced GUI disabled
65,019,296  This PR, advanced GUI disabled

Excluding the files entirely from compilation would likely reduce binary size further, while preventing you from accidentally using the classes in C++ when you're not supposed to.

Either way, it means this PR is technically mergeable now, but the increase in binary size is an issue I'd like to have resolved first.

@bruvzg Do you know if you could make Label process text on a per-paragraph basis? Intuitively, I think most people would expect Label to be as fast or faster than RichTextLabel for rendering text.

@Calinou Calinou force-pushed the add-license-notices-gui branch from 47ad666 to acd42d3 Compare October 24, 2024 00:45
scene/gui/licenses_dialog.cpp Outdated Show resolved Hide resolved
scene/gui/licenses_dialog.cpp Outdated Show resolved Hide resolved
scene/gui/licenses_dialog.cpp Outdated Show resolved Hide resolved
@bruvzg
Copy link
Member

bruvzg commented Oct 24, 2024

Do you know if you could make Label process text on a per-paragraph basis?

I'll take a look tomorrow, currently it can use only a single paragraph, but changing it to use multiple should not be hard.

Press Ctrl/Cmd + Shift + L (`ui_toggle_licenses_dialog` built-in action)
to show/hide the notices dialog.

The dialog can be shown via script using
`SceneTree.licenses_dialog_visible = true|false`.

Co-authored-by: MewPurPur <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants