summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
authorJuan Linietsky <juan@godotengine.org>2018-02-25 12:06:30 -0300
committerJuan Linietsky <juan@godotengine.org>2018-02-25 12:07:13 -0300
commit125fc8cc4432d28e63da76c3a2aff655b1a7cc6b (patch)
treef25f62ae4acc2e7a1512d9ed101c791e5f2ca50d /editor
parenteec9261a75699723f6e4b722910e5bb762b736db (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.svg72
-rw-r--r--editor/icons/icon_delete_split.svg95
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp192
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.h9
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;