From: <sag...@us...> - 2015-06-26 21:48:12
|
Revision: 5361 http://sourceforge.net/p/modplug/code/5361 Author: saga-games Date: 2015-06-26 21:48:05 +0000 (Fri, 26 Jun 2015) Log Message: ----------- [New] Pattern tab: Added option for smooth (tick-by-tick) pattern scrolling. Modified Paths: -------------- trunk/OpenMPT/mptrack/Draw_pat.cpp trunk/OpenMPT/mptrack/GeneralConfigDlg.cpp trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Notification.h trunk/OpenMPT/mptrack/TrackerSettings.h trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_pat.h trunk/OpenMPT/soundlib/Sndfile.h Modified: trunk/OpenMPT/mptrack/Draw_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Draw_pat.cpp 2015-06-26 21:03:11 UTC (rev 5360) +++ trunk/OpenMPT/mptrack/Draw_pat.cpp 2015-06-26 21:48:05 UTC (rev 5361) @@ -157,6 +157,13 @@ } +int CViewPattern::GetSmoothScrollOffset() const +//--------------------------------------------- +{ + return Util::muldivr_unsigned(m_szCell.cy, m_nPlayTick, std::max(1u, m_nTicksOnRow)); +} + + void CViewPattern::UpdateView(UpdateHint hint, CObject *pObj) //----------------------------------------------------------- { @@ -242,6 +249,12 @@ int yofs = GetYScrollPos(); int x = xofs + (pt.x - m_szHeader.cx) / GetColumnWidth(); if (pt.x < m_szHeader.cx) x = (xofs) ? xofs - 1 : 0; + + if((TrackerSettings::Instance().m_dwPatternSetup & PATTERN_SMOOTHSCROLL) != 0 && (m_Status & (psFollowSong | psDragActive)) == psFollowSong && IsLiveRecord()) + { + pt.y += GetSmoothScrollOffset(); + } + int y = yofs - m_nMidRow + (pt.y - m_szHeader.cy) / m_szCell.cy; if (y < 0) y = 0; int xx = (pt.x - m_szHeader.cx) % GetColumnWidth(), dx = 0; @@ -288,12 +301,10 @@ srcx = pfnt->nAlphaAM_X; srcy = pfnt->nAlphaAM_Y + 13 * pfnt->spacingY; break; - //rewbs.smoothVST case '\\': srcx = pfnt->nAlphaNZ_X; srcy = pfnt->nAlphaNZ_Y + 14 * pfnt->spacingY; break; - //end rewbs.smoothVST case ':': srcx = pfnt->nAlphaNZ_X; srcy = pfnt->nAlphaNZ_Y + 15 * pfnt->spacingY; @@ -461,14 +472,8 @@ { CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); CHAR s[256]; - HPEN oldpen; CRect rcClient, rect, rc; const CModDoc *pModDoc; - HDC hdc; - CHANNELINDEX xofs; - ROWINDEX yofs; - UINT nColumnWidth, ncols, ncolhdr; - int xpaint, ypaint, mixPlug; ASSERT(pDC); UpdateSizes(); @@ -477,106 +482,44 @@ const int vuHeight = MulDiv(VUMETERS_HEIGHT, m_nDPIy, 96); const int colHeight = MulDiv(COLHDR_HEIGHT, m_nDPIy, 96); const int recordInsX = MulDiv(3, m_nDPIx, 96); + const bool liveRecord = IsLiveRecord(); + const bool doSmoothScroll = (TrackerSettings::Instance().m_dwPatternSetup & PATTERN_SMOOTHSCROLL) != 0; GetClientRect(&rcClient); - hdc = pDC->m_hDC; - oldpen = SelectPen(hdc, CMainFrame::penDarkGray); - xofs = static_cast<CHANNELINDEX>(GetXScrollPos()); - yofs = static_cast<ROWINDEX>(GetYScrollPos()); - const CSoundFile &sndFile = pModDoc->GetrSoundFile(); - nColumnWidth = m_szCell.cx; - ncols = sndFile.GetNumChannels(); - xpaint = m_szHeader.cx; - ypaint = rcClient.top; - ncolhdr = xofs; - rect.SetRect(0, rcClient.top, rcClient.right, rcClient.top + m_szHeader.cy); - if (::RectVisible(hdc, &rect)) + + HDC hdc; + HBITMAP oldBitmap; + if(doSmoothScroll) { - wsprintf(s, "#%d", m_nPattern); - rect.right = m_szHeader.cx; - DrawButtonRect(hdc, &rect, s, FALSE, - ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_PATTERNHEADER)) ? TRUE : FALSE); - - // Drawing Channel Headers - while (xpaint < rcClient.right) + if(rcClient != m_oldClient) { - rect.SetRect(xpaint, ypaint, xpaint+nColumnWidth, ypaint + m_szHeader.cy); - if (ncolhdr < ncols) - { - const char *pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr]? "[Channel %d]" : "Channel %d"; - if ((sndFile.GetType() & (MOD_TYPE_XM | MOD_TYPE_IT | MOD_TYPE_MPT)) && sndFile.ChnSettings[ncolhdr].szName[0] != 0) - pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr] ? "%d: [%s]" : "%d: %s"; - else if (m_nDetailLevel < PatternCursor::volumeColumn) pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr] ? "[Ch%d]" : "Ch%d"; - else if (m_nDetailLevel < PatternCursor::effectColumn) pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr] ? "[Chn %d]" : "Chn %d"; - wsprintf(s, pszfmt, ncolhdr + 1, sndFile.ChnSettings[ncolhdr].szName); - DrawButtonRect(hdc, &rect, s, - sndFile.ChnSettings[ncolhdr].dwFlags[CHN_MUTE] ? TRUE : FALSE, - ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER) && ((m_nDragItem & DRAGITEM_VALUEMASK) == ncolhdr)) ? TRUE : FALSE, - pModDoc->IsChannelRecord(static_cast<CHANNELINDEX>(ncolhdr)) ? DT_RIGHT : DT_CENTER); + m_offScreenBitmap.DeleteObject(); + m_offScreenDC.DeleteDC(); + m_offScreenDC.CreateCompatibleDC(pDC); + m_offScreenBitmap.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height()); + m_oldClient = rcClient; + } + hdc = m_offScreenDC; + oldBitmap = SelectBitmap(hdc, m_offScreenBitmap); + } else + { + hdc = pDC->m_hDC; + } - // When dragging around channel headers, mark insertion position - if(m_Status[psDragging] && !m_bInItemRect - && (m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER - && (m_nDropItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER - && (m_nDropItem & DRAGITEM_VALUEMASK) == ncolhdr) - { - RECT r; - r.top = rect.top; - r.bottom = rect.bottom; - // Drop position depends on whether hovered channel is left or right of dragged item. - r.left = ((m_nDropItem & DRAGITEM_VALUEMASK) < (m_nDragItem & DRAGITEM_VALUEMASK) || m_Status[psShiftDragging]) ? rect.left : rect.right - 2; - r.right = r.left + 2; - ::FillRect(hdc, &r, CMainFrame::brushText); - } + HPEN oldpen = SelectPen(hdc, CMainFrame::penDarkGray); + CHANNELINDEX xofs = static_cast<CHANNELINDEX>(GetXScrollPos()); + ROWINDEX yofs = static_cast<ROWINDEX>(GetYScrollPos()); + const CSoundFile &sndFile = pModDoc->GetrSoundFile(); + UINT nColumnWidth = m_szCell.cx; + UINT ncols = sndFile.GetNumChannels(); + int xpaint = m_szHeader.cx; + int ypaint = rcClient.top + m_szHeader.cy; - rect.bottom = rect.top + colHeight; - - CRect insRect; - insRect.SetRect(xpaint, ypaint, xpaint + nColumnWidth / 8 + recordInsX, ypaint + colHeight); - if (pModDoc->IsChannelRecord1(static_cast<CHANNELINDEX>(ncolhdr))) - { - FrameRect(hdc,&rect,CMainFrame::brushGray); - InvertRect(hdc, &rect); - s[0] = '1'; - s[1] = '\0'; - DrawButtonRect(hdc, &insRect, s, FALSE, FALSE, DT_CENTER); - FrameRect(hdc,&insRect,CMainFrame::brushBlack); - } else if (pModDoc->IsChannelRecord2(static_cast<CHANNELINDEX>(ncolhdr))) - { - FrameRect(hdc,&rect,CMainFrame::brushGray); - InvertRect(hdc, &rect); - s[0] = '2'; - s[1] = '\0'; - DrawButtonRect(hdc, &insRect, s, FALSE, FALSE, DT_CENTER); - FrameRect(hdc,&insRect,CMainFrame::brushBlack); - } - - if(m_Status[psShowVUMeters]) - { - OldVUMeters[ncolhdr] = 0; - DrawChannelVUMeter(hdc, rect.left + 1, rect.bottom, ncolhdr); - rect.top += vuHeight; - rect.bottom += vuHeight; - } - if(m_Status[psShowPluginNames]) - { - rect.top += m_szPluginHeader.cy; - rect.bottom += m_szPluginHeader.cy; - mixPlug = sndFile.ChnSettings[ncolhdr].nMixPlugin; - if (mixPlug) - wsprintf(s, "%d: %s", mixPlug, (sndFile.m_MixPlugins[mixPlug - 1]).pMixPlugin ? (sndFile.m_MixPlugins[mixPlug - 1]).GetName() : "[empty]"); - else - wsprintf(s, "---"); - DrawButtonRect(hdc, &rect, s, FALSE, - ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_PLUGNAME) && ((m_nDragItem & DRAGITEM_VALUEMASK) == ncolhdr)) ? TRUE : FALSE, DT_CENTER); - } - - } else break; - ncolhdr++; - xpaint += nColumnWidth; - } + // Scroll tick by tick (always if active row is centered, otherwise only if the top row isn't the first one) + if(doSmoothScroll && liveRecord && (m_Status & (psFollowSong | psDragActive)) == psFollowSong && (m_nMidRow != 0 || yofs > 0)) + { + ypaint -= GetSmoothScrollOffset(); } - ypaint += m_szHeader.cy; if (m_nMidRow) { @@ -677,8 +620,108 @@ { DrawDragSel(hdc); } + + UINT ncolhdr = xofs; + xpaint = m_szHeader.cx; + ypaint = rcClient.top; + rect.SetRect(0, rcClient.top, rcClient.right, rcClient.top + m_szHeader.cy); + if (::RectVisible(hdc, &rect)) + { + sprintf(s, "#%u", m_nPattern); + rect.right = m_szHeader.cx; + DrawButtonRect(hdc, &rect, s, FALSE, + ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_PATTERNHEADER)) ? TRUE : FALSE); + + // Drawing Channel Headers + while (xpaint < rcClient.right) + { + rect.SetRect(xpaint, ypaint, xpaint + nColumnWidth, ypaint + m_szHeader.cy); + if (ncolhdr < ncols) + { + const char *pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr]? "[Channel %u]" : "Channel %u"; + if ((sndFile.GetType() & (MOD_TYPE_XM | MOD_TYPE_IT | MOD_TYPE_MPT)) && sndFile.ChnSettings[ncolhdr].szName[0] != 0) + pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr] ? "%u: [%s]" : "%u: %s"; + else if (m_nDetailLevel < PatternCursor::volumeColumn) pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr] ? "[Ch%u]" : "Ch%u"; + else if (m_nDetailLevel < PatternCursor::effectColumn) pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr] ? "[Chn %u]" : "Chn %u"; + sprintf(s, pszfmt, ncolhdr + 1, sndFile.ChnSettings[ncolhdr].szName); + DrawButtonRect(hdc, &rect, s, + sndFile.ChnSettings[ncolhdr].dwFlags[CHN_MUTE] ? TRUE : FALSE, + ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER) && ((m_nDragItem & DRAGITEM_VALUEMASK) == ncolhdr)) ? TRUE : FALSE, + pModDoc->IsChannelRecord(static_cast<CHANNELINDEX>(ncolhdr)) ? DT_RIGHT : DT_CENTER); + + // When dragging around channel headers, mark insertion position + if(m_Status[psDragging] && !m_bInItemRect + && (m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER + && (m_nDropItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER + && (m_nDropItem & DRAGITEM_VALUEMASK) == ncolhdr) + { + RECT r; + r.top = rect.top; + r.bottom = rect.bottom; + // Drop position depends on whether hovered channel is left or right of dragged item. + r.left = ((m_nDropItem & DRAGITEM_VALUEMASK) < (m_nDragItem & DRAGITEM_VALUEMASK) || m_Status[psShiftDragging]) ? rect.left : rect.right - 2; + r.right = r.left + 2; + ::FillRect(hdc, &r, CMainFrame::brushText); + } + + rect.bottom = rect.top + colHeight; + + CRect insRect; + insRect.SetRect(xpaint, ypaint, xpaint + nColumnWidth / 8 + recordInsX, ypaint + colHeight); + if (pModDoc->IsChannelRecord1(static_cast<CHANNELINDEX>(ncolhdr))) + { + FrameRect(hdc,&rect,CMainFrame::brushGray); + InvertRect(hdc, &rect); + s[0] = '1'; + s[1] = '\0'; + DrawButtonRect(hdc, &insRect, s, FALSE, FALSE, DT_CENTER); + FrameRect(hdc,&insRect,CMainFrame::brushBlack); + } else if (pModDoc->IsChannelRecord2(static_cast<CHANNELINDEX>(ncolhdr))) + { + FrameRect(hdc,&rect,CMainFrame::brushGray); + InvertRect(hdc, &rect); + s[0] = '2'; + s[1] = '\0'; + DrawButtonRect(hdc, &insRect, s, FALSE, FALSE, DT_CENTER); + FrameRect(hdc,&insRect,CMainFrame::brushBlack); + } + + if(m_Status[psShowVUMeters]) + { + OldVUMeters[ncolhdr] = 0; + DrawChannelVUMeter(hdc, rect.left + 1, rect.bottom, ncolhdr); + rect.top += vuHeight; + rect.bottom += vuHeight; + } + if(m_Status[psShowPluginNames]) + { + rect.top += m_szPluginHeader.cy; + rect.bottom += m_szPluginHeader.cy; + PLUGINDEX mixPlug = sndFile.ChnSettings[ncolhdr].nMixPlugin; + if (mixPlug) + sprintf(s, "%u: %s", mixPlug, (sndFile.m_MixPlugins[mixPlug - 1]).pMixPlugin ? (sndFile.m_MixPlugins[mixPlug - 1]).GetName() : "[empty]"); + else + sprintf(s, "---"); + DrawButtonRect(hdc, &rect, s, FALSE, + ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_PLUGNAME) && ((m_nDragItem & DRAGITEM_VALUEMASK) == ncolhdr)) ? TRUE : FALSE, DT_CENTER); + } + + } else break; + ncolhdr++; + xpaint += nColumnWidth; + } + } + if (oldpen) SelectPen(hdc, oldpen); + if(doSmoothScroll) + { + CRect clipRect; + pDC->GetClipBox(clipRect); + pDC->BitBlt(clipRect.left, clipRect.top, clipRect.Width(), clipRect.Height(), &m_offScreenDC, clipRect.left, clipRect.top, SRCCOPY); + SelectBitmap(m_offScreenDC, oldBitmap); + } + //rewbs.fxVis if (m_pEffectVis) { Modified: trunk/OpenMPT/mptrack/GeneralConfigDlg.cpp =================================================================== --- trunk/OpenMPT/mptrack/GeneralConfigDlg.cpp 2015-06-26 21:03:11 UTC (rev 5360) +++ trunk/OpenMPT/mptrack/GeneralConfigDlg.cpp 2015-06-26 21:48:05 UTC (rev 5361) @@ -42,6 +42,7 @@ {PATTERN_PLAYNEWNOTE, "Play new notes while recording", "When this option is enabled, notes entered in the pattern editor will always be played (If not checked, notes won't be played in record mode)."}, {PATTERN_PLAYEDITROW, "Play whole row while recording", "When this option is enabled, all notes on the current row are played when entering notes in the pattern editor."}, {PATTERN_CENTERROW, "Always center active row", "Turn on this option to have the active row always centered in the pattern editor."}, + {PATTERN_SMOOTHSCROLL, "Smooth pattern scrolling", "Scroll patterns tick by tick rather than row by row at the expense of an increased CPU load."}, {PATTERN_HEXDISPLAY, "Display rows in hex", "With this option enabled, row numbers and sequence numbers will be displayed in hexadecimal."}, {PATTERN_WRAP, "Cursor wrap in pattern editor", "When this option is active, going past the end of a pattern row or channel will move the cursor to the beginning. When \"Continuous scroll\"-option is enabled, row wrap is disabled."}, {PATTERN_DRAGNDROPEDIT, "Drag and Drop Editing", "Enable moving a selection in the pattern editor (copying if pressing shift while dragging)"}, Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2015-06-26 21:03:11 UTC (rev 5360) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2015-06-26 21:48:05 UTC (rev 5361) @@ -921,7 +921,7 @@ // Add an entry to the notification history - Notification notification(notifyType, notifyItem, streamPosition, m_pSndFile->m_PlayState.m_nRow, m_pSndFile->m_PlayState.m_nTickCount, m_pSndFile->m_PlayState.m_nCurrentOrder, m_pSndFile->m_PlayState.m_nPattern, m_pSndFile->GetMixStat(), static_cast<uint8>(m_pSndFile->m_MixerSettings.gnChannels)); + Notification notification(notifyType, notifyItem, streamPosition, m_pSndFile->m_PlayState.m_nRow, m_pSndFile->m_PlayState.m_nTickCount, m_pSndFile->GetNumTicksOnCurrentRow(), m_pSndFile->m_PlayState.m_nCurrentOrder, m_pSndFile->m_PlayState.m_nPattern, m_pSndFile->GetMixStat(), static_cast<uint8>(m_pSndFile->m_MixerSettings.gnChannels)); m_pSndFile->ResetMixStat(); Modified: trunk/OpenMPT/mptrack/Notification.h =================================================================== --- trunk/OpenMPT/mptrack/Notification.h 2015-06-26 21:03:11 UTC (rev 5360) +++ trunk/OpenMPT/mptrack/Notification.h 2015-06-26 21:48:05 UTC (rev 5361) @@ -3,8 +3,7 @@ * -------------- * Purpose: GUI update notification struct * Notes : (currently none) - * Authors: Olivier Lapicque - * OpenMPT Devs + * Authors: OpenMPT Devs * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. */ @@ -39,7 +38,7 @@ FlagSet<Notification::Type> type; Item item; // Sample or instrument number, depending on type ROWINDEX row; // Always valid - uint32 tick; // ditto + uint32 tick, ticksOnRow; // ditto ORDERINDEX order; // ditto PATTERNINDEX pattern; // ditto uint32 mixedChannels; // ditto @@ -47,7 +46,7 @@ uint8 masterVUchannels; // ditto SmpLength pos[MAX_CHANNELS]; // Sample / envelope pos for each channel if != PosInvalid, or pattern channel VUs - Notification(FlagSet<Notification::Type> t = Default, Item i = 0, int64 s = 0, ROWINDEX r = 0, uint32 ti = 0, ORDERINDEX o = 0, PATTERNINDEX p = 0, uint32 x = 0, uint8 outChannels = 0) : timestampSamples(s), type(t), item(i), row(r), tick(ti), order(o), pattern(p), mixedChannels(x), masterVUchannels(outChannels) + Notification(FlagSet<Notification::Type> t = Default, Item i = 0, int64 s = 0, ROWINDEX r = 0, uint32 ti = 0, uint32 tir = 0, ORDERINDEX o = 0, PATTERNINDEX p = 0, uint32 x = 0, uint8 outChannels = 0) : timestampSamples(s), type(t), item(i), row(r), tick(ti), ticksOnRow(tir), order(o), pattern(p), mixedChannels(x), masterVUchannels(outChannels) { MemsetZero(masterVU); } Modified: trunk/OpenMPT/mptrack/TrackerSettings.h =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.h 2015-06-26 21:03:11 UTC (rev 5360) +++ trunk/OpenMPT/mptrack/TrackerSettings.h 2015-06-26 21:48:05 UTC (rev 5361) @@ -77,7 +77,7 @@ // Feel free to replace the deprecated flags by new flags, but be sure to // update TrackerSettings::TrackerSettings() as well. #define PATTERN_PLAYNEWNOTE 0x01 // play new notes while recording -//#define PATTERN_LARGECOMMENTS 0x02 // use large font in comments +#define PATTERN_SMOOTHSCROLL 0x02 // scroll tick by tick, not row by row #define PATTERN_STDHIGHLIGHT 0x04 // enable primary highlight (measures) //#define PATTERN_SMALLFONT 0x08 // use small font in pattern editor #define PATTERN_CENTERROW 0x10 // always center active row Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2015-06-26 21:03:11 UTC (rev 5360) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2015-06-26 21:48:05 UTC (rev 5361) @@ -170,6 +170,14 @@ } +CViewPattern::~CViewPattern() +//--------------------------- +{ + m_offScreenBitmap.DeleteObject(); + m_offScreenDC.DeleteDC(); +} + + void CViewPattern::OnInitialUpdate() //---------------------------------- { @@ -182,6 +190,7 @@ m_nPlayPat = PATTERNINDEX_INVALID; m_nPlayRow = 0; m_nPlayTick = 0; + m_nTicksOnRow = 1; m_nMidRow = 0; m_nDragItem = 0; m_bInItemRect = false; @@ -610,18 +619,22 @@ } -bool CViewPattern::SetPlayCursor(PATTERNINDEX pat, ROWINDEX row) -//-------------------------------------------------------------- +bool CViewPattern::SetPlayCursor(PATTERNINDEX pat, ROWINDEX row, uint32 tick) +//--------------------------------------------------------------------------- { PATTERNINDEX oldPat = m_nPlayPat; ROWINDEX oldRow = m_nPlayRow; + uint32 oldTick = m_nPlayTick; m_nPlayPat = pat; m_nPlayRow = row; + m_nPlayTick = tick; - if (oldPat == m_nPattern) + if(m_nPlayTick != oldTick && (TrackerSettings::Instance().m_dwPatternSetup & PATTERN_SMOOTHSCROLL)) + InvalidatePattern(true); + else if (oldPat == m_nPattern) InvalidateRow(oldRow); - if (m_nPlayPat == m_nPattern) + else if (m_nPlayPat == m_nPattern) InvalidateRow(m_nPlayRow); return true; @@ -634,6 +647,7 @@ return SendCtrlMessage(CTRLMSG_GETCURRENTINSTRUMENT); } + bool CViewPattern::ShowEditWindow() //--------------------------------- { @@ -3747,6 +3761,8 @@ } // Don't follow song if user drags selections or scrollbars. + m_nTicksOnRow = pnotify->ticksOnRow; + SetPlayCursor(nPat, nRow, pnotify->tick); if((m_Status & (psFollowSong | psDragActive)) == psFollowSong) { if (nPat < pSndFile->Patterns.Size()) @@ -3770,8 +3786,6 @@ updateOrderList = false; } } - SetPlayCursor(nPat, nRow); - m_nPlayTick = pnotify->tick; } } @@ -3785,7 +3799,7 @@ MemsetZero(ChnVUMeters); // Also zero all non-visible VU meters if((m_Status & (psFollowSong | psDragActive)) == psFollowSong) { - SetPlayCursor(PATTERNINDEX_INVALID, ROWINDEX_INVALID); + SetPlayCursor(PATTERNINDEX_INVALID, ROWINDEX_INVALID, 0); } } @@ -5371,7 +5385,7 @@ newcmd.command = CMD_S3MCMDEX; if(!sndFile.GetModSpecifications().HasCommand(CMD_S3MCMDEX)) newcmd.command = CMD_MODCMDEX; UINT maxSpeed = 0x0F; - if(sndFile.m_PlayState.m_nMusicSpeed > 0) maxSpeed = MIN(0x0F, sndFile.m_PlayState.m_nMusicSpeed - 1); + if(m_nTicksOnRow > 0) maxSpeed = MIN(0x0F, m_nTicksOnRow - 1); newcmd.param = static_cast<ModCommand::PARAM>(0xD0 | MIN(maxSpeed, m_nPlayTick)); } } @@ -5821,8 +5835,8 @@ return; } - const ROWINDEX currentTick = sndFile->m_PlayState.m_nMusicSpeed * row + m_nPlayTick; - const ROWINDEX ticksPerNote = TrackerSettings::Instance().recordQuantizeRows * sndFile->m_PlayState.m_nMusicSpeed; + const ROWINDEX currentTick = m_nTicksOnRow * row + m_nPlayTick; + const ROWINDEX ticksPerNote = TrackerSettings::Instance().recordQuantizeRows * m_nTicksOnRow; // Previous quantization step const ROWINDEX quantLow = (currentTick / ticksPerNote) * ticksPerNote; @@ -5831,10 +5845,10 @@ if(currentTick - quantLow < quantHigh - currentTick) { - row = quantLow / sndFile->m_PlayState.m_nMusicSpeed; + row = quantLow / m_nTicksOnRow; } else { - row = quantHigh / sndFile->m_PlayState.m_nMusicSpeed; + row = quantHigh / m_nTicksOnRow; } if(!sndFile->Patterns[pat].IsValidRow(row)) Modified: trunk/OpenMPT/mptrack/View_pat.h =================================================================== --- trunk/OpenMPT/mptrack/View_pat.h 2015-06-26 21:03:11 UTC (rev 5360) +++ trunk/OpenMPT/mptrack/View_pat.h 2015-06-26 21:48:05 UTC (rev 5361) @@ -157,13 +157,16 @@ protected: CFastBitmap m_Dib; + CDC m_offScreenDC; + CBitmap m_offScreenBitmap; CEditCommand *m_pEditWnd; CPatternGotoDialog *m_pGotoWnd; CSize m_szHeader, m_szPluginHeader, m_szCell; + CRect m_oldClient; UINT m_nMidRow, m_nSpacing, m_nAccelChar, m_nLastPlayedRow, m_nLastPlayedOrder; FlagSet<PatternStatus> m_Status; ROWINDEX m_nPlayRow; - uint32 m_nPlayTick; + uint32 m_nPlayTick, m_nTicksOnRow; PATTERNINDEX m_nPattern, m_nPlayPat; ORDERINDEX m_nOrder; int32 m_nTransposeAmount; @@ -210,6 +213,7 @@ CEffectVis *m_pEffectVis; //rewbs.fxVis CViewPattern(); + ~CViewPattern(); DECLARE_SERIAL(CViewPattern) public: @@ -230,6 +234,7 @@ int GetYScrollPos() const { return m_nYScroll; } int GetColumnWidth() const { return m_szCell.cx; } int GetColumnHeight() const { return m_szCell.cy; } + int GetSmoothScrollOffset() const; PATTERNINDEX GetCurrentPattern() const { return m_nPattern; } ROWINDEX GetCurrentRow() const { return m_Cursor.GetRow(); } @@ -271,7 +276,7 @@ // This should be used instead of consecutive calls to SetCurrentRow() then SetCurrentColumn() bool SetCursorPosition(const PatternCursor &cursor, bool wrap = false); bool DragToSel(const PatternCursor &cursor, bool scrollHorizontal, bool scrollVertical, bool noMove = false); - bool SetPlayCursor(PATTERNINDEX pat, ROWINDEX row); + bool SetPlayCursor(PATTERNINDEX pat, ROWINDEX row, uint32 tick); bool UpdateScrollbarPositions(bool updateHorizontalScrollbar = true); BYTE EnterNote(UINT nNote, UINT nIns=0, BOOL bCheck=FALSE, int vol=-1, BOOL bMultiCh=FALSE); bool ShowEditWindow(); Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2015-06-26 21:03:11 UTC (rev 5360) +++ trunk/OpenMPT/soundlib/Sndfile.h 2015-06-26 21:48:05 UTC (rev 5361) @@ -872,12 +872,12 @@ void DoFreqSlide(ModChannel *pChn, int32 nFreqSlide) const; void UpdateTimeSignature(); +public: uint32 GetNumTicksOnCurrentRow() const { return (m_PlayState.m_nMusicSpeed + m_PlayState.m_nFrameDelay) * MAX(m_PlayState.m_nPatternDelay, 1); } -public: bool DestroySample(SAMPLEINDEX nSample); bool DestroySampleThreadsafe(SAMPLEINDEX nSample); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |