You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-08 12:40:44 +00:00
Make anchors draggable
This commit is contained in:
@@ -709,8 +709,8 @@ CanvasItem *CanvasItemEditor::get_single_item() {
|
|||||||
return single_item;
|
return single_item;
|
||||||
}
|
}
|
||||||
|
|
||||||
CanvasItemEditor::DragType CanvasItemEditor::_find_drag_type(const Point2 &p_click, Vector2 &r_point) {
|
CanvasItemEditor::DragType CanvasItemEditor::_get_resize_handle_drag_type(const Point2 &p_click, Vector2 &r_point) {
|
||||||
|
// Returns a drag type if a resize handle is clicked
|
||||||
CanvasItem *canvas_item = get_single_item();
|
CanvasItem *canvas_item = get_single_item();
|
||||||
|
|
||||||
ERR_FAIL_COND_V(!canvas_item, DRAG_NONE);
|
ERR_FAIL_COND_V(!canvas_item, DRAG_NONE);
|
||||||
@@ -784,6 +784,51 @@ Vector2 CanvasItemEditor::_anchor_to_position(Control *p_control, Vector2 anchor
|
|||||||
return parent_transform.xform(Vector2(parent_size.x * anchor.x, parent_size.y * anchor.y));
|
return parent_transform.xform(Vector2(parent_size.x * anchor.x, parent_size.y * anchor.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 CanvasItemEditor::_position_to_anchor(Control *p_control, Vector2 position) {
|
||||||
|
ERR_FAIL_COND_V(!p_control, Vector2());
|
||||||
|
Size2 parent_size = p_control->get_parent_area_size();
|
||||||
|
|
||||||
|
return p_control->get_transform().xform(position) / parent_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasItemEditor::DragType CanvasItemEditor::_get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point) {
|
||||||
|
// Returns a drag type if an anchor handle is clicked
|
||||||
|
CanvasItem *canvas_item = get_single_item();
|
||||||
|
ERR_FAIL_COND_V(!canvas_item, DRAG_NONE);
|
||||||
|
|
||||||
|
Control *control = canvas_item->cast_to<Control>();
|
||||||
|
ERR_FAIL_COND_V(!control, DRAG_NONE);
|
||||||
|
|
||||||
|
Vector2 anchor_pos[4];
|
||||||
|
anchor_pos[0] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_TOP));
|
||||||
|
anchor_pos[1] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_TOP));
|
||||||
|
anchor_pos[2] = Vector2(control->get_anchor(MARGIN_RIGHT), control->get_anchor(MARGIN_BOTTOM));
|
||||||
|
anchor_pos[3] = Vector2(control->get_anchor(MARGIN_LEFT), control->get_anchor(MARGIN_BOTTOM));
|
||||||
|
|
||||||
|
Rect2 anchor_rects[4];
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
anchor_pos[i] = (transform * control->get_global_transform_with_canvas()).xform(_anchor_to_position(control, anchor_pos[i]));
|
||||||
|
anchor_rects[i] = Rect2(anchor_pos[i], anchor_handle->get_size());
|
||||||
|
anchor_rects[i].position -= anchor_handle->get_size() * Vector2(i == 0 || i == 3, i <= 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DragType dragger[] = {
|
||||||
|
DRAG_ANCHOR_TOP_LEFT,
|
||||||
|
DRAG_ANCHOR_TOP_RIGHT,
|
||||||
|
DRAG_ANCHOR_BOTTOM_RIGHT,
|
||||||
|
DRAG_ANCHOR_BOTTOM_LEFT,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (anchor_rects[i].has_point(p_click)) {
|
||||||
|
r_point = transform.affine_inverse().xform(anchor_pos[i]);
|
||||||
|
return dragger[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DRAG_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
void CanvasItemEditor::_prepare_drag(const Point2 &p_click_pos) {
|
void CanvasItemEditor::_prepare_drag(const Point2 &p_click_pos) {
|
||||||
|
|
||||||
List<Node *> &selection = editor_selection->get_selected_node_list();
|
List<Node *> &selection = editor_selection->get_selected_node_list();
|
||||||
@@ -1345,8 +1390,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drag
|
// Drag resize handles
|
||||||
drag = _find_drag_type(click, drag_point_from);
|
drag = _get_resize_handle_drag_type(click, drag_point_from);
|
||||||
if (drag != DRAG_NONE) {
|
if (drag != DRAG_NONE) {
|
||||||
drag_from = transform.affine_inverse().xform(click);
|
drag_from = transform.affine_inverse().xform(click);
|
||||||
se->undo_state = canvas_item->edit_get_state();
|
se->undo_state = canvas_item->edit_get_state();
|
||||||
@@ -1356,6 +1401,16 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
|
|||||||
se->undo_pivot = canvas_item->cast_to<Control>()->get_pivot_offset();
|
se->undo_pivot = canvas_item->cast_to<Control>()->get_pivot_offset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drag anchor handles
|
||||||
|
if (canvas_item->cast_to<Control>()) {
|
||||||
|
drag = _get_anchor_handle_drag_type(click, drag_point_from);
|
||||||
|
if (drag != DRAG_NONE) {
|
||||||
|
drag_from = transform.affine_inverse().xform(click);
|
||||||
|
se->undo_state = canvas_item->edit_get_state();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1432,9 +1487,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (drag == DRAG_NONE) {
|
if (drag == DRAG_NONE) {
|
||||||
|
|
||||||
if ((m->get_button_mask() & BUTTON_MASK_LEFT && tool == TOOL_PAN) || m->get_button_mask() & BUTTON_MASK_MIDDLE || (m->get_button_mask() & BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
|
if ((m->get_button_mask() & BUTTON_MASK_LEFT && tool == TOOL_PAN) || m->get_button_mask() & BUTTON_MASK_MIDDLE || (m->get_button_mask() & BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE))) {
|
||||||
|
// Pan the viewport
|
||||||
Point2i relative;
|
Point2i relative;
|
||||||
if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) {
|
if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) {
|
||||||
relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect());
|
relative = Input::get_singleton()->warp_mouse_motion(m, viewport->get_global_rect());
|
||||||
@@ -1450,7 +1504,6 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Node *> &selection = editor_selection->get_selected_node_list();
|
List<Node *> &selection = editor_selection->get_selected_node_list();
|
||||||
|
|
||||||
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
|
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
|
||||||
|
|
||||||
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
|
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
|
||||||
@@ -1479,7 +1532,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (drag == DRAG_ROTATE) {
|
if (drag == DRAG_ROTATE) {
|
||||||
|
// Rotate the node
|
||||||
Vector2 center = canvas_item->get_global_transform_with_canvas().get_origin();
|
Vector2 center = canvas_item->get_global_transform_with_canvas().get_origin();
|
||||||
{
|
{
|
||||||
Node2D *node = canvas_item->cast_to<Node2D>();
|
Node2D *node = canvas_item->cast_to<Node2D>();
|
||||||
@@ -1508,10 +1561,40 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Control *control = canvas_item->cast_to<Control>();
|
||||||
|
if (control) {
|
||||||
|
Vector2 anchor = _position_to_anchor(control, canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto - drag_from + drag_point_from));
|
||||||
|
|
||||||
|
switch (drag) {
|
||||||
|
// Handles anchor dragging
|
||||||
|
case DRAG_ANCHOR_TOP_LEFT:
|
||||||
|
control->set_anchor(MARGIN_LEFT, anchor.x);
|
||||||
|
control->set_anchor(MARGIN_TOP, anchor.y);
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case DRAG_ANCHOR_TOP_RIGHT:
|
||||||
|
control->set_anchor(MARGIN_RIGHT, anchor.x);
|
||||||
|
control->set_anchor(MARGIN_TOP, anchor.y);
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case DRAG_ANCHOR_BOTTOM_RIGHT:
|
||||||
|
control->set_anchor(MARGIN_RIGHT, anchor.x);
|
||||||
|
control->set_anchor(MARGIN_BOTTOM, anchor.y);
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case DRAG_ANCHOR_BOTTOM_LEFT:
|
||||||
|
control->set_anchor(MARGIN_LEFT, anchor.x);
|
||||||
|
control->set_anchor(MARGIN_BOTTOM, anchor.y);
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool uniform = m->get_shift();
|
bool uniform = m->get_shift();
|
||||||
bool symmetric = m->get_alt();
|
bool symmetric = m->get_alt();
|
||||||
|
|
||||||
dto = dto - (drag == DRAG_ALL || drag == DRAG_NODE_2D ? drag_from - drag_point_from : Vector2(0, 0));
|
if (drag == DRAG_ALL || drag == DRAG_NODE_2D)
|
||||||
|
dto -= drag_from - drag_point_from;
|
||||||
|
|
||||||
if (uniform && (drag == DRAG_ALL || drag == DRAG_NODE_2D)) {
|
if (uniform && (drag == DRAG_ALL || drag == DRAG_NODE_2D)) {
|
||||||
if (ABS(dto.x - drag_point_from.x) > ABS(dto.y - drag_point_from.y)) {
|
if (ABS(dto.x - drag_point_from.x) > ABS(dto.y - drag_point_from.y)) {
|
||||||
|
|||||||
@@ -144,11 +144,14 @@ class CanvasItemEditor : public VBoxContainer {
|
|||||||
DRAG_BOTTOM_RIGHT,
|
DRAG_BOTTOM_RIGHT,
|
||||||
DRAG_BOTTOM,
|
DRAG_BOTTOM,
|
||||||
DRAG_BOTTOM_LEFT,
|
DRAG_BOTTOM_LEFT,
|
||||||
|
DRAG_ANCHOR_TOP_LEFT,
|
||||||
|
DRAG_ANCHOR_TOP_RIGHT,
|
||||||
|
DRAG_ANCHOR_BOTTOM_RIGHT,
|
||||||
|
DRAG_ANCHOR_BOTTOM_LEFT,
|
||||||
DRAG_ALL,
|
DRAG_ALL,
|
||||||
DRAG_ROTATE,
|
DRAG_ROTATE,
|
||||||
DRAG_PIVOT,
|
DRAG_PIVOT,
|
||||||
DRAG_NODE_2D,
|
DRAG_NODE_2D,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum KeyMoveMODE {
|
enum KeyMoveMODE {
|
||||||
@@ -327,10 +330,12 @@ class CanvasItemEditor : public VBoxContainer {
|
|||||||
void _key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE p_move_mode);
|
void _key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE p_move_mode);
|
||||||
void _list_select(const Ref<InputEventMouseButton> &b);
|
void _list_select(const Ref<InputEventMouseButton> &b);
|
||||||
|
|
||||||
DragType _find_drag_type(const Point2 &p_click, Vector2 &r_point);
|
DragType _get_resize_handle_drag_type(const Point2 &p_click, Vector2 &r_point);
|
||||||
void _prepare_drag(const Point2 &p_click_pos);
|
void _prepare_drag(const Point2 &p_click_pos);
|
||||||
|
DragType _get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point);
|
||||||
|
|
||||||
Vector2 _anchor_to_position(Control *p_control, Vector2 anchor);
|
Vector2 _anchor_to_position(Control *p_control, Vector2 anchor);
|
||||||
|
Vector2 _position_to_anchor(Control *p_control, Vector2 position);
|
||||||
|
|
||||||
void _popup_callback(int p_op);
|
void _popup_callback(int p_op);
|
||||||
bool updating_scroll;
|
bool updating_scroll;
|
||||||
|
|||||||
Reference in New Issue
Block a user