From e07c78d2fcae719f9ae1d97e924dd16206b3905e Mon Sep 17 00:00:00 2001 From: Spekular Date: Thu, 9 Jul 2020 17:18:57 +0200 Subject: [PATCH] Better minimum length when resizing notes (#5512) * Limit note length to quantization value Draging a note to it's minimum value of 1 will add this new length to the note if you later choose to stretch it which will not be clearly visible in the Piano Roll unless you zoom in a bit. Limit the note length to the quantization value and use key to override and set a smaller value. * Update src/gui/editors/PianoRoll.cpp Co-authored-by: Spekular * Remember min note length if shorter than quantization() * Find note length modulo quantization, pick smallest from selected notes * Comment on and improve m_minResizeLen calculation Co-authored-by: Oskar Wallgren --- include/PianoRoll.h | 3 +++ src/gui/editors/PianoRoll.cpp | 24 +++++++++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/include/PianoRoll.h b/include/PianoRoll.h index bf8aa983c..86a65050c 100644 --- a/include/PianoRoll.h +++ b/include/PianoRoll.h @@ -406,6 +406,9 @@ private: volume_t m_lastNoteVolume; panning_t m_lastNotePanning; + //When resizing several notes, we want to calculate a common minimum length + MidiTime m_minResizeLen; + int m_startKey; // first key when drawing int m_lastKey; diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index e0f4fdadf..2f948523a 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -181,6 +181,7 @@ PianoRoll::PianoRoll() : m_lenOfNewNotes( MidiTime( 0, DefaultTicksPerBar/4 ) ), m_lastNoteVolume( DefaultVolume ), m_lastNotePanning( DefaultPanning ), + m_minResizeLen( 0 ), m_startKey( INITIAL_START_KEY ), m_lastKey( 0 ), m_editMode( ModeDraw ), @@ -1727,9 +1728,21 @@ void PianoRoll::mousePressEvent(QMouseEvent * me ) // then resize the note m_action = ActionResizeNote; + //Calculate the minimum length we should allow when resizing + //each note, and let all notes use the smallest one found + m_minResizeLen = quantization(); for (Note *note : selectedNotes) { - if (note->oldLength() <= 0) { note->setOldLength(4); } + //Notes from the BB editor can have a negative length, so + //change their length to the displayed one before resizing + if (note->oldLength() <= 0) { note->setOldLength(4); } + //Let the note be sized down by quantized increments, stopping + //when the next step down would result in a negative length + int thisMin = note->oldLength() % quantization(); + //The initial value for m_minResizeLen is the minimum length of + //a note divisible by the current Q. Therefore we ignore notes + //where thisMin == 0 when checking for a new minimum + if (thisMin > 0 && thisMin < m_minResizeLen) { m_minResizeLen = thisMin; } } // set resize-cursor @@ -2664,7 +2677,7 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl ) // If shift is pressed we resize and rearrange only the selected notes // If shift + ctrl then we also rearrange all posterior notes (sticky) // If shift is pressed but only one note is selected, apply sticky - + auto selectedNotes = getSelectedNotes(); if (shift) @@ -2750,11 +2763,12 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl ) else { // shift is not pressed; stretch length of selected notes but not their position + int minLength = alt ? 1 : m_minResizeLen.getTicks(); + for (Note *note : selectedNotes) { - int newLength = note->oldLength() + off_ticks; - newLength = qMax(1, newLength); - note->setLength( MidiTime(newLength) ); + int newLength = qMax(minLength, note->oldLength() + off_ticks); + note->setLength(MidiTime(newLength)); m_lenOfNewNotes = note->length(); }