Skip to content

Commit e6bdc09

Browse files
KoBeWiGeneralProtectionFault
authored andcommitted
Add pivot_offset_ratio property to Control
1 parent fedd0c9 commit e6bdc09

6 files changed

Lines changed: 55 additions & 10 deletions

File tree

doc/classes/Control.xml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,12 @@
409409
Returns combined minimum size from [member custom_minimum_size] and [method get_minimum_size].
410410
</description>
411411
</method>
412+
<method name="get_combined_pivot_offset" qualifiers="const">
413+
<return type="Vector2" />
414+
<description>
415+
Returns the combined value of [member pivot_offset] and [member pivot_offset_ratio], in pixels. The ratio is multiplied by the control's size.
416+
</description>
417+
</method>
412418
<method name="get_cursor_shape" qualifiers="const">
413419
<return type="int" enum="Control.CursorShape" />
414420
<param index="0" name="position" type="Vector2" default="Vector2(0, 0)" />
@@ -1121,7 +1127,12 @@
11211127
</member>
11221128
<member name="physics_interpolation_mode" type="int" setter="set_physics_interpolation_mode" getter="get_physics_interpolation_mode" overrides="Node" enum="Node.PhysicsInterpolationMode" default="2" />
11231129
<member name="pivot_offset" type="Vector2" setter="set_pivot_offset" getter="get_pivot_offset" default="Vector2(0, 0)">
1124-
By default, the node's pivot is its top-left corner. When you change its [member rotation] or [member scale], it will rotate or scale around this pivot. Set this property to [member size] / 2 to pivot around the Control's center.
1130+
By default, the node's pivot is its top-left corner. When you change its [member rotation] or [member scale], it will rotate or scale around this pivot.
1131+
The actual offset is the combined value of this property and [member pivot_offset_ratio].
1132+
</member>
1133+
<member name="pivot_offset_ratio" type="Vector2" setter="set_pivot_offset_ratio" getter="get_pivot_offset_ratio" default="Vector2(0, 0)">
1134+
Same as [member pivot_offset], but expressed as uniform vector, where [code]Vector2(0, 0)[/code] is the top-left corner of this control, and [code]Vector2(1, 1)[/code] is its bottom-right corner. Set this property to [code]Vector2(0.5, 0.5)[/code] to pivot around this control's center.
1135+
The actual offset is the combined value of this property and [member pivot_offset].
11251136
</member>
11261137
<member name="position" type="Vector2" setter="_set_position" getter="get_position" default="Vector2(0, 0)">
11271138
The node's position, relative to its containing node. It corresponds to the rectangle's top-left corner. The property is not affected by [member pivot_offset].

