From 30a7f44c127fab6f318684c2faef002d32f4d5df Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 11 Jun 2024 15:14:03 -0600 Subject: [PATCH] fix geometry calculations during NoteCreateDrags. This also only uses the draw length parameter if no motion occured during the NoteCreateDrag. Otherwise it uses the length that was dragged (which is subjected to a threshold). --- gtk2_ardour/editor_drag.cc | 16 +++++++++++----- gtk2_ardour/midi_cue_view.cc | 2 ++ gtk2_ardour/midi_cue_view.h | 4 ++++ gtk2_ardour/midi_view.cc | 5 +++-- gtk2_ardour/midi_view.h | 6 +++++- 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 2775e4ee40..e63d9ccf5b 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -6852,11 +6852,11 @@ NoteCreateDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) const timepos_t pos = _drags->current_pointer_time (); Temporal::Beats aligned_beats (round_to_grid (pos, event)); - const Temporal::Beats grid_beats (_midi_view->get_draw_length_beats (pos)); + const Temporal::Beats min_length (0, Temporal::Beats::PPQN/ 128); _note[0] = timepos_t (aligned_beats); /* minimum initial length is grid beats */ - _note[1] = _note[0] + timepos_t (grid_beats); + _note[1] = _note[0] + timepos_t (min_length); /* the note positions we've just computed are in absolute beats, but * the drag rect is a member of the region view group, so we need @@ -6882,7 +6882,7 @@ NoteCreateDrag::motion (GdkEvent* event, bool) const timepos_t pos = _drags->current_pointer_time (); /* when the user clicks and starts a drag to define the note's length, require notes to be at least |this| long */ - const Temporal::Beats min_length (_midi_view->get_draw_length_beats (pos)); + const Temporal::Beats min_length (0, Temporal::Beats::PPQN / 128); Temporal::Beats aligned_beats = round_to_grid (pos, event); _note[1] = std::max (aligned_beats, (_note[0].beats () + min_length)); @@ -6899,12 +6899,18 @@ NoteCreateDrag::motion (GdkEvent* event, bool) void NoteCreateDrag::finished (GdkEvent* ev, bool had_movement) { - /* we create a note even if there was no movement */ + Beats length; /* Compute start within region, rather than absolute time start */ Beats const start = _midi_view->midi_region ()->absolute_time_to_region_beats (min (_note[0], _note[1])); - Beats length = max (Beats (0, 1), (_note[0].distance (_note[1]).abs ().beats ())); + + if (!had_movement) { + /* we create a note even if there was no movement */ + length = _midi_view->get_draw_length_beats (_note[0]); + } else { + length = _note[0].distance (_note[1]).abs ().beats (); + } /* create_note_at() implements UNDO for us */ if (UIConfiguration::instance().get_select_last_drawn_note_only()) { diff --git a/gtk2_ardour/midi_cue_view.cc b/gtk2_ardour/midi_cue_view.cc index e2bc66a2b1..89011d35fa 100644 --- a/gtk2_ardour/midi_cue_view.cc +++ b/gtk2_ardour/midi_cue_view.cc @@ -53,6 +53,8 @@ MidiCueView::MidiCueView (std::shared_ptr mt, event_rect->set_outline (false); _note_group->raise_to_top (); + + set_extensible (true); } void diff --git a/gtk2_ardour/midi_cue_view.h b/gtk2_ardour/midi_cue_view.h index c27d39b791..c1e49a7135 100644 --- a/gtk2_ardour/midi_cue_view.h +++ b/gtk2_ardour/midi_cue_view.h @@ -41,6 +41,10 @@ class MidiCueView : public MidiView void set_height (double); ArdourCanvas::Item* drag_group() const; + bool note_in_region_range (const std::shared_ptr note, bool& visible) const { + visible = true; + return true; + } protected: bool scroll (GdkEventScroll* ev); diff --git a/gtk2_ardour/midi_view.cc b/gtk2_ardour/midi_view.cc index 0312a3a35a..1438a44313 100644 --- a/gtk2_ardour/midi_view.cc +++ b/gtk2_ardour/midi_view.cc @@ -135,6 +135,7 @@ MidiView::MidiView (std::shared_ptr mt, , _mouse_changed_selection (false) , split_tuple (0) , note_splitting (false) + , _extensible (false) { init (); } @@ -1095,7 +1096,7 @@ MidiView::model_changed() std::shared_ptr note (*n); bool visible; - if (note_in_region_range (note, visible)) { + if (_extensible || note_in_region_range (note, visible)) { if (!empty_when_starting && (cne = find_canvas_note (note)) != 0) { cne->validate (); if (visible) { @@ -1648,7 +1649,7 @@ MidiView::update_sustained (Note* ev, bool update_ghost_regions) const Temporal::Beats source_end ((_midi_region->start() + _midi_region->length()).beats()); - if (note->end_time() > source_end) { + if (!_extensible && note->end_time() > source_end) { note_end = timepos_t (source_end); } diff --git a/gtk2_ardour/midi_view.h b/gtk2_ardour/midi_view.h index 763467825a..dcbc22d0cd 100644 --- a/gtk2_ardour/midi_view.h +++ b/gtk2_ardour/midi_view.h @@ -229,7 +229,7 @@ class MidiView : public virtual sigc::trackable * @param visible will be set to true if the note is within the visible note range, false otherwise. * @return true iff the note is within the (time) extent of the region. */ - bool note_in_region_range(const std::shared_ptr note, bool& visible) const; + virtual bool note_in_region_range(const std::shared_ptr note, bool& visible) const; /* Test if a note is withing this region's time range. Return true if so */ bool note_in_region_time_range(const std::shared_ptr note) const; @@ -625,6 +625,10 @@ class MidiView : public virtual sigc::trackable uint32_t split_tuple; bool note_splitting; + bool _extensible; /* if true, we can add data beyond the current region/source end */ + + bool extensible() const { return _extensible; } + void set_extensible (bool yn) { _extensible = yn; } void start_note_splitting (); void end_note_splitting ();