diff --git a/synfig-studio/src/gui/widgets/widget_curves.cpp b/synfig-studio/src/gui/widgets/widget_curves.cpp index d5abb5d..ab15eb3 100644 --- a/synfig-studio/src/gui/widgets/widget_curves.cpp +++ b/synfig-studio/src/gui/widgets/widget_curves.cpp @@ -224,9 +224,7 @@ struct Widget_Curves::CurveStruct: sigc::trackable Widget_Curves::Widget_Curves(): range_adjustment(Gtk::Adjustment::create(-1.0, -2.0, 2.0, 0.1, 0.1, 2)), - waypoint_edge_length(16), - hovered_point(nullptr), - hovered_curve(-1) + waypoint_edge_length(16) { set_size_request(64, 64); @@ -261,8 +259,7 @@ Widget_Curves::clear() { value_desc_changed.pop_back(); } curve_list.clear(); - hovered_curve = -1; - hovered_point = nullptr; + hovered_point.invalidate(); } void @@ -270,8 +267,7 @@ Widget_Curves::refresh() { for(std::list::iterator i = curve_list.begin(); i != curve_list.end(); ++i) i->clear_all_values(); - hovered_curve = -1; - hovered_point = nullptr; + hovered_point.invalidate(); queue_draw(); } @@ -345,36 +341,14 @@ Widget_Curves::on_event(GdkEvent *event) break; } case GDK_MOTION_NOTIFY: { - auto previous_hovered_point = hovered_point; - hovered_point = nullptr; - for(std::list::iterator curve_it = curve_list.begin(); curve_it != curve_list.end(); ++curve_it) { - int channels = (int)curve_it->channels.size(); - int pointer_x, pointer_y; - get_pointer(pointer_x, pointer_y); - - WaypointRenderer::foreach_visible_waypoint(curve_it->value_desc, *time_plot_data, - [&](const synfig::TimePoint &tp, const synfig::Time &t, void *_data) -> bool - { - int px = time_plot_data->get_pixel_t_coord(t); - for (int c = 0; c < channels; ++c) { - Real y = curve_it->get_value(c, t, time_plot_data->dt); - int py = time_plot_data->get_pixel_y_coord(y); - - if (pointer_x > px - waypoint_edge_length/2 && pointer_x <= px + waypoint_edge_length/2) { - if (pointer_y > py - waypoint_edge_length/2 && pointer_y <= py + waypoint_edge_length/2) { - hovered_point = &tp; - hovered_curve = c; - return true; - } - } - } - return false; - }); + auto previous_hovered_point = hovered_point.time_point; + hovered_point.invalidate(); - if (hovered_point) - break; - } - if (previous_hovered_point != hovered_point) + int pointer_x, pointer_y; + get_pointer(pointer_x, pointer_y); + find_channelpoint_at_position(pointer_x, pointer_y, hovered_point); + + if (previous_hovered_point != hovered_point.time_point) queue_draw(); } default: @@ -384,6 +358,40 @@ Widget_Curves::on_event(GdkEvent *event) return Gtk::DrawingArea::on_event(event); } +bool Widget_Curves::find_channelpoint_at_position(int pos_x, int pos_y, ChannelPoint & cp) +{ + cp.invalidate(); + bool found = false; + for(auto curve_it = curve_list.begin(); curve_it != curve_list.end(); ++curve_it) { + int channels = (int)curve_it->channels.size(); + + WaypointRenderer::foreach_visible_waypoint(curve_it->value_desc, *time_plot_data, + [&](const synfig::TimePoint &tp, const synfig::Time &t, void *data) -> bool + { + int px = time_plot_data->get_pixel_t_coord(t); + for (int c = 0; c < channels; ++c) { + Real y = curve_it->get_value(c, t, time_plot_data->dt); + int py = time_plot_data->get_pixel_y_coord(y); + + if (pos_x > px - waypoint_edge_length/2 && pos_x <= px + waypoint_edge_length/2) { + if (pos_y > py - waypoint_edge_length/2 && pos_y <= py + waypoint_edge_length/2) { + cp.time_point = &tp; + cp.channel_idx = c; + *static_cast(data) = true; + return true; + } + } + } + *static_cast(data) = false; + return false; + }, &found); + + if (found) + break; + } + return found; +} + bool Widget_Curves::on_draw(const Cairo::RefPtr &cr) { @@ -496,7 +504,7 @@ Widget_Curves::on_draw(const Cairo::RefPtr &cr) waypoint_edge_length - 2, waypoint_edge_length - 2); bool selected = false; - bool hover = &tp == hovered_point; + bool hover = &tp == hovered_point.time_point; for (int c = 0; c < channels; ++c) { Real y = curve_it->get_value(c, t, time_plot_data->dt); int py = time_plot_data->get_pixel_y_coord(y); @@ -517,3 +525,29 @@ Widget_Curves::on_draw(const Cairo::RefPtr &cr) return true; } + +Widget_Curves::ChannelPoint::ChannelPoint() +{ + invalidate(); +} + +Widget_Curves::ChannelPoint::ChannelPoint(const TimePoint* time_point, int channel_idx) : + time_point(time_point), channel_idx(channel_idx) +{ +} + +void Widget_Curves::ChannelPoint::invalidate() +{ + time_point = nullptr; + channel_idx = -1; +} + +bool Widget_Curves::ChannelPoint::is_invalid() const +{ + return time_point == nullptr || channel_idx < 0; +} + +bool Widget_Curves::ChannelPoint::operator ==(const Widget_Curves::ChannelPoint& b) const +{ + return time_point == b.time_point && channel_idx == b.channel_idx; +} diff --git a/synfig-studio/src/gui/widgets/widget_curves.h b/synfig-studio/src/gui/widgets/widget_curves.h index 12786b2..213eb44 100644 --- a/synfig-studio/src/gui/widgets/widget_curves.h +++ b/synfig-studio/src/gui/widgets/widget_curves.h @@ -52,6 +52,18 @@ class Widget_Curves: public Gtk::DrawingArea private: struct Channel; struct CurveStruct; + struct ChannelPoint { + const synfig::TimePoint * time_point; + int channel_idx; + + ChannelPoint(); + ChannelPoint(const synfig::TimePoint * time_point, int channel_idx); + void invalidate(); + bool is_invalid() const; + + bool operator ==(const ChannelPoint &b) const; + bool operator !=(const ChannelPoint &b) const {return !operator==(b);} + }; Glib::RefPtr range_adjustment; @@ -63,8 +75,9 @@ private: int waypoint_edge_length; - const synfig::TimePoint * hovered_point; - int hovered_curve; + ChannelPoint hovered_point; + + bool find_channelpoint_at_position(int pos_x, int pos_y, ChannelPoint & cp); public: Widget_Curves();