more improvements to velocity drawing (including straight line)

This commit is contained in:
Paul Davis 2023-10-27 11:49:36 -06:00
parent 91fbb1c65b
commit ef0938a16d
7 changed files with 59 additions and 71 deletions

View File

@ -7308,7 +7308,7 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
double y = ev->motion.y - r.y0;
if (drawn_points.empty()) {
line_start_x = x;
line_start_x = pointer_x;
line_start_y = y;
}

View File

@ -215,6 +215,7 @@ MidiGhostRegion::GhostEvent::GhostEvent (NoteBase* e, ArdourCanvas::Container* g
, item (i)
, is_hit (false)
{
velocity_while_editing = event->note()->velocity();
}
MidiGhostRegion::GhostEvent::GhostEvent (NoteBase* e, ArdourCanvas::Container* g)
@ -235,6 +236,8 @@ MidiGhostRegion::GhostEvent::GhostEvent (NoteBase* e, ArdourCanvas::Container* g
is_hit = true;
}
velocity_while_editing = event->note()->velocity();
CANVAS_DEBUG_NAME (item, "ghost note item");
}

View File

@ -108,6 +108,7 @@ public:
NoteBase* event;
ArdourCanvas::Item* item;
bool is_hit;
int velocity_while_editing;
};
MidiGhostRegion(MidiRegionView& rv,

View File

@ -3402,54 +3402,18 @@ MidiRegionView::begin_drag_edit (std::string const & why)
if (!_selected) {
trackview.editor().get_selection().set (this, true);
}
start_note_diff_command (why);
}
void
MidiRegionView::drag_apply ()
MidiRegionView::end_drag_edit ()
{
if (!_note_diff_command) {
return;
}
bool add_or_remove = _note_diff_command->adds_or_removes();
if (add_or_remove) {
// Mark all selected notes for selection when model reloads
for (auto const & sel : _selection) {
_marked_for_selection.insert (sel->note());
}
}
{
PBD::Unwinder<bool> puw (_select_all_notes_after_add, true);
/*note that we don't use as_commit here, because that would BEGIN a new undo record; we already have one underway*/
_model->apply_diff_command_as_subcommand (*trackview.session(), _note_diff_command);
}
}
void
MidiRegionView::mid_drag_edit ()
{
drag_apply ();
_note_diff_command = _model->new_note_diff_command ();
}
void
MidiRegionView::end_drag_edit (bool apply)
{
if (apply) {
drag_apply ();
trackview.editor().commit_reversible_command ();
_note_diff_command = nullptr;
} else {
abort_note_diff ();
}
}
bool
MidiRegionView::set_velocities_for_notes (std::vector<NoteBase*> notes, std::vector<int> velocities)
{
start_note_diff_command (_("draw velocities"));
assert (notes.size() == velocities.size());
/* Does not use selection, used when drawing/dragging in velocity lane */
@ -3472,6 +3436,11 @@ MidiRegionView::set_velocities_for_notes (std::vector<NoteBase*> notes, std::vec
++veloi;
}
apply_note_diff (true /*subcommand, we don't want this to start a new commit*/, false);
trackview.editor().commit_reversible_command ();
delete _note_diff_command;
_note_diff_command = nullptr;
return changed;
}

View File

@ -181,8 +181,7 @@ public:
void extend_active_notes();
void begin_drag_edit (std::string const & why);
void mid_drag_edit ();
void end_drag_edit (bool apply);
void end_drag_edit ();
void display_model(std::shared_ptr<ARDOUR::MidiModel> model);
std::shared_ptr<ARDOUR::MidiModel> model() const { return _model; }
@ -591,7 +590,6 @@ public:
void model_changed ();
void sync_ghost_selection (NoteBase*);
void drag_apply ();
};

View File

