From: <sag...@us...> - 2010-12-13 15:23:45
|
Revision: 772 http://modplug.svn.sourceforge.net/modplug/?rev=772&view=rev Author: saga-games Date: 2010-12-13 15:23:38 +0000 (Mon, 13 Dec 2010) Log Message: ----------- [Imp] Pattern Editor: The new "select whole row" feature now also autoscrolls the pattern. [Ref] Some refactoring (IT Saver: Using IsPatternEmpty, const modifiers in modcommand.h, refactored visited rows code for future expansion) [Mod] OpenMPT: Version is now 1.19.00.15 Modified Paths: -------------- trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/modcommand.h Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2010-12-06 23:54:31 UTC (rev 771) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2010-12-13 15:23:38 UTC (rev 772) @@ -512,6 +512,11 @@ } +// Drag a selection to position dwPos. +// If bScroll is true, the point dwPos is scrolled into the view if needed. +// If bNoMode if specified, the original selection points are not altered. +// Note that scrolling will only be executed if dwPos contains legal coordinates. +// This can be useful when selecting a whole row and specifying 0xFFFF as the end channel. BOOL CViewPattern::DragToSel(DWORD dwPos, BOOL bScroll, BOOL bNoMove) //------------------------------------------------------------------- { @@ -1322,7 +1327,7 @@ // Mark row number => mark whole row (continue) InvalidateSelection(); m_dwEndSel = GetPositionFromPoint(point) | 0xFFFF; - SetCurSel(m_dwStartSel, m_dwEndSel); + DragToSel(m_dwEndSel, TRUE, FALSE); } else if (m_dwStatus & PATSTATUS_MOUSEDRAGSEL) { CModDoc *pModDoc = GetDocument(); Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2010-12-06 23:54:31 UTC (rev 771) +++ trunk/OpenMPT/mptrack/version.h 2010-12-13 15:23:38 UTC (rev 772) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 19 #define VER_MINOR 00 -#define VER_MINORMINOR 14 +#define VER_MINORMINOR 15 //Creates version number from version parts that appears in version string. //For example MAKE_VERSION_NUMERIC(1,17,02,28) gives version number of Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2010-12-06 23:54:31 UTC (rev 771) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2010-12-13 15:23:38 UTC (rev 772) @@ -1637,22 +1637,12 @@ bNeedsMptPatSave = true; // Check for empty pattern - if (Patterns[npat].GetNumRows() == 64) + if (Patterns[npat].GetNumRows() == 64 && Patterns.IsPatternEmpty(npat)) { - MODCOMMAND *pzc = Patterns[npat]; - UINT nz = Patterns[npat].GetNumRows() * m_nChannels; - UINT iz = 0; - for (iz=0; iz<nz; iz++) - { - if ((pzc[iz].note) || (pzc[iz].instr) - || (pzc[iz].volcmd) || (pzc[iz].command)) break; - } - if (iz == nz) - { - patpos[npat] = 0; - continue; - } + patpos[npat] = 0; + continue; } + fwrite(patinfo, 8, 1, f); dwPos += 8; memset(chnmask, 0xFF, sizeof(chnmask)); @@ -2237,23 +2227,14 @@ patinfo[1] = Patterns[npat].GetNumRows(); patinfo[2] = 0; patinfo[3] = 0; + // Check for empty pattern - if (Patterns[npat].GetNumRows() == 64) + if (Patterns[npat].GetNumRows() == 64 && Patterns.IsPatternEmpty(npat)) { - MODCOMMAND *pzc = Patterns[npat]; - UINT nz = Patterns[npat].GetNumRows() * nChannels; - UINT iz = 0; - for (iz=0; iz<nz; iz++) - { - if ((pzc[iz].note) || (pzc[iz].instr) - || (pzc[iz].volcmd) || (pzc[iz].command)) break; - } - if (iz == nz) - { - patpos[npat] = 0; - continue; - } + patpos[npat] = 0; + continue; } + fwrite(patinfo, 8, 1, f); dwPos += 8; memset(chnmask, 0xFF, sizeof(chnmask)); Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-12-06 23:54:31 UTC (rev 771) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-12-13 15:23:38 UTC (rev 772) @@ -78,10 +78,6 @@ { bool dummy = false; double result = GetLength(dummy, bAdjust, endOrder, endRow); - if(!bAdjust) - { - InitializeVisitedRows(true); // forget that we went over the whole module. - } return result; } @@ -106,28 +102,22 @@ // -! NEW_FEATURE#0022 UINT nMusicSpeed = m_nDefaultSpeed, nMusicTempo = m_nDefaultTempo, nNextRow = 0; LONG nGlbVol = m_nDefaultGlobalVolume, nOldGlbVolSlide = 0; - vector<BYTE> instr; - vector<UINT> notes; - vector<BYTE> vols; - vector<BYTE> oldparam; - vector<UINT> chnvols; - vector<double> patloop; - vector<ROWINDEX> patloopstart; - - notes.resize(m_nChannels, 0); - instr.resize(m_nChannels, 0); - vols.resize(m_nChannels, 0xFF); - oldparam.resize(m_nChannels, 0); - chnvols.resize(m_nChannels, 64); - patloop.resize(m_nChannels, 0); - patloopstart.resize(m_nChannels, 0); + vector<BYTE> instr(m_nChannels, 0); + vector<UINT> notes(m_nChannels, 0); + vector<BYTE> vols(m_nChannels, 0xFF); + vector<BYTE> oldparam(m_nChannels, 0); + vector<UINT> chnvols(m_nChannels, 64); + vector<double> patloop(m_nChannels, 0); + vector<ROWINDEX> patloopstart(m_nChannels, 0); + VisitedRowsType visitedRows; // temporary visited rows vector (so that GetLength() won't interfere with the player code if the module is playing at the same time) + + InitializeVisitedRows(true, &visitedRows); + for(CHANNELINDEX icv = 0; icv < m_nChannels; icv++) chnvols[icv] = ChnSettings[icv].nVolume; nCurrentPattern = nNextPattern = 0; nPattern = Order[0]; nRow = nNextRow = 0; - InitializeVisitedRows(true); - for (;;) { UINT nSpeedCount = 0; @@ -157,7 +147,7 @@ } nPattern = (nCurrentPattern < Order.size()) ? Order[nCurrentPattern] : Order.GetInvalidPatIndex(); nNextPattern = nCurrentPattern; - if((!Patterns.IsValidPat(nPattern)) && IsRowVisited(nCurrentPattern, 0, true)) + if((!Patterns.IsValidPat(nPattern)) && IsRowVisited(nCurrentPattern, 0, true, &visitedRows)) break; } // Skip non-existing patterns @@ -180,7 +170,7 @@ break; } - if(IsRowVisited(nCurrentPattern, nRow, true)) + if(IsRowVisited(nCurrentPattern, nRow, true, &visitedRows)) break; // Update next position @@ -458,6 +448,8 @@ m_nMusicTempo = m_nDefaultTempo; m_nGlobalVolume = m_nDefaultGlobalVolume; } + // When adjusting the playback status, we will also want to update the visited rows vector according to the current position. + m_bVisitedRows = visitedRows; } return dElapsedTime / 1000.0; @@ -4220,8 +4212,8 @@ Specific implementations: Length detection code: - As the ModPlug engine already deals with pattern loops sufficiently, there's no problem with (infinite) pattern loops - in this code. + As the ModPlug engine already deals with pattern loops sufficiently (though not always correctly), + there's no problem with (infinite) pattern loops in this code. Normal player code: Bare in mind that rows inside pattern loops should only be evaluated once, or else the algorithm will cancel too early! @@ -4229,65 +4221,97 @@ */ -void CSoundFile::InitializeVisitedRows(const bool bReset) -//------------------------------------------------------- +// Resize / Clear the row vector. +// If bReset is true, the vector is not only resized to the required dimensions, but also completely cleared (i.e. all visited rows are unset). +// If pRowVector is specified, an alternative row vector instead of the module's global one will be used (f.e. when using GetLength()). +void CSoundFile::InitializeVisitedRows(const bool bReset, VisitedRowsType *pRowVector) +//------------------------------------------------------------------------------------ { - m_bVisitedRows.resize(Order.GetLengthTailTrimmed()); + if(pRowVector == nullptr) + { + pRowVector = &m_bVisitedRows; + } + pRowVector->resize(Order.GetLengthTailTrimmed()); for(ORDERINDEX nOrd = 0; nOrd < Order.GetLengthTailTrimmed(); nOrd++) { - // If we want to reset the vectors completely, we overwrite exisiting items with 0. + VisitedRowsBaseType *pRow = &(pRowVector->at(nOrd)); + // If we want to reset the vectors completely, we overwrite existing items with false. if(bReset) { - for(size_t i = 0; i < m_bVisitedRows[nOrd].size(); i++) - { - m_bVisitedRows[nOrd][i] = false; - } + pRow->assign(pRow->size(), false); } - m_bVisitedRows[nOrd].resize(GetVisitedRowsVectorSize(Order[nOrd]), false); + pRow->resize(GetVisitedRowsVectorSize(Order[nOrd]), false); } } // (Un)sets a given row as visited. -void CSoundFile::SetRowVisited(const ORDERINDEX nOrd, const ROWINDEX nRow, const bool bVisited) -//--------------------------------------------------------------------------------------------- +// nOrd, nRow - which row should be (un)set +// If bVisited is true, the row will be set as visited. +// If pRowVector is specified, an alternative row vector instead of the module's global one will be used (f.e. when using GetLength()). +void CSoundFile::SetRowVisited(const ORDERINDEX nOrd, const ROWINDEX nRow, const bool bVisited, VisitedRowsType *pRowVector) +//-------------------------------------------------------------------------------------------------------------------------- { const ORDERINDEX nMaxOrd = Order.GetLengthTailTrimmed(); if(nOrd >= nMaxOrd || nRow > Patterns[Order[nOrd]].GetNumRows()) + { return; + } + if(pRowVector == nullptr) + { + pRowVector = &m_bVisitedRows; + } + // The module might have been edited in the meantime - so we have to extend this a bit. - if(nOrd >= m_bVisitedRows.size() || nRow >= m_bVisitedRows[nOrd].size()) - InitializeVisitedRows(false); + if(nOrd >= pRowVector->size() || nRow >= pRowVector->at(nOrd).size()) + { + InitializeVisitedRows(false, pRowVector); + } - m_bVisitedRows[nOrd][nRow] = bVisited; + pRowVector->at(nOrd)[nRow] = bVisited; } // Returns if a given row has been visited yet. // If bAutoSet is true, the queried row will automatically be marked as visited. -// Use this parameter instead of consecutive IsRowVisited/SetRowVisited calls, as it's faster. -bool CSoundFile::IsRowVisited(const ORDERINDEX nOrd, const ROWINDEX nRow, const bool bAutoSet) -//-------------------------------------------------------------------------------------------- +// Use this parameter instead of consecutive IsRowVisited/SetRowVisited calls. +// If pRowVector is specified, an alternative row vector instead of the module's global one will be used (f.e. when using GetLength()). +bool CSoundFile::IsRowVisited(const ORDERINDEX nOrd, const ROWINDEX nRow, const bool bAutoSet, VisitedRowsType *pRowVector) +//------------------------------------------------------------------------------------------------------------------------- { const ORDERINDEX nMaxOrd = Order.GetLengthTailTrimmed(); if(nOrd >= nMaxOrd) + { return false; + } + if(pRowVector == nullptr) + { + pRowVector = &m_bVisitedRows; + } + // The row slot for this row has not been assigned yet - Just return false, as this means that the program has not played the row yet. - if(nOrd >= m_bVisitedRows.size() || nRow >= m_bVisitedRows[nOrd].size()) + if(nOrd >= pRowVector->size() || nRow >= pRowVector->at(nOrd).size()) { if(bAutoSet) - SetRowVisited(nOrd, nRow, true); + { + SetRowVisited(nOrd, nRow, true, pRowVector); + } return false; } - if(m_bVisitedRows[nOrd][nRow]) - return true; // we visited this row already - this module must be looping. + if(pRowVector->at(nOrd)[nRow]) + { + // we visited this row already - this module must be looping. + return true; + } if(bAutoSet) - m_bVisitedRows[nOrd][nRow] = true; + { + pRowVector->at(nOrd)[nRow] = true; + } return false; } @@ -4298,7 +4322,12 @@ //------------------------------------------------------------------ { if(Patterns.IsValidPat(nPat)) + { return (size_t)(Patterns[nPat].GetNumRows()); + } else - return 1; // invalid patterns consist of a "fake" row. + { + // invalid patterns consist of a "fake" row. + return 1; + } } \ No newline at end of file Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2010-12-06 23:54:31 UTC (rev 771) +++ trunk/OpenMPT/soundlib/Sndfile.h 2010-12-13 15:23:38 UTC (rev 772) @@ -470,10 +470,11 @@ ORDERINDEX order; // which order is this? }; +// Data type for the visited rows routines. +typedef vector<bool> VisitedRowsBaseType; +typedef vector<VisitedRowsBaseType> VisitedRowsType; -class CSoundFile; - //Note: These are bit indeces. MSF <-> Mod(Specific)Flag. //If changing these, ChangeModTypeTo() might need modification. const BYTE MSF_COMPATIBLE_PLAY = 0; //IT/MPT/XM @@ -553,7 +554,7 @@ const CModSpecifications* m_pModSpecs; // For handling backwards jumps and stuff to prevent infinite loops when counting the mod length or rendering to wav. - vector<vector<bool> > m_bVisitedRows; + VisitedRowsType m_bVisitedRows; @@ -689,6 +690,7 @@ //Returns song length in seconds. DWORD GetSongTime() { return static_cast<DWORD>((m_nTempoMode == tempo_mode_alternative) ? GetLength(false) + 1.0 : GetLength(false) + 0.5); } + // A repeat count value of -1 means infinite loop void SetRepeatCount(int n) { m_nRepeatCount = n; } int GetRepeatCount() const { return m_nRepeatCount; } bool IsPaused() const { return (m_dwSongFlags & (SONG_PAUSED|SONG_STEP)) ? true : false; } // Added SONG_STEP as it seems to be desirable in most cases to check for this as well. @@ -1023,10 +1025,10 @@ // A couple of functions for handling backwards jumps and stuff to prevent infinite loops when counting the mod length or rendering to wav. public: - void InitializeVisitedRows(const bool bReset = true); + void InitializeVisitedRows(const bool bReset = true, VisitedRowsType *pRowVector = nullptr); private: - void SetRowVisited(const ORDERINDEX nOrd, const ROWINDEX nRow, const bool bVisited = true); - bool IsRowVisited(const ORDERINDEX nOrd, const ROWINDEX nRow, const bool bAutoSet = true); + void SetRowVisited(const ORDERINDEX nOrd, const ROWINDEX nRow, const bool bVisited = true, VisitedRowsType *pRowVector = nullptr); + bool IsRowVisited(const ORDERINDEX nOrd, const ROWINDEX nRow, const bool bAutoSet = true, VisitedRowsType *pRowVector = nullptr); size_t GetVisitedRowsVectorSize(const PATTERNINDEX nPat); public: Modified: trunk/OpenMPT/soundlib/modcommand.h =================================================================== --- trunk/OpenMPT/soundlib/modcommand.h 2010-12-06 23:54:31 UTC (rev 771) +++ trunk/OpenMPT/soundlib/modcommand.h 2010-12-13 15:23:38 UTC (rev 772) @@ -53,7 +53,7 @@ // Returns true if modcommand is empty, false otherwise. // If ignoreEffectValues is true (default), effect values are ignored are ignored if there is no effect command present. - bool IsEmpty(bool ignoreEffectValues = true) const + bool IsEmpty(const bool ignoreEffectValues = true) const { if(ignoreEffectValues) return (this->note == 0 && this->instr == 0 && this->volcmd == 0 && this->command == 0); @@ -66,7 +66,7 @@ // Returns true if and only if note is NOTE_PC or NOTE_PCS. bool IsPcNote() const { return note == NOTE_PC || note == NOTE_PCS; } - static bool IsPcNote(NOTE note_id) { return note_id == NOTE_PC || note_id == NOTE_PCS; } + static bool IsPcNote(const NOTE note_id) { return note_id == NOTE_PC || note_id == NOTE_PCS; } // Swap volume and effect column (doesn't do any conversion as it's mainly for importing formats with multiple effect columns, so beware!) void SwapEffects() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |