diff options
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.cpp | 58 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.h | 1 | ||||
-rw-r--r-- | scene/gui/control.cpp | 42 | ||||
-rw-r--r-- | scene/gui/control.h | 6 |
4 files changed, 96 insertions, 11 deletions
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 7c6b233bd4..e51254f84b 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -199,6 +199,25 @@ void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) { undo_redo->add_undo_method(n2dc, "set_global_position", n2dc->get_global_position()); } } + + Control *cnt = E->get()->cast_to<Control>(); + if (cnt) { + + Vector2 old_pivot = cnt->get_pivot_offset(); + Vector2 new_pivot = cnt->get_global_transform_with_canvas().affine_inverse().xform(mouse_pos); + Vector2 old_pos = cnt->get_position(); + + Vector2 top_pos = cnt->get_transform().get_origin(); //remember where top pos was + cnt->set_pivot_offset(new_pivot); + Vector2 new_top_pos = cnt->get_transform().get_origin(); //check where it is now + + Vector2 new_pos = old_pos - (new_top_pos - top_pos); //offset it back + + undo_redo->add_do_method(cnt, "set_pivot_offset", new_pivot); + undo_redo->add_do_method(cnt, "set_position", new_pos); + undo_redo->add_undo_method(cnt, "set_pivot_offset", old_pivot); + undo_redo->add_undo_method(cnt, "set_position", old_pos); + } } undo_redo->commit_action(); @@ -842,6 +861,8 @@ void CanvasItemEditor::_prepare_drag(const Point2 &p_click_pos) { se->undo_state = canvas_item->edit_get_state(); if (canvas_item->cast_to<Node2D>()) se->undo_pivot = canvas_item->cast_to<Node2D>()->edit_get_pivot(); + if (canvas_item->cast_to<Control>()) + se->undo_pivot = canvas_item->cast_to<Control>()->get_pivot_offset(); } if (selection.size() == 1 && selection[0]->cast_to<Node2D>()) { @@ -1149,6 +1170,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { canvas_item->edit_set_state(se->undo_state); if (canvas_item->cast_to<Node2D>()) canvas_item->cast_to<Node2D>()->edit_set_pivot(se->undo_pivot); + if (canvas_item->cast_to<Node2D>()) + canvas_item->cast_to<Control>()->set_pivot_offset(se->undo_pivot); } } @@ -1238,12 +1261,18 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { Variant state = canvas_item->edit_get_state(); undo_redo->add_do_method(canvas_item, "edit_set_state", state); undo_redo->add_undo_method(canvas_item, "edit_set_state", se->undo_state); - if (canvas_item->cast_to<Node2D>()) { + { Node2D *pvt = canvas_item->cast_to<Node2D>(); - if (pvt->edit_has_pivot()) { + if (pvt && pvt->edit_has_pivot()) { undo_redo->add_do_method(canvas_item, "edit_set_pivot", pvt->edit_get_pivot()); undo_redo->add_undo_method(canvas_item, "edit_set_pivot", se->undo_pivot); } + + Control *cnt = canvas_item->cast_to<Control>(); + if (cnt) { + undo_redo->add_do_method(canvas_item, "set_pivot_offset", cnt->get_pivot_offset()); + undo_redo->add_undo_method(canvas_item, "set_pivot_offset", se->undo_pivot); + } } } undo_redo->commit_action(); @@ -1380,7 +1409,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { if (canvas_item->cast_to<Node2D>()) se->undo_pivot = canvas_item->cast_to<Node2D>()->edit_get_pivot(); if (canvas_item->cast_to<Control>()) - se->undo_pivot = Vector2(); + se->undo_pivot = canvas_item->cast_to<Control>()->get_pivot_offset(); return; } @@ -1405,6 +1434,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { se->undo_state = canvas_item->edit_get_state(); if (canvas_item->cast_to<Node2D>()) se->undo_pivot = canvas_item->cast_to<Node2D>()->edit_get_pivot(); + if (canvas_item->cast_to<Control>()) + se->undo_pivot = canvas_item->cast_to<Control>()->get_pivot_offset(); return; } @@ -1522,6 +1553,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { canvas_item->edit_set_state(se->undo_state); //reset state and reapply if (canvas_item->cast_to<Node2D>()) canvas_item->cast_to<Node2D>()->edit_set_pivot(se->undo_pivot); + if (canvas_item->cast_to<Control>()) + canvas_item->cast_to<Control>()->set_pivot_offset(se->undo_pivot); } Vector2 dfrom = drag_from; @@ -1659,6 +1692,9 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) { Node2D *n2d = canvas_item->cast_to<Node2D>(); n2d->edit_set_pivot(se->undo_pivot + drag_vector); } + if (canvas_item->cast_to<Control>()) { + canvas_item->cast_to<Control>()->set_pivot_offset(se->undo_pivot + drag_vector); + } continue; } break; case DRAG_NODE_2D: { @@ -1920,6 +1956,14 @@ void CanvasItemEditor::_viewport_draw() { pivot_found = true; } } + if (canvas_item->cast_to<Control>()) { + Vector2 pivot_ofs = canvas_item->cast_to<Control>()->get_pivot_offset(); + if (pivot_ofs != Vector2()) { + viewport->draw_texture(pivot, xform.xform(pivot_ofs) + (-pivot->get_size() / 2).floor()); + } + can_move_pivot = true; + pivot_found = true; + } if (tool == TOOL_SELECT) { @@ -2108,10 +2152,16 @@ void CanvasItemEditor::_notification(int p_what) { Transform2D xform = canvas_item->get_transform(); - if (r != se->prev_rect || xform != se->prev_xform) { + Vector2 pivot; + if (canvas_item->cast_to<Control>()) { + pivot = canvas_item->cast_to<Control>()->get_pivot_offset(); + } + + if (r != se->prev_rect || xform != se->prev_xform || pivot != se->prev_pivot) { viewport->update(); se->prev_rect = r; se->prev_xform = xform; + se->prev_pivot = pivot; } } diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 22fa5b5db8..702deb51f9 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -56,6 +56,7 @@ public: Transform2D prev_xform; float prev_rot; Rect2 prev_rect; + Vector2 prev_pivot; CanvasItemEditorSelectedItem() { prev_rot = 0; } }; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 51461e9c41..4cb779c21b 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -90,11 +90,22 @@ Size2 Control::edit_get_minimum_size() const { return get_combined_minimum_size(); } +Transform2D Control::_get_internal_transform() const { + + Transform2D rot_scale; + rot_scale.set_rotation_and_scale(data.rotation, data.scale); + Transform2D offset; + offset.set_origin(-data.pivot_offset); + + return offset.affine_inverse() * (rot_scale * offset); +} void Control::edit_set_rect(const Rect2 &p_edit_rect) { - Transform2D postxf; - postxf.set_rotation_and_scale(data.rotation, data.scale); - Vector2 new_pos = postxf.xform(p_edit_rect.position); + Transform2D xform = _get_internal_transform(); + + // xform[2] += get_position(); + + Vector2 new_pos = xform.basis_xform(p_edit_rect.position); Vector2 pos = get_position() + new_pos; @@ -353,8 +364,9 @@ void Control::remove_child_notify(Node *p_child) { void Control::_update_canvas_item_transform() { - Transform2D xform = Transform2D(data.rotation, get_position()); - xform.scale_basis(data.scale); + Transform2D xform = _get_internal_transform(); + xform[2] += get_position(); + VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform); } @@ -1903,8 +1915,8 @@ Control::CursorShape Control::get_cursor_shape(const Point2 &p_pos) const { Transform2D Control::get_transform() const { - Transform2D xform = Transform2D(data.rotation, get_position()); - xform.scale_basis(data.scale); + Transform2D xform = _get_internal_transform(); + xform[2] += get_position(); return xform; } @@ -2230,6 +2242,19 @@ void Control::_font_changed() { minimum_size_changed(); //fonts affect minimum size pretty much almost always } +void Control::set_pivot_offset(const Vector2 &p_pivot) { + + data.pivot_offset = p_pivot; + update(); + _notify_transform(); + _change_notify("rect_pivot_offset"); +} + +Vector2 Control::get_pivot_offset() const { + + return data.pivot_offset; +} + void Control::set_scale(const Vector2 &p_scale) { data.scale = p_scale; @@ -2362,6 +2387,7 @@ void Control::_bind_methods() { // TODO: Obsolete this method (old name) properly (GH-4397) ClassDB::bind_method(D_METHOD("_set_rotation_deg", "degrees"), &Control::_set_rotation_deg); ClassDB::bind_method(D_METHOD("set_scale", "scale"), &Control::set_scale); + ClassDB::bind_method(D_METHOD("set_pivot_offset", "pivot_offset"), &Control::set_pivot_offset); ClassDB::bind_method(D_METHOD("get_margin", "margin"), &Control::get_margin); ClassDB::bind_method(D_METHOD("get_begin"), &Control::get_begin); ClassDB::bind_method(D_METHOD("get_end"), &Control::get_end); @@ -2372,6 +2398,7 @@ void Control::_bind_methods() { // TODO: Obsolete this method (old name) properly (GH-4397) ClassDB::bind_method(D_METHOD("_get_rotation_deg"), &Control::_get_rotation_deg); ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale); + ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset); ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size); ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_size); ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position); @@ -2491,6 +2518,7 @@ void Control::_bind_methods() { ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size"); ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "rect_rotation", PROPERTY_HINT_RANGE, "-1080,1080,0.01"), "set_rotation_deg", "get_rotation_deg"); ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale"); + ADD_PROPERTYNO(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset"); ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents"); ADD_GROUP("Hint", "hint_"); diff --git a/scene/gui/control.h b/scene/gui/control.h index f55010a354..92acedd89c 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -127,6 +127,7 @@ private: float rotation; Vector2 scale; + Vector2 pivot_offset; bool pending_resize; @@ -207,6 +208,8 @@ private: void _update_canvas_item_transform(); + Transform2D _get_internal_transform() const; + friend class Viewport; void _modal_stack_remove(); void _modal_set_prev_focus_owner(ObjectID p_prev); @@ -306,6 +309,9 @@ public: float get_rotation() const; float get_rotation_deg() const; + void set_pivot_offset(const Vector2 &p_pivot); + Vector2 get_pivot_offset() const; + void set_scale(const Vector2 &p_scale); Vector2 get_scale() const; |