rework mouse hit creation (percussive mode) - mostly as per #7130.
authornick_m <mainsbridge@gmail.com>
Sun, 20 Nov 2016 17:02:21 +0000 (04:02 +1100)
committernick_m <mainsbridge@gmail.com>
Sun, 20 Nov 2016 17:02:21 +0000 (04:02 +1100)
- snap behaviour is round to nearest

- holding down button 1 while dragging creates many
  (if not already present) hits.

gtk2_ardour/editor_drag.cc
gtk2_ardour/midi_region_view.cc

index bc082e9c8c63f3dd5ae152b5fe1697764ba9efff..6a663daf9f93620f997c3f7569d4f68679165132 100644 (file)
@@ -6333,6 +6333,100 @@ NoteCreateDrag::aborted (bool)
 
 }
 
+PercussiveCreateDrag::PercussiveCreateDrag (Editor* e, ArdourCanvas::Item* i, MidiRegionView* rv)
+       : Drag (e, i)
+       , _region_view (rv)
+       , _y (0.0)
+{
+}
+
+PercussiveCreateDrag::~PercussiveCreateDrag ()
+{
+}
+
+framecnt_t
+PercussiveCreateDrag::grid_frames (framepos_t t) const
+{
+       bool success;
+       Evoral::Beats grid_beats = _editor->get_grid_type_as_beats (success, t);
+       if (!success) {
+               grid_beats = Evoral::Beats(1);
+       }
+       const Evoral::Beats t_beats = _region_view->region_frames_to_region_beats (t);
+
+       return _region_view->region_beats_to_region_frames (t_beats + grid_beats)
+               - _region_view->region_beats_to_region_frames (t_beats);
+
+}
+
+void
+PercussiveCreateDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
+{
+       Drag::start_grab (event, cursor);
+
+       TempoMap& map (_editor->session()->tempo_map());
+
+       const framepos_t pf = _drags->current_pointer_frame ();
+       const int32_t divisions = _editor->get_grid_music_divisions (event->button.state);
+
+       bool success = false;
+       Evoral::Beats grid_beats = _editor->get_grid_type_as_beats (success, pf);
+       if (!success) {
+               grid_beats = Evoral::Beats(1);
+       }
+
+       const double eqaf = map.exact_qn_at_frame (pf, divisions);
+       const framepos_t start = map.frame_at_quarter_note (eqaf) - _region_view->region()->position();
+
+       MidiStreamView* sv = _region_view->midi_stream_view ();
+       _y = sv->note_to_y (sv->y_to_note (y_to_region (event->button.y)));
+
+       _region_view->create_note_at (start, _y,  grid_beats, event->button.state, false);
+}
+
+void
+PercussiveCreateDrag::motion (GdkEvent* event, bool)
+{
+       TempoMap& map (_editor->session()->tempo_map());
+
+       const framepos_t pf = _drags->current_pointer_frame ();
+       const int32_t divisions = _editor->get_grid_music_divisions (event->button.state);
+       const double eqaf = map.exact_qn_at_frame (pf, divisions);
+       const framepos_t start = map.frame_at_quarter_note (eqaf) - _region_view->region()->position ();
+
+       MidiStreamView* sv = _region_view->midi_stream_view ();
+       _y = sv->note_to_y (sv->y_to_note (y_to_region (event->button.y)));
+
+       bool success = false;
+       Evoral::Beats grid_beats = _editor->get_grid_type_as_beats (success, pf);
+       if (!success) {
+               grid_beats = Evoral::Beats(1);
+       }
+
+       _region_view->create_note_at (start, _y, grid_beats, event->button.state, false);
+
+}
+
+void
+PercussiveCreateDrag::finished (GdkEvent* /* ev */, bool /* had_movement */)
+{
+
+}
+
+double
+PercussiveCreateDrag::y_to_region (double y) const
+{
+       double x = 0;
+       _region_view->get_canvas_group()->canvas_to_item (x, y);
+       return y;
+}
+
+void
+PercussiveCreateDrag::aborted (bool)
+{
+       // umm..
+}
+
 CrossfadeEdgeDrag::CrossfadeEdgeDrag (Editor* e, AudioRegionView* rv, ArdourCanvas::Item* i, bool start_yn)
        : Drag (e, i)
        , arv (rv)
index 0ae27f4698663725860aef1a5fdb07176ad44d2d..7d8082964a6e7bbfeb7eaf9a6c71b0fcebb11459 100644 (file)
@@ -497,13 +497,20 @@ MidiRegionView::button_press (GdkEventButton* ev)
        if (_mouse_state != SelectTouchDragging) {
 
                _pressed_button = ev->button;
-               _mouse_state = Pressed;
 
                if (m == MouseDraw || (m == MouseContent && Keyboard::modifier_state_contains (ev->state, Keyboard::insert_note_modifier()))) {
-                       editor->drags()->set (new NoteCreateDrag (dynamic_cast<Editor *> (editor), group, this), (GdkEvent *) ev);
+
+                       if (midi_view()->note_mode() == Percussive) {
+                               editor->drags()->set (new PercussiveCreateDrag (dynamic_cast<Editor *> (editor), group, this), (GdkEvent *) ev);
+                       } else {
+                               editor->drags()->set (new NoteCreateDrag (dynamic_cast<Editor *> (editor), group, this), (GdkEvent *) ev);
+                       }
+
                        _mouse_state = AddDragging;
                        remove_ghost_note ();
                        hide_verbose_cursor ();
+               } else {
+                       _mouse_state = Pressed;
                }
 
                return true;
@@ -3745,7 +3752,8 @@ MidiRegionView::update_ghost_note (double x, double y, uint32_t state)
        framepos_t const unsnapped_frame = editor.pixel_to_sample (x);
 
        const int32_t divisions = editor.get_grid_music_divisions (state);
-       const Evoral::Beats snapped_beats = snap_frame_to_grid_underneath (unsnapped_frame, divisions, true);
+       const bool shift_snap = midi_view()->note_mode() != Percussive;
+       const Evoral::Beats snapped_beats = snap_frame_to_grid_underneath (unsnapped_frame, divisions, shift_snap);
 
        /* ghost note may have been snapped before region */
        if (_ghost_note && snapped_beats.to_double() < 0.0) {