1/**************************************************************************/
2/* polygon_2d_editor_plugin.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "polygon_2d_editor_plugin.h"
32
33#include "core/input/input_event.h"
34#include "core/math/geometry_2d.h"
35#include "editor/editor_node.h"
36#include "editor/editor_scale.h"
37#include "editor/editor_settings.h"
38#include "editor/editor_undo_redo_manager.h"
39#include "editor/plugins/canvas_item_editor_plugin.h"
40#include "scene/2d/skeleton_2d.h"
41#include "scene/gui/check_box.h"
42#include "scene/gui/dialogs.h"
43#include "scene/gui/label.h"
44#include "scene/gui/menu_button.h"
45#include "scene/gui/panel.h"
46#include "scene/gui/scroll_container.h"
47#include "scene/gui/separator.h"
48#include "scene/gui/slider.h"
49#include "scene/gui/spin_box.h"
50#include "scene/gui/split_container.h"
51#include "scene/gui/texture_rect.h"
52#include "scene/gui/view_panner.h"
53
54Node2D *Polygon2DEditor::_get_node() const {
55 return node;
56}
57
58void Polygon2DEditor::_set_node(Node *p_polygon) {
59 node = Object::cast_to<Polygon2D>(p_polygon);
60 _update_polygon_editing_state();
61}
62
63Vector2 Polygon2DEditor::_get_offset(int p_idx) const {
64 return node->get_offset();
65}
66
67int Polygon2DEditor::_get_polygon_count() const {
68 if (node->get_internal_vertex_count() > 0) {
69 return 0; //do not edit if internal vertices exist
70 } else {
71 return 1;
72 }
73}
74
75void Polygon2DEditor::_notification(int p_what) {
76 switch (p_what) {
77 case NOTIFICATION_ENTER_TREE:
78 case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
79 uv_panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EDITOR_GET("editors/panning/simple_panning")));
80 } break;
81
82 case NOTIFICATION_READY: {
83 button_uv->set_icon(get_editor_theme_icon(SNAME("Uv")));
84
85 uv_button[UV_MODE_CREATE]->set_icon(get_editor_theme_icon(SNAME("Edit")));
86 uv_button[UV_MODE_CREATE_INTERNAL]->set_icon(get_editor_theme_icon(SNAME("EditInternal")));
87 uv_button[UV_MODE_REMOVE_INTERNAL]->set_icon(get_editor_theme_icon(SNAME("RemoveInternal")));
88 uv_button[UV_MODE_EDIT_POINT]->set_icon(get_editor_theme_icon(SNAME("ToolSelect")));
89 uv_button[UV_MODE_MOVE]->set_icon(get_editor_theme_icon(SNAME("ToolMove")));
90 uv_button[UV_MODE_ROTATE]->set_icon(get_editor_theme_icon(SNAME("ToolRotate")));
91 uv_button[UV_MODE_SCALE]->set_icon(get_editor_theme_icon(SNAME("ToolScale")));
92 uv_button[UV_MODE_ADD_POLYGON]->set_icon(get_editor_theme_icon(SNAME("Edit")));
93 uv_button[UV_MODE_REMOVE_POLYGON]->set_icon(get_editor_theme_icon(SNAME("Close")));
94 uv_button[UV_MODE_PAINT_WEIGHT]->set_icon(get_editor_theme_icon(SNAME("Bucket")));
95 uv_button[UV_MODE_CLEAR_WEIGHT]->set_icon(get_editor_theme_icon(SNAME("Clear")));
96
97 b_snap_grid->set_icon(get_editor_theme_icon(SNAME("Grid")));
98 b_snap_enable->set_icon(get_editor_theme_icon(SNAME("SnapGrid")));
99 uv_icon_zoom->set_texture(get_editor_theme_icon(SNAME("Zoom")));
100
101 uv_vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE);
102 uv_hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE);
103 [[fallthrough]];
104 }
105 case NOTIFICATION_THEME_CHANGED: {
106 uv_edit_draw->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
107 bone_scroll->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
108 } break;
109
110 case NOTIFICATION_VISIBILITY_CHANGED: {
111 if (!is_visible()) {
112 uv_edit->hide();
113 }
114 } break;
115 }
116}
117
118void Polygon2DEditor::_sync_bones() {
119 Skeleton2D *skeleton = nullptr;
120 if (!node->has_node(node->get_skeleton())) {
121 error->set_text(TTR("The skeleton property of the Polygon2D does not point to a Skeleton2D node"));
122 error->popup_centered();
123 } else {
124 Node *sn = node->get_node(node->get_skeleton());
125 skeleton = Object::cast_to<Skeleton2D>(sn);
126 }
127
128 Array prev_bones = node->call("_get_bones");
129 node->clear_bones();
130
131 if (!skeleton) {
132 error->set_text(TTR("The skeleton property of the Polygon2D does not point to a Skeleton2D node"));
133 error->popup_centered();
134 } else {
135 for (int i = 0; i < skeleton->get_bone_count(); i++) {
136 NodePath path = skeleton->get_path_to(skeleton->get_bone(i));
137 Vector<float> weights;
138 int wc = node->get_polygon().size();
139
140 for (int j = 0; j < prev_bones.size(); j += 2) {
141 NodePath pvp = prev_bones[j];
142 Vector<float> pv = prev_bones[j + 1];
143 if (pvp == path && pv.size() == wc) {
144 weights = pv;
145 }
146 }
147
148 if (weights.size() == 0) { //create them
149 weights.resize(node->get_polygon().size());
150 float *w = weights.ptrw();
151 for (int j = 0; j < wc; j++) {
152 w[j] = 0.0;
153 }
154 }
155
156 node->add_bone(path, weights);
157 }
158 }
159
160 Array new_bones = node->call("_get_bones");
161
162 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
163 undo_redo->create_action(TTR("Sync Bones"));
164 undo_redo->add_do_method(node, "_set_bones", new_bones);
165 undo_redo->add_undo_method(node, "_set_bones", prev_bones);
166 undo_redo->add_do_method(this, "_update_bone_list");
167 undo_redo->add_undo_method(this, "_update_bone_list");
168 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
169 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
170 undo_redo->commit_action();
171}
172
173void Polygon2DEditor::_update_bone_list() {
174 NodePath selected;
175 while (bone_scroll_vb->get_child_count()) {
176 CheckBox *cb = Object::cast_to<CheckBox>(bone_scroll_vb->get_child(0));
177 if (cb && cb->is_pressed()) {
178 selected = cb->get_meta("bone_path");
179 }
180 memdelete(bone_scroll_vb->get_child(0));
181 }
182
183 Ref<ButtonGroup> bg;
184 bg.instantiate();
185 for (int i = 0; i < node->get_bone_count(); i++) {
186 CheckBox *cb = memnew(CheckBox);
187 NodePath np = node->get_bone_path(i);
188 String name;
189 if (np.get_name_count()) {
190 name = np.get_name(np.get_name_count() - 1);
191 }
192 if (name.is_empty()) {
193 name = "Bone " + itos(i);
194 }
195 cb->set_text(name);
196 cb->set_button_group(bg);
197 cb->set_meta("bone_path", np);
198 cb->set_focus_mode(FOCUS_NONE);
199 bone_scroll_vb->add_child(cb);
200
201 if (np == selected || bone_scroll_vb->get_child_count() < 2) {
202 cb->set_pressed(true);
203 }
204
205 cb->connect("pressed", callable_mp(this, &Polygon2DEditor::_bone_paint_selected).bind(i));
206 }
207
208 uv_edit_draw->queue_redraw();
209}
210
211void Polygon2DEditor::_bone_paint_selected(int p_index) {
212 uv_edit_draw->queue_redraw();
213}
214
215void Polygon2DEditor::_uv_edit_mode_select(int p_mode) {
216 if (p_mode == 0) { //uv
217
218 uv_button[UV_MODE_CREATE]->hide();
219 uv_button[UV_MODE_CREATE_INTERNAL]->hide();
220 uv_button[UV_MODE_REMOVE_INTERNAL]->hide();
221 for (int i = UV_MODE_EDIT_POINT; i <= UV_MODE_SCALE; i++) {
222 uv_button[i]->show();
223 }
224 uv_button[UV_MODE_ADD_POLYGON]->hide();
225 uv_button[UV_MODE_REMOVE_POLYGON]->hide();
226 uv_button[UV_MODE_PAINT_WEIGHT]->hide();
227 uv_button[UV_MODE_CLEAR_WEIGHT]->hide();
228 _uv_mode(UV_MODE_EDIT_POINT);
229
230 bone_scroll_main_vb->hide();
231 bone_paint_strength->hide();
232 bone_paint_radius->hide();
233 bone_paint_radius_label->hide();
234 } else if (p_mode == 1) { //poly
235
236 for (int i = 0; i <= UV_MODE_SCALE; i++) {
237 uv_button[i]->show();
238 }
239 uv_button[UV_MODE_ADD_POLYGON]->hide();
240 uv_button[UV_MODE_REMOVE_POLYGON]->hide();
241 uv_button[UV_MODE_PAINT_WEIGHT]->hide();
242 uv_button[UV_MODE_CLEAR_WEIGHT]->hide();
243 _uv_mode(UV_MODE_EDIT_POINT);
244
245 bone_scroll_main_vb->hide();
246 bone_paint_strength->hide();
247 bone_paint_radius->hide();
248 bone_paint_radius_label->hide();
249 } else if (p_mode == 2) { //splits
250
251 for (int i = 0; i <= UV_MODE_SCALE; i++) {
252 uv_button[i]->hide();
253 }
254 uv_button[UV_MODE_ADD_POLYGON]->show();
255 uv_button[UV_MODE_REMOVE_POLYGON]->show();
256 uv_button[UV_MODE_PAINT_WEIGHT]->hide();
257 uv_button[UV_MODE_CLEAR_WEIGHT]->hide();
258 _uv_mode(UV_MODE_ADD_POLYGON);
259
260 bone_scroll_main_vb->hide();
261 bone_paint_strength->hide();
262 bone_paint_radius->hide();
263 bone_paint_radius_label->hide();
264 } else if (p_mode == 3) { //bones´
265
266 for (int i = 0; i <= UV_MODE_REMOVE_POLYGON; i++) {
267 uv_button[i]->hide();
268 }
269 uv_button[UV_MODE_PAINT_WEIGHT]->show();
270 uv_button[UV_MODE_CLEAR_WEIGHT]->show();
271 _uv_mode(UV_MODE_PAINT_WEIGHT);
272
273 bone_scroll_main_vb->show();
274 bone_paint_strength->show();
275 bone_paint_radius->show();
276 bone_paint_radius_label->show();
277 _update_bone_list();
278 bone_paint_pos = Vector2(-100000, -100000); //send brush away when switching
279 }
280
281 uv_edit->set_size(uv_edit->get_size()); // Necessary readjustment of the popup window.
282 uv_edit_draw->queue_redraw();
283}
284
285void Polygon2DEditor::_uv_edit_popup_hide() {
286 EditorSettings::get_singleton()->set("interface/dialogs/uv_editor_bounds", Rect2(uv_edit->get_position(), uv_edit->get_size()));
287
288 _cancel_editing();
289}
290
291void Polygon2DEditor::_menu_option(int p_option) {
292 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
293 switch (p_option) {
294 case MODE_EDIT_UV: {
295 if (node->get_texture().is_null()) {
296 error->set_text(TTR("No texture in this polygon.\nSet a texture to be able to edit UV."));
297 error->popup_centered();
298 return;
299 }
300
301 uv_edit_draw->set_texture_filter(node->get_texture_filter_in_tree());
302
303 Vector<Vector2> points = node->get_polygon();
304 Vector<Vector2> uvs = node->get_uv();
305 if (uvs.size() != points.size()) {
306 undo_redo->create_action(TTR("Create UV Map"));
307 undo_redo->add_do_method(node, "set_uv", points);
308 undo_redo->add_undo_method(node, "set_uv", uvs);
309 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
310 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
311 undo_redo->commit_action();
312 }
313
314 if (EditorSettings::get_singleton()->has_setting("interface/dialogs/uv_editor_bounds")) {
315 uv_edit->popup(EDITOR_GET("interface/dialogs/uv_editor_bounds"));
316 } else {
317 uv_edit->popup_centered_ratio(0.85);
318 }
319 _update_bone_list();
320 } break;
321 case UVEDIT_POLYGON_TO_UV: {
322 Vector<Vector2> points = node->get_polygon();
323 if (points.size() == 0) {
324 break;
325 }
326 Vector<Vector2> uvs = node->get_uv();
327 undo_redo->create_action(TTR("Create UV Map"));
328 undo_redo->add_do_method(node, "set_uv", points);
329 undo_redo->add_undo_method(node, "set_uv", uvs);
330 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
331 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
332 undo_redo->commit_action();
333 } break;
334 case UVEDIT_UV_TO_POLYGON: {
335 Vector<Vector2> points = node->get_polygon();
336 Vector<Vector2> uvs = node->get_uv();
337 if (uvs.size() == 0) {
338 break;
339 }
340
341 undo_redo->create_action(TTR("Create Polygon"));
342 undo_redo->add_do_method(node, "set_polygon", uvs);
343 undo_redo->add_undo_method(node, "set_polygon", points);
344 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
345 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
346 undo_redo->commit_action();
347 } break;
348 case UVEDIT_UV_CLEAR: {
349 Vector<Vector2> uvs = node->get_uv();
350 if (uvs.size() == 0) {
351 break;
352 }
353 undo_redo->create_action(TTR("Create UV Map"));
354 undo_redo->add_do_method(node, "set_uv", Vector<Vector2>());
355 undo_redo->add_undo_method(node, "set_uv", uvs);
356 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
357 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
358 undo_redo->commit_action();
359 } break;
360 case UVEDIT_GRID_SETTINGS: {
361 grid_settings->popup_centered();
362 } break;
363 default: {
364 AbstractPolygon2DEditor::_menu_option(p_option);
365 } break;
366 }
367}
368
369void Polygon2DEditor::_cancel_editing() {
370 if (uv_create) {
371 uv_drag = false;
372 uv_create = false;
373 node->set_uv(uv_create_uv_prev);
374 node->set_polygon(uv_create_poly_prev);
375 node->set_internal_vertex_count(uv_create_prev_internal_vertices);
376 node->set_vertex_colors(uv_create_colors_prev);
377 node->call("_set_bones", uv_create_bones_prev);
378 node->set_polygons(polygons_prev);
379
380 _update_polygon_editing_state();
381 } else if (uv_drag) {
382 uv_drag = false;
383 if (uv_edit_mode[0]->is_pressed()) { // Edit UV.
384 node->set_uv(points_prev);
385 } else if (uv_edit_mode[1]->is_pressed()) { // Edit polygon.
386 node->set_polygon(points_prev);
387 }
388 }
389
390 polygon_create.clear();
391}
392
393void Polygon2DEditor::_update_polygon_editing_state() {
394 if (!_get_node()) {
395 return;
396 }
397
398 if (node->get_internal_vertex_count() > 0) {
399 disable_polygon_editing(true, TTR("Polygon 2D has internal vertices, so it can no longer be edited in the viewport."));
400 } else {
401 disable_polygon_editing(false, String());
402 }
403}
404
405void Polygon2DEditor::_commit_action() {
406 // Makes that undo/redoing actions made outside of the UV editor still affect its polygon.
407 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
408 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
409 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
410 undo_redo->add_do_method(CanvasItemEditor::get_singleton(), "update_viewport");
411 undo_redo->add_undo_method(CanvasItemEditor::get_singleton(), "update_viewport");
412 undo_redo->commit_action();
413}
414
415void Polygon2DEditor::_set_use_snap(bool p_use) {
416 use_snap = p_use;
417 EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_enabled", p_use);
418}
419
420void Polygon2DEditor::_set_show_grid(bool p_show) {
421 snap_show_grid = p_show;
422 EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "show_grid", p_show);
423 uv_edit_draw->queue_redraw();
424}
425
426void Polygon2DEditor::_set_snap_off_x(real_t p_val) {
427 snap_offset.x = p_val;
428 EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_offset", snap_offset);
429 uv_edit_draw->queue_redraw();
430}
431
432void Polygon2DEditor::_set_snap_off_y(real_t p_val) {
433 snap_offset.y = p_val;
434 EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_offset", snap_offset);
435 uv_edit_draw->queue_redraw();
436}
437
438void Polygon2DEditor::_set_snap_step_x(real_t p_val) {
439 snap_step.x = p_val;
440 EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_step", snap_step);
441 uv_edit_draw->queue_redraw();
442}
443
444void Polygon2DEditor::_set_snap_step_y(real_t p_val) {
445 snap_step.y = p_val;
446 EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_step", snap_step);
447 uv_edit_draw->queue_redraw();
448}
449
450void Polygon2DEditor::_uv_mode(int p_mode) {
451 polygon_create.clear();
452 uv_drag = false;
453 uv_create = false;
454
455 uv_mode = UVMode(p_mode);
456 for (int i = 0; i < UV_MODE_MAX; i++) {
457 uv_button[i]->set_pressed(p_mode == i);
458 }
459}
460
461void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) {
462 if (!_get_node()) {
463 return;
464 }
465
466 if (uv_panner->gui_input(p_input)) {
467 accept_event();
468 return;
469 }
470
471 Transform2D mtx;
472 mtx.columns[2] = -uv_draw_ofs;
473 mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom));
474
475 EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton();
476
477 Ref<InputEventMouseButton> mb = p_input;
478 if (mb.is_valid()) {
479 if (mb->get_button_index() == MouseButton::LEFT) {
480 if (mb->is_pressed()) {
481 uv_drag_from = snap_point(mb->get_position());
482 uv_drag = true;
483 points_prev = node->get_uv();
484
485 if (uv_edit_mode[0]->is_pressed()) { //edit uv
486 points_prev = node->get_uv();
487 } else { //edit polygon
488 points_prev = node->get_polygon();
489 }
490
491 uv_move_current = uv_mode;
492 if (uv_move_current == UV_MODE_CREATE) {
493 if (!uv_create) {
494 points_prev.clear();
495 Vector2 tuv = mtx.affine_inverse().xform(snap_point(mb->get_position()));
496 points_prev.push_back(tuv);
497 uv_create_to = tuv;
498 point_drag_index = 0;
499 uv_drag_from = tuv;
500 uv_drag = true;
501 uv_create = true;
502 uv_create_uv_prev = node->get_uv();
503 uv_create_poly_prev = node->get_polygon();
504 uv_create_prev_internal_vertices = node->get_internal_vertex_count();
505 uv_create_colors_prev = node->get_vertex_colors();
506 uv_create_bones_prev = node->call("_get_bones");
507 polygons_prev = node->get_polygons();
508 disable_polygon_editing(false, String());
509 node->set_polygon(points_prev);
510 node->set_uv(points_prev);
511 node->set_internal_vertex_count(0);
512
513 uv_edit_draw->queue_redraw();
514 } else {
515 Vector2 tuv = mtx.affine_inverse().xform(snap_point(mb->get_position()));
516
517 // Close the polygon if selected point is near start. Threshold for closing scaled by zoom level
518 if (points_prev.size() > 2 && tuv.distance_to(points_prev[0]) < (8 / uv_draw_zoom)) {
519 undo_redo->create_action(TTR("Create Polygon & UV"));
520 undo_redo->add_do_method(node, "set_uv", node->get_uv());
521 undo_redo->add_undo_method(node, "set_uv", uv_create_uv_prev);
522 undo_redo->add_do_method(node, "set_polygon", node->get_polygon());
523 undo_redo->add_undo_method(node, "set_polygon", uv_create_poly_prev);
524 undo_redo->add_do_method(node, "set_internal_vertex_count", 0);
525 undo_redo->add_undo_method(node, "set_internal_vertex_count", uv_create_prev_internal_vertices);
526 undo_redo->add_do_method(node, "set_vertex_colors", Vector<Color>());
527 undo_redo->add_undo_method(node, "set_vertex_colors", uv_create_colors_prev);
528 undo_redo->add_do_method(node, "clear_bones");
529 undo_redo->add_undo_method(node, "_set_bones", uv_create_bones_prev);
530 undo_redo->add_do_method(this, "_update_polygon_editing_state");
531 undo_redo->add_undo_method(this, "_update_polygon_editing_state");
532 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
533 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
534 undo_redo->commit_action();
535 uv_drag = false;
536 uv_create = false;
537
538 _uv_mode(UV_MODE_EDIT_POINT);
539 _menu_option(MODE_EDIT);
540 } else {
541 points_prev.push_back(tuv);
542 point_drag_index = points_prev.size() - 1;
543 uv_drag_from = tuv;
544 }
545 node->set_polygon(points_prev);
546 node->set_uv(points_prev);
547 }
548
549 CanvasItemEditor::get_singleton()->update_viewport();
550 }
551
552 if (uv_move_current == UV_MODE_CREATE_INTERNAL) {
553 uv_create_uv_prev = node->get_uv();
554 uv_create_poly_prev = node->get_polygon();
555 uv_create_colors_prev = node->get_vertex_colors();
556 uv_create_bones_prev = node->call("_get_bones");
557 int internal_vertices = node->get_internal_vertex_count();
558
559 Vector2 pos = mtx.affine_inverse().xform(snap_point(mb->get_position()));
560
561 uv_create_poly_prev.push_back(pos);
562 uv_create_uv_prev.push_back(pos);
563 if (uv_create_colors_prev.size()) {
564 uv_create_colors_prev.push_back(Color(1, 1, 1));
565 }
566
567 undo_redo->create_action(TTR("Create Internal Vertex"));
568 undo_redo->add_do_method(node, "set_uv", uv_create_uv_prev);
569 undo_redo->add_undo_method(node, "set_uv", node->get_uv());
570 undo_redo->add_do_method(node, "set_polygon", uv_create_poly_prev);
571 undo_redo->add_undo_method(node, "set_polygon", node->get_polygon());
572 undo_redo->add_do_method(node, "set_vertex_colors", uv_create_colors_prev);
573 undo_redo->add_undo_method(node, "set_vertex_colors", node->get_vertex_colors());
574 for (int i = 0; i < node->get_bone_count(); i++) {
575 Vector<float> bonew = node->get_bone_weights(i);
576 bonew.push_back(0);
577 undo_redo->add_do_method(node, "set_bone_weights", i, bonew);
578 undo_redo->add_undo_method(node, "set_bone_weights", i, node->get_bone_weights(i));
579 }
580 undo_redo->add_do_method(node, "set_internal_vertex_count", internal_vertices + 1);
581 undo_redo->add_undo_method(node, "set_internal_vertex_count", internal_vertices);
582 undo_redo->add_do_method(this, "_update_polygon_editing_state");
583 undo_redo->add_undo_method(this, "_update_polygon_editing_state");
584 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
585 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
586 undo_redo->commit_action();
587 }
588
589 if (uv_move_current == UV_MODE_REMOVE_INTERNAL) {
590 uv_create_uv_prev = node->get_uv();
591 uv_create_poly_prev = node->get_polygon();
592 uv_create_colors_prev = node->get_vertex_colors();
593 uv_create_bones_prev = node->call("_get_bones");
594 int internal_vertices = node->get_internal_vertex_count();
595
596 if (internal_vertices <= 0) {
597 return;
598 }
599
600 int closest = -1;
601 real_t closest_dist = 1e20;
602
603 for (int i = points_prev.size() - internal_vertices; i < points_prev.size(); i++) {
604 Vector2 tuv = mtx.xform(uv_create_poly_prev[i]);
605 real_t dist = tuv.distance_to(mb->get_position());
606 if (dist < 8 && dist < closest_dist) {
607 closest = i;
608 closest_dist = dist;
609 }
610 }
611
612 if (closest == -1) {
613 return;
614 }
615
616 uv_create_poly_prev.remove_at(closest);
617 uv_create_uv_prev.remove_at(closest);
618 if (uv_create_colors_prev.size()) {
619 uv_create_colors_prev.remove_at(closest);
620 }
621
622 undo_redo->create_action(TTR("Remove Internal Vertex"));
623 undo_redo->add_do_method(node, "set_uv", uv_create_uv_prev);
624 undo_redo->add_undo_method(node, "set_uv", node->get_uv());
625 undo_redo->add_do_method(node, "set_polygon", uv_create_poly_prev);
626 undo_redo->add_undo_method(node, "set_polygon", node->get_polygon());
627 undo_redo->add_do_method(node, "set_vertex_colors", uv_create_colors_prev);
628 undo_redo->add_undo_method(node, "set_vertex_colors", node->get_vertex_colors());
629 for (int i = 0; i < node->get_bone_count(); i++) {
630 Vector<float> bonew = node->get_bone_weights(i);
631 bonew.remove_at(closest);
632 undo_redo->add_do_method(node, "set_bone_weights", i, bonew);
633 undo_redo->add_undo_method(node, "set_bone_weights", i, node->get_bone_weights(i));
634 }
635 undo_redo->add_do_method(node, "set_internal_vertex_count", internal_vertices - 1);
636 undo_redo->add_undo_method(node, "set_internal_vertex_count", internal_vertices);
637 undo_redo->add_do_method(this, "_update_polygon_editing_state");
638 undo_redo->add_undo_method(this, "_update_polygon_editing_state");
639 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
640 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
641 undo_redo->commit_action();
642 }
643
644 if (uv_move_current == UV_MODE_EDIT_POINT) {
645 if (mb->is_shift_pressed() && mb->is_command_or_control_pressed()) {
646 uv_move_current = UV_MODE_SCALE;
647 } else if (mb->is_shift_pressed()) {
648 uv_move_current = UV_MODE_MOVE;
649 } else if (mb->is_command_or_control_pressed()) {
650 uv_move_current = UV_MODE_ROTATE;
651 }
652 }
653
654 if (uv_move_current == UV_MODE_EDIT_POINT) {
655 point_drag_index = -1;
656 for (int i = 0; i < points_prev.size(); i++) {
657 Vector2 tuv = mtx.xform(points_prev[i]);
658 if (tuv.distance_to(mb->get_position()) < 8) {
659 uv_drag_from = tuv;
660 point_drag_index = i;
661 }
662 }
663
664 if (point_drag_index == -1) {
665 uv_drag = false;
666 }
667 }
668
669 if (uv_move_current == UV_MODE_ADD_POLYGON) {
670 int closest = -1;
671 real_t closest_dist = 1e20;
672
673 for (int i = 0; i < points_prev.size(); i++) {
674 Vector2 tuv = mtx.xform(points_prev[i]);
675 real_t dist = tuv.distance_to(mb->get_position());
676 if (dist < 8 && dist < closest_dist) {
677 closest = i;
678 closest_dist = dist;
679 }
680 }
681
682 if (closest != -1) {
683 if (polygon_create.size() && closest == polygon_create[0]) {
684 //close
685 if (polygon_create.size() < 3) {
686 error->set_text(TTR("Invalid Polygon (need 3 different vertices)"));
687 error->popup_centered();
688 } else {
689 Array polygons = node->get_polygons();
690 polygons = polygons.duplicate(); //copy because its a reference
691
692 //todo, could check whether it already exists?
693 polygons.push_back(polygon_create);
694 undo_redo->create_action(TTR("Add Custom Polygon"));
695 undo_redo->add_do_method(node, "set_polygons", polygons);
696 undo_redo->add_undo_method(node, "set_polygons", node->get_polygons());
697 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
698 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
699 undo_redo->commit_action();
700 }
701
702 polygon_create.clear();
703 } else if (!polygon_create.has(closest)) {
704 //add temporarily if not exists
705 polygon_create.push_back(closest);
706 }
707 }
708 }
709
710 if (uv_move_current == UV_MODE_REMOVE_POLYGON) {
711 Array polygons = node->get_polygons();
712 polygons = polygons.duplicate(); //copy because its a reference
713
714 int erase_index = -1;
715 for (int i = polygons.size() - 1; i >= 0; i--) {
716 Vector<int> points = polygons[i];
717 Vector<Vector2> polys;
718 polys.resize(points.size());
719 for (int j = 0; j < polys.size(); j++) {
720 int idx = points[j];
721 if (idx < 0 || idx >= points_prev.size()) {
722 continue;
723 }
724 polys.write[j] = mtx.xform(points_prev[idx]);
725 }
726
727 if (Geometry2D::is_point_in_polygon(mb->get_position(), polys)) {
728 erase_index = i;
729 break;
730 }
731 }
732
733 if (erase_index != -1) {
734 polygons.remove_at(erase_index);
735 undo_redo->create_action(TTR("Remove Custom Polygon"));
736 undo_redo->add_do_method(node, "set_polygons", polygons);
737 undo_redo->add_undo_method(node, "set_polygons", node->get_polygons());
738 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
739 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
740 undo_redo->commit_action();
741 }
742 }
743
744 if (uv_move_current == UV_MODE_PAINT_WEIGHT || uv_move_current == UV_MODE_CLEAR_WEIGHT) {
745 int bone_selected = -1;
746 for (int i = 0; i < bone_scroll_vb->get_child_count(); i++) {
747 CheckBox *c = Object::cast_to<CheckBox>(bone_scroll_vb->get_child(i));
748 if (c && c->is_pressed()) {
749 bone_selected = i;
750 break;
751 }
752 }
753
754 if (bone_selected != -1 && node->get_bone_weights(bone_selected).size() == points_prev.size()) {
755 prev_weights = node->get_bone_weights(bone_selected);
756 bone_painting = true;
757 bone_painting_bone = bone_selected;
758 }
759 }
760 } else {
761 if (uv_drag && !uv_create) {
762 if (uv_edit_mode[0]->is_pressed()) { // Edit UV.
763 undo_redo->create_action(TTR("Transform UV Map"));
764 undo_redo->add_do_method(node, "set_uv", node->get_uv());
765 undo_redo->add_undo_method(node, "set_uv", points_prev);
766 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
767 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
768 undo_redo->commit_action();
769 } else if (uv_edit_mode[1]->is_pressed() && uv_move_current == UV_MODE_EDIT_POINT) { // Edit polygon.
770 undo_redo->create_action(TTR("Transform Polygon"));
771 undo_redo->add_do_method(node, "set_polygon", node->get_polygon());
772 undo_redo->add_undo_method(node, "set_polygon", points_prev);
773 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
774 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
775 undo_redo->commit_action();
776 }
777
778 uv_drag = false;
779 }
780
781 if (bone_painting) {
782 undo_redo->create_action(TTR("Paint Bone Weights"));
783 undo_redo->add_do_method(node, "set_bone_weights", bone_painting_bone, node->get_bone_weights(bone_painting_bone));
784 undo_redo->add_undo_method(node, "set_bone_weights", bone_painting_bone, prev_weights);
785 undo_redo->add_do_method(uv_edit_draw, "queue_redraw");
786 undo_redo->add_undo_method(uv_edit_draw, "queue_redraw");
787 undo_redo->commit_action();
788 bone_painting = false;
789 }
790 }
791 } else if (mb->get_button_index() == MouseButton::RIGHT && mb->is_pressed()) {
792 _cancel_editing();
793
794 if (bone_painting) {
795 node->set_bone_weights(bone_painting_bone, prev_weights);
796 }
797
798 uv_edit_draw->queue_redraw();
799 }
800 }
801
802 Ref<InputEventMouseMotion> mm = p_input;
803
804 if (mm.is_valid()) {
805 if (uv_drag) {
806 Vector2 uv_drag_to = mm->get_position();
807 uv_drag_to = snap_point(uv_drag_to); // FIXME: Only works correctly with 'UV_MODE_EDIT_POINT', it's imprecise with the rest.
808 Vector2 drag = mtx.affine_inverse().xform(uv_drag_to) - mtx.affine_inverse().xform(uv_drag_from);
809
810 switch (uv_move_current) {
811 case UV_MODE_CREATE: {
812 if (uv_create) {
813 uv_create_to = mtx.affine_inverse().xform(snap_point(mm->get_position()));
814 }
815 } break;
816 case UV_MODE_EDIT_POINT: {
817 Vector<Vector2> uv_new = points_prev;
818 uv_new.set(point_drag_index, uv_new[point_drag_index] + drag);
819
820 if (uv_edit_mode[0]->is_pressed()) { //edit uv
821 node->set_uv(uv_new);
822 } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon
823 node->set_polygon(uv_new);
824 }
825 } break;
826 case UV_MODE_MOVE: {
827 Vector<Vector2> uv_new = points_prev;
828 for (int i = 0; i < uv_new.size(); i++) {
829 uv_new.set(i, uv_new[i] + drag);
830 }
831
832 if (uv_edit_mode[0]->is_pressed()) { //edit uv
833 node->set_uv(uv_new);
834 } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon
835 node->set_polygon(uv_new);
836 }
837 } break;
838 case UV_MODE_ROTATE: {
839 Vector2 center;
840 Vector<Vector2> uv_new = points_prev;
841
842 for (int i = 0; i < uv_new.size(); i++) {
843 center += points_prev[i];
844 }
845 center /= uv_new.size();
846
847 real_t angle = (uv_drag_from - mtx.xform(center)).normalized().angle_to((uv_drag_to - mtx.xform(center)).normalized());
848
849 for (int i = 0; i < uv_new.size(); i++) {
850 Vector2 rel = points_prev[i] - center;
851 rel = rel.rotated(angle);
852 uv_new.set(i, center + rel);
853 }
854
855 if (uv_edit_mode[0]->is_pressed()) { //edit uv
856 node->set_uv(uv_new);
857 } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon
858 node->set_polygon(uv_new);
859 }
860 } break;
861 case UV_MODE_SCALE: {
862 Vector2 center;
863 Vector<Vector2> uv_new = points_prev;
864
865 for (int i = 0; i < uv_new.size(); i++) {
866 center += points_prev[i];
867 }
868 center /= uv_new.size();
869
870 real_t from_dist = uv_drag_from.distance_to(mtx.xform(center));
871 real_t to_dist = uv_drag_to.distance_to(mtx.xform(center));
872 if (from_dist < 2) {
873 break;
874 }
875
876 real_t scale = to_dist / from_dist;
877
878 for (int i = 0; i < uv_new.size(); i++) {
879 Vector2 rel = points_prev[i] - center;
880 rel = rel * scale;
881 uv_new.set(i, center + rel);
882 }
883
884 if (uv_edit_mode[0]->is_pressed()) { //edit uv
885 node->set_uv(uv_new);
886 } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon
887 node->set_polygon(uv_new);
888 }
889 } break;
890 case UV_MODE_PAINT_WEIGHT:
891 case UV_MODE_CLEAR_WEIGHT: {
892 bone_paint_pos = mm->get_position();
893 } break;
894 default: {
895 }
896 }
897
898 if (bone_painting) {
899 Vector<float> painted_weights = node->get_bone_weights(bone_painting_bone);
900
901 {
902 int pc = painted_weights.size();
903 real_t amount = bone_paint_strength->get_value();
904 real_t radius = bone_paint_radius->get_value() * EDSCALE;
905
906 if (uv_mode == UV_MODE_CLEAR_WEIGHT) {
907 amount = -amount;
908 }
909
910 float *w = painted_weights.ptrw();
911 const float *r = prev_weights.ptr();
912 const Vector2 *rv = points_prev.ptr();
913
914 for (int i = 0; i < pc; i++) {
915 if (mtx.xform(rv[i]).distance_to(bone_paint_pos) < radius) {
916 w[i] = CLAMP(r[i] + amount, 0, 1);
917 }
918 }
919 }
920
921 node->set_bone_weights(bone_painting_bone, painted_weights);
922 }
923
924 uv_edit_draw->queue_redraw();
925 CanvasItemEditor::get_singleton()->update_viewport();
926 } else if (polygon_create.size()) {
927 uv_create_to = mtx.affine_inverse().xform(mm->get_position());
928 uv_edit_draw->queue_redraw();
929 } else if (uv_mode == UV_MODE_PAINT_WEIGHT || uv_mode == UV_MODE_CLEAR_WEIGHT) {
930 bone_paint_pos = mm->get_position();
931 uv_edit_draw->queue_redraw();
932 }
933 }
934
935 Ref<InputEventMagnifyGesture> magnify_gesture = p_input;
936 if (magnify_gesture.is_valid()) {
937 uv_zoom->set_value(uv_zoom->get_value() * magnify_gesture->get_factor());
938 }
939
940 Ref<InputEventPanGesture> pan_gesture = p_input;
941 if (pan_gesture.is_valid()) {
942 uv_hscroll->set_value(uv_hscroll->get_value() + uv_hscroll->get_page() * pan_gesture->get_delta().x / 8);
943 uv_vscroll->set_value(uv_vscroll->get_value() + uv_vscroll->get_page() * pan_gesture->get_delta().y / 8);
944 }
945}
946
947void Polygon2DEditor::_uv_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
948 uv_hscroll->set_value(uv_hscroll->get_value() - p_scroll_vec.x);
949 uv_vscroll->set_value(uv_vscroll->get_value() - p_scroll_vec.y);
950}
951
952void Polygon2DEditor::_uv_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
953 uv_zoom->set_value(uv_zoom->get_value() * p_zoom_factor);
954}
955
956void Polygon2DEditor::_uv_scroll_changed(real_t) {
957 if (updating_uv_scroll) {
958 return;
959 }
960
961 uv_draw_ofs.x = uv_hscroll->get_value();
962 uv_draw_ofs.y = uv_vscroll->get_value();
963 uv_draw_zoom = uv_zoom->get_value();
964 uv_edit_draw->queue_redraw();
965}
966
967void Polygon2DEditor::_uv_draw() {
968 if (!uv_edit->is_visible() || !_get_node()) {
969 return;
970 }
971
972 Ref<Texture2D> base_tex = node->get_texture();
973 if (base_tex.is_null()) {
974 return;
975 }
976
977 String warning;
978
979 Transform2D mtx;
980 mtx.columns[2] = -uv_draw_ofs;
981 mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom));
982
983 RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), mtx);
984 uv_edit_draw->draw_texture(base_tex, Point2());
985 RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), Transform2D());
986
987 if (snap_show_grid) {
988 Color grid_color = Color(1.0, 1.0, 1.0, 0.15);
989 Size2 s = uv_edit_draw->get_size();
990 int last_cell = 0;
991
992 if (snap_step.x != 0) {
993 for (int i = 0; i < s.width; i++) {
994 int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(i, 0)).x - snap_offset.x) / snap_step.x));
995 if (i == 0) {
996 last_cell = cell;
997 }
998 if (last_cell != cell) {
999 uv_edit_draw->draw_line(Point2(i, 0), Point2(i, s.height), grid_color, Math::round(EDSCALE));
1000 }
1001 last_cell = cell;
1002 }
1003 }
1004
1005 if (snap_step.y != 0) {
1006 for (int i = 0; i < s.height; i++) {
1007 int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(0, i)).y - snap_offset.y) / snap_step.y));
1008 if (i == 0) {
1009 last_cell = cell;
1010 }
1011 if (last_cell != cell) {
1012 uv_edit_draw->draw_line(Point2(0, i), Point2(s.width, i), grid_color, Math::round(EDSCALE));
1013 }
1014 last_cell = cell;
1015 }
1016 }
1017 }
1018
1019 Array polygons = node->get_polygons();
1020
1021 Vector<Vector2> uvs;
1022 if (uv_edit_mode[0]->is_pressed()) { //edit uv
1023 uvs = node->get_uv();
1024 } else { //edit polygon
1025 uvs = node->get_polygon();
1026 }
1027
1028 const float *weight_r = nullptr;
1029
1030 if (uv_edit_mode[3]->is_pressed()) {
1031 int bone_selected = -1;
1032 for (int i = 0; i < bone_scroll_vb->get_child_count(); i++) {
1033 CheckBox *c = Object::cast_to<CheckBox>(bone_scroll_vb->get_child(i));
1034 if (c && c->is_pressed()) {
1035 bone_selected = i;
1036 break;
1037 }
1038 }
1039
1040 if (bone_selected != -1 && node->get_bone_weights(bone_selected).size() == uvs.size()) {
1041 weight_r = node->get_bone_weights(bone_selected).ptr();
1042 }
1043 }
1044
1045 // All UV points are sharp, so use the sharp handle icon
1046 Ref<Texture2D> handle = get_editor_theme_icon(SNAME("EditorPathSharpHandle"));
1047
1048 Color poly_line_color = Color(0.9, 0.5, 0.5);
1049 if (polygons.size() || polygon_create.size()) {
1050 poly_line_color.a *= 0.25;
1051 }
1052 Color polygon_line_color = Color(0.5, 0.5, 0.9);
1053 Vector<Color> polygon_fill_color;
1054 {
1055 Color pf = polygon_line_color;
1056 pf.a *= 0.5;
1057 polygon_fill_color.push_back(pf);
1058 }
1059 Color prev_color = Color(0.5, 0.5, 0.5);
1060 Rect2 rect;
1061
1062 int uv_draw_max = uvs.size();
1063
1064 uv_draw_max -= node->get_internal_vertex_count();
1065 if (uv_draw_max < 0) {
1066 uv_draw_max = 0;
1067 }
1068
1069 for (int i = 0; i < uvs.size(); i++) {
1070 int next = uv_draw_max > 0 ? (i + 1) % uv_draw_max : 0;
1071
1072 if (i < uv_draw_max && uv_drag && uv_move_current == UV_MODE_EDIT_POINT && EDITOR_GET("editors/polygon_editor/show_previous_outline")) {
1073 uv_edit_draw->draw_line(mtx.xform(points_prev[i]), mtx.xform(points_prev[next]), prev_color, Math::round(EDSCALE));
1074 }
1075
1076 Vector2 next_point = uvs[next];
1077 if (uv_create && i == uvs.size() - 1) {
1078 next_point = uv_create_to;
1079 }
1080 if (i < uv_draw_max) { // If using or creating polygons, do not show outline (will show polygons instead).
1081 uv_edit_draw->draw_line(mtx.xform(uvs[i]), mtx.xform(next_point), poly_line_color, Math::round(EDSCALE));
1082 }
1083 }
1084
1085 for (int i = 0; i < polygons.size(); i++) {
1086 Vector<int> points = polygons[i];
1087 Vector<Vector2> polypoints;
1088 for (int j = 0; j < points.size(); j++) {
1089 int next = (j + 1) % points.size();
1090
1091 int idx = points[j];
1092 int idx_next = points[next];
1093 if (idx < 0 || idx >= uvs.size()) {
1094 continue;
1095 }
1096 polypoints.push_back(mtx.xform(uvs[idx]));
1097
1098 if (idx_next < 0 || idx_next >= uvs.size()) {
1099 continue;
1100 }
1101 uv_edit_draw->draw_line(mtx.xform(uvs[idx]), mtx.xform(uvs[idx_next]), polygon_line_color, Math::round(EDSCALE));
1102 }
1103 if (points.size() >= 3) {
1104 uv_edit_draw->draw_polygon(polypoints, polygon_fill_color);
1105 }
1106 }
1107
1108 for (int i = 0; i < uvs.size(); i++) {
1109 if (weight_r) {
1110 Vector2 draw_pos = mtx.xform(uvs[i]);
1111 float weight = weight_r[i];
1112 uv_edit_draw->draw_rect(Rect2(draw_pos - Vector2(2, 2) * EDSCALE, Vector2(5, 5) * EDSCALE), Color(weight, weight, weight, 1.0), Math::round(EDSCALE));
1113 } else {
1114 if (i < uv_draw_max) {
1115 uv_edit_draw->draw_texture(handle, mtx.xform(uvs[i]) - handle->get_size() * 0.5);
1116 } else {
1117 // Internal vertex
1118 uv_edit_draw->draw_texture(handle, mtx.xform(uvs[i]) - handle->get_size() * 0.5, Color(0.6, 0.8, 1));
1119 }
1120 }
1121 }
1122
1123 if (polygon_create.size()) {
1124 for (int i = 0; i < polygon_create.size(); i++) {
1125 Vector2 from = uvs[polygon_create[i]];
1126 Vector2 to = (i + 1) < polygon_create.size() ? uvs[polygon_create[i + 1]] : uv_create_to;
1127 uv_edit_draw->draw_line(mtx.xform(from), mtx.xform(to), polygon_line_color, Math::round(EDSCALE));
1128 }
1129 }
1130
1131 if (uv_mode == UV_MODE_PAINT_WEIGHT || uv_mode == UV_MODE_CLEAR_WEIGHT) {
1132 NodePath bone_path;
1133 for (int i = 0; i < bone_scroll_vb->get_child_count(); i++) {
1134 CheckBox *c = Object::cast_to<CheckBox>(bone_scroll_vb->get_child(i));
1135 if (c && c->is_pressed()) {
1136 bone_path = node->get_bone_path(i);
1137 break;
1138 }
1139 }
1140
1141 //draw skeleton
1142 NodePath skeleton_path = node->get_skeleton();
1143 if (node->has_node(skeleton_path)) {
1144 Skeleton2D *skeleton = Object::cast_to<Skeleton2D>(node->get_node(skeleton_path));
1145 if (skeleton) {
1146 for (int i = 0; i < skeleton->get_bone_count(); i++) {
1147 Bone2D *bone = skeleton->get_bone(i);
1148 if (bone->get_rest() == Transform2D(0, 0, 0, 0, 0, 0)) {
1149 continue; //not set
1150 }
1151
1152 bool current = bone_path == skeleton->get_path_to(bone);
1153
1154 bool found_child = false;
1155
1156 for (int j = 0; j < bone->get_child_count(); j++) {
1157 Bone2D *n = Object::cast_to<Bone2D>(bone->get_child(j));
1158 if (!n) {
1159 continue;
1160 }
1161
1162 found_child = true;
1163
1164 Transform2D bone_xform = node->get_global_transform().affine_inverse() * (skeleton->get_global_transform() * bone->get_skeleton_rest());
1165 Transform2D endpoint_xform = bone_xform * n->get_transform();
1166
1167 Color color = current ? Color(1, 1, 1) : Color(0.5, 0.5, 0.5);
1168 uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), Color(0, 0, 0), Math::round((current ? 5 : 4) * EDSCALE));
1169 uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, Math::round((current ? 3 : 2) * EDSCALE));
1170 }
1171
1172 if (!found_child) {
1173 //draw normally
1174 Transform2D bone_xform = node->get_global_transform().affine_inverse() * (skeleton->get_global_transform() * bone->get_skeleton_rest());
1175 Transform2D endpoint_xform = bone_xform * Transform2D(0, Vector2(bone->get_length(), 0));
1176
1177 Color color = current ? Color(1, 1, 1) : Color(0.5, 0.5, 0.5);
1178 uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), Color(0, 0, 0), Math::round((current ? 5 : 4) * EDSCALE));
1179 uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, Math::round((current ? 3 : 2) * EDSCALE));
1180 }
1181 }
1182 }
1183 }
1184
1185 //draw paint circle
1186 uv_edit_draw->draw_circle(bone_paint_pos, bone_paint_radius->get_value() * EDSCALE, Color(1, 1, 1, 0.1));
1187 }
1188
1189 rect.position = -uv_edit_draw->get_size();
1190 rect.size = uv_edit_draw->get_size() * 2.0 + base_tex->get_size() * uv_draw_zoom;
1191
1192 updating_uv_scroll = true;
1193
1194 uv_hscroll->set_min(rect.position.x);
1195 uv_hscroll->set_max(rect.position.x + rect.size.x);
1196 if (ABS(rect.position.x - (rect.position.x + rect.size.x)) <= uv_edit_draw->get_size().x) {
1197 uv_hscroll->hide();
1198 } else {
1199 uv_hscroll->show();
1200 uv_hscroll->set_page(uv_edit_draw->get_size().x);
1201 uv_hscroll->set_value(uv_draw_ofs.x);
1202 }
1203
1204 uv_vscroll->set_min(rect.position.y);
1205 uv_vscroll->set_max(rect.position.y + rect.size.y);
1206 if (ABS(rect.position.y - (rect.position.y + rect.size.y)) <= uv_edit_draw->get_size().y) {
1207 uv_vscroll->hide();
1208 } else {
1209 uv_vscroll->show();
1210 uv_vscroll->set_page(uv_edit_draw->get_size().y);
1211 uv_vscroll->set_value(uv_draw_ofs.y);
1212 }
1213
1214 Size2 hmin = uv_hscroll->get_combined_minimum_size();
1215 Size2 vmin = uv_vscroll->get_combined_minimum_size();
1216
1217 // Avoid scrollbar overlapping.
1218 uv_hscroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, uv_vscroll->is_visible() ? -vmin.width : 0);
1219 uv_vscroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, uv_hscroll->is_visible() ? -hmin.height : 0);
1220
1221 updating_uv_scroll = false;
1222}
1223
1224void Polygon2DEditor::_bind_methods() {
1225 ClassDB::bind_method(D_METHOD("_update_bone_list"), &Polygon2DEditor::_update_bone_list);
1226 ClassDB::bind_method(D_METHOD("_update_polygon_editing_state"), &Polygon2DEditor::_update_polygon_editing_state);
1227}
1228
1229Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const {
1230 if (use_snap) {
1231 p_target.x = Math::snap_scalar(snap_offset.x * uv_draw_zoom - uv_draw_ofs.x, snap_step.x * uv_draw_zoom, p_target.x);
1232 p_target.y = Math::snap_scalar(snap_offset.y * uv_draw_zoom - uv_draw_ofs.y, snap_step.y * uv_draw_zoom, p_target.y);
1233 }
1234
1235 return p_target;
1236}
1237
1238Polygon2DEditor::Polygon2DEditor() {
1239 snap_offset = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "snap_offset", Vector2());
1240 // A power-of-two value works better as a default grid size.
1241 snap_step = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "snap_step", Vector2(8, 8));
1242 use_snap = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "snap_enabled", false);
1243 snap_show_grid = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "show_grid", false);
1244
1245 button_uv = memnew(Button);
1246 button_uv->set_flat(true);
1247 add_child(button_uv);
1248 button_uv->set_tooltip_text(TTR("Open Polygon 2D UV editor."));
1249 button_uv->connect("pressed", callable_mp(this, &Polygon2DEditor::_menu_option).bind(MODE_EDIT_UV));
1250
1251 uv_mode = UV_MODE_EDIT_POINT;
1252 uv_edit = memnew(AcceptDialog);
1253 add_child(uv_edit);
1254 uv_edit->set_title(TTR("Polygon 2D UV Editor"));
1255 uv_edit->connect("canceled", callable_mp(this, &Polygon2DEditor::_uv_edit_popup_hide));
1256
1257 VBoxContainer *uv_main_vb = memnew(VBoxContainer);
1258 uv_edit->add_child(uv_main_vb);
1259 HBoxContainer *uv_mode_hb = memnew(HBoxContainer);
1260
1261 uv_edit_group.instantiate();
1262
1263 uv_edit_mode[0] = memnew(Button);
1264 uv_mode_hb->add_child(uv_edit_mode[0]);
1265 uv_edit_mode[0]->set_toggle_mode(true);
1266 uv_edit_mode[1] = memnew(Button);
1267 uv_mode_hb->add_child(uv_edit_mode[1]);
1268 uv_edit_mode[1]->set_toggle_mode(true);
1269 uv_edit_mode[2] = memnew(Button);
1270 uv_mode_hb->add_child(uv_edit_mode[2]);
1271 uv_edit_mode[2]->set_toggle_mode(true);
1272 uv_edit_mode[3] = memnew(Button);
1273 uv_mode_hb->add_child(uv_edit_mode[3]);
1274 uv_edit_mode[3]->set_toggle_mode(true);
1275
1276 uv_edit_mode[0]->set_text(TTR("UV"));
1277 uv_edit_mode[0]->set_pressed(true);
1278 uv_edit_mode[1]->set_text(TTR("Points"));
1279 uv_edit_mode[2]->set_text(TTR("Polygons"));
1280 uv_edit_mode[3]->set_text(TTR("Bones"));
1281
1282 uv_edit_mode[0]->set_button_group(uv_edit_group);
1283 uv_edit_mode[1]->set_button_group(uv_edit_group);
1284 uv_edit_mode[2]->set_button_group(uv_edit_group);
1285 uv_edit_mode[3]->set_button_group(uv_edit_group);
1286
1287 uv_edit_mode[0]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(0));
1288 uv_edit_mode[1]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(1));
1289 uv_edit_mode[2]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(2));
1290 uv_edit_mode[3]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(3));
1291
1292 uv_mode_hb->add_child(memnew(VSeparator));
1293
1294 uv_main_vb->add_child(uv_mode_hb);
1295 for (int i = 0; i < UV_MODE_MAX; i++) {
1296 uv_button[i] = memnew(Button);
1297 uv_button[i]->set_flat(true);
1298 uv_button[i]->set_toggle_mode(true);
1299 uv_mode_hb->add_child(uv_button[i]);
1300 uv_button[i]->connect("pressed", callable_mp(this, &Polygon2DEditor::_uv_mode).bind(i));
1301 uv_button[i]->set_focus_mode(FOCUS_NONE);
1302 }
1303
1304 uv_button[UV_MODE_CREATE]->set_tooltip_text(TTR("Create Polygon"));
1305 uv_button[UV_MODE_CREATE_INTERNAL]->set_tooltip_text(TTR("Create Internal Vertex"));
1306 uv_button[UV_MODE_REMOVE_INTERNAL]->set_tooltip_text(TTR("Remove Internal Vertex"));
1307 uv_button[UV_MODE_EDIT_POINT]->set_tooltip_text(TTR("Move Points") + "\n" + TTR("Ctrl: Rotate") + "\n" + TTR("Shift: Move All") + "\n" + TTR("Shift+Ctrl: Scale"));
1308 uv_button[UV_MODE_MOVE]->set_tooltip_text(TTR("Move Polygon"));
1309 uv_button[UV_MODE_ROTATE]->set_tooltip_text(TTR("Rotate Polygon"));
1310 uv_button[UV_MODE_SCALE]->set_tooltip_text(TTR("Scale Polygon"));
1311 uv_button[UV_MODE_ADD_POLYGON]->set_tooltip_text(TTR("Create a custom polygon. Enables custom polygon rendering."));
1312 uv_button[UV_MODE_REMOVE_POLYGON]->set_tooltip_text(TTR("Remove a custom polygon. If none remain, custom polygon rendering is disabled."));
1313 uv_button[UV_MODE_PAINT_WEIGHT]->set_tooltip_text(TTR("Paint weights with specified intensity."));
1314 uv_button[UV_MODE_CLEAR_WEIGHT]->set_tooltip_text(TTR("Unpaint weights with specified intensity."));
1315
1316 uv_button[UV_MODE_CREATE]->hide();
1317 uv_button[UV_MODE_CREATE_INTERNAL]->hide();
1318 uv_button[UV_MODE_REMOVE_INTERNAL]->hide();
1319 uv_button[UV_MODE_ADD_POLYGON]->hide();
1320 uv_button[UV_MODE_REMOVE_POLYGON]->hide();
1321 uv_button[UV_MODE_PAINT_WEIGHT]->hide();
1322 uv_button[UV_MODE_CLEAR_WEIGHT]->hide();
1323 uv_button[UV_MODE_EDIT_POINT]->set_pressed(true);
1324
1325 bone_paint_strength = memnew(HSlider);
1326 uv_mode_hb->add_child(bone_paint_strength);
1327 bone_paint_strength->set_custom_minimum_size(Size2(75 * EDSCALE, 0));
1328 bone_paint_strength->set_v_size_flags(SIZE_SHRINK_CENTER);
1329 bone_paint_strength->set_min(0);
1330 bone_paint_strength->set_max(1);
1331 bone_paint_strength->set_step(0.01);
1332 bone_paint_strength->set_value(0.5);
1333
1334 bone_paint_radius_label = memnew(Label(TTR("Radius:")));
1335 uv_mode_hb->add_child(bone_paint_radius_label);
1336 bone_paint_radius = memnew(SpinBox);
1337 uv_mode_hb->add_child(bone_paint_radius);
1338
1339 bone_paint_strength->hide();
1340 bone_paint_radius->hide();
1341 bone_paint_radius_label->hide();
1342 bone_paint_radius->set_min(1);
1343 bone_paint_radius->set_max(100);
1344 bone_paint_radius->set_step(1);
1345 bone_paint_radius->set_value(32);
1346
1347 HSplitContainer *uv_main_hsc = memnew(HSplitContainer);
1348 uv_main_vb->add_child(uv_main_hsc);
1349 uv_main_hsc->set_v_size_flags(SIZE_EXPAND_FILL);
1350 uv_edit_draw = memnew(Panel);
1351 uv_main_hsc->add_child(uv_edit_draw);
1352 uv_edit_draw->set_h_size_flags(SIZE_EXPAND_FILL);
1353 uv_edit_draw->set_custom_minimum_size(Size2(200, 200) * EDSCALE);
1354
1355 Control *space = memnew(Control);
1356 uv_mode_hb->add_child(space);
1357 space->set_h_size_flags(SIZE_EXPAND_FILL);
1358
1359 uv_menu = memnew(MenuButton);
1360 uv_mode_hb->add_child(uv_menu);
1361 uv_menu->set_text(TTR("Edit"));
1362 uv_menu->get_popup()->add_item(TTR("Copy Polygon to UV"), UVEDIT_POLYGON_TO_UV);
1363 uv_menu->get_popup()->add_item(TTR("Copy UV to Polygon"), UVEDIT_UV_TO_POLYGON);
1364 uv_menu->get_popup()->add_separator();
1365 uv_menu->get_popup()->add_item(TTR("Clear UV"), UVEDIT_UV_CLEAR);
1366 uv_menu->get_popup()->add_separator();
1367 uv_menu->get_popup()->add_item(TTR("Grid Settings"), UVEDIT_GRID_SETTINGS);
1368 uv_menu->get_popup()->connect("id_pressed", callable_mp(this, &Polygon2DEditor::_menu_option));
1369
1370 uv_mode_hb->add_child(memnew(VSeparator));
1371
1372 b_snap_enable = memnew(Button);
1373 b_snap_enable->set_flat(true);
1374 uv_mode_hb->add_child(b_snap_enable);
1375 b_snap_enable->set_text(TTR("Snap"));
1376 b_snap_enable->set_focus_mode(FOCUS_NONE);
1377 b_snap_enable->set_toggle_mode(true);
1378 b_snap_enable->set_pressed(use_snap);
1379 b_snap_enable->set_tooltip_text(TTR("Enable Snap"));
1380 b_snap_enable->connect("toggled", callable_mp(this, &Polygon2DEditor::_set_use_snap));
1381
1382 b_snap_grid = memnew(Button);
1383 b_snap_grid->set_flat(true);
1384 uv_mode_hb->add_child(b_snap_grid);
1385 b_snap_grid->set_text(TTR("Grid"));
1386 b_snap_grid->set_focus_mode(FOCUS_NONE);
1387 b_snap_grid->set_toggle_mode(true);
1388 b_snap_grid->set_pressed(snap_show_grid);
1389 b_snap_grid->set_tooltip_text(TTR("Show Grid"));
1390 b_snap_grid->connect("toggled", callable_mp(this, &Polygon2DEditor::_set_show_grid));
1391
1392 grid_settings = memnew(AcceptDialog);
1393 grid_settings->set_title(TTR("Configure Grid:"));
1394 add_child(grid_settings);
1395 VBoxContainer *grid_settings_vb = memnew(VBoxContainer);
1396 grid_settings->add_child(grid_settings_vb);
1397
1398 SpinBox *sb_off_x = memnew(SpinBox);
1399 sb_off_x->set_min(-256);
1400 sb_off_x->set_max(256);
1401 sb_off_x->set_step(1);
1402 sb_off_x->set_value(snap_offset.x);
1403 sb_off_x->set_suffix("px");
1404 sb_off_x->connect("value_changed", callable_mp(this, &Polygon2DEditor::_set_snap_off_x));
1405 grid_settings_vb->add_margin_child(TTR("Grid Offset X:"), sb_off_x);
1406
1407 SpinBox *sb_off_y = memnew(SpinBox);
1408 sb_off_y->set_min(-256);
1409 sb_off_y->set_max(256);
1410 sb_off_y->set_step(1);
1411 sb_off_y->set_value(snap_offset.y);
1412 sb_off_y->set_suffix("px");
1413 sb_off_y->connect("value_changed", callable_mp(this, &Polygon2DEditor::_set_snap_off_y));
1414 grid_settings_vb->add_margin_child(TTR("Grid Offset Y:"), sb_off_y);
1415
1416 SpinBox *sb_step_x = memnew(SpinBox);
1417 sb_step_x->set_min(-256);
1418 sb_step_x->set_max(256);
1419 sb_step_x->set_step(1);
1420 sb_step_x->set_value(snap_step.x);
1421 sb_step_x->set_suffix("px");
1422 sb_step_x->connect("value_changed", callable_mp(this, &Polygon2DEditor::_set_snap_step_x));
1423 grid_settings_vb->add_margin_child(TTR("Grid Step X:"), sb_step_x);
1424
1425 SpinBox *sb_step_y = memnew(SpinBox);
1426 sb_step_y->set_min(-256);
1427 sb_step_y->set_max(256);
1428 sb_step_y->set_step(1);
1429 sb_step_y->set_value(snap_step.y);
1430 sb_step_y->set_suffix("px");
1431 sb_step_y->connect("value_changed", callable_mp(this, &Polygon2DEditor::_set_snap_step_y));
1432 grid_settings_vb->add_margin_child(TTR("Grid Step Y:"), sb_step_y);
1433
1434 uv_mode_hb->add_child(memnew(VSeparator));
1435 uv_icon_zoom = memnew(TextureRect);
1436 uv_icon_zoom->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
1437 uv_mode_hb->add_child(uv_icon_zoom);
1438 uv_zoom = memnew(HSlider);
1439 uv_zoom->set_min(0.01);
1440 uv_zoom->set_max(16);
1441 uv_zoom->set_value(1);
1442 uv_zoom->set_step(0.01);
1443 uv_zoom->set_v_size_flags(SIZE_SHRINK_CENTER);
1444
1445 uv_mode_hb->add_child(uv_zoom);
1446 uv_zoom->set_custom_minimum_size(Size2(80 * EDSCALE, 0));
1447 uv_zoom_value = memnew(SpinBox);
1448 uv_zoom->share(uv_zoom_value);
1449 uv_zoom_value->set_custom_minimum_size(Size2(50, 0));
1450 uv_mode_hb->add_child(uv_zoom_value);
1451 uv_zoom->connect("value_changed", callable_mp(this, &Polygon2DEditor::_uv_scroll_changed));
1452
1453 uv_vscroll = memnew(VScrollBar);
1454 uv_vscroll->set_step(0.001);
1455 uv_edit_draw->add_child(uv_vscroll);
1456 uv_vscroll->connect("value_changed", callable_mp(this, &Polygon2DEditor::_uv_scroll_changed));
1457 uv_hscroll = memnew(HScrollBar);
1458 uv_hscroll->set_step(0.001);
1459 uv_edit_draw->add_child(uv_hscroll);
1460 uv_hscroll->connect("value_changed", callable_mp(this, &Polygon2DEditor::_uv_scroll_changed));
1461
1462 bone_scroll_main_vb = memnew(VBoxContainer);
1463 bone_scroll_main_vb->hide();
1464 bone_scroll_main_vb->set_custom_minimum_size(Size2(150 * EDSCALE, 0));
1465 sync_bones = memnew(Button(TTR("Sync Bones to Polygon")));
1466 bone_scroll_main_vb->add_child(sync_bones);
1467 sync_bones->set_h_size_flags(0);
1468 sync_bones->connect("pressed", callable_mp(this, &Polygon2DEditor::_sync_bones));
1469 uv_main_hsc->add_child(bone_scroll_main_vb);
1470 bone_scroll = memnew(ScrollContainer);
1471 bone_scroll->set_v_scroll(true);
1472 bone_scroll->set_h_scroll(false);
1473 bone_scroll_main_vb->add_child(bone_scroll);
1474 bone_scroll->set_v_size_flags(SIZE_EXPAND_FILL);
1475 bone_scroll_vb = memnew(VBoxContainer);
1476 bone_scroll->add_child(bone_scroll_vb);
1477
1478 uv_panner.instantiate();
1479 uv_panner->set_callbacks(callable_mp(this, &Polygon2DEditor::_uv_pan_callback), callable_mp(this, &Polygon2DEditor::_uv_zoom_callback));
1480
1481 uv_edit_draw->connect("draw", callable_mp(this, &Polygon2DEditor::_uv_draw));
1482 uv_edit_draw->connect("gui_input", callable_mp(this, &Polygon2DEditor::_uv_input));
1483 uv_edit_draw->connect("focus_exited", callable_mp(uv_panner.ptr(), &ViewPanner::release_pan_key));
1484 uv_edit_draw->set_focus_mode(FOCUS_CLICK);
1485 uv_draw_zoom = 1.0;
1486 point_drag_index = -1;
1487 uv_drag = false;
1488 uv_create = false;
1489 updating_uv_scroll = false;
1490 bone_painting = false;
1491
1492 error = memnew(AcceptDialog);
1493 add_child(error);
1494
1495 uv_edit_draw->set_clip_contents(true);
1496}
1497
1498Polygon2DEditorPlugin::Polygon2DEditorPlugin() :
1499 AbstractPolygon2DEditorPlugin(memnew(Polygon2DEditor), "Polygon2D") {
1500}
1501