From e2f74ee6e669f570134b8b9d19432b01b4981207 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 5 Dec 2008 08:03:15 +0000 Subject: [PATCH] piano roll improvements, especially with moving notes around. see changelog. git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@1871 0778d3d1-df1d-0410-868b-ea421aaaa00d --- ChangeLog | 14 ++ TODO | 22 +- include/note.h | 30 ++- include/piano_roll.h | 29 ++- src/core/note.cpp | 41 +++- src/gui/piano_roll.cpp | 462 +++++++++++++++++++++-------------------- 6 files changed, 352 insertions(+), 246 deletions(-) diff --git a/ChangeLog b/ChangeLog index 634771985..e775eafe8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-12-05 Andrew Kelley + + * include/piano_roll.h: + * src/core/piano_roll.cpp: + * include/note.h: + * src/core/note.cpp: + - don't play notes when you click on one if the song is already playing + - now you can move and resize unquantized notes in quantized amounts + - shift+drag to copy one or more notes (we need to figure out some other + way to implement note detuning) + - removed stagnant note movement code + - dragging a group of notes to boundary conditions is handled correctly + - ability to scroll using arrow keys while dragging notes + 2008-12-04 Tobias Doerffel * CMakeLists.txt: diff --git a/TODO b/TODO index 91c39c181..b9b253ce3 100644 --- a/TODO +++ b/TODO @@ -52,23 +52,25 @@ - add FLAC as export-format? Andrew Kelley's todo: -- don't play notes when you click on one if the song is already playing -- humanizing tool for piano roll (add a tools menu to piano roll and put some of the tools with keyboard shortcuts on there) -- dragging a note below the automation level messes up dragging it's weird and glitchy fix it -- holding control and shift shouldn't bring up the automation window -- shift+drag to copy one or more notes -- moving a group of notes shouldn't crunch them together if brought to boundary conditions -- moving a group with an unquantized note will quantize that note when you move the selection (this is bad) +- add a tools menu to piano roll + * put some of the tools on there that already have keyboard shortcuts (ctrl+up/down, shift+left/right) + * humanizing tool + * quick slice + * look through FL Studio's tools and implement some of them - undo/redo for piano roll +- make copy/paste work beyond inside piano roll - it didn't work when I copied notes from one pattern and then opened another pattern and pasted. +- piano roll: make the note volume section have adjustable height +- add note panning ability to piano roll +- make piano roll grid change based on quantization + - when you clone a track in the song editor, rename the track so that it doesn't have the same name (increment the number if necessary) -- doing actions on the piano roll when LMMS doesn't have focus is glitchy - somehow enable easy pattern copy pasting in the beat+bassline editor - make knobs easier to tune (less sensitive) -- make copy/paste work beyond inside piano roll - it didn't work when I copied notes from one pattern and then opened another pattern and pasted. - make it so you can see the notes when putting a pattern in the playlist - make the menu for a channel happen when you right click, instead of renaming, and make the midi input a top-level menu item -- segfault on quit - recording automation - adding/removing steps to the beat+bassline editor is awkward - the 'add beat+bassline' button in the beat+bassline editor is misleading - I say we remove it and rely on the song editor to add beat+basslines - make it so that 3xosc notes don't max out +- implement note detuning (used to be ctrl+click to access note detuning) (need some other intuitive way to access note detuning as ctrl, shift, and alt are all being used) +- make the horizontal scroll bar do the same thing as shift+vertical scroll bar diff --git a/include/note.h b/include/note.h index 50b6f0520..c8c1c82b1 100644 --- a/include/note.h +++ b/include/note.h @@ -91,7 +91,11 @@ public: note( const note & _note ); virtual ~note(); - void setSelected( const bool selected ); + void setSelected( const bool _selected ); + void setOldKey( const int _oldKey ); + void setOldPos( const midiTime & _oldPos ); + void setOldLength( const midiTime & _oldLength ); + void setLength( const midiTime & _length ); void setPos( const midiTime & _pos ); void setKey( const int _key ); @@ -107,10 +111,25 @@ public: return (bool) ((int) ( *lhs ).pos() < (int) ( *rhs ).pos()); } - inline bool getSelected( void ) const + inline bool selected( void ) const { return m_selected; } + + inline int oldKey( void ) const + { + return m_oldKey; + } + + inline midiTime oldPos( void ) const + { + return m_oldPos; + } + + inline midiTime oldLength( void ) const + { + return m_oldLength; + } inline midiTime endPos( void ) const { @@ -190,7 +209,12 @@ private: ChangePosition } ;*/ - bool m_selected; // for piano roll editing + // for piano roll editing + bool m_selected; + int m_oldKey; + midiTime m_oldPos; + midiTime m_oldLength; + int m_key; volume m_volume; panning m_panning; diff --git a/include/piano_roll.h b/include/piano_roll.h index 1743d63ef..0d49d0591 100644 --- a/include/piano_roll.h +++ b/include/piano_roll.h @@ -118,7 +118,6 @@ protected slots: void drawButtonToggled( void ); void eraseButtonToggled( void ); void selectButtonToggled( void ); - void moveButtonToggled( void ); void copySelectedNotes( void ); void cutSelectedNotes( void ); @@ -170,6 +169,8 @@ private: void shiftPos(int amount); void shiftSemiTone(int amount); bool isSelection() const; + + void dragNotes( int x, int y, bool alt ); static const int cm_scrollAmtHoriz = 10; static const int cm_scrollAmtVert = 1; @@ -225,10 +226,25 @@ private: int m_selectedTick; int m_selectStartKey; int m_selectedKeys; - - int m_moveStartKey; - int m_moveStartTick; - int m_moveXOffset; + + // boundary box around all selected notes when dragging + int m_moveBoundaryLeft; + int m_moveBoundaryTop; + int m_moveBoundaryRight; + int m_moveBoundaryBottom; + + // remember where the scrolling started when dragging so that + // we can handle dragging while scrolling with arrow keys + int m_mouseDownKey; + int m_mouseDownTick; + + // remember the last x and y of a mouse movement + int m_lastMouseX; + int m_lastMouseY; + + // x,y of when the user starts a drag + int m_moveStartX; + int m_moveStartY; int m_notesEditHeight; int m_ppt; @@ -239,9 +255,6 @@ private: int m_startKey; // first key when drawing int m_lastKey; - noteVector m_selNotesForMove; - - editModes m_editMode; editModes m_ctrlMode; // mode they were in before they hit ctrl diff --git a/src/core/note.cpp b/src/core/note.cpp index 3f821228c..10e117cfb 100644 --- a/src/core/note.cpp +++ b/src/core/note.cpp @@ -40,6 +40,10 @@ note::note( const midiTime & _length, const midiTime & _pos, int _key, volume _volume, panning _panning, detuningHelper * _detuning ) : + m_selected( false ), + m_oldKey( tLimit( _key, 0, NumKeys ) ), + m_oldPos( _pos ), + m_oldLength( _length ), m_key( tLimit( _key, 0, NumKeys ) ), m_volume( tLimit( _volume, MinVolume, MaxVolume ) ), m_panning( tLimit( _panning, PanningLeft, PanningRight ) ), @@ -48,7 +52,6 @@ note::note( const midiTime & _length, const midiTime & _pos, { //saveJournallingState( FALSE ); // setJournalling( FALSE ); - setSelected( false ); if( _detuning ) { m_detuning = sharedObject::ref( _detuning ); @@ -66,6 +69,9 @@ note::note( const midiTime & _length, const midiTime & _pos, note::note( const note & _note ) : serializingObject( _note ), m_selected( _note.m_selected ), + m_oldKey( _note.m_oldKey ), + m_oldPos( _note.m_oldPos ), + m_oldLength( _note.m_oldLength ), m_key( _note.m_key), m_volume( _note.m_volume ), m_panning( _note.m_panning ), @@ -83,12 +89,41 @@ note::~note() sharedObject::unref( m_detuning ); } -void note::setSelected( const bool selected ) + + + +void note::setSelected( const bool _selected ) { - m_selected = selected; + m_selected = _selected; } + + +void note::setOldKey( const int _oldKey ) +{ + m_oldKey = _oldKey; +} + + + + +void note::setOldPos( const midiTime & _oldPos ) +{ + m_oldPos = _oldPos; +} + + + + +void note::setOldLength( const midiTime & _oldLength ) +{ + m_oldLength = _oldLength; +} + + + + void note::setLength( const midiTime & _length ) { // addJournalEntry( journalEntry( ChangeLength, m_length - _length ) ); diff --git a/src/gui/piano_roll.cpp b/src/gui/piano_roll.cpp index 60c7823e4..112bf6b4a 100644 --- a/src/gui/piano_roll.cpp +++ b/src/gui/piano_roll.cpp @@ -139,8 +139,8 @@ pianoRoll::pianoRoll( void ) : m_recording( false ), m_currentNote( NULL ), m_action( ActionNone ), - m_moveStartKey( 0 ), - m_moveStartTick( 0 ), + m_lastMouseX( 0 ), + m_lastMouseY( 0 ), m_notesEditHeight( 100 ), m_ppt( DEFAULT_PR_PPT ), m_lenOfNewNotes( midiTime( 0, DefaultTicksPerTact/4 ) ), @@ -689,7 +689,7 @@ void pianoRoll::shiftSemiTone(int amount) // shift notes by amount semitones { // if none are selected, move all notes, otherwise // only move selected notes - if( useAllNotes || ( *it )->getSelected() ) + if( useAllNotes || ( *it )->selected() ) { ( *it )->setKey( ( *it )->key() + amount ); } @@ -709,7 +709,7 @@ void pianoRoll::shiftPos(int amount) //shift notes pos by amount { // if none are selected, move all notes, otherwise // only move selected notes - if( useAllNotes || ( *it )->getSelected() ) + if( useAllNotes || ( *it )->selected() ) { ( *it )->setPos( ( *it )->pos() + amount ); } @@ -725,7 +725,7 @@ bool pianoRoll::isSelection() const // are any notes selected? const noteVector & notes = m_pattern->notes(); for( noteVector::const_iterator it = notes.begin(); it != notes.end(); ++it) { - if( ( *it )->getSelected() ) + if( ( *it )->selected() ) { return true; } @@ -762,6 +762,13 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke ) // scroll m_topBottomScroll->setValue( m_topBottomScroll->value() - cm_scrollAmtVert ); + + // if they are moving notes around or resizing, + // recalculate the note/resize position + if( m_action == ActionMoveNote || m_action == ActionResizeNote ) + { + dragNotes( m_lastMouseX, m_lastMouseY, _ke->modifiers() & Qt::AltModifier ); + } } break; case Qt::Key_Down: @@ -777,6 +784,12 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke ) m_topBottomScroll->setValue( m_topBottomScroll->value() + cm_scrollAmtVert ); + // if they are moving notes around or resizing, + // recalculate the note/resize position + if( m_action == ActionMoveNote || m_action == ActionResizeNote ) + { + dragNotes( m_lastMouseX, m_lastMouseY, _ke->modifiers() & Qt::AltModifier ); + } } break; @@ -803,6 +816,14 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke ) // scroll m_leftRightScroll->setValue( m_leftRightScroll->value() - cm_scrollAmtHoriz ); + + // if they are moving notes around or resizing, + // recalculate the note/resize position + if( m_action == ActionMoveNote || m_action == ActionResizeNote ) + { + dragNotes( m_lastMouseX, m_lastMouseY, _ke->modifiers() & Qt::AltModifier ); + } + } break; } @@ -826,6 +847,14 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke ) // scroll m_leftRightScroll->setValue( m_leftRightScroll->value() + cm_scrollAmtHoriz ); + + // if they are moving notes around or resizing, + // recalculate the note/resize position + if( m_action == ActionMoveNote || m_action == ActionResizeNote ) + { + dragNotes( m_lastMouseX, m_lastMouseY, _ke->modifiers() & Qt::AltModifier ); + } + } @@ -965,13 +994,14 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke ) update(); break; case Qt::Key_Shift: + /* TODO: implement note detuning some other way. if( mouseOverNote() ) { m_editMode = ModeOpen; QApplication::changeOverrideCursor( QCursor( Qt::ArrowCursor ) ); update(); - } + } */ break; default: _ke->ignore(); @@ -1045,7 +1075,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) if( _me->y() > PR_TOP_MARGIN ) { - bool play_note = true; + bool play_note = ! engine::getSong()->isPlaying(); volume vol = DefaultVolume; bool edit_note = ( _me->y() > height() - @@ -1054,6 +1084,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) int key_num = getKey( _me->y() ); int x = _me->x(); + if( x > WHITE_KEY_WIDTH ) { @@ -1142,6 +1173,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) else if( _me->button() == Qt::LeftButton && m_editMode == ModeDraw ) { + note * created_new_note = NULL; // did it reach end of vector because // there's no note?? if( it == notes.end() ) @@ -1162,8 +1194,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) note new_note( note_len, note_pos, key_num ); new_note.setSelected( true ); - note * created_new_note = - m_pattern->addNote( new_note ); + created_new_note = m_pattern->addNote( new_note ); // reset it so that it can be used for // ops (move, resize) after this @@ -1179,7 +1210,56 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) } m_currentNote = *it; + + + // keep track of the point where the user clicked down + m_moveStartX = _me->x(); + m_moveStartY = _me->y(); + m_mouseDownKey = m_startKey; + m_mouseDownTick = m_currentPosition; + + bool first = true; + it = notes.begin(); + while( it != notes.end() ) + { + + // remember note starting positions + ( *it )->setOldKey( ( *it )->key() ); + ( *it )->setOldPos( ( *it )->pos() ); + ( *it )->setOldLength( ( *it )->length() ); + + if( ( *it )->selected() ) + { + + // figure out the bounding box of all the selected notes + if( first ) + { + m_moveBoundaryLeft = ( *it )->pos().getTicks(); + m_moveBoundaryRight = ( *it )->pos() + ( *it )->length(); + m_moveBoundaryBottom = ( *it )->key(); + m_moveBoundaryTop = ( *it )->key(); + + first = false; + } + else + { + m_moveBoundaryLeft = qMin( + ( *it )->pos().getTicks(), + m_moveBoundaryLeft ); + m_moveBoundaryRight = qMax( ( *it )->pos() + + ( *it )->length(), + m_moveBoundaryRight ); + m_moveBoundaryBottom = qMin( ( *it )->key(), + m_moveBoundaryBottom ); + m_moveBoundaryTop = qMax( ( *it )->key(), + m_moveBoundaryTop ); + } + } + + ++it; + } + // clicked at the "tail" of the note? if( pos_ticks*m_ppt/midiTime::ticksPerTact() > ( m_currentNote->pos() + @@ -1200,23 +1280,57 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) { // otherwise move it m_action = ActionMoveNote; - int aligned_x = (int)( (float)( ( - m_currentNote->pos() - - m_currentPosition ) * - m_ppt ) / - midiTime::ticksPerTact() ); - m_moveXOffset = x - aligned_x - 1; + + + + + // set move-cursor QCursor c( Qt::SizeAllCursor ); QApplication::setOverrideCursor( c ); + // if they're holding shift, copy all selected notes + if( *it != created_new_note && + _me->modifiers() & Qt::ShiftModifier ) + { + + // vector to hold new notes until we're through the loop + QVector newNotes; + it = notes.begin(); + while( it != notes.end() ) + { + if( ( *it )->selected() ) + { + // copy this note + note noteCopy( (note) **it ); + newNotes.push_back( noteCopy ); + } + ++it; + } + + if( newNotes.size() != 0 ) + { + //put notes from vector into piano roll + for( int i=0; iaddNote( newNotes[i] ); + newNote->setSelected( false ); + } + + // added new notes, so must update engine, song, etc + engine::getSong()->setModified(); + update(); + engine::getSongEditor()->update(); + } + } } // if clicked on an unselected note, remove selection - if( ! m_currentNote->getSelected() ) + if( ! m_currentNote->selected() ) { clearSelectedNotes(); + m_currentNote->setSelected( true ); } engine::getSong()->setModified(); @@ -1259,21 +1373,6 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) // appears in wrong spot on mousedown mouseMoveEvent( _me ); } - else if( _me->button() == Qt::LeftButton && - m_editMode == ModeMove ) - { - // move selection (including selected notes) - - // save position where move-process began - m_moveStartTick = pos_ticks; - m_moveStartKey = key_num; - - m_action = ActionMoveSelection; - m_mouseDownLeft = true; - - play_note = false; - engine::getSong()->setModified(); - } else if( _me->button() == Qt::RightButton && m_editMode == ModeMove ) { @@ -1467,7 +1566,7 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) update(); return; } - + if( _me->y() > PR_TOP_MARGIN ) { bool edit_note = ( _me->y() > height() - @@ -1501,7 +1600,7 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) midiTime() ); } } - if( _me->x() < WHITE_KEY_WIDTH ) + if( x < WHITE_KEY_WIDTH ) { update(); return; @@ -1509,7 +1608,13 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) x -= WHITE_KEY_WIDTH; // Volume Bars - if( ( edit_note == true || m_action == ActionChangeNoteVolume ) && + if( _me->buttons() & Qt::LeftButton + && m_editMode == ModeDraw + && (m_action == ActionMoveNote || m_action == ActionResizeNote ) ) + { + dragNotes(_me->x(), _me->y(), _me->modifiers() && Qt::AltModifier); + } + else if( ( edit_note == true || m_action == ActionChangeNoteVolume ) && _me->buttons() & Qt::LeftButton ) { // Use nearest-note when changing volume so the bars can @@ -1604,94 +1709,6 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) midiTime() ); } } - else if( m_currentNote != NULL && - _me->buttons() & Qt::LeftButton && m_editMode == ModeDraw ) - { - //int key_num = getKey( _me->y() ); - int key_offset = getKey( _me->y() ) - m_currentNote->key(); - - if( m_action == ActionMoveNote ) - { - x -= m_moveXOffset; - } - - - int pos_ticks_offset = x * midiTime::ticksPerTact() / m_ppt + - m_currentPosition - m_currentNote->pos().getTicks(); - - - // get note-vector of current pattern - const noteVector & notes = m_pattern->notes(); - - // will be our iterator in the following loop - noteVector::const_iterator it = notes.begin(); - while( it != notes.end() ) - { - if( ( *it )->getSelected() || m_currentNote == *it ) - { - - if( m_action == ActionMoveNote ) - { - // moving note - int pos_ticks = midiTime( ( *it )->pos().getTicks() - + pos_ticks_offset ); - int key_num = ( *it )->key() + key_offset; - - if( pos_ticks < 0 ) - { - pos_ticks = 0; - } - // upper/lower bound checks on key_num - if( key_num < 0 ) - { - key_num = 0; - } - else if( key_num > NumKeys ) - { - key_num = NumKeys; - } - - ( *it )->setPos( midiTime( - pos_ticks ) ); - ( *it )->setKey( key_num ); - if( ! ( _me->modifiers() & Qt::AltModifier ) ) - { - ( *it )->quantizePos( quantization() ); - } - - - } - else - { - // resizing note - //int pos_ticks = midiTime( ( *it )->pos().getTicks() - // + pos_ticks_offset ); - //int ticks_diff = pos_ticks - - // m_currentNote->pos(); - - int ticks_diff = pos_ticks_offset; - - if( ticks_diff <= 0 ) - { - ticks_diff = 1; - } - ( *it )->setLength( midiTime( ticks_diff ) ); - - if( ! ( _me->modifiers() & Qt::AltModifier ) ) - { - ( *it )->quantizeLength( quantization() ); - } - - m_lenOfNewNotes = ( *it )->length(); - m_pattern->dataChanged(); - } - } - ++it; - } - - engine::getSong()->setModified(); - - } else if( _me->buttons() == Qt::NoButton && m_editMode == ModeDraw ) { // set move- or resize-cursor @@ -1842,90 +1859,6 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) --m_selectedKeys; } } - else if( _me->buttons() & Qt::LeftButton && - m_editMode == ModeMove && - m_action == ActionMoveSelection ) - { - // move selection + selected notes - - // do horizontal move-stuff - int pos_ticks = x * midiTime::ticksPerTact() / m_ppt + - m_currentPosition; - int ticks_diff = pos_ticks - m_moveStartTick; - if( m_selectedTick > 0 ) - { - if( (int) m_selectStartTick + ticks_diff < 0 ) - { - ticks_diff = -m_selectStartTick; - } - } - else - { - if( (int) m_selectStartTick + - m_selectedTick + ticks_diff < 0 ) - { - ticks_diff = -( m_selectStartTick + - m_selectedTick ); - } - } - if( !m_selNotesForMove.isEmpty() ) - { - const int q = note::quantized( m_selNotesForMove.first()->pos() + - ticks_diff, quantization() ) - - m_selNotesForMove.first()->pos(); - ticks_diff = ( q / quantization() ) * quantization(); - if( ticks_diff != 0) - { - m_moveStartTick = pos_ticks; - } - } - m_selectStartTick += ticks_diff; - - // do vertical move-stuff - int key_diff = key_num - m_moveStartKey; - - if( m_selectedKeys > 0 ) - { - if( m_selectStartKey + key_diff < -1 ) - { - key_diff = -m_selectStartKey - 1; - } - else if( m_selectStartKey + m_selectedKeys + - key_diff >= KeysPerOctave * - NumOctaves ) - { - key_diff = KeysPerOctave * NumOctaves - - ( m_selectStartKey + - m_selectedKeys ) - 1; - } - } - else - { - if( m_selectStartKey + m_selectedKeys + - key_diff < -1 ) - { - key_diff = -( m_selectStartKey + - m_selectedKeys ) - 1; - } - else if( m_selectStartKey + key_diff >= - KeysPerOctave * NumOctaves ) - { - key_diff = KeysPerOctave * NumOctaves - - m_selectStartKey - 1; - } - } - m_selectStartKey += key_diff; - for( noteVector::iterator it = - m_selNotesForMove.begin(); - it != m_selNotesForMove.end(); ++it ) - { - ( *it )->setPos( ( *it )->pos() + ticks_diff ); - ( *it )->setKey( ( *it )->key() + key_diff ); - *it = m_pattern->rearrangeNote( *it, false ); - } - - m_moveStartKey = key_num; - } else if( m_editMode == ModeOpen && !( mouseOverNote() && _me->modifiers() & Qt::ShiftModifier ) ) { @@ -2074,13 +2007,110 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me ) } QApplication::restoreOverrideCursor(); } - + + m_lastMouseX = _me->x(); + m_lastMouseY = _me->y(); + update(); } +void pianoRoll::dragNotes( int x, int y, bool alt ) +{ + // dragging one or more notes around + + // convert pixels to ticks and keys + int off_x = x - m_moveStartX; + int off_ticks = off_x * midiTime::ticksPerTact() / m_ppt; + int off_key = getKey( y ) - getKey( m_moveStartY ); + + // if they're not holding alt, quantize the offset + if( ! alt ) + { + off_ticks = floor( off_ticks / quantization() ) + * quantization(); + } + + // handle scroll changes while dragging + off_ticks -= m_mouseDownTick - m_currentPosition; + off_key -= m_mouseDownKey - m_startKey; + + // make sure notes won't go outside boundary conditions + if( m_action == ActionMoveNote ) + { + if( m_moveBoundaryLeft + off_ticks < 0 ) + { + off_ticks += 0 - (off_ticks + m_moveBoundaryLeft); + } + if( m_moveBoundaryTop + off_key > NumKeys ) + { + off_key -= NumKeys - (m_moveBoundaryTop + off_key); + } + if( m_moveBoundaryBottom + off_key < 0 ) + { + off_key += 0 - (m_moveBoundaryBottom + off_key); + } + } + + // get note-vector of current pattern + const noteVector & notes = m_pattern->notes(); + + // will be our iterator in the following loop + noteVector::const_iterator it = notes.begin(); + while( it != notes.end() ) + { + if( ( *it )->selected() ) + { + + if( m_action == ActionMoveNote ) + { + // moving note + int pos_ticks = ( *it )->oldPos().getTicks() + + off_ticks; + int key_num = ( *it )->oldKey() + off_key; + + if( pos_ticks < 0 ) + { + pos_ticks = 0; + } + // upper/lower bound checks on key_num + if( key_num < 0 ) + { + key_num = 0; + } + else if( key_num > NumKeys ) + { + key_num = NumKeys; + } + + ( *it )->setPos( midiTime( pos_ticks ) ); + ( *it )->setKey( key_num ); + } + else if( m_action == ActionResizeNote ) + { + // resizing note + int ticks_new = ( *it )->oldLength().getTicks() + + off_ticks; + if( ticks_new <= 0 ) + { + ticks_new = 1; + } + ( *it )->setLength( midiTime( ticks_new ) ); + + m_lenOfNewNotes = ( *it )->length(); + m_pattern->dataChanged(); + } + } + ++it; + } + + engine::getSong()->setModified(); +} + + + void pianoRoll::paintEvent( QPaintEvent * _pe ) { QStyleOption opt; @@ -2390,7 +2420,7 @@ void pianoRoll::paintEvent( QPaintEvent * _pe ) drawNoteRect( p, x + WHITE_KEY_WIDTH, y_base - key * KEY_LINE_HEIGHT, note_width, - ( *it )->getSelected(), + ( *it )->selected(), ( *it )->length() < 0 ); } // draw volume-line of note @@ -2757,18 +2787,6 @@ void pianoRoll::selectButtonToggled( void ) - -void pianoRoll::moveButtonToggled( void ) -{ - m_editMode = ModeMove; - m_selNotesForMove.clear(); - getSelectedNotes( m_selNotesForMove ); - update(); -} - - - - void pianoRoll::selectAll( void ) { if( validPattern() == false ) @@ -2840,7 +2858,7 @@ void pianoRoll::getSelectedNotes( noteVector & _selected_notes ) for( noteVector::const_iterator it = notes.begin(); it != notes.end(); ++it ) { - if( ( *it )->getSelected() ) + if( ( *it )->selected() ) { _selected_notes.push_back( *it ); } @@ -2983,7 +3001,7 @@ void pianoRoll::deleteSelectedNotes( void ) noteVector::const_iterator it = notes.begin(); while( it != notes.end() ) { - if( ( *it )->getSelected() ) + if( ( *it )->selected() ) { // delete this note m_pattern->removeNote( ( *it ) );