godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.17k stars 98 forks source link

Remove the anchors and margin workflow from Control nodes, and move the feature to containers. #4994

Open groud opened 2 years ago

groud commented 2 years ago

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:

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

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

Zireael07 commented 2 years ago

+1 to full screen container, quite recently I had to go through all of my projects to make the HUD adapt to screen size

SilencedPerson commented 2 years ago

Honestly, this is kinda wild idea and I would probably have to try it out to know if I like it.

zinnschlag commented 2 years ago

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.

balloonpopper commented 2 years ago

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?

1) The current presets seem to fall short for me for a couple of reasons as they seem to set the nodes up with fixed coordinates when you select them. This doesn't help when dealing with other resolutions (if I have something centred on my widescreen monitor, I want it centred on non widescreen monitors as well for example). It might work on other resolutions, but I assume the pixel settings it configures will be maintained on any machine running the project, regardless of the resolution. 2) Margins etc don't seem to account for ratios. If I want a screen that's divided in 2 with the left panel 40% of the screen width and the right 60%, I would want that preserved across resolutions. Support for percentages rather than fixed pixel sizes would address this (unless there's some way to do this I'm not aware of).

YuriSizov commented 2 years ago

@YuriSizov Since this is a compatibility breaking change, is 4.x really appropriate? Sounds more like 4.0 to me.

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 5.0 😛

groud commented 2 years ago

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 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.

The current presets seem to fall short for me for a couple of reasons as they seem to set the nodes up with fixed coordinates when you select them. This doesn't help when dealing with other resolutions (if I have something centred on my widescreen monitor, I want it centred on non widescreen monitors as well for example). It might work on other resolutions, but I assume the pixel settings it configures will be maintained on any machine running the project, regardless of the resolution.

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.

Margins etc don't seem to account for ratios. If I want a screen that's divided in 2 with the left panel 40% of the screen width and the right 60%, I would want that preserved across resolutions. Support for percentages rather than fixed pixel sizes would address this (unless there's some way to do this I'm not aware of).

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).

dploeger commented 2 years ago

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.

nezvers commented 2 years ago

Anchors = percentual distance from a side. Margin = pixel distance from a side. Container inherited nodes are controlling child node size, anchor & margin. Childs can influence it with flags. I don't see anything confusing.

groud commented 2 years ago

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)

The proposal is to move the anchors an margin/offset properties, which are rarely used, from outside Control to a dedicated Container node instead.

Do we have information on what specifically is confusing to most users? Maybe it's just the terminology or something. I don't see anything confusing.

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.

nezvers commented 2 years ago

Why not simply hide those parameters when they are controlled by parents?

Zireael07 commented 2 years ago

@nezvers That already happens in 4.x

dploeger commented 2 years ago

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. 😊

groud commented 2 years ago

Why not simply hide those parameters when they are controlled by parents?

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.

dploeger commented 2 years ago

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)

YuriSizov commented 2 years ago

A highly controversial question I guess, but what is the point of not using containers in the first place?

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.

TheDuriel commented 2 years ago

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:

MarginContainer (Full Rect Preset)
  HBoxContainer
    VBoxContainer (Left screen column)
      UI Element top left corner
      UI Element left side
      UI Element bottom left corner
    VBoxContainer (Center screen column)
      UI Element top edge
      UI Element center
      UI Element bottom edge
    VBoxContainer (Right screen column)
      UI Element top right corner
      UI Element left side
      UI Element bottom right corner

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:

Root Node
      UI Element top left corner
      UI Element left side
      UI Element bottom left corner
      UI Element top edge
      UI Element center
      UI Element bottom edge
      UI Element top right corner
      UI Element left side
      UI Element bottom right corner

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:

  1. Collapse the size flag configuration into more user readable settings. Instead of: "Fill, Expand, Expand and FIll" We can use more verbose language in the UI.

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.)

  1. Change the default behavior of Control nodes to expand to fill the entire viewport.

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.

  1. Refactor containers

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. Growth Direction: All Directions, BottomRight, Bottom, Left, etc.

