From: <sv...@op...> - 2024-11-07 21:12:06
|
Author: sagamusix Date: Thu Nov 7 22:11:52 2024 New Revision: 22106 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=22106 Log: [New] Pattern tab: Can now toggle instrument / volume / effect column visibility independently (https://bugs.openmpt.org/view.php?id=1523). Modified: trunk/OpenMPT/mptrack/Childfrm.h trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/CommandSet.h trunk/OpenMPT/mptrack/Ctrl_pat.cpp trunk/OpenMPT/mptrack/Ctrl_pat.h trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/Draw_pat.cpp trunk/OpenMPT/mptrack/PatternCursor.h trunk/OpenMPT/mptrack/PatternFindReplace.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_pat.h trunk/OpenMPT/mptrack/WindowMessages.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/res/originals/pattern_toolbar.pfi trunk/OpenMPT/mptrack/res/pattern_toolbar.png trunk/OpenMPT/mptrack/resource.h Modified: trunk/OpenMPT/mptrack/Childfrm.h ============================================================================== --- trunk/OpenMPT/mptrack/Childfrm.h Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/Childfrm.h Thu Nov 7 22:11:52 2024 (r22106) @@ -37,9 +37,9 @@ PATTERNINDEX nPattern = 0; PatternCursor cursor = 0; PatternRect selection; - PatternCursor::Columns nDetailLevel = PatternCursor::firstColumn; ORDERINDEX nOrder = 0; ORDERINDEX initialOrder = ORDERINDEX_INVALID; + std::bitset<PatternCursor::numColumns> visibleColumns = std::bitset<PatternCursor::numColumns>{}.set(); bool initialized = false; }; Modified: trunk/OpenMPT/mptrack/CommandSet.cpp ============================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/CommandSet.cpp Thu Nov 7 22:11:52 2024 (r22106) @@ -1395,6 +1395,9 @@ {2100, kcGotoParamColumn, _T("Go to effect parameter column")}, {2101, kcContextMenu, _T("Open Context Menu")}, {2102, kcOrderlistStreamExport, _T("Stream Export")}, + {2103, kcToggleVisibilityInstrColumn, _T("Toggle instrument column visibility") }, + {2104, kcToggleVisibilityVolumeColumn, _T("Toggle volume column visibility") }, + {2105, kcToggleVisibilityEffectColumn, _T("Toggle effect column visibility") }, }; // clang-format on Modified: trunk/OpenMPT/mptrack/CommandSet.h ============================================================================== --- trunk/OpenMPT/mptrack/CommandSet.h Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/CommandSet.h Thu Nov 7 22:11:52 2024 (r22106) @@ -337,7 +337,10 @@ kcToggleOverflowPaste, kcToggleNoteOffRecordPC, kcToggleNoteOffRecordMIDI, - kcEndPatternEditMisc = kcToggleNoteOffRecordMIDI, + kcToggleVisibilityInstrColumn, + kcToggleVisibilityVolumeColumn, + kcToggleVisibilityEffectColumn, + kcEndPatternEditMisc = kcToggleVisibilityEffectColumn, kcStartChannelKeys, kcChannelMute = kcStartChannelKeys, Modified: trunk/OpenMPT/mptrack/Ctrl_pat.cpp ============================================================================== --- trunk/OpenMPT/mptrack/Ctrl_pat.cpp Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/Ctrl_pat.cpp Thu Nov 7 22:11:52 2024 (r22106) @@ -19,6 +19,7 @@ #include "Mainfrm.h" #include "Moddoc.h" #include "Mptrack.h" +#include "PatternCursor.h" #include "PatternEditorDialogs.h" #include "Reporting.h" #include "resource.h" @@ -41,47 +42,49 @@ ON_WM_KEYDOWN() ON_WM_VSCROLL() ON_WM_XBUTTONUP() - ON_COMMAND(IDC_BUTTON1, &CCtrlPatterns::OnSequenceNext) - ON_COMMAND(IDC_BUTTON2, &CCtrlPatterns::OnSequencePrev) - ON_COMMAND(ID_PLAYER_PAUSE, &CCtrlPatterns::OnPlayerPause) - ON_COMMAND(IDC_PATTERN_NEW, &CCtrlPatterns::OnPatternNew) - ON_COMMAND(IDC_PATTERN_STOP, &CCtrlPatterns::OnPatternStop) - ON_COMMAND(IDC_PATTERN_PLAY, &CCtrlPatterns::OnPatternPlay) - ON_COMMAND(IDC_PATTERN_PLAYFROMSTART, &CCtrlPatterns::OnPatternPlayFromStart) - ON_COMMAND(IDC_PATTERN_RECORD, &CCtrlPatterns::OnPatternRecord) - ON_COMMAND(IDC_PATTERN_LOOP, &CCtrlPatterns::OnChangeLoopStatus) - ON_COMMAND(ID_PATTERN_PLAYROW, &CCtrlPatterns::OnPatternPlayRow) - ON_COMMAND(ID_PATTERN_CHANNELMANAGER, &CCtrlPatterns::OnChannelManager) - ON_COMMAND(ID_PATTERN_VUMETERS, &CCtrlPatterns::OnPatternVUMeters) - ON_COMMAND(ID_VIEWPLUGNAMES, &CCtrlPatterns::OnPatternViewPlugNames) - ON_COMMAND(ID_NEXTINSTRUMENT, &CCtrlPatterns::OnNextInstrument) - ON_COMMAND(ID_PREVINSTRUMENT, &CCtrlPatterns::OnPrevInstrument) - ON_COMMAND(IDC_PATTERN_FOLLOWSONG, &CCtrlPatterns::OnFollowSong) - ON_COMMAND(ID_PATTERN_CHORDEDIT, &CCtrlPatterns::OnChordEditor) - ON_COMMAND(ID_PATTERN_PROPERTIES, &CCtrlPatterns::OnPatternProperties) - ON_COMMAND(ID_PATTERN_EXPAND, &CCtrlPatterns::OnPatternExpand) - ON_COMMAND(ID_PATTERN_SHRINK, &CCtrlPatterns::OnPatternShrink) - ON_COMMAND(ID_PATTERN_AMPLIFY, &CCtrlPatterns::OnPatternAmplify) - ON_COMMAND(ID_ORDERLIST_NEW, &CCtrlPatterns::OnPatternNew) - ON_COMMAND(ID_ORDERLIST_COPY, &CCtrlPatterns::OnPatternDuplicate) - ON_COMMAND(ID_ORDERLIST_MERGE, &CCtrlPatterns::OnPatternMerge) - ON_COMMAND(ID_PATTERNCOPY, &CCtrlPatterns::OnPatternCopy) - ON_COMMAND(ID_PATTERNPASTE, &CCtrlPatterns::OnPatternPaste) - ON_COMMAND(ID_EDIT_UNDO, &CCtrlPatterns::OnEditUndo) - ON_COMMAND(ID_PATTERNDETAIL_LO, &CCtrlPatterns::OnDetailLo) - ON_COMMAND(ID_PATTERNDETAIL_MED, &CCtrlPatterns::OnDetailMed) - ON_COMMAND(ID_PATTERNDETAIL_HI, &CCtrlPatterns::OnDetailHi) - ON_COMMAND(ID_OVERFLOWPASTE, &CCtrlPatterns::OnToggleOverflowPaste) - ON_CBN_DROPDOWN(IDC_COMBO_INSTRUMENT, &CCtrlPatterns::OnOpenInstrumentDropdown) + ON_COMMAND(IDC_BUTTON1, &CCtrlPatterns::OnSequenceNext) + ON_COMMAND(IDC_BUTTON2, &CCtrlPatterns::OnSequencePrev) + ON_COMMAND(ID_PLAYER_PAUSE, &CCtrlPatterns::OnPlayerPause) + ON_COMMAND(IDC_PATTERN_NEW, &CCtrlPatterns::OnPatternNew) + ON_COMMAND(IDC_PATTERN_STOP, &CCtrlPatterns::OnPatternStop) + ON_COMMAND(IDC_PATTERN_PLAY, &CCtrlPatterns::OnPatternPlay) + ON_COMMAND(IDC_PATTERN_PLAYFROMSTART, &CCtrlPatterns::OnPatternPlayFromStart) + ON_COMMAND(IDC_PATTERN_RECORD, &CCtrlPatterns::OnPatternRecord) + ON_COMMAND(IDC_PATTERN_LOOP, &CCtrlPatterns::OnChangeLoopStatus) + ON_COMMAND(ID_PATTERN_PLAYROW, &CCtrlPatterns::OnPatternPlayRow) + ON_COMMAND(ID_PATTERN_CHANNELMANAGER, &CCtrlPatterns::OnChannelManager) + ON_COMMAND(ID_PATTERN_VUMETERS, &CCtrlPatterns::OnPatternVUMeters) + ON_COMMAND(ID_VIEWPLUGNAMES, &CCtrlPatterns::OnPatternViewPlugNames) + ON_COMMAND(ID_NEXTINSTRUMENT, &CCtrlPatterns::OnNextInstrument) + ON_COMMAND(ID_PREVINSTRUMENT, &CCtrlPatterns::OnPrevInstrument) + ON_COMMAND(IDC_PATTERN_FOLLOWSONG, &CCtrlPatterns::OnFollowSong) + ON_COMMAND(ID_PATTERN_CHORDEDIT, &CCtrlPatterns::OnChordEditor) + ON_COMMAND(ID_PATTERN_PROPERTIES, &CCtrlPatterns::OnPatternProperties) + ON_COMMAND(ID_PATTERN_EXPAND, &CCtrlPatterns::OnPatternExpand) + ON_COMMAND(ID_PATTERN_SHRINK, &CCtrlPatterns::OnPatternShrink) + ON_COMMAND(ID_PATTERN_AMPLIFY, &CCtrlPatterns::OnPatternAmplify) + ON_COMMAND(ID_ORDERLIST_NEW, &CCtrlPatterns::OnPatternNew) + ON_COMMAND(ID_ORDERLIST_COPY, &CCtrlPatterns::OnPatternDuplicate) + ON_COMMAND(ID_ORDERLIST_MERGE, &CCtrlPatterns::OnPatternMerge) + ON_COMMAND(ID_PATTERNCOPY, &CCtrlPatterns::OnPatternCopy) + ON_COMMAND(ID_PATTERNPASTE, &CCtrlPatterns::OnPatternPaste) + ON_COMMAND(ID_EDIT_UNDO, &CCtrlPatterns::OnEditUndo) + ON_COMMAND(ID_PATTERNDETAIL_DROPDOWN, &CCtrlPatterns::OnDetailSwitch) + ON_COMMAND(ID_PATTERNDETAIL_INSTR, &CCtrlPatterns::OnDetailInstr) + ON_COMMAND(ID_PATTERNDETAIL_VOLUME, &CCtrlPatterns::OnDetailVolume) + ON_COMMAND(ID_PATTERNDETAIL_EFFECT, &CCtrlPatterns::OnDetailEffect) + ON_COMMAND(ID_OVERFLOWPASTE, &CCtrlPatterns::OnToggleOverflowPaste) + ON_CBN_DROPDOWN(IDC_COMBO_INSTRUMENT, &CCtrlPatterns::OnOpenInstrumentDropdown) ON_CBN_SELENDCANCEL(IDC_COMBO_INSTRUMENT, &CCtrlPatterns::OnCancelInstrumentDropdown) - ON_CBN_SELENDOK(IDC_COMBO_INSTRUMENT, &CCtrlPatterns::OnInstrumentChanged) - ON_COMMAND(IDC_PATINSTROPLUGGUI, &CCtrlPatterns::TogglePluginEditor) - ON_EN_CHANGE(IDC_EDIT_SPACING, &CCtrlPatterns::OnSpacingChanged) - ON_EN_CHANGE(IDC_EDIT_PATTERNNAME, &CCtrlPatterns::OnPatternNameChanged) - ON_EN_CHANGE(IDC_EDIT_SEQUENCE_NAME, &CCtrlPatterns::OnSequenceNameChanged) - ON_EN_CHANGE(IDC_EDIT_SEQNUM, &CCtrlPatterns::OnSequenceNumChanged) - ON_UPDATE_COMMAND_UI(IDC_PATTERN_RECORD,&CCtrlPatterns::OnUpdateRecord) - ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &CCtrlPatterns::OnToolTipText) + ON_CBN_SELENDOK(IDC_COMBO_INSTRUMENT, &CCtrlPatterns::OnInstrumentChanged) + ON_COMMAND(IDC_PATINSTROPLUGGUI, &CCtrlPatterns::TogglePluginEditor) + ON_EN_CHANGE(IDC_EDIT_SPACING, &CCtrlPatterns::OnSpacingChanged) + ON_EN_CHANGE(IDC_EDIT_PATTERNNAME, &CCtrlPatterns::OnPatternNameChanged) + ON_EN_CHANGE(IDC_EDIT_SEQUENCE_NAME, &CCtrlPatterns::OnSequenceNameChanged) + ON_EN_CHANGE(IDC_EDIT_SEQNUM, &CCtrlPatterns::OnSequenceNumChanged) + ON_NOTIFY(TBN_DROPDOWN, IDC_TOOLBAR1, &CCtrlPatterns::OnTbnDropDownToolBar) + ON_UPDATE_COMMAND_UI(IDC_PATTERN_RECORD, &CCtrlPatterns::OnUpdateRecord) + ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &CCtrlPatterns::OnToolTipText) //}}AFX_MSG_MAP ON_WM_MOUSEWHEEL() END_MESSAGE_MAP() @@ -140,7 +143,8 @@ m_OrderList.Init(rcOrderList, pMainFrm->GetGUIFont()); // Toolbar buttons m_ToolBar.Init(CMainFrame::GetMainFrame()->m_PatternIcons, CMainFrame::GetMainFrame()->m_PatternIconsDisabled); - m_ToolBar.AddButton(IDC_PATTERN_NEW, TIMAGE_PATTERN_NEW); + m_ToolBar.SetExtendedStyle(m_ToolBar.GetExtendedStyle() | TBSTYLE_EX_DRAWDDARROWS); + m_ToolBar.AddButton(IDC_PATTERN_NEW, TIMAGE_PATTERN_NEW, TBSTYLE_BUTTON | TBSTYLE_DROPDOWN); m_ToolBar.AddButton(IDC_PATTERN_PLAY, TIMAGE_PATTERN_PLAY); m_ToolBar.AddButton(IDC_PATTERN_PLAYFROMSTART, TIMAGE_PATTERN_RESTART); m_ToolBar.AddButton(IDC_PATTERN_STOP, TIMAGE_PATTERN_STOP); @@ -160,9 +164,7 @@ m_ToolBar.AddButton(ID_PATTERN_SHRINK, TIMAGE_PATTERN_SHRINK); // m_ToolBar.AddButton(ID_PATTERN_AMPLIFY, TIMAGE_SAMPLE_AMPLIFY); m_ToolBar.AddButton(ID_SEPARATOR, 0, TBSTYLE_SEP); - m_ToolBar.AddButton(ID_PATTERNDETAIL_LO, TIMAGE_PATTERN_DETAIL_LO, TBSTYLE_CHECK, TBSTATE_ENABLED); - m_ToolBar.AddButton(ID_PATTERNDETAIL_MED, TIMAGE_PATTERN_DETAIL_MED, TBSTYLE_CHECK, TBSTATE_ENABLED); - m_ToolBar.AddButton(ID_PATTERNDETAIL_HI, TIMAGE_PATTERN_DETAIL_HI, TBSTYLE_CHECK, TBSTATE_ENABLED | TBSTATE_CHECKED); + m_ToolBar.AddButton(ID_PATTERNDETAIL_DROPDOWN, TIMAGE_PATTERN_DETAIL_LO, TBSTYLE_BUTTON | TBSTYLE_DROPDOWN); m_ToolBar.AddButton(ID_SEPARATOR, 0, TBSTYLE_SEP); m_ToolBar.AddButton(ID_OVERFLOWPASTE, TIMAGE_PATTERN_OVERFLOWPASTE, TBSTYLE_CHECK, ((TrackerSettings::Instance().m_dwPatternSetup & PATTERN_OVERFLOWPASTE) ? TBSTATE_CHECKED : 0) | TBSTATE_ENABLED); @@ -443,7 +445,6 @@ SendViewMessage(VIEWMSG_FOLLOWSONG, IsDlgButtonChecked(IDC_PATTERN_FOLLOWSONG)); SendViewMessage(VIEWMSG_PATTERNLOOP, (m_sndFile.m_PlayState.m_flags[SONG_PATTERNLOOP]) ? TRUE : FALSE); OnSpacingChanged(); - SendViewMessage(VIEWMSG_SETDETAIL, m_nDetailLevel); SendViewMessage(VIEWMSG_SETRECORD, m_bRecord); SendViewMessage(VIEWMSG_SETVUMETERS, m_bVUMeters); SendViewMessage(VIEWMSG_SETPLUGINNAMES, m_bPluginNames); @@ -1027,21 +1028,20 @@ void CCtrlPatterns::OnPatternPlay() { - m_modDoc.OnPatternPlay(); + if(CMainFrame::GetMainFrame()->GetInputHandler()->ShiftPressed()) + m_modDoc.OnPatternPlayNoLoop(); + else + m_modDoc.OnPatternPlay(); SwitchToView(); } -//rewbs.playSongFromCursor -void CCtrlPatterns::OnPatternPlayNoLoop() -{ - m_modDoc.OnPatternPlayNoLoop(); - SwitchToView(); -} -//end rewbs.playSongFromCursor void CCtrlPatterns::OnPatternPlayFromStart() { - m_modDoc.OnPatternRestart(); + if(CMainFrame::GetMainFrame()->GetInputHandler()->ShiftPressed()) + m_modDoc.OnPatternRestart(false); + else + m_modDoc.OnPatternRestart(); SwitchToView(); } @@ -1207,47 +1207,76 @@ } -void CCtrlPatterns::OnDetailLo() +void CCtrlPatterns::OnTbnDropDownToolBar(NMHDR *pNMHDR, LRESULT *pResult) { - m_ToolBar.SetState(ID_PATTERNDETAIL_LO, TBSTATE_CHECKED | TBSTATE_ENABLED); - if(m_nDetailLevel != PatternCursor::instrColumn) - { - m_nDetailLevel = PatternCursor::instrColumn; - m_ToolBar.SetState(ID_PATTERNDETAIL_MED, TBSTATE_ENABLED); - m_ToolBar.SetState(ID_PATTERNDETAIL_HI, TBSTATE_ENABLED); - SendViewMessage(VIEWMSG_SETDETAIL, m_nDetailLevel); + CInputHandler *ih = CMainFrame::GetInputHandler(); + NMTOOLBAR *pToolBar = reinterpret_cast<NMTOOLBAR *>(pNMHDR); + ClientToScreen(&(pToolBar->rcButton)); // TrackPopupMenu uses screen coords + const int offset = Util::ScalePixels(4, m_hWnd); // Compared to the main toolbar, the offset seems to be a bit wrong here...? + int x = pToolBar->rcButton.left + offset, y = pToolBar->rcButton.bottom + offset; + const auto visibleColumns = std::bitset<PatternCursor::numColumns>{static_cast<unsigned long>(SendViewMessage(VIEWMSG_GETDETAIL))}; + CMenu menu; + switch(pToolBar->iItem) + { + case IDC_PATTERN_NEW: + menu.CreatePopupMenu(); + menu.AppendMenu(MF_STRING, ID_ORDERLIST_COPY, ih->GetKeyTextFromCommand(kcDuplicatePattern, _T("&Duplicate Pattern"))); + menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, this); + menu.DestroyMenu(); + break; + + case ID_PATTERNDETAIL_DROPDOWN: + menu.CreatePopupMenu(); + menu.AppendMenu(MF_STRING | (visibleColumns[PatternCursor::instrColumn] ? MF_CHECKED : 0), ID_PATTERNDETAIL_INSTR, ih->GetKeyTextFromCommand(kcToggleVisibilityInstrColumn, _T("Show &Instrument Column"))); + menu.AppendMenu(MF_STRING | (visibleColumns[PatternCursor::volumeColumn] ? MF_CHECKED : 0), ID_PATTERNDETAIL_VOLUME, ih->GetKeyTextFromCommand(kcToggleVisibilityVolumeColumn, _T("Show &Volume Column"))); + menu.AppendMenu(MF_STRING | (visibleColumns[PatternCursor::effectColumn] ? MF_CHECKED : 0), ID_PATTERNDETAIL_EFFECT, ih->GetKeyTextFromCommand(kcToggleVisibilityEffectColumn, _T("Show &Effect Column"))); + menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, this); + menu.DestroyMenu(); + break; } + *pResult = 0; +} + + +void CCtrlPatterns::OnDetailSwitch() +{ + // Cycle through all bit combinations + auto visibleColumns = std::bitset<PatternCursor::numColumns>{static_cast<unsigned long>(SendViewMessage(VIEWMSG_GETDETAIL) + 1)}; + visibleColumns.set(PatternCursor::noteColumn); + visibleColumns.set(PatternCursor::paramColumn, visibleColumns[PatternCursor::effectColumn]); + SendViewMessage(VIEWMSG_SETDETAIL, visibleColumns.to_ulong()); SwitchToView(); } -void CCtrlPatterns::OnDetailMed() +void CCtrlPatterns::OnDetailInstr() { - m_ToolBar.SetState(ID_PATTERNDETAIL_MED, TBSTATE_CHECKED | TBSTATE_ENABLED); - if(m_nDetailLevel != PatternCursor::volumeColumn) - { - m_nDetailLevel = PatternCursor::volumeColumn; - m_ToolBar.SetState(ID_PATTERNDETAIL_LO, TBSTATE_ENABLED); - m_ToolBar.SetState(ID_PATTERNDETAIL_HI, TBSTATE_ENABLED); - SendViewMessage(VIEWMSG_SETDETAIL, m_nDetailLevel); - } + auto visibleColumns = std::bitset<PatternCursor::numColumns>{static_cast<unsigned long>(SendViewMessage(VIEWMSG_GETDETAIL))}; + visibleColumns.flip(PatternCursor::instrColumn); + SendViewMessage(VIEWMSG_SETDETAIL, visibleColumns.to_ulong()); SwitchToView(); } -void CCtrlPatterns::OnDetailHi() +void CCtrlPatterns::OnDetailVolume() { - m_ToolBar.SetState(ID_PATTERNDETAIL_HI, TBSTATE_CHECKED | TBSTATE_ENABLED); - if(m_nDetailLevel != PatternCursor::lastColumn) - { - m_nDetailLevel = PatternCursor::lastColumn; - m_ToolBar.SetState(ID_PATTERNDETAIL_LO, TBSTATE_ENABLED); - m_ToolBar.SetState(ID_PATTERNDETAIL_MED, TBSTATE_ENABLED); - SendViewMessage(VIEWMSG_SETDETAIL, m_nDetailLevel); - } + auto visibleColumns = std::bitset<PatternCursor::numColumns>{static_cast<unsigned long>(SendViewMessage(VIEWMSG_GETDETAIL))}; + visibleColumns.flip(PatternCursor::volumeColumn); + SendViewMessage(VIEWMSG_SETDETAIL, visibleColumns.to_ulong()); + SwitchToView(); +} + + +void CCtrlPatterns::OnDetailEffect() +{ + auto visibleColumns = std::bitset<PatternCursor::numColumns>{static_cast<unsigned long>(SendViewMessage(VIEWMSG_GETDETAIL))}; + visibleColumns.flip(PatternCursor::effectColumn); + visibleColumns.flip(PatternCursor::paramColumn); + SendViewMessage(VIEWMSG_SETDETAIL, visibleColumns.to_ulong()); SwitchToView(); } + void CCtrlPatterns::OnToggleOverflowPaste() { TrackerSettings::Instance().m_dwPatternSetup ^= PATTERN_OVERFLOWPASTE; @@ -1319,8 +1348,8 @@ switch(id) { case IDC_PATTERN_NEW: s = _T("Insert Pattern"); cmd = kcNewPattern; break; - case IDC_PATTERN_PLAY: s = _T("Play Pattern"); cmd = kcPlayPatternFromCursor; break; - case IDC_PATTERN_PLAYFROMSTART: s = _T("Replay Pattern"); cmd = kcPlayPatternFromStart; break; + case IDC_PATTERN_PLAY: s = _T("Play Pattern (Shift-click to play song from cursor)"); cmd = kcPlayPatternFromCursor; break; + case IDC_PATTERN_PLAYFROMSTART: s = _T("Replay Pattern (Shift-click to play song from start of pattern)"); cmd = kcPlayPatternFromStart; break; case IDC_PATTERN_STOP: s = _T("Stop"); cmd = kcPauseSong; break; case ID_PATTERN_PLAYROW: s = _T("Play Row"); cmd = kcPatternPlayRow; break; case IDC_PATTERN_RECORD: s = _T("Record"); cmd = kcPatternRecord; break; @@ -1338,9 +1367,6 @@ case ID_PATTERN_PROPERTIES: s = _T("Pattern Properties"); cmd = kcShowPatternProperties; break; case ID_PATTERN_EXPAND: s = _T("Expand Pattern"); break; case ID_PATTERN_SHRINK: s = _T("Shrink Pattern"); break; - case ID_PATTERNDETAIL_LO: s = _T("Low Pattern Detail Level"); break; - case ID_PATTERNDETAIL_MED: s = _T("Medium Pattern Detail Level"); break; - case ID_PATTERNDETAIL_HI: s = _T("High Pattern Detail Level"); break; case ID_OVERFLOWPASTE: s = _T("Toggle Overflow Paste"); cmd = kcToggleOverflowPaste; break; case IDC_PATTERN_LOOP: s = _T("Toggle Loop Pattern"); cmd = kcChangeLoopStatus; break; case IDC_PATTERN_FOLLOWSONG: s = _T("Toggle Follow Song"); cmd = kcToggleFollowSong; break; Modified: trunk/OpenMPT/mptrack/Ctrl_pat.h ============================================================================== --- trunk/OpenMPT/mptrack/Ctrl_pat.h Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/Ctrl_pat.h Thu Nov 7 22:11:52 2024 (r22106) @@ -14,7 +14,6 @@ #include "openmpt/all/BuildSettings.hpp" #include "Globals.h" -#include "PatternCursor.h" OPENMPT_NAMESPACE_BEGIN @@ -198,7 +197,6 @@ CSpinButtonCtrl m_SpinInstrument, m_SpinSpacing, m_SpinSequence; CModControlBar m_ToolBar; INSTRUMENTINDEX m_nInstrument = 0; - PatternCursor::Columns m_nDetailLevel = PatternCursor::lastColumn; // Visible Columns bool m_bRecord = false, m_bVUMeters = false, m_bPluginNames = false; bool m_instrDropdownOpen = false; @@ -228,7 +226,8 @@ //}}AFX_VIRTUAL protected: //{{AFX_MSG(CCtrlPatterns) - afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar *pScrollBar); + afx_msg void OnTbnDropDownToolBar(NMHDR *pNMHDR, LRESULT *pResult); afx_msg void OnSequenceNext(); afx_msg void OnSequencePrev(); afx_msg void OnChannelManager(); @@ -239,7 +238,6 @@ afx_msg void OnPatternMerge(); afx_msg void OnPatternStop(); afx_msg void OnPatternPlay(); - afx_msg void OnPatternPlayNoLoop(); afx_msg void OnPatternPlayRow(); afx_msg void OnPatternPlayFromStart(); afx_msg void OnPatternRecord(); @@ -262,9 +260,10 @@ afx_msg void OnPatternNameChanged(); afx_msg void OnSequenceNameChanged(); afx_msg void OnChordEditor(); - afx_msg void OnDetailLo(); - afx_msg void OnDetailMed(); - afx_msg void OnDetailHi(); + afx_msg void OnDetailSwitch(); + afx_msg void OnDetailInstr(); + afx_msg void OnDetailVolume(); + afx_msg void OnDetailEffect(); afx_msg void OnEditUndo(); afx_msg void OnUpdateRecord(CCmdUI *pCmdUI); afx_msg void TogglePluginEditor(); Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp ============================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp Thu Nov 7 22:11:52 2024 (r22106) @@ -1140,30 +1140,24 @@ switch(pToolBar->iItem) { case IDC_SAMPLE_NEW: - { - menu.CreatePopupMenu(); - menu.AppendMenu(MF_STRING, IDC_SAMPLE_DUPLICATE, ih->GetKeyTextFromCommand(kcSampleDuplicate, m_sndFile.GetSample(m_nSample).uFlags[CHN_ADLIB] ? _T("&Duplicate Instrument") : _T("&Duplicate Sample"))); - menu.AppendMenu(MF_STRING | (m_sndFile.SupportsOPL() ? 0 : MF_DISABLED), IDC_SAMPLE_INITOPL, ih->GetKeyTextFromCommand(kcSampleInitializeOPL, _T("Initialize &OPL Instrument"))); - menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, this); - menu.DestroyMenu(); - } + menu.CreatePopupMenu(); + menu.AppendMenu(MF_STRING, IDC_SAMPLE_DUPLICATE, ih->GetKeyTextFromCommand(kcSampleDuplicate, m_sndFile.GetSample(m_nSample).uFlags[CHN_ADLIB] ? _T("&Duplicate Instrument") : _T("&Duplicate Sample"))); + menu.AppendMenu(MF_STRING | (m_sndFile.SupportsOPL() ? 0 : MF_DISABLED), IDC_SAMPLE_INITOPL, ih->GetKeyTextFromCommand(kcSampleInitializeOPL, _T("Initialize &OPL Instrument"))); + menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, this); + menu.DestroyMenu(); break; case IDC_SAMPLE_OPEN: - { - menu.CreatePopupMenu(); - menu.AppendMenu(MF_STRING, IDC_SAMPLE_OPENKNOWN, ih->GetKeyTextFromCommand(kcSampleLoad, _T("Import &Sample..."))); - menu.AppendMenu(MF_STRING, IDC_SAMPLE_OPENRAW, ih->GetKeyTextFromCommand(kcSampleLoadRaw, _T("Import &Raw Sample..."))); - menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, this); - menu.DestroyMenu(); - } + menu.CreatePopupMenu(); + menu.AppendMenu(MF_STRING, IDC_SAMPLE_OPENKNOWN, ih->GetKeyTextFromCommand(kcSampleLoad, _T("Import &Sample..."))); + menu.AppendMenu(MF_STRING, IDC_SAMPLE_OPENRAW, ih->GetKeyTextFromCommand(kcSampleLoadRaw, _T("Import &Raw Sample..."))); + menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, this); + menu.DestroyMenu(); break; case IDC_SAMPLE_SAVEAS: - { - menu.CreatePopupMenu(); - menu.AppendMenu(MF_STRING, IDC_SAVE_ALL, _T("Save &All...")); - menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, this); - menu.DestroyMenu(); - } + menu.CreatePopupMenu(); + menu.AppendMenu(MF_STRING, IDC_SAVE_ALL, _T("Save &All...")); + menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y, this); + menu.DestroyMenu(); break; } *pResult = 0; Modified: trunk/OpenMPT/mptrack/Draw_pat.cpp ============================================================================== --- trunk/OpenMPT/mptrack/Draw_pat.cpp Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/Draw_pat.cpp Thu Nov 7 22:11:52 2024 (r22106) @@ -38,6 +38,7 @@ VUMETERS_HEIGHT = 13, // Height of vu-meters (including padding) VUMETERS_HEIGHT_LED = 10, // Height of vu-meters (without padding) VUMETERS_LEDS_PER_SIDE = 8, + SEPARATOR_WIDTH = 4, }; enum @@ -104,6 +105,18 @@ } +void CViewPattern::UpdateVisibileColumns(std::bitset<PatternCursor::numColumns> visibleColumns) +{ + m_visibleColumns = visibleColumns; + m_visibleColumns.set(PatternCursor::noteColumn); // Cannot be disabled at the moment + m_visibleColumns.set(PatternCursor::paramColumn, m_visibleColumns[PatternCursor::effectColumn]); + UpdateSizes(); + UpdateScrollSize(); + SetCurrentColumn(m_Cursor); + InvalidatePattern(true, true); +} + + bool CViewPattern::UpdateSizes() { const PATTERNFONT *pfnt = PatternFont::currentFont; @@ -113,10 +126,12 @@ m_szPluginHeader.cx = 0; m_szPluginHeader.cy = m_Status[psShowPluginNames] ? MulDiv(PLUGNAME_HEIGHT, m_nDPIy, 96) : 0; if(m_Status[psShowVUMeters]) m_szHeader.cy += VUMETERS_HEIGHT; - m_szCell.cx = 4 + pfnt->nEltWidths[0]; - if (m_nDetailLevel >= PatternCursor::instrColumn) m_szCell.cx += pfnt->nEltWidths[1]; - if (m_nDetailLevel >= PatternCursor::volumeColumn) m_szCell.cx += pfnt->nEltWidths[2]; - if (m_nDetailLevel >= PatternCursor::effectColumn) m_szCell.cx += pfnt->nEltWidths[3] + pfnt->nEltWidths[4]; + m_szCell.cx = SEPARATOR_WIDTH; + for(size_t i = 0; i <= PatternCursor::lastColumn; i++) + { + if(m_visibleColumns[static_cast<PatternCursor::Columns>(i)]) + m_szCell.cx += pfnt->nEltWidths[i]; + } m_szCell.cy = pfnt->nHeight; m_szHeader.cx = MulDiv(m_szHeader.cx, m_nDPIx, 96); @@ -230,21 +245,16 @@ PatternCursor::Columns imax = cursor.GetColumnType(); LimitMax(imax, PatternCursor::lastColumn); -// if(imax > m_nDetailLevel) -// { -// // Extend to next channel -// imax = PatternCursor::firstColumn; -// cursor.Move(0, 1, 0); -// } - pt.x = (cursor.GetChannel() - xofs) * GetChannelWidth(); for(int i = 0; i < imax; i++) { - pt.x += pfnt->nEltWidths[i]; + if(m_visibleColumns[static_cast<PatternCursor::Columns>(i)]) + pt.x += pfnt->nEltWidths[i]; } - if (pt.x < 0) pt.x = 0; + if(pt.x < 0) + pt.x = 0; pt.x += Util::ScalePixels(ROWHDR_WIDTH, m_hWnd); pt.y = (cursor.GetRow() - yofs + m_nMidRow) * m_szCell.cy; @@ -266,11 +276,10 @@ int y = yofs - m_nMidRow + (pt.y - m_szHeader.cy + GetSmoothScrollOffset()) / m_szCell.cy; if (y < 0) y = 0; int xx = (pt.x - m_szHeader.cx) % GetChannelWidth(), dx = 0; - int imax = 4; - if (imax > (int)m_nDetailLevel + 1) imax = m_nDetailLevel + 1; - int i = 0; - for (i=0; i<imax; i++) + size_t i = 0; + for(; i < PatternCursor::lastColumn; i++) { + if(m_visibleColumns[static_cast<PatternCursor::Columns>(i)]) dx += pfnt->nEltWidths[i]; if(xx < dx) break; @@ -371,7 +380,7 @@ } #endif -static MPT_FORCEINLINE void DrawPadding(CFastBitmap &dib, const PATTERNFONT *pfnt, int x, int y, int col) +static MPT_FORCEINLINE void DrawPadding(CFastBitmap &dib, const PATTERNFONT *pfnt, int x, int y, PatternCursor::Columns col) { if(pfnt->padding[col]) dib.TextBlt(x + pfnt->nEltWidths[col] - pfnt->padding[col], y, pfnt->padding[col], pfnt->spacingY, pfnt->nClrX + pfnt->nEltWidths[col] - pfnt->padding[col], pfnt->nClrY, pfnt->dib); @@ -440,7 +449,7 @@ DrawLetter(x + pfnt->nNoteWidth[0] + pfnt->nNoteWidth[1], y, '?', pfnt->nOctaveWidth); } } - DrawPadding(m_Dib, pfnt, x, y, 0); + DrawPadding(m_Dib, pfnt, x, y, PatternCursor::noteColumn); } @@ -462,7 +471,7 @@ { m_Dib.TextBlt(x, y, pfnt->nEltWidths[1], pfnt->spacingY, pfnt->nClrX+pfnt->nEltWidths[0], pfnt->nClrY, pfnt->dib); } - DrawPadding(m_Dib, pfnt, x, y, 1); + DrawPadding(m_Dib, pfnt, x, y, PatternCursor::instrColumn); } @@ -504,11 +513,13 @@ pfnt->nNumX, pfnt->nNumY + (vol % 10) * pfnt->spacingY, pfnt->dib); } else { - int srcx = pfnt->nEltWidths[0] + pfnt->nEltWidths[1]; + int srcx = pfnt->nEltWidths[0]; + if(m_visibleColumns[PatternCursor::instrColumn]) + srcx += pfnt->nEltWidths[1]; m_Dib.TextBlt(x, y, pfnt->nEltWidths[2], pfnt->spacingY, pfnt->nClrX+srcx, pfnt->nClrY, pfnt->dib); } } - DrawPadding(m_Dib, pfnt, x, y, 2); + DrawPadding(m_Dib, pfnt, x, y, PatternCursor::volumeColumn); } @@ -700,9 +711,11 @@ const char *pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr]? "[Channel %u]" : "Channel %u"; if(channel.szName[0] != 0) pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr] ? "%u: [%s]" : "%u: %s"; - else if(m_nDetailLevel < PatternCursor::volumeColumn) + else if(const auto numVisibleColums = m_visibleColumns.count(); numVisibleColums < 2) + pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr] ? "[%u]" : "%u"; + else if(numVisibleColums < 3) pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr] ? "[Ch%u]" : "Ch%u"; - else if(m_nDetailLevel < PatternCursor::effectColumn) + else if(numVisibleColums < 5) pszfmt = sndFile.m_bChannelMuteTogglePending[ncolhdr] ? "[Chn %u]" : "Chn %u"; sprintf(s, pszfmt, ncolhdr + 1, channel.szName.buf); DrawButtonRect(hdc, &rect, s, @@ -834,6 +847,18 @@ CHANNELINDEX maxcol = ncols; while((maxcol > startChan) && (m_chnState[maxcol -1].selectedCols & COLUMN_BITS_INVISIBLE)) maxcol--; + + // Check if there's no "hole" in the visible columns (to speed up empty pattern cell drawing) + bool allColumnsConsecutive = true; + for(int i = LastVisibleColumn(); i >= 0; i--) + { + if(!m_visibleColumns[static_cast<PatternCursor::Columns>(i)]) + { + allColumnsConsecutive = false; + break; + } + } + // Init bitmap border { UINT maxndx = sndFile.GetNumChannels() * m_szCell.cx; @@ -842,7 +867,7 @@ do { ibmp += nColumnWidth; - m_Dib.TextBlt(ibmp-4, 0, 4, m_szCell.cy, pfnt->nClrX+pfnt->nWidth-4, pfnt->nClrY, pfnt->dib); + m_Dib.TextBlt(ibmp - SEPARATOR_WIDTH, 0, SEPARATOR_WIDTH, m_szCell.cy, pfnt->nClrX + pfnt->nWidth - SEPARATOR_WIDTH, pfnt->nClrY, pfnt->dib); } while (ibmp + nColumnWidth <= maxndx); } @@ -955,7 +980,7 @@ xbmp = nbmp = 0; do { - int x, bk_col, tx_col, col_sel, fx_col; + int x = 0, xClear = 0, bk_col, tx_col, col_sel, fx_col; const ModCommand *m = pattern.GetpModCommand(row, static_cast<CHANNELINDEX>(col)); @@ -968,20 +993,26 @@ const ModCommand *mold = m - ncols; const bool drawOldDefaultVolume = DrawDefaultVolume(mold); - if (m->note == mold->note) dwSpeedUpMask |= COLUMN_BITS_NOTE; - if ((m->instr == mold->instr) || (m_nDetailLevel < PatternCursor::instrColumn)) dwSpeedUpMask |= COLUMN_BITS_INSTRUMENT; - if ( m->IsPcNote() || mold->IsPcNote() ) + if(m->note == mold->note || !m_visibleColumns[PatternCursor::noteColumn]) + dwSpeedUpMask |= COLUMN_BITS_NOTE; + if((m->instr == mold->instr) || !m_visibleColumns[PatternCursor::instrColumn]) + dwSpeedUpMask |= COLUMN_BITS_INSTRUMENT; + if (m->IsPcNote() || mold->IsPcNote()) { // Handle speedup mask for PC notes. if(m->note == mold->note) { - if(m->GetValueVolCol() == mold->GetValueVolCol() || (m_nDetailLevel < PatternCursor::volumeColumn)) dwSpeedUpMask |= COLUMN_BITS_VOLUME; - if(m->GetValueEffectCol() == mold->GetValueEffectCol() || (m_nDetailLevel < PatternCursor::effectColumn)) dwSpeedUpMask |= COLUMN_BITS_FXCMDANDPARAM; + if(m->GetValueVolCol() == mold->GetValueVolCol() || !m_visibleColumns[PatternCursor::volumeColumn]) + dwSpeedUpMask |= COLUMN_BITS_VOLUME; + if(m->GetValueEffectCol() == mold->GetValueEffectCol() || !m_visibleColumns[PatternCursor::effectColumn]) + dwSpeedUpMask |= COLUMN_BITS_FXCMDANDPARAM; } } else { - if ((m->volcmd == mold->volcmd && (m->volcmd == VOLCMD_NONE || m->vol == mold->vol) && !drawDefaultVolume && !drawOldDefaultVolume) || (m_nDetailLevel < PatternCursor::volumeColumn)) dwSpeedUpMask |= COLUMN_BITS_VOLUME; - if ((m->command == mold->command) || (m_nDetailLevel < PatternCursor::effectColumn)) dwSpeedUpMask |= (m->command != CMD_NONE) ? COLUMN_BITS_FXCMD : COLUMN_BITS_FXCMDANDPARAM; + if ((m->volcmd == mold->volcmd && (m->volcmd == VOLCMD_NONE || m->vol == mold->vol) && !drawDefaultVolume && !drawOldDefaultVolume) || !m_visibleColumns[PatternCursor::volumeColumn]) + dwSpeedUpMask |= COLUMN_BITS_VOLUME; + if ((m->command == mold->command) || !m_visibleColumns[PatternCursor::effectColumn]) + dwSpeedUpMask |= (m->command != CMD_NONE) ? COLUMN_BITS_FXCMD : COLUMN_BITS_FXCMDANDPARAM; } if (dwSpeedUpMask == COLUMN_BITS_ALLCOLUMNS) goto DoBlit; } @@ -996,13 +1027,13 @@ bk_col = MODCOLOR_BACKSELECTED; } // Speedup: Empty command which is either not or fully selected - if (m->IsEmpty() && ((!col_sel) || (col_sel == COLUMN_BITS_ALLCOLUMNS))) + if (m->IsEmpty() && ((!col_sel) || (col_sel == COLUMN_BITS_ALLCOLUMNS)) && allColumnsConsecutive) { m_Dib.SetTextColor(tx_col, bk_col); - m_Dib.TextBlt(xbmp, 0, nColumnWidth-4, m_szCell.cy, pfnt->nClrX, pfnt->nClrY, pfnt->dib); + m_Dib.TextBlt(xbmp, 0, nColumnWidth - SEPARATOR_WIDTH, m_szCell.cy, pfnt->nClrX, pfnt->nClrY, pfnt->dib); goto DoBlit; } - x = 0; + // Note if (!(dwSpeedUpMask & COLUMN_BITS_NOTE)) { @@ -1041,8 +1072,9 @@ DrawNote(xbmp+x, 0, m->note); } x += pfnt->nEltWidths[0]; + xClear += pfnt->nEltWidths[0]; // Instrument - if (m_nDetailLevel >= PatternCursor::instrColumn) + if (m_visibleColumns[PatternCursor::instrColumn]) { if (!(dwSpeedUpMask & COLUMN_BITS_INSTRUMENT)) { @@ -1063,8 +1095,9 @@ } x += pfnt->nEltWidths[1]; } + xClear += pfnt->nEltWidths[1]; // Volume - if (m_nDetailLevel >= PatternCursor::volumeColumn) + if (m_visibleColumns[PatternCursor::volumeColumn]) { if (!(dwSpeedUpMask & COLUMN_BITS_VOLUME)) { @@ -1091,8 +1124,9 @@ } x += pfnt->nEltWidths[2]; } + xClear += pfnt->nEltWidths[2]; // Command & param - if (m_nDetailLevel >= PatternCursor::effectColumn) + if (m_visibleColumns[PatternCursor::effectColumn]) { const bool isPCnote = m->IsPcNote(); uint16 val = m->GetValueEffectCol(); @@ -1119,7 +1153,7 @@ m_Dib.SetTextColor(tx_col, bk_col); if(isPCnote) { - m_Dib.TextBlt(xbmp + x, 0, 2, pfnt->spacingY, pfnt->nClrX+x, pfnt->nClrY, pfnt->dib); + m_Dib.TextBlt(xbmp + x, 0, 2, pfnt->spacingY, pfnt->nClrX + xClear, pfnt->nClrY, pfnt->dib); m_Dib.TextBlt(xbmp + x + pfnt->pcValMargin, 0, pfnt->nEltWidths[3], m_szCell.cy, pfnt->nNumX, pfnt->nNumY+(val / 100)*pfnt->spacingY, pfnt->dib); } else { @@ -1130,12 +1164,13 @@ DrawLetter(xbmp+x, 0, n, pfnt->nEltWidths[3], pfnt->nCmdOfs); } else { - m_Dib.TextBlt(xbmp+x, 0, pfnt->nEltWidths[3], pfnt->spacingY, pfnt->nClrX+x, pfnt->nClrY, pfnt->dib); + m_Dib.TextBlt(xbmp+x, 0, pfnt->nEltWidths[3], pfnt->spacingY, pfnt->nClrX + xClear, pfnt->nClrY, pfnt->dib); } } - DrawPadding(m_Dib, pfnt, xbmp + x, 0, 3); + DrawPadding(m_Dib, pfnt, xbmp + x, 0, PatternCursor::effectColumn); } x += pfnt->nEltWidths[3]; + xClear += pfnt->nEltWidths[3]; // Param if (!(dwSpeedUpMask & COLUMN_BITS_FXPARAM)) { @@ -1162,10 +1197,10 @@ m_Dib.TextBlt(xbmp + x + pfnt->nParamHiWidth, 0, pfnt->nEltWidths[4] - pfnt->padding[4] - pfnt->nParamHiWidth, m_szCell.cy, pfnt->nNumX+pfnt->paramLoMargin, pfnt->nNumY+(m->param & 0x0F)*pfnt->spacingY, pfnt->dib); } else { - m_Dib.TextBlt(xbmp+x, 0, pfnt->nEltWidths[4], m_szCell.cy, pfnt->nClrX+x, pfnt->nClrY, pfnt->dib); + m_Dib.TextBlt(xbmp+x, 0, pfnt->nEltWidths[4], m_szCell.cy, pfnt->nClrX + xClear, pfnt->nClrY, pfnt->dib); } } - DrawPadding(m_Dib, pfnt, xbmp + x, 0, 4); + DrawPadding(m_Dib, pfnt, xbmp + x, 0, PatternCursor::paramColumn); } } DoBlit: @@ -1279,7 +1314,7 @@ if(end.GetColumnType() == PatternCursor::firstColumn) { // Special case: If selection ends on the last column of a channel, subtract the channel separator width. - ptBottomRight.x -= 4; + ptBottomRight.x -= SEPARATOR_WIDTH; } // invert the brush pattern (looks just like frame window sizing) @@ -1514,7 +1549,7 @@ m_Selection = PatternRect(beginSel, endSel); if(const CSoundFile *sndFile = GetSoundFile(); sndFile != nullptr && sndFile->Patterns.IsValidPat(m_nPattern)) { - m_Selection.Sanitize(sndFile->Patterns[m_nPattern].GetNumRows(), sndFile->GetNumChannels(), m_nDetailLevel); + m_Selection.Sanitize(sndFile->Patterns[m_nPattern].GetNumRows(), sndFile->GetNumChannels(), LastVisibleColumn()); } UpdateIndicator(); Modified: trunk/OpenMPT/mptrack/PatternCursor.h ============================================================================== --- trunk/OpenMPT/mptrack/PatternCursor.h Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/PatternCursor.h Thu Nov 7 22:11:52 2024 (r22106) @@ -31,6 +31,7 @@ effectColumn, paramColumn, lastColumn = paramColumn, + numColumns }; protected: Modified: trunk/OpenMPT/mptrack/PatternFindReplace.cpp ============================================================================== --- trunk/OpenMPT/mptrack/PatternFindReplace.cpp Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/PatternFindReplace.cpp Thu Nov 7 22:11:52 2024 (r22106) @@ -40,7 +40,7 @@ } else if(sndFile.Patterns.IsValidPat(m_nPattern)) { const CPattern &pat = sndFile.Patterns[m_nPattern]; - m_Cursor.Sanitize(pat.GetNumRows(), pat.GetNumChannels(), m_nDetailLevel); + m_Cursor.Sanitize(pat.GetNumRows(), pat.GetNumChannels(), LastVisibleColumn()); m = *pat.GetpModCommand(m_Cursor.GetRow(), m_Cursor.GetChannel()); } @@ -155,7 +155,7 @@ for(; chn <= lastChannel; chn++, m++) { - RowMask findWhere; + std::bitset<PatternCursor::numColumns> findWhere = std::bitset<PatternCursor::numColumns>{}.set(); if(FindReplace::instance.findFlags[FindReplace::InPatSelection]) { @@ -169,42 +169,31 @@ { PatternCursor cursor(row, chn, static_cast<PatternCursor::Columns>(i)); if(!FindReplace::instance.selection.Contains(cursor)) - { - switch(i) - { - case PatternCursor::noteColumn: findWhere.note = false; break; - case PatternCursor::instrColumn: findWhere.instrument = false; break; - case PatternCursor::volumeColumn: findWhere.volume = false; break; - case PatternCursor::effectColumn: findWhere.command = false; break; - case PatternCursor::paramColumn: findWhere.parameter = false; break; - } - } + findWhere.reset(i); } } else { // For channels inside the selection, we have an easier job to solve. if(!FindReplace::instance.selection.Contains(PatternCursor(row, chn))) - { - findWhere.Clear(); - } + findWhere.reset(); } } if(m->instr > 0) lastInstr[chn] = m->instr; - if((FindReplace::instance.findFlags[FindReplace::Note] && (!findWhere.note || m->note < FindReplace::instance.findNoteMin || m->note > FindReplace::instance.findNoteMax)) - || (FindReplace::instance.findFlags[FindReplace::Instr] && (!findWhere.instrument || m->instr < FindReplace::instance.findInstrMin || m->instr > FindReplace::instance.findInstrMax))) + if((FindReplace::instance.findFlags[FindReplace::Note] && (!findWhere[PatternCursor::noteColumn] || m->note < FindReplace::instance.findNoteMin || m->note > FindReplace::instance.findNoteMax)) + || (FindReplace::instance.findFlags[FindReplace::Instr] && (!findWhere[PatternCursor::instrColumn] || m->instr < FindReplace::instance.findInstrMin || m->instr > FindReplace::instance.findInstrMax))) { continue; } if(!m->IsPcNote()) { - if((FindReplace::instance.findFlags[FindReplace::VolCmd] && (!findWhere.volume || m->volcmd != FindReplace::instance.findVolCmd)) - || (FindReplace::instance.findFlags[FindReplace::Volume] && (!findWhere.volume || m->volcmd == VOLCMD_NONE || m->vol < FindReplace::instance.findVolumeMin || m->vol > FindReplace::instance.findVolumeMax)) - || (FindReplace::instance.findFlags[FindReplace::Command] && (!findWhere.command || m->command != FindReplace::instance.findCommand)) - || (FindReplace::instance.findFlags[FindReplace::Param] && (!findWhere.parameter || m->command == CMD_NONE || m->param < FindReplace::instance.findParamMin || m->param > FindReplace::instance.findParamMax)) + if((FindReplace::instance.findFlags[FindReplace::VolCmd] && (!findWhere[PatternCursor::volumeColumn] || m->volcmd != FindReplace::instance.findVolCmd)) + || (FindReplace::instance.findFlags[FindReplace::Volume] && (!findWhere[PatternCursor::volumeColumn] || m->volcmd == VOLCMD_NONE || m->vol < FindReplace::instance.findVolumeMin || m->vol > FindReplace::instance.findVolumeMax)) + || (FindReplace::instance.findFlags[FindReplace::Command] && (!findWhere[PatternCursor::effectColumn] || m->command != FindReplace::instance.findCommand)) + || (FindReplace::instance.findFlags[FindReplace::Param] && (!findWhere[PatternCursor::paramColumn] || m->command == CMD_NONE || m->param < FindReplace::instance.findParamMin || m->param > FindReplace::instance.findParamMax)) || FindReplace::instance.findFlags[FindReplace::PCParam] || FindReplace::instance.findFlags[FindReplace::PCValue]) { @@ -212,8 +201,8 @@ } } else { - if((FindReplace::instance.findFlags[FindReplace::PCParam] && (!findWhere.volume || m->GetValueVolCol() < FindReplace::instance.findParamMin || m->GetValueVolCol() > FindReplace::instance.findParamMax)) - || (FindReplace::instance.findFlags[FindReplace::PCValue] && (!(findWhere.command || findWhere.parameter) || m->GetValueEffectCol() < FindReplace::instance.findVolumeMin || m->GetValueEffectCol() > FindReplace::instance.findVolumeMax)) + if((FindReplace::instance.findFlags[FindReplace::PCParam] && (!findWhere[PatternCursor::volumeColumn] || m->GetValueVolCol() < FindReplace::instance.findParamMin || m->GetValueVolCol() > FindReplace::instance.findParamMax)) + || (FindReplace::instance.findFlags[FindReplace::PCValue] && (!(findWhere[PatternCursor::effectColumn] || findWhere[PatternCursor::paramColumn]) || m->GetValueEffectCol() < FindReplace::instance.findVolumeMin || m->GetValueEffectCol() > FindReplace::instance.findVolumeMax)) || FindReplace::instance.findFlags[FindReplace::VolCmd] || FindReplace::instance.findFlags[FindReplace::Volume] || FindReplace::instance.findFlags[FindReplace::Command] Modified: trunk/OpenMPT/mptrack/View_pat.cpp ============================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/View_pat.cpp Thu Nov 7 22:11:52 2024 (r22106) @@ -387,7 +387,9 @@ return false; } - LimitMax(column, m_nDetailLevel); + LimitMax(column, LastVisibleColumn()); + while(!m_visibleColumns[column]) + column = static_cast<PatternCursor::Columns>(column + 1); m_Cursor.SetColumn(channel, column); PatternCursor selStart(m_Cursor); @@ -403,6 +405,18 @@ } +PatternCursor::Columns CViewPattern::LastVisibleColumn() const noexcept +{ + for(size_t i = PatternCursor::lastColumn; i > PatternCursor::firstColumn; i--) + { + if(m_visibleColumns[i]) + return static_cast<PatternCursor::Columns>(i); + } + return PatternCursor::firstColumn; + +} + + // Set document as modified and optionally update all pattern views. void CViewPattern::SetModified(bool updateAllViews) { @@ -980,7 +994,7 @@ OnClearSelection(); } -void CViewPattern::OnClearSelection(bool ITStyle, RowMask rm) //Default RowMask: all elements enabled +void CViewPattern::OnClearSelection(bool ITStyle, std::bitset<PatternCursor::numColumns> rm) { CSoundFile *pSndFile = GetSoundFile(); if(pSndFile == nullptr || !pSndFile->Patterns.IsValidPat(m_nPattern) || !IsEditingEnabled_bmsg()) @@ -1008,7 +1022,7 @@ for(int i = PatternCursor::firstColumn; i <= PatternCursor::lastColumn; i++) { PatternCursor cell(row, chn, static_cast<PatternCursor::Columns>(i)); - if(!m_Selection.ContainsHorizontal(cell)) + if(!m_Selection.ContainsHorizontal(cell) || !rm[i]) { // We might have to skip the first / last few entries. continue; @@ -1017,61 +1031,46 @@ switch(i) { case PatternCursor::noteColumn: // Clear note - if(rm.note) + if(m.IsPcNote()) + { // Clear whole cell if clearing PC note + m.Clear(); + } else { - if(m.IsPcNote()) - { // Clear whole cell if clearing PC note - m.Clear(); - } else - { - m.note = NOTE_NONE; - if(ITStyle) - m.instr = 0; - } + m.note = NOTE_NONE; + if(ITStyle) + m.instr = 0; } break; case PatternCursor::instrColumn: // Clear instrument - if(rm.instrument) - { - m.instr = 0; - } + m.instr = 0; break; case PatternCursor::volumeColumn: // Clear volume - if(rm.volume) - { - m.volcmd = VOLCMD_NONE; - m.vol = 0; - } + m.volcmd = VOLCMD_NONE; + m.vol = 0; break; case PatternCursor::effectColumn: // Clear Command - if(rm.command) + m.command = CMD_NONE; + if(m.IsPcNote()) { - m.command = CMD_NONE; - if(m.IsPcNote()) - { - m.SetValueEffectCol(0); - } + m.SetValueEffectCol(0); } break; case PatternCursor::paramColumn: // Clear Command Param - if(rm.parameter) + m.param = 0; + if(m.IsPcNote()) { - m.param = 0; - if(m.IsPcNote()) - { - m.SetValueEffectCol(0); + m.SetValueEffectCol(0); - if(cell.CompareColumn(m_Selection.GetUpperLeft()) == 0) - { - // If this is the first selected column, update effect column char as well - PatternCursor upper(m_Selection.GetUpperLeft()); - upper.Move(0, 0, -1); - m_Selection = PatternRect(upper, m_Selection.GetLowerRight()); - } + if(cell.CompareColumn(m_Selection.GetUpperLeft()) == 0) + { + // If this is the first selected column, update effect column char as well + PatternCursor upper(m_Selection.GetUpperLeft()); + upper.Move(0, 0, -1); + m_Selection = PatternRect(upper, m_Selection.GetLowerRight()); } } break; @@ -3854,8 +3853,8 @@ if(pSndFile != nullptr && pSndFile->Patterns.IsValidPat(GetCurrentPattern())) { const auto &pattern = GetSoundFile()->Patterns[m_nPattern]; - m_Cursor.Sanitize(pattern.GetNumRows(), pattern.GetNumChannels(), m_nDetailLevel); - m_Selection.Sanitize(pattern.GetNumRows(), pattern.GetNumChannels(), m_nDetailLevel); + m_Cursor.Sanitize(pattern.GetNumRows(), pattern.GetNumChannels(), LastVisibleColumn()); + m_Selection.Sanitize(pattern.GetNumRows(), pattern.GetNumChannels(), LastVisibleColumn()); } }; @@ -4195,8 +4194,7 @@ if(lParam) { PATTERNVIEWSTATE *pState = (PATTERNVIEWSTATE *)lParam; - if(pState->nDetailLevel != PatternCursor::firstColumn) - m_nDetailLevel = pState->nDetailLevel; + UpdateVisibileColumns(pState->visibleColumns); if(pState->initialized) { SetCurrentPattern(pState->nPattern); @@ -4215,8 +4213,8 @@ pState->nPattern = m_nPattern; pState->cursor = m_Cursor; pState->selection = m_Selection; - pState->nDetailLevel = m_nDetailLevel; pState->nOrder = GetCurrentOrder(); + pState->visibleColumns = m_visibleColumns; } break; @@ -4261,15 +4259,11 @@ OnPatternAmplify(); break; + case VIEWMSG_GETDETAIL: + return m_visibleColumns.to_ulong(); + case VIEWMSG_SETDETAIL: - if(lParam != m_nDetailLevel) - { - m_nDetailLevel = static_cast<PatternCursor::Columns>(lParam); - UpdateSizes(); - UpdateScrollSize(); - SetCurrentColumn(m_Cursor); - InvalidatePattern(true, true); - } + UpdateVisibileColumns(lParam); break; case VIEWMSG_DOSCROLL: OnMouseWheel(0, static_cast<short>(lParam), CPoint(0, 0)); @@ -4513,8 +4507,8 @@ case kcEndHorizontalSelect: case kcEndHorizontal: - if(m_Cursor.CompareColumn(PatternCursor(0, sndFile.GetNumChannels() - 1, m_nDetailLevel)) < 0) - SetCurrentColumn(sndFile.GetNumChannels() - 1, m_nDetailLevel); + if(m_Cursor.CompareColumn(PatternCursor(0, sndFile.GetNumChannels() - 1, LastVisibleColumn())) < 0) + SetCurrentColumn(sndFile.GetNumChannels() - 1, LastVisibleColumn()); else if(GetCurrentRow() < pModDoc->GetPatternSize(m_nPattern) - 1) SetCurrentRow(pModDoc->GetPatternSize(m_nPattern) - 1); return wParam; @@ -4522,12 +4516,12 @@ case kcEndVertical: if(GetCurrentRow() < pModDoc->GetPatternSize(m_nPattern) - 1) SetCurrentRow(pModDoc->GetPatternSize(m_nPattern) - 1); - else if(m_Cursor.CompareColumn(PatternCursor(0, sndFile.GetNumChannels() - 1, m_nDetailLevel)) < 0) - SetCurrentColumn(sndFile.GetNumChannels() - 1, m_nDetailLevel); + else if(m_Cursor.CompareColumn(PatternCursor(0, sndFile.GetNumChannels() - 1, LastVisibleColumn())) < 0) + SetCurrentColumn(sndFile.GetNumChannels() - 1, LastVisibleColumn()); return wParam; case kcEndAbsoluteSelect: case kcEndAbsolute: - SetCurrentColumn(sndFile.GetNumChannels() - 1, m_nDetailLevel); + SetCurrentColumn(sndFile.GetNumChannels() - 1, LastVisibleColumn()); if(GetCurrentRow() < pModDoc->GetPatternSize(m_nPattern) - 1) SetCurrentRow(pModDoc->GetPatternSize(m_nPattern) - 1); return wParam; @@ -4613,12 +4607,12 @@ SetCurSel(PatternCursor(m_Selection.GetStartRow(), 0, PatternCursor::firstColumn), PatternCursor(m_Selection.GetEndRow(), sndFile.GetNumChannels(), PatternCursor::lastColumn)); return wParam; - case kcClearRow: OnClearField(RowMask(), false); return wParam; - case kcClearField: OnClearField(RowMask(m_Cursor), false); return wParam; - case kcClearFieldITStyle: OnClearField(RowMask(m_Cursor), false, true); return wParam; - case kcClearRowStep: OnClearField(RowMask(), true); return wParam; - case kcClearFieldStep: OnClearField(RowMask(m_Cursor), true); return wParam; - case kcClearFieldStepITStyle: OnClearField(RowMask(m_Cursor), true, true); return wParam; + case kcClearRow: OnClearField(std::bitset<PatternCursor::numColumns>{}.set(), false); return wParam; + case kcClearField: OnClearField(std::bitset<PatternCursor::numColumns>{}.set(m_Cursor.GetColumnType()), false); return wParam; + case kcClearFieldITStyle: OnClearField(std::bitset<PatternCursor::numColumns>{}.set(m_Cursor.GetColumnType()), false, true); return wParam; + case kcClearRowStep: OnClearField(std::bitset<PatternCursor::numColumns>{}.set(), true); return wParam; + case kcClearFieldStep: OnClearField(std::bitset<PatternCursor::numColumns>{}.set(m_Cursor.GetColumnType()), true); return wParam; + case kcClearFieldStepITStyle: OnClearField(std::bitset<PatternCursor::numColumns>{}.set(m_Cursor.GetColumnType()), true, true); return wParam; case kcDeleteRow: OnDeleteRow(); return wParam; case kcDeleteWholeRow: OnDeleteWholeRow(); return wParam; @@ -4695,6 +4689,10 @@ case kcToggleNoteOffRecordPC: TrackerSettings::Instance().m_dwPatternSetup ^= PATTERN_KBDNOTEOFF; return wParam; case kcToggleNoteOffRecordMIDI: TrackerSettings::Instance().m_dwMidiSetup ^= MIDISETUP_RECORDNOTEOFF; return wParam; + case kcToggleVisibilityInstrColumn: UpdateVisibileColumns(m_visibleColumns.flip(PatternCursor::instrColumn)); return wParam; + case kcToggleVisibilityVolumeColumn: UpdateVisibileColumns(m_visibleColumns.flip(PatternCursor::volumeColumn)); return wParam; + case kcToggleVisibilityEffectColumn : UpdateVisibileColumns(m_visibleColumns.flip(PatternCursor::effectColumn)); return wParam; + case kcPatternEditPCNotePlugin: OnTogglePCNotePluginEditor(); return wParam; case kcQuantizeSettings: OnSetQuantize(); return wParam; case kcLockPlaybackToRows: OnLockPatternRows(); return wParam; @@ -4872,16 +4870,19 @@ if((TrackerSettings::Instance().m_dwPatternSetup & PATTERN_WRAP) && m_Cursor.IsInFirstColumn()) { // Wrap around to last channel - SetCurrentColumn(GetDocument()->GetNumChannels() - 1, m_nDetailLevel); + SetCurrentColumn(GetDocument()->GetNumChannels() - 1, LastVisibleColumn()); } else if(!m_Cursor.IsInFirstColumn()) { - m_Cursor.Move(0, 0, -1); + do + { + m_Cursor.Move(0, 0, -1); + } while(!m_visibleColumns[m_Cursor.GetColumnType()]); SetCurrentColumn(m_Cursor); } } else { // Move cursor one column to the right - const PatternCursor rightmost(0, GetDocument()->GetNumChannels() - 1, m_nDetailLevel); + const PatternCursor rightmost(0, GetDocument()->GetNumChannels() - 1, LastVisibleColumn()); if(m_Cursor.CompareColumn(rightmost) >= 0) { if((TrackerSettings::Instance().m_dwPatternSetup & PATTERN_WRAP)) @@ -4897,7 +4898,7 @@ do { m_Cursor.Move(0, 0, 1); - } while(m_Cursor.GetColumnType() > m_nDetailLevel); + } while(!m_visibleColumns[m_Cursor.GetColumnType()]); SetCurrentColumn(m_Cursor); } } @@ -6269,7 +6270,7 @@ } -void CViewPattern::OnClearField(const RowMask &mask, bool step, bool ITStyle) +void CViewPattern::OnClearField(const std::bitset<PatternCursor::numColumns> mask, bool step, bool ITStyle) { CSoundFile *sndFile = GetSoundFile(); if(sndFile == nullptr || !IsEditingEnabled_bmsg()) @@ -6287,7 +6288,7 @@ ModCommand &target = GetCursorCommand(); ModCommand oldcmd = target; - if(mask.note) + if(mask[PatternCursor::noteColumn]) { // Clear note if(target.IsPcNote()) @@ -6303,29 +6304,29 @@ } } } - if(mask.instrument) + if(mask[PatternCursor::instrColumn]) { // Clear instrument target.instr = 0; } - if(mask.volume) + if(mask[PatternCursor::volumeColumn]) { // Clear volume effect target.volcmd = VOLCMD_NONE; target.vol = 0; } - if(mask.command) + if(mask[PatternCursor::effectColumn]) { // Clear effect command target.command = CMD_NONE; } - if(mask.parameter) + if(mask[PatternCursor::paramColumn]) { // Clear effect parameter target.param = 0; } - if((mask.command || mask.parameter) && (target.IsPcNote())) + if((mask[PatternCursor::effectColumn] || mask[PatternCursor::paramColumn]) && (target.IsPcNote())) { target.SetValueEffectCol(0); } Modified: trunk/OpenMPT/mptrack/View_pat.h ============================================================================== --- trunk/OpenMPT/mptrack/View_pat.h Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/View_pat.h Thu Nov 7 22:11:52 2024 (r22106) @@ -65,50 +65,6 @@ inline constexpr ROWINDEX MAX_SPACING = MAX_PATTERN_ROWS; -// Struct for controlling selection clearing. This is used to define which data fields should be cleared. -struct RowMask -{ - bool note : 1; - bool instrument : 1; - bool volume : 1; - bool command : 1; - bool parameter : 1; - - // Default row mask (all rows are selected) - RowMask() - { - note = instrument = volume = command = parameter = true; - }; - - // Construct mask from list - RowMask(bool n, bool i, bool v, bool c, bool p) - { - note = n; - instrument = i; - volume = v; - command = c; - parameter = p; - } - - // Construct mask from column index - RowMask(const PatternCursor &cursor) - { - const PatternCursor::Columns column = cursor.GetColumnType(); - - note = (column == PatternCursor::noteColumn); - instrument = (column == PatternCursor::instrColumn); - volume = (column == PatternCursor::volumeColumn); - command = (column == PatternCursor::effectColumn); - parameter = (column == PatternCursor::paramColumn); - } - - void Clear() - { - note = instrument = volume = command = parameter = false; - } -}; - - struct PatternEditPos { ROWINDEX row = ROWINDEX_INVALID; @@ -172,7 +128,7 @@ int m_nXScroll = 0, m_nYScroll = 0; int m_ledWidth = 0, m_ledHeight = 0; - PatternCursor::Columns m_nDetailLevel = PatternCursor::lastColumn; // Visible Columns + std::bitset<PatternCursor::numColumns> m_visibleColumns; // Cursor and selection positions PatternCursor m_Cursor; // Current cursor position in pattern. @@ -254,6 +210,7 @@ void UpdateIndicator(bool updateAccessibility = true); void UpdateXInfoText(); void UpdateColors(); + void UpdateVisibileColumns(std::bitset<PatternCursor::numColumns> visibleColumns); CString GetCursorDescription() const; @@ -372,7 +329,7 @@ PATTERNINDEX GetNextPattern() const; void SetSpacing(int n); - void OnClearField(const RowMask &mask, bool step, bool ITStyle = false); + void OnClearField(const std::bitset<PatternCursor::numColumns> mask, bool step, bool ITStyle = false); void SetSelectionInstrument(const INSTRUMENTINDEX instr, bool setEmptyInstrument); void FindInstrument(); @@ -428,7 +385,7 @@ afx_msg void OnEditPasteFlood() { ExecutePaste(PatternClipboard::pmPasteFlood); }; afx_msg void OnEditPushForwardPaste() { ExecutePaste(PatternClipboard::pmPushForward); }; - afx_msg void OnClearSelection(bool ITStyle = false, RowMask sb = RowMask()); + afx_msg void OnClearSelection(bool ITStyle = false, std::bitset<PatternCursor::numColumns> sb = std::bitset<PatternCursor::numColumns>{}.set()); afx_msg void OnGrowSelection(); afx_msg void OnShrinkSelection(); afx_msg void OnEditSelectAll(); @@ -593,6 +550,8 @@ void CreateVUMeterBitmap(); + PatternCursor::Columns LastVisibleColumn() const noexcept; + public: afx_msg void OnRButtonUp(UINT nFlags, CPoint point); Modified: trunk/OpenMPT/mptrack/WindowMessages.h ============================================================================== --- trunk/OpenMPT/mptrack/WindowMessages.h Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/WindowMessages.h Thu Nov 7 22:11:52 2024 (r22106) @@ -121,6 +121,7 @@ VIEWMSG_COPYPATTERN, VIEWMSG_PASTEPATTERN, VIEWMSG_AMPLIFYPATTERN, + VIEWMSG_GETDETAIL, VIEWMSG_SETDETAIL, // Sample-Specific VIEWMSG_SETCURRENTSAMPLE, Modified: trunk/OpenMPT/mptrack/mptrack.rc ============================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/mptrack.rc Thu Nov 7 22:11:52 2024 (r22106) @@ -3227,15 +3227,13 @@ STRINGTABLE BEGIN - ID_SAMPLE_TRIM "Delete everything except the current selection\nTrim Sample" - ID_FILE_SAVEMIDI "Export the current song to a standard MIDI file" - ID_INSTRUMENT_SAMPLEMAP "Edit the sample map" - ID_SAMPLE_ZOOMUP "Zoom In" - ID_SAMPLE_ZOOMDOWN "Zoom Out" - ID_PATTERNDETAIL_LO "Low pattern detail level\nLow pattern detail level" - ID_PATTERNDETAIL_MED "Medium pattern detail level\nMedium pattern detail level" - ID_PATTERNDETAIL_HI "High pattern detail level\nHigh pattern detail level" - ID_PATTERN_AMPLIFY "Amplify selection\nAmplify" + ID_SAMPLE_TRIM "Delete everything except the current selection\nTrim Sample" + ID_FILE_SAVEMIDI "Export the current song to a standard MIDI file" + ID_INSTRUMENT_SAMPLEMAP "Edit the sample map" + ID_SAMPLE_ZOOMUP "Zoom In" + ID_SAMPLE_ZOOMDOWN "Zoom Out" + ID_PATTERNDETAIL_DROPDOWN "Toggle visibility of pattern columns\nToggle visibility of pattern columns" + ID_PATTERN_AMPLIFY "Amplify selection\nAmplify" END STRINGTABLE Modified: trunk/OpenMPT/mptrack/res/originals/pattern_toolbar.pfi ============================================================================== Binary file (source and/or target). No diff available. Modified: trunk/OpenMPT/mptrack/res/pattern_toolbar.png ============================================================================== Binary file (source and/or target). No diff available. Modified: trunk/OpenMPT/mptrack/resource.h ============================================================================== --- trunk/OpenMPT/mptrack/resource.h Wed Nov 6 22:19:28 2024 (r22105) +++ trunk/OpenMPT/mptrack/resource.h Thu Nov 7 22:11:52 2024 (r22106) @@ -1092,11 +1092,12 @@ #define ID_SAMPLE_SLICE 32885 #define ID_INSTRUMENT_SAMPLEMAP 32886 #define ID_SAMPLE_MONOCONVERT 32887 +#define ID_PATTERNDETAIL_DROPDOWN 32888 #define ID_SAMPLE_ZOOMUP 32889 #define ID_SAMPLE_ZOOMDOWN 32890 -#define ID_PATTERNDETAIL_LO 32891 -#define ID_PATTERNDETAIL_MED 32892 -#define ID_PATTERNDETAIL_HI 32893 +#define ID_PATTERNDETAIL_INSTR 32891 +#define ID_PATTERNDETAIL_VOLUME 32892 +#define ID_PATTERNDETAIL_EFFECT 32893 #define ID_INSTRUMENT_DUPLICATE 32894 #define ID_PATTERN_AMPLIFY 32895 #define ID_MODTREE_MUTE 32896 |