diff --git a/editor/animation/animation_blend_space_1d_editor.cpp b/editor/animation/animation_blend_space_1d_editor.cpp index cf6c92f7b5d0..1bc5b51e0261 100644 --- a/editor/animation/animation_blend_space_1d_editor.cpp +++ b/editor/animation/animation_blend_space_1d_editor.cpp @@ -574,12 +574,8 @@ void AnimationNodeBlendSpace1DEditor::_add_animation_type(int p_index) { } void AnimationNodeBlendSpace1DEditor::_tool_switch(int p_tool) { - if (p_tool == 0) { - tool_erase->show(); - tool_erase_sep->show(); - } else { - tool_erase->hide(); - tool_erase_sep->hide(); + if (p_tool != 0) { + _set_selected_point(-1); } _update_tool_erase(); @@ -985,14 +981,6 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { tool_blend->set_tooltip_text(TTR("Set the blending position within the space.")); tool_blend->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch).bind(2)); - tool_erase_sep = memnew(VSeparator); - top_hb->add_child(tool_erase_sep); - tool_erase = memnew(Button); - tool_erase->set_theme_type_variation(SceneStringName(FlatButton)); - top_hb->add_child(tool_erase); - tool_erase->set_tooltip_text(TTR("Erase points.")); - tool_erase->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeBlendSpace1DEditor::_erase_selected)); - top_hb->add_child(memnew(VSeparator)); snap = memnew(Button); @@ -1074,6 +1062,14 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { edit_value->set_accessibility_name(TTRC("Blend Value")); edit_value->connect(SceneStringName(value_changed), callable_mp(this, &AnimationNodeBlendSpace1DEditor::_edit_point_pos)); + edit_hb->add_child(memnew(VSeparator)); + tool_erase = memnew(Button); + tool_erase->set_theme_type_variation(SceneStringName(FlatButton)); + top_hb->add_child(tool_erase); + tool_erase->set_tooltip_text(TTR("Erase points.")); + tool_erase->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeBlendSpace1DEditor::_erase_selected)); + tool_erase->set_disabled(true); + edit_hb->hide(); open_editor->hide(); open_editor_sep->hide(); diff --git a/editor/animation/animation_blend_space_1d_editor.h b/editor/animation/animation_blend_space_1d_editor.h index f25ba0bd1744..26d0a1c674a0 100644 --- a/editor/animation/animation_blend_space_1d_editor.h +++ b/editor/animation/animation_blend_space_1d_editor.h @@ -58,7 +58,6 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin { Button *tool_blend = nullptr; Button *tool_select = nullptr; Button *tool_create = nullptr; - VSeparator *tool_erase_sep = nullptr; Button *tool_erase = nullptr; Button *snap = nullptr; SpinBox *snap_value = nullptr; diff --git a/editor/animation/animation_blend_space_2d_editor.cpp b/editor/animation/animation_blend_space_2d_editor.cpp index 530812a0be8b..ccfed9037f9f 100644 --- a/editor/animation/animation_blend_space_2d_editor.cpp +++ b/editor/animation/animation_blend_space_2d_editor.cpp @@ -86,7 +86,7 @@ void AnimationNodeBlendSpace2DEditor::edit(const Ref &p_node) { edit_x->set_editable(!read_only); edit_y->set_editable(!read_only); index_edit->set_editable(!read_only); - tool_triangle->set_disabled(read_only); + tool_triangle->set_disabled(read_only || (blend_space.is_valid() && blend_space->get_auto_triangles())); auto_triangles->set_disabled(read_only); sync->set_disabled(read_only); cyclic_length_value->set_editable(!read_only); @@ -106,13 +106,19 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref k = p_event; if (k.is_valid() && k->is_pressed() && !k->is_echo()) { - if (k->get_keycode() == Key::ESCAPE && editing_point != -1) { - _cancel_inline_edit(); + if (k->get_keycode() == Key::ESCAPE) { + if (editing_point != -1) { + _cancel_inline_edit(); + } + if (making_triangle.size()) { + making_triangle.clear(); + blend_space_draw->queue_redraw(); + } accept_event(); return; } - if (tool_select->is_pressed() && k->get_keycode() == Key::KEY_DELETE) { + if ((tool_select->is_pressed() || tool_triangle->is_pressed()) && k->get_keycode() == Key::KEY_DELETE) { if (selected_point != -1 || selected_triangle != -1) { if (!read_only) { _erase_selected(); @@ -270,6 +276,25 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Refget_auto_triangles()) { // Protecting state just in case. + for (int i = 0; i < blend_space->get_triangle_count(); i++) { + Vector triangle; + + for (int j = 0; j < 3; j++) { + int idx = blend_space->get_triangle_point(i, j); + ERR_FAIL_INDEX(idx, points.size()); + triangle.push_back(points[idx]); + } + + if (Geometry2D::is_point_in_triangle(mb->get_position(), triangle[0], triangle[1], triangle[2])) { + selected_triangle = i; + _update_tool_erase(); + return; + } + } + } } if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == MouseButton::LEFT) { @@ -497,24 +522,13 @@ void AnimationNodeBlendSpace2DEditor::_update_tool_erase() { void AnimationNodeBlendSpace2DEditor::_tool_switch(int p_tool) { making_triangle.clear(); - if (p_tool == 3) { - Vector bl_points; - for (int i = 0; i < blend_space->get_blend_point_count(); i++) { - bl_points.push_back(blend_space->get_blend_point_position(i)); - } - Vector tr = Delaunay2D::triangulate(bl_points); - for (int i = 0; i < tr.size(); i++) { - blend_space->add_triangle(tr[i].points[0], tr[i].points[1], tr[i].points[2]); + if (p_tool != 0) { + _set_selected_point(-1); + if (p_tool != 3) { + selected_triangle = -1; } } - if (p_tool == 0) { - tool_erase->show(); - tool_erase_sep->show(); - } else { - tool_erase->hide(); - tool_erase_sep->hide(); - } _update_tool_erase(); blend_space_draw->queue_redraw(); } @@ -754,12 +768,17 @@ void AnimationNodeBlendSpace2DEditor::_update_space() { updating = true; if (blend_space->get_auto_triangles()) { - tool_triangle->hide(); + tool_triangle->set_disabled(true); + if (tool_triangle->is_pressed()) { + tool_select->set_pressed(true); + _tool_switch(0); + } } else { - tool_triangle->show(); + tool_triangle->set_disabled(false); } auto_triangles->set_pressed(blend_space->get_auto_triangles()); + reset_triangles->set_visible(!blend_space->get_auto_triangles()); sync->select(blend_space->get_sync_mode()); cyclic_length_value->set_value(blend_space->get_cyclic_length()); @@ -1016,6 +1035,7 @@ void AnimationNodeBlendSpace2DEditor::_notification(int p_what) { snap->set_button_icon(get_editor_theme_icon(SNAME("SnapGrid"))); open_editor->set_button_icon(get_editor_theme_icon(SNAME("Edit"))); auto_triangles->set_button_icon(get_editor_theme_icon(SNAME("AutoTriangle"))); + reset_triangles->set_button_icon(get_editor_theme_icon(SNAME("Reload"))); interpolation->clear(); interpolation->add_icon_item(get_editor_theme_icon(SNAME("TrackContinuous")), TTR("Continuous"), 0); interpolation->add_icon_item(get_editor_theme_icon(SNAME("TrackDiscrete")), TTR("Discrete"), 1); @@ -1077,6 +1097,18 @@ void AnimationNodeBlendSpace2DEditor::_auto_triangles_toggled() { undo_redo->commit_action(); } +void AnimationNodeBlendSpace2DEditor::_reset_triangles() { + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + undo_redo->create_action(TTR("Reset BlendSpace2D Triangles")); + for (int i = blend_space->get_triangle_count() - 1; i >= 0; i--) { + undo_redo->add_do_method(blend_space.ptr(), "remove_triangle", i); + undo_redo->add_undo_method(blend_space.ptr(), "add_triangle", blend_space->get_triangle_point(i, 0), blend_space->get_triangle_point(i, 1), blend_space->get_triangle_point(i, 2), i); + } + undo_redo->add_do_method(this, "_update_space"); + undo_redo->add_undo_method(this, "_update_space"); + undo_redo->commit_action(); +} + void AnimationNodeBlendSpace2DEditor::_bind_methods() { ClassDB::bind_method("_update_space", &AnimationNodeBlendSpace2DEditor::_update_space); ClassDB::bind_method("_update_tool_erase", &AnimationNodeBlendSpace2DEditor::_update_tool_erase); @@ -1229,18 +1261,9 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_triangle->set_toggle_mode(true); tool_triangle->set_button_group(bg); top_hb->add_child(tool_triangle); - tool_triangle->set_tooltip_text(TTR("Create triangles by connecting points.")); + tool_triangle->set_tooltip_text(TTR("Create triangles manually by connecting points.")); tool_triangle->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(3)); - tool_erase_sep = memnew(VSeparator); - top_hb->add_child(tool_erase_sep); - tool_erase = memnew(Button); - tool_erase->set_theme_type_variation(SceneStringName(FlatButton)); - top_hb->add_child(tool_erase); - tool_erase->set_tooltip_text(TTR("Erase points and triangles.")); - tool_erase->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeBlendSpace2DEditor::_erase_selected)); - tool_erase->set_disabled(true); - top_hb->add_child(memnew(VSeparator)); auto_triangles = memnew(Button); @@ -1248,7 +1271,14 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { top_hb->add_child(auto_triangles); auto_triangles->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeBlendSpace2DEditor::_auto_triangles_toggled)); auto_triangles->set_toggle_mode(true); - auto_triangles->set_tooltip_text(TTR("Generate blend triangles automatically (instead of manually)")); + auto_triangles->set_tooltip_text(TTR("Generate blend triangles automatically.")); + + reset_triangles = memnew(Button); + reset_triangles->set_theme_type_variation(SceneStringName(FlatButton)); + top_hb->add_child(reset_triangles); + reset_triangles->set_tooltip_text(TTR("Reset triangles.")); + reset_triangles->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeBlendSpace2DEditor::_reset_triangles)); + reset_triangles->set_visible(false); top_hb->add_child(memnew(VSeparator)); @@ -1348,6 +1378,14 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { edit_y->set_accessibility_name(TTRC("Blend Y Value")); edit_y->connect(SceneStringName(value_changed), callable_mp(this, &AnimationNodeBlendSpace2DEditor::_edit_point_pos)); + edit_hb->add_child(memnew(VSeparator)); + tool_erase = memnew(Button); + tool_erase->set_theme_type_variation(SceneStringName(FlatButton)); + top_hb->add_child(tool_erase); + tool_erase->set_tooltip_text(TTR("Erase points and triangles.")); + tool_erase->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeBlendSpace2DEditor::_erase_selected)); + tool_erase->set_disabled(true); + edit_hb->hide(); open_editor->hide(); open_editor_sep->hide(); diff --git a/editor/animation/animation_blend_space_2d_editor.h b/editor/animation/animation_blend_space_2d_editor.h index d7a4712910eb..caf41a65fbd0 100644 --- a/editor/animation/animation_blend_space_2d_editor.h +++ b/editor/animation/animation_blend_space_2d_editor.h @@ -59,7 +59,6 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin { Button *tool_select = nullptr; Button *tool_create = nullptr; Button *tool_triangle = nullptr; - VSeparator *tool_erase_sep = nullptr; Button *tool_erase = nullptr; Button *snap = nullptr; SpinBox *snap_x = nullptr; @@ -69,6 +68,7 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin { OptionButton *interpolation = nullptr; Button *auto_triangles = nullptr; + Button *reset_triangles = nullptr; LineEdit *label_x = nullptr; LineEdit *label_y = nullptr; @@ -148,6 +148,7 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin { void _show_indices_with_cooldown(); void _auto_triangles_toggled(); + void _reset_triangles(); StringName get_blend_position_path() const; String _get_safe_name(const Ref &p_blend_space, const String &p_name); diff --git a/editor/animation/animation_state_machine_editor.cpp b/editor/animation/animation_state_machine_editor.cpp index bd69d1d2c897..e77159742109 100644 --- a/editor/animation/animation_state_machine_editor.cpp +++ b/editor/animation/animation_state_machine_editor.cpp @@ -283,7 +283,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Refget_position())) { //edit name + if (node_rects[i].edit.has_point(mb->get_position())) { // Open editor. callable_mp(this, &AnimationNodeStateMachineEditor::_open_editor).call_deferred(node_rects[i].node_name); return; } @@ -511,13 +511,13 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Refget_button_index() == MouseButton::LEFT && !mb->is_pressed() && box_selecting) { + if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT && box_selecting) { box_selecting = false; state_machine_draw->queue_redraw(); _update_mode(); } - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { + if (mb.is_valid() && mb->is_pressed() && !tool_connect->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { StringName clicked_node; for (int i = node_rects.size() - 1; i >= 0; i--) { if (node_rects[i].node.has_point(mb->get_position())) { @@ -707,7 +707,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Refis_pressed()) { + if (tool_select->is_pressed() && !reconnecting) { int closest_for_highlight = -1; int closest_for_tooltip = -1; float closest_d_highlight = 1e20; @@ -1057,7 +1057,9 @@ void AnimationNodeStateMachineEditor::_add_transition(const bool p_nested_action updating = false; } - _select_transition(connecting_from, connecting_to_node); + if (tool_select->is_pressed()) { + _select_transition(connecting_from, connecting_to_node); + } if (selected_transition_index >= 0) { if (!state_machine->is_transition_across_group(selected_transition_index)) { @@ -1971,12 +1973,17 @@ void AnimationNodeStateMachineEditor::_erase_selected(const bool p_nested_action void AnimationNodeStateMachineEditor::_update_mode() { if (tool_select->is_pressed()) { - selection_tools_hb->show(); bool nothing_selected = selected_nodes.is_empty() && selected_transition_from == StringName() && selected_transition_to == StringName(); bool start_end_selected = selected_nodes.size() == 1 && (*selected_nodes.begin() == SceneStringName(Start) || *selected_nodes.begin() == SceneStringName(End)); tool_erase->set_disabled(nothing_selected || start_end_selected || read_only); - } else { - selection_tools_hb->hide(); + } else { // Clear selection when not using select tool. + selected_transition_from = StringName(); + selected_transition_to = StringName(); + selected_transition_index = -1; + selected_node = StringName(); + selected_nodes.clear(); + connected_nodes.clear(); + state_machine_draw->queue_redraw(); } if (read_only) { @@ -2084,18 +2091,6 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_connect->set_tooltip_text(TTR("Connect nodes.")); tool_connect->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), CONNECT_DEFERRED); - // Context-sensitive selection tools: - selection_tools_hb = memnew(HBoxContainer); - top_hb->add_child(selection_tools_hb); - selection_tools_hb->add_child(memnew(VSeparator)); - - tool_erase = memnew(Button); - tool_erase->set_theme_type_variation(SceneStringName(FlatButton)); - tool_erase->set_tooltip_text(TTR("Remove selected node or transition.")); - tool_erase->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeStateMachineEditor::_erase_selected).bind(false)); - tool_erase->set_disabled(true); - selection_tools_hb->add_child(tool_erase); - transition_tools_hb = memnew(HBoxContainer); top_hb->add_child(transition_tools_hb); transition_tools_hb->add_child(memnew(VSeparator)); @@ -2111,12 +2106,21 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { auto_advance->set_pressed(true); transition_tools_hb->add_child(auto_advance); - top_hb->add_spacer(); + top_hb->add_child(memnew(VSeparator)); top_hb->add_child(memnew(Label(TTR("Play Mode")))); play_mode = memnew(OptionButton); top_hb->add_child(play_mode); + top_hb->add_spacer(); + + tool_erase = memnew(Button); + tool_erase->set_theme_type_variation(SceneStringName(FlatButton)); + tool_erase->set_tooltip_text(TTR("Remove selected node or transition.")); + tool_erase->connect(SceneStringName(pressed), callable_mp(this, &AnimationNodeStateMachineEditor::_erase_selected).bind(false)); + tool_erase->set_disabled(true); + top_hb->add_child(tool_erase); + panel = memnew(PanelContainer); panel->set_clip_contents(true); panel->set_mouse_filter(Control::MOUSE_FILTER_PASS); diff --git a/editor/animation/animation_state_machine_editor.h b/editor/animation/animation_state_machine_editor.h index 53dd75cde0e9..416210e7102c 100644 --- a/editor/animation/animation_state_machine_editor.h +++ b/editor/animation/animation_state_machine_editor.h @@ -54,7 +54,6 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { Popup *name_edit_popup = nullptr; LineEdit *name_edit = nullptr; - HBoxContainer *selection_tools_hb = nullptr; Button *tool_erase = nullptr; HBoxContainer *transition_tools_hb = nullptr;