Open CsloudX opened 2 years ago
I think using the default true
for the second parameter causes Godot to adjust the offsets so that no change is visible. If you call
box.set_anchors_preset(Control.PRESET_FULL_RECT)
box.offset_left = 0
box.offset_right = 0
box.offset_bottom = 0
box.offset_top = 0
You get the expected outcome. The anchors are automatically set to 0 when using the preset via the editor.
Calling box.set_anchors_preset(Control.PRESET_FULL_RECT, false)
will show you an expanded rectangle but with the old offsets you provided.
Edited to add:
@dominiks Thanks
But I have to agree that this does not work as expected and I would have ran into the same issue, even though it's documented. I'm not sure if there is a technical reason for this behaviour or if set_anchors_and_offsets_preset is supposed to mirror the behaviour of the editor button.
This seems to still be an issue, I get some weird formatting when I try to use the set_anchors_and_offsets_preset.
Setting by above advised steps resolves this, but annoying:
This seems to still be an issue, I get some weird formatting when I try to use the set_anchors_and_offsets_preset.
Setting by above advised steps resolves this, but annoying:
I've tested a bit. Your issue seems to be the same as mine. The problem you show in your images is that the node UI/VBoxContainer is in the editor as "Layout Mode: Position" or "Layout Mode: Top Left". If you cahnge it to "Layout Mode: Center" you will see it will work. This is not an intended feature but a bug
Changing the propierty anchors_preset
solves everything. But this propierty is not meant to be used scripting, it's supposed to be internal but it was exposed by mistake.
Both anchors_preset and layout_mode are not supposed to be used in scripting. They are marked as PROPERTY_USAGE_INTERNAL, and are only relevant for the editor. They exist as properties because that's the only way to have them in the inspector and in a specific order.
Found where the mistake was. This is the function set_anchor in Control.cpp,
The problem is in
if (!p_keep_offset) { data.offset[p_side] = previous_pos - data.anchor[p_side] * parent_range; if (p_push_opposite_anchor) { data.offset[(p_side + 2) % 4] = previous_opposite_pos - data.anchor[(p_side + 2) % 4] * parent_range; } }
I feel like it is indeed changing the anchor_preset but also changing the offset just as much so it looks like nothing really happended. I'll try to code a solution for this
EDIT:
pretty sure
data.offset[p_side] = 0
I'll test tomorrow
EDIT2: tested it and set_anchor() works perfectly with PRESET_LEFT and PRESET_TOP. Will rewrite a few things so it works with RIGHT and BOTTOM.
EDIT3: Since all this code looks good (to me) this would mean the offset of RIGHT and/or BOT is changed somewhere else, or it is badly redrawn. I cannot think of any else. I give up to some legend to show up
DONE! I finally got a way to set_anchor() to work! This is the code of the function set_anchor (which is in godot/scene/gui/Control.cpp):
void Control::set_anchor(Side p_side, real_t p_anchor, bool p_keep_offset, bool p_push_opposite_anchor) {
ERR_MAIN_THREAD_GUARD;
ERR_FAIL_INDEX((int)p_side, 4);
Rect2 parent_rect = get_parent_anchorable_rect();
// real_t parent_range = (p_side == SIDE_LEFT || p_side == SIDE_RIGHT) ? parent_rect.size.x : parent_rect.size.y;
// real_t previous_pos = data.offset[p_side] + data.anchor[p_side] * parent_range;
// real_t previous_opposite_pos = data.offset[(p_side + 2) % 4] + data.anchor[(p_side + 2) % 4] * parent_range;
data.anchor[p_side] = p_anchor;
if (((p_side == SIDE_LEFT || p_side == SIDE_TOP) && data.anchor[p_side] > data.anchor[(p_side + 2) % 4]) || ((p_side == SIDE_RIGHT || p_side == SIDE_BOTTOM) && data.anchor[p_side] < data.anchor[(p_side + 2) % 4])) {
if (p_push_opposite_anchor) {
data.anchor[(p_side + 2) % 4] = data.anchor[p_side];
} else {
data.anchor[p_side] = data.anchor[(p_side + 2) % 4];
}
}
if (!p_keep_offset) {
if(p_side == SIDE_LEFT) {data.offset[0] = 0;};
if(p_side == SIDE_TOP) {data.offset[1] = 0;};
if(p_side == SIDE_RIGHT) {data.offset[2] = (data.anchor[2] - 1) * (parent_rect.size.x - parent_rect.position.x);};
if(p_side == SIDE_BOTTOM) {data.offset[3] = (data.anchor[3] - 1) * (parent_rect.size.y - parent_rect.position.y);};
}
if (is_inside_tree()) {
_size_changed();
}
queue_redraw();
}
I gotta say. It could be much better for some reasons:
Making a bunch of "if" with all possibilities (left, top, right, bottom) is kind of sad
Other functions (lets call them functions X's which I don't know all of them but I think queue_redraw or _size_changed are function X's) depend on the offsets. set_anchor changes the offset when 3º argument is false (by default is false). But when we are talking about RIGHT and BOTTOM and 3º argument is false, offset[3] (which is right) and offset[4] which is bottom) are not zero always, they are zero just when 2º argument is 0. This is because functions X's are done in such a way that they think it is apropiate that they shouldn't be zero when there is no margin when we are talking about SIDE_LEFT or SIDE_BOTTOM. I honestly disagree with how functions X's work, because if you are setting 3º argument to false then the offset should be zero always because margins are zero. The code I wrote works with those functions X's in mind but I gotta insist, it would be better if we just did offset = 0 and change those functions X's.
I haven't tried set anchor_preset or any other. They may work.
I got no time to test if it worked, so If nobody test it in a month I will be back to test it. I would like to do a pull request or call testes or something, but I don't know how github works. Anyone can tell me what the next thing to do? Is it to do a pull request?
So, sorry I'm just picking up with this right now. I am not sure the API is clear, and it seems that the current state of the API + editor is causing some confusion. There might be a few bugs but I need to investigate it a bit further.
To make it clearer:
set_anchor_preset
, like the set_anchor
function, is supposed to only modify the anchors values. So that's not supposed to be what the editor calls when setting the preset in the top toolbar menu. Instead it should call set_anchors_and_offset_preset
, as this function is supposed to both set the anchors and the offsets to good values. From a quick look to the code, it seems like the editor only changes the anchor_preset
value, which is not super clear.p_keep_offset
is a bit weirdly named, but the idea behind it is that, when you modify an anchor, the corresponding side of the control gets moved accordingly (like, the offset is an absolute value from the anchor position, which is relative to the parent's size). p_keep_offset
is supposed to change the offset value accordingly, so that control's side's position stays the same, despite the anchor value being changed. From a quick test, there are indeed a few bugs here and there, and I need to figure out what broke things. I think the set_anchor
function is likely fine.
I'll have a deeper look to that when I get the time to.
Ok, so offset is different from margin. Let's suppose we have a very simple scene of controls. Is there an intuitive way to see how much the offset is? Here are some examples of what I feel is intuitive: You can see that those properties can be easily drawn, but I am not so sure about offset.
I discovered offset[SIDE_RIGHT]
(and offset[SIDE_BOTTOM]
) follow this formula. But still, I can't figure a way to draw it:
I already did a pull request that solves set_anchor completely.
I rather have other property different from offset because it feels inintuitive (at this moment), so I may propose to change how distance with anchors are calculated, and erease completely offset from code (maybe substitute it to something more intuitive).
What do you think?
Ok, so offset is different from margin. Let's suppose we have a very simple scene of controls. Is there an intuitive way to see how much the offset is? Here are some examples of what I feel is intuitive:
Hmm, this drawing does not seem right to me. The anchors are usually within the boundaries of the parent, and they don't have anything to do with the parent positioning (they only impact the child control ones). Here is a better representation: (here the parent is the whole window but it works the same for having a parent control)
The position
is not depicted on that picture, but it is basically the position of the child control relative to the parent's one. So here, and in general, position = Vector2(left_anchor * parent_size + left_offset, top_anchor * parent_size + top_offset)
Ok now I understand. Totally my bad! I was using wrongly offset. I will update my PR. I may also fix set_anchor_preset and the others.
Godot version
v4.0.beta2.official [f8745f2f7]
System information
Windows 10 64bit
Issue description
In the docs, it say:
In the 2D editor, I can set the anchors preset as expect:
And I want set preset with code:
But there wasn't any effect:
Steps to reproduce
Please run the reproduction project
Minimal reproduction project
AnchorTest.zip