diff options
Diffstat (limited to 'editor/plugins')
26 files changed, 802 insertions, 927 deletions
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 16423decc4..a85f4456f7 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -103,6 +103,11 @@ bool AbstractPolygon2DEditor::_is_line() const { return false; } +bool AbstractPolygon2DEditor::_has_uv() const { + + return false; +} + int AbstractPolygon2DEditor::_get_polygon_count() const { return 1; @@ -202,12 +207,7 @@ void AbstractPolygon2DEditor::_notification(int p_what) { button_edit->set_pressed(true); get_tree()->connect("node_removed", this, "_node_removed"); - create_resource->connect("confirmed", this, "_create_resource"); - - } break; - case NOTIFICATION_PHYSICS_PROCESS: { - } break; } } @@ -250,8 +250,12 @@ void AbstractPolygon2DEditor::_wip_close() { _set_polygon(0, wip); } else if (wip.size() >= (_is_line() ? 2 : 3)) { - undo_redo->create_action(TTR("Create Poly")); + undo_redo->create_action(TTR("Create Polygon")); _action_add_polygon(wip); + if (_has_uv()) { + undo_redo->add_do_method(_get_node(), "set_uv", PoolVector<Vector2>()); + undo_redo->add_undo_method(_get_node(), "set_uv", _get_node()->get("uv")); + } _commit_action(); } else { @@ -313,7 +317,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) if (vertices.size() < (_is_line() ? 2 : 3)) { vertices.push_back(cpoint); - undo_redo->create_action(TTR("Edit Poly")); + undo_redo->create_action(TTR("Edit Polygon")); selected_point = Vertex(insert.polygon, vertices.size()); _action_set_polygon(insert.polygon, vertices); _commit_action(); @@ -331,7 +335,6 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) undo_redo->create_action(TTR("Insert Point")); _action_set_polygon(insert.polygon, vertices); _commit_action(); - return true; } } else { @@ -363,7 +366,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) ERR_FAIL_INDEX_V(edited_point.vertex, vertices.size(), false); vertices.write[edited_point.vertex] = edited_point.pos - _get_offset(edited_point.polygon); - undo_redo->create_action(TTR("Edit Poly")); + undo_redo->create_action(TTR("Edit Polygon")); _action_set_polygon(edited_point.polygon, pre_move_edit, vertices); _commit_action(); @@ -531,6 +534,7 @@ bool AbstractPolygon2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) } void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { + if (!_get_node()) return; @@ -631,9 +635,11 @@ void AbstractPolygon2DEditor::edit(Node *p_polygon) { _set_node(p_polygon); - //Enable the pencil tool if the polygon is empty + // Enable the pencil tool if the polygon is empty. if (_is_empty()) _menu_option(MODE_CREATE); + else + _menu_option(MODE_EDIT); wip.clear(); wip_active = false; @@ -664,12 +670,12 @@ void AbstractPolygon2DEditor::remove_point(const Vertex &p_vertex) { vertices.remove(p_vertex.vertex); - undo_redo->create_action(TTR("Edit Poly (Remove Point)")); + undo_redo->create_action(TTR("Edit Polygon (Remove Point)")); _action_set_polygon(p_vertex.polygon, vertices); _commit_action(); } else { - undo_redo->create_action(TTR("Remove Poly And Point")); + undo_redo->create_action(TTR("Remove Polygon And Point")); _action_remove_polygon(p_vertex.polygon); _commit_action(); } @@ -777,19 +783,19 @@ AbstractPolygon2DEditor::AbstractPolygon2DEditor(EditorNode *p_editor, bool p_wi add_child(button_create); button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE)); button_create->set_toggle_mode(true); - button_create->set_tooltip(TTR("Create a new polygon from scratch")); + button_create->set_tooltip(TTR("Create points.")); button_edit = memnew(ToolButton); add_child(button_edit); button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT)); button_edit->set_toggle_mode(true); - button_edit->set_tooltip(TTR("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point.")); + button_edit->set_tooltip(TTR("Edit points.\nLMB: Move Point\nRMB: Erase Point")); button_delete = memnew(ToolButton); add_child(button_delete); button_delete->connect("pressed", this, "_menu_option", varray(MODE_DELETE)); button_delete->set_toggle_mode(true); - button_delete->set_tooltip(TTR("Delete points")); + button_delete->set_tooltip(TTR("Erase points.")); create_resource = memnew(ConfirmationDialog); add_child(create_resource); diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h index c03670f254..046e8540e7 100644 --- a/editor/plugins/abstract_polygon_2d_editor.h +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -88,12 +88,10 @@ class AbstractPolygon2DEditor : public HBoxContainer { protected: enum { - MODE_CREATE, MODE_EDIT, MODE_DELETE, MODE_CONT, - }; int mode; @@ -116,13 +114,12 @@ protected: PosVertex closest_edge_point(const Vector2 &p_pos) const; bool _is_empty() const; - void _commit_action(); -protected: virtual Node2D *_get_node() const = 0; virtual void _set_node(Node *p_polygon) = 0; virtual bool _is_line() const; + virtual bool _has_uv() const; virtual int _get_polygon_count() const; virtual Vector2 _get_offset(int p_idx) const; virtual Variant _get_polygon(int p_idx) const; @@ -132,6 +129,7 @@ protected: virtual void _action_remove_polygon(int p_idx); virtual void _action_set_polygon(int p_idx, const Variant &p_polygon); virtual void _action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon); + virtual void _commit_action(); virtual bool _has_resource() const; virtual void _create_resource(); diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index 394b888d0e..e2fe9a91d8 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -607,6 +607,8 @@ void AnimationNodeBlendSpace2DEditor::_update_space() { auto_triangles->set_pressed(blend_space->get_auto_triangles()); + interpolation->select(blend_space->get_blend_mode()); + max_x_value->set_value(blend_space->get_max_space().x); max_y_value->set_value(blend_space->get_max_space().y); @@ -636,6 +638,8 @@ void AnimationNodeBlendSpace2DEditor::_config_changed(double) { undo_redo->add_undo_method(blend_space.ptr(), "set_min_space", blend_space->get_min_space()); undo_redo->add_do_method(blend_space.ptr(), "set_snap", Vector2(snap_x->get_value(), snap_y->get_value())); undo_redo->add_undo_method(blend_space.ptr(), "set_snap", blend_space->get_snap()); + undo_redo->add_do_method(blend_space.ptr(), "set_blend_mode", interpolation->get_selected()); + undo_redo->add_undo_method(blend_space.ptr(), "set_blend_mode", blend_space->get_blend_mode()); undo_redo->add_do_method(this, "_update_space"); undo_redo->add_undo_method(this, "_update_space"); undo_redo->commit_action(); @@ -752,6 +756,10 @@ void AnimationNodeBlendSpace2DEditor::_notification(int p_what) { snap->set_icon(get_icon("SnapGrid", "EditorIcons")); open_editor->set_icon(get_icon("Edit", "EditorIcons")); auto_triangles->set_icon(get_icon("AutoTriangle", "EditorIcons")); + interpolation->clear(); + interpolation->add_icon_item(get_icon("TrackContinuous", "EditorIcons"), "", 0); + interpolation->add_icon_item(get_icon("TrackDiscrete", "EditorIcons"), "", 1); + interpolation->add_icon_item(get_icon("TrackCapture", "EditorIcons"), "", 2); } if (p_what == NOTIFICATION_PROCESS) { @@ -914,6 +922,13 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { snap_y->set_step(0.01); snap_y->set_max(1000); + top_hb->add_child(memnew(VSeparator)); + + top_hb->add_child(memnew(Label(TTR("Blend:")))); + interpolation = memnew(OptionButton); + top_hb->add_child(interpolation); + interpolation->connect("item_selected", this, "_config_changed"); + edit_hb = memnew(HBoxContainer); top_hb->add_child(edit_hb); edit_hb->add_child(memnew(VSeparator)); diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h index 613289e4d8..603fa1cd19 100644 --- a/editor/plugins/animation_blend_space_2d_editor.h +++ b/editor/plugins/animation_blend_space_2d_editor.h @@ -60,6 +60,7 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin { ToolButton *snap; SpinBox *snap_x; SpinBox *snap_y; + OptionButton *interpolation; ToolButton *auto_triangles; diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index e83773257b..990c77430f 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -849,7 +849,7 @@ void AnimationNodeStateMachineEditor::_state_machine_pos_draw() { return; int idx = -1; - for (int i = 0; node_rects.size(); i++) { + for (int i = 0; i < node_rects.size(); i++) { if (node_rects[i].node_name == playback->get_current_node()) { idx = i; break; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index ee2283a035..8d9872236c 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -4606,7 +4606,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { warning_child_of_container = memnew(Label); warning_child_of_container->hide(); - warning_child_of_container->set_text("Warning: Children of a container get their position and size determined only by their parent"); + warning_child_of_container->set_text(TTR("Warning: Children of a container get their position and size determined only by their parent")); add_control_to_info_overlay(warning_child_of_container); h_scroll = memnew(HScrollBar); @@ -4626,19 +4626,19 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { zoom_minus = memnew(ToolButton); zoom_hb->add_child(zoom_minus); zoom_minus->connect("pressed", this, "_button_zoom_minus"); - zoom_minus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_minus", TTR("Zoom out"), KEY_MASK_CMD | KEY_MINUS)); + zoom_minus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_minus", TTR("Zoom Out"), KEY_MASK_CMD | KEY_MINUS)); zoom_minus->set_focus_mode(FOCUS_NONE); zoom_reset = memnew(ToolButton); zoom_hb->add_child(zoom_reset); zoom_reset->connect("pressed", this, "_button_zoom_reset"); - zoom_reset->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom reset"), KEY_MASK_CMD | KEY_0)); + zoom_reset->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset"), KEY_MASK_CMD | KEY_0)); zoom_reset->set_focus_mode(FOCUS_NONE); zoom_plus = memnew(ToolButton); zoom_hb->add_child(zoom_plus); zoom_plus->connect("pressed", this, "_button_zoom_plus"); - zoom_plus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_plus", TTR("Zoom in"), KEY_MASK_CMD | KEY_EQUAL)); // Usually direct access key for PLUS + zoom_plus->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_plus", TTR("Zoom In"), KEY_MASK_CMD | KEY_EQUAL)); // Usually direct access key for PLUS zoom_plus->set_focus_mode(FOCUS_NONE); updating_scroll = false; diff --git a/editor/plugins/collision_polygon_editor_plugin.cpp b/editor/plugins/collision_polygon_editor_plugin.cpp index 805a7d3835..e92a91db7c 100644 --- a/editor/plugins/collision_polygon_editor_plugin.cpp +++ b/editor/plugins/collision_polygon_editor_plugin.cpp @@ -95,7 +95,7 @@ void Polygon3DEditor::_menu_option(int p_option) { void Polygon3DEditor::_wip_close() { - undo_redo->create_action(TTR("Create Poly3D")); + undo_redo->create_action(TTR("Create Polygon3D")); undo_redo->add_undo_method(node, "set_polygon", node->call("get_polygon")); undo_redo->add_do_method(node, "set_polygon", wip); undo_redo->add_do_method(this, "_polygon_draw"); diff --git a/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp index 8df40232b0..a32f42cc56 100644 --- a/editor/plugins/item_list_editor_plugin.cpp +++ b/editor/plugins/item_list_editor_plugin.cpp @@ -265,6 +265,9 @@ void ItemListEditor::_notification(int p_notification) { add_button->set_icon(get_icon("Add", "EditorIcons")); del_button->set_icon(get_icon("Remove", "EditorIcons")); + } else if (p_notification == NOTIFICATION_READY) { + + get_tree()->connect("node_removed", this, "_node_removed"); } } @@ -341,6 +344,7 @@ bool ItemListEditor::handles(Object *p_object) const { void ItemListEditor::_bind_methods() { + ClassDB::bind_method("_node_removed", &ItemListEditor::_node_removed); ClassDB::bind_method("_edit_items", &ItemListEditor::_edit_items); ClassDB::bind_method("_add_button", &ItemListEditor::_add_pressed); ClassDB::bind_method("_delete_button", &ItemListEditor::_delete_pressed); diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp index 6a16cf0989..646883fbda 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.cpp +++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp @@ -30,425 +30,91 @@ #include "light_occluder_2d_editor_plugin.h" -#include "canvas_item_editor_plugin.h" -#include "core/os/file_access.h" -#include "editor/editor_settings.h" +Ref<OccluderPolygon2D> LightOccluder2DEditor::_ensure_occluder() const { -void LightOccluder2DEditor::_notification(int p_what) { + Ref<OccluderPolygon2D> occluder = node->get_occluder_polygon(); + if (!occluder.is_valid()) { - switch (p_what) { - - case NOTIFICATION_READY: { - - button_create->set_icon(get_icon("Edit", "EditorIcons")); - button_edit->set_icon(get_icon("MovePoint", "EditorIcons")); - button_edit->set_pressed(true); - get_tree()->connect("node_removed", this, "_node_removed"); - create_poly->connect("confirmed", this, "_create_poly"); - - } break; - case NOTIFICATION_PHYSICS_PROCESS: { - - } break; - } -} -void LightOccluder2DEditor::_node_removed(Node *p_node) { - - if (p_node == node) { - node = NULL; - hide(); - canvas_item_editor->update_viewport(); + occluder = Ref<OccluderPolygon2D>(memnew(OccluderPolygon2D)); + node->set_occluder_polygon(occluder); } + return occluder; } -void LightOccluder2DEditor::_menu_option(int p_option) { +Node2D *LightOccluder2DEditor::_get_node() const { - switch (p_option) { - - case MODE_CREATE: { - - mode = MODE_CREATE; - button_create->set_pressed(true); - button_edit->set_pressed(false); - } break; - case MODE_EDIT: { - - mode = MODE_EDIT; - button_create->set_pressed(false); - button_edit->set_pressed(true); - } break; - } + return node; } -void LightOccluder2DEditor::_wip_close(bool p_closed) { - - undo_redo->create_action(TTR("Create Poly")); - undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", node->get_occluder_polygon()->get_polygon()); - undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", wip); - undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_closed", node->get_occluder_polygon()->is_closed()); - undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_closed", p_closed); +void LightOccluder2DEditor::_set_node(Node *p_polygon) { - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); - undo_redo->commit_action(); - wip.clear(); - wip_active = false; - mode = MODE_EDIT; - button_edit->set_pressed(true); - button_create->set_pressed(false); - edited_point = -1; + node = Object::cast_to<LightOccluder2D>(p_polygon); } -bool LightOccluder2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { +bool LightOccluder2DEditor::_is_line() const { - if (!node) + Ref<OccluderPolygon2D> occluder = node->get_occluder_polygon(); + if (occluder.is_valid()) + return !occluder->is_closed(); + else return false; - - if (node->get_occluder_polygon().is_null()) { - Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) { - create_poly->set_text(TTR("No OccluderPolygon2D resource on this node.\nCreate and assign one?")); - create_poly->popup_centered_minsize(); - } - return (mb.is_valid() && mb->get_button_index() == 1); - } - - Ref<InputEventMouseButton> mb = p_event; - - if (mb.is_valid()) { - - Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - - Vector2 gpoint = mb->get_position(); - Vector2 cpoint = node->get_global_transform().affine_inverse().xform(canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mb->get_position()))); - - Vector<Vector2> poly = Variant(node->get_occluder_polygon()->get_polygon()); - - //first check if a point is to be added (segment split) - real_t grab_threshold = EDITOR_DEF("editors/poly_editor/point_grab_radius", 8); - - switch (mode) { - - case MODE_CREATE: { - - if (mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) { - - if (!wip_active) { - - wip.clear(); - wip.push_back(cpoint); - wip_active = true; - edited_point_pos = cpoint; - canvas_item_editor->update_viewport(); - edited_point = 1; - return true; - } else { - - if (wip.size() > 1 && xform.xform(wip[0]).distance_to(gpoint) < grab_threshold) { - //wip closed - _wip_close(true); - - return true; - } else if (wip.size() > 1 && xform.xform(wip[wip.size() - 1]).distance_to(gpoint) < grab_threshold) { - //wip closed - _wip_close(false); - return true; - - } else { - - wip.push_back(cpoint); - edited_point = wip.size(); - canvas_item_editor->update_viewport(); - return true; - - //add wip point - } - } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && wip_active) { - _wip_close(true); - } - - } break; - - case MODE_EDIT: { - - if (mb->get_button_index() == BUTTON_LEFT) { - if (mb->is_pressed()) { - - if (mb->get_control()) { - - if (poly.size() < 3) { - - undo_redo->create_action(TTR("Edit Poly")); - undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", poly); - poly.push_back(cpoint); - undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", poly); - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); - undo_redo->commit_action(); - return true; - } - - //search edges - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - for (int i = 0; i < poly.size(); i++) { - - Vector2 points[2] = { xform.xform(poly[i]), - xform.xform(poly[(i + 1) % poly.size()]) }; - - Vector2 cp = Geometry::get_closest_point_to_segment_2d(gpoint, points); - if (cp.distance_squared_to(points[0]) < CMP_EPSILON2 || cp.distance_squared_to(points[1]) < CMP_EPSILON2) - continue; //not valid to reuse point - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_dist = d; - closest_pos = cp; - closest_idx = i; - } - } - - if (closest_idx >= 0) { - - pre_move_edit = poly; - poly.insert(closest_idx + 1, xform.affine_inverse().xform(closest_pos)); - edited_point = closest_idx + 1; - edited_point_pos = xform.affine_inverse().xform(closest_pos); - node->get_occluder_polygon()->set_polygon(Variant(poly)); - canvas_item_editor->update_viewport(); - return true; - } - } else { - - //look for points to move - - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - for (int i = 0; i < poly.size(); i++) { - - Vector2 cp = xform.xform(poly[i]); - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_dist = d; - closest_pos = cp; - closest_idx = i; - } - } - - if (closest_idx >= 0) { - - pre_move_edit = poly; - edited_point = closest_idx; - edited_point_pos = xform.affine_inverse().xform(closest_pos); - canvas_item_editor->update_viewport(); - return true; - } - } - } else { - - if (edited_point != -1) { - - //apply - - ERR_FAIL_INDEX_V(edited_point, poly.size(), false); - poly.write[edited_point] = edited_point_pos; - undo_redo->create_action(TTR("Edit Poly")); - undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", poly); - undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", pre_move_edit); - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); - undo_redo->commit_action(); - - edited_point = -1; - return true; - } - } - } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed() && edited_point == -1) { - - int closest_idx = -1; - Vector2 closest_pos; - real_t closest_dist = 1e10; - for (int i = 0; i < poly.size(); i++) { - - Vector2 cp = xform.xform(poly[i]); - - real_t d = cp.distance_to(gpoint); - if (d < closest_dist && d < grab_threshold) { - closest_dist = d; - closest_pos = cp; - closest_idx = i; - } - } - - if (closest_idx >= 0) { - - undo_redo->create_action(TTR("Edit Poly (Remove Point)")); - undo_redo->add_undo_method(node->get_occluder_polygon().ptr(), "set_polygon", poly); - poly.remove(closest_idx); - undo_redo->add_do_method(node->get_occluder_polygon().ptr(), "set_polygon", poly); - undo_redo->add_do_method(canvas_item_editor, "update_viewport"); - undo_redo->add_undo_method(canvas_item_editor, "update_viewport"); - undo_redo->commit_action(); - return true; - } - } - - } break; - } - } - - Ref<InputEventMouseMotion> mm = p_event; - - if (mm.is_valid()) { - - if (edited_point != -1 && (wip_active || mm->get_button_mask() & BUTTON_MASK_LEFT)) { - - Vector2 gpoint = mm->get_position(); - Vector2 cpoint = canvas_item_editor->get_canvas_transform().affine_inverse().xform(gpoint); - cpoint = canvas_item_editor->snap_point(cpoint); - edited_point_pos = node->get_global_transform().affine_inverse().xform(cpoint); - - canvas_item_editor->update_viewport(); - } - } - - return false; } -void LightOccluder2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { - - if (!node || !node->get_occluder_polygon().is_valid()) - return; - - Vector<Vector2> poly; +int LightOccluder2DEditor::_get_polygon_count() const { - if (wip_active) - poly = wip; + Ref<OccluderPolygon2D> occluder = node->get_occluder_polygon(); + if (occluder.is_valid()) + return occluder->get_polygon().size(); else - poly = Variant(node->get_occluder_polygon()->get_polygon()); - - Transform2D xform = canvas_item_editor->get_canvas_transform() * node->get_global_transform(); - Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); - - for (int i = 0; i < poly.size(); i++) { - - Vector2 p, p2; - p = i == edited_point ? edited_point_pos : poly[i]; - if ((wip_active && i == poly.size() - 1) || (((i + 1) % poly.size()) == edited_point)) - p2 = edited_point_pos; - else - p2 = poly[(i + 1) % poly.size()]; + return 0; +} - Vector2 point = xform.xform(p); - Vector2 next_point = xform.xform(p2); +Variant LightOccluder2DEditor::_get_polygon(int p_idx) const { - Color col = Color(1, 0.3, 0.1, 0.8); + Ref<OccluderPolygon2D> occluder = node->get_occluder_polygon(); + if (occluder.is_valid()) + return occluder->get_polygon(); + else + return Variant(Vector<Vector2>()); +} - if (i == poly.size() - 1 && (!node->get_occluder_polygon()->is_closed() || wip_active)) { +void LightOccluder2DEditor::_set_polygon(int p_idx, const Variant &p_polygon) const { - } else { - p_overlay->draw_line(point, next_point, col, 2); - } - p_overlay->draw_texture(handle, point - handle->get_size() * 0.5); - } + Ref<OccluderPolygon2D> occluder = _ensure_occluder(); + occluder->set_polygon(p_polygon); } -void LightOccluder2DEditor::edit(Node *p_collision_polygon) { +void LightOccluder2DEditor::_action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon) { - if (!canvas_item_editor) { - canvas_item_editor = CanvasItemEditor::get_singleton(); - } + Ref<OccluderPolygon2D> occluder = _ensure_occluder(); + undo_redo->add_do_method(occluder.ptr(), "set_polygon", p_polygon); + undo_redo->add_undo_method(occluder.ptr(), "set_polygon", p_previous); +} - if (p_collision_polygon) { +bool LightOccluder2DEditor::_has_resource() const { - node = Object::cast_to<LightOccluder2D>(p_collision_polygon); - wip.clear(); - wip_active = false; - edited_point = -1; - canvas_item_editor->update_viewport(); - } else { - node = NULL; - } + return node && node->get_occluder_polygon().is_valid(); } -void LightOccluder2DEditor::_create_poly() { +void LightOccluder2DEditor::_create_resource() { if (!node) return; + undo_redo->create_action(TTR("Create Occluder Polygon")); undo_redo->add_do_method(node, "set_occluder_polygon", Ref<OccluderPolygon2D>(memnew(OccluderPolygon2D))); undo_redo->add_undo_method(node, "set_occluder_polygon", Variant(REF())); undo_redo->commit_action(); -} - -void LightOccluder2DEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_menu_option"), &LightOccluder2DEditor::_menu_option); - ClassDB::bind_method(D_METHOD("_node_removed"), &LightOccluder2DEditor::_node_removed); - ClassDB::bind_method(D_METHOD("_create_poly"), &LightOccluder2DEditor::_create_poly); + _menu_option(MODE_CREATE); } -LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) { +LightOccluder2DEditor::LightOccluder2DEditor(EditorNode *p_editor) : + AbstractPolygon2DEditor(p_editor) { node = NULL; - canvas_item_editor = NULL; - editor = p_editor; - undo_redo = editor->get_undo_redo(); - - add_child(memnew(VSeparator)); - button_create = memnew(ToolButton); - add_child(button_create); - button_create->connect("pressed", this, "_menu_option", varray(MODE_CREATE)); - button_create->set_toggle_mode(true); - button_create->set_tooltip(TTR("Create a new polygon from scratch.")); - - button_edit = memnew(ToolButton); - add_child(button_edit); - button_edit->connect("pressed", this, "_menu_option", varray(MODE_EDIT)); - button_edit->set_toggle_mode(true); - button_edit->set_tooltip(TTR("Edit existing polygon:") + "\n" + TTR("LMB: Move Point.") + "\n" + TTR("Ctrl+LMB: Split Segment.") + "\n" + TTR("RMB: Erase Point.")); - - create_poly = memnew(ConfirmationDialog); - add_child(create_poly); - create_poly->get_ok()->set_text(TTR("Create")); - - mode = MODE_EDIT; - wip_active = false; -} - -void LightOccluder2DEditorPlugin::edit(Object *p_object) { - - light_occluder_editor->edit(Object::cast_to<Node>(p_object)); -} - -bool LightOccluder2DEditorPlugin::handles(Object *p_object) const { - - return p_object->is_class("LightOccluder2D"); -} - -void LightOccluder2DEditorPlugin::make_visible(bool p_visible) { - - if (p_visible) { - light_occluder_editor->show(); - } else { - - light_occluder_editor->hide(); - light_occluder_editor->edit(NULL); - } -} - -LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) { - - editor = p_node; - light_occluder_editor = memnew(LightOccluder2DEditor(p_node)); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(light_occluder_editor); - - light_occluder_editor->hide(); } -LightOccluder2DEditorPlugin::~LightOccluder2DEditorPlugin() { +LightOccluder2DEditorPlugin::LightOccluder2DEditorPlugin(EditorNode *p_node) : + AbstractPolygon2DEditorPlugin(p_node, memnew(LightOccluder2DEditor(p_node)), "LightOccluder2D") { } diff --git a/editor/plugins/light_occluder_2d_editor_plugin.h b/editor/plugins/light_occluder_2d_editor_plugin.h index a1962892ee..6117d50e89 100644 --- a/editor/plugins/light_occluder_2d_editor_plugin.h +++ b/editor/plugins/light_occluder_2d_editor_plugin.h @@ -31,83 +31,44 @@ #ifndef LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H #define LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H -#include "editor/editor_node.h" -#include "editor/editor_plugin.h" +#include "editor/plugins/abstract_polygon_2d_editor.h" #include "scene/2d/light_occluder_2d.h" -#include "scene/gui/tool_button.h" /** @author Juan Linietsky <reduzio@gmail.com> */ -class CanvasItemEditor; +class LightOccluder2DEditor : public AbstractPolygon2DEditor { -class LightOccluder2DEditor : public HBoxContainer { + GDCLASS(LightOccluder2DEditor, AbstractPolygon2DEditor); - GDCLASS(LightOccluder2DEditor, HBoxContainer); - - UndoRedo *undo_redo; - enum Mode { - - MODE_CREATE, - MODE_EDIT, - - }; - - Mode mode; - - ToolButton *button_create; - ToolButton *button_edit; - - CanvasItemEditor *canvas_item_editor; - EditorNode *editor; - Panel *panel; LightOccluder2D *node; - MenuButton *options; - int edited_point; - Vector2 edited_point_pos; - Vector<Vector2> pre_move_edit; - Vector<Vector2> wip; - bool wip_active; + Ref<OccluderPolygon2D> _ensure_occluder() const; - ConfirmationDialog *create_poly; +protected: + virtual Node2D *_get_node() const; + virtual void _set_node(Node *p_polygon); - void _wip_close(bool p_closed); - void _menu_option(int p_option); - void _create_poly(); + virtual bool _is_line() const; + virtual int _get_polygon_count() const; + virtual Variant _get_polygon(int p_idx) const; + virtual void _set_polygon(int p_idx, const Variant &p_polygon) const; -protected: - void _notification(int p_what); - void _node_removed(Node *p_node); - static void _bind_methods(); + virtual void _action_set_polygon(int p_idx, const Variant &p_previous, const Variant &p_polygon); + + virtual bool _has_resource() const; + virtual void _create_resource(); public: - Vector2 snap_point(const Vector2 &p_point) const; - void forward_canvas_draw_over_viewport(Control *p_overlay); - bool forward_gui_input(const Ref<InputEvent> &p_event); - void edit(Node *p_collision_polygon); LightOccluder2DEditor(EditorNode *p_editor); }; -class LightOccluder2DEditorPlugin : public EditorPlugin { +class LightOccluder2DEditorPlugin : public AbstractPolygon2DEditorPlugin { - GDCLASS(LightOccluder2DEditorPlugin, EditorPlugin); - - LightOccluder2DEditor *light_occluder_editor; - EditorNode *editor; + GDCLASS(LightOccluder2DEditorPlugin, AbstractPolygon2DEditorPlugin); public: - virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return light_occluder_editor->forward_gui_input(p_event); } - virtual void forward_canvas_draw_over_viewport(Control *p_overlay) { return light_occluder_editor->forward_canvas_draw_over_viewport(p_overlay); } - - virtual String get_name() const { return "LightOccluder2D"; } - bool has_main_screen() const { return false; } - virtual void edit(Object *p_object); - virtual bool handles(Object *p_object) const; - virtual void make_visible(bool p_visible); - LightOccluder2DEditorPlugin(EditorNode *p_node); - ~LightOccluder2DEditorPlugin(); }; #endif // LIGHT_OCCLUDER_2D_EDITOR_PLUGIN_H diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index f937744d45..97448f3f88 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -56,6 +56,12 @@ void Polygon2DEditor::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + + uv_edit_draw->add_style_override("panel", get_stylebox("bg", "Tree")); + bone_scroll->add_style_override("bg", get_stylebox("bg", "Tree")); + } break; case NOTIFICATION_READY: { button_uv->set_icon(get_icon("Uv", "EditorIcons")); @@ -73,66 +79,68 @@ void Polygon2DEditor::_notification(int p_what) { b_snap_grid->set_icon(get_icon("Grid", "EditorIcons")); b_snap_enable->set_icon(get_icon("SnapGrid", "EditorIcons")); uv_icon_zoom->set_texture(get_icon("Zoom", "EditorIcons")); - } break; - case NOTIFICATION_PHYSICS_PROCESS: { + case NOTIFICATION_VISIBILITY_CHANGED: { + if (!is_visible()) { + uv_edit->hide(); + } } break; } } void Polygon2DEditor::_sync_bones() { + Skeleton2D *skeleton; if (!node->has_node(node->get_skeleton())) { error->set_text(TTR("The skeleton property of the Polygon2D does not point to a Skeleton2D node")); error->popup_centered_minsize(); - return; + } else { + Node *sn = node->get_node(node->get_skeleton()); + skeleton = Object::cast_to<Skeleton2D>(sn); } - Node *sn = node->get_node(node->get_skeleton()); - Skeleton2D *skeleton = Object::cast_to<Skeleton2D>(sn); + Array prev_bones = node->call("_get_bones"); + node->clear_bones(); if (!skeleton) { error->set_text(TTR("The skeleton property of the Polygon2D does not point to a Skeleton2D node")); error->popup_centered_minsize(); - return; - } - - Array prev_bones = node->call("_get_bones"); - node->clear_bones(); - - for (int i = 0; i < skeleton->get_bone_count(); i++) { - NodePath path = skeleton->get_path_to(skeleton->get_bone(i)); - PoolVector<float> weights; - int wc = node->get_polygon().size(); - - for (int j = 0; j < prev_bones.size(); j += 2) { - NodePath pvp = prev_bones[j]; - PoolVector<float> pv = prev_bones[j + 1]; - if (pvp == path && pv.size() == wc) { - weights = pv; + } else { + for (int i = 0; i < skeleton->get_bone_count(); i++) { + NodePath path = skeleton->get_path_to(skeleton->get_bone(i)); + PoolVector<float> weights; + int wc = node->get_polygon().size(); + + for (int j = 0; j < prev_bones.size(); j += 2) { + NodePath pvp = prev_bones[j]; + PoolVector<float> pv = prev_bones[j + 1]; + if (pvp == path && pv.size() == wc) { + weights = pv; + } } - } - if (weights.size() == 0) { //create them - weights.resize(node->get_polygon().size()); - PoolVector<float>::Write w = weights.write(); - for (int j = 0; j < wc; j++) { - w[j] = 0.0; + if (weights.size() == 0) { //create them + weights.resize(node->get_polygon().size()); + PoolVector<float>::Write w = weights.write(); + for (int j = 0; j < wc; j++) { + w[j] = 0.0; + } } - } - node->add_bone(path, weights); + node->add_bone(path, weights); + } } + Array new_bones = node->call("_get_bones"); - undo_redo->create_action(TTR("Sync bones")); + undo_redo->create_action(TTR("Sync Bones")); undo_redo->add_do_method(node, "_set_bones", new_bones); undo_redo->add_undo_method(node, "_set_bones", prev_bones); - undo_redo->add_do_method(uv_edit_draw, "update"); - undo_redo->add_undo_method(uv_edit_draw, "update"); 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, "update"); + undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); } @@ -162,9 +170,10 @@ void Polygon2DEditor::_update_bone_list() { cb->set_text(name); cb->set_button_group(bg); cb->set_meta("bone_path", np); + cb->set_focus_mode(FOCUS_NONE); bone_scroll_vb->add_child(cb); - if (np == selected) + if (np == selected || bone_scroll_vb->get_child_count() < 2) cb->set_pressed(true); cb->connect("pressed", this, "_bone_paint_selected", varray(i)); @@ -180,6 +189,7 @@ void Polygon2DEditor::_bone_paint_selected(int p_index) { void Polygon2DEditor::_uv_edit_mode_select(int p_mode) { if (p_mode == 0) { //uv + uv_button[UV_MODE_CREATE]->hide(); for (int i = UV_MODE_MOVE; i <= UV_MODE_SCALE; i++) { uv_button[i]->show(); @@ -194,8 +204,8 @@ void Polygon2DEditor::_uv_edit_mode_select(int p_mode) { 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(); } @@ -209,8 +219,8 @@ void Polygon2DEditor::_uv_edit_mode_select(int p_mode) { 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(); } @@ -224,8 +234,8 @@ void Polygon2DEditor::_uv_edit_mode_select(int p_mode) { 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_SPLIT; i++) { uv_button[i]->hide(); } @@ -241,9 +251,17 @@ void Polygon2DEditor::_uv_edit_mode_select(int p_mode) { bone_paint_pos = Vector2(-100000, -100000); //send brush away when switching } + uv_edit->set_size(uv_edit->get_size()); // Necessary readjustment of the popup window. uv_edit_draw->update(); } +void Polygon2DEditor::_uv_edit_popup_hide() { + + EditorSettings::get_singleton()->set("interface/dialogs/uv_editor_bounds", uv_edit->get_rect()); + + _cancel_editing(); +} + void Polygon2DEditor::_menu_option(int p_option) { switch (p_option) { @@ -252,7 +270,7 @@ void Polygon2DEditor::_menu_option(int p_option) { if (node->get_texture().is_null()) { - error->set_text("No texture in this polygon.\nSet a texture to be able to edit UV."); + error->set_text(TTR("No texture in this polygon.\nSet a texture to be able to edit UV.")); error->popup_centered_minsize(); return; } @@ -268,7 +286,10 @@ void Polygon2DEditor::_menu_option(int p_option) { undo_redo->commit_action(); } - uv_edit->popup_centered_ratio(0.85); + if (EditorSettings::get_singleton()->has_setting("interface/dialogs/uv_editor_bounds")) + uv_edit->popup(EditorSettings::get_singleton()->get("interface/dialogs/uv_editor_bounds")); + else + uv_edit->popup_centered_ratio(0.85); } break; case UVEDIT_POLYGON_TO_UV: { @@ -282,7 +303,6 @@ void Polygon2DEditor::_menu_option(int p_option) { undo_redo->add_do_method(uv_edit_draw, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); - } break; case UVEDIT_UV_TO_POLYGON: { @@ -291,13 +311,12 @@ void Polygon2DEditor::_menu_option(int p_option) { if (uvs.size() == 0) break; - undo_redo->create_action(TTR("Create UV Map")); + 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, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); - } break; case UVEDIT_UV_CLEAR: { @@ -310,43 +329,81 @@ void Polygon2DEditor::_menu_option(int p_option) { undo_redo->add_do_method(uv_edit_draw, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); - } break; case UVEDIT_GRID_SETTINGS: { + grid_settings->popup_centered_minsize(); } 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->call("_set_bones", uv_create_bones_prev); + node->set_splits(splits_prev); + } 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 (split_create) { + split_create = false; + } +} + +void Polygon2DEditor::_commit_action() { + + // Makes that undo/redoing actions made outside of the UV editor still affects its polygon. + undo_redo->add_do_method(uv_edit_draw, "update"); + undo_redo->add_undo_method(uv_edit_draw, "update"); + undo_redo->add_do_method(CanvasItemEditor::get_singleton(), "update_viewport"); + undo_redo->add_undo_method(CanvasItemEditor::get_singleton(), "update_viewport"); + undo_redo->commit_action(); +} + void Polygon2DEditor::_set_use_snap(bool p_use) { use_snap = p_use; + EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_enabled", 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->update(); } void Polygon2DEditor::_set_snap_off_x(float p_val) { snap_offset.x = p_val; + EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_offset", snap_offset); uv_edit_draw->update(); } void Polygon2DEditor::_set_snap_off_y(float p_val) { snap_offset.y = p_val; + EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_offset", snap_offset); uv_edit_draw->update(); } void Polygon2DEditor::_set_snap_step_x(float p_val) { snap_step.x = p_val; + EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_step", snap_step); uv_edit_draw->update(); } void Polygon2DEditor::_set_snap_step_y(float p_val) { snap_step.y = p_val; + EditorSettings::get_singleton()->set_project_metadata("polygon_2d_uv_editor", "snap_step", snap_step); uv_edit_draw->update(); } @@ -364,6 +421,9 @@ void Polygon2DEditor::_uv_mode(int p_mode) { void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { + if (!_get_node()) + return; + Transform2D mtx; mtx.elements[2] = -uv_draw_ofs; mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom)); @@ -376,7 +436,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { if (mb->is_pressed()) { - uv_drag_from = Vector2(mb->get_position().x, mb->get_position().y); + uv_drag_from = snap_point(Vector2(mb->get_position().x, mb->get_position().y)); uv_drag = true; points_prev = node->get_uv(); @@ -390,8 +450,9 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { if (uv_move_current == UV_MODE_CREATE) { if (!uv_create) { + points_prev.resize(0); - Vector2 tuv = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y)); + Vector2 tuv = mtx.affine_inverse().xform(snap_point(Vector2(mb->get_position().x, mb->get_position().y))); points_prev.push_back(tuv); uv_create_to = tuv; point_drag_index = 0; @@ -405,23 +466,27 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { node->set_polygon(points_prev); node->set_uv(points_prev); + uv_edit_draw->update(); } else { - Vector2 tuv = mtx.affine_inverse().xform(Vector2(mb->get_position().x, mb->get_position().y)); - if (points_prev.size() > 3 && tuv.distance_to(points_prev[0]) < 8) { + Vector2 tuv = mtx.affine_inverse().xform(snap_point(Vector2(mb->get_position().x, mb->get_position().y))); + + if (points_prev.size() > 2 && tuv.distance_to(points_prev[0]) < 8) { 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", points_prev); + undo_redo->add_undo_method(node, "set_uv", uv_create_uv_prev); undo_redo->add_do_method(node, "set_polygon", node->get_polygon()); - undo_redo->add_undo_method(node, "set_polygon", points_prev); + undo_redo->add_undo_method(node, "set_polygon", uv_create_poly_prev); undo_redo->add_do_method(node, "clear_bones"); - undo_redo->add_undo_method(node, "_set_bones", node->call("_get_bones")); + undo_redo->add_undo_method(node, "_set_bones", uv_create_bones_prev); undo_redo->add_do_method(uv_edit_draw, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); uv_drag = false; uv_create = false; + _uv_mode(UV_MODE_EDIT_POINT); + _menu_option(MODE_EDIT); } else { points_prev.push_back(tuv); point_drag_index = points_prev.size() - 1; @@ -430,6 +495,8 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { node->set_polygon(points_prev); node->set_uv(points_prev); } + + CanvasItemEditor::get_singleton()->update_viewport(); } if (uv_move_current == UV_MODE_EDIT_POINT) { @@ -540,7 +607,6 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { splits_prev.push_back(split_to_index); undo_redo->create_action(TTR("Add Split")); - undo_redo->add_do_method(node, "set_splits", splits_prev); undo_redo->add_undo_method(node, "set_splits", node->get_splits()); undo_redo->add_do_method(uv_edit_draw, "update"); @@ -575,13 +641,11 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { splits_prev.remove(i); undo_redo->create_action(TTR("Remove Split")); - undo_redo->add_do_method(node, "set_splits", splits_prev); undo_redo->add_undo_method(node, "set_splits", node->get_splits()); undo_redo->add_do_method(uv_edit_draw, "update"); undo_redo->add_undo_method(uv_edit_draw, "update"); undo_redo->commit_action(); - break; } } @@ -608,12 +672,12 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } else if (uv_drag && !uv_create) { - undo_redo->create_action(TTR("Transform UV Map")); - if (uv_edit_mode[0]->is_pressed()) { //edit 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); } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon + 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); } @@ -624,7 +688,7 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { uv_drag = false; } else if (bone_painting) { - undo_redo->create_action(TTR("Paint bone weights")); + 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, "update"); @@ -635,30 +699,12 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } else if (mb->get_button_index() == BUTTON_RIGHT && mb->is_pressed()) { - if (uv_create) { + _cancel_editing(); - uv_drag = false; - uv_create = false; - node->set_uv(uv_create_uv_prev); - node->set_polygon(uv_create_poly_prev); - node->call("_set_bones", uv_create_bones_prev); - node->set_splits(splits_prev); - uv_edit_draw->update(); - } else if (uv_drag) { - - uv_drag = false; - if (uv_edit_mode[0]->is_pressed()) { //edit uv - node->set_uv(points_prev); - } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon - node->set_polygon(points_prev); - } - uv_edit_draw->update(); - } else if (split_create) { - split_create = false; - uv_edit_draw->update(); - } else if (bone_painting) { + if (bone_painting) node->set_bone_weights(bone_painting_bone, prev_weights); - } + + uv_edit_draw->update(); } else if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) { @@ -682,13 +728,15 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } else if (uv_drag) { Vector2 uv_drag_to = mm->get_position(); + uv_drag_to = snap_point(uv_drag_to); // FIXME: Only works correctly with 'UV_MODE_EDIT_POINT', it's imprecise with the rest. Vector2 drag = mtx.affine_inverse().xform(uv_drag_to) - mtx.affine_inverse().xform(uv_drag_from); switch (uv_move_current) { case UV_MODE_CREATE: { + if (uv_create) { - uv_create_to = mtx.affine_inverse().xform(Vector2(mm->get_position().x, mm->get_position().y)); + uv_create_to = mtx.affine_inverse().xform(snap_point(Vector2(mm->get_position().x, mm->get_position().y))); } } break; case UV_MODE_EDIT_POINT: { @@ -713,7 +761,6 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon node->set_polygon(uv_new); } - } break; case UV_MODE_ROTATE: { @@ -737,7 +784,6 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { } else if (uv_edit_mode[1]->is_pressed()) { //edit polygon node->set_polygon(uv_new); } - } break; case UV_MODE_SCALE: { @@ -767,11 +813,15 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { node->set_polygon(uv_new); } } break; + case UV_MODE_PAINT_WEIGHT: + case UV_MODE_CLEAR_WEIGHT: { + + bone_paint_pos = Vector2(mm->get_position().x, mm->get_position().y); + } break; default: {} } if (bone_painting) { - bone_paint_pos = Vector2(mm->get_position().x, mm->get_position().y); PoolVector<float> painted_weights = node->get_bone_weights(bone_painting_bone); { @@ -796,7 +846,9 @@ void Polygon2DEditor::_uv_input(const Ref<InputEvent> &p_input) { node->set_bone_weights(bone_painting_bone, painted_weights); } + uv_edit_draw->update(); + CanvasItemEditor::get_singleton()->update_viewport(); } else if (split_create) { uv_create_to = mtx.affine_inverse().xform(Vector2(mm->get_position().x, mm->get_position().y)); uv_edit_draw->update(); @@ -833,6 +885,9 @@ void Polygon2DEditor::_uv_scroll_changed(float) { void Polygon2DEditor::_uv_draw() { + if (!uv_edit->is_visible() || !_get_node()) + return; + Ref<Texture> base_tex = node->get_texture(); if (base_tex.is_null()) return; @@ -848,6 +903,7 @@ void Polygon2DEditor::_uv_draw() { VS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), Transform2D()); if (snap_show_grid) { + Color grid_color = Color(1.0, 1.0, 1.0, 0.15); Size2 s = uv_edit_draw->get_size(); int last_cell = 0; @@ -857,7 +913,7 @@ void Polygon2DEditor::_uv_draw() { if (i == 0) last_cell = cell; if (last_cell != cell) - uv_edit_draw->draw_line(Point2(i, 0), Point2(i, s.height), Color(0.3, 0.7, 1, 0.3)); + uv_edit_draw->draw_line(Point2(i, 0), Point2(i, s.height), grid_color); last_cell = cell; } } @@ -868,7 +924,7 @@ void Polygon2DEditor::_uv_draw() { if (i == 0) last_cell = cell; if (last_cell != cell) - uv_edit_draw->draw_line(Point2(0, i), Point2(s.width, i), Color(0.3, 0.7, 1, 0.3)); + uv_edit_draw->draw_line(Point2(0, i), Point2(s.width, i), grid_color); last_cell = cell; } } @@ -901,19 +957,26 @@ void Polygon2DEditor::_uv_draw() { Ref<Texture> handle = get_icon("EditorHandle", "EditorIcons"); + Color poly_line_color = Color(0.9, 0.5, 0.5); + Color prev_color = Color(0.5, 0.5, 0.5); Rect2 rect(Point2(), mtx.basis_xform(base_tex->get_size())); rect.expand_to(mtx.basis_xform(uv_edit_draw->get_size())); for (int i = 0; i < uvs.size(); i++) { int next = (i + 1) % uvs.size(); + + if (uv_drag && uv_move_current == UV_MODE_EDIT_POINT && EDITOR_DEF("editors/poly_editor/show_previous_outline", true)) { + uv_edit_draw->draw_line(mtx.xform(points_prev[i]), mtx.xform(points_prev[next]), prev_color, 2 * EDSCALE); + } + Vector2 next_point = uvs[next]; if (uv_create && i == uvs.size() - 1) { next_point = uv_create_to; } - uv_edit_draw->draw_line(mtx.xform(uvs[i]), mtx.xform(next_point), Color(0.9, 0.5, 0.5), 2); - if (weight_r.ptr()) { + uv_edit_draw->draw_line(mtx.xform(uvs[i]), mtx.xform(next_point), poly_line_color, 2 * EDSCALE); + if (weight_r.ptr()) { 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)); @@ -926,7 +989,7 @@ void Polygon2DEditor::_uv_draw() { if (split_create) { Vector2 from = uvs[point_drag_index]; Vector2 to = uv_create_to; - uv_edit_draw->draw_line(mtx.xform(from), mtx.xform(to), Color(0.9, 0.5, 0.5), 2); + uv_edit_draw->draw_line(mtx.xform(from), mtx.xform(to), poly_line_color, 2); } PoolVector<int> splits = node->get_splits(); @@ -936,7 +999,7 @@ void Polygon2DEditor::_uv_draw() { int idx_to = splits[i + 1]; if (idx_from < 0 || idx_to >= uvs.size()) continue; - uv_edit_draw->draw_line(mtx.xform(uvs[idx_from]), mtx.xform(uvs[idx_to]), Color(0.9, 0.5, 0.5), 2); + uv_edit_draw->draw_line(mtx.xform(uvs[idx_from]), mtx.xform(uvs[idx_to]), poly_line_color, 2); } if (uv_mode == UV_MODE_PAINT_WEIGHT || uv_mode == UV_MODE_CLEAR_WEIGHT) { @@ -963,22 +1026,32 @@ void Polygon2DEditor::_uv_draw() { bool current = bone_path == skeleton->get_path_to(bone); + bool found_child = false; + for (int j = 0; j < bone->get_child_count(); j++) { - Node2D *n = Object::cast_to<Node2D>(bone->get_child(j)); + Bone2D *n = Object::cast_to<Bone2D>(bone->get_child(j)); if (!n) continue; - bool edit_bone = n->has_meta("_edit_bone_") && n->get_meta("_edit_bone_"); - if (edit_bone) { + found_child = true; - Transform2D bone_xform = node->get_global_transform().affine_inverse() * (skeleton->get_global_transform() * bone->get_skeleton_rest()); - Transform2D endpoint_xform = bone_xform * n->get_transform(); + Transform2D bone_xform = node->get_global_transform().affine_inverse() * (skeleton->get_global_transform() * bone->get_skeleton_rest()); + 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), current ? 5 : 4); - uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, current ? 3 : 2); - } + 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), current ? 5 : 4); + uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, current ? 3 : 2); + } + + if (!found_child) { + //draw normally + Transform2D bone_xform = node->get_global_transform().affine_inverse() * (skeleton->get_global_transform() * bone->get_skeleton_rest()); + Transform2D endpoint_xform = bone_xform * Transform2D(0, Vector2(bone->get_default_length(), 0)); + + 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), current ? 5 : 4); + uv_edit_draw->draw_line(mtx.xform(bone_xform.get_origin()), mtx.xform(endpoint_xform.get_origin()), color, current ? 3 : 2); } } } @@ -992,15 +1065,23 @@ void Polygon2DEditor::_uv_draw() { updating_uv_scroll = true; uv_hscroll->set_min(rect.position.x); uv_hscroll->set_max(rect.position.x + rect.size.x); - uv_hscroll->set_page(uv_edit_draw->get_size().x); - uv_hscroll->set_value(uv_draw_ofs.x); - uv_hscroll->set_step(0.001); + if (ABS(rect.position.x - (rect.position.x + rect.size.x)) <= uv_edit_draw->get_size().x) { + uv_hscroll->hide(); + } else { + uv_hscroll->show(); + uv_hscroll->set_page(uv_edit_draw->get_size().x); + uv_hscroll->set_value(uv_draw_ofs.x); + } uv_vscroll->set_min(rect.position.y); uv_vscroll->set_max(rect.position.y + rect.size.y); - uv_vscroll->set_page(uv_edit_draw->get_size().y); - uv_vscroll->set_value(uv_draw_ofs.y); - uv_vscroll->set_step(0.001); + if (ABS(rect.position.y - (rect.position.y + rect.size.y)) <= uv_edit_draw->get_size().y) { + uv_vscroll->hide(); + } else { + uv_vscroll->show(); + uv_vscroll->set_page(uv_edit_draw->get_size().y); + uv_vscroll->set_value(uv_draw_ofs.y); + } updating_uv_scroll = false; } @@ -1017,9 +1098,9 @@ void Polygon2DEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_set_snap_step_x"), &Polygon2DEditor::_set_snap_step_x); ClassDB::bind_method(D_METHOD("_set_snap_step_y"), &Polygon2DEditor::_set_snap_step_y); ClassDB::bind_method(D_METHOD("_uv_edit_mode_select"), &Polygon2DEditor::_uv_edit_mode_select); + ClassDB::bind_method(D_METHOD("_uv_edit_popup_hide"), &Polygon2DEditor::_uv_edit_popup_hide); ClassDB::bind_method(D_METHOD("_sync_bones"), &Polygon2DEditor::_sync_bones); ClassDB::bind_method(D_METHOD("_update_bone_list"), &Polygon2DEditor::_update_bone_list); - ClassDB::bind_method(D_METHOD("_bone_paint_selected"), &Polygon2DEditor::_bone_paint_selected); } @@ -1036,23 +1117,25 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : AbstractPolygon2DEditor(p_editor) { node = NULL; - snap_step = Vector2(10, 10); - use_snap = false; - snap_show_grid = false; + snap_offset = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "snap_offset", Vector2()); + snap_step = EditorSettings::get_singleton()->get_project_metadata("polygon_2d_uv_editor", "snap_step", Vector2(10, 10)); + 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(ToolButton); add_child(button_uv); + button_uv->set_tooltip(TTR("Open Polygon 2D UV editor.")); button_uv->connect("pressed", this, "_menu_option", varray(MODE_EDIT_UV)); uv_mode = UV_MODE_EDIT_POINT; uv_edit = memnew(AcceptDialog); add_child(uv_edit); uv_edit->set_title(TTR("Polygon 2D UV Editor")); - uv_edit->set_self_modulate(Color(1, 1, 1, 0.9)); + uv_edit->set_resizable(true); + uv_edit->connect("popup_hide", this, "_uv_edit_popup_hide"); VBoxContainer *uv_main_vb = memnew(VBoxContainer); uv_edit->add_child(uv_main_vb); - //uv_edit->set_child_rect(uv_main_vb); HBoxContainer *uv_mode_hb = memnew(HBoxContainer); uv_edit_group.instance(); @@ -1099,14 +1182,14 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : } uv_button[0]->set_tooltip(TTR("Create Polygon")); - uv_button[1]->set_tooltip(TTR("Move Point") + "\n" + TTR("Ctrl: Rotate") + "\n" + TTR("Shift: Move All") + "\n" + TTR("Shift+Ctrl: Scale")); + uv_button[1]->set_tooltip(TTR("Move Points") + "\n" + TTR("Ctrl: Rotate") + "\n" + TTR("Shift: Move All") + "\n" + TTR("Shift+Ctrl: Scale")); uv_button[2]->set_tooltip(TTR("Move Polygon")); uv_button[3]->set_tooltip(TTR("Rotate Polygon")); uv_button[4]->set_tooltip(TTR("Scale Polygon")); - uv_button[5]->set_tooltip(TTR("Connect two points to make a split")); - uv_button[6]->set_tooltip(TTR("Select a split to erase it")); - uv_button[7]->set_tooltip(TTR("Paint weights with specified intensity")); - uv_button[8]->set_tooltip(TTR("UnPaint weights with specified intensity")); + uv_button[5]->set_tooltip(TTR("Connect two points to make a split.")); + uv_button[6]->set_tooltip(TTR("Select a split to erase it.")); + uv_button[7]->set_tooltip(TTR("Paint weights with specified intensity.")); + uv_button[8]->set_tooltip(TTR("Unpaint weights with specified intensity.")); uv_button[0]->hide(); uv_button[5]->hide(); @@ -1124,7 +1207,7 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : bone_paint_strength->set_step(0.01); bone_paint_strength->set_value(0.5); - bone_paint_radius_label = memnew(Label(" " + TTR("Radius:") + " ")); + bone_paint_radius_label = memnew(Label(TTR("Radius:"))); uv_mode_hb->add_child(bone_paint_radius_label); bone_paint_radius = memnew(SpinBox); uv_mode_hb->add_child(bone_paint_radius); @@ -1137,12 +1220,13 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : bone_paint_radius->set_step(1); bone_paint_radius->set_value(32); - HBoxContainer *uv_main_hb = memnew(HBoxContainer); - uv_main_vb->add_child(uv_main_hb); - uv_edit_draw = memnew(Control); - uv_main_hb->add_child(uv_edit_draw); - uv_main_hb->set_v_size_flags(SIZE_EXPAND_FILL); + HSplitContainer *uv_main_hsc = memnew(HSplitContainer); + uv_main_vb->add_child(uv_main_hsc); + uv_main_hsc->set_v_size_flags(SIZE_EXPAND_FILL); + uv_edit_draw = memnew(Panel); + uv_main_hsc->add_child(uv_edit_draw); uv_edit_draw->set_h_size_flags(SIZE_EXPAND_FILL); + uv_edit_draw->set_custom_minimum_size(Size2(200, 200) * EDSCALE); uv_menu = memnew(MenuButton); uv_mode_hb->add_child(uv_menu); uv_menu->set_text(TTR("Edit")); @@ -1218,6 +1302,7 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_mode_hb->add_child(memnew(VSeparator)); uv_icon_zoom = memnew(TextureRect); + uv_icon_zoom->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); uv_mode_hb->add_child(uv_icon_zoom); uv_zoom = memnew(HSlider); uv_zoom->set_min(0.01); @@ -1235,17 +1320,25 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : uv_zoom->connect("value_changed", this, "_uv_scroll_changed"); uv_vscroll = memnew(VScrollBar); - uv_main_hb->add_child(uv_vscroll); + uv_vscroll->set_step(0.001); + uv_edit_draw->add_child(uv_vscroll); + uv_vscroll->set_anchors_and_margins_preset(PRESET_RIGHT_WIDE); uv_vscroll->connect("value_changed", this, "_uv_scroll_changed"); uv_hscroll = memnew(HScrollBar); - uv_main_vb->add_child(uv_hscroll); + uv_hscroll->set_step(0.001); + uv_edit_draw->add_child(uv_hscroll); + uv_hscroll->set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE); + uv_hscroll->set_margin(MARGIN_RIGHT, -uv_vscroll->get_size().x * EDSCALE); uv_hscroll->connect("value_changed", this, "_uv_scroll_changed"); 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); - uv_main_hb->add_child(bone_scroll_main_vb); + sync_bones->set_h_size_flags(0); + sync_bones->connect("pressed", this, "_sync_bones"); + uv_main_hsc->add_child(bone_scroll_main_vb); bone_scroll = memnew(ScrollContainer); bone_scroll->set_v_scroll(true); bone_scroll->set_h_scroll(false); @@ -1253,7 +1346,6 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) : bone_scroll->set_v_size_flags(SIZE_EXPAND_FILL); bone_scroll_vb = memnew(VBoxContainer); bone_scroll->add_child(bone_scroll_vb); - sync_bones->connect("pressed", this, "_sync_bones"); uv_edit_draw->connect("draw", this, "_uv_draw"); uv_edit_draw->connect("gui_input", this, "_uv_input"); diff --git a/editor/plugins/polygon_2d_editor_plugin.h b/editor/plugins/polygon_2d_editor_plugin.h index f9b42a21c2..935f1cfff0 100644 --- a/editor/plugins/polygon_2d_editor_plugin.h +++ b/editor/plugins/polygon_2d_editor_plugin.h @@ -41,13 +41,11 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { GDCLASS(Polygon2DEditor, AbstractPolygon2DEditor); enum Mode { - MODE_EDIT_UV = MODE_CONT, UVEDIT_POLYGON_TO_UV, UVEDIT_UV_TO_POLYGON, UVEDIT_UV_CLEAR, UVEDIT_GRID_SETTINGS - }; enum UVMode { @@ -73,7 +71,7 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { ToolButton *uv_button[UV_MODE_MAX]; ToolButton *b_snap_enable; ToolButton *b_snap_grid; - Control *uv_edit_draw; + Panel *uv_edit_draw; HSlider *uv_zoom; SpinBox *uv_zoom_value; HScrollBar *uv_hscroll; @@ -125,6 +123,8 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { virtual void _menu_option(int p_option); + void _cancel_editing(); + void _uv_scroll_changed(float); void _uv_input(const Ref<InputEvent> &p_input); void _uv_draw(); @@ -138,6 +138,7 @@ class Polygon2DEditor : public AbstractPolygon2DEditor { void _set_snap_step_y(float p_val); void _uv_edit_mode_select(int p_mode); + void _uv_edit_popup_hide(); void _bone_paint_selected(int p_index); protected: @@ -146,6 +147,9 @@ protected: virtual Vector2 _get_offset(int p_idx) const; + virtual bool _has_uv() const { return true; }; + virtual void _commit_action(); + void _notification(int p_what); static void _bind_methods(); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index e101c0d99e..44f1625d06 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -40,6 +40,7 @@ #include "editor/editor_settings.h" #include "editor/find_in_files.h" #include "editor/node_dock.h" +#include "editor/plugins/shader_editor_plugin.h" #include "editor/script_editor_debugger.h" #include "scene/main/viewport.h" #include "script_text_editor.h" @@ -50,8 +51,7 @@ void ScriptEditorBase::_bind_methods() { ADD_SIGNAL(MethodInfo("name_changed")); ADD_SIGNAL(MethodInfo("edited_script_changed")); - ADD_SIGNAL(MethodInfo("request_help_search", PropertyInfo(Variant::STRING, "topic"))); - ADD_SIGNAL(MethodInfo("request_help_index")); + ADD_SIGNAL(MethodInfo("request_help", PropertyInfo(Variant::STRING, "topic"))); ADD_SIGNAL(MethodInfo("request_open_script_at_line", PropertyInfo(Variant::OBJECT, "script"), PropertyInfo(Variant::INT, "line"))); ADD_SIGNAL(MethodInfo("request_save_history")); ADD_SIGNAL(MethodInfo("go_to_help", PropertyInfo(Variant::STRING, "what"))); @@ -897,12 +897,12 @@ void ScriptEditor::_file_dialog_action(String p_file) { } break; case THEME_SAVE_AS: { if (!EditorSettings::get_singleton()->save_text_editor_theme_as(p_file)) { - editor->show_warning(TTR("Error while saving theme"), TTR("Error saving")); + editor->show_warning(TTR("Error while saving theme."), TTR("Error Saving")); } } break; case THEME_IMPORT: { if (!EditorSettings::get_singleton()->import_text_editor_theme(p_file)) { - editor->show_warning(TTR("Error importing theme"), TTR("Error importing")); + editor->show_warning(TTR("Error importing theme."), TTR("Error Importing")); } } break; } @@ -975,10 +975,6 @@ void ScriptEditor::_menu_option(int p_option) { help_search_dialog->popup_dialog(); } break; - case SEARCH_CLASSES: { - - help_index->popup_dialog(); - } break; case SEARCH_WEBSITE: { OS::get_singleton()->shell_open("https://docs.godotengine.org/"); @@ -1094,7 +1090,7 @@ void ScriptEditor::_menu_option(int p_option) { Ref<Script> scr = current->get_edited_resource(); if (scr == NULL || scr.is_null()) { - EditorNode::get_singleton()->show_warning("Can't obtain the script for running"); + EditorNode::get_singleton()->show_warning("Can't obtain the script for running."); break; } @@ -1107,13 +1103,13 @@ void ScriptEditor::_menu_option(int p_option) { } if (!scr->is_tool()) { - EditorNode::get_singleton()->show_warning("Script is not in tool mode, will not be able to run"); + EditorNode::get_singleton()->show_warning("Script is not in tool mode, will not be able to run."); return; } if (!ClassDB::is_parent_class(scr->get_instance_base_type(), "EditorScript")) { - EditorNode::get_singleton()->show_warning("To run this script, it must inherit EditorScript and be set to tool mode"); + EditorNode::get_singleton()->show_warning("To run this script, it must inherit EditorScript and be set to tool mode."); return; } @@ -1206,12 +1202,6 @@ void ScriptEditor::_menu_option(int p_option) { if (help) { switch (p_option) { - - case SEARCH_CLASSES: { - - help_index->popup_dialog(); - help_index->call_deferred("select_class", help->get_class()); - } break; case HELP_SEARCH_FIND: { help->popup_search(); } break; @@ -1318,7 +1308,6 @@ void ScriptEditor::_notification(int p_what) { EditorSettings::get_singleton()->connect("settings_changed", this, "_editor_settings_changed"); help_search->set_icon(get_icon("HelpSearch", "EditorIcons")); site_search->set_icon(get_icon("Instance", "EditorIcons")); - class_search->set_icon(get_icon("ClassList", "EditorIcons")); script_forward->set_icon(get_icon("Forward", "EditorIcons")); script_back->set_icon(get_icon("Back", "EditorIcons")); @@ -1330,7 +1319,6 @@ void ScriptEditor::_notification(int p_what) { get_tree()->connect("tree_changed", this, "_tree_changed"); editor->get_inspector_dock()->connect("request_help", this, "_request_help"); editor->connect("request_help_search", this, "_help_search"); - editor->connect("request_help_index", this, "_help_index"); } break; case NOTIFICATION_EXIT_TREE: { @@ -1350,7 +1338,6 @@ void ScriptEditor::_notification(int p_what) { help_search->set_icon(get_icon("HelpSearch", "EditorIcons")); site_search->set_icon(get_icon("Instance", "EditorIcons")); - class_search->set_icon(get_icon("ClassList", "EditorIcons")); script_forward->set_icon(get_icon("Forward", "EditorIcons")); script_back->set_icon(get_icon("Back", "EditorIcons")); @@ -1829,6 +1816,10 @@ Ref<TextFile> ScriptEditor::_load_text_file(const String &p_path, Error *r_error text_file->set_file_path(local_path); text_file->set_path(local_path, true); + if (ResourceLoader::get_timestamp_on_load()) { + text_file->set_last_modified_time(FileAccess::get_modified_time(path)); + } + if (r_error) { *r_error = OK; } @@ -1858,6 +1849,10 @@ Error ScriptEditor::_save_text_file(Ref<TextFile> p_text_file, const String &p_p file->close(); memdelete(file); + if (ResourceSaver::get_timestamp_on_save()) { + p_text_file->set_last_modified_time(FileAccess::get_modified_time(p_path)); + } + _res_saved_callback(sqscr); return OK; } @@ -2006,7 +2001,7 @@ bool ScriptEditor::edit(const RES &p_resource, int p_line, int p_col, bool p_gra _save_layout(); se->connect("name_changed", this, "_update_script_names"); se->connect("edited_script_changed", this, "_script_changed"); - se->connect("request_help_search", this, "_help_search"); + se->connect("request_help", this, "_help_search"); se->connect("request_open_script_at_line", this, "_goto_script_line"); se->connect("go_to_help", this, "_help_class_goto"); se->connect("request_save_history", this, "_save_history"); @@ -2733,10 +2728,6 @@ void ScriptEditor::set_live_auto_reload_running_scripts(bool p_enabled) { auto_reload_running_scripts = p_enabled; } -void ScriptEditor::_help_index(String p_text) { - help_index->popup_dialog(); -} - void ScriptEditor::_help_search(String p_text) { help_search_dialog->popup_dialog(p_text); } @@ -2788,13 +2779,18 @@ void ScriptEditor::_on_find_in_files_requested(String text) { void ScriptEditor::_on_find_in_files_result_selected(String fpath, int line_number, int begin, int end) { RES res = ResourceLoader::load(fpath); - edit(res); - - ScriptEditorBase *seb = _get_current_editor(); + if (fpath.get_extension() == "shader") { + ShaderEditorPlugin *shader_editor = Object::cast_to<ShaderEditorPlugin>(EditorNode::get_singleton()->get_editor_data().get_editor("Shader")); + shader_editor->edit(res.ptr()); + shader_editor->make_visible(true); + shader_editor->get_shader_editor()->goto_line_selection(line_number - 1, begin, end); + } else { + edit(res); - ScriptTextEditor *ste = Object::cast_to<ScriptTextEditor>(seb); - if (ste) { - ste->goto_line_selection(line_number - 1, begin, end); + ScriptTextEditor *ste = Object::cast_to<ScriptTextEditor>(_get_current_editor()); + if (ste) { + ste->goto_line_selection(line_number - 1, begin, end); + } } } @@ -2842,7 +2838,6 @@ void ScriptEditor::_bind_methods() { ClassDB::bind_method("_goto_script_line", &ScriptEditor::_goto_script_line); ClassDB::bind_method("_goto_script_line2", &ScriptEditor::_goto_script_line2); ClassDB::bind_method("_help_search", &ScriptEditor::_help_search); - ClassDB::bind_method("_help_index", &ScriptEditor::_help_index); ClassDB::bind_method("_save_history", &ScriptEditor::_save_history); ClassDB::bind_method("_copy_script_path", &ScriptEditor::_copy_script_path); @@ -2984,9 +2979,9 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu->set_text(TTR("File")); file_menu->set_switch_on_hover(true); file_menu->get_popup()->set_hide_on_window_lose_focus(true); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New Script")), FILE_NEW); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new_textfile", TTR("New TextFile")), FILE_NEW_TEXTFILE); - file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/open", TTR("Open")), FILE_OPEN); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new", TTR("New Script...")), FILE_NEW); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/new_textfile", TTR("New TextFile...")), FILE_NEW_TEXTFILE); + file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/open", TTR("Open...")), FILE_OPEN); file_menu->get_popup()->add_submenu_item(TTR("Open Recent"), "RecentScripts", FILE_OPEN_RECENT); recent_scripts = memnew(PopupMenu); @@ -3015,10 +3010,11 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { theme_submenu->set_name("Theme"); file_menu->get_popup()->add_child(theme_submenu); theme_submenu->connect("id_pressed", this, "_theme_option"); - theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/import_theme", TTR("Import Theme")), THEME_IMPORT); + theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/import_theme", TTR("Import Theme...")), THEME_IMPORT); theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/reload_theme", TTR("Reload Theme")), THEME_RELOAD); + theme_submenu->add_separator(); theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/save_theme", TTR("Save Theme")), THEME_SAVE); - theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/save_theme_as", TTR("Save Theme As")), THEME_SAVE_AS); + theme_submenu->add_shortcut(ED_SHORTCUT("script_editor/save_theme_as", TTR("Save Theme As...")), THEME_SAVE_AS); file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_shortcut(ED_SHORTCUT("script_editor/close_docs", TTR("Close Docs")), CLOSE_DOCS); @@ -3080,12 +3076,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { menu_hb->add_child(site_search); site_search->set_tooltip(TTR("Open Godot online documentation")); - class_search = memnew(ToolButton); - class_search->set_text(TTR("Classes")); - class_search->connect("pressed", this, "_menu_option", varray(SEARCH_CLASSES)); - menu_hb->add_child(class_search); - class_search->set_tooltip(TTR("Search the class hierarchy.")); - help_search = memnew(ToolButton); help_search->set_text(TTR("Search Help")); help_search->connect("pressed", this, "_menu_option", varray(SEARCH_HELP)); @@ -3171,10 +3161,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { add_child(help_search_dialog); help_search_dialog->connect("go_to_help", this, "_help_class_goto"); - help_index = memnew(EditorHelpIndex); - add_child(help_index); - help_index->connect("open_class", this, "_help_class_open"); - find_in_files_dialog = memnew(FindInFilesDialog); find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_FIND_REQUESTED, this, "_start_find_in_files", varray(false)); find_in_files_dialog->connect(FindInFilesDialog::SIGNAL_REPLACE_REQUESTED, this, "_start_find_in_files", varray(true)); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 28c07393f7..4be5345aaa 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -34,6 +34,7 @@ #include "core/script_language.h" #include "editor/code_editor.h" #include "editor/editor_help.h" +#include "editor/editor_help_search.h" #include "editor/editor_plugin.h" #include "editor/script_create_dialog.h" #include "scene/gui/item_list.h" @@ -155,7 +156,6 @@ class ScriptEditor : public PanelContainer { DEBUG_SHOW_KEEP_OPEN, DEBUG_WITH_EXTERNAL_EDITOR, SEARCH_HELP, - SEARCH_CLASSES, SEARCH_WEBSITE, HELP_SEARCH_FIND, HELP_SEARCH_FIND_NEXT, @@ -200,7 +200,6 @@ class ScriptEditor : public PanelContainer { Button *help_search; Button *site_search; - Button *class_search; EditorHelpSearch *help_search_dialog; ItemList *script_list; @@ -254,7 +253,7 @@ class ScriptEditor : public PanelContainer { Vector<ScriptHistory> history; int history_pos; - EditorHelpIndex *help_index; + Vector<String> previous_scripts; void _tab_changed(int p_which); void _menu_option(int p_option); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index b7b259c6e1..b6dbc6fcf7 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -131,6 +131,7 @@ void ScriptTextEditor::_load_theme_settings() { Color safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color"); Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color"); Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color"); + Color indent_guide_color = EDITOR_GET("text_editor/highlighting/indent_guide_color"); Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color"); Color selection_color = EDITOR_GET("text_editor/highlighting/selection_color"); Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color"); @@ -163,6 +164,7 @@ void ScriptTextEditor::_load_theme_settings() { text_edit->add_color_override("safe_line_number_color", safe_line_number_color); text_edit->add_color_override("caret_color", caret_color); text_edit->add_color_override("caret_background_color", caret_background_color); + text_edit->add_color_override("indent_guide_color", indent_guide_color); text_edit->add_color_override("font_selected_color", text_selected_color); text_edit->add_color_override("selection_color", selection_color); text_edit->add_color_override("brace_mismatch_color", brace_mismatch_color); @@ -443,6 +445,7 @@ void ScriptTextEditor::_validate_script() { if (!script->get_language()->validate(text, line, col, errortxt, script->get_path(), &fnc, &warnings, &safe_lines)) { String error_text = "error(" + itos(line) + "," + itos(col) + "): " + errortxt; code_editor->set_error(error_text); + code_editor->set_error_pos(line - 1, col - 1); } else { code_editor->set_error(""); line = -1; @@ -1049,7 +1052,7 @@ void ScriptTextEditor::_edit_option(int p_op) { if (text == "") text = tx->get_word_under_cursor(); if (text != "") { - emit_signal("request_help_search", text); + emit_signal("request_help", text); } } break; case LOOKUP_SYMBOL: { diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 0e0c27ee99..e3389f25cf 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -70,6 +70,7 @@ void ShaderTextEditor::_load_theme_settings() { Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color"); Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color"); Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color"); + Color indent_guide_color = EDITOR_GET("text_editor/highlighting/indent_guide_color"); Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color"); Color selection_color = EDITOR_GET("text_editor/highlighting/selection_color"); Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color"); @@ -98,6 +99,7 @@ void ShaderTextEditor::_load_theme_settings() { get_text_edit()->add_color_override("line_number_color", line_number_color); get_text_edit()->add_color_override("caret_color", caret_color); get_text_edit()->add_color_override("caret_background_color", caret_background_color); + get_text_edit()->add_color_override("indent_guide_color", indent_guide_color); get_text_edit()->add_color_override("font_selected_color", text_selected_color); get_text_edit()->add_color_override("selection_color", selection_color); get_text_edit()->add_color_override("brace_mismatch_color", brace_mismatch_color); @@ -193,6 +195,7 @@ void ShaderTextEditor::_validate_script() { if (err != OK) { String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text(); set_error(error_text); + set_error_pos(sl.get_error_line() - 1, 0); for (int i = 0; i < get_text_edit()->get_line_count(); i++) get_text_edit()->set_line_as_marked(i, false); get_text_edit()->set_line_as_marked(sl.get_error_line() - 1, true); @@ -349,9 +352,9 @@ void ShaderEditor::_menu_option(int p_option) { void ShaderEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE) { - } - if (p_what == NOTIFICATION_DRAW) { + if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { + if (is_visible_in_tree()) + shader_editor->get_text_edit()->grab_focus(); } } @@ -367,6 +370,7 @@ void ShaderEditor::_editor_settings_changed() { shader_editor->get_text_edit()->set_indent_size(EditorSettings::get_singleton()->get("text_editor/indent/size")); shader_editor->get_text_edit()->set_indent_using_spaces(EditorSettings::get_singleton()->get("text_editor/indent/type")); shader_editor->get_text_edit()->set_auto_indent(EditorSettings::get_singleton()->get("text_editor/indent/auto_indent")); + shader_editor->get_text_edit()->set_draw_indent_guides(EditorSettings::get_singleton()->get("text_editor/indent/draw_indent_guides")); shader_editor->get_text_edit()->set_draw_tabs(EditorSettings::get_singleton()->get("text_editor/indent/draw_tabs")); shader_editor->get_text_edit()->set_show_line_numbers(EditorSettings::get_singleton()->get("text_editor/line_numbers/show_line_numbers")); shader_editor->get_text_edit()->set_syntax_coloring(EditorSettings::get_singleton()->get("text_editor/highlighting/syntax_highlighting")); @@ -388,7 +392,6 @@ void ShaderEditor::_bind_methods() { ClassDB::bind_method("_menu_option", &ShaderEditor::_menu_option); ClassDB::bind_method("_params_changed", &ShaderEditor::_params_changed); ClassDB::bind_method("apply_shaders", &ShaderEditor::apply_shaders); - //ClassDB::bind_method("_close_current_tab",&ShaderEditor::_close_current_tab); } void ShaderEditor::ensure_select_current() { @@ -404,6 +407,11 @@ void ShaderEditor::ensure_select_current() { }*/ } +void ShaderEditor::goto_line_selection(int p_line, int p_begin, int p_end) { + + shader_editor->goto_line_selection(p_line, p_begin, p_end); +} + void ShaderEditor::edit(const Ref<Shader> &p_shader) { if (p_shader.is_null() || !p_shader->is_text_shader()) diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index 2ea1562310..46e3dffdd5 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -120,6 +120,8 @@ public: void ensure_select_current(); void edit(const Ref<Shader> &p_shader); + void goto_line_selection(int p_line, int p_begin, int p_end); + virtual Size2 get_minimum_size() const { return Size2(0, 200); } void save_external_data(); @@ -143,6 +145,8 @@ public: virtual void make_visible(bool p_visible); virtual void selected_notify(); + ShaderEditor *get_shader_editor() const { return shader_editor; } + virtual void save_external_data(); virtual void apply_changes(); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 1b3e800dca..4fe278d005 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -3238,7 +3238,7 @@ bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const P if (mesh != NULL) { MeshInstance *mesh_instance = memnew(MeshInstance); mesh_instance->set_mesh(mesh); - mesh_instance->set_name(mesh->get_name()); + mesh_instance->set_name(path.get_file().get_basename()); instanced_scene = mesh_instance; } else { if (!scene.is_valid()) { // invalid scene diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 40781908fd..82936d63d2 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -598,7 +598,7 @@ bool SpriteFramesEditor::can_drop_data_fw(const Point2 &p_point, const Variant & return false; for (int i = 0; i < files.size(); i++) { - String file = files[0]; + String file = files[i]; String ftype = EditorFileSystem::get_singleton()->get_file_type(file); if (!ClassDB::is_parent_class(ftype, "Texture")) { diff --git a/editor/plugins/text_editor.cpp b/editor/plugins/text_editor.cpp index 4a8eae1ba4..52dd115b3e 100644 --- a/editor/plugins/text_editor.cpp +++ b/editor/plugins/text_editor.cpp @@ -84,6 +84,7 @@ void TextEditor::_load_theme_settings() { Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color"); Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color"); Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color"); + Color indent_guide_color = EDITOR_GET("text_editor/highlighting/indent_guide_color"); Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color"); Color selection_color = EDITOR_GET("text_editor/highlighting/selection_color"); Color brace_mismatch_color = EDITOR_GET("text_editor/highlighting/brace_mismatch_color"); @@ -115,6 +116,7 @@ void TextEditor::_load_theme_settings() { text_edit->add_color_override("line_number_color", line_number_color); text_edit->add_color_override("caret_color", caret_color); text_edit->add_color_override("caret_background_color", caret_background_color); + text_edit->add_color_override("indent_guide_color", indent_guide_color); text_edit->add_color_override("font_selected_color", text_selected_color); text_edit->add_color_override("selection_color", selection_color); text_edit->add_color_override("brace_mismatch_color", brace_mismatch_color); diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 7c3e524d89..aed3a7d503 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -169,15 +169,24 @@ void TextureRegionEditor::_region_draw() { updating_scroll = true; hscroll->set_min(scroll_rect.position.x); hscroll->set_max(scroll_rect.position.x + scroll_rect.size.x); - hscroll->set_page(edit_draw->get_size().x); - hscroll->set_value(draw_ofs.x); - hscroll->set_step(0.001); + if (ABS(scroll_rect.position.x - (scroll_rect.position.x + scroll_rect.size.x)) <= edit_draw->get_size().x) { + hscroll->hide(); + } else { + hscroll->show(); + hscroll->set_page(edit_draw->get_size().x); + hscroll->set_value(draw_ofs.x); + } vscroll->set_min(scroll_rect.position.y); vscroll->set_max(scroll_rect.position.y + scroll_rect.size.y); - vscroll->set_page(edit_draw->get_size().y); - vscroll->set_value(draw_ofs.y); - vscroll->set_step(0.001); + if (ABS(scroll_rect.position.y - (scroll_rect.position.y + scroll_rect.size.y)) <= edit_draw->get_size().y) { + vscroll->hide(); + draw_ofs.y = scroll_rect.position.y; + } else { + vscroll->show(); + vscroll->set_page(edit_draw->get_size().y); + vscroll->set_value(draw_ofs.y); + } updating_scroll = false; float margins[4]; @@ -299,6 +308,8 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { undo_redo->add_do_method(atlas_tex.ptr(), "set_region", rect); undo_redo->add_undo_method(atlas_tex.ptr(), "set_region", atlas_tex->get_region()); } + undo_redo->add_do_method(this, "_update_rect"); + undo_redo->add_undo_method(this, "_update_rect"); undo_redo->add_do_method(edit_draw, "update"); undo_redo->add_undo_method(edit_draw, "update"); undo_redo->commit_action(); @@ -336,7 +347,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { } else if (drag) { if (edited_margin >= 0) { - undo_redo->create_action("Set Margin"); + undo_redo->create_action(TTR("Set Margin")); static Margin m[4] = { MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT }; if (node_ninepatch) { undo_redo->add_do_method(node_ninepatch, "set_patch_margin", m[edited_margin], node_ninepatch->get_patch_margin(m[edited_margin])); @@ -348,7 +359,7 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { } edited_margin = -1; } else { - undo_redo->create_action("Set Region Rect"); + undo_redo->create_action(TTR("Set Region Rect")); if (node_sprite) { undo_redo->add_do_method(node_sprite, "set_region_rect", node_sprite->get_region_rect()); undo_redo->add_undo_method(node_sprite, "set_region_rect", rect_prev); @@ -364,6 +375,8 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) { } drag_index = -1; } + undo_redo->add_do_method(this, "_update_rect"); + undo_redo->add_undo_method(this, "_update_rect"); undo_redo->add_do_method(edit_draw, "update"); undo_redo->add_undo_method(edit_draw, "update"); undo_redo->commit_action(); @@ -509,10 +522,7 @@ void TextureRegionEditor::_scroll_changed(float) { } void TextureRegionEditor::_set_snap_mode(int p_mode) { - snap_mode_button->get_popup()->set_item_checked(snap_mode, false); snap_mode = p_mode; - snap_mode_button->set_text(snap_mode_button->get_popup()->get_item_text(p_mode)); - snap_mode_button->get_popup()->set_item_checked(snap_mode, true); if (snap_mode == SNAP_GRID) hb_grid->show(); @@ -577,15 +587,26 @@ void TextureRegionEditor::_zoom_out() { } } -void TextureRegionEditor::apply_rect(const Rect2 &rect) { +void TextureRegionEditor::apply_rect(const Rect2 &p_rect) { + if (node_sprite) + node_sprite->set_region_rect(p_rect); + else if (node_ninepatch) + node_ninepatch->set_region_rect(p_rect); + else if (obj_styleBox.is_valid()) + obj_styleBox->set_region_rect(p_rect); + else if (atlas_tex.is_valid()) + atlas_tex->set_region(p_rect); +} + +void TextureRegionEditor::_update_rect() { if (node_sprite) - node_sprite->set_region_rect(rect); + rect = node_sprite->get_region_rect(); else if (node_ninepatch) - node_ninepatch->set_region_rect(rect); + rect = node_ninepatch->get_region_rect(); else if (obj_styleBox.is_valid()) - obj_styleBox->set_region_rect(rect); + rect = obj_styleBox->get_region_rect(); else if (atlas_tex.is_valid()) - atlas_tex->set_region(rect); + rect = atlas_tex->get_region(); } void TextureRegionEditor::_update_autoslice() { @@ -657,6 +678,10 @@ void TextureRegionEditor::_update_autoslice() { void TextureRegionEditor::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + edit_draw->add_style_override("panel", get_stylebox("bg", "Tree")); + } break; case NOTIFICATION_READY: { zoom_out->set_icon(get_icon("ZoomLess", "EditorIcons")); zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons")); @@ -669,7 +694,7 @@ void TextureRegionEditor::_notification(int p_what) { } break; case MainLoop::NOTIFICATION_WM_FOCUS_IN: { // This happens when the user leaves the Editor and returns, - // he/she could have changed the textures, so the cache is cleared + // they could have changed the textures, so the cache is cleared. cache_map.clear(); _edit_region(); } break; @@ -702,6 +727,7 @@ void TextureRegionEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("_zoom_in"), &TextureRegionEditor::_zoom_in); ClassDB::bind_method(D_METHOD("_zoom_reset"), &TextureRegionEditor::_zoom_reset); ClassDB::bind_method(D_METHOD("_zoom_out"), &TextureRegionEditor::_zoom_out); + ClassDB::bind_method(D_METHOD("_update_rect"), &TextureRegionEditor::_update_rect); } bool TextureRegionEditor::is_stylebox() { @@ -774,6 +800,9 @@ void TextureRegionEditor::_edit_region() { texture = atlas_tex->get_atlas(); if (texture.is_null()) { + _zoom_reset(); + hscroll->hide(); + vscroll->hide(); edit_draw->update(); return; } @@ -790,15 +819,7 @@ void TextureRegionEditor::_edit_region() { } } - if (node_sprite) - rect = node_sprite->get_region_rect(); - else if (node_ninepatch) - rect = node_ninepatch->get_region_rect(); - else if (obj_styleBox.is_valid()) - rect = obj_styleBox->get_region_rect(); - else if (atlas_tex.is_valid()) - rect = atlas_tex->get_region(); - + _update_rect(); edit_draw->update(); } @@ -826,30 +847,23 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { drag_index = -1; drag = false; - VBoxContainer *main_vb = memnew(VBoxContainer); - add_child(main_vb); - main_vb->set_anchors_and_margins_preset(Control::PRESET_WIDE); HBoxContainer *hb_tools = memnew(HBoxContainer); - main_vb->add_child(hb_tools); - + add_child(hb_tools); hb_tools->add_child(memnew(Label(TTR("Snap Mode:")))); - snap_mode_button = memnew(MenuButton); + snap_mode_button = memnew(OptionButton); hb_tools->add_child(snap_mode_button); - snap_mode_button->set_text(TTR("<None>")); - PopupMenu *p = snap_mode_button->get_popup(); - p->set_hide_on_checkable_item_selection(false); - p->add_radio_check_item(TTR("<None>"), 0); - p->add_radio_check_item(TTR("Pixel Snap"), 1); - p->add_radio_check_item(TTR("Grid Snap"), 2); - p->add_radio_check_item(TTR("Auto Slice"), 3); - p->set_item_checked(0, true); - p->connect("id_pressed", this, "_set_snap_mode"); + snap_mode_button->add_item(TTR("None"), 0); + snap_mode_button->add_item(TTR("Pixel Snap"), 1); + snap_mode_button->add_item(TTR("Grid Snap"), 2); + snap_mode_button->add_item(TTR("Auto Slice"), 3); + snap_mode_button->select(0); + snap_mode_button->connect("item_selected", this, "_set_snap_mode"); + hb_grid = memnew(HBoxContainer); - //hb_tools->add_child(hb_grid); - main_vb->add_child(hb_grid); - hb_grid->add_child(memnew(VSeparator)); + hb_tools->add_child(hb_grid); + hb_grid->add_child(memnew(VSeparator)); hb_grid->add_child(memnew(Label(TTR("Offset:")))); sb_off_x = memnew(SpinBox); @@ -914,42 +928,47 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) { hb_grid->hide(); - HBoxContainer *main_hb = memnew(HBoxContainer); - main_vb->add_child(main_hb); - edit_draw = memnew(Control); - main_hb->add_child(edit_draw); - main_hb->set_v_size_flags(SIZE_EXPAND_FILL); - edit_draw->set_h_size_flags(SIZE_EXPAND_FILL); + edit_draw = memnew(Panel); + add_child(edit_draw); + edit_draw->set_v_size_flags(SIZE_EXPAND_FILL); + edit_draw->connect("draw", this, "_region_draw"); + edit_draw->connect("gui_input", this, "_region_input"); + + draw_zoom = 1.0; + edit_draw->set_clip_contents(true); - Control *separator = memnew(Control); - separator->set_h_size_flags(Control::SIZE_EXPAND_FILL); - hb_tools->add_child(separator); + HBoxContainer *zoom_hb = memnew(HBoxContainer); + edit_draw->add_child(zoom_hb); + zoom_hb->set_begin(Point2(5, 5)); zoom_out = memnew(ToolButton); + zoom_out->set_tooltip(TTR("Zoom Out")); zoom_out->connect("pressed", this, "_zoom_out"); - hb_tools->add_child(zoom_out); + zoom_hb->add_child(zoom_out); zoom_reset = memnew(ToolButton); + zoom_out->set_tooltip(TTR("Zoom Reset")); zoom_reset->connect("pressed", this, "_zoom_reset"); - hb_tools->add_child(zoom_reset); + zoom_hb->add_child(zoom_reset); zoom_in = memnew(ToolButton); + zoom_out->set_tooltip(TTR("Zoom In")); zoom_in->connect("pressed", this, "_zoom_in"); - hb_tools->add_child(zoom_in); + zoom_hb->add_child(zoom_in); vscroll = memnew(VScrollBar); - main_hb->add_child(vscroll); + vscroll->set_step(0.001); + edit_draw->add_child(vscroll); + vscroll->set_anchors_and_margins_preset(PRESET_RIGHT_WIDE); vscroll->connect("value_changed", this, "_scroll_changed"); hscroll = memnew(HScrollBar); - main_vb->add_child(hscroll); + hscroll->set_step(0.001); + edit_draw->add_child(hscroll); + hscroll->set_anchors_and_margins_preset(PRESET_BOTTOM_WIDE); + hscroll->set_margin(MARGIN_RIGHT, -vscroll->get_size().x * EDSCALE); hscroll->connect("value_changed", this, "_scroll_changed"); - edit_draw->connect("draw", this, "_region_draw"); - edit_draw->connect("gui_input", this, "_region_input"); - draw_zoom = 1.0; updating_scroll = false; - - edit_draw->set_clip_contents(true); } void TextureRegionEditorPlugin::edit(Object *p_object) { @@ -978,7 +997,6 @@ void TextureRegionEditorPlugin::make_visible(bool p_visible) { Dictionary TextureRegionEditorPlugin::get_state() const { Dictionary state; - state["zoom"] = region_editor->draw_zoom; state["snap_offset"] = region_editor->snap_offset; state["snap_step"] = region_editor->snap_step; state["snap_separation"] = region_editor->snap_separation; @@ -989,10 +1007,6 @@ Dictionary TextureRegionEditorPlugin::get_state() const { void TextureRegionEditorPlugin::set_state(const Dictionary &p_state) { Dictionary state = p_state; - if (state.has("zoom")) { - region_editor->draw_zoom = p_state["zoom"]; - } - if (state.has("snap_step")) { Vector2 s = state["snap_step"]; region_editor->sb_step_x->set_value(s.x); @@ -1016,6 +1030,7 @@ void TextureRegionEditorPlugin::set_state(const Dictionary &p_state) { if (state.has("snap_mode")) { region_editor->_set_snap_mode(state["snap_mode"]); + region_editor->snap_mode_button->select(state["snap_mode"]); } } diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h index 61ef769f89..4f301ea916 100644 --- a/editor/plugins/texture_region_editor_plugin.h +++ b/editor/plugins/texture_region_editor_plugin.h @@ -43,9 +43,9 @@ @author Mariano Suligoy */ -class TextureRegionEditor : public Control { +class TextureRegionEditor : public VBoxContainer { - GDCLASS(TextureRegionEditor, Control); + GDCLASS(TextureRegionEditor, VBoxContainer); enum SnapMode { SNAP_NONE, @@ -55,7 +55,7 @@ class TextureRegionEditor : public Control { }; friend class TextureRegionEditorPlugin; - MenuButton *snap_mode_button; + OptionButton *snap_mode_button; ToolButton *zoom_in; ToolButton *zoom_reset; ToolButton *zoom_out; @@ -66,7 +66,7 @@ class TextureRegionEditor : public Control { SpinBox *sb_off_x; SpinBox *sb_sep_y; SpinBox *sb_sep_x; - Control *edit_draw; + Panel *edit_draw; VScrollBar *vscroll; HScrollBar *hscroll; @@ -111,7 +111,8 @@ class TextureRegionEditor : public Control { void _zoom_in(); void _zoom_reset(); void _zoom_out(); - void apply_rect(const Rect2 &rect); + void apply_rect(const Rect2 &p_rect); + void _update_rect(); void _update_autoslice(); protected: diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 213cd2ce1a..1d8a80d3f3 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -1862,7 +1862,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { toolbar->add_child(tile_info); options = memnew(MenuButton); - options->set_text("Tile Map"); + options->set_text("TileMap"); options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("TileMap", "EditorIcons")); options->set_process_unhandled_key_input(false); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index d0e0b3e006..cab9a4297d 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -172,6 +172,7 @@ Error TileSetEditor::update_library_file(Node *p_base_scene, Ref<TileSet> ml, bo } void TileSetEditor::_bind_methods() { + ClassDB::bind_method("_on_tileset_toolbar_button_pressed", &TileSetEditor::_on_tileset_toolbar_button_pressed); ClassDB::bind_method("_on_textures_added", &TileSetEditor::_on_textures_added); ClassDB::bind_method("_on_tileset_toolbar_confirm", &TileSetEditor::_on_tileset_toolbar_confirm); @@ -184,58 +185,69 @@ void TileSetEditor::_bind_methods() { ClassDB::bind_method("_on_workspace_input", &TileSetEditor::_on_workspace_input); ClassDB::bind_method("_on_tool_clicked", &TileSetEditor::_on_tool_clicked); ClassDB::bind_method("_on_priority_changed", &TileSetEditor::_on_priority_changed); + ClassDB::bind_method("_on_z_index_changed", &TileSetEditor::_on_z_index_changed); ClassDB::bind_method("_on_grid_snap_toggled", &TileSetEditor::_on_grid_snap_toggled); ClassDB::bind_method("_set_snap_step", &TileSetEditor::_set_snap_step); ClassDB::bind_method("_set_snap_off", &TileSetEditor::_set_snap_off); ClassDB::bind_method("_set_snap_sep", &TileSetEditor::_set_snap_sep); + ClassDB::bind_method("_zoom_in", &TileSetEditor::_zoom_in); + ClassDB::bind_method("_zoom_out", &TileSetEditor::_zoom_out); + ClassDB::bind_method("_zoom_reset", &TileSetEditor::_zoom_reset); } void TileSetEditor::_notification(int p_what) { - if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { - - tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->set_icon(get_icon("ToolAddNode", "EditorIcons")); - tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->set_icon(get_icon("Remove", "EditorIcons")); - tileset_toolbar_tools->set_icon(get_icon("Tools", "EditorIcons")); - - tool_workspacemode[WORKSPACE_EDIT]->set_icon(get_icon("Edit", "EditorIcons")); - tool_workspacemode[WORKSPACE_CREATE_SINGLE]->set_icon(get_icon("AddSingleTile", "EditorIcons")); - tool_workspacemode[WORKSPACE_CREATE_AUTOTILE]->set_icon(get_icon("AddAutotile", "EditorIcons")); - tool_workspacemode[WORKSPACE_CREATE_ATLAS]->set_icon(get_icon("AddAtlasTile", "EditorIcons")); - - tools[TOOL_SELECT]->set_icon(get_icon("ToolSelect", "EditorIcons")); - tools[BITMASK_COPY]->set_icon(get_icon("Duplicate", "EditorIcons")); - tools[BITMASK_PASTE]->set_icon(get_icon("Override", "EditorIcons")); - tools[BITMASK_CLEAR]->set_icon(get_icon("Clear", "EditorIcons")); - tools[SHAPE_NEW_POLYGON]->set_icon(get_icon("CollisionPolygon2D", "EditorIcons")); - tools[SHAPE_DELETE]->set_icon(get_icon("Remove", "EditorIcons")); - tools[SHAPE_KEEP_INSIDE_TILE]->set_icon(get_icon("Snap", "EditorIcons")); - tools[TOOL_GRID_SNAP]->set_icon(get_icon("SnapGrid", "EditorIcons")); - tools[ZOOM_OUT]->set_icon(get_icon("ZoomLess", "EditorIcons")); - tools[ZOOM_1]->set_icon(get_icon("ZoomReset", "EditorIcons")); - tools[ZOOM_IN]->set_icon(get_icon("ZoomMore", "EditorIcons")); - tools[VISIBLE_INFO]->set_icon(get_icon("InformationSign", "EditorIcons")); - - tool_editmode[EDITMODE_REGION]->set_icon(get_icon("RegionEdit", "EditorIcons")); - tool_editmode[EDITMODE_COLLISION]->set_icon(get_icon("StaticBody2D", "EditorIcons")); - tool_editmode[EDITMODE_OCCLUSION]->set_icon(get_icon("LightOccluder2D", "EditorIcons")); - tool_editmode[EDITMODE_NAVIGATION]->set_icon(get_icon("Navigation2D", "EditorIcons")); - tool_editmode[EDITMODE_BITMASK]->set_icon(get_icon("PackedDataContainer", "EditorIcons")); - tool_editmode[EDITMODE_PRIORITY]->set_icon(get_icon("MaterialPreviewLight1", "EditorIcons")); - tool_editmode[EDITMODE_ICON]->set_icon(get_icon("LargeTexture", "EditorIcons")); + + switch (p_what) { + case NOTIFICATION_READY: { + + add_constant_override("autohide", 1); // Fixes the dragger always showing up. + } break; + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + + tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->set_icon(get_icon("ToolAddNode", "EditorIcons")); + tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->set_icon(get_icon("Remove", "EditorIcons")); + tileset_toolbar_tools->set_icon(get_icon("Tools", "EditorIcons")); + + tool_workspacemode[WORKSPACE_EDIT]->set_icon(get_icon("Edit", "EditorIcons")); + tool_workspacemode[WORKSPACE_CREATE_SINGLE]->set_icon(get_icon("AddSingleTile", "EditorIcons")); + tool_workspacemode[WORKSPACE_CREATE_AUTOTILE]->set_icon(get_icon("AddAutotile", "EditorIcons")); + tool_workspacemode[WORKSPACE_CREATE_ATLAS]->set_icon(get_icon("AddAtlasTile", "EditorIcons")); + + tools[TOOL_SELECT]->set_icon(get_icon("ToolSelect", "EditorIcons")); + tools[BITMASK_COPY]->set_icon(get_icon("Duplicate", "EditorIcons")); + tools[BITMASK_PASTE]->set_icon(get_icon("Override", "EditorIcons")); + tools[BITMASK_CLEAR]->set_icon(get_icon("Clear", "EditorIcons")); + tools[SHAPE_NEW_POLYGON]->set_icon(get_icon("CollisionPolygon2D", "EditorIcons")); + tools[SHAPE_DELETE]->set_icon(get_icon("Remove", "EditorIcons")); + tools[SHAPE_KEEP_INSIDE_TILE]->set_icon(get_icon("Snap", "EditorIcons")); + tools[TOOL_GRID_SNAP]->set_icon(get_icon("SnapGrid", "EditorIcons")); + tools[ZOOM_OUT]->set_icon(get_icon("ZoomLess", "EditorIcons")); + tools[ZOOM_1]->set_icon(get_icon("ZoomReset", "EditorIcons")); + tools[ZOOM_IN]->set_icon(get_icon("ZoomMore", "EditorIcons")); + tools[VISIBLE_INFO]->set_icon(get_icon("InformationSign", "EditorIcons")); + + tool_editmode[EDITMODE_REGION]->set_icon(get_icon("RegionEdit", "EditorIcons")); + tool_editmode[EDITMODE_COLLISION]->set_icon(get_icon("StaticBody2D", "EditorIcons")); + tool_editmode[EDITMODE_OCCLUSION]->set_icon(get_icon("LightOccluder2D", "EditorIcons")); + tool_editmode[EDITMODE_NAVIGATION]->set_icon(get_icon("Navigation2D", "EditorIcons")); + tool_editmode[EDITMODE_BITMASK]->set_icon(get_icon("PackedDataContainer", "EditorIcons")); + tool_editmode[EDITMODE_PRIORITY]->set_icon(get_icon("MaterialPreviewLight1", "EditorIcons")); + tool_editmode[EDITMODE_ICON]->set_icon(get_icon("LargeTexture", "EditorIcons")); + tool_editmode[EDITMODE_Z_INDEX]->set_icon(get_icon("Sort", "EditorIcons")); + + scroll->add_style_override("bg", get_stylebox("bg", "Tree")); + } break; } } TileSetEditor::TileSetEditor(EditorNode *p_editor) { editor = p_editor; - set_name("Tile Set Bottom Editor"); - - HSplitContainer *split = memnew(HSplitContainer); - split->set_anchors_and_margins_preset(PRESET_WIDE, PRESET_MODE_MINSIZE, 10); - add_child(split); + current_tile = -1; VBoxContainer *left_container = memnew(VBoxContainer); - split->add_child(left_container); + add_child(left_container); texture_list = memnew(ItemList); left_container->add_child(texture_list); @@ -247,30 +259,22 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { left_container->add_child(tileset_toolbar_container); tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE] = memnew(ToolButton); - Vector<Variant> p; - p.push_back((int)TOOL_TILESET_ADD_TEXTURE); - tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->connect("pressed", this, "_on_tileset_toolbar_button_pressed", p); + tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->connect("pressed", this, "_on_tileset_toolbar_button_pressed", varray(TOOL_TILESET_ADD_TEXTURE)); tileset_toolbar_container->add_child(tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]); - tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->set_tooltip(TTR("Add Texture(s) to TileSet")); + tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->set_tooltip(TTR("Add Texture(s) to TileSet.")); tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE] = memnew(ToolButton); - p = Vector<Variant>(); - p.push_back((int)TOOL_TILESET_REMOVE_TEXTURE); - tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->connect("pressed", this, "_on_tileset_toolbar_button_pressed", p); + tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->connect("pressed", this, "_on_tileset_toolbar_button_pressed", varray(TOOL_TILESET_REMOVE_TEXTURE)); tileset_toolbar_container->add_child(tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]); - tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->set_tooltip(TTR("Remove current Texture from TileSet")); + tileset_toolbar_buttons[TOOL_TILESET_REMOVE_TEXTURE]->set_tooltip(TTR("Remove selected Texture from TileSet.")); Control *toolbar_separator = memnew(Control); toolbar_separator->set_h_size_flags(Control::SIZE_EXPAND_FILL); tileset_toolbar_container->add_child(toolbar_separator); tileset_toolbar_tools = memnew(MenuButton); - tileset_toolbar_tools->set_text("Tools"); - p = Vector<Variant>(); - p.push_back((int)TOOL_TILESET_CREATE_SCENE); + tileset_toolbar_tools->set_text(TTR("Tools")); tileset_toolbar_tools->get_popup()->add_item(TTR("Create from Scene"), TOOL_TILESET_CREATE_SCENE); - p = Vector<Variant>(); - p.push_back((int)TOOL_TILESET_MERGE_SCENE); tileset_toolbar_tools->get_popup()->add_item(TTR("Merge from Scene"), TOOL_TILESET_MERGE_SCENE); tileset_toolbar_tools->get_popup()->connect("id_pressed", this, "_on_tileset_toolbar_button_pressed"); @@ -279,7 +283,7 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { //--------------- VBoxContainer *right_container = memnew(VBoxContainer); right_container->set_v_size_flags(SIZE_EXPAND_FILL); - split->add_child(right_container); + add_child(right_container); dragging_point = -1; creating_shape = false; @@ -296,21 +300,18 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { Ref<ButtonGroup> g(memnew(ButtonGroup)); String workspace_label[WORKSPACE_MODE_MAX] = { "Edit", "New Single Tile", "New Autotile", "New Atlas" }; - for (int i = 0; i < (int)WORKSPACE_MODE_MAX; i++) { tool_workspacemode[i] = memnew(Button); - tool_workspacemode[i]->set_text(workspace_label[i]); + tool_workspacemode[i]->set_text(TTR(workspace_label[i])); tool_workspacemode[i]->set_toggle_mode(true); tool_workspacemode[i]->set_button_group(g); - Vector<Variant> p; - p.push_back(i); - tool_workspacemode[i]->connect("pressed", this, "_on_workspace_mode_changed", p); + tool_workspacemode[i]->connect("pressed", this, "_on_workspace_mode_changed", varray(i)); tool_hb->add_child(tool_workspacemode[i]); } Control *spacer = memnew(Control); spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL); tool_hb->add_child(spacer); - tool_hb->move_child(spacer, (int)WORKSPACE_CREATE_SINGLE); + tool_hb->move_child(spacer, WORKSPACE_CREATE_SINGLE); tool_workspacemode[WORKSPACE_EDIT]->set_pressed(true); workspace_mode = WORKSPACE_EDIT; @@ -321,16 +322,13 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { tool_hb = memnew(HBoxContainer); g = Ref<ButtonGroup>(memnew(ButtonGroup)); - String label[EDITMODE_MAX] = { "Region", "Collision", "Occlusion", "Navigation", "Bitmask", "Priority", "Icon" }; - + String label[EDITMODE_MAX] = { "Region", "Collision", "Occlusion", "Navigation", "Bitmask", "Priority", "Icon", "Z Index" }; for (int i = 0; i < (int)EDITMODE_MAX; i++) { tool_editmode[i] = memnew(Button); tool_editmode[i]->set_text(label[i]); tool_editmode[i]->set_toggle_mode(true); tool_editmode[i]->set_button_group(g); - Vector<Variant> p; - p.push_back(i); - tool_editmode[i]->connect("pressed", this, "_on_edit_mode_changed", p); + tool_editmode[i]->connect("pressed", this, "_on_edit_mode_changed", varray(i)); tool_hb->add_child(tool_editmode[i]); } tool_editmode[EDITMODE_COLLISION]->set_pressed(true); @@ -343,42 +341,38 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { toolbar = memnew(HBoxContainer); Ref<ButtonGroup> tg(memnew(ButtonGroup)); - p = Vector<Variant>(); tools[TOOL_SELECT] = memnew(ToolButton); toolbar->add_child(tools[TOOL_SELECT]); - tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to use as icon, this will be also used on invalid autotile bindings.")); tools[TOOL_SELECT]->set_toggle_mode(true); tools[TOOL_SELECT]->set_button_group(tg); tools[TOOL_SELECT]->set_pressed(true); - p.push_back((int)TOOL_SELECT); - tools[TOOL_SELECT]->connect("pressed", this, "_on_tool_clicked", p); + tools[TOOL_SELECT]->connect("pressed", this, "_on_tool_clicked", varray(TOOL_SELECT)); + separator_bitmask = memnew(VSeparator); + toolbar->add_child(separator_bitmask); tools[BITMASK_COPY] = memnew(ToolButton); - p.push_back((int)BITMASK_COPY); - tools[BITMASK_COPY]->connect("pressed", this, "_on_tool_clicked", p); + tools[BITMASK_COPY]->set_tooltip(TTR("Copy bitmask.")); + tools[BITMASK_COPY]->connect("pressed", this, "_on_tool_clicked", varray(BITMASK_COPY)); toolbar->add_child(tools[BITMASK_COPY]); tools[BITMASK_PASTE] = memnew(ToolButton); - p = Vector<Variant>(); - p.push_back((int)BITMASK_PASTE); - tools[BITMASK_PASTE]->connect("pressed", this, "_on_tool_clicked", p); + tools[BITMASK_PASTE]->set_tooltip(TTR("Paste bitmask.")); + tools[BITMASK_PASTE]->connect("pressed", this, "_on_tool_clicked", varray(BITMASK_PASTE)); toolbar->add_child(tools[BITMASK_PASTE]); tools[BITMASK_CLEAR] = memnew(ToolButton); - p = Vector<Variant>(); - p.push_back((int)BITMASK_CLEAR); - tools[BITMASK_CLEAR]->connect("pressed", this, "_on_tool_clicked", p); + tools[BITMASK_CLEAR]->set_tooltip(TTR("Erase bitmask.")); + tools[BITMASK_CLEAR]->connect("pressed", this, "_on_tool_clicked", varray(BITMASK_CLEAR)); toolbar->add_child(tools[BITMASK_CLEAR]); tools[SHAPE_NEW_POLYGON] = memnew(ToolButton); toolbar->add_child(tools[SHAPE_NEW_POLYGON]); tools[SHAPE_NEW_POLYGON]->set_toggle_mode(true); tools[SHAPE_NEW_POLYGON]->set_button_group(tg); + tools[SHAPE_NEW_POLYGON]->set_tooltip(TTR("Create a new polygon.")); separator_delete = memnew(VSeparator); toolbar->add_child(separator_delete); tools[SHAPE_DELETE] = memnew(ToolButton); - p = Vector<Variant>(); - p.push_back((int)SHAPE_DELETE); - tools[SHAPE_DELETE]->connect("pressed", this, "_on_tool_clicked", p); + tools[SHAPE_DELETE]->connect("pressed", this, "_on_tool_clicked", varray(SHAPE_DELETE)); toolbar->add_child(tools[SHAPE_DELETE]); separator_grid = memnew(VSeparator); @@ -386,9 +380,11 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { tools[SHAPE_KEEP_INSIDE_TILE] = memnew(ToolButton); tools[SHAPE_KEEP_INSIDE_TILE]->set_toggle_mode(true); tools[SHAPE_KEEP_INSIDE_TILE]->set_pressed(true); + tools[SHAPE_KEEP_INSIDE_TILE]->set_tooltip(TTR("Keep polygon inside region Rect.")); toolbar->add_child(tools[SHAPE_KEEP_INSIDE_TILE]); tools[TOOL_GRID_SNAP] = memnew(ToolButton); tools[TOOL_GRID_SNAP]->set_toggle_mode(true); + tools[TOOL_GRID_SNAP]->set_tooltip(TTR("Enable snap and show grid (configurable via the Inspector).")); tools[TOOL_GRID_SNAP]->connect("toggled", this, "_on_grid_snap_toggled"); toolbar->add_child(tools[TOOL_GRID_SNAP]); @@ -401,32 +397,35 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { spin_priority->hide(); toolbar->add_child(spin_priority); + spin_z_index = memnew(SpinBox); + spin_z_index->set_min(VS::CANVAS_ITEM_Z_MIN); + spin_z_index->set_max(VS::CANVAS_ITEM_Z_MAX); + spin_z_index->set_step(1); + spin_z_index->set_custom_minimum_size(Size2(100, 0)); + spin_z_index->connect("value_changed", this, "_on_z_index_changed"); + spin_z_index->hide(); + toolbar->add_child(spin_z_index); + Control *separator = memnew(Control); separator->set_h_size_flags(SIZE_EXPAND_FILL); toolbar->add_child(separator); tools[ZOOM_OUT] = memnew(ToolButton); - p = Vector<Variant>(); - p.push_back((int)ZOOM_OUT); - tools[ZOOM_OUT]->connect("pressed", this, "_on_tool_clicked", p); + tools[ZOOM_OUT]->connect("pressed", this, "_zoom_out"); toolbar->add_child(tools[ZOOM_OUT]); tools[ZOOM_OUT]->set_tooltip(TTR("Zoom Out")); tools[ZOOM_1] = memnew(ToolButton); - p = Vector<Variant>(); - p.push_back((int)ZOOM_1); - tools[ZOOM_1]->connect("pressed", this, "_on_tool_clicked", p); + tools[ZOOM_1]->connect("pressed", this, "_zoom_reset"); toolbar->add_child(tools[ZOOM_1]); - tools[ZOOM_1]->set_tooltip(TTR("Reset Zoom")); + tools[ZOOM_1]->set_tooltip(TTR("Zoom Reset")); tools[ZOOM_IN] = memnew(ToolButton); - p = Vector<Variant>(); - p.push_back((int)ZOOM_IN); - tools[ZOOM_IN]->connect("pressed", this, "_on_tool_clicked", p); + tools[ZOOM_IN]->connect("pressed", this, "_zoom_in"); toolbar->add_child(tools[ZOOM_IN]); tools[ZOOM_IN]->set_tooltip(TTR("Zoom In")); tools[VISIBLE_INFO] = memnew(ToolButton); tools[VISIBLE_INFO]->set_toggle_mode(true); - tools[VISIBLE_INFO]->set_tooltip(TTR("Display tile's names (hold Alt Key)")); + tools[VISIBLE_INFO]->set_tooltip(TTR("Display Tile Names (Hold Alt Key)")); toolbar->add_child(tools[VISIBLE_INFO]); main_vb->add_child(toolbar); @@ -600,10 +599,14 @@ void TileSetEditor::_on_textures_added(const PoolStringArray &p_paths) { } void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { + draw_handles = false; + creating_shape = false; edit_mode = (EditMode)p_edit_mode; switch (edit_mode) { case EDITMODE_REGION: { tools[TOOL_SELECT]->show(); + + separator_bitmask->hide(); tools[BITMASK_COPY]->hide(); tools[BITMASK_PASTE]->hide(); tools[BITMASK_CLEAR]->hide(); @@ -623,30 +626,16 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[TOOL_SELECT]->set_pressed(true); tools[TOOL_SELECT]->set_tooltip(TTR("Drag handles to edit Rect.\nClick on another Tile to edit it.")); + tools[SHAPE_DELETE]->set_tooltip(TTR("Delete selected Rect.")); spin_priority->hide(); - } break; - case EDITMODE_BITMASK: { - tools[TOOL_SELECT]->show(); - tools[BITMASK_COPY]->show(); - tools[BITMASK_PASTE]->show(); - tools[BITMASK_CLEAR]->show(); - tools[SHAPE_NEW_POLYGON]->hide(); - - separator_delete->hide(); - tools[SHAPE_DELETE]->hide(); - - separator_grid->hide(); - tools[SHAPE_KEEP_INSIDE_TILE]->hide(); - tools[TOOL_GRID_SNAP]->hide(); - - tools[TOOL_SELECT]->set_pressed(true); - tools[TOOL_SELECT]->set_tooltip(TTR("LMB: set bit on.\nRMB: set bit off.\nClick on another Tile to edit it.")); - spin_priority->hide(); + spin_z_index->hide(); } break; case EDITMODE_COLLISION: case EDITMODE_NAVIGATION: case EDITMODE_OCCLUSION: { tools[TOOL_SELECT]->show(); + + separator_bitmask->hide(); tools[BITMASK_COPY]->hide(); tools[BITMASK_PASTE]->hide(); tools[BITMASK_CLEAR]->hide(); @@ -660,11 +649,38 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { tools[TOOL_GRID_SNAP]->show(); tools[TOOL_SELECT]->set_tooltip(TTR("Select current edited sub-tile.\nClick on another Tile to edit it.")); + tools[SHAPE_DELETE]->set_tooltip(TTR("Delete polygon.")); spin_priority->hide(); + spin_z_index->hide(); + select_coord(edited_shape_coord); } break; - default: { + case EDITMODE_BITMASK: { tools[TOOL_SELECT]->show(); + + separator_bitmask->show(); + tools[BITMASK_COPY]->show(); + tools[BITMASK_PASTE]->show(); + tools[BITMASK_CLEAR]->show(); + tools[SHAPE_NEW_POLYGON]->hide(); + + separator_delete->hide(); + tools[SHAPE_DELETE]->hide(); + + separator_grid->hide(); + tools[SHAPE_KEEP_INSIDE_TILE]->hide(); + tools[TOOL_GRID_SNAP]->hide(); + + tools[TOOL_SELECT]->set_pressed(true); + tools[TOOL_SELECT]->set_tooltip(TTR("LMB: Set bit on.\nRMB: Set bit off.\nClick on another Tile to edit it.")); + spin_priority->hide(); + } break; + case EDITMODE_Z_INDEX: + case EDITMODE_PRIORITY: + case EDITMODE_ICON: { + tools[TOOL_SELECT]->show(); + + separator_bitmask->hide(); tools[BITMASK_COPY]->hide(); tools[BITMASK_PASTE]->hide(); tools[BITMASK_CLEAR]->hide(); @@ -680,11 +696,18 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) { if (edit_mode == EDITMODE_ICON) { tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to use as icon, this will be also used on invalid autotile bindings.\nClick on another Tile to edit it.")); spin_priority->hide(); - } else { + spin_z_index->hide(); + } else if (edit_mode == EDITMODE_PRIORITY) { tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to change its priority.\nClick on another Tile to edit it.")); spin_priority->show(); + spin_z_index->hide(); + } else { + tools[TOOL_SELECT]->set_tooltip(TTR("Select sub-tile to change its z index.\nClick on another Tile to edit it.")); + spin_priority->hide(); + spin_z_index->show(); } } break; + default: {} } workspace->update(); } @@ -706,15 +729,16 @@ void TileSetEditor::_on_workspace_mode_changed(int p_workspace_mode) { void TileSetEditor::_on_workspace_draw() { - const Color COLOR_AUTOTILE = Color(0.266373, 0.565288, 0.988281); - const Color COLOR_SINGLE = Color(0.988281, 0.909323, 0.266373); - const Color COLOR_ATLAS = Color(0.78653, 0.812835, 0.832031); - - if (tileset.is_null()) - return; - if (!get_current_texture().is_valid()) + if (tileset.is_null() || !get_current_texture().is_valid()) return; + const Color COLOR_AUTOTILE = Color(0.3, 0.6, 1); + const Color COLOR_SINGLE = Color(1, 1, 0.3); + const Color COLOR_ATLAS = Color(0.8, 0.8, 0.8); + const Color COLOR_SUBDIVISION = Color(0.3, 0.7, 0.6); + + draw_handles = false; + draw_highlight_current_tile(); draw_grid_snap(); @@ -808,10 +832,12 @@ void TileSetEditor::_on_workspace_draw() { spin_priority->set_suffix(" / " + String::num(total, 0)); draw_highlight_subtile(edited_shape_coord, queue_others); } break; + case EDITMODE_Z_INDEX: { + spin_z_index->set_value(tileset->autotile_get_z_index(get_current_tile(), edited_shape_coord)); + draw_highlight_subtile(edited_shape_coord); + } break; default: {} } - - draw_tile_subdivision(get_current_tile(), Color(0.347214, 0.722656, 0.617063)); } RID current_texture_rid = get_current_texture()->get_rid(); @@ -819,7 +845,7 @@ void TileSetEditor::_on_workspace_draw() { tileset->get_tile_list(tiles); for (List<int>::Element *E = tiles->front(); E; E = E->next()) { int t_id = E->get(); - if (tileset->tile_get_texture(t_id)->get_rid() == current_texture_rid && (t_id != get_current_tile() || edit_mode != EDITMODE_REGION)) { + if (tileset->tile_get_texture(t_id)->get_rid() == current_texture_rid && (t_id != get_current_tile() || edit_mode != EDITMODE_REGION || workspace_mode != WORKSPACE_EDIT)) { Rect2i region = tileset->tile_get_region(t_id); region.position += WORKSPACE_MARGIN; Color c; @@ -829,10 +855,11 @@ void TileSetEditor::_on_workspace_draw() { c = COLOR_AUTOTILE; else if (tileset->tile_get_tile_mode(t_id) == TileSet::ATLAS_TILE) c = COLOR_ATLAS; - draw_tile_subdivision(t_id, Color(0.347214, 0.722656, 0.617063, 0.5)); + draw_tile_subdivision(t_id, COLOR_SUBDIVISION); workspace->draw_rect(region, c, false); } } + if (edit_mode == EDITMODE_REGION) { if (workspace_mode != WORKSPACE_EDIT) { Rect2i region = edited_region; @@ -854,6 +881,12 @@ void TileSetEditor::_on_workspace_draw() { region = tileset->tile_get_region(t_id); region.position += WORKSPACE_MARGIN; } + + if (draw_edited_region) + draw_edited_region_subdivision(); + else + draw_tile_subdivision(t_id, COLOR_SUBDIVISION); + Color c; if (tileset->tile_get_tile_mode(t_id) == TileSet::SINGLE_TILE) c = COLOR_SINGLE; @@ -861,13 +894,10 @@ void TileSetEditor::_on_workspace_draw() { c = COLOR_AUTOTILE; else if (tileset->tile_get_tile_mode(t_id) == TileSet::ATLAS_TILE) c = COLOR_ATLAS; - if (draw_edited_region) - draw_edited_region_subdivision(); - else - draw_tile_subdivision(t_id, Color(0.347214, 0.722656, 0.617063, 1)); workspace->draw_rect(region, c, false); } } + workspace_overlay->update(); } @@ -887,9 +917,7 @@ void TileSetEditor::_on_workspace_process() { void TileSetEditor::_on_workspace_overlay_draw() { - if (!tileset.is_valid()) - return; - if (!get_current_texture().is_valid()) + if (!tileset.is_valid() || !get_current_texture().is_valid()) return; const Color COLOR_AUTOTILE = Color(0.266373, 0.565288, 0.988281); @@ -939,9 +967,8 @@ void TileSetEditor::_on_workspace_overlay_draw() { #define MIN_DISTANCE_SQUARED 6 void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { - if (tileset.is_null()) - return; - if (!get_current_texture().is_valid()) + + if (tileset.is_null() || !get_current_texture().is_valid()) return; static bool dragging; @@ -979,11 +1006,9 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { } // Mouse Wheel Event - const int _mouse_button_index = mb->get_button_index(); - if (_mouse_button_index == BUTTON_WHEEL_UP && mb->get_control()) { + if (mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed() && mb->get_control()) { _zoom_in(); - - } else if (_mouse_button_index == BUTTON_WHEEL_DOWN && mb->get_control()) { + } else if (mb->get_button_index() == BUTTON_WHEEL_DOWN && mb->is_pressed() && mb->get_control()) { _zoom_out(); } } @@ -1032,10 +1057,14 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { tileset->tile_set_tile_mode(t_id, workspace_mode == WORKSPACE_CREATE_AUTOTILE ? TileSet::AUTO_TILE : TileSet::ATLAS_TILE); } set_current_tile(t_id); + tool_workspacemode[WORKSPACE_EDIT]->set_pressed(true); + tool_editmode[EDITMODE_COLLISION]->set_pressed(true); + edit_mode = EDITMODE_COLLISION; _on_workspace_mode_changed(WORKSPACE_EDIT); } } + edited_region = Rect2(); workspace->update(); workspace_overlay->update(); return; @@ -1201,7 +1230,8 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) { case EDITMODE_COLLISION: case EDITMODE_OCCLUSION: case EDITMODE_NAVIGATION: - case EDITMODE_PRIORITY: { + case EDITMODE_PRIORITY: + case EDITMODE_Z_INDEX: { Vector2 shape_anchor = Vector2(0, 0); if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) { shape_anchor = edited_shape_coord; @@ -1416,6 +1446,7 @@ void TileSetEditor::_on_tool_clicked(int p_tool) { case EDITMODE_REGION: { if (workspace_mode == WORKSPACE_EDIT && get_current_tile() >= 0) { tileset->remove_tile(get_current_tile()); + set_current_tile(-1); workspace->update(); workspace_overlay->update(); } @@ -1461,12 +1492,6 @@ void TileSetEditor::_on_tool_clicked(int p_tool) { default: {} } } - } else if (p_tool == ZOOM_OUT) { - _zoom_out(); - } else if (p_tool == ZOOM_1) { - _reset_zoom(); - } else if (p_tool == ZOOM_IN) { - _zoom_in(); } else if (p_tool == TOOL_SELECT) { if (creating_shape) { // Cancel Creation @@ -1482,6 +1507,11 @@ void TileSetEditor::_on_priority_changed(float val) { workspace->update(); } +void TileSetEditor::_on_z_index_changed(float val) { + tileset->autotile_set_z_index(get_current_tile(), edited_shape_coord, (int)val); + workspace->update(); +} + void TileSetEditor::_on_grid_snap_toggled(bool p_val) { helper->set_snap_options_visible(p_val); workspace->update(); @@ -1524,7 +1554,7 @@ void TileSetEditor::_zoom_out() { workspace_overlay->set_custom_minimum_size(workspace->get_rect().size * scale); } } -void TileSetEditor::_reset_zoom() { +void TileSetEditor::_zoom_reset() { workspace->set_scale(Vector2(1, 1)); workspace_container->set_custom_minimum_size(workspace->get_rect().size); workspace_overlay->set_custom_minimum_size(workspace->get_rect().size); @@ -1532,20 +1562,32 @@ void TileSetEditor::_reset_zoom() { void TileSetEditor::draw_highlight_current_tile() { - if (get_current_tile() >= 0) { - Rect2 region = tileset->tile_get_region(get_current_tile()); - region.position += WORKSPACE_MARGIN; - workspace->draw_rect(Rect2(0, 0, workspace->get_rect().size.x, region.position.y), Color(0.3, 0.3, 0.3, 0.3)); - workspace->draw_rect(Rect2(0, region.position.y, region.position.x, region.size.y), Color(0.3, 0.3, 0.3, 0.3)); - workspace->draw_rect(Rect2(region.position.x + region.size.x, region.position.y, workspace->get_rect().size.x - region.position.x - region.size.x, region.size.y), Color(0.3, 0.3, 0.3, 0.3)); - workspace->draw_rect(Rect2(0, region.position.y + region.size.y, workspace->get_rect().size.x, workspace->get_rect().size.y - region.size.y - region.position.y), Color(0.3, 0.3, 0.3, 0.3)); + Color shadow_color = Color(0.3, 0.3, 0.3, 0.3); + if ((workspace_mode == WORKSPACE_EDIT && get_current_tile() >= 0) || !edited_region.has_no_area()) { + Rect2 region; + if (edited_region.has_no_area()) { + region = tileset->tile_get_region(get_current_tile()); + region.position += WORKSPACE_MARGIN; + } else { + region = edited_region; + } + + if (region.position.y >= 0) + workspace->draw_rect(Rect2(0, 0, workspace->get_rect().size.x, region.position.y), shadow_color); + if (region.position.x >= 0) + workspace->draw_rect(Rect2(0, MAX(0, region.position.y), region.position.x, MIN(workspace->get_rect().size.y - region.position.y, MIN(region.size.y, region.position.y + region.size.y))), shadow_color); + if (region.position.x + region.size.x <= workspace->get_rect().size.x) + workspace->draw_rect(Rect2(region.position.x + region.size.x, MAX(0, region.position.y), workspace->get_rect().size.x - region.position.x - region.size.x, MIN(workspace->get_rect().size.y - region.position.y, MIN(region.size.y, region.position.y + region.size.y))), shadow_color); + if (region.position.y + region.size.y <= workspace->get_rect().size.y) + workspace->draw_rect(Rect2(0, region.position.y + region.size.y, workspace->get_rect().size.x, workspace->get_rect().size.y - region.size.y - region.position.y), shadow_color); } else { - workspace->draw_rect(Rect2(Point2(0, 0), workspace->get_rect().size), Color(0.3, 0.3, 0.3, 0.3)); + workspace->draw_rect(Rect2(Point2(0, 0), workspace->get_rect().size), shadow_color); } } void TileSetEditor::draw_highlight_subtile(Vector2 coord, const Vector<Vector2> &other_highlighted) { + Color shadow_color = Color(0.3, 0.3, 0.3, 0.3); Vector2 size = tileset->autotile_get_size(get_current_tile()); int spacing = tileset->autotile_get_spacing(get_current_tile()); Rect2 region = tileset->tile_get_region(get_current_tile()); @@ -1553,10 +1595,16 @@ void TileSetEditor::draw_highlight_subtile(Vector2 coord, const Vector<Vector2> coord.y *= (size.y + spacing); coord += region.position; coord += WORKSPACE_MARGIN; - workspace->draw_rect(Rect2(0, 0, workspace->get_rect().size.x, coord.y), Color(0.3, 0.3, 0.3, 0.3)); - workspace->draw_rect(Rect2(0, coord.y, coord.x, size.y), Color(0.3, 0.3, 0.3, 0.3)); - workspace->draw_rect(Rect2(coord.x + size.x, coord.y, workspace->get_rect().size.x - coord.x - size.x, size.y), Color(0.3, 0.3, 0.3, 0.3)); - workspace->draw_rect(Rect2(0, coord.y + size.y, workspace->get_rect().size.x, workspace->get_rect().size.y - size.y - coord.y), Color(0.3, 0.3, 0.3, 0.3)); + + if (coord.y >= 0) + workspace->draw_rect(Rect2(0, 0, workspace->get_rect().size.x, coord.y), shadow_color); + if (coord.x >= 0) + workspace->draw_rect(Rect2(0, MAX(0, coord.y), coord.x, MIN(workspace->get_rect().size.y - coord.y, MIN(size.y, coord.y + size.y))), shadow_color); + if (coord.x + size.x <= workspace->get_rect().size.x) + workspace->draw_rect(Rect2(coord.x + size.x, MAX(0, coord.y), workspace->get_rect().size.x - coord.x - size.x, MIN(workspace->get_rect().size.y - coord.y, MIN(size.y, coord.y + size.y))), shadow_color); + if (coord.y + size.y <= workspace->get_rect().size.y) + workspace->draw_rect(Rect2(0, coord.y + size.y, workspace->get_rect().size.x, workspace->get_rect().size.y - size.y - coord.y), shadow_color); + coord += Vector2(1, 1) / workspace->get_scale().x; workspace->draw_rect(Rect2(coord, size - Vector2(2, 2) / workspace->get_scale().x), Color(1, 0, 0), false); for (int i = 0; i < other_highlighted.size(); i++) { @@ -1576,35 +1624,35 @@ void TileSetEditor::draw_tile_subdivision(int p_id, Color p_color) const { Rect2 region = tileset->tile_get_region(p_id); Size2 size = tileset->autotile_get_size(p_id); int spacing = tileset->autotile_get_spacing(p_id); - float j = 0; + float j = size.x; + while (j < region.size.x) { - j += size.x; if (spacing <= 0) { workspace->draw_line(region.position + WORKSPACE_MARGIN + Point2(j, 0), region.position + WORKSPACE_MARGIN + Point2(j, region.size.y), c); } else { workspace->draw_rect(Rect2(region.position + WORKSPACE_MARGIN + Point2(j, 0), Size2(spacing, region.size.y)), c); } - j += spacing; + j += spacing + size.x; } - j = 0; + j = size.y; while (j < region.size.y) { - j += size.y; if (spacing <= 0) { workspace->draw_line(region.position + WORKSPACE_MARGIN + Point2(0, j), region.position + WORKSPACE_MARGIN + Point2(region.size.x, j), c); } else { workspace->draw_rect(Rect2(region.position + WORKSPACE_MARGIN + Point2(0, j), Size2(region.size.x, spacing)), c); } - j += spacing; + j += spacing + size.y; } } } void TileSetEditor::draw_edited_region_subdivision() const { - Color c = Color(0.347214, 0.722656, 0.617063, 1); + Color c = Color(0.3, 0.7, 0.6); Rect2 region = edited_region; Size2 size; int spacing; bool draw; + if (workspace_mode == WORKSPACE_EDIT) { int p_id = get_current_tile(); size = tileset->autotile_get_size(p_id); @@ -1615,66 +1663,72 @@ void TileSetEditor::draw_edited_region_subdivision() const { spacing = snap_separation.x; draw = workspace_mode != WORKSPACE_CREATE_SINGLE; } - if (draw) { - float j = 0; + if (draw) { + float j = size.x; while (j < region.size.x) { - j += size.x; if (spacing <= 0) { workspace->draw_line(region.position + Point2(j, 0), region.position + Point2(j, region.size.y), c); } else { workspace->draw_rect(Rect2(region.position + Point2(j, 0), Size2(spacing, region.size.y)), c); } - j += spacing; + j += spacing + size.x; } - j = 0; + j = size.y; while (j < region.size.y) { - j += size.y; if (spacing <= 0) { workspace->draw_line(region.position + Point2(0, j), region.position + Point2(region.size.x, j), c); } else { workspace->draw_rect(Rect2(region.position + Point2(0, j), Size2(region.size.x, spacing)), c); } - j += spacing; + j += spacing + size.y; } } } void TileSetEditor::draw_grid_snap() { if (tools[TOOL_GRID_SNAP]->is_pressed()) { - Color grid_color = Color(0.39, 0, 1, 0.2f); + Color grid_color = Color(0.4, 0, 1); Size2 s = workspace->get_size(); - int width_count = (int)(s.width / (snap_step.x + snap_separation.x)); - int height_count = (int)(s.height / (snap_step.y + snap_separation.y)); + int width_count = Math::floor((s.width - WORKSPACE_MARGIN.x) / (snap_step.x + snap_separation.x)); + int height_count = Math::floor((s.height - WORKSPACE_MARGIN.y) / (snap_step.y + snap_separation.y)); + int last_p = 0; if (snap_step.x != 0) { - int last_p = 0; for (int i = 0; i <= width_count; i++) { if (i == 0 && snap_offset.x != 0) { last_p = snap_offset.x; } - if (snap_separation.x != 0 && i != 0) { - workspace->draw_rect(Rect2(last_p, 0, snap_separation.x, s.height), grid_color); - last_p += snap_separation.x; - } else + if (snap_separation.x != 0) { + if (i != 0) { + workspace->draw_rect(Rect2(last_p, 0, snap_separation.x, s.height), grid_color); + last_p += snap_separation.x; + } else { + workspace->draw_rect(Rect2(last_p, 0, -snap_separation.x, s.height), grid_color); + } + } else { workspace->draw_line(Point2(last_p, 0), Point2(last_p, s.height), grid_color); - + } last_p += snap_step.x; } } - + last_p = 0; if (snap_step.y != 0) { - int last_p = 0; for (int i = 0; i <= height_count; i++) { if (i == 0 && snap_offset.y != 0) { last_p = snap_offset.y; } - if (snap_separation.x != 0 && i != 0) { - workspace->draw_rect(Rect2(0, last_p, s.width, snap_separation.y), grid_color); - last_p += snap_separation.y; - } else + if (snap_separation.x != 0) { + if (i != 0) { + workspace->draw_rect(Rect2(0, last_p, s.width, snap_separation.y), grid_color); + last_p += snap_separation.y; + } else { + workspace->draw_rect(Rect2(0, last_p, s.width, -snap_separation.y), grid_color); + } + } else { workspace->draw_line(Point2(0, last_p), Point2(s.width, last_p), grid_color); + } last_p += snap_step.y; } } @@ -1687,8 +1741,6 @@ void TileSetEditor::draw_polygon_shapes() { if (t_id < 0) return; - draw_handles = false; - switch (edit_mode) { case EDITMODE_COLLISION: { Vector<TileSet::ShapeData> sd = tileset->tile_get_shapes(t_id); @@ -2154,6 +2206,18 @@ void TileSetEditor::update_texture_list_icon() { void TileSetEditor::update_workspace_tile_mode() { + if (!get_current_texture().is_valid()) { + tool_workspacemode[WORKSPACE_EDIT]->set_pressed(true); + workspace_mode = WORKSPACE_EDIT; + for (int i = 1; i < WORKSPACE_MODE_MAX; i++) { + tool_workspacemode[i]->set_disabled(true); + } + } else { + for (int i = 1; i < WORKSPACE_MODE_MAX; i++) { + tool_workspacemode[i]->set_disabled(false); + } + } + if (workspace_mode != WORKSPACE_EDIT) { for (int i = 0; i < EDITMODE_MAX; i++) { tool_editmode[i]->hide(); @@ -2172,7 +2236,9 @@ void TileSetEditor::update_workspace_tile_mode() { for (int i = 0; i < ZOOM_OUT; i++) { tools[i]->hide(); } + separator_editmode->hide(); + separator_bitmask->hide(); separator_delete->hide(); separator_grid->hide(); return; @@ -2184,7 +2250,7 @@ void TileSetEditor::update_workspace_tile_mode() { separator_editmode->show(); if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) { - if (tool_editmode[EDITMODE_ICON]->is_pressed() || tool_editmode[EDITMODE_PRIORITY]->is_pressed() || tool_editmode[EDITMODE_BITMASK]->is_pressed()) { + if (tool_editmode[EDITMODE_ICON]->is_pressed() || tool_editmode[EDITMODE_PRIORITY]->is_pressed() || tool_editmode[EDITMODE_BITMASK]->is_pressed() || tool_editmode[EDITMODE_Z_INDEX]->is_pressed()) { tool_editmode[EDITMODE_COLLISION]->set_pressed(true); edit_mode = EDITMODE_COLLISION; } @@ -2193,6 +2259,7 @@ void TileSetEditor::update_workspace_tile_mode() { tool_editmode[EDITMODE_ICON]->hide(); tool_editmode[EDITMODE_BITMASK]->hide(); tool_editmode[EDITMODE_PRIORITY]->hide(); + tool_editmode[EDITMODE_Z_INDEX]->hide(); } else if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::AUTO_TILE || tileset->tile_get_tile_mode(get_current_tile()) == TileSet::ATLAS_TILE) { if (edit_mode == EDITMODE_ICON) select_coord(tileset->autotile_get_icon_coordinate(get_current_tile())); @@ -2218,25 +2285,18 @@ void TileSetEditor::update_edited_region(const Vector2 &end_point) { edited_region = Rect2(region_from, Size2()); if (tools[TOOL_GRID_SNAP]->is_pressed()) { Vector2 grid_coord; - grid_coord.x = Math::floor((region_from.x - snap_offset.x) / (snap_step.x + snap_separation.x)); - grid_coord.y = Math::floor((region_from.y - snap_offset.y) / (snap_step.y + snap_separation.y)); - grid_coord.x *= (snap_step.x + snap_separation.x); - grid_coord.y *= (snap_step.y + snap_separation.y); + grid_coord = ((region_from - snap_offset) / (snap_step + snap_separation)).floor(); + grid_coord *= (snap_step + snap_separation); grid_coord += snap_offset; edited_region.expand_to(grid_coord); - grid_coord += snap_step; + grid_coord += snap_step + snap_separation; edited_region.expand_to(grid_coord); - grid_coord.x = Math::floor((end_point.x - snap_offset.x) / (snap_step.x + snap_separation.x)); - grid_coord.y = Math::floor((end_point.y - snap_offset.y) / (snap_step.y + snap_separation.y)); - grid_coord.x *= (snap_step.x + snap_separation.x); - grid_coord.y *= (snap_step.y + snap_separation.y); + + grid_coord = ((end_point - snap_offset) / (snap_step + snap_separation)).floor(); + grid_coord *= (snap_step + snap_separation); grid_coord += snap_offset; edited_region.expand_to(grid_coord); - grid_coord += snap_step; - if (grid_coord.x < end_point.x) - grid_coord.x += snap_separation.x; - if (grid_coord.y < end_point.y) - grid_coord.y += snap_separation.y; + grid_coord += snap_step + snap_separation; edited_region.expand_to(grid_coord); } else { edited_region.expand_to(end_point); @@ -2414,7 +2474,13 @@ void TilesetEditorContext::_get_property_list(List<PropertyInfo> *p_list) const } } +void TilesetEditorContext::_bind_methods() { + + ClassDB::bind_method("_hide_script_from_inspector", &TilesetEditorContext::_hide_script_from_inspector); +} + TilesetEditorContext::TilesetEditorContext(TileSetEditor *p_tileset_editor) { + tileset_editor = p_tileset_editor; } @@ -2428,8 +2494,7 @@ void TileSetEditorPlugin::edit(Object *p_node) { bool TileSetEditorPlugin::handles(Object *p_node) const { - return p_node->is_class("TileSet") || - p_node->is_class("TilesetEditorContext"); + return p_node->is_class("TileSet") || p_node->is_class("TilesetEditorContext"); } void TileSetEditorPlugin::make_visible(bool p_visible) { @@ -2444,6 +2509,41 @@ void TileSetEditorPlugin::make_visible(bool p_visible) { } } +Dictionary TileSetEditorPlugin::get_state() const { + + Dictionary state; + state["snap_offset"] = tileset_editor->snap_offset; + state["snap_step"] = tileset_editor->snap_step; + state["snap_separation"] = tileset_editor->snap_separation; + state["snap_enabled"] = tileset_editor->tools[TileSetEditor::TOOL_GRID_SNAP]->is_pressed(); + state["keep_inside_tile"] = tileset_editor->tools[TileSetEditor::SHAPE_KEEP_INSIDE_TILE]->is_pressed(); + return state; +} + +void TileSetEditorPlugin::set_state(const Dictionary &p_state) { + + Dictionary state = p_state; + if (state.has("snap_step")) { + tileset_editor->_set_snap_step(state["snap_step"]); + } + + if (state.has("snap_offset")) { + tileset_editor->_set_snap_off(state["snap_offset"]); + } + + if (state.has("snap_separation")) { + tileset_editor->_set_snap_sep(state["snap_separation"]); + } + + if (state.has("snap_enabled")) { + tileset_editor->tools[TileSetEditor::TOOL_GRID_SNAP]->set_pressed(state["snap_enabled"]); + } + + if (state.has("keep_inside_tile")) { + tileset_editor->tools[TileSetEditor::SHAPE_KEEP_INSIDE_TILE]->set_pressed(state["keep_inside_tile"]); + } +} + TileSetEditorPlugin::TileSetEditorPlugin(EditorNode *p_node) { editor = p_node; tileset_editor = memnew(TileSetEditor(p_node)); @@ -2451,6 +2551,6 @@ TileSetEditorPlugin::TileSetEditorPlugin(EditorNode *p_node) { tileset_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); tileset_editor->hide(); - tileset_editor_button = p_node->add_bottom_panel_item(TTR("Tile Set"), tileset_editor); + tileset_editor_button = p_node->add_bottom_panel_item(TTR("TileSet"), tileset_editor); tileset_editor_button->hide(); } diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h index bd8a2ddb98..276e23f9ee 100644 --- a/editor/plugins/tile_set_editor_plugin.h +++ b/editor/plugins/tile_set_editor_plugin.h @@ -40,12 +40,12 @@ #define WORKSPACE_MARGIN Vector2(10, 10) class TilesetEditorContext; -class TileSetEditor : public Control { +class TileSetEditor : public HSplitContainer { friend class TileSetEditorPlugin; friend class TilesetEditorContext; - GDCLASS(TileSetEditor, Control) + GDCLASS(TileSetEditor, HSplitContainer) enum TextureToolButtons { TOOL_TILESET_ADD_TEXTURE, @@ -71,6 +71,7 @@ class TileSetEditor : public Control { EDITMODE_BITMASK, EDITMODE_PRIORITY, EDITMODE_ICON, + EDITMODE_Z_INDEX, EDITMODE_MAX }; @@ -134,9 +135,11 @@ class TileSetEditor : public Control { HSeparator *separator_editmode; HBoxContainer *toolbar; ToolButton *tools[TOOL_MAX]; + VSeparator *separator_bitmask; VSeparator *separator_delete; VSeparator *separator_grid; SpinBox *spin_priority; + SpinBox *spin_z_index; WorkspaceMode workspace_mode; EditMode edit_mode; int current_tile; @@ -177,6 +180,7 @@ private: void _on_workspace_input(const Ref<InputEvent> &p_ie); void _on_tool_clicked(int p_tool); void _on_priority_changed(float val); + void _on_z_index_changed(float val); void _on_grid_snap_toggled(bool p_val); void _set_snap_step(Vector2 p_val); void _set_snap_off(Vector2 p_val); @@ -184,7 +188,7 @@ private: void _zoom_in(); void _zoom_out(); - void _reset_zoom(); + void _zoom_reset(); void draw_highlight_current_tile(); void draw_highlight_subtile(Vector2 coord, const Vector<Vector2> &other_highlighted = Vector<Vector2>()); @@ -212,6 +216,7 @@ class TilesetEditorContext : public Object { bool snap_options_visible; public: + bool _hide_script_from_inspector() { return true; } void set_tileset(const Ref<TileSet> &p_tileset); private: @@ -221,6 +226,7 @@ protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; + static void _bind_methods(); public: TilesetEditorContext(TileSetEditor *p_tileset_editor); @@ -240,6 +246,8 @@ public: virtual void edit(Object *p_node); virtual bool handles(Object *p_node) const; virtual void make_visible(bool p_visible); + void set_state(const Dictionary &p_state); + Dictionary get_state() const; TileSetEditorPlugin(EditorNode *p_node); }; diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 39e50ec7f8..f55adf6c7d 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -636,13 +636,15 @@ void VisualShaderEditor::_duplicate_nodes() { for (int i = 0; i < graph->get_child_count(); i++) { - if (Object::cast_to<GraphNode>(graph->get_child(i))) { - int id = String(graph->get_child(i)->get_name()).to_int(); + GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); + if (gn) { + int id = String(gn->get_name()).to_int(); Ref<VisualShaderNode> node = visual_shader->get_node(type, id); Ref<VisualShaderNodeOutput> output = node; - if (output.is_valid()) //can't duplicate output + if (output.is_valid()) { // can't duplicate output continue; - if (node.is_valid()) { + } + if (node.is_valid() && gn->is_selected()) { nodes.push_back(id); } } @@ -798,7 +800,7 @@ VisualShaderEditor::VisualShaderEditor() { add_node = memnew(MenuButton); graph->get_zoom_hbox()->add_child(add_node); - add_node->set_text(TTR("Add Node..")); + add_node->set_text(TTR("Add Node...")); graph->get_zoom_hbox()->move_child(add_node, 0); add_node->get_popup()->connect("id_pressed", this, "_add_node"); |