PatternClips now use startTimeOffset, too, and can be resized on their start [FIX 7]
This commit is contained in:
committed by
Kevin Zander
parent
534e7edf0f
commit
1a68aee149
@@ -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() )
|
||||
{
|
||||
@@ -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();
|
||||
|
||||
@@ -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"
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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) )
|
||||
@@ -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 );
|
||||
@@ -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();
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -240,4 +248,4 @@ void PatternTrack::swapPatternTracks(Track* track1, Track* track2)
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms
|
||||
} // namespace lmms
|
||||
|
||||
Reference in New Issue
Block a user