-
-
Notifications
You must be signed in to change notification settings - Fork 97
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
Remove the anchors and margin workflow from Control nodes, and move the feature to containers #4994
Comments
+1 to full screen container, quite recently I had to go through all of my projects to make the HUD adapt to screen size |
Honestly, this is kinda wild idea and I would probably have to try it out to know if I like it. |
It makes sense in theory. But I have the feeling (after using a lot of non-containered control nodes recently) that the resulting bloat of the scene tree would be a pain in the arse. I agree that the current system is confusing. I haven't used Godot 4 yet, but from what I am reading this is mostly a solved problem already (maybe with some additional API documentation). @YuriSizov Since this is a compatibility breaking change, is 4.x really appropriate? Sounds more like 4.0 to me. |
As someone who's been spending hours (>30 at a guess) over the last couple of weeks with Godot's UI containers and fighting to get them to do what it seems they should intuitively do, I'd be a fan of anything that makes them more user friendly and intuitive. I'm not an expert with them by any stretch so the following points are likely just my lack of understanding, (I apologise if I misunderstand how some of the control nodes are supposed to work!). Hopefully your proposal addresses these?
|
Well, I just wanted to indicate that we aren't trying to hastily solve this now. This is a big change, and I feel people will have a lot to say about the usability in this area. So this is for some future version, really. But fine, I'll put it into |
I don't think that's true. From my experience, I think most projects would only require one top FullScreenContainer (as the root of their UI) and maybe a handful of AnchorMarginsContainer to position things in the screen. The remaining parts usually consists in a set of nested Containers which would not change that much. At least from my experience, I barely needed anchors and margins outside of my root UI nodes, all other Controls being positioned using containers. Also, the 4.0 unique node name feature makes it easy to reference a node deeper in the hierarchy, so I don't think the issue is that strong.
If you set the anchors correctly, your control should be able to adapt to any resolution and screen size already. But yeah, that's why things are a little bit confusing.
Yep, this is supported by anchors values. Anchors are exactly that, they are like coordinates, but relative to the parent container. (their value is between 0 and 1). |
Hm. Maybe I don't get this right, so please correct me if I'm wrong. Isn't the proposal basically moving the properties away from the editor and into another node type but keep the workflow as confusing as it is? (And maybe add node types that basically just encapsulate a margin prefix) As of now I can't see the benefit of that. Quite the opposite, actually, as it would add another complexity layer. Don't get me wrong, the system is confusing but every dynamical resizing framework is confusing. All HTML/CSS developers can agree I guess. And Godot's UI framework is still one of the best and easiest I've ever seen. Do we have information on what specifically is confusing to most users? Maybe it's just the terminology or something. |
Anchors = percentual distance from a side. |
The proposal is to move the anchors an margin/offset properties, which are rarely used, from outside Control to a dedicated Container node instead.
What is confusing is the fact that Control node expose properties for two different workflows:
This made it so @YuriSizov reworked the UI a lot in 4.0 so that things are clearer in the inspector, showing only the properties that make sense depending on whether the parent is a Container or not. It helps, but it does not change the fact that all anchors and margins related APIs are still present, while not useful around 90% of the time. Also users might be confused by the fact the inspector changes a lot depending on the two different situations. We can not remove anchors and margins right away, because they are still useful when you want to position a Control relatively to the screen. That's why this proposal is about moving the anchors and margins use case to a dedicated Container instead. You would set the anchors and margins as a properties of the Container, and the child Control would be automatically positioned according to those properties. |
Why not simply hide those parameters when they are controlled by parents? |
@nezvers That already happens in 4.x |
I guess my problem here is that I always use controls that position and resize dynamically so I don't see the main problem here. 😊 |
Yes, that's what is done in 4.0 already. The issue is more about the API, and the fact it's difficult to manage two positioning systems at the same time. That's why moving everything to the Container-based workflow would make things easier to understand. |
A highly controversial question I guess, but what is the point of not using containers in the first place? We're developing games for SOO many resolutions, I'd say that a container approach is the only one that should be used. (Ducks away) |
Containers work for defining "behavior", and anchors/position work when you want to have precise positioning. I find both useful. Anchors/position are especially handy for anything you need to animate or anything that interacts with Node2Ds. Personally, don't mind the proposed change in principle, but it may be harder for users to understand despite the goal for having the opposite. I share the same worries groud already described in the OP. With that, if anchors/precise position are replaced with a container that does the same thing, I think animation/interaction with Node2Ds can be adapted. To me this signifies a bigger change, that containers and the rest of controls should be considered different groups of nodes, ones mostly for making layouts and another is a collection of pre-built widgets. Both can draw, of course, but so can any canvas item. |
Anchors and Margins as currently implemented, while complicated, are vital to the creation of dynamic huds. Imagine a hud similar to the Borderlands games https://cdna.artstation.com/p/assets/images/images/024/379/316/large/ghent-bailey-bl3-rough-hud-layout.jpg in which you have various elements anchored to relative screen positions. Capable of growing towards a fixed direction. This is something that would require a batshit crazy amount of Containers to replicate. Just to position each UI element in the correct part of the screen. Just as a baseline you are looking at a construct like:
Just to get the correct layout. However, containers grow with their contents size. So you couldn't have elements growing past the vertical column they are occupying. The same structure with anchors and margins as currently implemented looks like this:
Now that this lesson on the current state of things is done with. Containers already manage control node growth directions. This is done by setting the size_flags. The behavior of these isn't directly obvious. And we could do some things to improve that:
For example instead of Fill, expand and shrink, use terminology that communicates whether a flag Aligns a control to the beginning, center, or end, of a container. Currently you have to set the flags to: None, Shrink Center, and Shrink End, respectively to achieve that kind of alignment. TLDR: Turn size_flags into Two or three separate settings options each. The Fill setting would have the options: Largest Size, Smallest Size, Custom (Grow, Shrink, and None respectively.) The Alignment setting would have the options: Start, Center, End. (Or Top, Middle, Bottom, or Left, Middle, Right, depending on the parent container.) The Expand setting would be a boolean off and on. If off, a node with Fill.Shrink and Align.Left would take its smallest size in the left most space of a HBoxContainer. (Equal to the current behavior of: No flags set at at all.) While with it on, a node with the same settings would Center itself in the left most space, but retain it's smallest size. (Equal to the current behavior of: Expand + Shrink Center being enabled.)
That would basically mean, in current terms, changing the default anchors and margins configuration from "Top Left, smallest size" to "Full Rect" If you want a control node to not occupy the entire area, then you should enable the 'shrink' setting. Alternatively, "Fill all available space" would be default for Containers. And "Stays as small as possible" would be the default for anything that is not a container.
MarginContainer should default to NO margins being applied. (Currently the default is a invisible 20px left margin or something like that. That isn't visible in the settings AT ALL.) H and VBoxContainers should merge because c'mon really how is that issue still open? <.< AlignmentContainers can be added with the express purpose of being only used to be the top level node of a UI. They also come with growth directions. Alignment, Full Screen, TopLeft, Top, TopRight, etc. To, going back to my very first example of current godot, turn our tree into this:
Here is hoping some of these ramblings make sense. |
Well, your example is kind of wrong here, since with the new AnchorMarginContainer, the hierarchy would be something like that:
While right now it's something like:
It's basically one level deeper. But it's not really a "batshit crazy amount of Containers", at least with that proposal.
No, that's a false assumption in fact. Containers may or may not adapt to their children size, it simply depends on the Container type. While most Containters do that, the ScrollContainer, for example, does not. And this AnchorMarginContainer would not do that either.
Yes, but there's also a grow_direction property in Control nodes, which is mainly used by the anchors and margins system (when having no Container parent). For the remaining part I can't really comment, those are matter for other proposals. |
My first examples, before the line -, were about Godot in its current form in 2.x-3.x.
Then it plainly is not a container. It's a Anchor. Arguably, it should not even be a control node at that point. |
Well, if you say so. Containers are simply Control nodes that position their children, nothing more 🤷. ScrollContainer is a Container and does not return a minimum size that depends on its children, and it's still a container. Edit: that being said, the ScrollContainer node allows to disable one scroll axis and thus may adapt its size to its content if needed. I guess we could implement such a behavior in AnchorMarginContainer too, but not sure what it would do. |
Part of what makes the current system so complicated though, honestly, is the fact that Control nodes are incredibly bloated. They do alignment, they do drawing, they do custom constants, they do sorting. Many of the container and specialized control nodes barely implement any code themselves, but can rely on Control already having it buried in there somewhere. If we're thinking of completely redoing how UI is laid out; might as well do a clear separation between Anchors, Containers, And Controls. Instead of jamming more code and settings into Control, just so it can do all of those things. |
I say no to this one. For example, making a non-trivial responsive UI relies heavily on margins, anchors, grow directions and size flags and the Scene Tree is already bloated enough for those kinds of UIs (even when sub-instancing a lot). Putting anchors and margins outside of Controls as Standalone Nodes will make things unmanageable, and hard to keep track. Right now you know exactly what Node dictates the sizing and placement behaviours, by placing those settings outside you would be creating a completely separate dependency chain. |
A tangent idea that would be made sensible with this PR: It would allow a slightly bigger inspector editor for editing Anchors and Offsets (I get 3.x and 4.x terminology mixed all the time in it, sorry!) without having to clutter Control. I made a quick mockup. I originally thought about doing examples for the docs, but I think it being in the editor like this does the job well, too, and it's more discoverable since some people... um... don't... read the docs? And when the preview isn't showing, it actually looks quite tidy. This one is a little bit odd, since there are currently no animations in the editor, but I think it can go a long way :) I am still fond of how it currently is, but might just be a case of good ol' stockholm syndrome.
This could be an extra incentive for people to like the change in their workflows. I'm starting to like the idea of "all CanvasItems are floating, top-left-positioned by default, just like the current Node2Ds, and are only automatically resized in any way by Containers." As for Growth Direction, I like the proportional Pivot Offset approach, but the absolute version might be also useful. |
I really like @mrpedrobraga 's mock up. It would make designing/implementing UI a lot easier because of it's visual feedback. I'd say that is the most effective means of improving users understanding. |
Please don't do this, IMO this is a way to node hell... I find it fine how it is. It is already really tedious to use Node paths in the UI with several Container nodes, i don't want to add multiple levels of Margin nodes on top of this. |
This concern has been made completely irrelevant with https://docs.godotengine.org/en/stable/tutorials/scripting/scene_unique_nodes.html |
Would be new to me, that this is also a feature for C#. Or did i miss the addition? Also this prevents me from doing something like "Items -> Information -> Name", because i now have to do monster names like "ItemInformationName" for my child nodes where i want to use the unique name. |
It doesn't prevent anything like that. And it works with C# just fine. Additionally I'd like to note that, some forms of this proposal here would realistically significantly reduce the number of nodes in a scene. |
It prevents me from things like: "Items -> Information -> Name" because when i want a node at a other place in the tree i can't use "Vehicles -> Information -> Name" as this is not unique anymore. So i must still use something like "ItemInformationName" and "VehicleInformationName" for my TextEdit. |
Don't use it for that then. It appears you have not tried it yet, or fully understood how it works. Which is not helpful to discussing how to lay out UI elements. |
I understand how a unique name works, but it has the disadvantage that the name must be unique, this could be helpful in projects where something is really unique like "HealthLabel" or something like that, but in my large item editor there are many different properties where some nodes have the same name. And i don't know what this does have to do with intent of my first post, as for my needs and bigger UIs, unique naming is not useful, that means not that i don't know how i should arrange my UI? |
Aside from as duriel says that this concern is irrelevant thanks to scene unique nodes (and node typed export variables), I'd also argue its generally not smart to build most or all of your UI nodes with a heavily reliance on anchors and margins, it massively defeats the point of containers which you can't even use in a container anyway, (which is what's encouraged and also a big reason this proposal exists) a small top level set of your main control nodes would optimally be set by anchors (preferable over directly messing with the margins in most cases anyway) and then you should rely on containers to handle the rest for you. I've only ever felt bothered to set one node's anchor on my control node trees, (even with complex UI or multiple UI regions, only the top level of the those regions has a modified anchor or margin value) that being the top level control node, in using containers I don't need to change anything else. I can't see a good reason to set anchors for even most of your controls. I've never been limited by doing this in the UI I've been able to build. |
@GrauBlitz I don't understand why you'd have a large UI scene with the all the code handled by the root, but if you're using get_node a lot you might benefit from That's how I've been doing on my pixel art app and on my music notation app, and it saves lots of runtime get_node calls. |
@mrpedrobraga Because i want to omit having 50 scripts for the nodes, this is extremely bloating, also many things are shared as this only around the Item Datatype. GetNode is the cleanest version for me with this widget count, i only do GetNode ones the scene loads and never after. |
@GrauBlitz If you put all of this in a single script, isn't it still necessary to name the variables holding # Before
@onready var vehicle_information_name: Label = $Vehicles/Information/Name
@onready var item_information_name: Label = $Items/Information/Name
# After
@onready var vehicle_information_name: Label = %VehicleInformationName
@onready var item_information_name: Label = %ItemInformationName You can even create those variables by control-dragging the nodes into the script editor. |
@timothyqiu But then i end up with the following chaos in my node tree: |
@GrauBlitz That long name problem is the trade off that must be made if you want to use Scene Unique Name currently. Making the node hierarchy bloated is a common problem with using containers. It exists even without this proposal. A clean hierarchy like I like to keep my node hierarchy clean too. But most of the time, I just end up giving up and live with container names like |
@timothyqiu Yes, that is the reason why i stick to just using the full path with GetNode and use Unique names only on the more top level nodes. |
Note as well that export node variables are also supposed to follow reoganization of your scene's node tree, so you should only need to reassign them if you delete said nodes and scenes from said node. And you really shouldn't be creating hyper-dependent scenes, if you have a lot of nodes you're keeping track of at once in a scene, that suggests you're not segregating your functionality well enough, that's a very fragile workspace and sounds extremely hard to manage. |
I agree that the entire layout system needs overhauling. When I first started trying to do layouts, I assumed that a container inside another container would stay within the bounds of its parent. That's pretty fundamental, but not for Godot. And with the lack of documentation to explain how containers work together, all the redundant and overlapping properties, I ended up wasting months working it all out. And now that stuff I worked out in 3.51 needs to be rethought because the layout system blew up in 4.0. This is turning into another Blender project where each new release means relearning everything from scratch without the help of docs because they aren't comprehensive. |
@rontarrant Containers within containers work exactly the same as other controls within containers. Containers always affect their children in the same exact way. And children always contribute to their containers in the exact same way. There is no special documentation because there is nothing special about the relationship that you describe. Also, layouts in Godot 4 work exactly the same as in 3.5. There were some renames, and some UX improvements to the editor UI, but the underlying system is exactly the same, so you don't need to rethink anything. |
If this means we get to remove redundant controls and separate menus and tree items I'm all in! I think we need to remove a bunch of controls and focus on making the ones we do keep reusable, customizable and themable. For example hbox and vbox container could be a list container that has a option whether or not it's vertical or horizontal |
You can already do that, base BoxContainer is available for use in Godot 4. |
why do we need hbox and vbox contains then? it sounds like engine bloat unless they do something that BoxContainer can't but could do |
We already had them, and they are helpful to make the layout clear when looking at the node tree alone. It's important when working with a lot of UI. |
Makes sense thankyou for explaining |
@groud alot of this can be fixed if we added option for outer padding for controls so....
becomes this...
|
Describe the project you are working on
Godot, and a 3D game
Describe the problem or limitation you are having in your project
The anchors and margin workflow is difficult to grasp for most users, and is hard to explain. It is only working when a control has no Container parent, and, while recent enhancements hid the unused properties in the inspector, it is still exposed in the API.
Also, the anchors/margin workflow has little uses. most of the time people just use a preset in the preset list and don't make complete use of the full anchors/margins capabilities.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
The idea would be to remove anchors, margin and maybe grow_direction completely from the Control nodes, and instead moving them to a Container node instead (let's call it AnchorMarginsContainer for now). The only properties allowing to position a Control would likely be position, size and pivot.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
The AnchorMarginsContainer node would allow you to position its child node exactly like would would have done with the anchors and margins workflow, but the properties would be moved from the child Control node to this parent AnchorMarginsContainer container. I guess AnchorMarginsContainer would handle all existing presets too.
This AnchorMarginsContainer could allow use to get rid of the CenterContainer and the MarginContainer nodes too, as they would fulfill almost the exact same use case.
If we don't want to get rid of more specialized containers, this AnchorMarginsContainer could also be split into different Containers if we want to. This splitting could be done according to some presets, like CenterContainer, WideContainer, FullRectContainer, etc... Those more dedicated container could even extend the generic AnchorMarginsContainer too.
Overall, this proposal would simplify dealing with Controls a lot, and fixing a bunch of issues we have with UI (the inspector could be simplified for example). The downsides I see with this proposal are the following:
If we don't want to add that node, we could also keep a boolean on Control to enable/disable the fullscreen resizing, or even make this behavior the default when you don't have a CanvasItem parent, but I fear this might be confusing IDK.
Edit: as a precision, the FullScreenContainer node would not necessarily need to extend the Control or Container class, since this node would not be positioned by a parent container, but would simply resize its Control children to the size of the screen.
Edit 2: The mockup:
![AnchorsMarginContainer](https://user-images.githubusercontent.com/6093119/181453824-6d8dd183-03e7-4f0a-b398-096471cfca79.png)
If this enhancement will not be used often, can it be worked around with a few lines of script?
No
Is there a reason why this should be core and not an add-on in the asset library?
This is core
The text was updated successfully, but these errors were encountered: