first steps towards improving straight line drags for velocity

This commit is contained in:
Paul Davis 2023-10-26 22:31:45 -06:00
parent 68f55d62d0
commit 91fbb1c65b
7 changed files with 112 additions and 13 deletions

View File

@ -7243,6 +7243,8 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::FreehandLineDrag (Editor* edito
, edge_x (0)
, did_snap (false)
, line_break_pending (false)
, line_start_x (-1)
, line_start_y (-1)
{
DEBUG_TRACE (DEBUG::Drags, "New FreehandLinDrag\n");
}
@ -7305,6 +7307,11 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
double x = pointer_x - r.x0;
double y = ev->motion.y - r.y0;
if (drawn_points.empty()) {
line_start_x = x;
line_start_y = y;
}
if (x < 0) {
dragging_line->clear ();
drawn_points.clear ();
@ -7319,12 +7326,12 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
bool add_point = false;
bool pop_point = false;
const bool line = Keyboard::modifier_state_equals (ev->motion.state, Keyboard::PrimaryModifier);
const bool straight_line = Keyboard::modifier_state_equals (ev->motion.state, Keyboard::PrimaryModifier);
if (direction > 0) {
if (x < r.width() && (line || (pointer_x > edge_x) || (pointer_x == edge_x && ev->motion.y != last_pointer_y()))) {
if (x < r.width() && (straight_line || (pointer_x > edge_x) || (pointer_x == edge_x && ev->motion.y != last_pointer_y()))) {
if (line && dragging_line->get().size() > 1) {
if (straight_line && dragging_line->get().size() > 1) {
pop_point = true;
}
@ -7333,9 +7340,9 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
} else if (direction < 0) {
if (x >= 0. && (line || (pointer_x < edge_x) || (pointer_x == edge_x && ev->motion.y != last_pointer_y()))) {
if (x >= 0. && (straight_line || (pointer_x < edge_x) || (pointer_x == edge_x && ev->motion.y != last_pointer_y()))) {
if (line && dragging_line->get().size() > 1) {
if (straight_line && dragging_line->get().size() > 1) {
pop_point = true;
}
@ -7343,6 +7350,13 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
}
}
if (straight_line) {
if (dragging_line->get().size() > 1) {
pop_point = true;
}
add_point = true;
}
bool child_call = false;
if (pop_point) {
@ -7364,7 +7378,11 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
}
if (child_call) {
point_added (ArdourCanvas::Duple (pointer_x, y), base_rect, first_move ? -1 : edge_x);
if (straight_line && !first_move) {
line_extended (ArdourCanvas::Duple (line_start_x, line_start_y), ArdourCanvas::Duple (pointer_x, y), base_rect, first_move ? -1 : edge_x);
} else {
point_added (ArdourCanvas::Duple (pointer_x, y), base_rect, first_move ? -1 : edge_x);
}
}
if (add_point) {
@ -7483,6 +7501,12 @@ VelocityLineDrag::point_added (Duple const & d, ArdourCanvas::Rectangle const &
drag_did_change |= grv->line_draw_motion (d, r, last_x);
}
void
VelocityLineDrag::line_extended (Duple const & from, Duple const & to, ArdourCanvas::Rectangle const & r, double last_x)
{
drag_did_change |= grv->line_extended (from, to, r, last_x);
}
void
VelocityLineDrag::finished (GdkEvent* event, bool motion_occured)
{

View File

@ -1582,6 +1582,9 @@ class FreehandLineDrag : public Drag
void finished (GdkEvent*, bool);
bool mid_drag_key_event (GdkEventKey*);
virtual void point_added (ArdourCanvas::Duple const & d, ArdourCanvas::Rectangle const & r, double last_x) {}
virtual void line_extended (ArdourCanvas::Duple const & from, ArdourCanvas::Duple const & to, ArdourCanvas::Rectangle const & r, double last_x) {
point_added (to, r, last_x);
}
protected:
ArdourCanvas::Item* parent; /* we do not own this. If null, use base_rect as the parent */
@ -1592,6 +1595,8 @@ class FreehandLineDrag : public Drag
bool did_snap;
bool line_break_pending;
OrderedPointList drawn_points;
ArdourCanvas::Coord line_start_x;
ArdourCanvas::Coord line_start_y;
void maybe_add_point (GdkEvent*, Temporal::timepos_t const &, bool first_move);
};
@ -1616,6 +1621,7 @@ class VelocityLineDrag : public FreehandLineDrag<Evoral::ControlList::OrderedPoi
void finished (GdkEvent*, bool);
void aborted (bool);
void point_added (ArdourCanvas::Duple const & d, ArdourCanvas::Rectangle const & r, double last_x);
void line_extended (ArdourCanvas::Duple const & from, ArdourCanvas::Duple const & to, ArdourCanvas::Rectangle const & r, double last_x);
private:
VelocityGhostRegion* grv;

View File

@ -3447,6 +3447,34 @@ MidiRegionView::end_drag_edit (bool apply)
}
}
bool
MidiRegionView::set_velocities_for_notes (std::vector<NoteBase*> notes, std::vector<int> velocities)
{
assert (notes.size() == velocities.size());
/* Does not use selection, used when drawing/dragging in velocity lane */
bool changed = false;
auto notei = notes.begin();
auto veloi = velocities.begin();
while (notei != notes.end()) {
int delta = (*veloi) - (*notei)->note()->velocity();
if (delta) {
changed = true;
change_note_velocity (*notei, delta, true);
}
++notei;
++veloi;
}
return changed;
}
bool
MidiRegionView::set_velocity_for_notes (std::vector<NoteBase*> notes, int velocity)
{

View File

@ -185,6 +185,7 @@ public:
void end_drag_edit (bool apply);
void display_model(std::shared_ptr<ARDOUR::MidiModel> model);
std::shared_ptr<ARDOUR::MidiModel> model() const { return _model; }
/* note_diff commands should start here; this initiates an undo record */
void start_note_diff_command (std::string name = "midi edit");
@ -295,6 +296,7 @@ public:
void change_velocities (bool up, bool fine, bool allow_smush, bool all_together);
void set_velocity (NoteBase* primary, int velocity);
bool set_velocity_for_notes (std::vector<NoteBase*> notes, int velocity);
bool set_velocities_for_notes (std::vector<NoteBase*> notes, std::vector<int> velocities);
void transpose (bool up, bool fine, bool allow_smush);
void nudge_notes (bool forward, bool fine);
void channel_edit ();

View File

@ -132,7 +132,7 @@ class NoteBase : public sigc::trackable
/// hue circle divided into 16 equal-looking parts, courtesy Thorsten Wilms
static const uint32_t midi_channel_colors[16];
bool mouse_near_ends () const;
virtual bool big_enough_to_trim () const;

View File

@ -86,14 +86,51 @@ VelocityGhostRegion::line_draw_motion (ArdourCanvas::Duple const & d, ArdourCanv
lollis_between (d.x, last_x, affected_lollis);
}
bool ret = false;
if (!affected_lollis.empty()) {
int velocity = y_position_to_velocity (r.height() - (r.y1() - d.y));
ret = mrv->set_velocity_for_notes (affected_lollis, velocity);
mrv->mid_drag_edit ();
if (affected_lollis.empty()) {
return false;
}
int velocity = y_position_to_velocity (r.height() - (r.y1() - d.y));
bool ret = mrv->set_velocity_for_notes (affected_lollis, velocity);
mrv->mid_drag_edit ();
return ret;
}
bool
VelocityGhostRegion::line_extended (ArdourCanvas::Duple const & from, ArdourCanvas::Duple const & to, ArdourCanvas::Rectangle const & r, double last_x)
{
std::vector<NoteBase*> affected_lollis;
lollis_between (from.x, to.x, affected_lollis);
if (affected_lollis.empty()) {
return false;
}
if (to.x == from.x) {
/* no x-axis motion */
return false;
}
double slope = (to.y - from.y) / (to.x - from.x);
std::vector<int> velocities;
for (auto const & nb : affected_lollis) {
ArdourCanvas::Item* it = nb->item();
ArdourCanvas::Duple pos = it->item_to_canvas (ArdourCanvas::Duple (nb->x0(), 0.0));
int y = from.y + (slope * (pos.x - from.x));
int velocity = y_position_to_velocity (r.height() - (r.y1() - y));
velocities.push_back (velocity);
}
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (&parent_rv);
bool ret = mrv->set_velocities_for_notes (affected_lollis, velocities);
mrv->mid_drag_edit ();
model_changed ();
return ret;
}

View File

@ -50,6 +50,8 @@ public:
void set_selected (bool);
bool line_draw_motion (ArdourCanvas::Duple const & d, ArdourCanvas::Rectangle const & r, double last_x);
bool line_extended (ArdourCanvas::Duple const & from, ArdourCanvas::Duple const & to, ArdourCanvas::Rectangle const & r, double last_x);
void start_line_drag ();
void end_line_drag (bool did_change);