Why do some nodes use "position" and others use "rect_position"?
Asked Answered
F

1

7

What's the technical reason for this? It seems strange to me that they can't all just use position. Is it a legacy thing?

Firedog answered 20/7, 2021 at 20:28 Comment(0)
L
9

There are three relevant sets of nodes. Those that extend:

  • Control, it is here where you find rect_position.
  • Node2D, it is here where you find position.
  • Spatial, and here you only find transform.

These nodes are color coded. All Controls are green, all Node2D are blue, and all Spatials are red. And yes, that is an accessibility concern regarding color vision deficiency. There is a call for an icon redesign here: Tweak editor node icons to be distinguishable without relying on color (colorblind-friendly).

And yes, there is some naming mess. For starter 2D nodes say "2D" in the name, but 3D nodes don't (e.g. Camera vs Camera2D). That in particular has changed for Godot 4.0.

If you have ideas of how the naming can be better, you may open a proposal (as an issue on github).

Let us talk about how the positioning of these sets of nodes differ…


On Transforms

Spatial nodes use Transform. In fact, some people has proposed renaming the transform property to "position". Which, as you would know, is not the same thing, because a Transform not only has position but also rotation, scaling, and such.

I know you didn't ask about transform. However, you need to know that a Node2D also has a transform property, of type - you gusseted - Transform2D. And this is how a Node2D is actually positioned. Meanwhile position, rotation, rotation_degrees and scale are for ease of use.


Positioning Controls

Spatial and Node2D have transform. Guess what? Control does not. Instead a Control is intended to be positioned in one of these ways:

  • It is placed in a Container (Which are also Controls), and the Container decides how it is positioned, taking into account "Size Flags" (that is what they are for).
  • By anchors (anchor_*) and margins (margin_*). The abstract is that the anchors are factors, and the margins are offset. For example, the leftmost part of the control will be positioned at anchor_left * parent_width + margin_left.
  • By rect_position and rect_size. Where rect_position is position from the top left corner of parent.

One caveat: rect_min_size is uphold. And yes, there is also rect_rotation and rect_scale which throw a wrench on the above explanation, but it works as one would imagine.

And I say intended because you can mix these. For example, you can position a control by anchors and margins, or by placing it in a Container, but then animate the rect_position for effect.


As you can see, position and rect_position are two different things. It is not the case that some nodes got stuck with one name or the other or something like that.

I should also mention that there are "global" version of these properties, because they are positioned respect to their parent.


On the prefix

Ok, they are different, but they do - to a first approximation - the same thing. Why can't they have the same name?

Beyond it being a reminder that they aren't the same thing. There is a reason to prefix properties in Godot. And that is to ease grouping them in the inspector panel.

For example, the "Anchor" group will have all the properties which name begin with anchor, and that prefix is not shown on the name of the property.

Similarly, one of the groups you find is "Rect". And yes, rect_position is inside. Along side related properties. This also helps in discovering these properties from the code editors, since they would show up together in autocomplete.

This all should make it easier for new user to figure out how Control positioning works. However, let us be honest, it is not working great. See also the proposal: Redesign how user interface (Controls) scaling is presented to the user.


Controls inside Node2D

You can - and you may need to - place Controls inside of a Node2D. For example, if you want a Label or a ProgressBar (which are Control) following a Node2D.

Godot will handle the position. But you will find problems with scaling and centering, because Node2D don't have a size that the Controls can use (some - such as Sprite - have a visual size as virtue of their Texture, which is not exposed as a property, and Control does not use it).

It is there where may want to hack it with some code that mixes rect_position and position.

Centering a Control in a Node2D is not hard per se (there are Containers, anchors and margins, and good old hand positioning). The problem is keeping it centered when the it changes size. In particular when you add more text to a Label, which insist in growing to the right despite all odds. But do not fret, what you need is to handle the resized signal and there call set_anchors_and_margins_preset, which is what you do from the "Layout" option in the editor.


Node2D inside Controls

You may also place a Node2D inside a Control, and again Godot will handle the position. You may want to set rect_clip_content on the Control.

However, placing a Node2D inside a Container does not work properly. The Container cannot handle Node2D children.

If you are trying to do that, chances are that you need to do one of these:

  • Change a Sprite (a Node2D) to a TextureRect (a Control).
  • Change a TouchScreenButton (a Node2D) to a Button (a Control) and enable touch emulation in Project Settings -> Input Devices -> Pointing.
  • Have a Viewport with a Camera2D along side whatever Node2D you want to display there. Which I recommend to make as a separate scene for ease of design. Don't forget to give size to the Viewport. And then, either:
    • Place that Viewport inside of a ViewportContainer (a Control). You may want to set the stretch of the ViewportContainer to true.
    • Or use a TextureRect with a ViewportTexture.

While I'm at it, I'll also suggest to make the root of your main scene a Node (not any derived type), and then use CanvasLayers to separate the UI from the game world. That will prevent the Camera2D from affecting the UI.

Laurustinus answered 20/7, 2021 at 23:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.