From bce3599bd7de6eb1bd65f5d9589b66e261d0f03c Mon Sep 17 00:00:00 2001 From: Robert Morse Date: Sat, 1 Dec 2018 14:45:54 -0600 Subject: [PATCH] Fixed an issue with the Path2D plugin editor not supporting the capability to split curves as its toolbar buttons originally advertised. --- editor/plugins/abstract_polygon_2d_editor.cpp | 8 +- editor/plugins/canvas_item_editor_plugin.cpp | 2 +- .../collision_polygon_editor_plugin.cpp | 2 +- editor/plugins/path_2d_editor_plugin.cpp | 94 +++++++++++++++++-- editor/plugins/path_2d_editor_plugin.h | 2 + 5 files changed, 96 insertions(+), 12 deletions(-) diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index a85f4456f7..e133552761 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -425,7 +425,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref &p_event) return true; } else { - const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); + const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); if (!_is_line() && wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) { //wip closed @@ -565,7 +565,7 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl offset = _get_offset(j); } - if (!wip_active && j == edited_point.polygon && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) { + if (!wip_active && j == edited_point.polygon && EDITOR_GET("editors/poly_editor/show_previous_outline")) { const Color col = Color(0.5, 0.5, 0.5); // FIXME polygon->get_outline_color(); const int n = pre_move_edit.size(); @@ -695,7 +695,7 @@ AbstractPolygon2DEditor::Vertex AbstractPolygon2DEditor::get_active_point() cons AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_point(const Vector2 &p_pos) const { - const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); + const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); const int n_polygons = _get_polygon_count(); const Transform2D xform = canvas_item_editor->get_canvas_transform() * _get_node()->get_global_transform(); @@ -726,7 +726,7 @@ AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_point(const AbstractPolygon2DEditor::PosVertex AbstractPolygon2DEditor::closest_edge_point(const Vector2 &p_pos) const { - const real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); + const real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); const real_t eps = grab_threshold * 2; const real_t eps2 = eps * eps; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 8d9872236c..c272f8d756 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -456,7 +456,7 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no if (Object::cast_to(p_node)) return; - const real_t grab_distance = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); + const real_t grab_distance = EDITOR_GET("editors/poly_editor/point_grab_radius"); CanvasItem *canvas_item = Object::cast_to(p_node); for (int i = p_node->get_child_count() - 1; i >= 0; i--) { diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp index e92a91db7c..9b31f2e24d 100644 --- a/editor/plugins/collision_polygon_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_editor_plugin.cpp @@ -144,7 +144,7 @@ bool Polygon3DEditor::forward_spatial_gui_input(Camera *p_camera, const Ref poly = node->call("get_polygon"); //first check if a point is to be added (segment split) - real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); + real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); switch (mode) { diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index c67c96798a..3d4816b17b 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -70,8 +70,9 @@ bool Path2DEditor::forward_gui_input(const Ref &p_event) { if (!node->get_curve().is_valid()) return false; - Ref mb = p_event; + real_t grab_threshold = EDITOR_GET("editors/poly_editor/point_grab_radius"); + Ref mb = p_event; if (mb.is_valid()) { Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); @@ -79,8 +80,6 @@ bool Path2DEditor::forward_gui_input(const Ref &p_event) { Vector2 gpoint = mb->get_position(); Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); - real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); - if (mb->is_pressed() && action == ACTION_NONE) { Ref curve = node->get_curve(); @@ -179,6 +178,41 @@ bool Path2DEditor::forward_gui_input(const Ref &p_event) { return true; } + // Check for segment split. + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && mode == MODE_EDIT && on_edge == true) { + Vector2 gpoint = mb->get_position(); + Ref curve = node->get_curve(); + + int insertion_point = -1; + float mbLength = curve->get_closest_offset(xform.affine_inverse().xform(gpoint)); + int len = curve->get_point_count(); + for (int i = 0; i < len - 1; i++) { + float compareLength = curve->get_closest_offset(curve->get_point_position(i + 1)); + if (mbLength >= curve->get_closest_offset(curve->get_point_position(i)) && mbLength <= compareLength) + insertion_point = i; + } + if (insertion_point == -1) + insertion_point = curve->get_point_count() - 2; + + undo_redo->create_action(TTR("Split Curve")); + undo_redo->add_do_method(curve.ptr(), "add_point", xform.affine_inverse().xform(gpoint), Vector2(0, 0), Vector2(0, 0), insertion_point + 1); + undo_redo->add_undo_method(curve.ptr(), "remove_point", insertion_point + 1); + undo_redo->add_do_method(canvas_item_editor, "update_viewport"); + undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); + undo_redo->commit_action(); + + action = ACTION_MOVING_POINT; + action_point = insertion_point + 1; + moving_from = curve->get_point_position(action_point); + moving_screen_from = gpoint; + + canvas_item_editor->update_viewport(); + + on_edge = false; + + return true; + } + // Check for point movement completion. if (!mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && action != ACTION_NONE) { @@ -245,6 +279,49 @@ bool Path2DEditor::forward_gui_input(const Ref &p_event) { if (mm.is_valid()) { + if (action == ACTION_NONE && mode == MODE_EDIT) { + // Handle Edge Follow + bool old_edge = on_edge; + + Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); + Vector2 gpoint = mm->get_position(); + + Ref curve = node->get_curve(); + if (curve == NULL) return true; + if (curve->get_point_count() < 2) return true; + + // Find edge + edge_point = xform.xform(curve->get_closest_point(xform.affine_inverse().xform(mm->get_position()))); + on_edge = false; + if (edge_point.distance_to(gpoint) <= grab_threshold) { + on_edge = true; + } + // However, if near a control point or its in-out handles then not on edge + int len = curve->get_point_count(); + for (int i = 0; i < len; i++) { + Vector2 pp = curve->get_point_position(i); + Vector2 p = xform.xform(pp); + if (p.distance_to(gpoint) <= grab_threshold) { + on_edge = false; + break; + } + p = xform.xform(pp + curve->get_point_in(i)); + if (p.distance_to(gpoint) <= grab_threshold) { + on_edge = false; + break; + } + p = xform.xform(pp + curve->get_point_out(i)); + if (p.distance_to(gpoint) <= grab_threshold) { + on_edge = false; + break; + } + } + if (on_edge || old_edge != on_edge) { + canvas_item_editor->update_viewport(); + return true; + } + } + if (action != ACTION_NONE) { // Handle point/control movement. Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); @@ -309,7 +386,6 @@ void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { Control *vpc = canvas_item_editor->get_viewport_control(); for (int i = 0; i < len; i++) { - Vector2 point = xform.xform(curve->get_point_position(i)); vpc->draw_texture_rect(handle, Rect2(point - handle_size * 0.5, handle_size), false, Color(1, 1, 1, 1)); @@ -325,6 +401,11 @@ void Path2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { vpc->draw_texture_rect(handle, Rect2(pointin - handle_size * 0.5, handle_size), false, Color(1, 0.5, 1, 0.3)); } } + + if (on_edge) { + Ref add_handle = get_icon("EditorHandleAdd", "EditorIcons"); + p_overlay->draw_texture(add_handle, edge_point - add_handle->get_size() * 0.5); + } } void Path2DEditor::_node_visibility_changed() { @@ -442,6 +523,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) { undo_redo = editor->get_undo_redo(); mirror_handle_angle = true; mirror_handle_length = true; + on_edge = false; mode = MODE_EDIT; action = ACTION_NONE; @@ -455,7 +537,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) { curve_edit->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveEdit", "EditorIcons")); curve_edit->set_toggle_mode(true); curve_edit->set_focus_mode(Control::FOCUS_NONE); - curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point")); + curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point")); curve_edit->connect("pressed", this, "_mode_selected", varray(MODE_EDIT)); base_hb->add_child(curve_edit); curve_edit_curve = memnew(ToolButton); @@ -469,7 +551,7 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) { curve_create->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("CurveCreate", "EditorIcons")); curve_create->set_toggle_mode(true); curve_create->set_focus_mode(Control::FOCUS_NONE); - curve_create->set_tooltip(TTR("Add Point (in empty space)") + "\n" + TTR("Split Segment (in curve)")); + curve_create->set_tooltip(TTR("Add Point (in empty space)")); curve_create->connect("pressed", this, "_mode_selected", varray(MODE_CREATE)); base_hb->add_child(curve_create); curve_del = memnew(ToolButton); diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h index 3a78657746..34952b473a 100644 --- a/editor/plugins/path_2d_editor_plugin.h +++ b/editor/plugins/path_2d_editor_plugin.h @@ -73,6 +73,7 @@ class Path2DEditor : public HBoxContainer { bool mirror_handle_angle; bool mirror_handle_length; + bool on_edge; enum HandleOption { HANDLE_OPTION_ANGLE, @@ -93,6 +94,7 @@ class Path2DEditor : public HBoxContainer { Point2 moving_screen_from; float orig_in_length; float orig_out_length; + Vector2 edge_point; void _mode_selected(int p_mode); void _handle_option_pressed(int p_option);