editor/scene/canvas_item_editor_plugin.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4210,17 +4210,18 @@ void CanvasItemEditor::_notification(int p_what) {
42104210

42114211
Control *control = Object::cast_to<Control>(ci);
42124212
if (control) {
4213-
real_t anchors[4];
4214-
Vector2 pivot;
4213+
Vector2 pivot = control->get_pivot_offset();
4214+
Vector2 pivot_ratio = control->get_pivot_offset_ratio();
42154215

4216-
pivot = control->get_pivot_offset();
4216+
real_t anchors[4];
42174217
anchors[SIDE_LEFT] = control->get_anchor(SIDE_LEFT);
42184218
anchors[SIDE_RIGHT] = control->get_anchor(SIDE_RIGHT);
42194219
anchors[SIDE_TOP] = control->get_anchor(SIDE_TOP);
42204220
anchors[SIDE_BOTTOM] = control->get_anchor(SIDE_BOTTOM);
42214221

4222-
if (pivot != se->prev_pivot || anchors[SIDE_LEFT] != se->prev_anchors[SIDE_LEFT] || anchors[SIDE_RIGHT] != se->prev_anchors[SIDE_RIGHT] || anchors[SIDE_TOP] != se->prev_anchors[SIDE_TOP] || anchors[SIDE_BOTTOM] != se->prev_anchors[SIDE_BOTTOM]) {
4222+
if (pivot != se->prev_pivot || pivot_ratio != se->prev_pivot_ratio || anchors[SIDE_LEFT] != se->prev_anchors[SIDE_LEFT] || anchors[SIDE_RIGHT] != se->prev_anchors[SIDE_RIGHT] || anchors[SIDE_TOP] != se->prev_anchors[SIDE_TOP] || anchors[SIDE_BOTTOM] != se->prev_anchors[SIDE_BOTTOM]) {
42234223
se->prev_pivot = pivot;
4224+
se->prev_pivot_ratio = pivot_ratio;
42244225
se->prev_anchors[SIDE_LEFT] = anchors[SIDE_LEFT];
42254226
se->prev_anchors[SIDE_RIGHT] = anchors[SIDE_RIGHT];
42264227
se->prev_anchors[SIDE_TOP] = anchors[SIDE_TOP];

editor/scene/canvas_item_editor_plugin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class CanvasItemEditorSelectedItem : public Object {
6666
Transform2D prev_xform;
6767
Rect2 prev_rect;
6868
Vector2 prev_pivot;
69+
Vector2 prev_pivot_ratio;
6970
real_t prev_anchors[4] = { (real_t)0.0 };
7071

7172
Transform2D pre_drag_xform;

editor/scene/gui/control_editor_plugin.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,6 @@ class ControlEditorToolbar : public HBoxContainer {
252252
ControlEditorToolbar();
253253
};
254254

255-
256255
class ControlOffsetTransformPreview : public Control {
257256
GDCLASS(ControlOffsetTransformPreview, Control);
258257

scene/gui/control.cpp

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ Dictionary Control::_edit_get_state() const {
6565
s["rotation"] = get_rotation();
6666
s["scale"] = get_scale();
6767
s["pivot"] = get_pivot_offset();
68+
s["pivot_ratio"] = get_pivot_offset_ratio();
6869

6970
Array anchors = { get_anchor(SIDE_LEFT), get_anchor(SIDE_TOP), get_anchor(SIDE_RIGHT), get_anchor(SIDE_BOTTOM) };
7071
s["anchors"] = anchors;
@@ -81,13 +82,14 @@ Dictionary Control::_edit_get_state() const {
8182
void Control::_edit_set_state(const Dictionary &p_state) {
8283
ERR_FAIL_COND(p_state.is_empty() ||
8384
!p_state.has("rotation") || !p_state.has("scale") ||
84-
!p_state.has("pivot") || !p_state.has("anchors") || !p_state.has("offsets") ||
85+
!p_state.has("pivot") || !p_state.has("pivot_ratio") || !p_state.has("anchors") || !p_state.has("offsets") ||
8586
!p_state.has("layout_mode") || !p_state.has("anchors_layout_preset"));
8687
Dictionary state = p_state;
8788

8889
set_rotation(state["rotation"]);
8990
set_scale(state["scale"]);
9091
set_pivot_offset(state["pivot"]);
92+
set_pivot_offset_ratio(state["pivot_ratio"]);
9193

9294
Array anchors = state["anchors"];
9395

@@ -159,10 +161,11 @@ void Control::_edit_set_pivot(const Point2 &p_pivot) {
159161
Vector2 move = Vector2((std::cos(data.rotation) - 1.0) * delta_pivot.x - std::sin(data.rotation) * delta_pivot.y, std::sin(data.rotation) * delta_pivot.x + (std::cos(data.rotation) - 1.0) * delta_pivot.y);
160162
set_position(get_position() + move);
161163
set_pivot_offset(p_pivot);
164+
set_pivot_offset_ratio(Vector2());
162165
}
163166

164167
Point2 Control::_edit_get_pivot() const {
165-
return get_pivot_offset();
168+
return get_combined_pivot_offset();
166169
}
167170

168171
bool Control::_edit_use_pivot() const {
@@ -545,7 +548,7 @@ void Control::_validate_property(PropertyInfo &p_property) const {
545548
// If the parent is a container, display only container-related properties.
546549
if (p_property.name.begins_with("anchor_") || is_anchor_offset_property_name || p_property.name.begins_with("grow_") || p_property.name == "anchors_preset") {
547550
p_property.usage ^= PROPERTY_USAGE_DEFAULT;
548-
} else if (p_property.name == "position" || p_property.name == "rotation" || p_property.name == "scale" || p_property.name == "size" || p_property.name == "pivot_offset") {
551+
} else if (p_property.name == "position" || p_property.name == "rotation" || p_property.name == "scale" || p_property.name == "size" || p_property.name == "pivot_offset" || p_property.name == "pivot_offset_ratio") {
549552
p_property.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY;
550553
} else if (Engine::get_singleton()->is_editor_hint() && p_property.name == "layout_mode") {
551554
// Set the layout mode to be disabled with the proper value.
@@ -1700,6 +1703,23 @@ real_t Control::get_rotation_degrees() const {
17001703
return Math::rad_to_deg(get_rotation());
17011704
}
17021705

1706+
void Control::set_pivot_offset_ratio(const Vector2 &p_ratio) {
1707+
ERR_MAIN_THREAD_GUARD;
1708+
if (data.pivot_offset_ratio == p_ratio) {
1709+
return;
1710+
}
1711+
1712+
data.pivot_offset_ratio = p_ratio;
1713+
queue_redraw();
1714+
_notify_transform();
1715+
queue_accessibility_update();
1716+
}
1717+
1718+
Vector2 Control::get_pivot_offset_ratio() const {
1719+
ERR_READ_THREAD_GUARD_V(Vector2());
1720+
return data.pivot_offset_ratio;
1721+
}
1722+
17031723
void Control::set_pivot_offset(const Vector2 &p_pivot) {
17041724
ERR_MAIN_THREAD_GUARD;
17051725
if (data.pivot_offset == p_pivot) {
@@ -1727,6 +1747,11 @@ Vector2 Control::get_pivot_offset() const {
17271747
return data.pivot_offset;
17281748
}
17291749

1750+
Vector2 Control::get_combined_pivot_offset() const {
1751+
ERR_READ_THREAD_GUARD_V(Vector2());
1752+
return data.pivot_offset + data.pivot_offset_ratio * get_size();
1753+
}
1754+
17301755
/// Sizes.
17311756

17321757
void Control::_update_minimum_size() {
@@ -4323,6 +4348,7 @@ void Control::_bind_methods() {
43234348
ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Control::set_rotation_degrees);
43244349
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale);
43254350
ClassDB::bind_method(D_METHOD("set_pivot_offset", "pivot_offset"), &Control::set_pivot_offset);
4351+
ClassDB::bind_method(D_METHOD("set_pivot_offset_ratio", "ratio"), &Control::set_pivot_offset_ratio);
43264352
ClassDB::bind_method(D_METHOD("get_begin"), &Control::get_begin);
43274353
ClassDB::bind_method(D_METHOD("get_end"), &Control::get_end);
43284354
ClassDB::bind_method(D_METHOD("get_position"), &Control::get_position);
@@ -4331,6 +4357,8 @@ void Control::_bind_methods() {
43314357
ClassDB::bind_method(D_METHOD("get_rotation_degrees"), &Control::get_rotation_degrees);
43324358
ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale);
43334359
ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset);
4360+
ClassDB::bind_method(D_METHOD("get_pivot_offset_ratio"), &Control::get_pivot_offset_ratio);
4361+
ClassDB::bind_method(D_METHOD("get_combined_pivot_offset"), &Control::get_combined_pivot_offset);
43344362
ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size);
43354363
ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_parent_area_size);
43364364
ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position);
@@ -4574,7 +4602,8 @@ void Control::_bind_methods() {
45744602
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_less,or_greater,radians_as_degrees"), "set_rotation", "get_rotation");
45754603
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation_degrees", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_rotation_degrees", "get_rotation_degrees");
45764604
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale");
4577-
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pivot_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_pivot_offset", "get_pivot_offset");
4605+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pivot_offset", PROPERTY_HINT_NONE, "suffix:px", PROPERTY_USAGE_EDITOR), "set_pivot_offset", "get_pivot_offset");
4606+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pivot_offset_ratio"), "set_pivot_offset_ratio", "get_pivot_offset_ratio");
45784607

45794608
ADD_SUBGROUP("Container Sizing", "size_flags_");
45804609
ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill:1,Expand:2,Shrink Center:4,Shrink End:8"), "set_h_size_flags", "get_h_size_flags");

scene/gui/control.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ class Control : public CanvasItem {
238238
real_t rotation = 0.0;
239239
Vector2 scale = Vector2(1, 1);
240240
Vector2 pivot_offset;
241+
Vector2 pivot_offset_ratio;
241242

242243
OffsetTransform *offset_transform = nullptr;
243244

@@ -568,8 +569,11 @@ class Control : public CanvasItem {
568569
void set_rotation_degrees(real_t p_degrees);
569570
real_t get_rotation() const;
570571
real_t get_rotation_degrees() const;
572+
void set_pivot_offset_ratio(const Vector2 &p_ratio);
573+
Vector2 get_pivot_offset_ratio() const;
571574
void set_pivot_offset(const Vector2 &p_pivot);
572575
Vector2 get_pivot_offset() const;
576+
Vector2 get_combined_pivot_offset() const;
573577

574578
void update_minimum_size();
575579

0 commit comments

Comments
 (0)