diff options
author | Ben Hickling <ben.hickling@aria-networks.com> | 2018-05-01 11:13:29 +0100 |
---|---|---|
committer | Ben Hickling <ben.hickling@aria-networks.com> | 2018-05-09 14:01:04 +0100 |
commit | 31b6776f116272592bc302fbb824a92e60fdb527 (patch) | |
tree | 555d62e977ee8c0d1438b8a79612ee94b710b742 /editor | |
parent | 0f930f831410bc57d0e975b4ab73715d0d034735 (diff) |
Added option to 2D and 3D curve editor to mirror curve tangent handles both in angle and/or length
Diffstat (limited to 'editor')
-rw-r--r-- | editor/plugins/path_2d_editor_plugin.cpp | 55 | ||||
-rw-r--r-- | editor/plugins/path_2d_editor_plugin.h | 12 | ||||
-rw-r--r-- | editor/plugins/path_editor_plugin.cpp | 65 | ||||
-rw-r--r-- | editor/plugins/path_editor_plugin.h | 19 |
4 files changed, 148 insertions, 3 deletions
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 5ec42b07aa..33e182faef 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -109,6 +109,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { action_point = i; moving_from = curve->get_point_out(i); moving_screen_from = gpoint; + orig_in_length = curve->get_point_in(action_point).length(); return true; } else if (dist_to_p_in < grab_threshold && i > 0) { @@ -116,6 +117,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { action_point = i; moving_from = curve->get_point_in(i); moving_screen_from = gpoint; + orig_out_length = curve->get_point_out(action_point).length(); return true; } } @@ -205,6 +207,11 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { undo_redo->create_action(TTR("Move In-Control in Curve")); undo_redo->add_do_method(curve.ptr(), "set_point_in", action_point, new_pos); undo_redo->add_undo_method(curve.ptr(), "set_point_in", action_point, moving_from); + + if (mirror_handle_angle) { + undo_redo->add_do_method(curve.ptr(), "set_point_out", action_point, mirror_handle_length ? -new_pos : (-new_pos.normalized() * orig_out_length)); + undo_redo->add_undo_method(curve.ptr(), "set_point_out", action_point, mirror_handle_length ? -moving_from : (-moving_from.normalized() * orig_out_length)); + } undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); undo_redo->commit_action(); @@ -216,6 +223,11 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { undo_redo->create_action(TTR("Move Out-Control in Curve")); undo_redo->add_do_method(curve.ptr(), "set_point_out", action_point, new_pos); undo_redo->add_undo_method(curve.ptr(), "set_point_out", action_point, moving_from); + + if (mirror_handle_angle) { + undo_redo->add_do_method(curve.ptr(), "set_point_in", action_point, mirror_handle_length ? -new_pos : (-new_pos.normalized() * orig_in_length)); + undo_redo->add_undo_method(curve.ptr(), "set_point_in", action_point, mirror_handle_length ? -moving_from : (-moving_from.normalized() * orig_in_length)); + } undo_redo->add_do_method(canvas_item_editor->get_viewport_control(), "update"); undo_redo->add_undo_method(canvas_item_editor->get_viewport_control(), "update"); undo_redo->commit_action(); @@ -255,10 +267,16 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) { case ACTION_MOVING_IN: { curve->set_point_in(action_point, new_pos); + + if (mirror_handle_angle) + curve->set_point_out(action_point, mirror_handle_length ? -new_pos : (-new_pos.normalized() * orig_out_length)); } break; case ACTION_MOVING_OUT: { curve->set_point_out(action_point, new_pos); + + if (mirror_handle_angle) + curve->set_point_in(action_point, mirror_handle_length ? -new_pos : (-new_pos.normalized() * orig_in_length)); } break; } @@ -342,6 +360,7 @@ void Path2DEditor::_bind_methods() { //ClassDB::bind_method(D_METHOD("_menu_option"),&Path2DEditor::_menu_option); ClassDB::bind_method(D_METHOD("_node_visibility_changed"), &Path2DEditor::_node_visibility_changed); ClassDB::bind_method(D_METHOD("_mode_selected"), &Path2DEditor::_mode_selected); + ClassDB::bind_method(D_METHOD("_handle_option_pressed"), &Path2DEditor::_handle_option_pressed); } void Path2DEditor::_mode_selected(int p_mode) { @@ -396,11 +415,33 @@ void Path2DEditor::_mode_selected(int p_mode) { mode = Mode(p_mode); } +void Path2DEditor::_handle_option_pressed(int p_option) { + + PopupMenu *pm; + pm = handle_menu->get_popup(); + + switch (p_option) { + case HANDLE_OPTION_ANGLE: { + bool is_checked = pm->is_item_checked(HANDLE_OPTION_ANGLE); + mirror_handle_angle = !is_checked; + pm->set_item_checked(HANDLE_OPTION_ANGLE, mirror_handle_angle); + pm->set_item_disabled(HANDLE_OPTION_LENGTH, !mirror_handle_angle); + } break; + case HANDLE_OPTION_LENGTH: { + bool is_checked = pm->is_item_checked(HANDLE_OPTION_LENGTH); + mirror_handle_length = !is_checked; + pm->set_item_checked(HANDLE_OPTION_LENGTH, mirror_handle_length); + } break; + } +} + Path2DEditor::Path2DEditor(EditorNode *p_editor) { canvas_item_editor = NULL; editor = p_editor; undo_redo = editor->get_undo_redo(); + mirror_handle_angle = true; + mirror_handle_length = true; mode = MODE_EDIT; action = ACTION_NONE; @@ -444,6 +485,20 @@ Path2DEditor::Path2DEditor(EditorNode *p_editor) { curve_close->set_tooltip(TTR("Close Curve")); curve_close->connect("pressed", this, "_mode_selected", varray(ACTION_CLOSE)); base_hb->add_child(curve_close); + + PopupMenu *menu; + + handle_menu = memnew(MenuButton); + handle_menu->set_text(TTR("Options")); + base_hb->add_child(handle_menu); + + menu = handle_menu->get_popup(); + menu->add_check_item(TTR("Mirror Handle Angles")); + menu->set_item_checked(HANDLE_OPTION_ANGLE, mirror_handle_angle); + menu->add_check_item(TTR("Mirror Handle Lengths")); + menu->set_item_checked(HANDLE_OPTION_LENGTH, mirror_handle_length); + menu->connect("id_pressed", this, "_handle_option_pressed"); + base_hb->hide(); curve_edit->set_pressed(true); diff --git a/editor/plugins/path_2d_editor_plugin.h b/editor/plugins/path_2d_editor_plugin.h index c92a696967..1e3955f84f 100644 --- a/editor/plugins/path_2d_editor_plugin.h +++ b/editor/plugins/path_2d_editor_plugin.h @@ -69,6 +69,15 @@ class Path2DEditor : public HBoxContainer { ToolButton *curve_edit_curve; ToolButton *curve_del; ToolButton *curve_close; + MenuButton *handle_menu; + + bool mirror_handle_angle; + bool mirror_handle_length; + + enum HandleOption { + HANDLE_OPTION_ANGLE, + HANDLE_OPTION_LENGTH + }; enum Action { @@ -82,8 +91,11 @@ class Path2DEditor : public HBoxContainer { int action_point; Point2 moving_from; Point2 moving_screen_from; + float orig_in_length; + float orig_out_length; void _mode_selected(int p_mode); + void _handle_option_pressed(int p_option); void _node_visibility_changed(); friend class Path2DEditorPlugin; diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp index 6dde639c54..72a8b55a52 100644 --- a/editor/plugins/path_editor_plugin.cpp +++ b/editor/plugins/path_editor_plugin.cpp @@ -128,11 +128,22 @@ void PathSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_p if (p.intersects_ray(ray_from, ray_dir, &inters)) { + if (!PathEditorPlugin::singleton->is_handle_clicked()) { + orig_in_length = c->get_point_in(idx).length(); + orig_out_length = c->get_point_out(idx).length(); + PathEditorPlugin::singleton->set_handle_clicked(true); + } + Vector3 local = gi.xform(inters) - base; if (t == 0) { c->set_point_in(idx, local); + + if (PathEditorPlugin::singleton->mirror_angle_enabled()) + c->set_point_out(idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -local : (-local.normalized() * orig_out_length)); } else { c->set_point_out(idx, local); + if (PathEditorPlugin::singleton->mirror_angle_enabled()) + c->set_point_in(idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -local : (-local.normalized() * orig_in_length)); } } } @@ -165,8 +176,6 @@ void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p int idx = p_idx / 2; int t = p_idx % 2; - Vector3 ofs; - if (t == 0) { if (p_cancel) { c->set_point_in(p_idx, p_restore); @@ -176,6 +185,11 @@ void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p ur->create_action(TTR("Set Curve In Position")); ur->add_do_method(c.ptr(), "set_point_in", idx, c->get_point_in(idx)); ur->add_undo_method(c.ptr(), "set_point_in", idx, p_restore); + + if (PathEditorPlugin::singleton->mirror_angle_enabled()) { + ur->add_do_method(c.ptr(), "set_point_out", idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -c->get_point_in(idx) : (-c->get_point_in(idx).normalized() * orig_out_length)); + ur->add_undo_method(c.ptr(), "set_point_out", idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -static_cast<Vector3>(p_restore) : (-static_cast<Vector3>(p_restore).normalized() * orig_out_length)); + } ur->commit_action(); } else { @@ -188,6 +202,11 @@ void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p ur->create_action(TTR("Set Curve Out Position")); ur->add_do_method(c.ptr(), "set_point_out", idx, c->get_point_out(idx)); ur->add_undo_method(c.ptr(), "set_point_out", idx, p_restore); + + if (PathEditorPlugin::singleton->mirror_angle_enabled()) { + ur->add_do_method(c.ptr(), "set_point_in", idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -c->get_point_out(idx) : (-c->get_point_out(idx).normalized() * orig_in_length)); + ur->add_undo_method(c.ptr(), "set_point_in", idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -static_cast<Vector3>(p_restore) : (-static_cast<Vector3>(p_restore).normalized() * orig_in_length)); + } ur->commit_action(); } } @@ -291,6 +310,9 @@ bool PathEditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref<Inp Point2 mbpos(mb->get_position().x, mb->get_position().y); + if (!mb->is_pressed()) + set_handle_clicked(false); + if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb->get_control()))) { //click into curve, break it down PoolVector<Vector3> v3a = c->tessellate(); @@ -459,6 +481,7 @@ void PathEditorPlugin::make_visible(bool p_visible) { curve_edit->show(); curve_del->show(); curve_close->show(); + handle_menu->show(); sep->show(); } else { @@ -466,6 +489,7 @@ void PathEditorPlugin::make_visible(bool p_visible) { curve_edit->hide(); curve_del->hide(); curve_close->hide(); + handle_menu->hide(); sep->hide(); { @@ -495,6 +519,26 @@ void PathEditorPlugin::_close_curve() { c->add_point(c->get_point_position(0), c->get_point_in(0), c->get_point_out(0)); } +void PathEditorPlugin::_handle_option_pressed(int p_option) { + + PopupMenu *pm; + pm = handle_menu->get_popup(); + + switch (p_option) { + case HANDLE_OPTION_ANGLE: { + bool is_checked = pm->is_item_checked(HANDLE_OPTION_ANGLE); + mirror_handle_angle = !is_checked; + pm->set_item_checked(HANDLE_OPTION_ANGLE, mirror_handle_angle); + pm->set_item_disabled(HANDLE_OPTION_LENGTH, !mirror_handle_angle); + } break; + case HANDLE_OPTION_LENGTH: { + bool is_checked = pm->is_item_checked(HANDLE_OPTION_LENGTH); + mirror_handle_length = !is_checked; + pm->set_item_checked(HANDLE_OPTION_LENGTH, mirror_handle_length); + } break; + } +} + void PathEditorPlugin::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { @@ -510,6 +554,7 @@ void PathEditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("_mode_changed"), &PathEditorPlugin::_mode_changed); ClassDB::bind_method(D_METHOD("_close_curve"), &PathEditorPlugin::_close_curve); + ClassDB::bind_method(D_METHOD("_handle_option_pressed"), &PathEditorPlugin::_handle_option_pressed); } PathEditorPlugin *PathEditorPlugin::singleton = NULL; @@ -519,6 +564,8 @@ PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) { path = NULL; editor = p_node; singleton = this; + mirror_handle_angle = true; + mirror_handle_length = true; path_material = Ref<SpatialMaterial>(memnew(SpatialMaterial)); path_material->set_albedo(Color(0.5, 0.5, 1.0, 0.8)); @@ -567,6 +614,20 @@ PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) { curve_close->set_tooltip(TTR("Close Curve")); SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_close); + PopupMenu *menu; + + handle_menu = memnew(MenuButton); + handle_menu->set_text(TTR("Options")); + handle_menu->hide(); + SpatialEditor::get_singleton()->add_control_to_menu_panel(handle_menu); + + menu = handle_menu->get_popup(); + menu->add_check_item(TTR("Mirror Handle Angles")); + menu->set_item_checked(HANDLE_OPTION_ANGLE, mirror_handle_angle); + menu->add_check_item(TTR("Mirror Handle Lengths")); + menu->set_item_checked(HANDLE_OPTION_LENGTH, mirror_handle_length); + menu->connect("id_pressed", this, "_handle_option_pressed"); + curve_edit->set_pressed(true); /* collision_polygon_editor = memnew( PathEditor(p_node) ); diff --git a/editor/plugins/path_editor_plugin.h b/editor/plugins/path_editor_plugin.h index 6d5f07f729..52dfb78b61 100644 --- a/editor/plugins/path_editor_plugin.h +++ b/editor/plugins/path_editor_plugin.h @@ -1,4 +1,4 @@ -/*************************************************************************/ +/*************************************************************************/ /* path_editor_plugin.h */ /*************************************************************************/ /* This file is part of: */ @@ -40,6 +40,8 @@ class PathSpatialGizmo : public EditorSpatialGizmo { Path *path; mutable Vector3 original; + mutable float orig_in_length; + mutable float orig_out_length; public: virtual String get_handle_name(int p_idx) const; @@ -60,6 +62,7 @@ class PathEditorPlugin : public EditorPlugin { ToolButton *curve_edit; ToolButton *curve_del; ToolButton *curve_close; + MenuButton *handle_menu; EditorNode *editor; @@ -67,6 +70,15 @@ class PathEditorPlugin : public EditorPlugin { void _mode_changed(int p_idx); void _close_curve(); + void _handle_option_pressed(int p_option); + bool handle_clicked; + bool mirror_handle_angle; + bool mirror_handle_length; + + enum HandleOption { + HANDLE_OPTION_ANGLE, + HANDLE_OPTION_LENGTH + }; protected: void _notification(int p_what); @@ -88,6 +100,11 @@ public: virtual bool handles(Object *p_object) const; virtual void make_visible(bool p_visible); + bool mirror_angle_enabled() { return mirror_handle_angle; } + bool mirror_length_enabled() { return mirror_handle_length; } + bool is_handle_clicked() { return handle_clicked; } + void set_handle_clicked(bool clicked) { handle_clicked = clicked; } + PathEditorPlugin(EditorNode *p_node); ~PathEditorPlugin(); }; |