Merge pull request #27559 from groud/anchor_mode

Improve the anchors and margin workflow
This commit is contained in:
Rémi Verschelde 2019-05-20 17:44:56 +02:00 committed by GitHub
commit 79cc95c6a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 238 additions and 66 deletions

View File

@ -546,7 +546,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("editors/2d/bone_ik_color", Color(0.9, 0.9, 0.45, 0.9));
_initial_set("editors/2d/bone_outline_color", Color(0.35, 0.35, 0.35));
_initial_set("editors/2d/bone_outline_size", 2);
_initial_set("editors/2d/keep_margins_when_changing_anchors", false);
_initial_set("editors/2d/viewport_border_color", Color(0.4, 0.4, 1.0, 0.4));
_initial_set("editors/2d/warped_mouse_panning", true);
_initial_set("editors/2d/simple_spacebar_panning", false);

View File

@ -1387,7 +1387,7 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
// Starts anchor dragging if needed
if (drag_type == DRAG_NONE) {
if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT && show_helpers) {
if (b.is_valid() && b->get_button_index() == BUTTON_LEFT && b->is_pressed() && tool == TOOL_SELECT) {
List<CanvasItem *> selection = _get_edited_canvas_items();
if (selection.size() == 1) {
Control *control = Object::cast_to<Control>(selection[0]);
@ -2213,6 +2213,7 @@ bool CanvasItemEditor::_gui_input_hover(const Ref<InputEvent> &p_event) {
void CanvasItemEditor::_gui_input_viewport(const Ref<InputEvent> &p_event) {
bool accepted = false;
if (EditorSettings::get_singleton()->get("editors/2d/simple_spacebar_panning") || !Input::get_singleton()->is_key_pressed(KEY_SPACE)) {
if ((accepted = _gui_input_rulers_and_guides(p_event))) {
//printf("Rulers and guides\n");
@ -2512,20 +2513,50 @@ void CanvasItemEditor::_draw_grid() {
}
}
void CanvasItemEditor::_draw_control_helpers(Control *control) {
void CanvasItemEditor::_draw_control_anchors(Control *control) {
Transform2D xform = transform * control->get_global_transform_with_canvas();
RID ci = viewport->get_canvas_item();
if (tool == TOOL_SELECT && show_helpers && !Object::cast_to<Container>(control->get_parent())) {
// Draw the helpers
Color color_base = Color(0.8, 0.8, 0.8, 0.5);
if (tool == TOOL_SELECT && !Object::cast_to<Container>(control->get_parent())) {
// Compute the anchors
float anchors_values[4];
anchors_values[0] = control->get_anchor(MARGIN_LEFT);
anchors_values[1] = control->get_anchor(MARGIN_TOP);
anchors_values[2] = control->get_anchor(MARGIN_RIGHT);
anchors_values[3] = control->get_anchor(MARGIN_BOTTOM);
Vector2 anchors_pos[4];
for (int i = 0; i < 4; i++) {
Vector2 value = Vector2((i % 2 == 0) ? anchors_values[i] : anchors_values[(i + 1) % 4], (i % 2 == 1) ? anchors_values[i] : anchors_values[(i + 1) % 4]);
anchors_pos[i] = xform.xform(_anchor_to_position(control, value));
}
// Draw the anchors handles
Rect2 anchor_rects[4];
anchor_rects[0] = Rect2(anchors_pos[0] - anchor_handle->get_size(), anchor_handle->get_size());
anchor_rects[1] = Rect2(anchors_pos[1] - Vector2(0.0, anchor_handle->get_size().y), Point2(-anchor_handle->get_size().x, anchor_handle->get_size().y));
anchor_rects[2] = Rect2(anchors_pos[2], -anchor_handle->get_size());
anchor_rects[3] = Rect2(anchors_pos[3] - Vector2(anchor_handle->get_size().x, 0.0), Point2(anchor_handle->get_size().x, -anchor_handle->get_size().y));
for (int i = 0; i < 4; i++) {
anchor_handle->draw_rect(ci, anchor_rects[i]);
}
}
}
void CanvasItemEditor::_draw_control_helpers(Control *control) {
Transform2D xform = transform * control->get_global_transform_with_canvas();
if (tool == TOOL_SELECT && show_helpers && !Object::cast_to<Container>(control->get_parent())) {
// Draw the helpers
Color color_base = Color(0.8, 0.8, 0.8, 0.5);
// Compute the anchors
float anchors_values[4];
anchors_values[0] = control->get_anchor(MARGIN_LEFT);
anchors_values[1] = control->get_anchor(MARGIN_TOP);
anchors_values[2] = control->get_anchor(MARGIN_RIGHT);
anchors_values[3] = control->get_anchor(MARGIN_BOTTOM);
// Draw the anchors
Vector2 anchors[4];
Vector2 anchors_pos[4];
for (int i = 0; i < 4; i++) {
@ -2592,16 +2623,6 @@ void CanvasItemEditor::_draw_control_helpers(Control *control) {
_draw_percentage_at_position(percent_val, (line_ends[(dragged_anchor + 1) % 4] + anchors_pos[dragged_anchor]) / 2, (Margin)((dragged_anchor + 1) % 4));
}
Rect2 anchor_rects[4];
anchor_rects[0] = Rect2(anchors_pos[0] - anchor_handle->get_size(), anchor_handle->get_size());
anchor_rects[1] = Rect2(anchors_pos[1] - Vector2(0.0, anchor_handle->get_size().y), Point2(-anchor_handle->get_size().x, anchor_handle->get_size().y));
anchor_rects[2] = Rect2(anchors_pos[2], -anchor_handle->get_size());
anchor_rects[3] = Rect2(anchors_pos[3] - Vector2(anchor_handle->get_size().x, 0.0), Point2(anchor_handle->get_size().x, -anchor_handle->get_size().y));
for (int i = 0; i < 4; i++) {
anchor_handle->draw_rect(ci, anchor_rects[i]);
}
// Draw the margin values and the node width/height when dragging control side
float ratio = 0.33;
Transform2D parent_transform = xform * control->get_transform().affine_inverse();
@ -2779,6 +2800,7 @@ void CanvasItemEditor::_draw_selection() {
// Draw control-related helpers
Control *control = Object::cast_to<Control>(canvas_item);
if (control && _is_node_movable(control)) {
_draw_control_anchors(control);
_draw_control_helpers(control);
}
@ -3311,24 +3333,32 @@ void CanvasItemEditor::_notification(int p_what) {
// Activate / Deactivate the pivot tool
pivot_button->set_disabled(nb_having_pivot == 0);
// Show / Hide the layout button
// Show / Hide the layout and anchors mode buttons
if (nb_control > 0 && nb_control == selection.size()) {
presets_menu->set_visible(true);
presets_menu->set_tooltip(TTR("Presets for the anchors and margins values of a Control node."));
anchor_mode_button->set_visible(true);
anchor_mode_button->set_tooltip(TTR("When active, moving Control nodes changes their anchors instead of their margins."));
// Set the pressed state of the node
anchor_mode_button->set_pressed(anchors_mode);
// Disable if the selected node is child of a container
presets_menu->set_disabled(false);
anchor_mode_button->set_disabled(false);
for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
Control *control = Object::cast_to<Control>(E->get());
if (!control || Object::cast_to<Container>(control->get_parent())) {
presets_menu->set_disabled(true);
presets_menu->set_tooltip(TTR("Children of containers have their anchors and margins values overridden by their parent."));
anchor_mode_button->set_disabled(true);
anchor_mode_button->set_tooltip(TTR("Children of containers have their anchors and margins values overridden by their parent."));
break;
}
}
} else {
presets_menu->set_visible(false);
anchor_mode_button->set_visible(false);
}
// Update the viewport if bones changes
@ -3436,9 +3466,10 @@ void CanvasItemEditor::_notification(int p_what) {
p->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), "HCenter Wide ", ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE);
p->add_separator();
p->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect", ANCHORS_AND_MARGINS_PRESET_WIDE);
p->add_icon_item(get_icon("Anchor", "EditorIcons"), "Keep Ratio", ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO);
p->add_separator();
p->add_submenu_item(TTR("Anchors Only"), "Anchors");
p->set_item_icon(20, get_icon("Anchor", "EditorIcons"));
p->add_submenu_item(TTR("Anchors only"), "Anchors");
p->set_item_icon(21, get_icon("Anchor", "EditorIcons"));
anchors_popup->clear();
anchors_popup->add_icon_item(get_icon("ControlAlignTopLeft", "EditorIcons"), "Top Left", ANCHORS_PRESET_TOP_LEFT);
@ -3460,9 +3491,31 @@ void CanvasItemEditor::_notification(int p_what) {
anchors_popup->add_icon_item(get_icon("ControlHcenterWide", "EditorIcons"), "HCenter Wide ", ANCHORS_PRESET_HCENTER_WIDE);
anchors_popup->add_separator();
anchors_popup->add_icon_item(get_icon("ControlAlignWide", "EditorIcons"), "Full Rect", ANCHORS_PRESET_WIDE);
anchor_mode_button->set_icon(get_icon("Anchor", "EditorIcons"));
}
}
void CanvasItemEditor::_selection_changed() {
// Update the anchors_mode
int nbValidControls = 0;
int nbAnchorsMode = 0;
List<Node *> selection = editor_selection->get_selected_node_list();
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Control *control = Object::cast_to<Control>(E->get());
if (!control)
continue;
if (Object::cast_to<Container>(control->get_parent()))
continue;
nbValidControls++;
if (control->has_meta("_edit_use_anchors_") && control->get_meta("_edit_use_anchors_")) {
nbAnchorsMode++;
}
}
anchors_mode = (nbValidControls == nbAnchorsMode);
}
void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
Array selection = editor_selection->get_selected_nodes();
@ -3680,6 +3733,36 @@ void CanvasItemEditor::_set_anchors_and_margins_preset(Control::LayoutPreset p_p
}
undo_redo->commit_action();
anchors_mode = false;
}
void CanvasItemEditor::_set_anchors_and_margins_to_keep_ratio() {
List<Node *> selection = editor_selection->get_selected_node_list();
undo_redo->create_action(TTR("Change Anchors and Margins"));
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Control *control = Object::cast_to<Control>(E->get());
if (control) {
Point2 top_left_anchor = _position_to_anchor(control, Point2());
Point2 bottom_right_anchor = _position_to_anchor(control, control->get_size());
undo_redo->add_do_method(control, "set_anchor", MARGIN_LEFT, top_left_anchor.x, false, true);
undo_redo->add_do_method(control, "set_anchor", MARGIN_RIGHT, bottom_right_anchor.x, false, true);
undo_redo->add_do_method(control, "set_anchor", MARGIN_TOP, top_left_anchor.y, false, true);
undo_redo->add_do_method(control, "set_anchor", MARGIN_BOTTOM, bottom_right_anchor.y, false, true);
undo_redo->add_do_method(control, "set_meta", "_edit_use_anchors_", true);
bool use_anchors = control->has_meta("_edit_use_anchors_") && control->get_meta("_edit_use_anchors_");
undo_redo->add_undo_method(control, "_edit_set_state", control->_edit_get_state());
undo_redo->add_undo_method(control, "set_meta", "_edit_use_anchors_", use_anchors);
anchors_mode = true;
}
}
undo_redo->commit_action();
}
void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) {
@ -3811,6 +3894,21 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
}
}
void CanvasItemEditor::_button_toggle_anchor_mode(bool p_status) {
List<CanvasItem *> selection = _get_edited_canvas_items(false, false);
for (List<CanvasItem *>::Element *E = selection.front(); E; E = E->next()) {
Control *control = Object::cast_to<Control>(E->get());
if (!control || Object::cast_to<Container>(control->get_parent()))
continue;
control->set_meta("_edit_use_anchors_", p_status);
}
anchors_mode = p_status;
viewport->update();
}
void CanvasItemEditor::_popup_callback(int p_op) {
last_option = MenuOption(p_op);
@ -4047,6 +4145,9 @@ void CanvasItemEditor::_popup_callback(int p_op) {
case ANCHORS_AND_MARGINS_PRESET_WIDE: {
_set_anchors_and_margins_preset(Control::PRESET_WIDE);
} break;
case ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO: {
_set_anchors_and_margins_to_keep_ratio();
} break;
case ANCHORS_PRESET_TOP_LEFT: {
_set_anchors_preset(PRESET_TOP_LEFT);
@ -4366,6 +4467,7 @@ void CanvasItemEditor::_bind_methods() {
ClassDB::bind_method("_button_zoom_reset", &CanvasItemEditor::_button_zoom_reset);
ClassDB::bind_method("_button_zoom_plus", &CanvasItemEditor::_button_zoom_plus);
ClassDB::bind_method("_button_toggle_snap", &CanvasItemEditor::_button_toggle_snap);
ClassDB::bind_method("_button_toggle_anchor_mode", &CanvasItemEditor::_button_toggle_anchor_mode);
ClassDB::bind_method("_update_scroll", &CanvasItemEditor::_update_scroll);
ClassDB::bind_method("_update_scrollbars", &CanvasItemEditor::_update_scrollbars);
ClassDB::bind_method("_popup_callback", &CanvasItemEditor::_popup_callback);
@ -4378,6 +4480,7 @@ void CanvasItemEditor::_bind_methods() {
ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed);
ClassDB::bind_method("_update_bone_list", &CanvasItemEditor::_update_bone_list);
ClassDB::bind_method("_tree_changed", &CanvasItemEditor::_tree_changed);
ClassDB::bind_method("_selection_changed", &CanvasItemEditor::_selection_changed);
ClassDB::bind_method("_popup_warning_depop", &CanvasItemEditor::_popup_warning_depop);
ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed);
ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide);
@ -4636,6 +4739,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
snap_relative = false;
snap_pixel = false;
anchors_mode = false;
skeleton_show_bones = true;
drag_type = DRAG_NONE;
@ -4654,6 +4759,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
editor_selection = p_editor->get_editor_selection();
editor_selection->add_editor_plugin(this);
editor_selection->connect("selection_changed", this, "update");
editor_selection->connect("selection_changed", this, "_selection_changed");
hb = memnew(HBoxContainer);
add_child(hb);
@ -4913,6 +5019,12 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
anchors_popup->set_name("Anchors");
anchors_popup->connect("id_pressed", this, "_popup_callback");
anchor_mode_button = memnew(ToolButton);
hb->add_child(anchor_mode_button);
anchor_mode_button->set_toggle_mode(true);
anchor_mode_button->hide();
anchor_mode_button->connect("toggled", this, "_button_toggle_anchor_mode");
animation_hb = memnew(HBoxContainer);
hb->add_child(animation_hb);
animation_hb->add_child(memnew(VSeparator));

View File

@ -129,6 +129,7 @@ private:
ANCHORS_AND_MARGINS_PRESET_VCENTER_WIDE,
ANCHORS_AND_MARGINS_PRESET_HCENTER_WIDE,
ANCHORS_AND_MARGINS_PRESET_WIDE,
ANCHORS_AND_MARGINS_PRESET_KEEP_RATIO,
ANCHORS_PRESET_TOP_LEFT,
ANCHORS_PRESET_TOP_RIGHT,
ANCHORS_PRESET_BOTTOM_LEFT,
@ -240,6 +241,8 @@ private:
Point2 view_offset;
Point2 previous_update_view_offset;
bool anchors_mode;
Point2 grid_offset;
Point2 grid_step;
int grid_step_multiplier;
@ -347,6 +350,8 @@ private:
PopupMenu *anchors_and_margins_popup;
PopupMenu *anchors_popup;
ToolButton *anchor_mode_button;
Button *key_loc_button;
Button *key_rot_button;
Button *key_scale_button;
@ -438,6 +443,7 @@ private:
void _draw_guides();
void _draw_focus();
void _draw_grid();
void _draw_control_anchors(Control *control);
void _draw_control_helpers(Control *control);
void _draw_selection();
void _draw_axis();
@ -462,6 +468,8 @@ private:
void _gui_input_viewport(const Ref<InputEvent> &p_event);
void _selection_changed();
void _focus_selection(int p_op);
void _solve_IK(Node2D *leaf_node, Point2 target_position);
@ -473,6 +481,9 @@ private:
void _set_anchors_preset(Control::LayoutPreset p_preset);
void _set_margins_preset(Control::LayoutPreset p_preset);
void _set_anchors_and_margins_preset(Control::LayoutPreset p_preset);
void _set_anchors_and_margins_to_keep_ratio();
void _button_toggle_anchor_mode(bool p_status);
HBoxContainer *zoom_hb;
void _zoom_on_position(float p_zoom, Point2 p_position = Point2());
@ -575,6 +586,8 @@ public:
void focus_selection();
bool is_anchors_mode_enabled() { return anchors_mode; };
CanvasItemEditor(EditorNode *p_editor);
};

View File

@ -43,6 +43,7 @@
#include "scene/scene_string_names.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_settings.h"
#include "editor/plugins/canvas_item_editor_plugin.h"
#endif
#include <stdio.h>
@ -66,6 +67,7 @@ Dictionary Control::_edit_get_state() const {
s["margins"] = margins;
return s;
}
void Control::_edit_set_state(const Dictionary &p_state) {
Dictionary state = p_state;
@ -87,7 +89,12 @@ void Control::_edit_set_state(const Dictionary &p_state) {
}
void Control::_edit_set_position(const Point2 &p_position) {
#ifdef TOOLS_ENABLED
set_position(p_position, CanvasItemEditor::get_singleton()->is_anchors_mode_enabled());
#else
// Unlikely to happen. TODO: enclose all _edit_ functions into TOOLS_ENABLED
set_position(p_position);
#endif
};
Point2 Control::_edit_get_position() const {
@ -103,8 +110,14 @@ Size2 Control::_edit_get_scale() const {
}
void Control::_edit_set_rect(const Rect2 &p_edit_rect) {
#ifdef TOOLS_ENABLED
set_position((get_position() + get_transform().basis_xform(p_edit_rect.position)).snapped(Vector2(1, 1)), CanvasItemEditor::get_singleton()->is_anchors_mode_enabled());
set_size(p_edit_rect.size.snapped(Vector2(1, 1)), CanvasItemEditor::get_singleton()->is_anchors_mode_enabled());
#else
// Unlikely to happen. TODO: enclose all _edit_ functions into TOOLS_ENABLED
set_position((get_position() + get_transform().basis_xform(p_edit_rect.position)).snapped(Vector2(1, 1)));
set_size(p_edit_rect.size.snapped(Vector2(1, 1)));
#endif
}
Rect2 Control::_edit_get_rect() const {
@ -1366,7 +1379,7 @@ void Control::set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin, bo
float previous_margin_pos = data.margin[p_margin] + data.anchor[p_margin] * parent_range;
float previous_opposite_margin_pos = data.margin[(p_margin + 2) % 4] + data.anchor[(p_margin + 2) % 4] * parent_range;
data.anchor[p_margin] = CLAMP(p_anchor, 0.0, 1.0);
data.anchor[p_margin] = p_anchor;
if (((p_margin == MARGIN_LEFT || p_margin == MARGIN_TOP) && data.anchor[p_margin] > data.anchor[(p_margin + 2) % 4]) ||
((p_margin == MARGIN_RIGHT || p_margin == MARGIN_BOTTOM) && data.anchor[p_margin] < data.anchor[(p_margin + 2) % 4])) {
@ -1395,15 +1408,7 @@ void Control::set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin, bo
}
void Control::_set_anchor(Margin p_margin, float p_anchor) {
#ifdef TOOLS_ENABLED
if (is_inside_tree() && Engine::get_singleton()->is_editor_hint()) {
set_anchor(p_margin, p_anchor, EDITOR_DEF("editors/2d/keep_margins_when_changing_anchors", false));
} else {
set_anchor(p_margin, p_anchor, false);
}
#else
set_anchor(p_margin, p_anchor, false);
#endif
set_anchor(p_margin, p_anchor);
}
void Control::set_anchor_and_margin(Margin p_margin, float p_anchor, float p_pos, bool p_push_opposite_anchor) {
@ -1412,7 +1417,7 @@ void Control::set_anchor_and_margin(Margin p_margin, float p_anchor, float p_pos
set_margin(p_margin, p_pos);
}
void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin) {
void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margins) {
//Left
switch (p_preset) {
case PRESET_TOP_LEFT:
@ -1423,21 +1428,21 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin) {
case PRESET_LEFT_WIDE:
case PRESET_HCENTER_WIDE:
case PRESET_WIDE:
set_anchor(MARGIN_LEFT, ANCHOR_BEGIN, p_keep_margin);
set_anchor(MARGIN_LEFT, ANCHOR_BEGIN, p_keep_margins);
break;
case PRESET_CENTER_TOP:
case PRESET_CENTER_BOTTOM:
case PRESET_CENTER:
case PRESET_VCENTER_WIDE:
set_anchor(MARGIN_LEFT, 0.5, p_keep_margin);
set_anchor(MARGIN_LEFT, 0.5, p_keep_margins);
break;
case PRESET_TOP_RIGHT:
case PRESET_BOTTOM_RIGHT:
case PRESET_CENTER_RIGHT:
case PRESET_RIGHT_WIDE:
set_anchor(MARGIN_LEFT, ANCHOR_END, p_keep_margin);
set_anchor(MARGIN_LEFT, ANCHOR_END, p_keep_margins);
break;
}
@ -1451,21 +1456,21 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin) {
case PRESET_TOP_WIDE:
case PRESET_VCENTER_WIDE:
case PRESET_WIDE:
set_anchor(MARGIN_TOP, ANCHOR_BEGIN, p_keep_margin);
set_anchor(MARGIN_TOP, ANCHOR_BEGIN, p_keep_margins);
break;
case PRESET_CENTER_LEFT:
case PRESET_CENTER_RIGHT:
case PRESET_CENTER:
case PRESET_HCENTER_WIDE:
set_anchor(MARGIN_TOP, 0.5, p_keep_margin);
set_anchor(MARGIN_TOP, 0.5, p_keep_margins);
break;
case PRESET_BOTTOM_LEFT:
case PRESET_BOTTOM_RIGHT:
case PRESET_CENTER_BOTTOM:
case PRESET_BOTTOM_WIDE:
set_anchor(MARGIN_TOP, ANCHOR_END, p_keep_margin);
set_anchor(MARGIN_TOP, ANCHOR_END, p_keep_margins);
break;
}
@ -1475,14 +1480,14 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin) {
case PRESET_BOTTOM_LEFT:
case PRESET_CENTER_LEFT:
case PRESET_LEFT_WIDE:
set_anchor(MARGIN_RIGHT, ANCHOR_BEGIN, p_keep_margin);
set_anchor(MARGIN_RIGHT, ANCHOR_BEGIN, p_keep_margins);
break;
case PRESET_CENTER_TOP:
case PRESET_CENTER_BOTTOM:
case PRESET_CENTER:
case PRESET_VCENTER_WIDE:
set_anchor(MARGIN_RIGHT, 0.5, p_keep_margin);
set_anchor(MARGIN_RIGHT, 0.5, p_keep_margins);
break;
case PRESET_TOP_RIGHT:
@ -1493,7 +1498,7 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin) {
case PRESET_BOTTOM_WIDE:
case PRESET_HCENTER_WIDE:
case PRESET_WIDE:
set_anchor(MARGIN_RIGHT, ANCHOR_END, p_keep_margin);
set_anchor(MARGIN_RIGHT, ANCHOR_END, p_keep_margins);
break;
}
@ -1503,14 +1508,14 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin) {
case PRESET_TOP_RIGHT:
case PRESET_CENTER_TOP:
case PRESET_TOP_WIDE:
set_anchor(MARGIN_BOTTOM, ANCHOR_BEGIN, p_keep_margin);
set_anchor(MARGIN_BOTTOM, ANCHOR_BEGIN, p_keep_margins);
break;
case PRESET_CENTER_LEFT:
case PRESET_CENTER_RIGHT:
case PRESET_CENTER:
case PRESET_HCENTER_WIDE:
set_anchor(MARGIN_BOTTOM, 0.5, p_keep_margin);
set_anchor(MARGIN_BOTTOM, 0.5, p_keep_margins);
break;
case PRESET_BOTTOM_LEFT:
@ -1521,7 +1526,7 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin) {
case PRESET_BOTTOM_WIDE:
case PRESET_VCENTER_WIDE:
case PRESET_WIDE:
set_anchor(MARGIN_BOTTOM, ANCHOR_END, p_keep_margin);
set_anchor(MARGIN_BOTTOM, ANCHOR_END, p_keep_margins);
break;
}
}
@ -1714,7 +1719,11 @@ Point2 Control::get_global_position() const {
return get_global_transform().get_origin();
}
void Control::set_global_position(const Point2 &p_point) {
void Control::_set_global_position(const Point2 &p_point) {
set_global_position(p_point);
}
void Control::set_global_position(const Point2 &p_point, bool p_keep_margins) {
Transform2D inv;
@ -1723,7 +1732,7 @@ void Control::set_global_position(const Point2 &p_point) {
inv = data.parent_canvas_item->get_global_transform().affine_inverse();
}
set_position(inv.xform(p_point));
set_position(inv.xform(p_point), p_keep_margins);
}
Rect2 Control::_compute_child_rect(const float p_anchors[4], const float p_margins[4]) const {
@ -1737,6 +1746,15 @@ Rect2 Control::_compute_child_rect(const float p_anchors[4], const float p_margi
return result;
}
void Control::_compute_anchors(Rect2 p_rect, const float p_margins[4], float (&r_anchors)[4]) {
Size2 parent_rect_size = get_parent_anchorable_rect().size;
r_anchors[0] = (p_rect.position.x - p_margins[0]) / parent_rect_size.x;
r_anchors[1] = (p_rect.position.y - p_margins[1]) / parent_rect_size.y;
r_anchors[2] = (p_rect.position.x + p_rect.size.x - p_margins[2]) / parent_rect_size.x;
r_anchors[3] = (p_rect.position.y + p_rect.size.y - p_margins[3]) / parent_rect_size.y;
}
void Control::_compute_margins(Rect2 p_rect, const float p_anchors[4], float (&r_margins)[4]) {
Size2 parent_rect_size = get_parent_anchorable_rect().size;
@ -1746,13 +1764,28 @@ void Control::_compute_margins(Rect2 p_rect, const float p_anchors[4], float (&r
r_margins[3] = p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y);
}
void Control::set_position(const Size2 &p_point) {
void Control::_set_position(const Size2 &p_point) {
set_position(p_point);
}
_compute_margins(Rect2(p_point, data.size_cache), data.anchor, data.margin);
void Control::set_position(const Size2 &p_point, bool p_keep_margins) {
if (p_keep_margins) {
_compute_anchors(Rect2(p_point, data.size_cache), data.margin, data.anchor);
_change_notify("anchor_left");
_change_notify("anchor_right");
_change_notify("anchor_top");
_change_notify("anchor_bottom");
} else {
_compute_margins(Rect2(p_point, data.size_cache), data.anchor, data.margin);
}
_size_changed();
}
void Control::set_size(const Size2 &p_size) {
void Control::_set_size(const Size2 &p_size) {
set_size(p_size);
}
void Control::set_size(const Size2 &p_size, bool p_keep_margins) {
Size2 new_size = p_size;
Size2 min = get_combined_minimum_size();
@ -1761,7 +1794,15 @@ void Control::set_size(const Size2 &p_size) {
if (new_size.y < min.y)
new_size.y = min.y;
_compute_margins(Rect2(data.pos_cache, new_size), data.anchor, data.margin);
if (p_keep_margins) {
_compute_anchors(Rect2(data.pos_cache, new_size), data.margin, data.anchor);
_change_notify("anchor_left");
_change_notify("anchor_right");
_change_notify("anchor_top");
_change_notify("anchor_bottom");
} else {
_compute_margins(Rect2(data.pos_cache, new_size), data.anchor, data.margin);
}
_size_changed();
}
@ -2702,20 +2743,23 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("accept_event"), &Control::accept_event);
ClassDB::bind_method(D_METHOD("get_minimum_size"), &Control::get_minimum_size);
ClassDB::bind_method(D_METHOD("get_combined_minimum_size"), &Control::get_combined_minimum_size);
ClassDB::bind_method(D_METHOD("set_anchors_preset", "preset", "keep_margin"), &Control::set_anchors_preset, DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_anchors_preset", "preset", "keep_margins"), &Control::set_anchors_preset, DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_margins_preset", "preset", "resize_mode", "margin"), &Control::set_margins_preset, DEFVAL(PRESET_MODE_MINSIZE), DEFVAL(0));
ClassDB::bind_method(D_METHOD("set_anchors_and_margins_preset", "preset", "resize_mode", "margin"), &Control::set_anchors_and_margins_preset, DEFVAL(PRESET_MODE_MINSIZE), DEFVAL(0));
ClassDB::bind_method(D_METHOD("set_anchor", "margin", "anchor", "keep_margin", "push_opposite_anchor"), &Control::set_anchor, DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("_set_anchor", "margin", "anchor"), &Control::_set_anchor);
ClassDB::bind_method(D_METHOD("set_anchor", "margin", "anchor", "keep_margin", "push_opposite_anchor"), &Control::set_anchor, DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_anchor", "margin"), &Control::get_anchor);
ClassDB::bind_method(D_METHOD("set_margin", "margin", "offset"), &Control::set_margin);
ClassDB::bind_method(D_METHOD("set_anchor_and_margin", "margin", "anchor", "offset", "push_opposite_anchor"), &Control::set_anchor_and_margin, DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_begin", "position"), &Control::set_begin);
ClassDB::bind_method(D_METHOD("set_end", "position"), &Control::set_end);
ClassDB::bind_method(D_METHOD("set_position", "position"), &Control::set_position);
ClassDB::bind_method(D_METHOD("set_size", "size"), &Control::set_size);
ClassDB::bind_method(D_METHOD("set_position", "position", "keep_margins"), &Control::set_position, DEFVAL(false));
ClassDB::bind_method(D_METHOD("_set_position", "margin"), &Control::_set_position);
ClassDB::bind_method(D_METHOD("set_size", "size", "keep_margins"), &Control::set_size, DEFVAL(false));
ClassDB::bind_method(D_METHOD("_set_size", "size"), &Control::_set_size);
ClassDB::bind_method(D_METHOD("set_custom_minimum_size", "size"), &Control::set_custom_minimum_size);
ClassDB::bind_method(D_METHOD("set_global_position", "position"), &Control::set_global_position);
ClassDB::bind_method(D_METHOD("set_global_position", "position", "keep_margins"), &Control::set_global_position, DEFVAL(false));
ClassDB::bind_method(D_METHOD("_set_global_position", "position"), &Control::_set_global_position);
ClassDB::bind_method(D_METHOD("set_rotation", "radians"), &Control::set_rotation);
ClassDB::bind_method(D_METHOD("set_rotation_degrees", "degrees"), &Control::set_rotation_degrees);
ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale);
@ -2835,10 +2879,10 @@ void Control::_bind_methods() {
BIND_VMETHOD(MethodInfo(Variant::BOOL, "_clips_input"));
ADD_GROUP("Anchor", "anchor_");
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_left", PROPERTY_HINT_RANGE, "0,1,0.01"), "_set_anchor", "get_anchor", MARGIN_LEFT);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_top", PROPERTY_HINT_RANGE, "0,1,0.01"), "_set_anchor", "get_anchor", MARGIN_TOP);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_right", PROPERTY_HINT_RANGE, "0,1,0.01"), "_set_anchor", "get_anchor", MARGIN_RIGHT);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_bottom", PROPERTY_HINT_RANGE, "0,1,0.01"), "_set_anchor", "get_anchor", MARGIN_BOTTOM);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_left", PROPERTY_HINT_RANGE, "0,1,0.01,or_lesser,or_greater"), "_set_anchor", "get_anchor", MARGIN_LEFT);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_top", PROPERTY_HINT_RANGE, "0,1,0.01,or_lesser,or_greater"), "_set_anchor", "get_anchor", MARGIN_TOP);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_right", PROPERTY_HINT_RANGE, "0,1,0.01,or_lesser,or_greater"), "_set_anchor", "get_anchor", MARGIN_RIGHT);
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_bottom", PROPERTY_HINT_RANGE, "0,1,0.01,or_lesser,or_greater"), "_set_anchor", "get_anchor", MARGIN_BOTTOM);
ADD_GROUP("Margin", "margin_");
ADD_PROPERTYI(PropertyInfo(Variant::INT, "margin_left", PROPERTY_HINT_RANGE, "-4096,4096"), "set_margin", "get_margin", MARGIN_LEFT);
@ -2851,9 +2895,9 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Begin,End,Both"), "set_v_grow_direction", "get_v_grow_direction");
ADD_GROUP("Rect", "rect_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_global_position", PROPERTY_HINT_NONE, "", 0), "set_global_position", "get_global_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_global_position", PROPERTY_HINT_NONE, "", 0), "_set_global_position", "get_global_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_size", "get_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_degrees", "get_rotation_degrees");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale");

View File

@ -217,6 +217,9 @@ private:
Control *_get_focus_neighbour(Margin p_margin, int p_count = 0);
void _set_anchor(Margin p_margin, float p_anchor);
void _set_position(const Point2 &p_point);
void _set_global_position(const Point2 &p_point);
void _set_size(const Size2 &p_size);
void _propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign = true);
void _theme_changed();
@ -229,6 +232,7 @@ private:
Rect2 _compute_child_rect(const float p_anchors[4], const float p_margins[4]) const;
void _compute_margins(Rect2 p_rect, const float p_anchors[4], float (&r_margins)[4]);
void _compute_anchors(Rect2 p_rect, const float p_margins[4], float (&r_anchors)[4]);
void _size_changed();
String _get_tooltip() const;
@ -325,7 +329,7 @@ public:
/* POSITIONING */
void set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin = true);
void set_anchors_preset(LayoutPreset p_preset, bool p_keep_margins = true);
void set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0);
void set_anchors_and_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0);
@ -343,12 +347,12 @@ public:
Point2 get_begin() const;
Point2 get_end() const;
void set_position(const Point2 &p_point);
void set_global_position(const Point2 &p_point);
void set_position(const Point2 &p_point, bool p_keep_margins = false);
void set_global_position(const Point2 &p_point, bool p_keep_margins = false);
Point2 get_position() const;
Point2 get_global_position() const;
void set_size(const Size2 &p_size);
void set_size(const Size2 &p_size, bool p_keep_margins = false);
Size2 get_size() const;
Rect2 get_rect() const;