diff --git a/ChangeLog b/ChangeLog index d410ac85a..731361c0a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2008-12-14 Andrew Kelley + + * include/piano_roll.h: + * src/gui/piano_roll.cpp: + * TODO: + - piano roll notes are painted with colors revealing their velocities + and panning + - switching between note edit modes is more clear with label text and + a right click menu + 2008-12-14 Tobias Doerffel * include/group_box.h: @@ -40,6 +50,7 @@ - first draft of panning editing. (for now, click the area below the piano to switch editing modes.) - supports horizontal mouse wheel + - paint notes darker/lighter based on how much volume they have * include/panning_constants.h: * include/midi.h: diff --git a/TODO b/TODO index 793bb0c8c..999e0ba4d 100644 --- a/TODO +++ b/TODO @@ -52,8 +52,12 @@ - add FLAC as export-format? Andrew Kelley's todo: -- paint piano roll notes with a darker color based on how high volume the note is - paint note volume blue if selected +- make the tip of a panning bar blue too so the user knows it's selected +- when you click on a note in the piano roll, it plays the note, but not the correct panning +- fix ctrl+mousewheel zooming in +- if you press both controls at the same time, the piano roll gets stuck in selection mode +- change my modifier code to use mainwindows modifier info - multiview button - show notes from every instrument in the current beat+bassline with different colors - undo/redo for piano roll - add a tools menu to piano roll @@ -61,11 +65,8 @@ Andrew Kelley's todo: * humanizing tool * quick slice * look through FL Studio's tools and implement some of them -- if you press both controls at the same time, the piano roll gets stuck in selection mode -- you can still move volumes for notes if you click down right on it, even if the - note is not selected. -- change my modifier code to use mainwindows modifier info -- fix ctrl+mousewheel zooming in +- when looking at a piano roll, if the song is playing that pattern, move the position ticker to where it should be +- double-click in note edit area to clear selection (assuming the intent of editing all notes) - recording automation - make knobs easier to tune (less sensitive) diff --git a/include/piano_roll.h b/include/piano_roll.h index 1295559d0..1775c0993 100644 --- a/include/piano_roll.h +++ b/include/piano_roll.h @@ -38,6 +38,9 @@ class QPainter; class QPixmap; class QScrollBar; +class QString; +class QMenu; +class QSignalMapper; class comboBox; class notePlayHandle; @@ -96,9 +99,7 @@ protected: int getKey( int _y ) const; static inline void drawNoteRect( QPainter & _p, int _x, int _y, - int _width, - const bool _is_selected, - const bool _is_step_note ); + int _width, note * _n ); void removeSelection( void ); void selectAll( void ); void getSelectedNotes( noteVector & _selected_notes ); @@ -128,6 +129,8 @@ protected slots: void zoomingChanged( void ); void quantizeChanged( void ); + + void changeNoteEditMode( int i ); private: @@ -155,7 +158,7 @@ private: { NoteEditVolume, NoteEditPanning, - NoteEditCount + NoteEditCount // make sure this one is always last }; enum pianoRollKeyTypes @@ -165,6 +168,9 @@ private: PR_BLACK_KEY }; + QVector m_nemStr; // gui names of each edit mode + QMenu * m_noteEditMenu; // when you right click below the key area + QSignalMapper * m_signalMapper; // to keep track of edit mode events pianoRoll( void ); pianoRoll( const pianoRoll & ); diff --git a/src/gui/piano_roll.cpp b/src/gui/piano_roll.cpp index 79ece54c5..9524332b5 100644 --- a/src/gui/piano_roll.cpp +++ b/src/gui/piano_roll.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include #ifndef __USE_XOPEN @@ -136,6 +138,9 @@ const int DEFAULT_PR_PPT = KEY_LINE_HEIGHT * DefaultStepsPerTact; pianoRoll::pianoRoll( void ) : + m_nemStr( QVector() ), + m_noteEditMenu( NULL ), + m_signalMapper( NULL ), m_zoomingModel(), m_quantizeModel(), m_noteLenModel(), @@ -158,6 +163,23 @@ pianoRoll::pianoRoll( void ) : m_mouseDownRight( false ), m_scrollBack( false ) { + // gui names of edit modes + m_nemStr.push_back( tr( "Note Volume" ) ); + m_nemStr.push_back( tr( "Note Panning" ) ); + + m_signalMapper = new QSignalMapper( this ); + m_noteEditMenu = new QMenu( this ); + m_noteEditMenu->clear(); + for( int i=0; isetMapping( act, i ); + m_noteEditMenu->addAction( act ); + } + connect( m_signalMapper, SIGNAL(mapped(int)), + this, SLOT(changeNoteEditMode(int)) ); + // init pixmaps if( s_whiteKeySmallPm == NULL ) { @@ -479,6 +501,11 @@ pianoRoll::pianoRoll( void ) : } +void pianoRoll::changeNoteEditMode( int i ) +{ + m_noteEditMode = (noteEditMode) i; + repaint(); +} pianoRoll::~pianoRoll() @@ -569,8 +596,7 @@ void pianoRoll::loadSettings( const QDomElement & _this ) inline void pianoRoll::drawNoteRect( QPainter & _p, int _x, int _y, - int _width, const bool _is_selected, - const bool _is_step_note ) + int _width, note * _n ) { ++_x; ++_y; @@ -580,27 +606,65 @@ inline void pianoRoll::drawNoteRect( QPainter & _p, int _x, int _y, { _width = 2; } + + int volVal = qMin( 255, (int) ( + ( (float)( _n->getVolume() - MinVolume ) ) / + ( (float)( MaxVolume - MinVolume ) ) * 255.0f) ); + float rightPercent = qMin( 1.0f, + ( (float)( _n->getPanning() - PanningLeft ) ) / + ( (float)( PanningRight - PanningLeft ) ) * 2.0f ); + + float leftPercent = qMin( 1.0f, + ( (float)( PanningRight - _n->getPanning() ) ) / + ( (float)( PanningRight - PanningLeft ) ) * 2.0f ); - QColor current_color( 0xFF, 0xB0, 0x00 ); - if( _is_step_note == true ) + QColor col; + + col = QColor( 0xFF, 0xB0, 0x00 ); + if( _n->length() < 0 ) { - current_color.setRgb( 0, 255, 0 ); + //step note + col.setRgb( 0, 255, 0 ); + _p.fillRect( _x, _y, _width, KEY_LINE_HEIGHT - 2, col ); } - else if( _is_selected == true ) + else if( _n->selected() ) { - current_color.setRgb( 0x00, 0x40, 0xC0 ); + col.setRgb( 0x00, 0x40, 0xC0 ); + _p.fillRect( _x, _y, _width, KEY_LINE_HEIGHT - 2, col ); } - _p.fillRect( _x, _y, _width, KEY_LINE_HEIGHT - 2, current_color ); - - _p.setPen( QColor( 0xFF, 0xDF, 0x20 ) ); + else + { + // adjust note to make it a bit faded if it has a lower volume + // in stereo using gradients + QColor lcol = QColor::fromHsv( col.hue(), col.saturation(), volVal * leftPercent ); + QColor rcol = QColor::fromHsv( col.hue(), col.saturation(), volVal * rightPercent ); + col = QColor::fromHsv( col.hue(), col.saturation(), volVal ); + + QLinearGradient gradient( _x, _y, _x+_width, _y+KEY_LINE_HEIGHT ); + gradient.setColorAt( 0, lcol ); + gradient.setColorAt( 1, rcol ); + _p.setBrush( gradient ); + _p.setPen( Qt::NoPen ); + _p.drawRect( _x, _y, _width, KEY_LINE_HEIGHT ); + } + + // hilighting lines around the note + _p.setPen( Qt::SolidLine ); + _p.setBrush( Qt::NoBrush ); + + col = QColor( 0xFF, 0xDF, 0x20 ); + _p.setPen( QColor::fromHsv( col.hue(), col.saturation(), volVal ) ); _p.drawLine( _x, _y, _x + _width, _y ); _p.drawLine( _x, _y, _x, _y + KEY_LINE_HEIGHT - 2 ); - - _p.setPen( QColor( 0xFF, 0x9F, 0x00 ) ); + + col = QColor( 0xFF, 0x9F, 0x00 ); + _p.setPen( QColor::fromHsv( col.hue(), col.saturation(), volVal ) ); _p.drawLine( _x + _width, _y, _x + _width, _y + KEY_LINE_HEIGHT - 2 ); _p.drawLine( _x, _y + KEY_LINE_HEIGHT - 2, _x + _width, _y + KEY_LINE_HEIGHT - 2 ); - + + // that little tab thing on the end hinting at the user + // to resize the note _p.setPen( QColor( 0xFF, 0xFF, 0x40 ) ); if( _width > 2 ) { @@ -1420,13 +1484,21 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me ) } else { - // clicked in the box below the keys to the left of note edit area - m_noteEditMode = (noteEditMode)(((int)m_noteEditMode)+1); - if( m_noteEditMode > 1 ) + if( _me->buttons() == Qt::LeftButton ) { - m_noteEditMode = (noteEditMode)0; + // clicked in the box below the keys to the left of note edit area + m_noteEditMode = (noteEditMode)(((int)m_noteEditMode)+1); + if( m_noteEditMode == NoteEditCount ) + { + m_noteEditMode = (noteEditMode)0; + } + repaint(); + } + else if( _me->buttons() == Qt::RightButton ) + { + // pop menu asking which one they want to edit + m_noteEditMenu->popup( mapToGlobal( QPoint( _me->x(), _me->y() ) ) ); } - repaint(); } } } @@ -2315,7 +2387,16 @@ void pianoRoll::paintEvent( QPaintEvent * _pe ) p.fillRect( QRect( 0, keyAreaBottom(), WHITE_KEY_WIDTH, noteEditBottom()-keyAreaBottom() ), QColor( 0, 0, 0 ) ); - + + // display note editing info + QFont f = p.font(); + f.setBold( false ); + p.setFont( pointSize<10>( f ) ); + p.setPen( QColor( 255, 255, 0 ) ); + p.drawText( QRect( 0, keyAreaBottom(), + WHITE_KEY_WIDTH, noteEditBottom() - keyAreaBottom() ), + Qt::AlignCenter | Qt::TextWordWrap, + m_nemStr.at( m_noteEditMode ) + ":" ); // set clipping area, because we are not allowed to paint over // keyboard... @@ -2452,9 +2533,7 @@ void pianoRoll::paintEvent( QPaintEvent * _pe ) // note drawNoteRect( p, x + WHITE_KEY_WIDTH, y_base - key * KEY_LINE_HEIGHT, - note_width, - ( *it )->selected(), - ( *it )->length() < 0 ); + note_width, *it ); } // draw note editing stuff