Skip to content
Binary file added data/themes/default/gridmode.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 14 additions & 1 deletion include/PianoRoll.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ protected slots:
void clearGhostPattern();
void glueNotes();

void changeSnapMode();


signals:
void currentPatternChanged();
Expand Down Expand Up @@ -253,6 +255,13 @@ protected slots:
PR_BLACK_KEY
};

enum GridMode
{
gridNudge,
gridSnap,
gridFree
};

PositionLine * m_positionLine;

QVector<QString> m_nemStr; // gui names of each edit mode
Expand Down Expand Up @@ -294,7 +303,8 @@ protected slots:
int noteEditRight() const;
int noteEditLeft() const;

void dragNotes( int x, int y, bool alt, bool shift, bool ctrl );
void dragNotes( int x, int y, bool alt, bool shift, bool ctrl, Note * nt );
Note * m_draggedNote;

static const int cm_scrollAmtHoriz = 10;
static const int cm_scrollAmtVert = 1;
Expand All @@ -316,6 +326,7 @@ protected slots:
ComboBoxModel m_keyModel;
ComboBoxModel m_scaleModel;
ComboBoxModel m_chordModel;
ComboBoxModel m_snapModel;

static const QVector<double> m_zoomLevels;
static const QVector<double> m_zoomYLevels;
Expand All @@ -338,6 +349,7 @@ protected slots:
Note * m_currentNote;
Actions m_action;
NoteEditMode m_noteEditMode;
GridMode m_gridMode;

int m_selectStartTick;
int m_selectedTick;
Expand Down Expand Up @@ -513,6 +525,7 @@ private slots:
ComboBox * m_keyComboBox;
ComboBox * m_scaleComboBox;
ComboBox * m_chordComboBox;
ComboBox * m_snapComboBox;
QPushButton * m_clearGhostButton;

};
Expand Down
111 changes: 102 additions & 9 deletions src/gui/editors/PianoRoll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ typedef AutomationPattern::timeMap timeMap;


// some constants...
const int INITIAL_PIANOROLL_WIDTH = 860;
const int INITIAL_PIANOROLL_WIDTH = 970;
const int INITIAL_PIANOROLL_HEIGHT = 485;

const int SCROLLBAR_SIZE = 12;
Expand Down Expand Up @@ -432,6 +432,13 @@ PianoRoll::PianoRoll() :
connect( m_timeLine, SIGNAL( regionSelectedFromPixels( int, int ) ),
this, SLOT( selectRegionFromPixels( int, int ) ) );

// Set up snap model
m_snapModel.addItem( tr("Nudge") );
m_snapModel.addItem( tr("Snap") );
m_snapModel.setValue( 0 );
connect( &m_snapModel, SIGNAL( dataChanged() ),
this, SLOT( changeSnapMode() ) );

m_stepRecorder.initialize();
}

Expand Down Expand Up @@ -1185,7 +1192,8 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke)
dragNotes( m_lastMouseX, m_lastMouseY,
ke->modifiers() & Qt::AltModifier,
ke->modifiers() & Qt::ShiftModifier,
ke->modifiers() & Qt::ControlModifier );
ke->modifiers() & Qt::ControlModifier,
nullptr );
}
}
ke->accept();
Expand Down Expand Up @@ -1241,7 +1249,8 @@ void PianoRoll::keyPressEvent(QKeyEvent* ke)
dragNotes( m_lastMouseX, m_lastMouseY,
ke->modifiers() & Qt::AltModifier,
ke->modifiers() & Qt::ShiftModifier,
ke->modifiers() & Qt::ControlModifier );
ke->modifiers() & Qt::ControlModifier,
nullptr );
}

}
Expand Down Expand Up @@ -2198,7 +2207,8 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me )
dragNotes( me->x(), me->y(),
me->modifiers() & Qt::AltModifier,
me->modifiers() & Qt::ShiftModifier,
me->modifiers() & Qt::ControlModifier );
me->modifiers() & Qt::ControlModifier,
noteUnderMouse() );

if( replay_note && m_action == ActionMoveNote && ! ( ( me->modifiers() & Qt::ShiftModifier ) && ! m_startedWithShift ) )
{
Expand Down Expand Up @@ -2535,13 +2545,20 @@ void PianoRoll::mouseMoveEvent( QMouseEvent * me )



void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl )
void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl, Note* noteDragged )
{
// dragging one or more notes around

// get note that's dragged
if (noteDragged != nullptr)
{
m_draggedNote = noteDragged;
}

// convert pixels to ticks and keys
int off_x = x - m_moveStartX;
int off_ticks = off_x * TimePos::ticksPerBar() / m_ppb;
int unquantized_off_ticks = off_ticks;
int off_key = getKey( y ) - getKey( m_moveStartY );

// handle scroll changes while dragging
Expand All @@ -2550,10 +2567,9 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl )


// if they're not holding alt, quantize the offset
if( ! alt )
if (!alt)
{
off_ticks = floor( off_ticks / quantization() )
* quantization();
off_ticks = floor(off_ticks / quantization()) * quantization();
}

// make sure notes won't go outside boundary conditions
Expand All @@ -2579,6 +2595,7 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl )

if (m_action == ActionMoveNote)
{
bool firstIteration = true;
for (Note *note : getSelectedNotes())
{
if (shift && ! m_startedWithShift)
Expand All @@ -2595,6 +2612,41 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl )
else
{
// moving note
if (m_gridMode == gridSnap && firstIteration)
{
firstIteration = false;
Note* copy(m_draggedNote);
// guantize first note
int start_pos_ticks = copy->oldPos().getTicks() + unquantized_off_ticks;
int end_pos_ticks = start_pos_ticks + copy->length().getTicks();
start_pos_ticks = qMax(0, start_pos_ticks);
end_pos_ticks = qMax(0, end_pos_ticks);

copy->setPos(TimePos(start_pos_ticks));
copy->quantizePos(quantization());
auto tmp_pos=copy->pos(); // store start position

int gap_start = qAbs(start_pos_ticks - copy->pos().getTicks());

copy->setPos(TimePos(end_pos_ticks));
copy->quantizePos(quantization());

int gap_end = qAbs(end_pos_ticks - copy->pos().getTicks());

if (gap_start < gap_end)
{
copy->setPos(tmp_pos); // restore start position
off_ticks += copy->pos().getTicks() - (m_draggedNote->oldPos().getTicks() + off_ticks);
}
else
{
off_ticks += copy->pos().getTicks() - (m_draggedNote->oldPos().getTicks() + off_ticks) - m_draggedNote->length().getTicks();
}

// new off_ticks based on quantized (copy) note and not-quantized notes

printf("gap_start = %i\n gap_end %i\n", gap_start,gap_end);
}
int pos_ticks = note->oldPos().getTicks() + off_ticks;
int key_num = note->oldKey() + off_key;

Expand Down Expand Up @@ -2702,10 +2754,19 @@ 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
bool firstIteraton = true;
int minLength = alt ? 1 : m_minResizeLen.getTicks();

for (Note *note : selectedNotes)
{
if (m_gridMode == gridSnap && firstIteraton)
{
firstIteraton = false;
Note copy (*note);
int oldEndPoint = copy.oldPos()+copy.oldLength();
int quantizedEndPoint = Note::quantized(copy.oldLength()+copy.oldPos(),quantization());
off_ticks += quantizedEndPoint - oldEndPoint;
}
int newLength = qMax(minLength, note->oldLength() + off_ticks);
note->setLength(TimePos(newLength));

Expand Down Expand Up @@ -4360,8 +4421,22 @@ Note * PianoRoll::noteUnderMouse()
return NULL;
}

void PianoRoll::changeSnapMode()
{
// gridNudge,
// gridSnap,
// gridFree - to be implemented


QString qs_snapMode = m_snapModel.currentText();
if (qs_snapMode == "Nudge")
{
m_gridMode = gridNudge;
}
if (qs_snapMode == "Snap")
{
m_gridMode = gridSnap;
}
}

PianoRollWindow::PianoRollWindow() :
Editor(true, true),
Expand Down Expand Up @@ -4510,6 +4585,15 @@ PianoRollWindow::PianoRollWindow() :
m_chordComboBox->setFixedSize( 105, ComboBox::DEFAULT_HEIGHT );
m_chordComboBox->setToolTip( tr( "Chord" ) );

// setup snap-stuff
QLabel *snap_lbl = new QLabel(m_toolBar);
snap_lbl->setPixmap(embed::getIconPixmap("gridmode"));

m_snapComboBox = new ComboBox(m_toolBar);
m_snapComboBox->setModel(&m_editor->m_snapModel);
m_snapComboBox->setFixedSize(105, ComboBox::DEFAULT_HEIGHT);
m_snapComboBox->setToolTip(tr("Snap mode"));

// -- Clear ghost pattern button
m_clearGhostButton = new QPushButton( m_toolBar );
m_clearGhostButton->setIcon( embed::getIconPixmap( "clear_ghost_note" ) );
Expand Down Expand Up @@ -4577,6 +4661,15 @@ PianoRollWindow::PianoRollWindow() :
zoomAndNotesToolBar->addSeparator();
zoomAndNotesToolBar->addWidget( m_clearGhostButton );

QWidget * snap_widget = new QWidget();
QHBoxLayout * snap_hbox = new QHBoxLayout();
snap_hbox->setContentsMargins(0, 0, 0, 0);
snap_hbox->addWidget(snap_lbl);
snap_hbox->addWidget(m_snapComboBox);
snap_widget->setLayout(snap_hbox);
zoomAndNotesToolBar->addSeparator();
zoomAndNotesToolBar->addWidget(snap_widget);

// setup our actual window
setFocusPolicy( Qt::StrongFocus );
setFocus();
Expand Down