@ -73,8 +73,7 @@ VelocityGhostRegion::~VelocityGhostRegion ()
bool
VelocityGhostRegion::line_draw_motion (ArdourCanvas::Duple const & d, ArdourCanvas::Rectangle const & r, double last_x)
{
std::vector<NoteBase*> affected_lollis;
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (&parent_rv);
std::vector<GhostEvent*> affected_lollis;
if (last_x < 0) {
lollis_close_to_x (d.x, 20., affected_lollis);
@ -91,16 +90,19 @@ VelocityGhostRegion::line_draw_motion (ArdourCanvas::Duple const & d, ArdourCanv
}
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;
for (auto & lolli : affected_lollis) {
lolli->velocity_while_editing = velocity;
set_size_and_position (*lolli);
}
return true;
}
bool
VelocityGhostRegion::line_extended (ArdourCanvas::Duple const & from, ArdourCanvas::Duple const & to, ArdourCanvas::Rectangle const & r, double last_x)
{
std::vector<NoteBase*> affected_lollis;
std::vector<GhostEvent*> affected_lollis;
lollis_between (from.x, to.x, affected_lollis);
@ -114,24 +116,16 @@ VelocityGhostRegion::line_extended (ArdourCanvas::Duple const & from, ArdourCanv
}
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));
for (auto const & lolli : affected_lollis) {
ArdourCanvas::Item* item = lolli->item;
ArdourCanvas::Duple pos = item->item_to_canvas (ArdourCanvas::Duple (lolli->event->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);
lolli->velocity_while_editing = y_position_to_velocity (r.height() - (r.y1() - y));
set_size_and_position (*lolli);
}
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;
return true;
}
bool
@ -189,7 +183,7 @@ VelocityGhostRegion::set_size_and_position (GhostEvent& ev)
{
ArdourCanvas::Lollipop* l = dynamic_cast<ArdourCanvas::Lollipop*> (ev.item);
const double available_height = base_rect->y1();
const double actual_height = (ev.event->note()->velocity() / 127.0) * available_height;
const double actual_height = (ev.velocity_while_editing / 127.0) * available_height;
l->set (ArdourCanvas::Duple (ev.event->x0(), base_rect->y1() - actual_height), actual_height, lollipop_radius);
}
@ -327,7 +321,7 @@ VelocityGhostRegion::note_selected (NoteBase* ev)
}
void
VelocityGhostRegion::lollis_between (int x0, int x1, std::vector<NoteBase*>& within)
VelocityGhostRegion::lollis_between (int x0, int x1, std::vector<GhostEvent*>& within)
{
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (&parent_rv);
assert (mrv);
@ -344,21 +338,21 @@ VelocityGhostRegion::lollis_between (int x0, int x1, std::vector<NoteBase*>& wit
if (l) {
ArdourCanvas::Duple pos = l->item_to_canvas (ArdourCanvas::Duple (l->x(), l->y0()));
if (pos.x >= x0 && pos.x < x1) {
within.push_back (gev.second->event);
within.push_back (gev.second);
}
}
}
}
void
VelocityGhostRegion::lollis_close_to_x (int x, double distance, std::vector<NoteBase*>& within)
VelocityGhostRegion::lollis_close_to_x (int x, double distance, std::vector<GhostEvent*>& within)
{
for (auto & gev : events) {
ArdourCanvas::Lollipop* l = dynamic_cast<ArdourCanvas::Lollipop*> (gev.second->item);
if (l) {
ArdourCanvas::Duple pos = l->item_to_canvas (ArdourCanvas::Duple (l->x(), l->y0()));
if (std::abs (pos.x - x) < distance) {
within.push_back (gev.second->event);
within.push_back (gev.second);
}
}
}
@ -368,7 +362,14 @@ void
VelocityGhostRegion::start_line_drag ()
{
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (&parent_rv);
mrv->begin_drag_edit (_("draw velocities"));
for (auto & e : events) {
GhostEvent* gev (e.second);
gev->velocity_while_editing = gev->event->note()->velocity();
}
desensitize_lollis ();
}
@ -376,7 +377,23 @@ void
VelocityGhostRegion::end_line_drag (bool did_change)
{
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (&parent_rv);
mrv->end_drag_edit (did_change);
if (did_change) {
std::vector<NoteBase*> notes;
std::vector<int> velocities;
for (auto & e : events) {
GhostEvent* gev (e.second);
if (gev->event->note()->velocity() != gev->velocity_while_editing) {
notes.push_back (gev->event);
velocities.push_back (gev->velocity_while_editing);
}
}
mrv->set_velocities_for_notes (notes, velocities);
}
mrv->end_drag_edit ();
sensitize_lollis ();
}

View File

@ -67,8 +67,8 @@ private:
bool base_event (GdkEvent*);
bool lollevent (GdkEvent*, MidiGhostRegion::GhostEvent*);
void set_size_and_position (MidiGhostRegion::GhostEvent&);
void lollis_close_to_x (int x, double distance, std::vector<NoteBase*>& events);
void lollis_between (int x0, int x1, std::vector<NoteBase*>& events);
void lollis_close_to_x (int x, double distance, std::vector<GhostEvent*>& events);
void lollis_between (int x0, int x1, std::vector<GhostEvent*>& events);
void desensitize_lollis ();
void sensitize_lollis ();
};