Merge pull request #87081 from timoschwarzer/feature/control-render-transform
Add transform offset to Control nodes
This commit is contained in:
commit
2759cbdc6c
5 changed files with 433 additions and 3 deletions
|
|
@ -1098,6 +1098,41 @@
|
|||
Distance between the node's top edge and its parent control, based on [member anchor_top].
|
||||
Offsets are often controlled by one or multiple parent [Container] nodes, so you should not modify them manually if your node is a direct child of a [Container]. Offsets update automatically when you move or resize the node.
|
||||
</member>
|
||||
<member name="offset_transform_enabled" type="bool" setter="set_offset_transform_enabled" getter="is_offset_transform_enabled" default="false">
|
||||
If [code]true[/code], applies all offset transform properties. Otherwise, no offset transform is applied and the properties have no effect.
|
||||
</member>
|
||||
<member name="offset_transform_pivot" type="Vector2" setter="set_offset_transform_pivot" getter="get_offset_transform_pivot" default="Vector2(0, 0)">
|
||||
Pivot used by [member offset_transform_rotation] and [member offset_transform_scale] in absolute units.
|
||||
The final pivot position is the combined value of this property and [member offset_transform_pivot_ratio].
|
||||
Has no effect unless [member offset_transform_enabled] is [code]true[/code].
|
||||
</member>
|
||||
<member name="offset_transform_pivot_ratio" type="Vector2" setter="set_offset_transform_pivot_ratio" getter="get_offset_transform_pivot_ratio" default="Vector2(0.5, 0.5)">
|
||||
Same as [member offset_transform_pivot] but expressed in units relative to the [Control] [member size] 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.
|
||||
The final pivot position is the combined value of this property and [member offset_transform_pivot].
|
||||
Has no effect unless [member offset_transform_enabled] is [code]true[/code].
|
||||
</member>
|
||||
<member name="offset_transform_position" type="Vector2" setter="set_offset_transform_position" getter="get_offset_transform_position" default="Vector2(0, 0)">
|
||||
Position offset in absolute units. The final offset is the combined value of this property and [member offset_transform_position_ratio].
|
||||
Has no effect unless [member offset_transform_enabled] is [code]true[/code].
|
||||
</member>
|
||||
<member name="offset_transform_position_ratio" type="Vector2" setter="set_offset_transform_position_ratio" getter="get_offset_transform_position_ratio" default="Vector2(0, 0)">
|
||||
Same as [member offset_transform_position] but expressed in units relative to the [Control] [member size] 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.
|
||||
The final offset is the combined value of this property and [member offset_transform_position].
|
||||
Has no effect unless [member offset_transform_enabled] is [code]true[/code].
|
||||
</member>
|
||||
<member name="offset_transform_rotation" type="float" setter="set_offset_transform_rotation" getter="get_offset_transform_rotation" default="0.0">
|
||||
Rotation offset. The rotation pivot is defined by [member offset_transform_pivot] and [member offset_transform_pivot_ratio].
|
||||
Has no effect unless [member offset_transform_enabled] is [code]true[/code].
|
||||
</member>
|
||||
<member name="offset_transform_scale" type="Vector2" setter="set_offset_transform_scale" getter="get_offset_transform_scale" default="Vector2(1, 1)">
|
||||
Scale offset. The scale pivot is defined by [member offset_transform_pivot] and [member offset_transform_pivot_ratio].
|
||||
Has no effect unless [member offset_transform_enabled] is [code]true[/code].
|
||||
</member>
|
||||
<member name="offset_transform_visual_only" type="bool" setter="set_offset_transform_visual_only" getter="is_offset_transform_visual_only" default="true">
|
||||
If [code]true[/code], the offset transforms is only applied visually and does not affect input. In other words, this Control will still receive input events at its original location before the offset transform is applied.
|
||||
If [code]false[/code], the entire transform of this Control is affected and input events will register where the Control is visually.
|
||||
Has no effect unless [member offset_transform_enabled] is [code]true[/code].
|
||||
</member>
|
||||
<member name="physics_interpolation_mode" type="int" setter="set_physics_interpolation_mode" getter="get_physics_interpolation_mode" overrides="Node" enum="Node.PhysicsInterpolationMode" default="2" />
|
||||
<member name="pivot_offset" type="Vector2" setter="set_pivot_offset" getter="get_pivot_offset" default="Vector2(0, 0)">
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -1261,11 +1261,79 @@ ControlEditorToolbar *ControlEditorToolbar::singleton = nullptr;
|
|||
|
||||
// Editor plugin.
|
||||
|
||||
void ControlOffsetTransformPreview::edit(Control *p_control) {
|
||||
if (p_control == selected_control) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Callable update_overlays = callable_mp(plugin, &EditorPlugin::update_overlays);
|
||||
|
||||
if (selected_control) {
|
||||
selected_control->disconnect(SceneStringName(draw), update_overlays);
|
||||
}
|
||||
|
||||
selected_control = p_control;
|
||||
|
||||
if (selected_control) {
|
||||
selected_control->connect(SceneStringName(draw), update_overlays);
|
||||
}
|
||||
|
||||
plugin->update_overlays();
|
||||
}
|
||||
|
||||
void ControlOffsetTransformPreview::forward_canvas_draw_over_viewport(Control *p_overlay) const {
|
||||
if (!selected_control || !selected_control->is_offset_transform_enabled() || selected_control->is_offset_transform_visual_only()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Point2 top_left = Point2();
|
||||
Point2 bottom_right = selected_control->get_size();
|
||||
Point2 top_right = Point2(bottom_right.x, top_left.y);
|
||||
Point2 bottom_left = Point2(top_left.x, bottom_right.y);
|
||||
|
||||
Transform2D control_transform_without_offset = selected_control->get_global_transform() * selected_control->get_offset_transform().affine_inverse();
|
||||
top_left = control_transform_without_offset.xform(top_left);
|
||||
bottom_right = control_transform_without_offset.xform(bottom_right);
|
||||
top_right = control_transform_without_offset.xform(top_right);
|
||||
bottom_left = control_transform_without_offset.xform(bottom_left);
|
||||
|
||||
Transform2D canvas_transform = CanvasItemEditor::get_singleton()->get_canvas_transform();
|
||||
top_left = canvas_transform.xform(top_left);
|
||||
bottom_right = canvas_transform.xform(bottom_right);
|
||||
top_right = canvas_transform.xform(top_right);
|
||||
bottom_left = canvas_transform.xform(bottom_left);
|
||||
|
||||
Color color = Color(0.5, 0.5, 0.5, 0.75);
|
||||
p_overlay->draw_dashed_line(top_left, top_right, color, 5.0, 4.0);
|
||||
p_overlay->draw_dashed_line(top_right, bottom_right, color, 5.0, 4.0);
|
||||
p_overlay->draw_dashed_line(bottom_right, bottom_left, color, 5.0, 4.0);
|
||||
p_overlay->draw_dashed_line(bottom_left, top_left, color, 5.0, 4.0);
|
||||
}
|
||||
|
||||
ControlOffsetTransformPreview::ControlOffsetTransformPreview(EditorPlugin *p_plugin) {
|
||||
plugin = p_plugin;
|
||||
}
|
||||
|
||||
void ControlEditorPlugin::edit(Object *p_object) {
|
||||
offset_transform_preview->edit(Object::cast_to<Control>(p_object));
|
||||
}
|
||||
|
||||
bool ControlEditorPlugin::handles(Object *p_object) const {
|
||||
return Object::cast_to<Control>(p_object) != nullptr;
|
||||
}
|
||||
|
||||
void ControlEditorPlugin::forward_canvas_draw_over_viewport(Control *p_overlay) {
|
||||
offset_transform_preview->forward_canvas_draw_over_viewport(p_overlay);
|
||||
}
|
||||
|
||||
ControlEditorPlugin::ControlEditorPlugin() {
|
||||
toolbar = memnew(ControlEditorToolbar);
|
||||
toolbar->hide();
|
||||
add_control_to_container(CONTAINER_CANVAS_EDITOR_MENU, toolbar);
|
||||
|
||||
offset_transform_preview = memnew(ControlOffsetTransformPreview(this));
|
||||
EditorNode::get_singleton()->get_gui_base()->add_child(offset_transform_preview);
|
||||
|
||||
Ref<EditorInspectorPluginControl> plugin;
|
||||
plugin.instantiate();
|
||||
add_inspector_plugin(plugin);
|
||||
|
|
|
|||
|
|
@ -252,14 +252,36 @@ public:
|
|||
ControlEditorToolbar();
|
||||
};
|
||||
|
||||
class ControlOffsetTransformPreview : public Control {
|
||||
GDCLASS(ControlOffsetTransformPreview, Control);
|
||||
|
||||
EditorPlugin *plugin = nullptr;
|
||||
Control *selected_control = nullptr;
|
||||
|
||||
friend class ControlEditorPlugin;
|
||||
|
||||
public:
|
||||
void edit(Control *p_control);
|
||||
|
||||
void forward_canvas_draw_over_viewport(Control *p_overlay) const;
|
||||
|
||||
ControlOffsetTransformPreview(EditorPlugin *p_plugin);
|
||||
};
|
||||
|
||||
// Editor plugin.
|
||||
class ControlEditorPlugin : public EditorPlugin {
|
||||
GDCLASS(ControlEditorPlugin, EditorPlugin);
|
||||
|
||||
ControlEditorToolbar *toolbar = nullptr;
|
||||
ControlOffsetTransformPreview *offset_transform_preview = nullptr;
|
||||
|
||||
public:
|
||||
virtual String get_plugin_name() const override { return "Control"; }
|
||||
|
||||
virtual void edit(Object *p_object) override;
|
||||
virtual bool handles(Object *p_object) const override;
|
||||
|
||||
virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override;
|
||||
|
||||
ControlEditorPlugin();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -538,6 +538,8 @@ void Control::_validate_property(PropertyInfo &p_property) const {
|
|||
}
|
||||
// Validate which positioning properties should be displayed depending on the parent and the layout mode.
|
||||
Control *parent_control = get_parent_control();
|
||||
bool is_anchor_offset_property_name = p_property.name.begins_with("offset_") && !p_property.name.begins_with("offset_transform_");
|
||||
|
||||
if (Engine::get_singleton()->is_editor_hint() && !parent_control) {
|
||||
// If there is no parent control, display both anchor and container options.
|
||||
|
||||
|
|
@ -549,12 +551,12 @@ void Control::_validate_property(PropertyInfo &p_property) const {
|
|||
|
||||
// Use the layout mode to display or hide advanced anchoring properties.
|
||||
bool use_custom_anchors = _get_anchors_layout_preset() == -1; // Custom "preset".
|
||||
if (!use_custom_anchors && (p_property.name.begins_with("anchor_") || p_property.name.begins_with("offset_") || p_property.name.begins_with("grow_"))) {
|
||||
if (!use_custom_anchors && (p_property.name.begins_with("anchor_") || is_anchor_offset_property_name || p_property.name.begins_with("grow_"))) {
|
||||
p_property.usage ^= PROPERTY_USAGE_EDITOR;
|
||||
}
|
||||
} else if (Object::cast_to<Container>(parent_control)) {
|
||||
// If the parent is a container, display only container-related properties.
|
||||
if (p_property.name.begins_with("anchor_") || p_property.name.begins_with("offset_") || p_property.name.begins_with("grow_") || p_property.name == "anchors_preset") {
|
||||
if (p_property.name.begins_with("anchor_") || is_anchor_offset_property_name || p_property.name.begins_with("grow_") || p_property.name == "anchors_preset") {
|
||||
p_property.usage ^= PROPERTY_USAGE_DEFAULT;
|
||||
} 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") {
|
||||
p_property.usage = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_READ_ONLY;
|
||||
|
|
@ -620,7 +622,7 @@ void Control::_validate_property(PropertyInfo &p_property) const {
|
|||
p_property.usage ^= PROPERTY_USAGE_EDITOR;
|
||||
}
|
||||
bool use_custom_anchors = use_anchors && _get_anchors_layout_preset() == -1; // Custom "preset".
|
||||
if (!use_custom_anchors && (p_property.name.begins_with("anchor_") || p_property.name.begins_with("offset_") || p_property.name.begins_with("grow_"))) {
|
||||
if (!use_custom_anchors && (p_property.name.begins_with("anchor_") || is_anchor_offset_property_name || p_property.name.begins_with("grow_"))) {
|
||||
p_property.usage ^= PROPERTY_USAGE_EDITOR;
|
||||
}
|
||||
}
|
||||
|
|
@ -731,6 +733,11 @@ Transform2D Control::_get_internal_transform() const {
|
|||
// T(pivot_offset) * R(rotation) * S(scale) * T(-pivot_offset)
|
||||
Transform2D xform(data.rotation, data.scale, 0.0f, get_combined_pivot_offset());
|
||||
xform.translate_local(-get_combined_pivot_offset());
|
||||
|
||||
if (is_offset_transform_enabled() && !data.offset_transform->visual_only) {
|
||||
xform *= get_offset_transform();
|
||||
}
|
||||
|
||||
return xform;
|
||||
}
|
||||
|
||||
|
|
@ -743,6 +750,10 @@ void Control::_update_canvas_item_transform() {
|
|||
xform[2] = (xform[2] + Vector2(0.5, 0.5)).floor();
|
||||
}
|
||||
|
||||
if (is_offset_transform_enabled() && data.offset_transform->visual_only) {
|
||||
xform *= get_offset_transform();
|
||||
}
|
||||
|
||||
RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform);
|
||||
}
|
||||
|
||||
|
|
@ -1941,6 +1952,218 @@ real_t Control::get_stretch_ratio() const {
|
|||
return data.expand;
|
||||
}
|
||||
|
||||
// Offset transform.
|
||||
|
||||
void Control::set_offset_transform_enabled(bool p_enabled) {
|
||||
if (is_offset_transform_enabled() == p_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_enabled) {
|
||||
_ensure_allocated_offset_transform();
|
||||
data.offset_transform->enabled = true;
|
||||
} else {
|
||||
// Never deallocate to not lose previously set values
|
||||
data.offset_transform->enabled = false;
|
||||
}
|
||||
|
||||
queue_redraw();
|
||||
_notify_transform();
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
bool Control::is_offset_transform_enabled() const {
|
||||
return data.offset_transform != nullptr && data.offset_transform->enabled;
|
||||
}
|
||||
|
||||
void Control::set_offset_transform_position(const Vector2 &p_offset) {
|
||||
if (get_offset_transform_position() == p_offset) {
|
||||
return;
|
||||
}
|
||||
|
||||
_ensure_allocated_offset_transform();
|
||||
data.offset_transform->translation_absolute = p_offset;
|
||||
|
||||
if (!data.offset_transform->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue_redraw();
|
||||
_notify_transform();
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
Vector2 Control::get_offset_transform_position() const {
|
||||
if (data.offset_transform == nullptr) {
|
||||
return Data::OffsetTransform::DEFAULT_TRANSLATION_ABSOLUTE;
|
||||
}
|
||||
|
||||
return data.offset_transform->translation_absolute;
|
||||
}
|
||||
|
||||
void Control::set_offset_transform_position_ratio(const Vector2 &p_offset) {
|
||||
if (get_offset_transform_position_ratio() == p_offset) {
|
||||
return;
|
||||
}
|
||||
|
||||
_ensure_allocated_offset_transform();
|
||||
data.offset_transform->translation_relative = p_offset;
|
||||
|
||||
if (!data.offset_transform->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue_redraw();
|
||||
_notify_transform();
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
Vector2 Control::get_offset_transform_position_ratio() const {
|
||||
if (data.offset_transform == nullptr) {
|
||||
return Data::OffsetTransform::DEFAULT_TRANSLATION_RELATIVE;
|
||||
}
|
||||
|
||||
return data.offset_transform->translation_relative;
|
||||
}
|
||||
|
||||
void Control::set_offset_transform_scale(const Vector2 &p_scale) {
|
||||
if (get_offset_transform_scale() == p_scale) {
|
||||
return;
|
||||
}
|
||||
|
||||
_ensure_allocated_offset_transform();
|
||||
data.offset_transform->scale = p_scale;
|
||||
|
||||
if (!data.offset_transform->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue_redraw();
|
||||
_notify_transform();
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
Vector2 Control::get_offset_transform_scale() const {
|
||||
if (data.offset_transform == nullptr) {
|
||||
return Data::OffsetTransform::DEFAULT_SCALE;
|
||||
}
|
||||
|
||||
return data.offset_transform->scale;
|
||||
}
|
||||
|
||||
void Control::set_offset_transform_rotation(real_t p_rotation) {
|
||||
if (get_offset_transform_rotation() == p_rotation) {
|
||||
return;
|
||||
}
|
||||
|
||||
_ensure_allocated_offset_transform();
|
||||
data.offset_transform->rotation = p_rotation;
|
||||
|
||||
if (!data.offset_transform->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue_redraw();
|
||||
_notify_transform();
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
real_t Control::get_offset_transform_rotation() const {
|
||||
if (data.offset_transform == nullptr) {
|
||||
return Data::OffsetTransform::DEFAULT_ROTATION;
|
||||
}
|
||||
|
||||
return data.offset_transform->rotation;
|
||||
}
|
||||
|
||||
void Control::set_offset_transform_pivot(const Vector2 &p_pivot) {
|
||||
if (get_offset_transform_pivot() == p_pivot) {
|
||||
return;
|
||||
}
|
||||
|
||||
_ensure_allocated_offset_transform();
|
||||
data.offset_transform->pivot_absolute = p_pivot;
|
||||
|
||||
if (!data.offset_transform->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue_redraw();
|
||||
_notify_transform();
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
Vector2 Control::get_offset_transform_pivot() const {
|
||||
if (data.offset_transform == nullptr) {
|
||||
return Data::OffsetTransform::DEFAULT_PIVOT_ABSOLUTE;
|
||||
}
|
||||
|
||||
return data.offset_transform->pivot_absolute;
|
||||
}
|
||||
|
||||
void Control::set_offset_transform_pivot_ratio(const Vector2 &p_pivot) {
|
||||
if (get_offset_transform_pivot_ratio() == p_pivot) {
|
||||
return;
|
||||
}
|
||||
|
||||
_ensure_allocated_offset_transform();
|
||||
data.offset_transform->pivot_relative = p_pivot;
|
||||
|
||||
if (!data.offset_transform->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue_redraw();
|
||||
_notify_transform();
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
Vector2 Control::get_offset_transform_pivot_ratio() const {
|
||||
if (data.offset_transform == nullptr) {
|
||||
return Data::OffsetTransform::DEFAULT_PIVOT_RELATIVE;
|
||||
}
|
||||
|
||||
return data.offset_transform->pivot_relative;
|
||||
}
|
||||
|
||||
void Control::set_offset_transform_visual_only(bool p_enabled) {
|
||||
if (is_offset_transform_visual_only() == p_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
_ensure_allocated_offset_transform();
|
||||
data.offset_transform->visual_only = p_enabled;
|
||||
|
||||
if (!data.offset_transform->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
queue_redraw();
|
||||
_notify_transform();
|
||||
queue_accessibility_update();
|
||||
}
|
||||
|
||||
bool Control::is_offset_transform_visual_only() const {
|
||||
if (data.offset_transform == nullptr) {
|
||||
return Data::OffsetTransform::DEFAULT_VISUAL_ONLY;
|
||||
}
|
||||
|
||||
return data.offset_transform->visual_only;
|
||||
}
|
||||
|
||||
Transform2D Control::get_offset_transform() const {
|
||||
if (!is_offset_transform_enabled()) {
|
||||
return Transform2D();
|
||||
}
|
||||
|
||||
Vector2 combined_translation = data.offset_transform->translation_absolute + data.offset_transform->translation_relative * get_size();
|
||||
Vector2 combined_pivot = data.offset_transform->pivot_absolute + data.offset_transform->pivot_relative * get_size();
|
||||
|
||||
Transform2D offset_xform(data.offset_transform->rotation, data.offset_transform->scale, 0.0f, combined_pivot + combined_translation);
|
||||
offset_xform.translate_local(-combined_pivot);
|
||||
return offset_xform;
|
||||
}
|
||||
|
||||
// Input events.
|
||||
|
||||
void Control::_call_gui_input(const Ref<InputEvent> &p_event) {
|
||||
|
|
@ -3761,6 +3984,14 @@ Control *Control::make_custom_tooltip(const String &p_text) const {
|
|||
return Object::cast_to<Control>(ret);
|
||||
}
|
||||
|
||||
void Control::_ensure_allocated_offset_transform() {
|
||||
if (data.offset_transform != nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
data.offset_transform = memnew(Data::OffsetTransform);
|
||||
}
|
||||
|
||||
// Base object overrides.
|
||||
|
||||
void Control::_accessibility_action_foucs(const Variant &p_data) {
|
||||
|
|
@ -4131,6 +4362,23 @@ void Control::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_v_size_flags", "flags"), &Control::set_v_size_flags);
|
||||
ClassDB::bind_method(D_METHOD("get_v_size_flags"), &Control::get_v_size_flags);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_offset_transform_enabled", "enabled"), &Control::set_offset_transform_enabled);
|
||||
ClassDB::bind_method(D_METHOD("is_offset_transform_enabled"), &Control::is_offset_transform_enabled);
|
||||
ClassDB::bind_method(D_METHOD("set_offset_transform_position", "offset"), &Control::set_offset_transform_position);
|
||||
ClassDB::bind_method(D_METHOD("get_offset_transform_position"), &Control::get_offset_transform_position);
|
||||
ClassDB::bind_method(D_METHOD("set_offset_transform_position_ratio", "offset"), &Control::set_offset_transform_position_ratio);
|
||||
ClassDB::bind_method(D_METHOD("get_offset_transform_position_ratio"), &Control::get_offset_transform_position_ratio);
|
||||
ClassDB::bind_method(D_METHOD("set_offset_transform_scale", "scale"), &Control::set_offset_transform_scale);
|
||||
ClassDB::bind_method(D_METHOD("get_offset_transform_scale"), &Control::get_offset_transform_scale);
|
||||
ClassDB::bind_method(D_METHOD("set_offset_transform_rotation", "rotation"), &Control::set_offset_transform_rotation);
|
||||
ClassDB::bind_method(D_METHOD("get_offset_transform_rotation"), &Control::get_offset_transform_rotation);
|
||||
ClassDB::bind_method(D_METHOD("set_offset_transform_pivot", "pivot"), &Control::set_offset_transform_pivot);
|
||||
ClassDB::bind_method(D_METHOD("get_offset_transform_pivot"), &Control::get_offset_transform_pivot);
|
||||
ClassDB::bind_method(D_METHOD("set_offset_transform_pivot_ratio", "pivot"), &Control::set_offset_transform_pivot_ratio);
|
||||
ClassDB::bind_method(D_METHOD("get_offset_transform_pivot_ratio"), &Control::get_offset_transform_pivot_ratio);
|
||||
ClassDB::bind_method(D_METHOD("set_offset_transform_visual_only", "enabled"), &Control::set_offset_transform_visual_only);
|
||||
ClassDB::bind_method(D_METHOD("is_offset_transform_visual_only"), &Control::is_offset_transform_visual_only);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Control::set_theme);
|
||||
ClassDB::bind_method(D_METHOD("get_theme"), &Control::get_theme);
|
||||
|
||||
|
|
@ -4338,6 +4586,16 @@ void Control::_bind_methods() {
|
|||
ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_vertical", PROPERTY_HINT_FLAGS, "Fill:1,Expand:2,Shrink Center:4,Shrink End:8"), "set_v_size_flags", "get_v_size_flags");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "size_flags_stretch_ratio", PROPERTY_HINT_RANGE, "0,20,0.01,or_greater"), "set_stretch_ratio", "get_stretch_ratio");
|
||||
|
||||
ADD_GROUP("Offset Transform", "offset_transform_");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "offset_transform_enabled", PROPERTY_HINT_GROUP_ENABLE), "set_offset_transform_enabled", "is_offset_transform_enabled");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset_transform_position", PROPERTY_HINT_NONE, "suffix:px"), "set_offset_transform_position", "get_offset_transform_position");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset_transform_position_ratio", PROPERTY_HINT_NONE), "set_offset_transform_position_ratio", "get_offset_transform_position_ratio");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset_transform_scale", PROPERTY_HINT_LINK), "set_offset_transform_scale", "get_offset_transform_scale");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "offset_transform_rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_less,or_greater,radians_as_degrees"), "set_offset_transform_rotation", "get_offset_transform_rotation");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset_transform_pivot", PROPERTY_HINT_NONE, "suffix:px"), "set_offset_transform_pivot", "get_offset_transform_pivot");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset_transform_pivot_ratio", PROPERTY_HINT_NONE), "set_offset_transform_pivot_ratio", "get_offset_transform_pivot_ratio");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "offset_transform_visual_only", PROPERTY_HINT_NONE), "set_offset_transform_visual_only", "is_offset_transform_visual_only");
|
||||
|
||||
ADD_GROUP("Localization", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "localize_numeral_system"), "set_localize_numeral_system", "is_localizing_numeral_system");
|
||||
|
||||
|
|
@ -4517,6 +4775,10 @@ Control::Control() {
|
|||
Control::~Control() {
|
||||
memdelete(data.theme_owner);
|
||||
|
||||
if (data.offset_transform != nullptr) {
|
||||
memdelete(data.offset_transform);
|
||||
}
|
||||
|
||||
// Resources need to be disconnected.
|
||||
for (KeyValue<StringName, Ref<Texture2D>> &E : data.theme_icon_override) {
|
||||
E.value->disconnect_changed(callable_mp(this, &Control::_notify_theme_override_changed));
|
||||
|
|
|
|||
|
|
@ -185,6 +185,25 @@ private:
|
|||
|
||||
// This Data struct is to avoid namespace pollution in derived classes.
|
||||
struct Data {
|
||||
struct OffsetTransform {
|
||||
static constexpr Vector2 DEFAULT_TRANSLATION_ABSOLUTE = Vector2();
|
||||
static constexpr Vector2 DEFAULT_TRANSLATION_RELATIVE = Vector2();
|
||||
static constexpr Vector2 DEFAULT_SCALE = Vector2(1, 1);
|
||||
static constexpr real_t DEFAULT_ROTATION = 0.0;
|
||||
static constexpr Vector2 DEFAULT_PIVOT_ABSOLUTE = Vector2();
|
||||
static constexpr Vector2 DEFAULT_PIVOT_RELATIVE = Vector2(0.5, 0.5);
|
||||
static constexpr bool DEFAULT_VISUAL_ONLY = true;
|
||||
|
||||
bool enabled = false;
|
||||
Vector2 translation_absolute = DEFAULT_TRANSLATION_ABSOLUTE;
|
||||
Vector2 translation_relative = DEFAULT_TRANSLATION_RELATIVE;
|
||||
Vector2 scale = DEFAULT_SCALE;
|
||||
real_t rotation = DEFAULT_ROTATION;
|
||||
Vector2 pivot_absolute = DEFAULT_PIVOT_ABSOLUTE;
|
||||
Vector2 pivot_relative = DEFAULT_PIVOT_RELATIVE;
|
||||
bool visual_only = DEFAULT_VISUAL_ONLY;
|
||||
};
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
// Global relations.
|
||||
|
|
@ -216,6 +235,8 @@ private:
|
|||
Vector2 pivot_offset;
|
||||
Vector2 pivot_offset_ratio;
|
||||
|
||||
OffsetTransform *offset_transform = nullptr;
|
||||
|
||||
Point2 pos_cache;
|
||||
Size2 size_cache;
|
||||
mutable Size2 minimum_size_cache;
|
||||
|
|
@ -366,6 +387,8 @@ private:
|
|||
void _notify_theme_override_changed();
|
||||
void _invalidate_theme_cache();
|
||||
|
||||
void _ensure_allocated_offset_transform();
|
||||
|
||||
// Extra properties.
|
||||
|
||||
static int root_layout_direction;
|
||||
|
|
@ -572,6 +595,26 @@ public:
|
|||
void set_stretch_ratio(real_t p_ratio);
|
||||
real_t get_stretch_ratio() const;
|
||||
|
||||
// Offset transform.
|
||||
|
||||
void set_offset_transform_enabled(bool p_enabled);
|
||||
bool is_offset_transform_enabled() const;
|
||||
void set_offset_transform_position(const Vector2 &p_offset);
|
||||
Vector2 get_offset_transform_position() const;
|
||||
void set_offset_transform_position_ratio(const Vector2 &p_offset);
|
||||
Vector2 get_offset_transform_position_ratio() const;
|
||||
void set_offset_transform_scale(const Vector2 &p_scale);
|
||||
Vector2 get_offset_transform_scale() const;
|
||||
void set_offset_transform_rotation(real_t p_rotation);
|
||||
real_t get_offset_transform_rotation() const;
|
||||
void set_offset_transform_pivot(const Vector2 &p_pivot);
|
||||
Vector2 get_offset_transform_pivot() const;
|
||||
void set_offset_transform_pivot_ratio(const Vector2 &p_pivot);
|
||||
Vector2 get_offset_transform_pivot_ratio() const;
|
||||
void set_offset_transform_visual_only(bool p_enabled);
|
||||
bool is_offset_transform_visual_only() const;
|
||||
Transform2D get_offset_transform() const;
|
||||
|
||||
// Input events.
|
||||
|
||||
virtual void gui_input(const Ref<InputEvent> &p_event);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue