You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +00:00
Fix #100536: Control set_position resizes offsets/anchors
The set_position method computes the anchors/offsets to match a rectangle at the given position with size "size_cache". However, when the Control's combined minimum size is larger than the size obtained through the offsets and anchors, "size_cache" is set to be as large as the combined minimum size. Therefore, when position is set while the combined minimum size is larger than the rectangle given by the anchors and offsets, it would resize these two fields, which would then stop the Control from shrinking when its combined minimum size decreased. To fix this, set_position now uses the size given by the offsets and anchors instead of the "size_cache" field. This way, the rectangle denoted by the offsets and anchors is simply moved, without being resized, enabling the Control to shrink automatically when its combined minimum size decreases. I also added a test case to ensure that the Control shrinks correctly after setting its position while it has a larger custom minimum size than the one obtained through the offsets and anchors.
This commit is contained in:
@@ -867,6 +867,13 @@ void Control::_compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (
|
||||
r_offsets[3] = p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y);
|
||||
}
|
||||
|
||||
void Control::_compute_edge_positions(Rect2 p_rect, real_t (&r_edge_positions)[4]) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
real_t area = p_rect.size[i & 1];
|
||||
r_edge_positions[i] = data.offset[i] + (data.anchor[i] * area);
|
||||
}
|
||||
}
|
||||
|
||||
/// Presets and layout modes.
|
||||
|
||||
void Control::_set_layout_mode(LayoutMode p_mode) {
|
||||
@@ -1392,10 +1399,13 @@ void Control::set_position(const Point2 &p_point, bool p_keep_offsets) {
|
||||
}
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
real_t edge_pos[4];
|
||||
_compute_edge_positions(get_parent_anchorable_rect(), edge_pos);
|
||||
Size2 offset_size(edge_pos[2] - edge_pos[0], edge_pos[3] - edge_pos[1]);
|
||||
if (p_keep_offsets) {
|
||||
_compute_anchors(Rect2(p_point, data.size_cache), data.offset, data.anchor);
|
||||
_compute_anchors(Rect2(p_point, offset_size), data.offset, data.anchor);
|
||||
} else {
|
||||
_compute_offsets(Rect2(p_point, data.size_cache), data.anchor, data.offset);
|
||||
_compute_offsets(Rect2(p_point, offset_size), data.anchor, data.offset);
|
||||
}
|
||||
_size_changed();
|
||||
}
|
||||
@@ -1682,14 +1692,8 @@ Size2 Control::get_combined_minimum_size() const {
|
||||
|
||||
void Control::_size_changed() {
|
||||
Rect2 parent_rect = get_parent_anchorable_rect();
|
||||
|
||||
real_t edge_pos[4];
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
real_t area = parent_rect.size[i & 1];
|
||||
edge_pos[i] = data.offset[i] + (data.anchor[i] * area);
|
||||
}
|
||||
|
||||
_compute_edge_positions(parent_rect, edge_pos);
|
||||
Point2 new_pos_cache = Point2(edge_pos[0], edge_pos[1]);
|
||||
Size2 new_size_cache = Point2(edge_pos[2], edge_pos[3]) - new_pos_cache;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user