To, going back to my very first example of current godot, turn our tree into this:

Root Node/Viewport/CanvasLayer
      AlignmentContainer (Align: TopLeft, Grow: BottomRight)
        MarginContainer (Margin from the left and top edge of the screen.) (AlignmentContainer might have the same functionality?)
          UI Element
<Repeat 8 times for different configurations>

Here is hoping some of these ramblings make sense.

groud commented 2 years ago

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.

Well, your example is kind of wrong here, since with the new AnchorMarginContainer, the hierarchy would be something like that:

FullScreenContainer -> Resize the child as the Viewport screen size
   AnchorMarginContainer -> top left corner preset
      UI elements -> likely several nested containers  
   AnchorMarginContainer -> top left side preset
      UI elements -> likely several nested containers  
   AnchorMarginContainer -> top left bottom preset
      UI elements -> likely several nested containers  
   etc, ...

While right now it's something like:

Root:
   UI Element top left corner
   UI Element left side
   UI Element bottom left corner
   etc, ...

It's basically one level deeper. But it's not really a "batshit crazy amount of Containers", at least with that proposal. But even then, I think it's not that bad anyway, positionning UI elements on the screen can take a few nodes, from my experience the ton of nodes will allways end up deeper in the tree, where you need to use a ton of Containers to position little UI elements.

Just to get the correct layout. However, containers grow with their contents size

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.

Containers already manage control node growth directions.

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.

TheDuriel commented 2 years ago

My first examples, before the line -, were about Godot in its current form in 2.x-3.x.

And this AnchorMarginContainer would not do that either.

Then it plainly is not a container. It's a Anchor. Arguably, it should not even be a control node at that point.

groud commented 2 years ago

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 :shrug:. 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.

TheDuriel commented 2 years ago

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.

alfredbaudisch commented 2 years ago

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.

UgisBrekis commented 2 years ago

Building complex UI is my bread and butter and Godot UI system is incredibly good and flexible, absolute joy to use. I don't intend to sound mean, but I re-read proposal 3x times and I still don't get how that is any better than the existing approach, so it's a big NO from me.

I think it's really important to understand where the feedback is coming from; to me it sounds exactly like people's first reaction to GDScript without understanding how powerful it is...

TheDuriel commented 2 years ago

@UgisBrekis The proposal and feedback in this case comes from at least one engine contributor working on the Godot Editor itself.

My opinions similarly come from making tools in Godot similar to the skyrim creation kit and the godot editor itself. As well as UI heavy games in need of complex layout rules.

In the field, it is pretty much fact that most people do not engage with the margins system. And do not understand how to use it to their advantage. Size flags are already a pretty big hurdle. You see it every single day on the discord, from people that are following tutorials from the documentation and third parties.

A cleanup of the tools, not a reduction in features, is what is desired here.

Goal: Same or better functionality. Easier to understand workflow.

mrpedrobraga commented 2 years ago

I work with UI constantly, and after understanding how anchors work it's almost second nature to design my UI -- almost, because I still second-guess myself from time to time.

It may be the case that a complete overhaul and redesign is what we need, with more clean nodes and all, but, I'd like to give it my two cents (and it's still useful for 3.x, too)

We need better ways to explain that:

