Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pianoroll: nudge/snap while dragging notes #5848

Merged
merged 12 commits into from
Mar 5, 2021
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
IanCaio marked this conversation as resolved.
Show resolved Hide resolved
};

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 * draggedNote;
PhysSong marked this conversation as resolved.
Show resolved Hide resolved

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
109 changes: 101 additions & 8 deletions src/gui/editors/PianoRoll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,13 @@ PianoRoll::PianoRoll() :
//connection for selecion from timeline
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)
{
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)
Spekular marked this conversation as resolved.
Show resolved Hide resolved
{
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)
IanCaio marked this conversation as resolved.
Show resolved Hide resolved
{
firstIteration = false;
Note* copy(draggedNote);
// guantize first note
IanCaio marked this conversation as resolved.
Show resolved Hide resolved
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() - (draggedNote->oldPos().getTicks() + off_ticks);
}
else
PhysSong marked this conversation as resolved.
Show resolved Hide resolved
{
off_ticks += copy->pos().getTicks() - (draggedNote->oldPos().getTicks() + off_ticks) - 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")
IanCaio marked this conversation as resolved.
Show resolved Hide resolved
{
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