From cafbecdaa6599b115ec2cd682e2fcefcb0cc13c5 Mon Sep 17 00:00:00 2001 From: Rodolfo Ribeiro Gomes Date: Dec 13 2019 04:29:26 +0000 Subject: allow to move Graph points along time axis and axis locking with Shift, like Handle dragging does: https://wiki.synfig.org/Handle --- diff --git a/synfig-studio/src/gui/widgets/widget_curves.cpp b/synfig-studio/src/gui/widgets/widget_curves.cpp index a0c3441..1e03ba7 100644 --- a/synfig-studio/src/gui/widgets/widget_curves.cpp +++ b/synfig-studio/src/gui/widgets/widget_curves.cpp @@ -409,10 +409,21 @@ Widget_Curves::on_event(GdkEvent *event) if (pointer_state == POINTER_DRAGGING && !dragging_started_by_key) { guint any_pointer_button = Gdk::BUTTON1_MASK |Gdk::BUTTON2_MASK | Gdk::BUTTON3_MASK; - if ((event->motion.state & any_pointer_button) != 0) - drag_to(pointer_x, pointer_y); - else // If some modal window is called, we lose the button-release event... + if ((event->motion.state & any_pointer_button) == 0) { + // If some modal window is called, we lose the button-release event... cancel_dragging(); + } else { + bool axis_lock = event->motion.state & Gdk::SHIFT_MASK; + if (axis_lock) { + int dx = pointer_x - pointer_tracking_start_x; + int dy = pointer_y - pointer_tracking_start_y; + if (std::abs(dy) > std::abs(dx)) + pointer_x = pointer_tracking_start_x; + else + pointer_y = pointer_tracking_start_y; + } + drag_to(pointer_x, pointer_y); + } } if (pointer_state != POINTER_NONE) { queue_draw(); @@ -548,7 +559,9 @@ Widget_Curves::on_event(GdkEvent *event) return true; } case GDK_KEY_Up: - case GDK_KEY_Down: { + case GDK_KEY_Down: + case GDK_KEY_Left: + case GDK_KEY_Right: { if (pointer_state == POINTER_DRAGGING) { if (dragging_started_by_key) finish_dragging(); @@ -577,8 +590,24 @@ Widget_Curves::on_event(GdkEvent *event) delta_drag(0, delta); return true; } - break; + case GDK_KEY_Left: + case GDK_KEY_Right: { + if (selected_points.size() == 0) + break; + if (pointer_state != POINTER_DRAGGING) { + start_dragging(selected_points.front()); + dragging_started_by_key = true; + } + int delta = time_plot_data->k/canvas_interface->get_canvas()->rend_desc().get_frame_rate(); + if (event->key.state & GDK_SHIFT_MASK) + delta *= 10; + if (event->key.keyval == GDK_KEY_Left) + delta = -delta; + delta_drag(delta, 0); + return true; } + break; + } } default: break; @@ -677,14 +706,21 @@ void Widget_Curves::drag_to(int pointer_x, int pointer_y) int current_y = time_plot_data->get_pixel_y_coord(active_point.get_value(time_plot_data->dt)); int waypoint_dy = current_y - active_point_initial_y; int dy = pointer_dy - waypoint_dy; - delta_drag(0, dy); + + float fps = canvas_interface->get_canvas()->rend_desc().get_frame_rate(); + Time pointer_t = time_plot_data->get_t_from_pixel_coord(pointer_x).round(fps); + Time current_t = active_point.time_point.get_time(); + int dx = (pointer_t - current_t) * time_plot_data->k; + delta_drag(dx, dy); } void Widget_Curves::delta_drag(int dx, int dy) { - for (auto point : selected_points) { + // Move value + for (const auto &point : selected_points) { if (!point.is_draggable()) continue; + Time time = point.time_point.get_time(); Real v = point.get_value(time_plot_data->dt); @@ -707,6 +743,31 @@ void Widget_Curves::delta_drag(int dx, int dy) canvas_interface->waypoint_set_value_node(value_node, waypoint); } + + // Move along time + if (dx == 0) + return; + std::set> times_to_move; + + const float fps = canvas_interface->get_canvas()->rend_desc().get_frame_rate(); + const Time base_time = active_point.time_point.get_time(); + const Time next_time = time_plot_data->get_t_from_pixel_coord(time_plot_data->get_pixel_t_coord(base_time) + dx).round(fps); + const Time deltatime = next_time - base_time; + + if (deltatime != 0) { + for (auto &point : selected_points) { + const ValueDesc &value_desc = point.curve_it->value_desc; + const Time &time = point.time_point.get_time(); + std::pair meta_data(value_desc, time); + if (times_to_move.find(meta_data) == times_to_move.end()) { + times_to_move.insert(meta_data); + canvas_interface->waypoint_move(value_desc, time, deltatime); + } + point.time_point = TimePoint(Time(time+deltatime).round(fps)); + } + active_point.time_point = next_time; + } + queue_draw(); } diff --git a/synfig-studio/src/synfigapp/canvasinterface.cpp b/synfig-studio/src/synfigapp/canvasinterface.cpp index b7ee733..1bf03e3 100644 --- a/synfig-studio/src/synfigapp/canvasinterface.cpp +++ b/synfig-studio/src/synfigapp/canvasinterface.cpp @@ -1154,6 +1154,30 @@ void CanvasInterface::waypoint_set_value_node(ValueNode::Handle value_node, cons get_ui_interface()->error(_("Action Failed.")); } +void CanvasInterface::waypoint_move(const ValueDesc& value_desc, const Time& time, const Time& deltatime) +{ + Action::Handle action(Action::create("TimepointsMove")); + + assert(action); + if(!action) + return; + + action->set_param("canvas", get_canvas()); + action->set_param("canvas_interface", this); + if (value_desc.get_value_type() == type_canvas && !getenv("SYNFIG_SHOW_CANVAS_PARAM_WAYPOINTS")) { + action->set_param("addcanvas", value_desc.get_value().get(Canvas::Handle())); + } else { + action->set_param("addvaluedesc", value_desc); + } + + action->set_param("addtime", time); + + action->set_param("deltatime", deltatime); + + if(!get_instance()->perform_action(action)) + get_ui_interface()->error(_("Action Failed.")); +} + void CanvasInterface::waypoint_duplicate(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint) { diff --git a/synfig-studio/src/synfigapp/canvasinterface.h b/synfig-studio/src/synfigapp/canvasinterface.h index 675181c..d22efca 100644 --- a/synfig-studio/src/synfigapp/canvasinterface.h +++ b/synfig-studio/src/synfigapp/canvasinterface.h @@ -315,6 +315,7 @@ public: bool resize_image = false ); void waypoint_set_value_node(synfig::ValueNode::Handle value_node, const synfig::Waypoint& waypoint); + void waypoint_move(const ValueDesc& value_desc, const synfig::Time& time, const synfig::Time& deltatime); void waypoint_duplicate(synfigapp::ValueDesc value_desc,synfig::Waypoint waypoint); void waypoint_duplicate(synfig::ValueNode::Handle value_node,synfig::Waypoint waypoint);