diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index 5a40c0e86af9..1cffdb645425 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -38,6 +38,7 @@ #include "editor/editor_string_names.h" #include "editor/editor_undo_redo_manager.h" #include "node_3d_editor_plugin.h" +#include "scene/gui/dialogs.h" #include "scene/gui/menu_button.h" #include "scene/resources/curve.h" @@ -735,6 +736,47 @@ void Path3DEditorPlugin::_handle_option_pressed(int p_option) { } } +void Path3DEditorPlugin::_confirm_clear_points() { + if (!path || path->get_curve().is_null() || path->get_curve()->get_point_count() == 0) { + return; + } + clear_points_dialog->reset_size(); + clear_points_dialog->popup_centered(); +} + +void Path3DEditorPlugin::_clear_points() { + EditorUndoRedoManager *undo_redo = EditorUndoRedoManager::get_singleton(); + PackedVector3Array points = path->get_curve()->get_points().duplicate(); + + undo_redo->create_action(TTR("Clear Curve Points")); + undo_redo->add_do_method(this, "_clear_curve_points"); + undo_redo->add_undo_method(this, "_restore_curve_points", points); + undo_redo->commit_action(); +} + +void Path3DEditorPlugin::_clear_curve_points() { + if (!path || path->get_curve().is_null() || path->get_curve()->get_point_count() == 0) { + return; + } + Ref curve = path->get_curve(); + curve->clear_points(); +} + +void Path3DEditorPlugin::_restore_curve_points(const PackedVector3Array &p_points) { + if (!path || path->get_curve().is_null()) { + return; + } + Ref curve = path->get_curve(); + + if (curve->get_point_count() > 0) { + curve->clear_points(); + } + + for (int i = 0; i < p_points.size(); i += 3) { + curve->add_point(p_points[i + 2], p_points[i], p_points[i + 1]); + } +} + void Path3DEditorPlugin::_update_theme() { // TODO: Split the EditorPlugin instance from the UI instance and connect this properly. // See the 2D path editor for inspiration. @@ -744,6 +786,7 @@ void Path3DEditorPlugin::_update_theme() { curve_create->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("CurveCreate"), EditorStringName(EditorIcons))); curve_del->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("CurveDelete"), EditorStringName(EditorIcons))); curve_close->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("CurveClose"), EditorStringName(EditorIcons))); + curve_clear_points->set_icon(EditorNode::get_singleton()->get_editor_theme()->get_icon(SNAME("Clear"), EditorStringName(EditorIcons))); } void Path3DEditorPlugin::_notification(int p_what) { @@ -769,6 +812,8 @@ void Path3DEditorPlugin::_notification(int p_what) { } void Path3DEditorPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("_clear_curve_points"), &Path3DEditorPlugin::_clear_curve_points); + ClassDB::bind_method(D_METHOD("_restore_curve_points"), &Path3DEditorPlugin::_restore_curve_points); } Path3DEditorPlugin *Path3DEditorPlugin::singleton = nullptr; @@ -830,7 +875,18 @@ Path3DEditorPlugin::Path3DEditorPlugin() { curve_close->set_tooltip_text(TTR("Close Curve")); topmenu_bar->add_child(curve_close); - PopupMenu *menu; + curve_clear_points = memnew(Button); + curve_clear_points->set_theme_type_variation("FlatButton"); + curve_clear_points->set_focus_mode(Control::FOCUS_NONE); + curve_clear_points->set_tooltip_text(TTR("Clear Points")); + curve_clear_points->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_confirm_clear_points)); + topmenu_bar->add_child(curve_clear_points); + + clear_points_dialog = memnew(ConfirmationDialog); + clear_points_dialog->set_title(TTR("Please Confirm...")); + clear_points_dialog->set_text(TTR("Remove all curve points?")); + clear_points_dialog->connect("confirmed", callable_mp(this, &Path3DEditorPlugin::_clear_points)); + topmenu_bar->add_child(clear_points_dialog); handle_menu = memnew(MenuButton); handle_menu->set_flat(false); @@ -838,6 +894,7 @@ Path3DEditorPlugin::Path3DEditorPlugin() { handle_menu->set_text(TTR("Options")); topmenu_bar->add_child(handle_menu); + PopupMenu *menu; menu = handle_menu->get_popup(); menu->add_check_item(TTR("Mirror Handle Angles")); menu->set_item_checked(HANDLE_OPTION_ANGLE, mirror_handle_angle); diff --git a/editor/plugins/path_3d_editor_plugin.h b/editor/plugins/path_3d_editor_plugin.h index 39b3c3c6a37c..6a933a419fd7 100644 --- a/editor/plugins/path_3d_editor_plugin.h +++ b/editor/plugins/path_3d_editor_plugin.h @@ -38,6 +38,7 @@ class HBoxContainer; class MenuButton; +class ConfirmationDialog; class Path3DGizmo : public EditorNode3DGizmo { GDCLASS(Path3DGizmo, EditorNode3DGizmo); @@ -118,8 +119,11 @@ class Path3DEditorPlugin : public EditorPlugin { Button *curve_edit_tilt = nullptr; Button *curve_del = nullptr; Button *curve_close = nullptr; + Button *curve_clear_points = nullptr; MenuButton *handle_menu = nullptr; + ConfirmationDialog *clear_points_dialog = nullptr; + float disk_size = 0.8; enum Mode { @@ -142,6 +146,11 @@ class Path3DEditorPlugin : public EditorPlugin { bool mirror_handle_angle; bool mirror_handle_length; + void _confirm_clear_points(); + void _clear_points(); + void _clear_curve_points(); + void _restore_curve_points(const PackedVector3Array &p_points); + enum HandleOption { HANDLE_OPTION_ANGLE, HANDLE_OPTION_LENGTH diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 2b54acef7531..8926eb1d511a 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -2029,6 +2029,10 @@ Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const { return nearest; } +PackedVector3Array Curve3D::get_points() const { + return _get_data()["points"]; +} + real_t Curve3D::get_closest_offset(const Vector3 &p_to_point) const { // Brute force method. diff --git a/scene/resources/curve.h b/scene/resources/curve.h index e085dfedbdcf..6da337a93f8c 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -345,6 +345,7 @@ class Curve3D : public Resource { PackedVector3Array get_baked_up_vectors() const; Vector3 get_closest_point(const Vector3 &p_to_point) const; real_t get_closest_offset(const Vector3 &p_to_point) const; + PackedVector3Array get_points() const; PackedVector3Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; // Useful for display. PackedVector3Array tessellate_even_length(int p_max_stages = 5, real_t p_length = 0.2) const; // Useful for baking.