piano roll improvements
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@1860 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
18
ChangeLog
18
ChangeLog
@@ -1,3 +1,21 @@
|
||||
2008-11-29 Andrew Kelley <superjoe30/at/gmail/dot/com>
|
||||
|
||||
* include/piano_roll.h:
|
||||
* src/gui/piano_roll.cpp:
|
||||
- when you draw a note it clears the selection and selects the new note
|
||||
- removed the move tool, it's irrelevant now
|
||||
- when dragging right click around to delete notes, show the eraser icon
|
||||
- when moving a selection around, show the move icon
|
||||
- ctrl+ up / ctrl+down arrow key to move everything up/down 12 semitones
|
||||
- shift+left / shift+right to move all notes to the left or right
|
||||
- make arrow keys left+right scroll
|
||||
|
||||
* src/core/note.cpp:
|
||||
got rid of warnings for copy constructor
|
||||
|
||||
* TODO:
|
||||
you know... todo stuff.
|
||||
|
||||
2008-11-29 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
|
||||
|
||||
* include/resources_tree_view.h:
|
||||
|
||||
10
TODO
10
TODO
@@ -41,6 +41,7 @@
|
||||
- Swedish
|
||||
- Norwegian
|
||||
- Greece
|
||||
- Elvish
|
||||
- ...
|
||||
|
||||
|
||||
@@ -51,12 +52,11 @@
|
||||
- add FLAC as export-format?
|
||||
|
||||
Andrew Kelley's todo:
|
||||
- when you draw a note, if there's a selection it should clear it
|
||||
- piano roll, copy and paste notes
|
||||
- remove the move tool, it's irrelevant now
|
||||
- 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
|
||||
- when dragging right click around to delete notes, show the eraser icon
|
||||
- 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)
|
||||
- undo/redo for piano roll
|
||||
@@ -69,6 +69,6 @@ Andrew Kelley's todo:
|
||||
- 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
|
||||
- dragging a note below the automation level messes up dragging it's weird and glitchy fix it
|
||||
- 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
|
||||
|
||||
@@ -166,8 +166,14 @@ private:
|
||||
virtual ~pianoRoll();
|
||||
|
||||
midiTime newNoteLen( void ) const;
|
||||
|
||||
|
||||
|
||||
void shiftPos(int amount);
|
||||
void shiftSemiTone(int amount);
|
||||
bool isSelection() const;
|
||||
|
||||
static const int cm_scrollAmtHoriz = 10;
|
||||
static const int cm_scrollAmtVert = 1;
|
||||
|
||||
static QPixmap * s_whiteKeyBigPm;
|
||||
static QPixmap * s_whiteKeySmallPm;
|
||||
static QPixmap * s_blackKeyPm;
|
||||
@@ -190,7 +196,6 @@ private:
|
||||
toolButton * m_drawButton;
|
||||
toolButton * m_eraseButton;
|
||||
toolButton * m_selectButton;
|
||||
toolButton * m_moveButton;
|
||||
|
||||
toolButton * m_cutButton;
|
||||
toolButton * m_copyButton;
|
||||
@@ -239,7 +244,9 @@ private:
|
||||
|
||||
editModes m_editMode;
|
||||
editModes m_ctrlMode; // mode they were in before they hit ctrl
|
||||
|
||||
|
||||
bool m_mouseDownLeft; //true if left click is being held down
|
||||
bool m_mouseDownRight; //true if right click is being held down
|
||||
|
||||
timeLine * m_timeLine;
|
||||
bool m_scrollBack;
|
||||
|
||||
@@ -65,12 +65,12 @@ note::note( const midiTime & _length, const midiTime & _pos,
|
||||
|
||||
note::note( const note & _note ) :
|
||||
serializingObject( _note ),
|
||||
m_selected( _note.m_selected ),
|
||||
m_key( _note.m_key),
|
||||
m_volume( _note.m_volume ),
|
||||
m_panning( _note.m_panning ),
|
||||
m_length( _note.m_length ),
|
||||
m_pos( _note.m_pos ),
|
||||
m_selected( _note.m_selected )
|
||||
m_pos( _note.m_pos )
|
||||
{
|
||||
m_detuning = sharedObject::ref( _note.m_detuning );
|
||||
}
|
||||
|
||||
@@ -147,6 +147,8 @@ pianoRoll::pianoRoll( void ) :
|
||||
m_startKey( INITIAL_START_KEY ),
|
||||
m_lastKey( 0 ),
|
||||
m_editMode( ModeDraw ),
|
||||
m_mouseDownLeft( false ),
|
||||
m_mouseDownRight( false ),
|
||||
m_scrollBack( false )
|
||||
{
|
||||
// init pixmaps
|
||||
@@ -291,17 +293,11 @@ pianoRoll::pianoRoll( void ) :
|
||||
m_toolBar );
|
||||
m_selectButton->setCheckable( true );
|
||||
|
||||
m_moveButton = new toolButton( embed::getIconPixmap( "edit_move" ),
|
||||
tr( "Move selection mode (Shift+M)" ),
|
||||
this, SLOT( moveButtonToggled() ),
|
||||
m_toolBar );
|
||||
m_moveButton->setCheckable( true );
|
||||
|
||||
QButtonGroup * tool_button_group = new QButtonGroup( this );
|
||||
tool_button_group->addButton( m_drawButton );
|
||||
tool_button_group->addButton( m_eraseButton );
|
||||
tool_button_group->addButton( m_selectButton );
|
||||
tool_button_group->addButton( m_moveButton );
|
||||
tool_button_group->setExclusive( true );
|
||||
|
||||
m_drawButton->setWhatsThis(
|
||||
@@ -320,11 +316,6 @@ pianoRoll::pianoRoll( void ) :
|
||||
"if you want to cut, copy, paste, delete or move "
|
||||
"notes. You can also press 'Shift+S' on your keyboard "
|
||||
"to activate this mode." ) );
|
||||
m_moveButton->setWhatsThis(
|
||||
tr( "Click here and move-mode will be activated. In this "
|
||||
"mode you can move the notes you selected in select-"
|
||||
"mode. You can also press 'Shift+M' on your keyboard "
|
||||
"to activate this mode." ) );
|
||||
|
||||
m_cutButton = new toolButton( embed::getIconPixmap( "edit_cut" ),
|
||||
tr( "Cut selected notes (Ctrl+X)" ),
|
||||
@@ -432,7 +423,6 @@ pianoRoll::pianoRoll( void ) :
|
||||
tb_layout->addWidget( m_drawButton );
|
||||
tb_layout->addWidget( m_eraseButton );
|
||||
tb_layout->addWidget( m_selectButton );
|
||||
tb_layout->addWidget( m_moveButton );
|
||||
tb_layout->addSpacing( 10 );
|
||||
tb_layout->addWidget( m_cutButton );
|
||||
tb_layout->addWidget( m_copyButton );
|
||||
@@ -691,8 +681,58 @@ void pianoRoll::closeEvent( QCloseEvent * _ce )
|
||||
_ce->ignore();
|
||||
}
|
||||
|
||||
void pianoRoll::shiftSemiTone(int amount) // shift notes by amount semitones
|
||||
{
|
||||
bool useAllNotes = ! isSelection();
|
||||
const noteVector & notes = m_pattern->notes();
|
||||
for( noteVector::const_iterator it = notes.begin(); it != notes.end(); ++it)
|
||||
{
|
||||
// if none are selected, move all notes, otherwise
|
||||
// only move selected notes
|
||||
if( useAllNotes || ( *it )->getSelected() )
|
||||
{
|
||||
( *it )->setKey( ( *it )->key() + amount );
|
||||
}
|
||||
}
|
||||
|
||||
// we modified the song
|
||||
update();
|
||||
engine::getSongEditor()->update();
|
||||
|
||||
}
|
||||
|
||||
void pianoRoll::shiftPos(int amount) //shift notes pos by amount
|
||||
{
|
||||
bool useAllNotes = ! isSelection();
|
||||
const noteVector & notes = m_pattern->notes();
|
||||
for( noteVector::const_iterator it = notes.begin(); it != notes.end(); ++it)
|
||||
{
|
||||
// if none are selected, move all notes, otherwise
|
||||
// only move selected notes
|
||||
if( useAllNotes || ( *it )->getSelected() )
|
||||
{
|
||||
( *it )->setPos( ( *it )->pos() + amount );
|
||||
}
|
||||
}
|
||||
|
||||
// we modified the song
|
||||
update();
|
||||
engine::getSongEditor()->update();
|
||||
}
|
||||
|
||||
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() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void pianoRoll::keyPressEvent( QKeyEvent * _ke )
|
||||
{
|
||||
@@ -711,28 +751,84 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke )
|
||||
switch( _ke->key() )
|
||||
{
|
||||
case Qt::Key_Up:
|
||||
m_topBottomScroll->setValue(
|
||||
m_topBottomScroll->value() - 1 );
|
||||
if( _ke->modifiers() & Qt::ControlModifier )
|
||||
{
|
||||
// shift selection up an octave
|
||||
// if nothing selected, shift _everything_
|
||||
shiftSemiTone( +12 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// scroll
|
||||
m_topBottomScroll->setValue(
|
||||
m_topBottomScroll->value() - cm_scrollAmtVert );
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_Down:
|
||||
m_topBottomScroll->setValue(
|
||||
m_topBottomScroll->value() + 1 );
|
||||
if( _ke->modifiers() & Qt::ControlModifier )
|
||||
{
|
||||
// shift selection down an octave
|
||||
// if nothing selected, shift _everything_
|
||||
shiftSemiTone( -12 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// scroll
|
||||
m_topBottomScroll->setValue(
|
||||
m_topBottomScroll->value() + cm_scrollAmtVert );
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_Left:
|
||||
{
|
||||
if( ( m_timeLine->pos() -= 16 ) < 0 )
|
||||
if( _ke->modifiers() & Qt::ControlModifier )
|
||||
{
|
||||
m_timeLine->pos().setTicks( 0 );
|
||||
// move time ticker
|
||||
if( ( m_timeLine->pos() -= 16 ) < 0 )
|
||||
{
|
||||
m_timeLine->pos().setTicks( 0 );
|
||||
}
|
||||
m_timeLine->updatePosition();
|
||||
}
|
||||
else if( _ke->modifiers() & Qt::ShiftModifier )
|
||||
{
|
||||
// move notes
|
||||
bool quantized = ! (_ke->modifiers() & Qt::AltModifier);
|
||||
int amt = quantized ? quantization() : 1;
|
||||
shiftPos( -amt );
|
||||
}
|
||||
else
|
||||
{
|
||||
// scroll
|
||||
m_leftRightScroll->setValue(
|
||||
m_leftRightScroll->value() - cm_scrollAmtHoriz );
|
||||
}
|
||||
m_timeLine->updatePosition();
|
||||
break;
|
||||
}
|
||||
case Qt::Key_Right:
|
||||
{
|
||||
m_timeLine->pos() += 16;
|
||||
m_timeLine->updatePosition();
|
||||
if( _ke->modifiers() & Qt::ControlModifier )
|
||||
{
|
||||
// move time ticker
|
||||
m_timeLine->pos() += 16;
|
||||
m_timeLine->updatePosition();
|
||||
}
|
||||
else if( _ke->modifiers() & Qt::ShiftModifier )
|
||||
{
|
||||
// move notes
|
||||
bool quantized = ! (_ke->modifiers() & Qt::AltModifier);
|
||||
int amt = quantized ? quantization() : 1;
|
||||
shiftPos( +amt );
|
||||
}
|
||||
else
|
||||
{
|
||||
// scroll
|
||||
m_leftRightScroll->setValue(
|
||||
m_leftRightScroll->value() + cm_scrollAmtHoriz );
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -815,17 +911,6 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke )
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_M:
|
||||
if( _ke->modifiers() & Qt::ShiftModifier )
|
||||
{
|
||||
m_moveButton->setChecked( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
_ke->ignore();
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_Delete:
|
||||
deleteSelectedNotes();
|
||||
break;
|
||||
@@ -1065,6 +1150,10 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
pattern::MelodyPattern );
|
||||
|
||||
// then set new note
|
||||
|
||||
// clear selection and select this new note
|
||||
clearSelectedNotes();
|
||||
|
||||
// +32 to quanitize the note correctly when placing notes with
|
||||
// the mouse. We do this here instead of in note.quantized
|
||||
// because live notes should still be quantized at the half.
|
||||
@@ -1072,7 +1161,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
midiTime note_len( newNoteLen() );
|
||||
|
||||
note new_note( note_len, note_pos, key_num );
|
||||
|
||||
new_note.setSelected( true );
|
||||
note * created_new_note =
|
||||
m_pattern->addNote( new_note );
|
||||
|
||||
@@ -1137,7 +1226,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
m_editMode == ModeErase )
|
||||
{
|
||||
// erase single note
|
||||
|
||||
m_mouseDownRight = true;
|
||||
play_note = false;
|
||||
if( it != notes.end() )
|
||||
{
|
||||
@@ -1170,15 +1259,6 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
// appears in wrong spot on mousedown
|
||||
mouseMoveEvent( _me );
|
||||
}
|
||||
else if( _me->button() == Qt::RightButton &&
|
||||
m_editMode == ModeSelect )
|
||||
{
|
||||
// when clicking right in select-move, we
|
||||
// switch to move-mode
|
||||
m_moveButton->setChecked( true );
|
||||
play_note = false;
|
||||
|
||||
}
|
||||
else if( _me->button() == Qt::LeftButton &&
|
||||
m_editMode == ModeMove )
|
||||
{
|
||||
@@ -1189,6 +1269,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
m_moveStartKey = key_num;
|
||||
|
||||
m_action = ActionMoveSelection;
|
||||
m_mouseDownLeft = true;
|
||||
|
||||
play_note = false;
|
||||
engine::getSong()->setModified();
|
||||
@@ -1312,6 +1393,19 @@ void pianoRoll::computeSelectedNotes(bool shift)
|
||||
|
||||
void pianoRoll::mouseReleaseEvent( QMouseEvent * _me )
|
||||
{
|
||||
bool mustRepaint = false;
|
||||
|
||||
if( _me->button() & Qt::LeftButton )
|
||||
{
|
||||
m_mouseDownLeft = false;
|
||||
mustRepaint = true;
|
||||
}
|
||||
if( _me->button() & Qt::RightButton )
|
||||
{
|
||||
m_mouseDownRight = false;
|
||||
mustRepaint = true;
|
||||
}
|
||||
|
||||
if( _me->button() & Qt::LeftButton &&
|
||||
m_editMode == ModeSelect &&
|
||||
m_action == ActionSelectNotes )
|
||||
@@ -1356,6 +1450,11 @@ void pianoRoll::mouseReleaseEvent( QMouseEvent * _me )
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
if( mustRepaint )
|
||||
{
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2373,7 +2472,21 @@ void pianoRoll::paintEvent( QPaintEvent * _pe )
|
||||
// draw current edit-mode-icon below the cursor
|
||||
switch( m_editMode )
|
||||
{
|
||||
case ModeDraw: cursor = s_toolDraw; break;
|
||||
case ModeDraw:
|
||||
if( m_mouseDownRight )
|
||||
{
|
||||
cursor = s_toolErase;
|
||||
}
|
||||
else if( m_action == ActionMoveSelection ||
|
||||
m_action == ActionMoveNote )
|
||||
{
|
||||
cursor = s_toolMove;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor = s_toolDraw;
|
||||
}
|
||||
break;
|
||||
case ModeErase: cursor = s_toolErase; break;
|
||||
case ModeSelect: cursor = s_toolSelect; break;
|
||||
case ModeMove: cursor = s_toolMove; break;
|
||||
|
||||
Reference in New Issue
Block a user