From: <sag...@us...> - 2014-02-10 23:02:06
|
Revision: 3695 http://sourceforge.net/p/modplug/code/3695 Author: saga-games Date: 2014-02-10 23:01:57 +0000 (Mon, 10 Feb 2014) Log Message: ----------- [New] Added sample redo functionality + undo names Modified Paths: -------------- trunk/OpenMPT/mptrack/CleanupSong.cpp trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/ModConvert.cpp trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/Undo.cpp trunk/OpenMPT/mptrack/Undo.h trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/mptrack/View_smp.h trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/soundlib/Sndfile.cpp Modified: trunk/OpenMPT/mptrack/CleanupSong.cpp =================================================================== --- trunk/OpenMPT/mptrack/CleanupSong.cpp 2014-02-10 21:23:39 UTC (rev 3694) +++ trunk/OpenMPT/mptrack/CleanupSong.cpp 2014-02-10 23:01:57 UTC (rev 3695) @@ -499,7 +499,7 @@ if(!sndFile.IsSampleUsed(smp)) { samplesUsed[smp] = false; - modDoc.GetSampleUndo().PrepareUndo(smp, sundo_delete); + modDoc.GetSampleUndo().PrepareUndo(smp, sundo_delete, "Remove Unused Sample"); } } @@ -584,7 +584,7 @@ SmpLength lmax = loopLength + 2; if(lmax < sample.nLength && lmax >= 2) { - modDoc.GetSampleUndo().PrepareUndo(nSmp, sundo_delete, lmax, sample.nLength); + modDoc.GetSampleUndo().PrepareUndo(nSmp, sundo_delete, "Trim Unused Data", lmax, sample.nLength); ctrlSmp::ResizeSample(sample, lmax, sndFile); } } Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-02-10 21:23:39 UTC (rev 3694) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2014-02-10 23:01:57 UTC (rev 3695) @@ -752,7 +752,7 @@ return false; } - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Replace"); bool bOk = m_sndFile.ReadSampleFromFile(m_nSample, file, TrackerSettings::Instance().m_MayNormalizeSamplesOnLoad); ModSample &sample = m_sndFile.GetSample(m_nSample); @@ -850,7 +850,7 @@ BeginWaitCursor(); - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Replace"); m_sndFile.ReadSampleFromSong(m_nSample, sndFile, nSample); ModSample &sample = m_sndFile.GetSample(m_nSample); if((m_sndFile.GetType() & MOD_TYPE_XM) && (!(sample.uFlags & CHN_PANNING))) @@ -922,7 +922,7 @@ if(duplicate && nOldSmp >= 1 && nOldSmp <= sndFile.GetNumSamples()) { - m_modDoc.GetSampleUndo().PrepareUndo(smp, sundo_replace); + m_modDoc.GetSampleUndo().PrepareUndo(smp, sundo_replace, "Duplicate"); sndFile.ReadSampleFromSong(smp, sndFile, nOldSmp); } @@ -1159,7 +1159,7 @@ } } - m_modDoc.GetSampleUndo().PrepareUndo(iSmp, sundo_update, selStart, selEnd); + m_modDoc.GetSampleUndo().PrepareUndo(iSmp, sundo_update, "Normalize", selStart, selEnd); if(sample.uFlags & CHN_STEREO) { selStart *= 2; selEnd *= 2; } @@ -1230,7 +1230,7 @@ SampleSelectionPoints selection = GetSelectionPoints(); - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_update, selection.nStart, selection.nEnd); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_update, "Amplify", selection.nStart, selection.nEnd); if (sample.uFlags & CHN_STEREO) { selection.nStart *= 2; selection.nEnd *= 2; } SmpLength len = selection.nEnd - selection.nStart; @@ -1309,7 +1309,7 @@ selEnd = selection.nEnd; } - m_modDoc.GetSampleUndo().PrepareUndo(iSmp, sundo_update, selStart, selEnd); + m_modDoc.GetSampleUndo().PrepareUndo(iSmp, sundo_update, "Remove DC Offset", selStart, selEnd); const float fOffset = ctrlSmp::RemoveDCOffset(m_sndFile.GetSample(iSmp), selStart, selEnd, m_sndFile.GetType(), m_sndFile); @@ -1417,7 +1417,7 @@ if (dwNewLen <= MAX_SAMPLE_LENGTH) pNewSample = ModSample::AllocateSample(dwNewLen, newsmplsize); if (pNewSample) { - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Upsample"); const UINT nCh = sample.GetNumChannels(); for (UINT iCh=0; iCh<nCh; iCh++) @@ -1554,7 +1554,7 @@ if (pNewSample) { - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Downsample"); const UINT nCh = sample.GetNumChannels(); for (UINT iCh=0; iCh<nCh; iCh++) @@ -1975,7 +1975,7 @@ ASSERT(nNewSampleLength >= nLengthCounter); - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Time Stretch"); // Swap sample buffer pointer to new buffer, update song + sample data & free old sample buffer ctrlSmp::ReplaceSample(sample, (LPSTR)pNewSample, std::min(nLengthCounter, nNewSampleLength), m_sndFile); @@ -2056,7 +2056,7 @@ float * buffer = new float[MAX_BUFFER_LENGTH + fft]; float * outbuf = new float[MAX_BUFFER_LENGTH + fft]; - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Pitch Shift"); // Process each channel separately for(UINT i = 0 ; i < nChn ; i++){ @@ -2176,7 +2176,7 @@ SampleSelectionPoints selection = GetSelectionPoints(); - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_reverse, selection.nStart, selection.nEnd); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_reverse, "Reverse", selection.nStart, selection.nEnd); if(ctrlSmp::ReverseSample(sample, selection.nStart, selection.nEnd, m_sndFile)) { m_modDoc.UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA, NULL); @@ -2197,7 +2197,7 @@ SampleSelectionPoints selection = GetSelectionPoints(); - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_invert, selection.nStart, selection.nEnd); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_invert, "Invert", selection.nStart, selection.nEnd); if(ctrlSmp::InvertSample(sample, selection.nStart, selection.nEnd, m_sndFile) == true) { m_modDoc.UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA, NULL); @@ -2223,7 +2223,7 @@ ModSample &sample = m_sndFile.GetSample(m_nSample); SampleSelectionPoints selection = GetSelectionPoints(); - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_unsign, selection.nStart, selection.nEnd); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_unsign, "Unsign", selection.nStart, selection.nEnd); if(ctrlSmp::UnsignSample(sample, selection.nStart, selection.nEnd, m_sndFile) == true) { m_modDoc.UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEDATA, NULL); @@ -2248,7 +2248,7 @@ if(selection.selectionActive == true) { ModSample &sample = m_sndFile.GetSample(m_nSample); - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_update, selection.nStart, selection.nEnd); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_update, "Silence", selection.nStart, selection.nEnd); SmpLength len = selection.nEnd - selection.nStart; if (sample.uFlags & CHN_STEREO) @@ -3102,7 +3102,7 @@ if(fadeLength < 4) return; - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_update, sample.nLoopEnd - fadeLength, sample.nLoopEnd); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_update, "Crossfade", sample.nLoopEnd - fadeLength, sample.nLoopEnd); // If we want to fade nFadeLength bytes, we need as much sample material before the loop point. nFadeLength has been adjusted above. if(sample.nLoopStart < fadeLength) { @@ -3138,7 +3138,7 @@ if(dlg.DoModal() == IDOK) { BeginWaitCursor(); - m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_none); + m_modDoc.GetSampleUndo().PrepareUndo(m_nSample, sundo_none, "Automatic Sample Tuning"); at.Apply(static_cast<double>(dlg.GetPitchReference()), dlg.GetTargetNote()); m_modDoc.UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO, NULL); m_modDoc.SetModified(); Modified: trunk/OpenMPT/mptrack/ModConvert.cpp =================================================================== --- trunk/OpenMPT/mptrack/ModConvert.cpp 2014-02-10 21:23:39 UTC (rev 3694) +++ trunk/OpenMPT/mptrack/ModConvert.cpp 2014-02-10 23:01:57 UTC (rev 3695) @@ -337,7 +337,7 @@ for(SAMPLEINDEX smp = 1; smp <= m_SndFile.GetNumSamples(); smp++) { ModSample &sample = m_SndFile.GetSample(smp); - GetSampleUndo().PrepareUndo(smp, sundo_none); + GetSampleUndo().PrepareUndo(smp, sundo_none, "Song Conversion"); // Too many samples? Only 31 samples allowed in MOD format... if(newTypeIsMOD && smp > 31 && sample.nLength > 0) Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2014-02-10 21:23:39 UTC (rev 3694) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2014-02-10 23:01:57 UTC (rev 3695) @@ -279,7 +279,7 @@ { if(newOrder[i] != i + 1) { - GetSampleUndo().PrepareUndo(i + 1, sundo_replace); + GetSampleUndo().PrepareUndo(i + 1, sundo_replace, "Rearrange"); } } Modified: trunk/OpenMPT/mptrack/Undo.cpp =================================================================== --- trunk/OpenMPT/mptrack/Undo.cpp 2014-02-10 21:23:39 UTC (rev 3694) +++ trunk/OpenMPT/mptrack/Undo.cpp 2014-02-10 23:01:57 UTC (rev 3695) @@ -31,10 +31,20 @@ } +// Create undo point. +// Parameter list: +// - pattern: Pattern of which an undo step should be created from. +// - firstChn: first channel, 0-based. +// - firstRow: first row, 0-based. +// - numChns: width +// - numRows: height +// - description: Short description text of action for undo menu. +// - linkToPrevious: Don't create a separate undo step, but link this to the previous undo event. Use this for commands that modify several patterns at once. +// - storeChannelInfo: Also store current channel header information (pan / volume / etc. settings) and number of channels in this undo point. bool CPatternUndo::PrepareUndo(PATTERNINDEX pattern, CHANNELINDEX firstChn, ROWINDEX firstRow, CHANNELINDEX numChns, ROWINDEX numRows, const char *description, bool linkToPrevious, bool storeChannelInfo) //--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- { - if(PrepareUndo(UndoBuffer, pattern, firstChn, firstRow, numChns, numRows, description, linkToPrevious, storeChannelInfo)) + if(PrepareBuffer(UndoBuffer, pattern, firstChn, firstRow, numChns, numRows, description, linkToPrevious, storeChannelInfo)) { ClearBuffer(RedoBuffer); return true; @@ -43,18 +53,8 @@ } -// Create undo point. -// Parameter list: -// - pattern: Pattern of which an undo step should be created from. -// - firstChn: first channel, 0-based. -// - firstRow: first row, 0-based. -// - numChns: width -// - numRows: height -// - description: Short description text of action for undo menu. -// - linkToPrevious: Don't create a separate undo step, but link this to the previous undo event. Use this for commands that modify several patterns at once. -// - storeChannelInfo: Also store current channel header information (pan / volume / etc. settings) and number of channels in this undo point. -bool CPatternUndo::PrepareUndo(undobuf_t &buffer, PATTERNINDEX pattern, CHANNELINDEX firstChn, ROWINDEX firstRow, CHANNELINDEX numChns, ROWINDEX numRows, const char *description, bool linkToPrevious, bool storeChannelInfo) -//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +bool CPatternUndo::PrepareBuffer(undobuf_t &buffer, PATTERNINDEX pattern, CHANNELINDEX firstChn, ROWINDEX firstRow, CHANNELINDEX numChns, ROWINDEX numRows, const char *description, bool linkToPrevious, bool storeChannelInfo) +//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ { const CSoundFile &sndFile = modDoc.GetrSoundFile(); @@ -70,19 +70,19 @@ // Remove an undo step if there are too many. while(buffer.size() >= MAX_UNDO_LEVEL) { - DeleteUndoStep(buffer, 0); + DeleteStep(buffer, 0); } - UndoInfo sUndo; - sUndo.pattern = pattern; - sUndo.numPatternRows = sndFile.Patterns[pattern].GetNumRows(); - sUndo.firstChannel = firstChn; - sUndo.firstRow = firstRow; - sUndo.numChannels = numChns; - sUndo.numRows = numRows; - sUndo.pbuffer = pUndoData; - sUndo.linkToPrevious = linkToPrevious; - sUndo.description = description; + UndoInfo undo; + undo.pattern = pattern; + undo.numPatternRows = sndFile.Patterns[pattern].GetNumRows(); + undo.firstChannel = firstChn; + undo.firstRow = firstRow; + undo.numChannels = numChns; + undo.numRows = numRows; + undo.pbuffer = pUndoData; + undo.linkToPrevious = linkToPrevious; + undo.description = description; const ModCommand *pPattern = sndFile.Patterns[pattern].GetpModCommand(firstRow, firstChn); for(ROWINDEX iy = 0; iy < numRows; iy++) { @@ -93,14 +93,14 @@ if(storeChannelInfo) { - sUndo.channelInfo = new UndoInfo::ChannelInfo(sndFile.GetNumChannels()); - memcpy(sUndo.channelInfo->settings, sndFile.ChnSettings, sizeof(ModChannelSettings) * sndFile.GetNumChannels()); + undo.channelInfo = new UndoInfo::ChannelInfo(sndFile.GetNumChannels()); + memcpy(undo.channelInfo->settings, sndFile.ChnSettings, sizeof(ModChannelSettings) * sndFile.GetNumChannels()); } else { - sUndo.channelInfo = nullptr; + undo.channelInfo = nullptr; } - buffer.push_back(sUndo); + buffer.push_back(undo); modDoc.UpdateAllViews(NULL, HINT_UNDO); return true; @@ -137,7 +137,7 @@ // Select most recent undo slot const UndoInfo &undo = fromBuf.back(); - PrepareUndo(toBuf, undo.pattern, undo.firstChannel, undo.firstRow, undo.numChannels, undo.numRows, undo.description, linkedFromPrevious, undo.channelInfo != nullptr); + PrepareBuffer(toBuf, undo.pattern, undo.firstChannel, undo.firstRow, undo.numChannels, undo.numRows, undo.description, linkedFromPrevious, undo.channelInfo != nullptr); if(undo.channelInfo != nullptr) { @@ -169,7 +169,7 @@ { if(!sndFile.Patterns[nPattern].AllocatePattern(undo.numPatternRows)) { - DeleteUndoStep(fromBuf, fromBuf.size() - 1); + DeleteStep(fromBuf, fromBuf.size() - 1); return PATTERNINDEX_INVALID; } } else if(sndFile.Patterns[nPattern].GetNumRows() != undo.numPatternRows) @@ -188,9 +188,9 @@ } } - DeleteUndoStep(fromBuf, fromBuf.size() - 1); + DeleteStep(fromBuf, fromBuf.size() - 1); - if(fromBuf.empty()) modDoc.UpdateAllViews(NULL, HINT_UNDO); + modDoc.UpdateAllViews(NULL, HINT_UNDO); if(linkToPrevious) { @@ -205,16 +205,16 @@ void CPatternUndo::ClearBuffer(undobuf_t &buffer) //----------------------------------------------- { - while(buffer.size() > 0) + while(!buffer.empty()) { - DeleteUndoStep(buffer, buffer.size() - 1); + DeleteStep(buffer, buffer.size() - 1); } } // Delete a given undo / redo step. -void CPatternUndo::DeleteUndoStep(undobuf_t &buffer, size_t step) -//--------------------------------------------------------------- +void CPatternUndo::DeleteStep(undobuf_t &buffer, size_t step) +//----------------------------------------------------------- { if(step >= buffer.size()) return; delete[] buffer[step].pbuffer; @@ -228,7 +228,7 @@ //------------------------------------- { if(!CanUndo()) return; - DeleteUndoStep(UndoBuffer, UndoBuffer.size() - 1); + DeleteStep(UndoBuffer, UndoBuffer.size() - 1); } @@ -264,21 +264,23 @@ { for(SAMPLEINDEX smp = 1; smp <= MAX_SAMPLES; smp++) { - ClearUndo(smp); + ClearUndo(UndoBuffer, smp); + ClearUndo(RedoBuffer, smp); } UndoBuffer.clear(); + RedoBuffer.clear(); } // Remove all undo steps of a given sample. -void CSampleUndo::ClearUndo(const SAMPLEINDEX smp) -//------------------------------------------------ +void CSampleUndo::ClearUndo(undobuf_t &buffer, const SAMPLEINDEX smp) +//------------------------------------------------------------------- { - if(!SampleBufferExists(smp, false)) return; + if(!SampleBufferExists(buffer, smp)) return; - while(UndoBuffer[smp - 1].size() > 0) + while(!buffer[smp - 1].empty()) { - DeleteUndoStep(smp, 0); + DeleteStep(buffer, smp, 0); } } @@ -286,27 +288,44 @@ // Create undo point for given sample. // The main program has to tell what kind of changes are going to be made to the sample. // That way, a lot of RAM can be saved, because some actions don't even require an undo sample buffer. -bool CSampleUndo::PrepareUndo(const SAMPLEINDEX smp, sampleUndoTypes changeType, SmpLength changeStart, SmpLength changeEnd) -//-------------------------------------------------------------------------------------------------------------------------- -{ - if(!SampleBufferExists(smp)) return false; +bool CSampleUndo::PrepareUndo(const SAMPLEINDEX smp, sampleUndoTypes changeType, const char *description, SmpLength changeStart, SmpLength changeEnd) +//--------------------------------------------------------------------------------------------------------------------------------------------------- +{ + if(PrepareBuffer(UndoBuffer, smp, changeType, description, changeStart, changeEnd)) + { + ClearUndo(RedoBuffer, smp); + return true; + } + return false; +} + +bool CSampleUndo::PrepareBuffer(undobuf_t &buffer, const SAMPLEINDEX smp, sampleUndoTypes changeType, const char *description, SmpLength changeStart, SmpLength changeEnd) +//------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +{ + if(smp == 0 || smp >= MAX_SAMPLES) return false; + if(smp > buffer.size()) + { + buffer.resize(smp); + } + // Remove an undo step if there are too many. - while(UndoBuffer[smp - 1].size() >= MAX_UNDO_LEVEL) + while(buffer[smp - 1].size() >= MAX_UNDO_LEVEL) { - DeleteUndoStep(smp, 0); + DeleteStep(buffer, smp, 0); } // Create new undo slot UndoInfo undo; - CSoundFile &sndFile = modDoc.GetrSoundFile(); + const CSoundFile &sndFile = modDoc.GetrSoundFile(); const ModSample &oldSample = sndFile.GetSample(smp); // Save old sample header undo.OldSample = oldSample; mpt::String::Copy(undo.oldName, sndFile.m_szNames[smp]); undo.changeType = changeType; + undo.description = description; if(changeType == sundo_replace) { @@ -356,8 +375,8 @@ #ifdef _DEBUG char s[64]; - const size_t nSize = (GetUndoBufferCapacity() + changeLen * bytesPerSample) >> 10; - wsprintf(s, "Sample undo buffer size is now %u.%u MB\n", nSize >> 10, (nSize & 1023) * 100 / 1024); + const size_t nSize = (GetBufferCapacity(UndoBuffer) + GetBufferCapacity(RedoBuffer) + changeLen * bytesPerSample) >> 10; + wsprintf(s, "Sample undo/redo buffer size is now %u.%u MB\n", nSize >> 10, (nSize & 1023) * 100 / 1024); Log(s); #endif @@ -369,7 +388,7 @@ return false; } - UndoBuffer[smp - 1].push_back(undo); + buffer[smp - 1].push_back(undo); modDoc.UpdateAllViews(NULL, HINT_UNDO); @@ -381,13 +400,37 @@ bool CSampleUndo::Undo(const SAMPLEINDEX smp) //------------------------------------------- { - if(!CanUndo(smp)) return false; + return Undo(UndoBuffer, RedoBuffer, smp); +} + +// Restore redo point for given sample +bool CSampleUndo::Redo(const SAMPLEINDEX smp) +//------------------------------------------- +{ + return Undo(RedoBuffer, UndoBuffer, smp); +} + + +// Restore undo/redo point for given sample +bool CSampleUndo::Undo(undobuf_t &fromBuf, undobuf_t &toBuf, const SAMPLEINDEX smp) +//--------------------------------------------------------------------------------- +{ + if(!SampleBufferExists(fromBuf, smp) || fromBuf[smp - 1].empty()) return false; + CSoundFile &sndFile = modDoc.GetrSoundFile(); // Select most recent undo slot - UndoInfo &undo = UndoBuffer[smp - 1].back(); + UndoInfo &undo = fromBuf[smp - 1].back(); + // When turning an undo point into a redo point (and vice versa), some action types need to be adjusted. + sampleUndoTypes redoType = undo.changeType; + if(redoType == sundo_delete) + redoType = sundo_insert; + else if(redoType == sundo_insert) + redoType = sundo_delete; + PrepareBuffer(toBuf, smp, redoType, undo.description, undo.changeStart, undo.changeEnd); + ModSample &sample = sndFile.GetSample(smp); char *pCurrentSample = static_cast<char *>(sample.pSample); char *pNewSample = nullptr; // a new sample is possibly going to be allocated, depending on what's going to be undone. @@ -463,40 +506,31 @@ } sample.PrecomputeLoops(sndFile, true); - RemoveLastUndoStep(smp); + DeleteStep(fromBuf, smp, fromBuf[smp - 1].size() - 1); - if(CanUndo(smp) == false) modDoc.UpdateAllViews(NULL, HINT_UNDO); + modDoc.UpdateAllViews(NULL, HINT_UNDO); modDoc.SetModified(); return true; } -// Check if given sample has a valid undo buffer -bool CSampleUndo::CanUndo(const SAMPLEINDEX smp) -//---------------------------------------------- +// Delete a given undo / redo step of a sample. +void CSampleUndo::DeleteStep(undobuf_t &buffer, const SAMPLEINDEX smp, const size_t step) +//--------------------------------------------------------------------------------------- { - if(!SampleBufferExists(smp, false) || UndoBuffer[smp - 1].size() == 0) return false; - return true; + if(!SampleBufferExists(buffer, smp) || step >= buffer[smp - 1].size()) return; + ModSample::FreeSample(buffer[smp - 1][step].samplePtr); + buffer[smp - 1].erase(buffer[smp - 1].begin() + step); } -// Delete a given undo step of a sample. -void CSampleUndo::DeleteUndoStep(const SAMPLEINDEX smp, const size_t step) -//------------------------------------------------------------------------ -{ - if(!SampleBufferExists(smp, false) || step >= UndoBuffer[smp - 1].size()) return; - ModSample::FreeSample(UndoBuffer[smp - 1][step].samplePtr); - UndoBuffer[smp - 1].erase(UndoBuffer[smp - 1].begin() + step); -} - - // Public helper function to remove the most recent undo point. void CSampleUndo::RemoveLastUndoStep(const SAMPLEINDEX smp) //--------------------------------------------------------- { if(CanUndo(smp) == false) return; - DeleteUndoStep(smp, UndoBuffer[smp - 1].size() - 1); + DeleteStep(UndoBuffer, smp, UndoBuffer[smp - 1].size() - 1); } @@ -505,43 +539,51 @@ void CSampleUndo::RestrictBufferSize() //------------------------------------ { - size_t capacity = GetUndoBufferCapacity(); + size_t capacity = GetBufferCapacity(UndoBuffer) + GetBufferCapacity(RedoBuffer); while(capacity > TrackerSettings::Instance().GetSampleUndoBufferSize()) { - for(SAMPLEINDEX smp = 1; smp <= UndoBuffer.size(); smp++) + RestrictBufferSize(UndoBuffer, capacity); + RestrictBufferSize(RedoBuffer, capacity); + } +} + + +void CSampleUndo::RestrictBufferSize(undobuf_t &buffer, size_t &capacity) +//----------------------------------------------------------------------- +{ + for(SAMPLEINDEX smp = 1; smp <= buffer.size(); smp++) + { + if(capacity <= TrackerSettings::Instance().GetSampleUndoBufferSize()) return; + for(size_t i = 0; i < buffer[smp - 1].size(); i++) { - for(size_t i = 0; i < UndoBuffer[smp - 1].size(); i++) + if(buffer[smp - 1][i].samplePtr != nullptr) { - if(UndoBuffer[smp - 1][i].samplePtr != nullptr) + capacity -= (buffer[smp - 1][i].changeEnd - buffer[smp - 1][i].changeStart) * buffer[smp - 1][i].OldSample.GetBytesPerSample(); + for(size_t j = 0; j <= i; j++) { - capacity -= (UndoBuffer[smp - 1][i].changeEnd - UndoBuffer[smp - 1][i].changeStart) * UndoBuffer[smp - 1][i].OldSample.GetBytesPerSample(); - for(size_t j = 0; j <= i; j++) - { - DeleteUndoStep(smp, j); - } - // Try to evenly spread out the restriction, i.e. move on to other samples before deleting another step for this sample. - break; + DeleteStep(buffer, smp, j); } + // Try to evenly spread out the restriction, i.e. move on to other samples before deleting another step for this sample. + break; } - if(capacity <= TrackerSettings::Instance().GetSampleUndoBufferSize()) return; } } } // Return total amount of bytes used by the sample undo buffer. -size_t CSampleUndo::GetUndoBufferCapacity() -//----------------------------------------- +size_t CSampleUndo::GetBufferCapacity(const undobuf_t &buffer) const +//------------------------------------------------------------------ { size_t sum = 0; - for(size_t smp = 0; smp < UndoBuffer.size(); smp++) + for(size_t smp = 0; smp < buffer.size(); smp++) { - for(size_t nStep = 0; nStep < UndoBuffer[smp].size(); nStep++) + for(size_t nStep = 0; nStep < buffer[smp].size(); nStep++) { - if(UndoBuffer[smp][nStep].samplePtr != nullptr) + if(buffer[smp][nStep].samplePtr != nullptr) { - sum += (UndoBuffer[smp][nStep].changeEnd - UndoBuffer[smp][nStep].changeStart) - * UndoBuffer[smp][nStep].OldSample.GetBytesPerSample(); + sum += (buffer[smp][nStep].changeEnd - buffer[smp][nStep].changeStart) + * buffer[smp][nStep].OldSample.GetBytesPerSample(); } } } @@ -550,18 +592,33 @@ // Ensure that the undo buffer is big enough for a given sample number -bool CSampleUndo::SampleBufferExists(const SAMPLEINDEX smp, bool forceCreation) -//----------------------------------------------------------------------------- +bool CSampleUndo::SampleBufferExists(const undobuf_t &buffer, const SAMPLEINDEX smp) const +//---------------------------------------------------------------------------------------- { - if(smp == 0 || smp > MAX_SAMPLES) return false; + if(smp == 0 || smp >= MAX_SAMPLES) return false; + if(smp <= buffer.size()) return true; + return false; +} - // Sample slot exists already - if(smp <= UndoBuffer.size()) return true; +// Get name of next undo item +const char *CSampleUndo::GetUndoName(const SAMPLEINDEX smp) const +//--------------------------------------------------------------- +{ + if(!CanUndo(smp)) + { + return ""; + } + return UndoBuffer[smp - 1].back().description; +} - // Sample slot doesn't exist, don't create it. - if(forceCreation == false) return false; - // Sample slot doesn't exist, so create it. - UndoBuffer.resize(smp); - return true; +// Get name of next redo item +const char *CSampleUndo::GetRedoName(const SAMPLEINDEX smp) const +//--------------------------------------------------------------- +{ + if(!CanRedo(smp)) + { + return ""; + } + return RedoBuffer[smp - 1].back().description; } Modified: trunk/OpenMPT/mptrack/Undo.h =================================================================== --- trunk/OpenMPT/mptrack/Undo.h 2014-02-10 21:23:39 UTC (rev 3694) +++ trunk/OpenMPT/mptrack/Undo.h 2014-02-10 23:01:57 UTC (rev 3695) @@ -64,10 +64,10 @@ // Pattern undo helper functions void ClearBuffer(undobuf_t &buffer); - void DeleteUndoStep(undobuf_t &buffer, size_t step); + void DeleteStep(undobuf_t &buffer, size_t step); PATTERNINDEX Undo(undobuf_t &fromBuf, undobuf_t &toBuf, bool linkedFromPrevious); - bool PrepareUndo(undobuf_t &buffer, PATTERNINDEX pattern, CHANNELINDEX firstChn, ROWINDEX firstRow, CHANNELINDEX numChns, ROWINDEX numRows, const char *description, bool linkToPrevious, bool storeChannelInfo); + bool PrepareBuffer(undobuf_t &buffer, PATTERNINDEX pattern, CHANNELINDEX firstChn, ROWINDEX firstRow, CHANNELINDEX numChns, ROWINDEX numRows, const char *description, bool linkToPrevious, bool storeChannelInfo); public: @@ -129,30 +129,41 @@ ModSample OldSample; char oldName[MAX_SAMPLENAME]; void *samplePtr; + const char *description; SmpLength changeStart, changeEnd; sampleUndoTypes changeType; }; typedef std::vector<std::vector<UndoInfo> > undobuf_t; undobuf_t UndoBuffer; + undobuf_t RedoBuffer; CModDoc &modDoc; // Sample undo helper functions - void DeleteUndoStep(const SAMPLEINDEX smp, const size_t step); - bool SampleBufferExists(const SAMPLEINDEX smp, bool forceCreation = true); + void ClearUndo(undobuf_t &buffer, const SAMPLEINDEX smp); + void DeleteStep(undobuf_t &buffer, const SAMPLEINDEX smp, const size_t step); + bool SampleBufferExists(const undobuf_t &buffer, const SAMPLEINDEX smp) const; void RestrictBufferSize(); - size_t GetUndoBufferCapacity(); + void RestrictBufferSize(undobuf_t &buffer, size_t &capacity); + size_t GetBufferCapacity(const undobuf_t &buffer) const; + bool PrepareBuffer(undobuf_t &buffer, const SAMPLEINDEX smp, sampleUndoTypes changeType, const char *description, SmpLength changeStart, SmpLength changeEnd); + bool Undo(undobuf_t &fromBuf, undobuf_t &toBuf, const SAMPLEINDEX smp); + public: // Sample undo functions void ClearUndo(); - void ClearUndo(const SAMPLEINDEX smp); - bool PrepareUndo(const SAMPLEINDEX smp, sampleUndoTypes changeType, SmpLength changeStart = 0, SmpLength changeEnd = 0); + void ClearUndo(const SAMPLEINDEX smp) { ClearUndo(UndoBuffer, smp); ClearUndo(RedoBuffer, smp); } + bool PrepareUndo(const SAMPLEINDEX smp, sampleUndoTypes changeType, const char *description, SmpLength changeStart = 0, SmpLength changeEnd = 0); bool Undo(const SAMPLEINDEX smp); - bool CanUndo(const SAMPLEINDEX smp); + bool Redo(const SAMPLEINDEX smp); + bool CanUndo(const SAMPLEINDEX smp) const { return SampleBufferExists(UndoBuffer, smp) && !UndoBuffer[smp - 1].empty(); } + bool CanRedo(const SAMPLEINDEX smp) const { return SampleBufferExists(RedoBuffer, smp) && !RedoBuffer[smp - 1].empty(); } void RemoveLastUndoStep(const SAMPLEINDEX smp); + const char *GetUndoName(const SAMPLEINDEX smp) const; + const char *GetRedoName(const SAMPLEINDEX smp) const; CSampleUndo(CModDoc &parent) : modDoc(parent) { } Modified: trunk/OpenMPT/mptrack/View_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp 2014-02-10 21:23:39 UTC (rev 3694) +++ trunk/OpenMPT/mptrack/View_smp.cpp 2014-02-10 23:01:57 UTC (rev 3695) @@ -80,6 +80,7 @@ ON_WM_DROPFILES() ON_WM_MOUSEWHEEL() ON_COMMAND(ID_EDIT_UNDO, OnEditUndo) + ON_COMMAND(ID_EDIT_REDO, OnEditRedo) ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll) ON_COMMAND(ID_EDIT_CUT, OnEditCut) ON_COMMAND(ID_EDIT_COPY, OnEditCopy) @@ -105,6 +106,8 @@ ON_COMMAND(ID_SAMPLE_ADDSILENCE, OnAddSilence) ON_COMMAND(ID_SAMPLE_GRID, OnChangeGridSize) ON_COMMAND(ID_SAMPLE_QUICKFADE, OnQuickFade) + ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateUndo) + ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateRedo) ON_MESSAGE(WM_MOD_MIDIMSG, OnMidiMsg) ON_MESSAGE(WM_MOD_KEYCOMMAND, OnCustomKeyMsg) //rewbs.customKeys //}}AFX_MSG_MAP @@ -838,7 +841,7 @@ ::FillRect(offScreenDC, &rcClient, CMainFrame::brushBlack); } ::SelectObject(offScreenDC, CMainFrame::penDarkGray); - if (sample.uFlags & CHN_STEREO) + if (sample.uFlags[CHN_STEREO]) { ::MoveToEx(offScreenDC, 0, ymed-yrange/2, NULL); ::LineTo(offScreenDC, rcClient.right, ymed-yrange/2); @@ -1465,7 +1468,7 @@ if (m_dwStatus[SMPSTATUS_DRAWING]) { m_lastDrawPoint = point; - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Draw Sample"); if(sample.GetElementarySampleSize() == 2) SetInitialDrawPoint<int16, uint16>(sample.pSample, point); else if(sample.GetElementarySampleSize() == 1) @@ -1537,10 +1540,10 @@ if (dwPos <= sample.nLength) { //Set loop points - wsprintf(s, "Set Loop Start to:\t%d", dwPos); + wsprintf(s, "Set &Loop Start to:\t%d", dwPos); ::AppendMenu(hMenu, MF_STRING | (dwPos + 4 <= sample.nLoopEnd ? 0 : MF_GRAYED), ID_SAMPLE_SETLOOPSTART, s); - wsprintf(s, "Set Loop End to:\t%d", dwPos); + wsprintf(s, "Set &Loop End to:\t%d", dwPos); ::AppendMenu(hMenu, MF_STRING | (dwPos >= sample.nLoopStart + 4 ? 0 : MF_GRAYED), ID_SAMPLE_SETLOOPEND, s); @@ -1548,10 +1551,10 @@ { //Set sustain loop points ::AppendMenu(hMenu, MF_SEPARATOR, 0, ""); - wsprintf(s, "Set Sustain Start to:\t%d", dwPos); + wsprintf(s, "Set &Sustain Start to:\t%d", dwPos); ::AppendMenu(hMenu, MF_STRING | (dwPos + 4 <= sample.nSustainEnd ? 0 : MF_GRAYED), ID_SAMPLE_SETSUSTAINSTART, s); - wsprintf(s, "Set Sustain End to:\t%d", dwPos); + wsprintf(s, "Set &Sustain End to:\t%d", dwPos); ::AppendMenu(hMenu, MF_STRING | (dwPos >= sample.nSustainStart + 4 ? 0 : MF_GRAYED), ID_SAMPLE_SETSUSTAINEND, s); } @@ -1573,7 +1576,7 @@ // "Trim" menu item is responding differently if there's no selection, // but a loop present: "trim around loop point"! (jojo in topic 2258) - std::string sTrimMenuText = "T&rim"; + std::string sTrimMenuText = "Tr&im"; bool bIsGrayed = ( (m_dwEndSel<=m_dwBeginSel) || (m_dwEndSel - m_dwBeginSel < MIN_TRIM_LENGTH) || (m_dwEndSel - m_dwBeginSel == sample.nLength) ); @@ -1600,7 +1603,8 @@ ::AppendMenu(hMenu, MF_STRING, ID_EDIT_COPY, "&Copy\t" + ih->GetKeyTextFromCommand(kcEditCopy)); } ::AppendMenu(hMenu, MF_STRING | (IsClipboardFormatAvailable(CF_WAVE) ? 0 : MF_GRAYED), ID_EDIT_PASTE, "&Paste\t" + ih->GetKeyTextFromCommand(kcEditPaste)); - ::AppendMenu(hMenu, MF_STRING | (pModDoc->GetSampleUndo().CanUndo(m_nSample) ? 0 : MF_GRAYED), ID_EDIT_UNDO, "&Undo\t" + ih->GetKeyTextFromCommand(kcEditUndo)); + ::AppendMenu(hMenu, MF_STRING | (pModDoc->GetSampleUndo().CanUndo(m_nSample) ? 0 : MF_GRAYED), ID_EDIT_UNDO, "&Undo" + CString(pModDoc->GetSampleUndo().GetUndoName(m_nSample)) + "\t" + ih->GetKeyTextFromCommand(kcEditUndo)); + ::AppendMenu(hMenu, MF_STRING | (pModDoc->GetSampleUndo().CanRedo(m_nSample) ? 0 : MF_GRAYED), ID_EDIT_REDO, "&Redo" + CString(pModDoc->GetSampleUndo().GetRedoName(m_nSample)) + "\t" + ih->GetKeyTextFromCommand(kcEditRedo)); ClientToScreen(&pt); ::TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, 0, m_hWnd, NULL); ::DestroyMenu(hMenu); @@ -1820,14 +1824,14 @@ || (m_dwEndSel - m_dwBeginSel + 4 >= len)) { if (Reporting::Confirm("Remove this sample?", "Remove Sample", true) != cnfYes) return; - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Delete Sample"); sndFile.DestroySampleThreadsafe(m_nSample); dwUpdateFlags |= HINT_SMPNAMES; } else { - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_delete, m_dwBeginSel, m_dwEndSel); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_delete, "Delete Selection", m_dwBeginSel, m_dwEndSel); CriticalSection cs; @@ -1978,7 +1982,7 @@ if ((hCpy) && ((p = (LPBYTE)GlobalLock(hCpy)) != NULL)) { - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Paste"); CSoundFile &sndFile = pModDoc->GetrSoundFile(); ModSample &sample = sndFile.GetSample(m_nSample); @@ -2015,11 +2019,21 @@ { CModDoc *pModDoc = GetDocument(); if(pModDoc == nullptr) return; - if(pModDoc->GetSampleUndo().Undo(m_nSample) == true) + if(pModDoc->GetSampleUndo().Undo(m_nSample)) pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); } +void CViewSample::OnEditRedo() +//---------------------------- +{ + CModDoc *pModDoc = GetDocument(); + if(pModDoc == nullptr) return; + if(pModDoc->GetSampleUndo().Redo(m_nSample)) + pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); +} + + void CViewSample::On8BitConvert() //------------------------------- { @@ -2031,7 +2045,7 @@ ModSample &sample = sndFile.GetSample(m_nSample); if(sample.uFlags[CHN_16BIT] && sample.pSample != nullptr && sample.nLength != 0) { - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "8-Bit Conversion"); CriticalSection cs; @@ -2083,7 +2097,7 @@ } } - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Mono Conversion"); if(ctrlSmp::ConvertToMono(sample, sndFile, convert)) { @@ -2156,7 +2170,7 @@ if ((sample.pSample) && (nStart+nEnd <= sample.nLength) && (nEnd >= MIN_TRIM_LENGTH)) { - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Trim"); CriticalSection cs; @@ -2186,6 +2200,7 @@ sample.uFlags.reset(CHN_SUSTAINLOOP|CHN_PINGPONGSUSTAIN); } sample.nLength = nEnd; + sample.PrecomputeLoops(sndFile); sample.PrecomputeLoops(sndFile); cs.Leave(); @@ -2204,8 +2219,8 @@ } -void CViewSample::PlayNote(UINT note, const uint32 nStartPos) -//----------------------------------------------------------- +void CViewSample::PlayNote(ModCommand::NOTE note, const SmpLength nStartPos) +//-------------------------------------------------------------------------- { CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); CModDoc *pModDoc = GetDocument(); @@ -2341,7 +2356,7 @@ { CriticalSection cs; - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Replace"); bCanDrop = dlsbank.ExtractSample(*pSndFile, m_nSample, nIns, nRgn); } bUpdate = TRUE; @@ -2369,7 +2384,7 @@ } CriticalSection cs; - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_replace, "Replace"); bCanDrop = pDLSBank->ExtractSample(*pSndFile, m_nSample, nIns, nRgn); bUpdate = TRUE; @@ -2447,7 +2462,7 @@ ModSample &sample = sndFile.GetSample(m_nSample); if ((m_dwMenuParam+4 <= sample.nLoopEnd) && (sample.nLoopStart != m_dwMenuParam)) { - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_none); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_none, "Set Loop Start"); sample.SetLoop(m_dwMenuParam, sample.nLoopEnd, true, sample.uFlags[CHN_PINGPONGLOOP], sndFile); pModDoc->SetModified(); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); @@ -2466,7 +2481,7 @@ ModSample &sample = sndFile.GetSample(m_nSample); if ((m_dwMenuParam >= sample.nLoopStart+4) && (sample.nLoopEnd != m_dwMenuParam)) { - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_none); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_none, "Set Loop End"); sample.SetLoop(sample.nLoopStart, m_dwMenuParam, true, sample.uFlags[CHN_PINGPONGLOOP], sndFile); pModDoc->SetModified(); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); @@ -2485,7 +2500,7 @@ ModSample &sample = sndFile.GetSample(m_nSample); if ((m_dwMenuParam+4 <= sample.nSustainEnd) && (sample.nSustainStart != m_dwMenuParam)) { - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_none); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_none, "Set Sustain Start"); sample.SetSustainLoop(m_dwMenuParam, sample.nSustainEnd, true, sample.uFlags[CHN_PINGPONGSUSTAIN], sndFile); pModDoc->SetModified(); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); @@ -2504,7 +2519,7 @@ ModSample &sample = sndFile.GetSample(m_nSample); if ((m_dwMenuParam >= sample.nSustainStart+4) && (sample.nSustainEnd != m_dwMenuParam)) { - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_none); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_none, "Set Sustain End"); sample.SetSustainLoop(sample.nSustainStart, m_dwMenuParam, true, sample.uFlags[CHN_PINGPONGSUSTAIN], sndFile); pModDoc->SetModified(); pModDoc->UpdateAllViews(NULL, (m_nSample << HINT_SHIFT_SMP) | HINT_SAMPLEINFO | HINT_SAMPLEDATA, NULL); @@ -2567,9 +2582,9 @@ CriticalSection cs; if(dlg.m_nSamples < sample.nLength) // make it shorter! - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_delete, dlg.m_nSamples, sample.nLength); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_delete, "Resize", dlg.m_nSamples, sample.nLength); else // make it longer! - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_insert, sample.nLength, dlg.m_nSamples); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_insert, "Add Silence", sample.nLength, dlg.m_nSamples); ctrlSmp::ResizeSample(sample, dlg.m_nSamples, sndFile); } } else @@ -2580,7 +2595,7 @@ CriticalSection cs; UINT nStart = (dlg.m_nEditOption == addsilence_at_end) ? sample.nLength : 0; - pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_insert, nStart, nStart + dlg.m_nSamples); + pModDoc->GetSampleUndo().PrepareUndo(m_nSample, sundo_insert, "Add Silence", nStart, nStart + dlg.m_nSamples); ctrlSmp::InsertSilence(sample, dlg.m_nSamples, nStart, sndFile); } } @@ -2707,6 +2722,7 @@ case kcEditCopy: OnEditCopy(); return wParam; case kcEditPaste: OnEditPaste(); return wParam; case kcEditUndo: OnEditUndo(); return wParam; + case kcEditRedo: OnEditRedo(); return wParam; case kcSample8Bit: On8BitConvert(); return wParam; case kcSampleMonoMix: OnMonoConvertMix(); return wParam; case kcSampleMonoLeft: OnMonoConvertLeft(); return wParam; @@ -2735,7 +2751,7 @@ } if (wParam >= kcSampStartNotes && wParam <= kcSampEndNotes) { - PlayNote(wParam - kcSampStartNotes + 1 + pMainFrm->GetBaseOctave() * 12); + PlayNote(static_cast<ModCommand::NOTE>(wParam - kcSampStartNotes + 1 + pMainFrm->GetBaseOctave() * 12)); return wParam; } if (wParam >= kcSampStartNoteStops && wParam <= kcSampEndNoteStops) @@ -2824,3 +2840,29 @@ InvalidateSample(); } } + + +void CViewSample::OnUpdateUndo(CCmdUI *pCmdUI) +//-------------------------------------------- +{ + CModDoc *pModDoc = GetDocument(); + if ((pCmdUI) && (pModDoc)) + { + pCmdUI->Enable(pModDoc->GetSampleUndo().CanUndo(m_nSample)); + pCmdUI->SetText(CString("Undo ") + CString(pModDoc->GetSampleUndo().GetUndoName(m_nSample)) + + CString("\t") + CMainFrame::GetInputHandler()->GetKeyTextFromCommand(kcEditUndo)); + } +} + + +void CViewSample::OnUpdateRedo(CCmdUI *pCmdUI) +//-------------------------------------------- +{ + CModDoc *pModDoc = GetDocument(); + if ((pCmdUI) && (pModDoc)) + { + pCmdUI->Enable(pModDoc->GetSampleUndo().CanRedo(m_nSample)); + pCmdUI->SetText(CString("Redo ") + CString(pModDoc->GetSampleUndo().GetRedoName(m_nSample)) + + CString("\t") + CMainFrame::GetInputHandler()->GetKeyTextFromCommand(kcEditRedo)); + } +} Modified: trunk/OpenMPT/mptrack/View_smp.h =================================================================== --- trunk/OpenMPT/mptrack/View_smp.h 2014-02-10 21:23:39 UTC (rev 3694) +++ trunk/OpenMPT/mptrack/View_smp.h 2014-02-10 23:01:57 UTC (rev 3695) @@ -61,7 +61,7 @@ BOOL SetZoom(UINT nZoom); int32 SampleToScreen(SmpLength pos) const; SmpLength ScreenToSample(int32 x) const; - void PlayNote(UINT note, const uint32 nStartPos = 0); //rewbs.customKeys + void PlayNote(ModCommand::NOTE note, const SmpLength nStartPos = 0); void InvalidateSample(); void SetCurSel(SmpLength nBegin, SmpLength nEnd); void ScrollToPosition(int x); @@ -141,6 +141,7 @@ afx_msg void OnEditCopy(); afx_msg void OnEditPaste(); afx_msg void OnEditUndo(); + afx_msg void OnEditRedo(); afx_msg void OnSetLoop(); afx_msg void OnSetSustainLoop(); afx_msg void On8BitConvert(); @@ -166,6 +167,8 @@ afx_msg LRESULT OnMidiMsg(WPARAM, LPARAM); afx_msg LRESULT OnCustomKeyMsg(WPARAM, LPARAM); //rewbs.customKeys afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); + afx_msg void OnUpdateUndo(CCmdUI *pCmdUI); + afx_msg void OnUpdateRedo(CCmdUI *pCmdUI); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2014-02-10 21:23:39 UTC (rev 3694) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2014-02-10 23:01:57 UTC (rev 3695) @@ -1482,7 +1482,7 @@ wsprintf(s, _T("Remove sample %u?"), modItemID); if(Reporting::Confirm(s, false, true) == cnfYes) { - modDoc->GetSampleUndo().PrepareUndo((SAMPLEINDEX)modItemID, sundo_replace); + modDoc->GetSampleUndo().PrepareUndo((SAMPLEINDEX)modItemID, sundo_replace, "Delete"); const SAMPLEINDEX oldNumSamples = modDoc->GetNumSamples(); if (modDoc->RemoveSample((SAMPLEINDEX)modItemID)) { Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2014-02-10 21:23:39 UTC (rev 3694) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2014-02-10 23:01:57 UTC (rev 3695) @@ -1604,7 +1604,7 @@ #ifdef MODPLUG_TRACKER if(GetpModDoc()) { - GetpModDoc()->GetSampleUndo().PrepareUndo(nSmp, sundo_replace); + GetpModDoc()->GetSampleUndo().PrepareUndo(nSmp, sundo_replace, "Remove Sample"); } #endif // MODPLUG_TRACKER This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |