snapping, straight lines, and merge drawn points to list for auto draw
This commit is contained in:
@@ -790,6 +790,70 @@ AutomationTimeAxisView::build_display_menu ()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AutomationTimeAxisView::merge_drawn_line (DrawnPoints const & points)
|
||||
{
|
||||
if (points.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_line) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<AutomationList> list = _line->the_list ();
|
||||
|
||||
if (list->in_write_pass()) {
|
||||
/* do not allow the GUI to add automation events during an
|
||||
automation write pass.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
XMLNode& before = list->get_state();
|
||||
std::list<Selectable*> results;
|
||||
bool failed = false;
|
||||
Temporal::timepos_t earliest = timepos_t::max (points.front().when.time_domain());
|
||||
Temporal::timepos_t latest = timepos_t::zero (points.front().when.time_domain());
|
||||
|
||||
for (auto const & dp : points) {
|
||||
|
||||
/* compute vertical fractional position */
|
||||
double y = 1.0 - (dp.y / _line->height());
|
||||
std::cerr << "merge point at fract " << y << std::endl;
|
||||
/* map using line */
|
||||
_line->view_to_model_coord_y (y);
|
||||
|
||||
if (!list->editor_add (dp.when, y, false)) {
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
earliest = std::min (earliest, dp.when);
|
||||
latest = std::max (latest, dp.when);
|
||||
}
|
||||
|
||||
list->thin (1.0);
|
||||
|
||||
if (_control->automation_state () == ARDOUR::Off) {
|
||||
set_automation_state (ARDOUR::Play);
|
||||
}
|
||||
|
||||
if (UIConfiguration::instance().get_automation_edit_cancels_auto_hide () && _control == _session->recently_touched_controllable ()) {
|
||||
RouteTimeAxisView::signal_ctrl_touched (false);
|
||||
}
|
||||
|
||||
|
||||
XMLNode& after = list->get_state();
|
||||
_editor.begin_reversible_command (_("draw automation"));
|
||||
_session->add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after));
|
||||
|
||||
_line->get_selectables (earliest, latest, 0.0, 1.0, results);
|
||||
_editor.get_selection ().set (results);
|
||||
|
||||
_editor.commit_reversible_command ();
|
||||
_session->set_dirty ();
|
||||
}
|
||||
|
||||
void
|
||||
AutomationTimeAxisView::add_automation_event (GdkEvent* event, timepos_t const & pos, double y, bool with_guard_points)
|
||||
{
|
||||
|
||||
@@ -147,6 +147,15 @@ public:
|
||||
|
||||
void set_selected_regionviews (RegionSelection&);
|
||||
|
||||
struct DrawnPoint {
|
||||
DrawnPoint (Temporal::timepos_t w, double v) : when (w), y (v) {}
|
||||
Temporal::timepos_t when;
|
||||
double y;
|
||||
};
|
||||
|
||||
typedef std::vector<DrawnPoint> DrawnPoints;
|
||||
void merge_drawn_line (DrawnPoints const &);
|
||||
|
||||
protected:
|
||||
/* Note that for MIDI controller "automation" (in regions), all of these
|
||||
* may be set. In this case, _automatable is likely _route so the
|
||||
|
||||
@@ -7280,24 +7280,54 @@ AutomationDrawDrag::motion (GdkEvent* ev, bool first_move)
|
||||
edge_x = grab_x ();
|
||||
}
|
||||
|
||||
timepos_t pos (_drags->current_pointer_time ());
|
||||
_editor->snap_to_with_modifier (pos, ev);
|
||||
double const pointer_x = _editor->time_to_pixel (pos);
|
||||
|
||||
ArdourCanvas::Rect r = base_rect.item_to_canvas (base_rect.get());
|
||||
|
||||
double x = ev->motion.x - r.x0;
|
||||
double x = pointer_x - r.x0;
|
||||
double y = ev->motion.y - r.y0;
|
||||
|
||||
x = std::max (0., x);
|
||||
y = std::max (0., std::min (r.height(), y));
|
||||
|
||||
bool add_point = false;
|
||||
bool pop_point = false;
|
||||
|
||||
if (direction > 0) {
|
||||
if ((ev->motion.x > edge_x) || (ev->motion.x == edge_x && ev->motion.y != last_pointer_y())) {
|
||||
dragging_line->add_point (ArdourCanvas::Duple (x, y));
|
||||
edge_x = x;
|
||||
if ((pointer_x > edge_x) || (pointer_x == edge_x && ev->motion.y != last_pointer_y())) {
|
||||
|
||||
bool line = Keyboard::modifier_state_equals (ev->motion.state, Keyboard::PrimaryModifier);
|
||||
|
||||
if (line && dragging_line->get().size() > 1) {
|
||||
pop_point = true;
|
||||
}
|
||||
add_point = true;
|
||||
}
|
||||
|
||||
} else if (direction < 0) {
|
||||
if ((ev->motion.x < edge_x) || (ev->motion.x == edge_x && ev->motion.y != last_pointer_y())) {
|
||||
dragging_line->add_point (ArdourCanvas::Duple (x, y));
|
||||
edge_x = x;
|
||||
if ((pointer_x < edge_x) || (pointer_x == edge_x && ev->motion.y != last_pointer_y())) {
|
||||
|
||||
bool line = Keyboard::modifier_state_equals (ev->motion.state, Keyboard::PrimaryModifier);
|
||||
|
||||
if (line && dragging_line->get().size() > 1) {
|
||||
pop_point = true;
|
||||
}
|
||||
add_point = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (pop_point) {
|
||||
dragging_line->pop_back();
|
||||
drawn_points.pop_back ();
|
||||
}
|
||||
|
||||
if (add_point) {
|
||||
dragging_line->add_point (ArdourCanvas::Duple (x, y));
|
||||
drawn_points.push_back (AutomationTimeAxisView::DrawnPoint (pos, y));
|
||||
edge_x = x;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7310,6 +7340,13 @@ AutomationDrawDrag::finished (GdkEvent* event, bool motion_occured)
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
AutomationTimeAxisView* atv = static_cast<AutomationTimeAxisView*>(base_rect.get_data ("trackview"));
|
||||
if (!atv) {
|
||||
return;
|
||||
}
|
||||
|
||||
atv->merge_drawn_line (drawn_points);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -7317,4 +7354,3 @@ AutomationDrawDrag::aborted (bool)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "gtkmm2ext/bindings.h"
|
||||
|
||||
#include "automation_time_axis.h"
|
||||
#include "cursor_context.h"
|
||||
#include "editor_items.h"
|
||||
#include "mouse_cursors.h"
|
||||
@@ -1595,6 +1596,7 @@ private:
|
||||
ArdourCanvas::PolyLine* dragging_line;
|
||||
int direction;
|
||||
int edge_x;
|
||||
AutomationTimeAxisView::DrawnPoints drawn_points;
|
||||
};
|
||||
|
||||
#endif /* __gtk2_ardour_editor_drag_h_ */
|
||||
|
||||
Reference in New Issue
Block a user