Make anchors draggable

This commit is contained in:
Gilles Roudiere 2017-07-29 16:57:32 +02:00
parent bd0384a9e9
commit fcff42dcb7
2 changed files with 99 additions and 11 deletions

View File

@ -709,8 +709,8 @@ CanvasItem *CanvasItemEditor::get_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();
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));
}
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) {
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 = _find_drag_type(click, drag_point_from);
// Drag resize handles
drag = _get_resize_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();
@ -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();
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 ((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;
if (bool(EditorSettings::get_singleton()->get("editors/2d/warped_mouse_panning"))) {
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();
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>();
@ -1479,7 +1532,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
continue;
if (drag == DRAG_ROTATE) {
// Rotate the node
Vector2 center = canvas_item->get_global_transform_with_canvas().get_origin();
{
Node2D *node = canvas_item->cast_to<Node2D>();
@ -1508,10 +1561,40 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
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 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 (ABS(dto.x - drag_point_from.x) > ABS(dto.y - drag_point_from.y)) {

View File

@ -144,11 +144,14 @@ class CanvasItemEditor : public VBoxContainer {
DRAG_BOTTOM_RIGHT,
DRAG_BOTTOM,
DRAG_BOTTOM_LEFT,
DRAG_ANCHOR_TOP_LEFT,
DRAG_ANCHOR_TOP_RIGHT,
DRAG_ANCHOR_BOTTOM_RIGHT,
DRAG_ANCHOR_BOTTOM_LEFT,
DRAG_ALL,
DRAG_ROTATE,
DRAG_PIVOT,
DRAG_NODE_2D,
};
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 _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);
DragType _get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point);
Vector2 _anchor_to_position(Control *p_control, Vector2 anchor);
Vector2 _position_to_anchor(Control *p_control, Vector2 position);
void _popup_callback(int p_op);
bool updating_scroll;