From 8318eda899ea42985b23aa112b13b9648de77d68 Mon Sep 17 00:00:00 2001 From: aXu-AP <1621768+aXu-AP@users.noreply.github.com> Date: Wed, 18 Oct 2023 01:28:04 +0300 Subject: [PATCH] Move Polygon2D editor to bottom panel Move UV editor to bottom panel to allow realtime preview of results. Rename the editor to Polygon editor. Refactor enums and rename polygon editor members. Remove "uv" prefixes and clarify some names. Reorder/regroup some members in header file. --- editor/plugins/polygon_2d_editor_plugin.cpp | 1012 ++++++++----------- editor/plugins/polygon_2d_editor_plugin.h | 129 +-- 2 files changed, 517 insertions(+), 624 deletions(-) diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 78f347dd4b1..4ecbab1549d 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -32,9 +32,11 @@ #include "core/input/input_event.h" #include "core/math/geometry_2d.h" +#include "editor/editor_command_palette.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/editor_undo_redo_manager.h" +#include "editor/gui/editor_bottom_panel.h" #include "editor/gui/editor_zoom_widget.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "editor/themes/editor_scale.h" @@ -51,38 +53,35 @@ #include "scene/gui/split_container.h" #include "scene/gui/view_panner.h" -class UVEditDialog : public AcceptDialog { - GDCLASS(UVEditDialog, AcceptDialog); - - void shortcut_input(const Ref &p_event) override { - const Ref k = p_event; - if (k.is_valid() && k->is_pressed()) { - bool handled = false; - - if (ED_IS_SHORTCUT("ui_undo", p_event)) { - EditorNode::get_singleton()->undo(); - handled = true; - } - - if (ED_IS_SHORTCUT("ui_redo", p_event)) { - EditorNode::get_singleton()->redo(); - handled = true; - } - - if (handled) { - set_input_as_handled(); - } - } - } -}; - Node2D *Polygon2DEditor::_get_node() const { return node; } void Polygon2DEditor::_set_node(Node *p_polygon) { + CanvasItem *draw = Object::cast_to(canvas); + if (node) { + node->disconnect(SceneStringName(draw), callable_mp(draw, &CanvasItem::queue_redraw)); + node->disconnect(SceneStringName(draw), callable_mp(this, &Polygon2DEditor::_update_available_modes)); + } node = Object::cast_to(p_polygon); _update_polygon_editing_state(); + canvas->queue_redraw(); + if (node) { + canvas->set_texture_filter(node->get_texture_filter_in_tree()); + + _update_bone_list(); + _update_available_modes(); + if (current_mode == MODE_MAX) { + _select_mode(MODE_POINTS); // Initialize when opening the first time. + } + if (previous_node != node) { + _center_view_on_draw(); + } + previous_node = node; + // Whenever polygon gets redrawn, there's possible changes for the editor as well. + node->connect(SceneStringName(draw), callable_mp(draw, &CanvasItem::queue_redraw)); + node->connect(SceneStringName(draw), callable_mp(this, &Polygon2DEditor::_update_available_modes)); + } } Vector2 Polygon2DEditor::_get_offset(int p_idx) const { @@ -106,45 +105,48 @@ void Polygon2DEditor::_notification(int p_what) { [[fallthrough]]; } case NOTIFICATION_ENTER_TREE: { - 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"))); - uv_panner->setup_warped_panning(get_viewport(), EDITOR_GET("editors/panning/warped_mouse_panning")); + 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"))); + panner->setup_warped_panning(get_viewport(), EDITOR_GET("editors/panning/warped_mouse_panning")); } break; case NOTIFICATION_READY: { - button_uv->set_button_icon(get_editor_theme_icon(SNAME("Uv"))); - - uv_button[UV_MODE_CREATE]->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); - uv_button[UV_MODE_CREATE_INTERNAL]->set_button_icon(get_editor_theme_icon(SNAME("EditInternal"))); - uv_button[UV_MODE_REMOVE_INTERNAL]->set_button_icon(get_editor_theme_icon(SNAME("RemoveInternal"))); - uv_button[UV_MODE_EDIT_POINT]->set_button_icon(get_editor_theme_icon(SNAME("ToolSelect"))); - uv_button[UV_MODE_MOVE]->set_button_icon(get_editor_theme_icon(SNAME("ToolMove"))); - uv_button[UV_MODE_ROTATE]->set_button_icon(get_editor_theme_icon(SNAME("ToolRotate"))); - uv_button[UV_MODE_SCALE]->set_button_icon(get_editor_theme_icon(SNAME("ToolScale"))); - uv_button[UV_MODE_ADD_POLYGON]->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); - uv_button[UV_MODE_REMOVE_POLYGON]->set_button_icon(get_editor_theme_icon(SNAME("Close"))); - uv_button[UV_MODE_PAINT_WEIGHT]->set_button_icon(get_editor_theme_icon(SNAME("Bucket"))); - uv_button[UV_MODE_CLEAR_WEIGHT]->set_button_icon(get_editor_theme_icon(SNAME("Clear"))); + action_buttons[ACTION_CREATE]->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); + action_buttons[ACTION_CREATE_INTERNAL]->set_button_icon(get_editor_theme_icon(SNAME("EditInternal"))); + action_buttons[ACTION_REMOVE_INTERNAL]->set_button_icon(get_editor_theme_icon(SNAME("RemoveInternal"))); + action_buttons[ACTION_EDIT_POINT]->set_button_icon(get_editor_theme_icon(SNAME("ToolSelect"))); + action_buttons[ACTION_MOVE]->set_button_icon(get_editor_theme_icon(SNAME("ToolMove"))); + action_buttons[ACTION_ROTATE]->set_button_icon(get_editor_theme_icon(SNAME("ToolRotate"))); + action_buttons[ACTION_SCALE]->set_button_icon(get_editor_theme_icon(SNAME("ToolScale"))); + action_buttons[ACTION_ADD_POLYGON]->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); + action_buttons[ACTION_REMOVE_POLYGON]->set_button_icon(get_editor_theme_icon(SNAME("Close"))); + action_buttons[ACTION_PAINT_WEIGHT]->set_button_icon(get_editor_theme_icon(SNAME("Bucket"))); + action_buttons[ACTION_CLEAR_WEIGHT]->set_button_icon(get_editor_theme_icon(SNAME("Clear"))); b_snap_grid->set_button_icon(get_editor_theme_icon(SNAME("Grid"))); b_snap_enable->set_button_icon(get_editor_theme_icon(SNAME("SnapGrid"))); - uv_vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE); - uv_hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE); + vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE); + hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE); // Avoid scrollbar overlapping. - Size2 hmin = uv_hscroll->get_combined_minimum_size(); - Size2 vmin = uv_vscroll->get_combined_minimum_size(); - uv_hscroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, -vmin.width); - uv_vscroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -hmin.height); + Size2 hmin = hscroll->get_combined_minimum_size(); + Size2 vmin = vscroll->get_combined_minimum_size(); + hscroll->set_anchor_and_offset(SIDE_RIGHT, ANCHOR_END, -vmin.width); + vscroll->set_anchor_and_offset(SIDE_BOTTOM, ANCHOR_END, -hmin.height); [[fallthrough]]; } case NOTIFICATION_THEME_CHANGED: { - uv_edit_draw->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); + canvas->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); bone_scroll->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree"))); } break; - case NOTIFICATION_VISIBILITY_CHANGED: { - if (!is_visible()) { - uv_edit->hide(); + if (is_visible()) { + dock_button->show(); + EditorNode::get_bottom_panel()->make_item_visible(polygon_edit); + } else { + dock_button->hide(); + if (polygon_edit->is_visible_in_tree()) { + EditorNode::get_bottom_panel()->hide_bottom_panel(); + } } } break; } @@ -200,8 +202,6 @@ void Polygon2DEditor::_sync_bones() { undo_redo->add_undo_method(node, "_set_bones", prev_bones); undo_redo->add_do_method(this, "_update_bone_list"); undo_redo->add_undo_method(this, "_update_bone_list"); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); undo_redo->commit_action(); } @@ -240,127 +240,76 @@ void Polygon2DEditor::_update_bone_list() { cb->connect(SceneStringName(pressed), callable_mp(this, &Polygon2DEditor::_bone_paint_selected).bind(i)); } - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); } void Polygon2DEditor::_bone_paint_selected(int p_index) { - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); } -void Polygon2DEditor::_uv_edit_mode_select(int p_mode) { - if (p_mode == 0) { //uv - - uv_button[UV_MODE_CREATE]->hide(); - uv_button[UV_MODE_CREATE_INTERNAL]->hide(); - uv_button[UV_MODE_REMOVE_INTERNAL]->hide(); - for (int i = UV_MODE_EDIT_POINT; i <= UV_MODE_SCALE; i++) { - uv_button[i]->show(); - } - uv_button[UV_MODE_ADD_POLYGON]->hide(); - uv_button[UV_MODE_REMOVE_POLYGON]->hide(); - uv_button[UV_MODE_PAINT_WEIGHT]->hide(); - uv_button[UV_MODE_CLEAR_WEIGHT]->hide(); - _uv_mode(UV_MODE_EDIT_POINT); - - bone_scroll_main_vb->hide(); - bone_paint_strength->hide(); - bone_paint_radius->hide(); - bone_paint_radius_label->hide(); - } else if (p_mode == 1) { //poly - - for (int i = 0; i <= UV_MODE_SCALE; i++) { - uv_button[i]->show(); - } - uv_button[UV_MODE_ADD_POLYGON]->hide(); - uv_button[UV_MODE_REMOVE_POLYGON]->hide(); - uv_button[UV_MODE_PAINT_WEIGHT]->hide(); - uv_button[UV_MODE_CLEAR_WEIGHT]->hide(); - if (node->get_polygon().is_empty()) { - _uv_mode(UV_MODE_CREATE); - } else { - _uv_mode(UV_MODE_EDIT_POINT); - } - - bone_scroll_main_vb->hide(); - bone_paint_strength->hide(); - bone_paint_radius->hide(); - bone_paint_radius_label->hide(); - } else if (p_mode == 2) { //splits - - for (int i = 0; i <= UV_MODE_SCALE; i++) { - uv_button[i]->hide(); - } - uv_button[UV_MODE_ADD_POLYGON]->show(); - uv_button[UV_MODE_REMOVE_POLYGON]->show(); - uv_button[UV_MODE_PAINT_WEIGHT]->hide(); - uv_button[UV_MODE_CLEAR_WEIGHT]->hide(); - _uv_mode(UV_MODE_ADD_POLYGON); - - bone_scroll_main_vb->hide(); - bone_paint_strength->hide(); - bone_paint_radius->hide(); - bone_paint_radius_label->hide(); - } else if (p_mode == 3) { //bones“ - - for (int i = 0; i <= UV_MODE_REMOVE_POLYGON; i++) { - uv_button[i]->hide(); - } - uv_button[UV_MODE_PAINT_WEIGHT]->show(); - uv_button[UV_MODE_CLEAR_WEIGHT]->show(); - _uv_mode(UV_MODE_PAINT_WEIGHT); - - bone_scroll_main_vb->show(); - bone_paint_strength->show(); - bone_paint_radius->show(); - bone_paint_radius_label->show(); - _update_bone_list(); - bone_paint_pos = Vector2(-100000, -100000); //send brush away when switching +void Polygon2DEditor::_select_mode(int p_mode) { + current_mode = Mode(p_mode); + mode_buttons[current_mode]->set_pressed(true); + for (int i = 0; i < ACTION_MAX; i++) { + action_buttons[i]->hide(); } + bone_scroll_main_vb->hide(); + bone_paint_strength->hide(); + bone_paint_radius->hide(); + bone_paint_radius_label->hide(); + switch (current_mode) { + case MODE_POINTS: { + action_buttons[ACTION_CREATE]->show(); + action_buttons[ACTION_CREATE_INTERNAL]->show(); + action_buttons[ACTION_REMOVE_INTERNAL]->show(); + action_buttons[ACTION_EDIT_POINT]->show(); + action_buttons[ACTION_MOVE]->show(); + action_buttons[ACTION_ROTATE]->show(); + action_buttons[ACTION_SCALE]->show(); - uv_edit->set_size(uv_edit->get_size()); // Necessary readjustment of the popup window. - uv_edit_draw->queue_redraw(); + if (node->get_polygon().is_empty()) { + _set_action(ACTION_CREATE); + } else { + _set_action(ACTION_EDIT_POINT); + } + } break; + case MODE_POLYGONS: { + action_buttons[ACTION_ADD_POLYGON]->show(); + action_buttons[ACTION_REMOVE_POLYGON]->show(); + _set_action(ACTION_ADD_POLYGON); + } break; + case MODE_UV: { + if (node->get_uv().size() != node->get_polygon().size()) { + _edit_menu_option(MENU_POLYGON_TO_UV); + } + action_buttons[ACTION_EDIT_POINT]->show(); + action_buttons[ACTION_MOVE]->show(); + action_buttons[ACTION_ROTATE]->show(); + action_buttons[ACTION_SCALE]->show(); + _set_action(ACTION_EDIT_POINT); + } break; + case MODE_BONES: { + action_buttons[ACTION_PAINT_WEIGHT]->show(); + action_buttons[ACTION_CLEAR_WEIGHT]->show(); + _set_action(ACTION_PAINT_WEIGHT); + + bone_scroll_main_vb->show(); + bone_paint_strength->show(); + bone_paint_radius->show(); + bone_paint_radius_label->show(); + _update_bone_list(); + bone_paint_pos = Vector2(-100000, -100000); // Send brush away when switching. + } break; + default: + break; + } + canvas->queue_redraw(); } -void Polygon2DEditor::_uv_edit_popup_show() { - EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->connect("version_changed", callable_mp(this, &Polygon2DEditor::_update_available_modes)); -} - -void Polygon2DEditor::_uv_edit_popup_hide() { - EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "uv_editor", Rect2(uv_edit->get_position(), uv_edit->get_size())); - _cancel_editing(); - EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->disconnect("version_changed", callable_mp(this, &Polygon2DEditor::_update_available_modes)); -} - -void Polygon2DEditor::_menu_option(int p_option) { +void Polygon2DEditor::_edit_menu_option(int p_option) { EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); switch (p_option) { - case MODE_EDIT_UV: { - uv_edit_draw->set_texture_filter(node->get_texture_filter_in_tree()); - - Vector points = node->get_polygon(); - Vector uvs = node->get_uv(); - if (uvs.size() != points.size()) { - undo_redo->create_action(TTR("Create UV Map")); - undo_redo->add_do_method(node, "set_uv", points); - undo_redo->add_undo_method(node, "set_uv", uvs); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); - undo_redo->commit_action(); - } - - const Rect2 bounds = EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "uv_editor", Rect2()); - if (bounds.has_area()) { - uv_edit->popup(bounds); - } else { - uv_edit->popup_centered_ratio(0.85); - } - _update_bone_list(); - _update_available_modes(); - get_tree()->connect("process_frame", callable_mp(this, &Polygon2DEditor::_center_view), CONNECT_ONE_SHOT); - } break; - case UVEDIT_POLYGON_TO_UV: { + case MENU_POLYGON_TO_UV: { Vector points = node->get_polygon(); if (points.size() == 0) { break; @@ -369,11 +318,9 @@ void Polygon2DEditor::_menu_option(int p_option) { undo_redo->create_action(TTR("Create UV Map")); undo_redo->add_do_method(node, "set_uv", points); undo_redo->add_undo_method(node, "set_uv", uvs); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); undo_redo->commit_action(); } break; - case UVEDIT_UV_TO_POLYGON: { + case MENU_UV_TO_POLYGON: { Vector points = node->get_polygon(); Vector uvs = node->get_uv(); if (uvs.size() == 0) { @@ -383,11 +330,9 @@ void Polygon2DEditor::_menu_option(int p_option) { undo_redo->create_action(TTR("Create Polygon")); undo_redo->add_do_method(node, "set_polygon", uvs); undo_redo->add_undo_method(node, "set_polygon", points); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); undo_redo->commit_action(); } break; - case UVEDIT_UV_CLEAR: { + case MENU_UV_CLEAR: { Vector uvs = node->get_uv(); if (uvs.size() == 0) { break; @@ -395,38 +340,33 @@ void Polygon2DEditor::_menu_option(int p_option) { undo_redo->create_action(TTR("Create UV Map")); undo_redo->add_do_method(node, "set_uv", Vector()); undo_redo->add_undo_method(node, "set_uv", uvs); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); undo_redo->commit_action(); } break; - case UVEDIT_GRID_SETTINGS: { + case MENU_GRID_SETTINGS: { grid_settings->popup_centered(); } break; - default: { - AbstractPolygon2DEditor::_menu_option(p_option); - } break; } } void Polygon2DEditor::_cancel_editing() { - if (uv_create) { - uv_drag = false; - uv_create = false; - node->set_uv(uv_create_uv_prev); - node->set_polygon(uv_create_poly_prev); - node->set_internal_vertex_count(uv_create_prev_internal_vertices); - node->set_vertex_colors(uv_create_colors_prev); - node->call("_set_bones", uv_create_bones_prev); - node->set_polygons(polygons_prev); + if (is_creating) { + is_dragging = false; + is_creating = false; + node->set_uv(previous_uv); + node->set_polygon(previous_polygon); + node->set_internal_vertex_count(previous_internal_vertices); + node->set_vertex_colors(previous_colors); + node->call("_set_bones", previous_bones); + node->set_polygons(previous_polygons); _update_polygon_editing_state(); _update_available_modes(); - } else if (uv_drag) { - uv_drag = false; - if (uv_edit_mode[0]->is_pressed()) { // Edit UV. - node->set_uv(points_prev); - } else if (uv_edit_mode[1]->is_pressed()) { // Edit polygon. - node->set_polygon(points_prev); + } else if (is_dragging) { + is_dragging = false; + if (current_mode == MODE_UV) { + node->set_uv(editing_points); + } else if (current_mode == MODE_POINTS) { + node->set_polygon(editing_points); } } @@ -448,8 +388,6 @@ void Polygon2DEditor::_update_polygon_editing_state() { void Polygon2DEditor::_commit_action() { // Makes that undo/redoing actions made outside of the UV editor still affect its polygon. EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); undo_redo->add_do_method(CanvasItemEditor::get_singleton(), "update_viewport"); undo_redo->add_undo_method(CanvasItemEditor::get_singleton(), "update_viewport"); undo_redo->commit_action(); @@ -463,58 +401,58 @@ void Polygon2DEditor::_set_use_snap(bool p_use) { void Polygon2DEditor::_set_show_grid(bool p_show) { snap_show_grid = p_show; EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "show_grid", p_show); - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); } void Polygon2DEditor::_set_snap_off_x(real_t p_val) { snap_offset.x = p_val; EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_offset", snap_offset); - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); } void Polygon2DEditor::_set_snap_off_y(real_t p_val) { snap_offset.y = p_val; EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_offset", snap_offset); - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); } void Polygon2DEditor::_set_snap_step_x(real_t p_val) { snap_step.x = p_val; EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_step", snap_step); - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); } void Polygon2DEditor::_set_snap_step_y(real_t p_val) { snap_step.y = p_val; EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_step", snap_step); - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); } -void Polygon2DEditor::_uv_mode(int p_mode) { +void Polygon2DEditor::_set_action(int p_action) { polygon_create.clear(); - uv_drag = false; - uv_create = false; + is_dragging = false; + is_creating = false; - uv_mode = UVMode(p_mode); - for (int i = 0; i < UV_MODE_MAX; i++) { - uv_button[i]->set_pressed(p_mode == i); + selected_action = Action(p_action); + for (int i = 0; i < ACTION_MAX; i++) { + action_buttons[i]->set_pressed(p_action == i); } - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); } -void Polygon2DEditor::_uv_input(const Ref &p_input) { +void Polygon2DEditor::_canvas_input(const Ref &p_input) { if (!_get_node()) { return; } - if (uv_panner->gui_input(p_input, uv_edit_draw->get_global_rect())) { + if (panner->gui_input(p_input, canvas->get_global_rect())) { accept_event(); return; } Transform2D mtx; - mtx.columns[2] = -uv_draw_ofs * uv_draw_zoom; - mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom)); + mtx.columns[2] = -draw_offset * draw_zoom; + mtx.scale_basis(Vector2(draw_zoom, draw_zoom)); EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); @@ -522,99 +460,95 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { if (mb.is_valid()) { if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { - uv_drag_from = snap_point(mb->get_position()); - uv_drag = true; - points_prev = node->get_uv(); - - if (uv_edit_mode[0]->is_pressed()) { //edit uv - points_prev = node->get_uv(); - } else { //edit polygon - points_prev = node->get_polygon(); + drag_from = snap_point(mb->get_position()); + is_dragging = true; + if (current_mode == MODE_UV) { + editing_points = node->get_uv(); + } else { + editing_points = node->get_polygon(); } - uv_move_current = uv_mode; - if (uv_move_current == UV_MODE_CREATE) { - if (!uv_create) { - points_prev.clear(); + current_action = selected_action; + if (current_action == ACTION_CREATE) { + if (!is_creating) { + editing_points.clear(); Vector2 tuv = mtx.affine_inverse().xform(snap_point(mb->get_position())); - points_prev.push_back(tuv); - uv_create_to = tuv; + editing_points.push_back(tuv); + create_to = tuv; point_drag_index = 0; - uv_drag_from = tuv; - uv_drag = true; - uv_create = true; - uv_create_uv_prev = node->get_uv(); - uv_create_poly_prev = node->get_polygon(); - uv_create_prev_internal_vertices = node->get_internal_vertex_count(); - uv_create_colors_prev = node->get_vertex_colors(); - uv_create_bones_prev = node->call("_get_bones"); - polygons_prev = node->get_polygons(); + drag_from = tuv; + is_dragging = true; + is_creating = true; + previous_uv = node->get_uv(); + previous_polygon = node->get_polygon(); + previous_internal_vertices = node->get_internal_vertex_count(); + previous_colors = node->get_vertex_colors(); + previous_bones = node->call("_get_bones"); + previous_polygons = node->get_polygons(); disable_polygon_editing(false, String()); - node->set_polygon(points_prev); - node->set_uv(points_prev); + node->set_polygon(editing_points); + node->set_uv(editing_points); node->set_internal_vertex_count(0); - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); } else { Vector2 tuv = mtx.affine_inverse().xform(snap_point(mb->get_position())); // Close the polygon if selected point is near start. Threshold for closing scaled by zoom level - if (points_prev.size() > 2 && tuv.distance_to(points_prev[0]) < (8 / uv_draw_zoom)) { + if (editing_points.size() > 2 && tuv.distance_to(editing_points[0]) < (8 / draw_zoom)) { undo_redo->create_action(TTR("Create Polygon & UV")); undo_redo->add_do_method(node, "set_uv", node->get_uv()); - undo_redo->add_undo_method(node, "set_uv", uv_create_uv_prev); + undo_redo->add_undo_method(node, "set_uv", previous_uv); undo_redo->add_do_method(node, "set_polygon", node->get_polygon()); - undo_redo->add_undo_method(node, "set_polygon", uv_create_poly_prev); + undo_redo->add_undo_method(node, "set_polygon", previous_polygon); undo_redo->add_do_method(node, "set_internal_vertex_count", 0); - undo_redo->add_undo_method(node, "set_internal_vertex_count", uv_create_prev_internal_vertices); + undo_redo->add_undo_method(node, "set_internal_vertex_count", previous_internal_vertices); undo_redo->add_do_method(node, "set_vertex_colors", Vector()); - undo_redo->add_undo_method(node, "set_vertex_colors", uv_create_colors_prev); + undo_redo->add_undo_method(node, "set_vertex_colors", previous_colors); undo_redo->add_do_method(node, "clear_bones"); - undo_redo->add_undo_method(node, "_set_bones", uv_create_bones_prev); + undo_redo->add_undo_method(node, "_set_bones", previous_bones); undo_redo->add_do_method(this, "_update_polygon_editing_state"); undo_redo->add_undo_method(this, "_update_polygon_editing_state"); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); undo_redo->commit_action(); - uv_drag = false; - uv_create = false; + is_dragging = false; + is_creating = false; _update_available_modes(); - _uv_mode(UV_MODE_EDIT_POINT); + _set_action(ACTION_EDIT_POINT); _menu_option(MODE_EDIT); } else { - points_prev.push_back(tuv); - point_drag_index = points_prev.size() - 1; - uv_drag_from = tuv; + editing_points.push_back(tuv); + point_drag_index = editing_points.size() - 1; + drag_from = tuv; } - node->set_polygon(points_prev); - node->set_uv(points_prev); + node->set_polygon(editing_points); + node->set_uv(editing_points); } CanvasItemEditor::get_singleton()->update_viewport(); } - if (uv_move_current == UV_MODE_CREATE_INTERNAL) { - uv_create_uv_prev = node->get_uv(); - uv_create_poly_prev = node->get_polygon(); - uv_create_colors_prev = node->get_vertex_colors(); - uv_create_bones_prev = node->call("_get_bones"); + if (current_action == ACTION_CREATE_INTERNAL) { + previous_uv = node->get_uv(); + previous_polygon = node->get_polygon(); + previous_colors = node->get_vertex_colors(); + previous_bones = node->call("_get_bones"); int internal_vertices = node->get_internal_vertex_count(); Vector2 pos = mtx.affine_inverse().xform(snap_point(mb->get_position())); - uv_create_poly_prev.push_back(pos); - uv_create_uv_prev.push_back(pos); - if (uv_create_colors_prev.size()) { - uv_create_colors_prev.push_back(Color(1, 1, 1)); + previous_polygon.push_back(pos); + previous_uv.push_back(pos); + if (previous_colors.size()) { + previous_colors.push_back(Color(1, 1, 1)); } undo_redo->create_action(TTR("Create Internal Vertex")); - undo_redo->add_do_method(node, "set_uv", uv_create_uv_prev); + undo_redo->add_do_method(node, "set_uv", previous_uv); undo_redo->add_undo_method(node, "set_uv", node->get_uv()); - undo_redo->add_do_method(node, "set_polygon", uv_create_poly_prev); + undo_redo->add_do_method(node, "set_polygon", previous_polygon); undo_redo->add_undo_method(node, "set_polygon", node->get_polygon()); - undo_redo->add_do_method(node, "set_vertex_colors", uv_create_colors_prev); + undo_redo->add_do_method(node, "set_vertex_colors", previous_colors); undo_redo->add_undo_method(node, "set_vertex_colors", node->get_vertex_colors()); for (int i = 0; i < node->get_bone_count(); i++) { Vector bonew = node->get_bone_weights(i); @@ -626,16 +560,14 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { undo_redo->add_undo_method(node, "set_internal_vertex_count", internal_vertices); undo_redo->add_do_method(this, "_update_polygon_editing_state"); undo_redo->add_undo_method(this, "_update_polygon_editing_state"); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); undo_redo->commit_action(); } - if (uv_move_current == UV_MODE_REMOVE_INTERNAL) { - uv_create_uv_prev = node->get_uv(); - uv_create_poly_prev = node->get_polygon(); - uv_create_colors_prev = node->get_vertex_colors(); - uv_create_bones_prev = node->call("_get_bones"); + if (current_action == ACTION_REMOVE_INTERNAL) { + previous_uv = node->get_uv(); + previous_polygon = node->get_polygon(); + previous_colors = node->get_vertex_colors(); + previous_bones = node->call("_get_bones"); int internal_vertices = node->get_internal_vertex_count(); if (internal_vertices <= 0) { @@ -645,8 +577,8 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { int closest = -1; real_t closest_dist = 1e20; - for (int i = points_prev.size() - internal_vertices; i < points_prev.size(); i++) { - Vector2 tuv = mtx.xform(uv_create_poly_prev[i]); + for (int i = editing_points.size() - internal_vertices; i < editing_points.size(); i++) { + Vector2 tuv = mtx.xform(previous_polygon[i]); real_t dist = tuv.distance_to(mb->get_position()); if (dist < 8 && dist < closest_dist) { closest = i; @@ -658,18 +590,18 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { return; } - uv_create_poly_prev.remove_at(closest); - uv_create_uv_prev.remove_at(closest); - if (uv_create_colors_prev.size()) { - uv_create_colors_prev.remove_at(closest); + previous_polygon.remove_at(closest); + previous_uv.remove_at(closest); + if (previous_colors.size()) { + previous_colors.remove_at(closest); } undo_redo->create_action(TTR("Remove Internal Vertex")); - undo_redo->add_do_method(node, "set_uv", uv_create_uv_prev); + undo_redo->add_do_method(node, "set_uv", previous_uv); undo_redo->add_undo_method(node, "set_uv", node->get_uv()); - undo_redo->add_do_method(node, "set_polygon", uv_create_poly_prev); + undo_redo->add_do_method(node, "set_polygon", previous_polygon); undo_redo->add_undo_method(node, "set_polygon", node->get_polygon()); - undo_redo->add_do_method(node, "set_vertex_colors", uv_create_colors_prev); + undo_redo->add_do_method(node, "set_vertex_colors", previous_colors); undo_redo->add_undo_method(node, "set_vertex_colors", node->get_vertex_colors()); for (int i = 0; i < node->get_bone_count(); i++) { Vector bonew = node->get_bone_weights(i); @@ -681,42 +613,40 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { undo_redo->add_undo_method(node, "set_internal_vertex_count", internal_vertices); undo_redo->add_do_method(this, "_update_polygon_editing_state"); undo_redo->add_undo_method(this, "_update_polygon_editing_state"); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); undo_redo->commit_action(); } - if (uv_move_current == UV_MODE_EDIT_POINT) { + if (current_action == ACTION_EDIT_POINT) { if (mb->is_shift_pressed() && mb->is_command_or_control_pressed()) { - uv_move_current = UV_MODE_SCALE; + current_action = ACTION_SCALE; } else if (mb->is_shift_pressed()) { - uv_move_current = UV_MODE_MOVE; + current_action = ACTION_MOVE; } else if (mb->is_command_or_control_pressed()) { - uv_move_current = UV_MODE_ROTATE; + current_action = ACTION_ROTATE; } } - if (uv_move_current == UV_MODE_EDIT_POINT) { + if (current_action == ACTION_EDIT_POINT) { point_drag_index = -1; - for (int i = 0; i < points_prev.size(); i++) { - Vector2 tuv = mtx.xform(points_prev[i]); + for (int i = 0; i < editing_points.size(); i++) { + Vector2 tuv = mtx.xform(editing_points[i]); if (tuv.distance_to(mb->get_position()) < 8) { - uv_drag_from = tuv; + drag_from = tuv; point_drag_index = i; } } if (point_drag_index == -1) { - uv_drag = false; + is_dragging = false; } } - if (uv_move_current == UV_MODE_ADD_POLYGON) { + if (current_action == ACTION_ADD_POLYGON) { int closest = -1; real_t closest_dist = 1e20; - for (int i = 0; i < points_prev.size(); i++) { - Vector2 tuv = mtx.xform(points_prev[i]); + for (int i = 0; i < editing_points.size(); i++) { + Vector2 tuv = mtx.xform(editing_points[i]); real_t dist = tuv.distance_to(mb->get_position()); if (dist < 8 && dist < closest_dist) { closest = i; @@ -739,8 +669,6 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { undo_redo->create_action(TTR("Add Custom Polygon")); undo_redo->add_do_method(node, "set_polygons", polygons); undo_redo->add_undo_method(node, "set_polygons", node->get_polygons()); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); undo_redo->commit_action(); } @@ -752,7 +680,7 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { } } - if (uv_move_current == UV_MODE_REMOVE_POLYGON) { + if (current_action == ACTION_REMOVE_POLYGON) { Array polygons = node->get_polygons(); polygons = polygons.duplicate(); //copy because its a reference @@ -763,10 +691,10 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { polys.resize(points.size()); for (int j = 0; j < polys.size(); j++) { int idx = points[j]; - if (idx < 0 || idx >= points_prev.size()) { + if (idx < 0 || idx >= editing_points.size()) { continue; } - polys.write[j] = mtx.xform(points_prev[idx]); + polys.write[j] = mtx.xform(editing_points[idx]); } if (Geometry2D::is_point_in_polygon(mb->get_position(), polys)) { @@ -780,13 +708,11 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { undo_redo->create_action(TTR("Remove Custom Polygon")); undo_redo->add_do_method(node, "set_polygons", polygons); undo_redo->add_undo_method(node, "set_polygons", node->get_polygons()); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); undo_redo->commit_action(); } } - if (uv_move_current == UV_MODE_PAINT_WEIGHT || uv_move_current == UV_MODE_CLEAR_WEIGHT) { + if (current_action == ACTION_PAINT_WEIGHT || current_action == ACTION_CLEAR_WEIGHT) { int bone_selected = -1; for (int i = 0; i < bone_scroll_vb->get_child_count(); i++) { CheckBox *c = Object::cast_to(bone_scroll_vb->get_child(i)); @@ -796,32 +722,28 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { } } - if (bone_selected != -1 && node->get_bone_weights(bone_selected).size() == points_prev.size()) { + if (bone_selected != -1 && node->get_bone_weights(bone_selected).size() == editing_points.size()) { prev_weights = node->get_bone_weights(bone_selected); bone_painting = true; bone_painting_bone = bone_selected; } } } else { - if (uv_drag && !uv_create) { - if (uv_edit_mode[0]->is_pressed()) { + if (is_dragging && !is_creating) { + if (current_mode == MODE_UV) { undo_redo->create_action(TTR("Transform UV Map")); undo_redo->add_do_method(node, "set_uv", node->get_uv()); - undo_redo->add_undo_method(node, "set_uv", points_prev); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); + undo_redo->add_undo_method(node, "set_uv", editing_points); undo_redo->commit_action(); - } else if (uv_edit_mode[1]->is_pressed()) { - switch (uv_move_current) { - case UV_MODE_EDIT_POINT: - case UV_MODE_MOVE: - case UV_MODE_ROTATE: - case UV_MODE_SCALE: { + } else if (current_mode == MODE_POINTS) { + switch (current_action) { + case ACTION_EDIT_POINT: + case ACTION_MOVE: + case ACTION_ROTATE: + case ACTION_SCALE: { undo_redo->create_action(TTR("Transform Polygon")); undo_redo->add_do_method(node, "set_polygon", node->get_polygon()); - undo_redo->add_undo_method(node, "set_polygon", points_prev); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); + undo_redo->add_undo_method(node, "set_polygon", editing_points); undo_redo->commit_action(); } break; default: { @@ -829,15 +751,13 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { } } - uv_drag = false; + is_dragging = false; } if (bone_painting) { undo_redo->create_action(TTR("Paint Bone Weights")); undo_redo->add_do_method(node, "set_bone_weights", bone_painting_bone, node->get_bone_weights(bone_painting_bone)); undo_redo->add_undo_method(node, "set_bone_weights", bone_painting_bone, prev_weights); - undo_redo->add_do_method(uv_edit_draw, "queue_redraw"); - undo_redo->add_undo_method(uv_edit_draw, "queue_redraw"); undo_redo->commit_action(); bone_painting = false; } @@ -849,79 +769,79 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { node->set_bone_weights(bone_painting_bone, prev_weights); } - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); } } Ref mm = p_input; if (mm.is_valid()) { - if (uv_drag) { + if (is_dragging) { Vector2 uv_drag_to = mm->get_position(); uv_drag_to = snap_point(uv_drag_to); - Vector2 drag = mtx.affine_inverse().basis_xform(uv_drag_to - uv_drag_from); + Vector2 drag = mtx.affine_inverse().basis_xform(uv_drag_to - drag_from); - switch (uv_move_current) { - case UV_MODE_CREATE: { - if (uv_create) { - uv_create_to = mtx.affine_inverse().xform(snap_point(mm->get_position())); + switch (current_action) { + case ACTION_CREATE: { + if (is_creating) { + create_to = mtx.affine_inverse().xform(snap_point(mm->get_position())); } } break; - case UV_MODE_EDIT_POINT: { - Vector uv_new = points_prev; + case ACTION_EDIT_POINT: { + Vector uv_new = editing_points; uv_new.set(point_drag_index, uv_new[point_drag_index] + drag); - if (uv_edit_mode[0]->is_pressed()) { //edit uv + if (current_mode == MODE_UV) { node->set_uv(uv_new); - } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon + } else if (current_mode == MODE_POINTS) { node->set_polygon(uv_new); } } break; - case UV_MODE_MOVE: { - Vector uv_new = points_prev; + case ACTION_MOVE: { + Vector uv_new = editing_points; for (int i = 0; i < uv_new.size(); i++) { uv_new.set(i, uv_new[i] + drag); } - if (uv_edit_mode[0]->is_pressed()) { //edit uv + if (current_mode == MODE_UV) { node->set_uv(uv_new); - } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon + } else if (current_mode == MODE_POINTS) { node->set_polygon(uv_new); } } break; - case UV_MODE_ROTATE: { + case ACTION_ROTATE: { Vector2 center; - Vector uv_new = points_prev; + Vector uv_new = editing_points; for (int i = 0; i < uv_new.size(); i++) { - center += points_prev[i]; + center += editing_points[i]; } center /= uv_new.size(); - real_t angle = (uv_drag_from - mtx.xform(center)).normalized().angle_to((uv_drag_to - mtx.xform(center)).normalized()); + real_t angle = (drag_from - mtx.xform(center)).normalized().angle_to((uv_drag_to - mtx.xform(center)).normalized()); for (int i = 0; i < uv_new.size(); i++) { - Vector2 rel = points_prev[i] - center; + Vector2 rel = editing_points[i] - center; rel = rel.rotated(angle); uv_new.set(i, center + rel); } - if (uv_edit_mode[0]->is_pressed()) { //edit uv + if (current_mode == MODE_UV) { node->set_uv(uv_new); - } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon + } else if (current_mode == MODE_POINTS) { node->set_polygon(uv_new); } } break; - case UV_MODE_SCALE: { + case ACTION_SCALE: { Vector2 center; - Vector uv_new = points_prev; + Vector uv_new = editing_points; for (int i = 0; i < uv_new.size(); i++) { - center += points_prev[i]; + center += editing_points[i]; } center /= uv_new.size(); - real_t from_dist = uv_drag_from.distance_to(mtx.xform(center)); + real_t from_dist = drag_from.distance_to(mtx.xform(center)); real_t to_dist = uv_drag_to.distance_to(mtx.xform(center)); if (from_dist < 2) { break; @@ -930,19 +850,19 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { real_t scale = to_dist / from_dist; for (int i = 0; i < uv_new.size(); i++) { - Vector2 rel = points_prev[i] - center; + Vector2 rel = editing_points[i] - center; rel = rel * scale; uv_new.set(i, center + rel); } - if (uv_edit_mode[0]->is_pressed()) { //edit uv + if (current_mode == MODE_UV) { node->set_uv(uv_new); - } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon + } else if (current_mode == MODE_POINTS) { node->set_polygon(uv_new); } } break; - case UV_MODE_PAINT_WEIGHT: - case UV_MODE_CLEAR_WEIGHT: { + case ACTION_PAINT_WEIGHT: + case ACTION_CLEAR_WEIGHT: { bone_paint_pos = mm->get_position(); } break; default: { @@ -957,13 +877,13 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { real_t amount = bone_paint_strength->get_value(); real_t radius = bone_paint_radius->get_value() * EDSCALE; - if (uv_mode == UV_MODE_CLEAR_WEIGHT) { + if (selected_action == ACTION_CLEAR_WEIGHT) { amount = -amount; } float *w = painted_weights.ptrw(); const float *r = prev_weights.ptr(); - const Vector2 *rv = points_prev.ptr(); + const Vector2 *rv = editing_points.ptr(); for (int i = 0; i < pc; i++) { if (mtx.xform(rv[i]).distance_to(bone_paint_pos) < radius) { @@ -975,14 +895,14 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { node->set_bone_weights(bone_painting_bone, painted_weights); } - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); CanvasItemEditor::get_singleton()->update_viewport(); } else if (polygon_create.size()) { - uv_create_to = mtx.affine_inverse().xform(mm->get_position()); - uv_edit_draw->queue_redraw(); - } else if (uv_mode == UV_MODE_PAINT_WEIGHT || uv_mode == UV_MODE_CLEAR_WEIGHT) { + create_to = mtx.affine_inverse().xform(mm->get_position()); + canvas->queue_redraw(); + } else if (selected_action == ACTION_PAINT_WEIGHT || selected_action == ACTION_CLEAR_WEIGHT) { bone_paint_pos = mm->get_position(); - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); } } } @@ -990,17 +910,16 @@ void Polygon2DEditor::_uv_input(const Ref &p_input) { void Polygon2DEditor::_update_available_modes() { // Force point editing mode if there's no polygon yet. if (node->get_polygon().is_empty()) { - if (!uv_edit_mode[1]->is_pressed()) { - uv_edit_mode[1]->set_pressed(true); - _uv_edit_mode_select(1); + if (current_mode != MODE_POINTS) { + _select_mode(MODE_POINTS); } - uv_edit_mode[0]->set_disabled(true); - uv_edit_mode[2]->set_disabled(true); - uv_edit_mode[3]->set_disabled(true); + mode_buttons[MODE_UV]->set_disabled(true); + mode_buttons[MODE_POLYGONS]->set_disabled(true); + mode_buttons[MODE_BONES]->set_disabled(true); } else { - uv_edit_mode[0]->set_disabled(false); - uv_edit_mode[2]->set_disabled(false); - uv_edit_mode[3]->set_disabled(false); + mode_buttons[MODE_UV]->set_disabled(false); + mode_buttons[MODE_POLYGONS]->set_disabled(false); + mode_buttons[MODE_BONES]->set_disabled(false); } } @@ -1008,7 +927,7 @@ void Polygon2DEditor::_center_view() { Size2 texture_size; if (node->get_texture().is_valid()) { texture_size = node->get_texture()->get_size(); - Vector2 zoom_factor = (uv_edit_draw->get_size() - Vector2(1, 1) * 50 * EDSCALE) / texture_size; + Vector2 zoom_factor = (canvas->get_size() - Vector2(1, 1) * 50 * EDSCALE) / texture_size; zoom_widget->set_zoom(MIN(zoom_factor.x, zoom_factor.y)); } else { zoom_widget->set_zoom(EDSCALE); @@ -1016,33 +935,33 @@ void Polygon2DEditor::_center_view() { // Recalculate scroll limits. _update_zoom_and_pan(false); - Size2 offset = (texture_size - uv_edit_draw->get_size() / uv_draw_zoom) / 2; - uv_hscroll->set_value_no_signal(offset.x); - uv_vscroll->set_value_no_signal(offset.y); + Size2 offset = (texture_size - canvas->get_size() / draw_zoom) / 2; + hscroll->set_value_no_signal(offset.x); + vscroll->set_value_no_signal(offset.y); _update_zoom_and_pan(false); } -void Polygon2DEditor::_uv_pan_callback(Vector2 p_scroll_vec, Ref p_event) { - uv_hscroll->set_value_no_signal(uv_hscroll->get_value() - p_scroll_vec.x / uv_draw_zoom); - uv_vscroll->set_value_no_signal(uv_vscroll->get_value() - p_scroll_vec.y / uv_draw_zoom); +void Polygon2DEditor::_pan_callback(Vector2 p_scroll_vec, Ref p_event) { + hscroll->set_value_no_signal(hscroll->get_value() - p_scroll_vec.x / draw_zoom); + vscroll->set_value_no_signal(vscroll->get_value() - p_scroll_vec.y / draw_zoom); _update_zoom_and_pan(false); } -void Polygon2DEditor::_uv_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref p_event) { - zoom_widget->set_zoom(uv_draw_zoom * p_zoom_factor); - uv_draw_ofs += p_origin / uv_draw_zoom - p_origin / zoom_widget->get_zoom(); - uv_hscroll->set_value_no_signal(uv_draw_ofs.x); - uv_vscroll->set_value_no_signal(uv_draw_ofs.y); +void Polygon2DEditor::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref p_event) { + zoom_widget->set_zoom(draw_zoom * p_zoom_factor); + draw_offset += p_origin / draw_zoom - p_origin / zoom_widget->get_zoom(); + hscroll->set_value_no_signal(draw_offset.x); + vscroll->set_value_no_signal(draw_offset.y); _update_zoom_and_pan(false); } void Polygon2DEditor::_update_zoom_and_pan(bool p_zoom_at_center) { - uv_draw_ofs = Vector2(uv_hscroll->get_value(), uv_vscroll->get_value()); - real_t previous_zoom = uv_draw_zoom; - uv_draw_zoom = zoom_widget->get_zoom(); + draw_offset = Vector2(hscroll->get_value(), vscroll->get_value()); + real_t previous_zoom = draw_zoom; + draw_zoom = zoom_widget->get_zoom(); if (p_zoom_at_center) { - Vector2 center = uv_edit_draw->get_size() / 2; - uv_draw_ofs += center / previous_zoom - center / uv_draw_zoom; + Vector2 center = canvas->get_size() / 2; + draw_offset += center / previous_zoom - center / draw_zoom; } Point2 min_corner; @@ -1051,55 +970,69 @@ void Polygon2DEditor::_update_zoom_and_pan(bool p_zoom_at_center) { max_corner += node->get_texture()->get_size(); } - Vector points = uv_edit_mode[0]->is_pressed() ? node->get_uv() : node->get_polygon(); + Vector points = current_mode == MODE_UV ? node->get_uv() : node->get_polygon(); for (int i = 0; i < points.size(); i++) { min_corner = min_corner.min(points[i]); max_corner = max_corner.max(points[i]); } - Size2 page_size = uv_edit_draw->get_size() / uv_draw_zoom; - Vector2 margin = Vector2(50, 50) * EDSCALE / uv_draw_zoom; + Size2 page_size = canvas->get_size() / draw_zoom; + Vector2 margin = Vector2(50, 50) * EDSCALE / draw_zoom; min_corner -= page_size - margin; max_corner += page_size - margin; - uv_hscroll->set_block_signals(true); - uv_hscroll->set_min(min_corner.x); - uv_hscroll->set_max(max_corner.x); - uv_hscroll->set_page(page_size.x); - uv_hscroll->set_value(uv_draw_ofs.x); - uv_hscroll->set_block_signals(false); + hscroll->set_block_signals(true); + hscroll->set_min(min_corner.x); + hscroll->set_max(max_corner.x); + hscroll->set_page(page_size.x); + hscroll->set_value(draw_offset.x); + hscroll->set_block_signals(false); - uv_vscroll->set_block_signals(true); - uv_vscroll->set_min(min_corner.y); - uv_vscroll->set_max(max_corner.y); - uv_vscroll->set_page(page_size.y); - uv_vscroll->set_value(uv_draw_ofs.y); - uv_vscroll->set_block_signals(false); + vscroll->set_block_signals(true); + vscroll->set_min(min_corner.y); + vscroll->set_max(max_corner.y); + vscroll->set_page(page_size.y); + vscroll->set_value(draw_offset.y); + vscroll->set_block_signals(false); - uv_edit_draw->queue_redraw(); + canvas->queue_redraw(); } -void Polygon2DEditor::_uv_draw() { - if (!uv_edit->is_visible() || !_get_node()) { +void Polygon2DEditor::_center_view_on_draw(bool p_enabled) { + if (center_view_on_draw == p_enabled) { return; } + center_view_on_draw = p_enabled; + if (center_view_on_draw) { + // Ensure that the view is centered even if the canvas is redrawn multiple times in the frame. + get_tree()->connect("process_frame", callable_mp(this, &Polygon2DEditor::_center_view_on_draw).bind(false), CONNECT_ONE_SHOT); + } +} + +void Polygon2DEditor::_canvas_draw() { + if (!polygon_edit->is_visible() || !_get_node()) { + return; + } + if (center_view_on_draw) { + _center_view(); + } Ref base_tex = node->get_texture(); String warning; Transform2D mtx; - mtx.columns[2] = -uv_draw_ofs * uv_draw_zoom; - mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom)); + mtx.columns[2] = -draw_offset * draw_zoom; + mtx.scale_basis(Vector2(draw_zoom, draw_zoom)); // Draw texture as a background if editing uvs or no uv mapping exist. - if (uv_edit_mode[0]->is_pressed() || uv_mode == UV_MODE_CREATE || node->get_polygon().is_empty() || node->get_uv().size() != node->get_polygon().size()) { + if (current_mode == MODE_UV || selected_action == ACTION_CREATE || node->get_polygon().is_empty() || node->get_uv().size() != node->get_polygon().size()) { if (base_tex.is_valid()) { Transform2D texture_transform = Transform2D(node->get_texture_rotation(), node->get_texture_offset()); texture_transform.scale(node->get_texture_scale()); texture_transform.affine_invert(); - RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), mtx * texture_transform); - uv_edit_draw->draw_texture(base_tex, Point2()); - RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), Transform2D()); + RS::get_singleton()->canvas_item_add_set_transform(canvas->get_canvas_item(), mtx * texture_transform); + canvas->draw_texture(base_tex, Point2()); + RS::get_singleton()->canvas_item_add_set_transform(canvas->get_canvas_item(), Transform2D()); } preview_polygon->hide(); } else { @@ -1116,7 +1049,7 @@ void Polygon2DEditor::_uv_draw() { preview_polygon->set_invert(node->get_invert()); preview_polygon->set_invert_border(node->get_invert_border()); preview_polygon->set_internal_vertex_count(node->get_internal_vertex_count()); - if (uv_mode == UV_MODE_ADD_POLYGON) { + if (selected_action == ACTION_ADD_POLYGON) { preview_polygon->set_polygons(Array()); } else { preview_polygon->set_polygons(node->get_polygons()); @@ -1126,7 +1059,7 @@ void Polygon2DEditor::_uv_draw() { if (snap_show_grid) { Color grid_color = Color(1.0, 1.0, 1.0, 0.15); - Size2 s = uv_edit_draw->get_size(); + Size2 s = canvas->get_size(); int last_cell = 0; if (snap_step.x != 0) { @@ -1136,7 +1069,7 @@ void Polygon2DEditor::_uv_draw() { last_cell = cell; } if (last_cell != cell) { - uv_edit_draw->draw_line(Point2(i, 0), Point2(i, s.height), grid_color, Math::round(EDSCALE)); + canvas->draw_line(Point2(i, 0), Point2(i, s.height), grid_color, Math::round(EDSCALE)); } last_cell = cell; } @@ -1149,7 +1082,7 @@ void Polygon2DEditor::_uv_draw() { last_cell = cell; } if (last_cell != cell) { - uv_edit_draw->draw_line(Point2(0, i), Point2(s.width, i), grid_color, Math::round(EDSCALE)); + canvas->draw_line(Point2(0, i), Point2(s.width, i), grid_color, Math::round(EDSCALE)); } last_cell = cell; } @@ -1159,15 +1092,15 @@ void Polygon2DEditor::_uv_draw() { Array polygons = node->get_polygons(); Vector uvs; - if (uv_edit_mode[0]->is_pressed()) { //edit uv + if (current_mode == MODE_UV) { uvs = node->get_uv(); - } else { //edit polygon + } else { uvs = node->get_polygon(); } const float *weight_r = nullptr; - if (uv_edit_mode[3]->is_pressed()) { + if (current_mode == MODE_BONES) { int bone_selected = -1; for (int i = 0; i < bone_scroll_vb->get_child_count(); i++) { CheckBox *c = Object::cast_to(bone_scroll_vb->get_child(i)); @@ -1204,16 +1137,16 @@ void Polygon2DEditor::_uv_draw() { for (int i = 0; i < uvs.size(); i++) { int next = uv_draw_max > 0 ? (i + 1) % uv_draw_max : 0; - if (i < uv_draw_max && uv_drag && uv_move_current == UV_MODE_EDIT_POINT && EDITOR_GET("editors/polygon_editor/show_previous_outline")) { - uv_edit_draw->draw_line(mtx.xform(points_prev[i]), mtx.xform(points_prev[next]), prev_color, Math::round(EDSCALE)); + if (i < uv_draw_max && is_dragging && current_action == ACTION_EDIT_POINT && EDITOR_GET("editors/polygon_editor/show_previous_outline")) { + canvas->draw_line(mtx.xform(editing_points[i]), mtx.xform(editing_points[next]), prev_color, Math::round(EDSCALE)); } Vector2 next_point = uvs[next]; - if (uv_create && i == uvs.size() - 1) { - next_point = uv_create_to; + if (is_creating && i == uvs.size() - 1) { + next_point = create_to; } if (i < uv_draw_max) { // If using or creating polygons, do not show outline (will show polygons instead). - uv_edit_draw->draw_line(mtx.xform(uvs[i]), mtx.xform(next_point), poly_line_color, Math::round(EDSCALE)); + canvas->draw_line(mtx.xform(uvs[i]), mtx.xform(next_point), poly_line_color, Math::round(EDSCALE)); } } @@ -1233,10 +1166,10 @@ void Polygon2DEditor::_uv_draw() { if (idx_next < 0 || idx_next >= uvs.size()) { continue; } - uv_edit_draw->draw_line(mtx.xform(uvs[idx]), mtx.xform(uvs[idx_next]), polygon_line_color, Math::round(EDSCALE)); + canvas->draw_line(mtx.xform(uvs[idx]), mtx.xform(uvs[idx_next]), polygon_line_color, Math::round(EDSCALE)); } if (points.size() >= 3) { - uv_edit_draw->draw_colored_polygon(polypoints, polygon_fill_color); + canvas->draw_colored_polygon(polypoints, polygon_fill_color); } } @@ -1244,13 +1177,13 @@ void Polygon2DEditor::_uv_draw() { if (weight_r) { Vector2 draw_pos = mtx.xform(uvs[i]); float weight = weight_r[i]; - 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)); + canvas->draw_rect(Rect2(draw_pos - Vector2(2, 2) * EDSCALE, Vector2(5, 5) * EDSCALE), Color(weight, weight, weight, 1.0), Math::round(EDSCALE)); } else { if (i < uv_draw_max) { - uv_edit_draw->draw_texture(handle, mtx.xform(uvs[i]) - handle->get_size() * 0.5); + canvas->draw_texture(handle, mtx.xform(uvs[i]) - handle->get_size() * 0.5); } else { // Internal vertex - uv_edit_draw->draw_texture(handle, mtx.xform(uvs[i]) - handle->get_size() * 0.5, Color(0.6, 0.8, 1)); + canvas->draw_texture(handle, mtx.xform(uvs[i]) - handle->get_size() * 0.5, Color(0.6, 0.8, 1)); } } } @@ -1258,12 +1191,12 @@ void Polygon2DEditor::_uv_draw() { if (polygon_create.size()) { for (int i = 0; i < polygon_create.size(); i++) { Vector2 from = uvs[polygon_create[i]]; - Vector2 to = (i + 1) < polygon_create.size() ? uvs[polygon_create[i + 1]] : uv_create_to; - uv_edit_draw->draw_line(mtx.xform(from), mtx.xform(to), polygon_line_color, Math::round(EDSCALE)); + Vector2 to = (i + 1) < polygon_create.size() ? uvs[polygon_create[i + 1]] : create_to; + canvas->draw_line(mtx.xform(from), mtx.xform(to), polygon_line_color, Math::round(EDSCALE)); } } - if (uv_mode == UV_MODE_PAINT_WEIGHT || uv_mode == UV_MODE_CLEAR_WEIGHT) { + if (selected_action == ACTION_PAINT_WEIGHT || selected_action == ACTION_CLEAR_WEIGHT) { NodePath bone_path; for (int i = 0; i < bone_scroll_vb->get_child_count(); i++) { CheckBox *c = Object::cast_to(bone_scroll_vb->get_child(i)); @@ -1300,8 +1233,8 @@ void Polygon2DEditor::_uv_draw() { Transform2D endpoint_xform = bone_xform * n->get_transform(); Color color = current ? Color(1, 1, 1) : Color(0.5, 0.5, 0.5); - 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)); - uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, Math::round((current ? 3 : 2) * EDSCALE)); + canvas->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), Color(0, 0, 0), Math::round((current ? 5 : 4) * EDSCALE)); + canvas->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, Math::round((current ? 3 : 2) * EDSCALE)); } if (!found_child) { @@ -1310,14 +1243,14 @@ void Polygon2DEditor::_uv_draw() { Transform2D endpoint_xform = bone_xform * Transform2D(0, Vector2(bone->get_length(), 0)).rotated(bone->get_bone_angle()); Color color = current ? Color(1, 1, 1) : Color(0.5, 0.5, 0.5); - 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)); - uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, Math::round((current ? 3 : 2) * EDSCALE)); + canvas->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), Color(0, 0, 0), Math::round((current ? 5 : 4) * EDSCALE)); + canvas->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, Math::round((current ? 3 : 2) * EDSCALE)); } } } //draw paint circle - uv_edit_draw->draw_circle(bone_paint_pos, bone_paint_radius->get_value() * EDSCALE, Color(1, 1, 1, 0.1)); + canvas->draw_circle(bone_paint_pos, bone_paint_radius->get_value() * EDSCALE, Color(1, 1, 1, 0.1)); } } @@ -1328,8 +1261,8 @@ void Polygon2DEditor::_bind_methods() { Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const { if (use_snap) { - p_target.x = Math::snap_scalar((snap_offset.x - uv_draw_ofs.x) * uv_draw_zoom, snap_step.x * uv_draw_zoom, p_target.x); - p_target.y = Math::snap_scalar((snap_offset.y - uv_draw_ofs.y) * uv_draw_zoom, snap_step.y * uv_draw_zoom, p_target.y); + p_target.x = Math::snap_scalar((snap_offset.x - draw_offset.x) * draw_zoom, snap_step.x * draw_zoom, p_target.x); + p_target.y = Math::snap_scalar((snap_offset.y - draw_offset.y) * draw_zoom, snap_step.y * draw_zoom, p_target.y); } return p_target; @@ -1342,93 +1275,52 @@ Polygon2DEditor::Polygon2DEditor() { use_snap = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "snap_enabled", false); snap_show_grid = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "show_grid", false); - button_uv = memnew(Button); - button_uv->set_theme_type_variation(SceneStringName(FlatButton)); - add_child(button_uv); - button_uv->set_tooltip_text(TTR("Open Polygon 2D UV editor.")); - button_uv->connect(SceneStringName(pressed), callable_mp(this, &Polygon2DEditor::_menu_option).bind(MODE_EDIT_UV)); + selected_action = ACTION_EDIT_POINT; + polygon_edit = memnew(VBoxContainer); + HBoxContainer *toolbar = memnew(HBoxContainer); - uv_mode = UV_MODE_EDIT_POINT; - uv_edit = memnew(UVEditDialog); - uv_edit->set_title(TTR("Polygon 2D UV Editor")); - uv_edit->set_process_shortcut_input(true); - add_child(uv_edit); - uv_edit->connect(SceneStringName(confirmed), callable_mp(this, &Polygon2DEditor::_uv_edit_popup_hide)); - uv_edit->connect("canceled", callable_mp(this, &Polygon2DEditor::_uv_edit_popup_hide)); - uv_edit->connect("about_to_popup", callable_mp(this, &Polygon2DEditor::_uv_edit_popup_show)); + Ref mode_button_group; + mode_button_group.instantiate(); + for (int i = 0; i < MODE_MAX; i++) { + mode_buttons[i] = memnew(Button); + toolbar->add_child(mode_buttons[i]); + mode_buttons[i]->set_toggle_mode(true); + mode_buttons[i]->set_button_group(mode_button_group); + mode_buttons[i]->connect(SceneStringName(pressed), callable_mp(this, &Polygon2DEditor::_select_mode).bind(i)); + } + mode_buttons[MODE_POINTS]->set_text(TTR("Points")); + mode_buttons[MODE_POLYGONS]->set_text(TTR("Polygons")); + mode_buttons[MODE_UV]->set_text(TTR("UV")); + mode_buttons[MODE_BONES]->set_text(TTR("Bones")); - VBoxContainer *uv_main_vb = memnew(VBoxContainer); - uv_edit->add_child(uv_main_vb); - HBoxContainer *uv_mode_hb = memnew(HBoxContainer); + toolbar->add_child(memnew(VSeparator)); - uv_edit_group.instantiate(); - - uv_edit_mode[0] = memnew(Button); - uv_mode_hb->add_child(uv_edit_mode[0]); - uv_edit_mode[0]->set_toggle_mode(true); - uv_edit_mode[1] = memnew(Button); - uv_mode_hb->add_child(uv_edit_mode[1]); - uv_edit_mode[1]->set_toggle_mode(true); - uv_edit_mode[2] = memnew(Button); - uv_mode_hb->add_child(uv_edit_mode[2]); - uv_edit_mode[2]->set_toggle_mode(true); - uv_edit_mode[3] = memnew(Button); - uv_mode_hb->add_child(uv_edit_mode[3]); - uv_edit_mode[3]->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("Points")); - uv_edit_mode[2]->set_text(TTR("Polygons")); - uv_edit_mode[3]->set_text(TTR("Bones")); - - 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[3]->set_button_group(uv_edit_group); - - uv_edit_mode[0]->connect(SceneStringName(pressed), callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(0)); - uv_edit_mode[1]->connect(SceneStringName(pressed), callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(1)); - uv_edit_mode[2]->connect(SceneStringName(pressed), callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(2)); - uv_edit_mode[3]->connect(SceneStringName(pressed), callable_mp(this, &Polygon2DEditor::_uv_edit_mode_select).bind(3)); - - uv_mode_hb->add_child(memnew(VSeparator)); - - uv_main_vb->add_child(uv_mode_hb); - for (int i = 0; i < UV_MODE_MAX; i++) { - uv_button[i] = memnew(Button); - uv_button[i]->set_theme_type_variation(SceneStringName(FlatButton)); - uv_button[i]->set_toggle_mode(true); - uv_mode_hb->add_child(uv_button[i]); - uv_button[i]->connect(SceneStringName(pressed), callable_mp(this, &Polygon2DEditor::_uv_mode).bind(i)); - uv_button[i]->set_focus_mode(FOCUS_NONE); + polygon_edit->add_child(toolbar); + for (int i = 0; i < ACTION_MAX; i++) { + action_buttons[i] = memnew(Button); + action_buttons[i]->set_theme_type_variation(SceneStringName(FlatButton)); + action_buttons[i]->set_toggle_mode(true); + toolbar->add_child(action_buttons[i]); + action_buttons[i]->connect(SceneStringName(pressed), callable_mp(this, &Polygon2DEditor::_set_action).bind(i)); + action_buttons[i]->set_focus_mode(FOCUS_NONE); } - uv_button[UV_MODE_CREATE]->set_tooltip_text(TTR("Create Polygon")); - uv_button[UV_MODE_CREATE_INTERNAL]->set_tooltip_text(TTR("Create Internal Vertex")); - uv_button[UV_MODE_REMOVE_INTERNAL]->set_tooltip_text(TTR("Remove Internal Vertex")); + action_buttons[ACTION_CREATE]->set_tooltip_text(TTR("Create Polygon")); + action_buttons[ACTION_CREATE_INTERNAL]->set_tooltip_text(TTR("Create Internal Vertex")); + action_buttons[ACTION_REMOVE_INTERNAL]->set_tooltip_text(TTR("Remove Internal Vertex")); Key key = (OS::get_singleton()->has_feature("macos") || OS::get_singleton()->has_feature("web_macos") || OS::get_singleton()->has_feature("web_ios")) ? Key::META : Key::CTRL; // TRANSLATORS: %s is Control or Command key name. - uv_button[UV_MODE_EDIT_POINT]->set_tooltip_text(TTR("Move Points") + "\n" + vformat(TTR("%s: Rotate"), find_keycode_name(key)) + "\n" + TTR("Shift: Move All") + "\n" + vformat(TTR("%s + Shift: Scale"), find_keycode_name(key))); - uv_button[UV_MODE_MOVE]->set_tooltip_text(TTR("Move Polygon")); - uv_button[UV_MODE_ROTATE]->set_tooltip_text(TTR("Rotate Polygon")); - uv_button[UV_MODE_SCALE]->set_tooltip_text(TTR("Scale Polygon")); - uv_button[UV_MODE_ADD_POLYGON]->set_tooltip_text(TTR("Create a custom polygon. Enables custom polygon rendering.")); - uv_button[UV_MODE_REMOVE_POLYGON]->set_tooltip_text(TTR("Remove a custom polygon. If none remain, custom polygon rendering is disabled.")); - uv_button[UV_MODE_PAINT_WEIGHT]->set_tooltip_text(TTR("Paint weights with specified intensity.")); - uv_button[UV_MODE_CLEAR_WEIGHT]->set_tooltip_text(TTR("Unpaint weights with specified intensity.")); - - uv_button[UV_MODE_CREATE]->hide(); - uv_button[UV_MODE_CREATE_INTERNAL]->hide(); - uv_button[UV_MODE_REMOVE_INTERNAL]->hide(); - uv_button[UV_MODE_ADD_POLYGON]->hide(); - uv_button[UV_MODE_REMOVE_POLYGON]->hide(); - uv_button[UV_MODE_PAINT_WEIGHT]->hide(); - uv_button[UV_MODE_CLEAR_WEIGHT]->hide(); - uv_button[UV_MODE_EDIT_POINT]->set_pressed(true); + action_buttons[ACTION_EDIT_POINT]->set_tooltip_text(TTR("Move Points") + "\n" + vformat(TTR("%s: Rotate"), find_keycode_name(key)) + "\n" + TTR("Shift: Move All") + "\n" + vformat(TTR("%s + Shift: Scale"), find_keycode_name(key))); + action_buttons[ACTION_MOVE]->set_tooltip_text(TTR("Move Polygon")); + action_buttons[ACTION_ROTATE]->set_tooltip_text(TTR("Rotate Polygon")); + action_buttons[ACTION_SCALE]->set_tooltip_text(TTR("Scale Polygon")); + action_buttons[ACTION_ADD_POLYGON]->set_tooltip_text(TTR("Create a custom polygon. Enables custom polygon rendering.")); + action_buttons[ACTION_REMOVE_POLYGON]->set_tooltip_text(TTR("Remove a custom polygon. If none remain, custom polygon rendering is disabled.")); + action_buttons[ACTION_PAINT_WEIGHT]->set_tooltip_text(TTR("Paint weights with specified intensity.")); + action_buttons[ACTION_CLEAR_WEIGHT]->set_tooltip_text(TTR("Unpaint weights with specified intensity.")); bone_paint_strength = memnew(HSlider); - uv_mode_hb->add_child(bone_paint_strength); + toolbar->add_child(bone_paint_strength); bone_paint_strength->set_custom_minimum_size(Size2(75 * EDSCALE, 0)); bone_paint_strength->set_v_size_flags(SIZE_SHRINK_CENTER); bone_paint_strength->set_min(0); @@ -1437,57 +1329,54 @@ Polygon2DEditor::Polygon2DEditor() { bone_paint_strength->set_value(0.5); bone_paint_radius_label = memnew(Label(TTR("Radius:"))); - uv_mode_hb->add_child(bone_paint_radius_label); + toolbar->add_child(bone_paint_radius_label); bone_paint_radius = memnew(SpinBox); - uv_mode_hb->add_child(bone_paint_radius); + toolbar->add_child(bone_paint_radius); - bone_paint_strength->hide(); - bone_paint_radius->hide(); - bone_paint_radius_label->hide(); bone_paint_radius->set_min(1); bone_paint_radius->set_max(100); bone_paint_radius->set_step(1); bone_paint_radius->set_value(32); HSplitContainer *uv_main_hsc = memnew(HSplitContainer); - uv_main_vb->add_child(uv_main_hsc); + polygon_edit->add_child(uv_main_hsc); uv_main_hsc->set_v_size_flags(SIZE_EXPAND_FILL); - uv_edit_background = memnew(Panel); - uv_main_hsc->add_child(uv_edit_background); - uv_edit_background->set_h_size_flags(SIZE_EXPAND_FILL); - uv_edit_background->set_custom_minimum_size(Size2(200, 200) * EDSCALE); - uv_edit_background->set_clip_contents(true); + canvas_background = memnew(Panel); + uv_main_hsc->add_child(canvas_background); + canvas_background->set_h_size_flags(SIZE_EXPAND_FILL); + canvas_background->set_custom_minimum_size(Size2(200, 200) * EDSCALE); + canvas_background->set_clip_contents(true); preview_polygon = memnew(Polygon2D); - uv_edit_background->add_child(preview_polygon); + canvas_background->add_child(preview_polygon); - uv_edit_draw = memnew(Control); - uv_edit_background->add_child(uv_edit_draw); - uv_edit_draw->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); + canvas = memnew(Control); + canvas_background->add_child(canvas); + canvas->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); Control *space = memnew(Control); - uv_mode_hb->add_child(space); + toolbar->add_child(space); space->set_h_size_flags(SIZE_EXPAND_FILL); - uv_menu = memnew(MenuButton); - uv_mode_hb->add_child(uv_menu); - uv_menu->set_flat(false); - uv_menu->set_theme_type_variation("FlatMenuButton"); - uv_menu->set_text(TTR("Edit")); - uv_menu->get_popup()->add_item(TTR("Copy Polygon to UV"), UVEDIT_POLYGON_TO_UV); - uv_menu->get_popup()->add_item(TTR("Copy UV to Polygon"), UVEDIT_UV_TO_POLYGON); - uv_menu->get_popup()->add_separator(); - uv_menu->get_popup()->add_item(TTR("Clear UV"), UVEDIT_UV_CLEAR); - uv_menu->get_popup()->add_separator(); - uv_menu->get_popup()->add_item(TTR("Grid Settings"), UVEDIT_GRID_SETTINGS); - uv_menu->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &Polygon2DEditor::_menu_option)); + edit_menu = memnew(MenuButton); + toolbar->add_child(edit_menu); + edit_menu->set_flat(false); + edit_menu->set_theme_type_variation("FlatMenuButton"); + edit_menu->set_text(TTR("Edit")); + edit_menu->get_popup()->add_item(TTR("Copy Polygon to UV"), MENU_POLYGON_TO_UV); + edit_menu->get_popup()->add_item(TTR("Copy UV to Polygon"), MENU_UV_TO_POLYGON); + edit_menu->get_popup()->add_separator(); + edit_menu->get_popup()->add_item(TTR("Clear UV"), MENU_UV_CLEAR); + edit_menu->get_popup()->add_separator(); + edit_menu->get_popup()->add_item(TTR("Grid Settings"), MENU_GRID_SETTINGS); + edit_menu->get_popup()->connect(SceneStringName(id_pressed), callable_mp(this, &Polygon2DEditor::_edit_menu_option)); - uv_mode_hb->add_child(memnew(VSeparator)); + toolbar->add_child(memnew(VSeparator)); b_snap_enable = memnew(Button); b_snap_enable->set_theme_type_variation(SceneStringName(FlatButton)); - uv_mode_hb->add_child(b_snap_enable); + toolbar->add_child(b_snap_enable); b_snap_enable->set_text(TTR("Snap")); b_snap_enable->set_focus_mode(FOCUS_NONE); b_snap_enable->set_toggle_mode(true); @@ -1497,7 +1386,7 @@ Polygon2DEditor::Polygon2DEditor() { b_snap_grid = memnew(Button); b_snap_grid->set_theme_type_variation(SceneStringName(FlatButton)); - uv_mode_hb->add_child(b_snap_grid); + toolbar->add_child(b_snap_grid); b_snap_grid->set_text(TTR("Grid")); b_snap_grid->set_focus_mode(FOCUS_NONE); b_snap_grid->set_toggle_mode(true); @@ -1507,7 +1396,7 @@ Polygon2DEditor::Polygon2DEditor() { grid_settings = memnew(AcceptDialog); grid_settings->set_title(TTR("Configure Grid:")); - uv_edit->add_child(grid_settings); + polygon_edit->add_child(grid_settings); VBoxContainer *grid_settings_vb = memnew(VBoxContainer); grid_settings->add_child(grid_settings_vb); @@ -1548,22 +1437,21 @@ Polygon2DEditor::Polygon2DEditor() { grid_settings_vb->add_margin_child(TTR("Grid Step Y:"), sb_step_y); zoom_widget = memnew(EditorZoomWidget); - uv_edit_draw->add_child(zoom_widget); + canvas->add_child(zoom_widget); zoom_widget->set_anchors_and_offsets_preset(Control::PRESET_TOP_LEFT, Control::PRESET_MODE_MINSIZE, 2 * EDSCALE); zoom_widget->connect("zoom_changed", callable_mp(this, &Polygon2DEditor::_update_zoom_and_pan).unbind(1).bind(true)); zoom_widget->set_shortcut_context(nullptr); - uv_vscroll = memnew(VScrollBar); - uv_vscroll->set_step(0.001); - uv_edit_draw->add_child(uv_vscroll); - uv_vscroll->connect(SceneStringName(value_changed), callable_mp(this, &Polygon2DEditor::_update_zoom_and_pan).unbind(1).bind(false)); - uv_hscroll = memnew(HScrollBar); - uv_hscroll->set_step(0.001); - uv_edit_draw->add_child(uv_hscroll); - uv_hscroll->connect(SceneStringName(value_changed), callable_mp(this, &Polygon2DEditor::_update_zoom_and_pan).unbind(1).bind(false)); + vscroll = memnew(VScrollBar); + vscroll->set_step(0.001); + canvas->add_child(vscroll); + vscroll->connect(SceneStringName(value_changed), callable_mp(this, &Polygon2DEditor::_update_zoom_and_pan).unbind(1).bind(false)); + hscroll = memnew(HScrollBar); + hscroll->set_step(0.001); + canvas->add_child(hscroll); + hscroll->connect(SceneStringName(value_changed), callable_mp(this, &Polygon2DEditor::_update_zoom_and_pan).unbind(1).bind(false)); bone_scroll_main_vb = memnew(VBoxContainer); - bone_scroll_main_vb->hide(); bone_scroll_main_vb->set_custom_minimum_size(Size2(150 * EDSCALE, 0)); sync_bones = memnew(Button(TTR("Sync Bones to Polygon"))); bone_scroll_main_vb->add_child(sync_bones); @@ -1578,21 +1466,19 @@ Polygon2DEditor::Polygon2DEditor() { bone_scroll_vb = memnew(VBoxContainer); bone_scroll->add_child(bone_scroll_vb); - uv_panner.instantiate(); - uv_panner->set_callbacks(callable_mp(this, &Polygon2DEditor::_uv_pan_callback), callable_mp(this, &Polygon2DEditor::_uv_zoom_callback)); + panner.instantiate(); + panner->set_callbacks(callable_mp(this, &Polygon2DEditor::_pan_callback), callable_mp(this, &Polygon2DEditor::_zoom_callback)); - uv_edit_draw->connect(SceneStringName(draw), callable_mp(this, &Polygon2DEditor::_uv_draw)); - uv_edit_draw->connect(SceneStringName(gui_input), callable_mp(this, &Polygon2DEditor::_uv_input)); - uv_edit_draw->connect(SceneStringName(focus_exited), callable_mp(uv_panner.ptr(), &ViewPanner::release_pan_key)); - uv_edit_draw->set_focus_mode(FOCUS_CLICK); - uv_draw_zoom = 1.0; - point_drag_index = -1; - uv_drag = false; - uv_create = false; - bone_painting = false; + canvas->connect(SceneStringName(draw), callable_mp(this, &Polygon2DEditor::_canvas_draw)); + canvas->connect(SceneStringName(gui_input), callable_mp(this, &Polygon2DEditor::_canvas_input)); + canvas->connect(SceneStringName(focus_exited), callable_mp(panner.ptr(), &ViewPanner::release_pan_key)); + canvas->set_focus_mode(FOCUS_CLICK); error = memnew(AcceptDialog); add_child(error); + + dock_button = EditorNode::get_bottom_panel()->add_item(TTR("Polygon"), polygon_edit, ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_polygon_2d_bottom_panel", TTR("Toggle Polygon Bottom Panel"))); + dock_button->hide(); } Polygon2DEditorPlugin::Polygon2DEditorPlugin() : diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index e4142e2affa..acf88042c7c 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -51,50 +51,62 @@ class VScrollBar; class Polygon2DEditor : public AbstractPolygon2DEditor { GDCLASS(Polygon2DEditor, AbstractPolygon2DEditor); + enum { + MENU_POLYGON_TO_UV, + MENU_UV_TO_POLYGON, + MENU_UV_CLEAR, + MENU_GRID_SETTINGS, + }; + enum Mode { - MODE_EDIT_UV = MODE_CONT, - UVEDIT_POLYGON_TO_UV, - UVEDIT_UV_TO_POLYGON, - UVEDIT_UV_CLEAR, - UVEDIT_GRID_SETTINGS + MODE_POINTS, + MODE_POLYGONS, + MODE_UV, + MODE_BONES, + MODE_MAX }; - enum UVMode { - UV_MODE_CREATE, - UV_MODE_CREATE_INTERNAL, - UV_MODE_REMOVE_INTERNAL, - UV_MODE_EDIT_POINT, - UV_MODE_MOVE, - UV_MODE_ROTATE, - UV_MODE_SCALE, - UV_MODE_ADD_POLYGON, - UV_MODE_REMOVE_POLYGON, - UV_MODE_PAINT_WEIGHT, - UV_MODE_CLEAR_WEIGHT, - UV_MODE_MAX + enum Action { + ACTION_CREATE, + ACTION_CREATE_INTERNAL, + ACTION_REMOVE_INTERNAL, + ACTION_EDIT_POINT, + ACTION_MOVE, + ACTION_ROTATE, + ACTION_SCALE, + ACTION_ADD_POLYGON, + ACTION_REMOVE_POLYGON, + ACTION_PAINT_WEIGHT, + ACTION_CLEAR_WEIGHT, + ACTION_MAX }; - Button *uv_edit_mode[4]; - Ref uv_edit_group; - Polygon2D *node = nullptr; + Polygon2D *previous_node = nullptr; - UVMode uv_mode; - AcceptDialog *uv_edit = nullptr; - Button *uv_button[UV_MODE_MAX]; + Button *dock_button = nullptr; + VBoxContainer *polygon_edit = nullptr; + Mode current_mode = MODE_MAX; // Uninitialized. + Button *mode_buttons[MODE_MAX]; + Action selected_action = ACTION_CREATE; + Button *action_buttons[ACTION_MAX]; Button *b_snap_enable = nullptr; Button *b_snap_grid = nullptr; - Panel *uv_edit_background = nullptr; - Polygon2D *preview_polygon = nullptr; - Control *uv_edit_draw = nullptr; - EditorZoomWidget *zoom_widget = nullptr; - HScrollBar *uv_hscroll = nullptr; - VScrollBar *uv_vscroll = nullptr; - MenuButton *uv_menu = nullptr; + MenuButton *edit_menu = nullptr; - Ref uv_panner; - void _uv_pan_callback(Vector2 p_scroll_vec, Ref p_event); - void _uv_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref p_event); + Control *canvas = nullptr; + Panel *canvas_background = nullptr; + Polygon2D *preview_polygon = nullptr; + EditorZoomWidget *zoom_widget = nullptr; + HScrollBar *hscroll = nullptr; + VScrollBar *vscroll = nullptr; + bool center_view_on_draw = false; + + Ref panner; + void _pan_callback(Vector2 p_scroll_vec, Ref p_event); + void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref p_event); + Vector2 draw_offset; + real_t draw_zoom = 1.0; VBoxContainer *bone_scroll_main_vb = nullptr; ScrollContainer *bone_scroll = nullptr; @@ -103,7 +115,7 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { HSlider *bone_paint_strength = nullptr; SpinBox *bone_paint_radius = nullptr; Label *bone_paint_radius_label = nullptr; - bool bone_painting; + bool bone_painting = false; int bone_painting_bone = 0; Vector prev_weights; Vector2 bone_paint_pos; @@ -112,34 +124,30 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { void _sync_bones(); void _update_bone_list(); - Vector2 uv_draw_ofs; - real_t uv_draw_zoom; - Vector points_prev; - Vector uv_create_uv_prev; - Vector uv_create_poly_prev; - Vector uv_create_colors_prev; - int uv_create_prev_internal_vertices = 0; - Array uv_create_bones_prev; - Array polygons_prev; + Vector editing_points; + Vector previous_uv; + Vector previous_polygon; + Vector previous_colors; + int previous_internal_vertices = 0; + Array previous_bones; + Array previous_polygons; - Vector2 uv_create_to; - int point_drag_index; - bool uv_drag; - bool uv_create; + Vector2 create_to; + int point_drag_index = -1; + bool is_dragging = false; + bool is_creating = false; Vector polygon_create; - UVMode uv_move_current; - Vector2 uv_drag_from; + Action current_action = ACTION_CREATE; + Vector2 drag_from; AcceptDialog *error = nullptr; - Button *button_uv = nullptr; - - bool use_snap; - bool snap_show_grid; + bool use_snap = false; + bool snap_show_grid = false; Vector2 snap_offset; Vector2 snap_step; - virtual void _menu_option(int p_option) override; + void _edit_menu_option(int p_option); void _cancel_editing(); void _update_polygon_editing_state(); @@ -147,9 +155,10 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { void _center_view(); void _update_zoom_and_pan(bool p_zoom_at_center); - void _uv_input(const Ref &p_input); - void _uv_draw(); - void _uv_mode(int p_mode); + void _canvas_input(const Ref &p_input); + void _center_view_on_draw(bool p_enabled = true); + void _canvas_draw(); + void _set_action(int p_mode); void _set_use_snap(bool p_use); void _set_show_grid(bool p_show); @@ -158,9 +167,7 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { void _set_snap_step_x(real_t p_val); void _set_snap_step_y(real_t p_val); - void _uv_edit_mode_select(int p_mode); - void _uv_edit_popup_show(); - void _uv_edit_popup_hide(); + void _select_mode(int p_mode); void _bone_paint_selected(int p_index); int _get_polygon_count() const override;