Fix layout rectangle computations
Makes use of growth directions for all size changes, not just minimum ones.
This commit is contained in:
@@ -1115,10 +1115,10 @@
|
||||
The node's global position, relative to the world (usually to the [CanvasLayer]).
|
||||
</member>
|
||||
<member name="grow_horizontal" type="int" setter="set_h_grow_direction" getter="get_h_grow_direction" enum="Control.GrowDirection" default="1">
|
||||
Controls the direction on the horizontal axis in which the control should grow if its horizontal minimum size is changed to be greater than its current size, as the control always has to be at least the minimum size.
|
||||
Controls the direction on the horizontal axis in which the control should grow or shrink if its horizontal size is changed.
|
||||
</member>
|
||||
<member name="grow_vertical" type="int" setter="set_v_grow_direction" getter="get_v_grow_direction" enum="Control.GrowDirection" default="1">
|
||||
Controls the direction on the vertical axis in which the control should grow if its vertical minimum size is changed to be greater than its current size, as the control always has to be at least the minimum size.
|
||||
Controls the direction on the vertical axis in which the control should grow or shrink if its vertical size is changed.
|
||||
</member>
|
||||
<member name="layout_direction" type="int" setter="set_layout_direction" getter="get_layout_direction" enum="Control.LayoutDirection" default="0">
|
||||
Controls layout direction and text writing direction. Right-to-left layouts are necessary for certain languages (e.g. Arabic and Hebrew). See also [method is_layout_rtl].
|
||||
@@ -1568,13 +1568,13 @@
|
||||
[b]Note:[/b] If the control has received [signal mouse_entered] but not [signal mouse_exited], changing the [member mouse_filter] to [constant MOUSE_FILTER_IGNORE] will cause [signal mouse_exited] to be emitted.
|
||||
</constant>
|
||||
<constant name="GROW_DIRECTION_BEGIN" value="0" enum="GrowDirection">
|
||||
The control will grow to the left or top to make up if its minimum size is changed to be greater than its current size on the respective axis.
|
||||
The control will grow/shrink to the left or top if its size is changed to be larger/smaller than its current size on the respective axis.
|
||||
</constant>
|
||||
<constant name="GROW_DIRECTION_END" value="1" enum="GrowDirection">
|
||||
The control will grow to the right or bottom to make up if its minimum size is changed to be greater than its current size on the respective axis.
|
||||
The control will grow/shrink to the right or bottom if its size is changed to be larger/smaller than its current size on the respective axis.
|
||||
</constant>
|
||||
<constant name="GROW_DIRECTION_BOTH" value="2" enum="GrowDirection">
|
||||
The control will grow in both directions equally to make up if its minimum size is changed to be greater than its current size.
|
||||
The control will grow/shrink in both directions equally if its size is changed to be larger/smaller than its current size.
|
||||
</constant>
|
||||
<constant name="ANCHOR_BEGIN" value="0" enum="Anchor">
|
||||
Snaps one of the 4 anchor's sides to the origin of the node's [code]Rect[/code], in the top left. Use it with one of the [code]anchor_*[/code] member variables, like [member anchor_left]. To change all 4 anchors at once, use [method set_anchors_preset].
|
||||
|
||||
+38
-29
@@ -918,32 +918,49 @@ Control::GrowDirection Control::get_v_grow_direction() const {
|
||||
return data.v_grow;
|
||||
}
|
||||
|
||||
void Control::_compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]) {
|
||||
void Control::_compute_layout_rect(Rect2 p_rect, bool p_keep_offsets) {
|
||||
Size2 parent_rect_size = get_parent_anchorable_rect().size;
|
||||
ERR_FAIL_COND(parent_rect_size.x == 0.0);
|
||||
ERR_FAIL_COND(parent_rect_size.y == 0.0);
|
||||
|
||||
if (p_keep_offsets) {
|
||||
// If computing anchors, we need to ensure the parent rect size is valid to avoid division by zero.
|
||||
ERR_FAIL_COND(parent_rect_size.x == 0.0);
|
||||
ERR_FAIL_COND(parent_rect_size.y == 0.0);
|
||||
}
|
||||
|
||||
real_t x = p_rect.position.x;
|
||||
real_t y = p_rect.position.y;
|
||||
|
||||
if (_get_layout_mode() != LayoutMode::LAYOUT_MODE_CONTAINER) {
|
||||
float left_grow_factor =
|
||||
(data.h_grow == GROW_DIRECTION_BEGIN) ? 1.0f
|
||||
: (data.h_grow == GROW_DIRECTION_END) ? 0.0f
|
||||
: 0.5f;
|
||||
float top_grow_factor =
|
||||
(data.v_grow == GROW_DIRECTION_BEGIN) ? 1.0f
|
||||
: (data.v_grow == GROW_DIRECTION_END) ? 0.0f
|
||||
: 0.5f;
|
||||
|
||||
Size2 size_diff = p_rect.size - data.size_cache;
|
||||
|
||||
x -= size_diff.x * (is_layout_rtl() ? (1.0f - left_grow_factor) : left_grow_factor);
|
||||
y -= size_diff.y * top_grow_factor;
|
||||
}
|
||||
|
||||
if (is_layout_rtl()) {
|
||||
x = parent_rect_size.x - x - p_rect.size.x;
|
||||
}
|
||||
r_anchors[0] = (x - p_offsets[0]) / parent_rect_size.x;
|
||||
r_anchors[1] = (p_rect.position.y - p_offsets[1]) / parent_rect_size.y;
|
||||
r_anchors[2] = (x + p_rect.size.x - p_offsets[2]) / parent_rect_size.x;
|
||||
r_anchors[3] = (p_rect.position.y + p_rect.size.y - p_offsets[3]) / parent_rect_size.y;
|
||||
}
|
||||
|
||||
void Control::_compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]) {
|
||||
Size2 parent_rect_size = get_parent_anchorable_rect().size;
|
||||
|
||||
real_t x = p_rect.position.x;
|
||||
if (is_layout_rtl()) {
|
||||
x = parent_rect_size.x - x - p_rect.size.x;
|
||||
if (p_keep_offsets) {
|
||||
data.anchor[0] = (x - data.offset[0]) / parent_rect_size.x;
|
||||
data.anchor[1] = (y - data.offset[1]) / parent_rect_size.y;
|
||||
data.anchor[2] = (x + p_rect.size.x - data.offset[2]) / parent_rect_size.x;
|
||||
data.anchor[3] = (y + p_rect.size.y - data.offset[3]) / parent_rect_size.y;
|
||||
} else {
|
||||
data.offset[0] = x - (data.anchor[0] * parent_rect_size.x);
|
||||
data.offset[1] = y - (data.anchor[1] * parent_rect_size.y);
|
||||
data.offset[2] = x + p_rect.size.x - (data.anchor[2] * parent_rect_size.x);
|
||||
data.offset[3] = y + p_rect.size.y - (data.anchor[3] * parent_rect_size.y);
|
||||
}
|
||||
r_offsets[0] = x - (p_anchors[0] * parent_rect_size.x);
|
||||
r_offsets[1] = p_rect.position.y - (p_anchors[1] * parent_rect_size.y);
|
||||
r_offsets[2] = x + p_rect.size.x - (p_anchors[2] * parent_rect_size.x);
|
||||
r_offsets[3] = p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y);
|
||||
}
|
||||
|
||||
/// Presets and layout modes.
|
||||
@@ -1476,11 +1493,7 @@ void Control::set_position(const Point2 &p_point, bool p_keep_offsets) {
|
||||
}
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
if (p_keep_offsets) {
|
||||
_compute_anchors(Rect2(p_point, data.size_cache), data.offset, data.anchor);
|
||||
} else {
|
||||
_compute_offsets(Rect2(p_point, data.size_cache), data.anchor, data.offset);
|
||||
}
|
||||
_compute_layout_rect(Rect2(p_point, data.size_cache), p_keep_offsets);
|
||||
_size_changed();
|
||||
}
|
||||
|
||||
@@ -1552,11 +1565,7 @@ void Control::set_size(const Size2 &p_size, bool p_keep_offsets) {
|
||||
|
||||
data.expanded_by_desired_size = false;
|
||||
|
||||
if (p_keep_offsets) {
|
||||
_compute_anchors(Rect2(data.pos_cache, new_size), data.offset, data.anchor);
|
||||
} else {
|
||||
_compute_offsets(Rect2(data.pos_cache, new_size), data.anchor, data.offset);
|
||||
}
|
||||
_compute_layout_rect(Rect2(data.pos_cache, new_size), p_keep_offsets);
|
||||
_size_changed();
|
||||
}
|
||||
|
||||
@@ -1576,7 +1585,7 @@ void Control::set_rect(const Rect2 &p_rect) {
|
||||
data.anchor[i] = ANCHOR_BEGIN;
|
||||
}
|
||||
|
||||
_compute_offsets(p_rect, data.anchor, data.offset);
|
||||
_compute_layout_rect(p_rect);
|
||||
if (is_inside_tree()) {
|
||||
_size_changed();
|
||||
}
|
||||
|
||||
+1
-2
@@ -365,8 +365,7 @@ private:
|
||||
void _set_global_position(const Point2 &p_point);
|
||||
void _set_size(const Size2 &p_size);
|
||||
|
||||
void _compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]);
|
||||
void _compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]);
|
||||
void _compute_layout_rect(Rect2 p_rect, bool p_keep_offsets = false);
|
||||
|
||||
void _set_layout_mode(LayoutMode p_mode);
|
||||
void _update_layout_mode();
|
||||
|
||||
Reference in New Issue
Block a user