diff options
author | Juan Linietsky <juan@godotengine.org> | 2018-02-25 12:06:30 -0300 |
---|---|---|
committer | Juan Linietsky <juan@godotengine.org> | 2018-02-25 12:07:13 -0300 |
commit | 125fc8cc4432d28e63da76c3a2aff655b1a7cc6b (patch) | |
tree | f25f62ae4acc2e7a1512d9ed101c791e5f2ca50d /editor | |
parent | eec9261a75699723f6e4b722910e5bb762b736db (diff) |
Add a split editor to polygon 2D UV editor, moving an inch closer to adding support for in the future
Diffstat (limited to 'editor')
-rw-r--r-- | editor/icons/icon_add_split.svg | 72 | ||||
-rw-r--r-- | editor/icons/icon_delete_split.svg | 95 | ||||
-rw-r--r-- | editor/plugins/polygon_2d_editor_plugin.cpp | 192 | ||||
-rw-r--r-- | editor/plugins/polygon_2d_editor_plugin.h | 9 |
4 files changed, 351 insertions, 17 deletions
diff --git a/editor/icons/icon_add_split.svg b/editor/icons/icon_add_split.svg new file mode 100644 index 0000000000..6cfd419e7f --- /dev/null +++ b/editor/icons/icon_add_split.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg4" + sodipodi:docname="icon_add_split.svg" + inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="3066" + inkscape:window-height="1689" + id="namedview6" + showgrid="false" + inkscape:zoom="41.7193" + inkscape:cx="7.7924561" + inkscape:cy="6.0148972" + inkscape:window-x="134" + inkscape:window-y="55" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <rect + style="fill:#800000" + id="rect12" + width="1.8456686" + height="2.0853658" + x="0.62321275" + y="6.9394455" /> + <rect + style="fill:#800000" + id="rect14" + width="1.6299411" + height="1.9894869" + x="12.488225" + y="7.1791425" /> + <rect + style="fill:#e9afaf" + id="rect16" + width="10.067283" + height="0.69512194" + x="2.492851" + y="7.7304463" /> +</svg> diff --git a/editor/icons/icon_delete_split.svg b/editor/icons/icon_delete_split.svg new file mode 100644 index 0000000000..c24f7449d6 --- /dev/null +++ b/editor/icons/icon_delete_split.svg @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="16" + height="16" + version="1.1" + viewBox="0 0 16 16" + id="svg4" + sodipodi:docname="icon_delete_split.svg" + inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="3066" + inkscape:window-height="1689" + id="namedview6" + showgrid="false" + inkscape:zoom="41.7193" + inkscape:cx="7.7924561" + inkscape:cy="6.0148972" + inkscape:window-x="134" + inkscape:window-y="55" + inkscape:window-maximized="1" + inkscape:current-layer="svg4" /> + <rect + style="fill:#800000" + id="rect12" + width="1.8456686" + height="2.0853658" + x="0.62321275" + y="6.9394455" /> + <rect + style="fill:#800000" + id="rect14" + width="1.6299411" + height="1.9894869" + x="12.488225" + y="7.1791425" /> + <rect + style="fill:#e9afaf" + id="rect37" + width="3.1640031" + height="0.40748528" + x="2.5407906" + y="7.9701433" /> + <rect + style="fill:#e9afaf" + id="rect39" + width="3.5235491" + height="0.52733386" + x="9.0126152" + y="8.0420523" /> + <rect + style="fill:#e9afaf" + id="rect41" + width="3.6433976" + height="0.4554247" + x="1.5110972" + y="-9.732645" + transform="rotate(123.99908)" /> + <rect + style="fill:#e9afaf" + id="rect41-3" + width="3.6433976" + height="0.4554247" + x="0.072069742" + y="-12.144793" + transform="rotate(123.99908)" /> +</svg> diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index f106d2a78e..3a169bd780 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -64,6 +64,8 @@ void Polygon2DEditor::_notification(int p_what) { uv_button[UV_MODE_MOVE]->set_icon(get_icon("ToolMove", "EditorIcons")); uv_button[UV_MODE_ROTATE]->set_icon(get_icon("ToolRotate", "EditorIcons")); uv_button[UV_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons")); + uv_button[UV_MODE_ADD_SPLIT]->set_icon(get_icon("AddSplit", "EditorIcons")); + uv_button[UV_MODE_REMOVE_SPLIT]->set_icon(get_icon("DeleteSplit", "EditorIcons")); b_snap_grid->set_icon(get_icon("Grid", "EditorIcons")); b_snap_enable->set_icon(get_icon("SnapGrid", "EditorIcons")); @@ -79,12 +81,28 @@ void Polygon2DEditor::_notification(int p_what) { void Polygon2DEditor::_uv_edit_mode_select(int p_mode) { if (p_mode == 0) { - if (uv_button[UV_MODE_CREATE]->is_pressed()) { - _uv_mode(1); - } uv_button[UV_MODE_CREATE]->hide(); + for (int i = UV_MODE_MOVE; i <= UV_MODE_SCALE; i++) { + uv_button[i]->show(); + } + uv_button[UV_MODE_ADD_SPLIT]->hide(); + uv_button[UV_MODE_REMOVE_SPLIT]->hide(); + _uv_mode(UV_MODE_EDIT_POINT); + + } else if (p_mode == 1) { + for (int i = 0; i <= UV_MODE_SCALE; i++) { + uv_button[i]->show(); + } + uv_button[UV_MODE_ADD_SPLIT]->hide(); + uv_button[UV_MODE_REMOVE_SPLIT]->hide(); + _uv_mode(UV_MODE_EDIT_POINT); } else { - uv_button[UV_MODE_CREATE]->show(); + for (int i = 0; i <= UV_MODE_SCALE; i++) { + uv_button[i]->hide(); + } + uv_button[UV_MODE_ADD_SPLIT]->show(); + uv_button[UV_MODE_REMOVE_SPLIT]->show(); + _uv_mode(UV_MODE_ADD_SPLIT); } uv_edit_draw->update(); @@ -195,6 +213,10 @@ void Polygon2DEditor::_set_snap_step_y(float p_val) { void Polygon2DEditor::_uv_mode(int p_mode) { + split_create = false; + uv_drag = false; + uv_create = false; + uv_mode = UVMode(p_mode); for (int i = 0; i < UV_MODE_MAX; i++) { uv_button[i]->set_pressed(p_mode == i); @@ -219,10 +241,11 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_drag = true; uv_prev = node->get_uv(); - if (uv_edit_mode[0]->is_pressed()) //edit uv + if (uv_edit_mode[0]->is_pressed()) { //edit uv uv_prev = node->get_uv(); - else + } else { //edit polygon uv_prev = node->get_polygon(); + } uv_move_current = uv_mode; if (uv_move_current == UV_MODE_CREATE) { @@ -238,6 +261,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_create = true; uv_create_uv_prev = node->get_uv(); uv_create_poly_prev = node->get_polygon(); + splits_prev = node->get_splits(); node->set_polygon(uv_prev); node->set_uv(uv_prev); @@ -292,6 +316,109 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_drag = false; } } + + if (uv_move_current == UV_MODE_ADD_SPLIT) { + + int drag_index = -1; + drag_index = -1; + for (int i = 0; i < uv_prev.size(); i++) { + + Vector2 tuv = mtx.xform(uv_prev[i]); + if (tuv.distance_to(Vector2(mb->get_position().x, mb->get_position().y)) < 8) { + drag_index = i; + } + } + + if (drag_index == -1) { + split_create = false; + return; + } + + if (split_create) { + + split_create = false; + if (drag_index < uv_drag_index) { + SWAP(drag_index, uv_drag_index); + } + bool valid = true; + if (drag_index == uv_drag_index) { + valid = false; + } + if (drag_index + 1 == uv_drag_index) { + //not a split,goes along the edge + valid = false; + } + if (drag_index == uv_prev.size() - 1 && uv_drag_index == 0) { + //not a split,goes along the edge + valid = false; + } + for (int i = 0; i < splits_prev.size(); i += 2) { + if (splits_prev[i] == uv_drag_index && splits_prev[i + 1] == drag_index) { + //already exists + valid = false; + } + if (splits_prev[i] > uv_drag_index && splits_prev[i + 1] > drag_index) { + //crossing + valid = false; + } + + if (splits_prev[i] < uv_drag_index && splits_prev[i + 1] < drag_index) { + //crossing opposite direction + valid = false; + } + } + + if (valid) { + + splits_prev.push_back(uv_drag_index); + splits_prev.push_back(drag_index); + + undo_redo->create_action(TTR("Add Split")); + + undo_redo->add_do_method(node, "set_splits", splits_prev); + undo_redo->add_undo_method(node, "set_splits", node->get_splits()); + undo_redo->add_do_method(uv_edit_draw, "update"); + undo_redo->add_undo_method(uv_edit_draw, "update"); + undo_redo->commit_action(); + } else { + error->set_text(TTR("Invalid Split")); + error->popup_centered_minsize(); + } + + } else { + uv_drag_index = drag_index; + split_create = true; + uv_create_to = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y)); + } + } + + if (uv_move_current == UV_MODE_REMOVE_SPLIT) { + + for (int i = 0; i < splits_prev.size(); i += 2) { + if (splits_prev[i] < 0 || splits_prev[i] >= uv_prev.size()) + continue; + if (splits_prev[i + 1] < 0 || splits_prev[i] >= uv_prev.size()) + continue; + Vector2 e[2] = { mtx.xform(uv_prev[splits_prev[i]]), mtx.xform(uv_prev[splits_prev[i + 1]]) }; + Vector2 mp = Vector2(mb->get_position().x, mb->get_position().y); + Vector2 cp = Geometry::get_closest_point_to_segment_2d(mp, e); + if (cp.distance_to(mp) < 8) { + splits_prev.remove(i); + splits_prev.remove(i); + + undo_redo->create_action(TTR("Remove Split")); + + undo_redo->add_do_method(node, "set_splits", splits_prev); + undo_redo->add_undo_method(node, "set_splits", node->get_splits()); + undo_redo->add_do_method(uv_edit_draw, "update"); + undo_redo->add_undo_method(uv_edit_draw, "update"); + undo_redo->commit_action(); + + break; + } + } + } + } else if (uv_drag && !uv_create) { undo_redo->create_action(TTR("Transform UV Map")); @@ -299,7 +426,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { if (uv_edit_mode[0]->is_pressed()) { //edit uv undo_redo->add_do_method(node, "set_uv", node->get_uv()); undo_redo->add_undo_method(node, "set_uv", uv_prev); - } else { + } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon undo_redo->add_do_method(node, "set_polygon", node->get_polygon()); undo_redo->add_undo_method(node, "set_polygon", uv_prev); } @@ -318,16 +445,20 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_create = false; node->set_uv(uv_create_uv_prev); node->set_polygon(uv_create_poly_prev); + node->set_splits(splits_prev); uv_edit_draw->update(); } else if (uv_drag) { uv_drag = false; if (uv_edit_mode[0]->is_pressed()) { //edit uv node->set_uv(uv_prev); - } else { + } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon node->set_polygon(uv_prev); } uv_edit_draw->update(); + } else if (split_create) { + split_create = false; + uv_edit_draw->update(); } } else if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) { @@ -368,7 +499,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { if (uv_edit_mode[0]->is_pressed()) { //edit uv node->set_uv(uv_new); - } else { + } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon node->set_polygon(uv_new); } } break; @@ -380,7 +511,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { if (uv_edit_mode[0]->is_pressed()) { //edit uv node->set_uv(uv_new); - } else { + } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon node->set_polygon(uv_new); } @@ -404,7 +535,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { if (uv_edit_mode[0]->is_pressed()) { //edit uv node->set_uv(uv_new); - } else { + } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon node->set_polygon(uv_new); } @@ -433,12 +564,15 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { if (uv_edit_mode[0]->is_pressed()) { //edit uv node->set_uv(uv_new); - } else { + } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon node->set_polygon(uv_new); } } break; } uv_edit_draw->update(); + } else if (split_create) { + uv_create_to = mtx.affine_inverse().xform(Vector2(mm->get_position().x, mm->get_position().y)); + uv_edit_draw->update(); } } @@ -509,10 +643,11 @@ void Polygon2DEditor::_uv_draw() { } PoolVector<Vector2> uvs; - if (uv_edit_mode[0]->is_pressed()) //edit uv + if (uv_edit_mode[0]->is_pressed()) { //edit uv uvs = node->get_uv(); - else + } else { //edit polygon uvs = node->get_polygon(); + } Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); @@ -531,6 +666,22 @@ void Polygon2DEditor::_uv_draw() { rect.expand_to(mtx.basis_xform(uvs[i])); } + if (split_create) { + Vector2 from = uvs[uv_drag_index]; + Vector2 to = uv_create_to; + uv_edit_draw->draw_line(mtx.xform(from), mtx.xform(to), Color(0.9, 0.5, 0.5), 2); + } + + PoolVector<int> splits = node->get_splits(); + + for (int i = 0; i < splits.size(); i += 2) { + int idx_from = splits[i]; + int idx_to = splits[i + 1]; + if (idx_from < 0 || idx_to >= uvs.size()) + continue; + uv_edit_draw->draw_line(mtx.xform(uvs[idx_from]), mtx.xform(uvs[idx_to]), Color(0.9, 0.5, 0.5), 2); + } + rect = rect.grow(200); updating_uv_scroll = true; uv_hscroll->set_min(rect.position.x); @@ -601,16 +752,22 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_edit_mode[1] = memnew(ToolButton); uv_mode_hb->add_child(uv_edit_mode[1]); uv_edit_mode[1]->set_toggle_mode(true); + uv_edit_mode[2] = memnew(ToolButton); + uv_mode_hb->add_child(uv_edit_mode[2]); + uv_edit_mode[2]->set_toggle_mode(true); uv_edit_mode[0]->set_text(TTR("UV")); uv_edit_mode[0]->set_pressed(true); uv_edit_mode[1]->set_text(TTR("Poly")); + uv_edit_mode[2]->set_text(TTR("Splits")); uv_edit_mode[0]->set_button_group(uv_edit_group); uv_edit_mode[1]->set_button_group(uv_edit_group); + uv_edit_mode[2]->set_button_group(uv_edit_group); uv_edit_mode[0]->connect("pressed", this, "_uv_edit_mode_select", varray(0)); uv_edit_mode[1]->connect("pressed", this, "_uv_edit_mode_select", varray(1)); + uv_edit_mode[2]->connect("pressed", this, "_uv_edit_mode_select", varray(2)); uv_mode_hb->add_child(memnew(VSeparator)); @@ -629,8 +786,12 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_button[2]->set_tooltip(TTR("Move Polygon")); uv_button[3]->set_tooltip(TTR("Rotate Polygon")); uv_button[4]->set_tooltip(TTR("Scale Polygon")); + uv_button[5]->set_tooltip(TTR("Connect two points to make a split")); + uv_button[6]->set_tooltip(TTR("Select a split to erase it")); uv_button[0]->hide(); + uv_button[5]->hide(); + uv_button[6]->hide(); uv_button[1]->set_pressed(true); HBoxContainer *uv_main_hb = memnew(HBoxContainer); uv_main_vb->add_child(uv_main_hb); @@ -737,8 +898,9 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_draw_zoom = 1.0; uv_drag_index = -1; uv_drag = false; - uv_create = true; + uv_create = false; updating_uv_scroll = false; + split_create = false; error = memnew(AcceptDialog); add_child(error); diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index 2ea2082052..8631ffb9a7 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -55,17 +55,19 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { UV_MODE_MOVE, UV_MODE_ROTATE, UV_MODE_SCALE, + UV_MODE_ADD_SPLIT, + UV_MODE_REMOVE_SPLIT, UV_MODE_MAX }; - ToolButton *uv_edit_mode[2]; + ToolButton *uv_edit_mode[3]; Ref<ButtonGroup> uv_edit_group; Polygon2D *node; UVMode uv_mode; AcceptDialog *uv_edit; - ToolButton *uv_button[5]; + ToolButton *uv_button[UV_MODE_MAX]; ToolButton *b_snap_enable; ToolButton *b_snap_grid; Control *uv_edit_draw; @@ -81,10 +83,13 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { PoolVector<Vector2> uv_prev; PoolVector<Vector2> uv_create_uv_prev; PoolVector<Vector2> uv_create_poly_prev; + PoolVector<int> splits_prev; + Vector2 uv_create_to; int uv_drag_index; bool uv_drag; bool uv_create; + bool split_create; UVMode uv_move_current; Vector2 uv_drag_from; bool updating_uv_scroll; |