For the first one, I think it would benefit from a custom editor that allowed you to see the Rect (similar to the StyleBoxes editor). Be it on the inspector, or on the main viewport (we already have those four little green thingies but they are easy to miss and don't draw the relationship).

Taking inspiration from game design show don't tell, on the docs, we would probably benefit from a GIF showing the behaviour between containers rescaling and the percentage-rect updating with it for different values of the anchors. It would be minimal, showing both rects using something like draw_line.

Additionally, a diagram that shows the margin offsets. In other programs, it usually shows an arrow or a line that make obvious the margin:

An example of spacers showing the distance from the border.

I guess there's probably a good reason as to why offsets are kept negative from the right and bottom sides, but with a custom anchor-and-offsets editor, they could be changed there at least visually.

As for bloat, well, maybe it is a good idea to have an "AnchorsMarginsContainer," since I can't remember the last time I used Anchors+Offsets that wasn't with Control, but even then, domain-specific UI could reduce the size it takes on the inspector.

Example of how Figma does it It doesn't need to be like the image, but something (I can mock it up later).

I believe UI is a very important part of just about every game and I love using the editor for everything; Godot could take a lead in regards to designing UI in its editor.

Zireael07 commented 2 years ago

The weirdest thing with anchors IMO is the fact that changing position changes anchors. I'd painstakingly set them up, then move the position and boom, anchors reset to default 0 even when I had them nicely set up. That's why a FullScreenContainer (or something else that is effectively the same) Is what I use when I need stuff that sticks to screen size, or a 40/60 split, or anything....

(As an aside, I have a control child of a viewportcontainer and it hid the position value in 4.x, it took me a long time to figure out where it was supposed to be placed. Shouldn't viewportcontainer be an exception to the "hide values" rule?)

TheDuriel commented 2 years ago

Shouldn't viewportcontainer be an exception to the "hide values" rule?)

Not really. You couldn't work with viewport contents before either.

fire-forge commented 2 years ago

Simplifying the Controls, anchor and margins, and containers system as much as possible while still having good usability and as much flexibility as possible is great. I'm not sure this is the best way to do it though. I almost always use Containers and dynamic layouts, but I do find anchors and margins to be useful in some situations.

I think it's really important to understand where the feedback is coming from; to me it sounds exactly like people's first reaction to GDScript without understanding how powerful it is...

@UgisBrekis This proposal is actually made by the person who created the new TileMap and TileSet system for 4.0, so not exactly a beginner 😅

groud commented 2 years ago

I feel like there's a misunderstanding that might come from the title. This proposal does not want to REMOVE anchors and margins, it wants to move them to a dedicated Container instead. So this system would be as powerful as it is right now (if not more in some cases)

Building complex UI is my bread and butter and Godot UI system is incredibly good and flexible, absolute joy to use. I don't intend to sound mean, but I re-read proposal 3x times and I still don't get how that is any better than the existing approach, so it's a big NO from me.

It is better in the way it does clean a lot the Control node properties and moves everything elsewhere, since most of the time anchors aren't needed.

A cleanup of the tools, not a reduction in features, is what is desired here. Goal: Same or better functionality. Easier to understand workflow.

That's exactly the goal here. I think this change could help us getting rid of a lot of bloat in the Control node while still keeping the exact same features.

I'll try to make a mockup of the changes it would make. Maybe it will make clearer what this brings to the UX.

QbieShay commented 2 years ago

I second what has been said so far - I don't think this is a proposal that would effectively improve control nodes.

Spartan322 commented 2 years ago

I personally reserve judgement on this change since in most cases I don't tend to specifically set any of these more then once in the root of my UI scenes, it would tend to optimize control's, specifically when you use containers, since there is very little reason to have more then one node set for these when you use containers. (least in using containers to organize my UIs) But I reserve personal judgement in order to wait for implementation, it seems a lot more drastic then it reasonably should be, I'm not sure what to say about it without feeling the implementation of it.

Diddykonga commented 2 years ago

Maybe we just merge Node2D and Control, and remove CanvasItem ( ͡° ͜ʖ ͡°)

me2beats commented 2 years ago

I'm for leaving anchors/margins as is, remaining it in the Control or test the idea first very well, if it can break something, for example the editor itself.

Anchors and margins are instructions to place the control node relatively to its parent. This is quite flexible in cases when you add the control node/scene to a parent of an arbitrary size - you don't want to set the position manually (say centered or bottom wide) with code, you can simply set the anchor/margin preset and save the scene. You can also set anchor/margin_preset from code.

  • If a Control is a child of a Container, anchors and margin values are useless.

this is indeed may be confusing. But the properties could just be hidden.

The containers approach already adds some noise to scenes. Maybe it would be better if we can add some components/behaviors to controls/nodes, but we can't.

So having anchors/margins in Control looks like a good compromise imo

me2beats commented 2 years ago

If a Control is a child of a Container, anchors and margin values are useless.

Btw this can be said for position, rotation and scale as well. if the control is inside a container, these properties are omitted

groud commented 2 years ago

Alright, I made a mockup illustrating the advantages and drawbacks of that approach. The "before" part is what is right now in Godot 4: AnchorsMarginContainer As you can see, it needs a little bit more nodes, especially when positioning according to the screen, but it cleans up the Control inspector a lot (not even mentioning the API and documentation cleanups). As a side note I believe it may allow us to move the position property from Control to CanvasItem, since they would kind of work the same as Node2D with the proposal.

I think the proposal makes most sense only if anchors and margins are not used often. From my experience, the vast majority of my Controls are positioned using Containers, so I personally would not mind anchors and margin positioning to be a little bit more tedious to setup if it simplifies the workflow for all other use cases.

timothyqiu commented 2 years ago

How will multiple nodes inside a AnchorMarginsContainer be arranged? Or should AnchorMarginsContainer only have one child?

groud commented 2 years ago

How will multiple nodes inside a AnchorMarginsContainer be arranged? Or should AnchorMarginsContainer only have one child?

AnchorMarginsContainer would be designed to have only one child, like AspectRatioContainer, CenterContainer, MarginContainer, PanelContainer or ScrollContainer. But well, if you add more, they would be drawn on top of each other.

If we allow AnchorMarginsContainer to have more children with different positions, then it means we would have to store the values in each child (like sizing flags), but that would defeat the purpose of this proposal. ^_^"

timothyqiu commented 2 years ago

Ah, I understand now. So instead of each control managing their own anchors and margins (and giving up if they are in a container), now we add an additional container to get that behavior.

It does make Control logic simpler. Although it also makes the tree hierarchy more complex if used often, with Unique Node Name, I think tree complexity won't be that important now ;)

groud commented 2 years ago

Ah, I understand now. So instead of each control managing their own anchors and margins (and giving up if they are in a container), now we add an additional container to get that behavior. It does make Control logic simpler. Although it also makes the tree hierarchy more complex if used often, with Unique Node Name, I think tree complexity won't be that important now ;)

Exactly, you nailed it! :)

eh-jogos commented 2 years ago

I really don't like this one. I use a lot of "Debug Labels" or other debug Controls inside Node2Ds, and having to turn use case 2 into 3 nodes instead of one seems really bad.

Even when I'm using a label on it's own inside a Node2D I still want to be able to control its grow_direction for example, and I don't care about the screen size, anchors or margins. So If I'm only able to use grow_direction in the AnchorMarginsContainer, and it only works inside a FullScreenContainer, I can never do that anymore, as the position of the Label will be based on the screen due to FullScreenContainer, and not on the Node2D.

For the inspector, you can always just close each "group" in the anchor presets if you don't need it and the inspector will look almost as clean as with this proposal (though not the API and documentation)

I also agree with @mr-pedro-braga comment that changing some nomenclature and some custom editor to make it clearer that anchors are percentage based, and visualization on the editor of what each property is controlling is best to make users understand and the system less confusing. Though all of his suggestions could be applied to the AnchorMarginsContainer as well, it's not a mutually exclusive thing.

But what he pointed out were the main difficulties I had when learning to deal with controls, and once I could visualize what each property was actually responsible for, I started using anchors and margins in more creative ways and felt I had a lot more control over the UI, even sometimes feeling that Containers were not necessary, or complementing the use of containers.

This seems like stripping A LOT of "power" from control nodes, and while you could have it all back by using a AnchorMarginsContainer node as a parent, I think the FullScreenContainer > AnchorMarginsContainer > Control solution isn't a good one. Hence my example at the start, I might want to use only grow_direction, or only anchors and offsets, or containers, and today we have a lot of freedom in using all these approaches and mixing them which I think it's good.

Control nodes are confusing because they are powerful tools to solve a very complex problem that is UI. Making them easier to use by making the complexity of them easier to see and understand like in @mr-pedro-braga's suggestion is a better solution in my opinion.

PoisonousGame commented 2 years ago

3.x The biggest confusion is that the size and position of the child nodes of a container are determined by the parent container, but the child nodes can still adjust anchor points and margins. Although they are invalid, they are not disabled. But if you move these properties to AnchorMarginContainer, according to common sense, the child nodes of the container is not able to control the size and position, now add an AnchorMarginContainer to break this common sense, may cause confusion. Moreover, this is only based on your own experience and preference, can not represent the public. If non-container nodes need to use anchors and margins to adjust the position, you need to add an AnchorMarginContainer, I think the complexity and tedium increases.

groud commented 2 years ago

Oops misclicked, didn't mean to close the proposal.

Even when I'm using a label on it's own inside a Node2D I still want to be able to control its grow_direction for example, and I don't care about the screen size, anchors or margins. So If I'm only able to use grow_direction in the AnchorMarginsContainer, and it only works inside a FullScreenContainer, I can never do that anymore, as the position of the Label will be based on the screen due to FullScreenContainer, and not on the Node2D.

Ah that's a good point. I guess that grow_direction could be kept in Control then.

For the other points that's fine. I understand that a lot of users got used to the fact that control is a big, all-in-one bloated node and don't want that to change, as once mastered it's very powerful indeed. But I still think that the cleanup, even if making some use cases more complicated, is still worth. I understand your experience would make this change more difficult for you, but I think a majority of users still struggle to understand how this system works and don't fully use it. That's why I think it should not be in the Control node itself.

Zireael07 commented 2 years ago

@eh-jogos I use a ton of similar debug labels and really, adding that one more node isn't an issue.

Re grow direction, I don't have an opinion either way.

Especially having seen the picture, I like this proposal a lot - it should make it easier to make responsive designs and it makes control cleaner/smaller (in 90% of cases this whole section of inspector is "I don't care scroll past" for me)

E: /s scare->care

eh-jogos commented 2 years ago

@groud

Ah that's a good point. I guess that grow_direction could be kept in Control then.

Had forgotten this was an option, and would solve that point easily.

For the other points that's fine. I understand that a lot of users got used to the fact that control is a big, all-in-one bloated node and don't want that to change, as once mastered it's very powerful indeed. But I still think that the cleanup, even if making some use cases more complicated, is still worth. I understand your experience would make this change more difficult for you, but I think a majority of users still struggle to understand how this system works and don't fully use it. That's why I think it should not be in the Control node itself.

Yeah, I'm trying to think of other cases were this proposal would get in my way badly, and haven't been able to think of concrete cases besides the one I pointed out about grow direction. I think my favorite option would still be @mr-pedro-braga visualizations like that "spacing pro tips" image. But again, that is independent from this proposal, and could go alongside it, implemented in the AnchorMarginsContainer.

Yeah, I might have been more scared of the change than needed

eh-jogos commented 2 years ago

@Zireael07

@eh-jogos I use a ton of similar debug labels and really, adding that one more node isn't an issue.

My issue was not adding one more node, but having to add two more nodes and still that workflow being impossible.

But as @groud said, it would be easily fixable by keeping grow_direction on Control, since it's useful apart from anchors and margins. And if I understood it correctly then I would be able to use it like today, just adding a single Label and just setting the grow direction on it.

TheDuriel commented 2 years ago

by keeping grow_direction on Control, since it's useful apart from anchors and margins.

Is it? Where?

All container nodes completely override the growth behavior, making it only functioning in the case of anchor based positioning.

I suppose you could argue "what should happen if a control node changes size, and is not a child of a container or anchor" to which I would reply: "Why do you have free floating unmanaged control nodes? And if for some reason that's a legit use case; they should grow evenly centered on their 'position' to cause the least offence."

Keeping growth direction inside of general control nodes is only useful, if you ALSO have the pivot point / anchoring still in all control nodes.

QbieShay commented 2 years ago

Because many people here outlined the issue with animating GUI, i think it could make everyone's life easier to have an offset property that's applied after margins?

TheDuriel commented 2 years ago

As for animating, I'd say it's like this, just like it always has been:

You animate the root object. In this case you gain the flexibility of the anchor and ui element itself being separate. You can move the anchor and scale the element separately.

The real problem with animations is the the inflexible rect_pivot_offset. There used to be a issue around turning that into a percentage value. Which would honestly alleviate a lot of issues. (It controls around which point rotation, scale, etc are applied.)

For truly intricate UI animations, a RemoteTransform approach works best. Where you completely separate the UI element from it's tree position. (Think about dragging a panel from one place to another, floating UI elements. Often desired for fancy animations.)

eh-jogos commented 2 years ago

@TheDuriel

by keeping grow_direction on Control, since it's useful apart from anchors and margins.

Is it? Where?

Here goes a simple example for you: image As you can see on the image I have a VBoxContainer for a list of debug labels (2) that float above a character's head (1). The messages I send to these debug labels can make the VBoxContainer grow in any direction but I don't want it to grow over the character, so I set grow direction to both on horizontal and to top on vertical (3), so that its base is fixed in place an it will only grow up.

At the same time this node is a child of a CharacterBody2D, so I really don't care about it's anchors or margins.

If I had to add a FullScreenContainer to be able to use an AnchorsMarginContainer inside of it to be able to use grow_direction, it would actually break the purpose of all of this, as FullScreenContainer would break the relation between my CharacterBody2D and the debug UI.

But this is not only useful for debug UI, in another project I did a similar thing with an HBoxContainer and status indicators that could appear above a character's head, like poison, sleep, etc..

All container nodes completely override the growth behavior, making it only functioning in the case of anchor based positioning.

I suppose you could argue "what should happen if a control node changes size, and is not a child of a container or anchor"

As I showed above, for any UI that floats above a character's head, for example. This change will also affect containers, not only the pure Control node, and for V/HboxContainers, while you can set their internal alignment, the direction they expand to is set by grow_direction.

to which I would reply: "Why do you have free floating unmanaged control nodes? And if for some reason that's a legit use case; they should grow evenly centered on their 'position' to cause the least offence."

Not really, centered is one possible solution, grow_direction gives you that and all the others. What if it's an element that should float to the left side of a character, you might want it's horizontal grow direction to be "Begin" so that it "aligns to the right".

Keeping growth direction inside of general control nodes is only useful, if you ALSO have the pivot point / anchoring still in all control nodes.

I don't know the details about implementation, but for me grow direction is really useful in UI regardless if I set the anchors, or even if I have anchors to set or not.

TheDuriel commented 2 years ago

Your example under the new system would be:

Anchor > Anchor: Point, Positioning: Up, Growth: Up
  VBoxContainer > Align: End
      Labels

FullScreenContainer to be able to use an AnchorsMarginContainer inside of it

That was never proposed here. They're two entirely separate things, you wouldn't combine them.

TheDuriel commented 2 years ago

InterfaceAnchor (MarginsAndAnchorContainer)

Represents a point in space. Has a single Position vector. Basically works like a Position2D node.

InterfaceZone (FullScreenContainer)

Represent a rectangular area.

Control Nodes added as Children will be made to expand to fill the entire area. (Default assumption is that you would use Containers.) Control Nodes can use their Expand flags (I previously reiterated how these can be cleaned up) to determine how they fill the Zone.


This is what I am imagining.