-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Sampletrack - resize from left #3487
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
Changes from 3 commits
b9c8f20
92099b2
f8ae969
9eb7b72
25fb7b2
d6701d1
b8e9248
0849eec
246797a
1c30827
2b27365
6b8353b
a6ec9e6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -276,6 +276,7 @@ protected slots: | |
| Move, | ||
| MoveSelection, | ||
| Resize, | ||
| ResizeLeft, | ||
| CopySelection, | ||
| ToggleSelected | ||
| } ; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,7 +67,7 @@ | |
| #include "SongEditor.h" | ||
| #include "StringPairDrag.h" | ||
| #include "TextFloat.h" | ||
|
|
||
| #include <QDebug> | ||
|
||
|
|
||
| /*! The width of the resize grip in pixels | ||
| */ | ||
|
|
@@ -697,8 +697,26 @@ void TrackContentObjectView::mousePressEvent( QMouseEvent * me ) | |
| m_tco->setJournalling( false ); | ||
|
|
||
| setInitialMousePos( me->pos() ); | ||
|
|
||
| if( me->x() < width() - RESIZE_GRIP_WIDTH ) | ||
| SampleTCO * sTco = dynamic_cast<SampleTCO*>( m_tco ); | ||
| if( me->x() < RESIZE_GRIP_WIDTH && sTco ) | ||
| { | ||
| m_action = ResizeLeft; | ||
| m_oldTime = m_tco->startPosition(); | ||
| QCursor c( Qt::SizeHorCursor ); | ||
| QApplication::setOverrideCursor( c ); | ||
| s_textFloat->setTitle( tr( "Current length" ) ); | ||
| delete m_hint; | ||
| m_hint = TextFloat::displayMessage( tr( "Hint" ), | ||
| tr( "Press <%1> for free " | ||
| "resizing." ).arg( | ||
| #ifdef LMMS_BUILD_APPLE | ||
| "⌘"), | ||
| #else | ||
| "Ctrl"), | ||
| #endif | ||
| embed::getIconPixmap( "hint" ), 0 ); | ||
|
||
| } | ||
| else if( me->x() < width() - RESIZE_GRIP_WIDTH ) | ||
| { | ||
| m_action = Move; | ||
| m_oldTime = m_tco->startPosition(); | ||
|
|
@@ -909,6 +927,45 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) | |
| s_textFloat->moveGlobal( this, QPoint( width() + 2, | ||
| height() + 2) ); | ||
| } | ||
| else if( m_action == ResizeLeft ) | ||
| { | ||
| SampleTCO * sTco = dynamic_cast<SampleTCO*>( m_tco ); | ||
| if( sTco ) | ||
| { | ||
| const int x = mapToParent( me->pos() ).x() - m_initialMousePos.x(); | ||
|
|
||
| MidiTime t = qMax( 0, (int) | ||
| m_trackView->trackContainerView()->currentPosition()+ | ||
| static_cast<int>( x * MidiTime::ticksPerTact() / | ||
| ppt ) ); | ||
| if( ! ( me->modifiers() & Qt::ControlModifier ) | ||
| && me->button() == Qt::NoButton ) | ||
| { | ||
| t = t.toNearestTact(); | ||
| } | ||
| MidiTime oldPos = m_tco->startPosition(); | ||
| if( m_tco->length() + ( oldPos - t ) >= MidiTime::ticksPerTact() ) | ||
| { | ||
| m_tco->movePosition( t ); | ||
| m_trackView->getTrackContentWidget()->changePosition(); | ||
| m_tco->changeLength( m_tco->length() + ( oldPos - t ) ); | ||
| sTco->setStartTimeOffset( sTco->startTimeOffset() + ( oldPos - t ) ); | ||
| s_textFloat->setText( tr( "%1:%2 (%3:%4 to %5:%6)" ). | ||
| arg( m_tco->length().getTact() ). | ||
| arg( m_tco->length().getTicks() % | ||
| MidiTime::ticksPerTact() ). | ||
| arg( m_tco->startPosition().getTact() + 1 ). | ||
| arg( m_tco->startPosition().getTicks() % | ||
| MidiTime::ticksPerTact() ). | ||
| arg( m_tco->endPosition().getTact() + 1 ). | ||
| arg( m_tco->endPosition().getTicks() % | ||
| MidiTime::ticksPerTact() ) ); | ||
| s_textFloat->moveGlobal( this, QPoint( width() + 2, | ||
| height() + 2) ); | ||
|
||
| } | ||
| } | ||
|
|
||
| } | ||
| else | ||
| { | ||
| if( me->x() > width() - RESIZE_GRIP_WIDTH && !me->buttons() && !m_tco->getAutoResize() ) | ||
|
|
@@ -925,6 +982,24 @@ void TrackContentObjectView::mouseMoveEvent( QMouseEvent * me ) | |
| QCursor c( Qt::SizeHorCursor ); | ||
| QApplication::setOverrideCursor( c ); | ||
| } | ||
| else if( me->x() < RESIZE_GRIP_WIDTH && !me->buttons() ) | ||
|
||
| { | ||
| SampleTCO * sTco = dynamic_cast<SampleTCO*>( m_tco ); | ||
| if( sTco ) | ||
| { | ||
| if( QApplication::overrideCursor() != NULL && | ||
| QApplication::overrideCursor()->shape() != | ||
| Qt::SizeHorCursor ) | ||
| { | ||
| while( QApplication::overrideCursor() != NULL ) | ||
| { | ||
| QApplication::restoreOverrideCursor(); | ||
| } | ||
| } | ||
| QCursor c( Qt::SizeHorCursor ); | ||
| QApplication::setOverrideCursor( c ); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| leaveEvent( NULL ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,7 +48,7 @@ | |
| #include "Mixer.h" | ||
| #include "EffectRackView.h" | ||
| #include "TrackLabelButton.h" | ||
|
|
||
| #include <QDebug> | ||
|
||
| SampleTCO::SampleTCO( Track * _track ) : | ||
| TrackContentObject( _track ), | ||
| m_sampleBuffer( new SampleBuffer ), | ||
|
|
@@ -184,11 +184,22 @@ void SampleTCO::updateTrackTcos() | |
| } | ||
| } | ||
|
|
||
| MidiTime SampleTCO::startTimeOffset() const | ||
| { | ||
| return m_startTimeOffset; | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
| bool SampleTCO::isPlaying() const | ||
| { | ||
| return m_isPlaying; | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
| void SampleTCO::setIsPlaying(bool isPlaying) | ||
| { | ||
| m_isPlaying = isPlaying; | ||
|
|
@@ -271,6 +282,14 @@ void SampleTCO::loadSettings( const QDomElement & _this ) | |
|
|
||
|
|
||
|
|
||
| void SampleTCO::setStartTimeOffset( MidiTime startTime ) | ||
| { | ||
| m_startTimeOffset = startTime; | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
| TrackContentObjectView * SampleTCO::createView( TrackView * _tv ) | ||
| { | ||
| return new SampleTCOView( this, _tv ); | ||
|
|
@@ -306,6 +325,7 @@ SampleTCOView::~SampleTCOView() | |
|
|
||
| void SampleTCOView::updateSample() | ||
| { | ||
| m_tco->setStartTimeOffset( 0 ); | ||
| update(); | ||
| // set tooltip to filename so that user can see what sample this | ||
| // sample-tco contains | ||
|
|
@@ -370,6 +390,8 @@ void SampleTCOView::dragEnterEvent( QDragEnterEvent * _dee ) | |
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| void SampleTCOView::dropEvent( QDropEvent * _de ) | ||
| { | ||
| if( StringPairDrag::decodeKey( _de ) == "samplefile" ) | ||
|
|
@@ -497,19 +519,21 @@ void SampleTCOView::paintEvent( QPaintEvent * pe ) | |
| float nom = Engine::getSong()->getTimeSigModel().getNumerator(); | ||
| float den = Engine::getSong()->getTimeSigModel().getDenominator(); | ||
| float ticksPerTact = DefaultTicksPerTact * nom / den; | ||
|
|
||
| QRect r = QRect( TCO_BORDER_WIDTH, spacing, | ||
|
|
||
| float offset = m_tco->startTimeOffset() / ticksPerTact * pixelsPerTact(); | ||
| QRect r = QRect( TCO_BORDER_WIDTH + offset, spacing, | ||
| qMax( static_cast<int>( m_tco->sampleLength() * ppt / ticksPerTact ), 1 ), rect().bottom() - 2 * spacing ); | ||
| m_tco->m_sampleBuffer->visualize( p, r, pe->rect() ); | ||
|
|
||
| // disable antialiasing for borders, since its not needed | ||
| p.setRenderHint( QPainter::Antialiasing, false ); | ||
|
|
||
| if( r.width() < width() - 1 ) | ||
| if( r.width() + offset < width() - 1 ) | ||
| { | ||
| p.drawLine( r.x(), r.y() + r.height() / 2, | ||
| rect().right() - TCO_BORDER_WIDTH, r.y() + r.height() / 2 ); | ||
| } | ||
| p.drawLine( 1, height() / 2, offset + 1, height() / 2 ); | ||
|
|
||
| // inner border | ||
| p.setPen( c.lighter( 160 ) ); | ||
|
|
@@ -601,12 +625,13 @@ bool SampleTrack::play( const MidiTime & _start, const fpp_t _frames, | |
| TrackContentObject * tco = getTCO( i ); | ||
| SampleTCO * sTco = dynamic_cast<SampleTCO*>( tco ); | ||
| float framesPerTick = Engine::framesPerTick(); | ||
|
|
||
| if( _start >= sTco->startPosition() && _start < sTco->endPosition() ) | ||
| { | ||
| if( sTco->isPlaying() == false ) | ||
| if( sTco->isPlaying() == false && _start > sTco->startPosition() + sTco->startTimeOffset() ) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should refactor the offset information because playing is more important than GUI events.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please explain, what is in your mind? @jasp00 |
||
| { | ||
| f_cnt_t sampleStart = framesPerTick * ( _start - sTco->startPosition() ); | ||
| f_cnt_t tcoFrameLength = framesPerTick * ( sTco->endPosition() - sTco->startPosition() ); | ||
| f_cnt_t sampleStart = framesPerTick * ( (_start - sTco->startPosition() ) - sTco->startTimeOffset() ); | ||
| f_cnt_t tcoFrameLength = framesPerTick * ( sTco->endPosition() - sTco->startPosition() - sTco->startTimeOffset() ); | ||
| f_cnt_t sampleBufferLength = sTco->sampleBuffer()->frames(); | ||
| //if the Tco smaller than the sample length we play only until Tco end | ||
| //else we play the sample to the end but nothing more | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure this feature will not be useful for other TCOs? You do not have to implement those cases now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jasp00 excellent point, yes this will be useful for other track types. Piano Roll, BBEdtior and Automation patterns can eventually benefit from this as well. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved it into Track.h/.cpp in the TrackContentObject. 👍