Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/core/PatternClip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ void PatternClip::saveSettings(QDomDocument& doc, QDomElement& element)
element.setAttribute( "pos", startPosition() );
}
element.setAttribute( "len", length() );
element.setAttribute("off", startTimeOffset());
element.setAttribute( "muted", isMuted() );
if( usesCustomClipColor() )
{
Expand All @@ -78,6 +79,7 @@ void PatternClip::loadSettings(const QDomElement& element)
movePosition( element.attribute( "pos" ).toInt() );
}
changeLength( element.attribute( "len" ).toInt() );
setStartTimeOffset(element.attribute("off").toInt());
if( element.attribute( "muted" ).toInt() != isMuted() )
{
toggleMute();
Expand Down
37 changes: 28 additions & 9 deletions src/gui/clips/ClipView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#include "MidiClip.h"
#include "MidiClipView.h"
#include "Note.h"
#include "PatternClip.h"
#include "PatternStore.h"
#include "SampleClip.h"
#include "Song.h"
#include "SongEditor.h"
Expand Down Expand Up @@ -502,10 +504,11 @@ void ClipView::dropEvent( QDropEvent * de )
void ClipView::updateCursor(QMouseEvent * me)
{
auto sClip = dynamic_cast<SampleClip*>(m_clip);
auto pClip = dynamic_cast<PatternClip*>(m_clip);

// If we are at the edges, use the resize cursor
if (!me->buttons() && !m_clip->getAutoResize() && !isSelected()
&& ((me->x() > width() - RESIZE_GRIP_WIDTH) || (me->x() < RESIZE_GRIP_WIDTH && sClip)))
&& ((me->x() > width() - RESIZE_GRIP_WIDTH) || (me->x() < RESIZE_GRIP_WIDTH && (sClip || pClip))))
{
setCursor(Qt::SizeHorCursor);
}
Expand Down Expand Up @@ -633,6 +636,7 @@ void ClipView::mousePressEvent( QMouseEvent * me )
if( !fixedClips() && me->button() == Qt::LeftButton )
{
auto sClip = dynamic_cast<SampleClip*>(m_clip);
auto pClip = dynamic_cast<PatternClip*>(m_clip);
const bool knifeMode = m_trackView->trackContainerView()->knifeMode();

if ( me->modifiers() & Qt::ControlModifier && !(sClip && knifeMode) )
Expand Down Expand Up @@ -677,7 +681,7 @@ void ClipView::mousePressEvent( QMouseEvent * me )
m_action = Resize;
setCursor( Qt::SizeHorCursor );
}
else if( me->x() < RESIZE_GRIP_WIDTH && sClip )
else if( me->x() < RESIZE_GRIP_WIDTH && (sClip || pClip) )
{
m_action = ResizeLeft;
setCursor( Qt::SizeHorCursor );
Expand Down Expand Up @@ -836,7 +840,6 @@ void ClipView::mouseMoveEvent( QMouseEvent * me )
if( m_action == Move )
{
TimePos newPos = draggedClipPos( me );

m_clip->movePosition(newPos);
newPos = m_clip->startPosition(); // Get the real position the Clip was dragged to for the label
m_trackView->getTrackContentWidget()->changePosition();
Expand Down Expand Up @@ -916,7 +919,8 @@ void ClipView::mouseMoveEvent( QMouseEvent * me )
else
{
auto sClip = dynamic_cast<SampleClip*>(m_clip);
if( sClip )
auto pClip = dynamic_cast<PatternClip*>(m_clip);
if( sClip || pClip )
{
const int x = mapToParent( me->pos() ).x() - m_initialMousePos.x();

Expand Down Expand Up @@ -948,12 +952,27 @@ void ClipView::mouseMoveEvent( QMouseEvent * me )
t = qMin<int>( m_initialClipEnd - minLength, m_initialClipPos + offset );
}

TimePos oldPos = m_clip->startPosition();
if( m_clip->length() + ( oldPos - t ) >= 1 )
TimePos positionOffset = m_clip->startPosition() - t;
if (m_clip->length() + positionOffset >= 1)
{
m_clip->movePosition( t );
m_clip->changeLength( m_clip->length() + ( oldPos - t ) );
sClip->setStartTimeOffset( sClip->startTimeOffset() + ( oldPos - t ) );
m_clip->movePosition(t);
m_clip->changeLength(m_clip->length() + positionOffset);
if (sClip)
{
sClip->setStartTimeOffset(sClip->startTimeOffset() + positionOffset);
}
else if (pClip)
{
// Modulus the start time offset as we need it only for offsets
// inside the pattern length. This is done to prevent a value overflow.
// The start time offset may still become larger than the pattern length
// whenever the pattern length decreases without a clip resize following.
// To deal safely with it, always modulus before use.
tick_t patternLength = Engine::patternStore()->lengthOfPattern(pClip->patternIndex())
* TimePos::ticksPerBar();
TimePos position = (pClip->startTimeOffset() + positionOffset) % patternLength;
pClip->setStartTimeOffset(position);
}
}
}
}
Expand Down
14 changes: 9 additions & 5 deletions src/gui/clips/PatternClipView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,18 @@ void PatternClipView::paintEvent(QPaintEvent*)

// bar lines
const int lineSize = 3;
int pixelsPerPattern = Engine::patternStore()->lengthOfPattern(m_patternClip->patternIndex()) * pixelsPerBar();
int offset = static_cast<int>(m_patternClip->startTimeOffset() * (pixelsPerBar() / TimePos::ticksPerBar()))
% pixelsPerPattern;
if (offset < 2) {
offset += pixelsPerPattern;
}

p.setPen( c.darker( 200 ) );

bar_t t = Engine::patternStore()->lengthOfPattern(m_patternClip->patternIndex());
if (m_patternClip->length() > TimePos::ticksPerBar() && t > 0)
if (pixelsPerPattern > 0)
{
for( int x = static_cast<int>( t * pixelsPerBar() );
x < width() - 2;
x += static_cast<int>( t * pixelsPerBar() ) )
for (int x = offset; x < width() - 2; x += pixelsPerPattern)
{
p.drawLine( x, BORDER_WIDTH, x, BORDER_WIDTH + lineSize );
p.drawLine( x, rect().bottom() - ( BORDER_WIDTH + lineSize ),
Expand Down
18 changes: 13 additions & 5 deletions src/tracks/PatternTrack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,27 @@ bool PatternTrack::play( const TimePos & _start, const fpp_t _frames,
}

TimePos lastPosition;
TimePos lastLen;
TimePos lastLength;
tick_t lastOffset = 0;
for (const auto& clip : clips)
{
if (!clip->isMuted() && clip->startPosition() >= lastPosition)
{
lastPosition = clip->startPosition();
lastLen = clip->length();
lastLength = clip->length();
tick_t patternLength = Engine::patternStore()->lengthOfPattern(static_cast<PatternClip*>(clip)->patternIndex())
* TimePos::ticksPerBar();
lastOffset = patternLength - (clip->startTimeOffset() % patternLength);
if (lastOffset == patternLength)
{
lastOffset = 0;
}
}
}

if( _start - lastPosition < lastLen )
if( _start - lastPosition < lastLength )
{
return Engine::patternStore()->play(_start - lastPosition, _frames, _offset, s_infoMap[this]);
return Engine::patternStore()->play(_start - lastPosition + lastOffset, _frames, _offset, s_infoMap[this]);
}
return false;
}
Expand Down Expand Up @@ -240,4 +248,4 @@ void PatternTrack::swapPatternTracks(Track* track1, Track* track2)
}


} // namespace lmms
} // namespace lmms