diff --git a/CMakeLists.txt b/CMakeLists.txt index 33dba8239..2aa5d92a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -807,6 +807,7 @@ src/gui/log.cpp src/gui/mixer.cpp src/gui/midiMap.cpp src/gui/newSong.cpp +src/gui/commandPalette.cpp src/gui/orders.cpp src/gui/osc.cpp src/gui/patManager.cpp diff --git a/src/gui/commandPalette.cpp b/src/gui/commandPalette.cpp new file mode 100644 index 000000000..6052fe054 --- /dev/null +++ b/src/gui/commandPalette.cpp @@ -0,0 +1,253 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2024 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "gui.h" +#include "guiConst.h" +#include "commandPalette.h" +#include "misc/cpp/imgui_stdlib.h" +#include +#include +#include +#include "../ta-log.h" + +static inline bool matchFuzzy(const char* haystack, const char* needle) { + size_t h_i=0; // haystack idx + size_t n_i=0; // needle idx + while (needle[n_i]!='\0') { + for (; std::tolower(haystack[h_i])!=std::tolower(needle[n_i]); h_i++) { + if (haystack[h_i]=='\0') + return false; + } + n_i+=1; + } + return true; +} + +void FurnaceGUI::drawPalette() { + bool accepted=false; + + if (paletteFirstFrame) + ImGui::SetKeyboardFocusHere(); + + int width=ImGui::GetContentRegionAvail().x; + ImGui::SetNextItemWidth(width); + + const char* hint="Search..."; + switch (curPaletteType) { + case CMDPAL_TYPE_RECENT: + hint="Search recent files..."; + break; + case CMDPAL_TYPE_INSTRUMENTS: + hint="Search instruments..."; + break; + case CMDPAL_TYPE_SAMPLES: + hint="Search samples..."; + break; + case CMDPAL_TYPE_INSTRUMENT_CHANGE: + hint="Search instruments (to change to)..."; + break; + case CMDPAL_TYPE_ADD_CHIP: + hint="Search chip (to add)..."; + break; + } + + if (ImGui::InputTextWithHint("##CommandPaletteSearch",hint,&paletteQuery) || paletteFirstFrame) { + paletteSearchResults.clear(); + + switch (curPaletteType) { + case CMDPAL_TYPE_MAIN: + for (int i=0; isong.insLen; i++) { + String s=fmt::sprintf("%02X: %s", i, e->song.ins[i]->name.c_str()); + if (matchFuzzy(s.c_str(),paletteQuery.c_str())) { + paletteSearchResults.push_back(i+1); // because over here ins=0 is 'None' + } + } + break; + + case CMDPAL_TYPE_SAMPLES: + for (int i=0; isong.sampleLen; i++) { + if (matchFuzzy(e->song.sample[i]->name.c_str(),paletteQuery.c_str())) { + paletteSearchResults.push_back(i); + } + } + break; + + case CMDPAL_TYPE_ADD_CHIP: + for (int i=0; availableSystems[i]; i++) { + int ds=availableSystems[i]; + const char* sysname=getSystemName((DivSystem)ds); + if (matchFuzzy(sysname,paletteQuery.c_str())) { + paletteSearchResults.push_back(ds); + } + } + break; + + default: + logE("invalid command palette type"); + ImGui::CloseCurrentPopup(); + break; + }; + } + + ImVec2 avail=ImGui::GetContentRegionAvail(); + avail.y-=ImGui::GetFrameHeightWithSpacing(); + + if (ImGui::BeginChild("CommandPaletteList",avail,false,0)) { + bool navigated=false; + if (ImGui::IsKeyPressed(ImGuiKey_UpArrow) && curPaletteChoice>0) { + curPaletteChoice-=1; + navigated=true; + } + if (ImGui::IsKeyPressed(ImGuiKey_DownArrow)) { + curPaletteChoice+=1; + navigated=true; + } + + if (paletteSearchResults.size()>0 && curPaletteChoice<0) { + curPaletteChoice=0; + navigated=true; + } + if (curPaletteChoice>=(int)paletteSearchResults.size()) { + curPaletteChoice=paletteSearchResults.size()-1; + navigated=true; + } + + for (int i=0; i<(int)paletteSearchResults.size(); i++) { + bool current=(i==curPaletteChoice); + int id=paletteSearchResults[i]; + + String s="???"; + switch (curPaletteType) { + case CMDPAL_TYPE_MAIN: + s=guiActions[id].friendlyName; + break; + case CMDPAL_TYPE_RECENT: + s=recentFile[id].c_str(); + break; + case CMDPAL_TYPE_INSTRUMENTS: + case CMDPAL_TYPE_INSTRUMENT_CHANGE: + if (id==0) { + s="- None -"; + } else { + s=fmt::sprintf("%02X: %s", id-1, e->song.ins[id-1]->name.c_str()); + } + break; + case CMDPAL_TYPE_SAMPLES: + s=e->song.sample[id]->name.c_str(); + break; + case CMDPAL_TYPE_ADD_CHIP: + s=getSystemName((DivSystem)id); + break; + default: + logE("invalid command palette type"); + break; + }; + + if (ImGui::Selectable(s.c_str(),current)) { + curPaletteChoice=i; + accepted=true; + } + if ((navigated || paletteFirstFrame) && current) ImGui::SetScrollHereY(); + } + } + ImGui::EndChild(); + + if (!accepted) { + if (curPaletteChoice>=(int)paletteSearchResults.size()) { + curPaletteChoice=paletteSearchResults.size()-1; + } + accepted=ImGui::IsKeyPressed(ImGuiKey_Enter); + } + + if (ImGui::Button("Cancel") || ImGui::IsKeyPressed(ImGuiKey_Escape)) { + ImGui::CloseCurrentPopup(); + } + + // do not move this to after the resetPalette() calls! + // if they are called before and we're jumping from one palette to the next, the paletteFirstFrame won't be true at the start and the setup will not happen. + paletteFirstFrame=false; + + if (accepted) { + if (paletteSearchResults.size()>0) { + int i=paletteSearchResults[curPaletteChoice]; + switch (curPaletteType) { + case CMDPAL_TYPE_MAIN: + doAction(i); + break; + + case CMDPAL_TYPE_RECENT: + openRecentFile(recentFile[i]); + break; + + case CMDPAL_TYPE_INSTRUMENTS: + curIns=i-1; + break; + + case CMDPAL_TYPE_SAMPLES: + curSample=i; + break; + + case CMDPAL_TYPE_INSTRUMENT_CHANGE: + doChangeIns(i-1); + break; + + case CMDPAL_TYPE_ADD_CHIP: + if (i!=DIV_SYSTEM_NULL) { + if (!e->addSystem((DivSystem)i)) { + showError("cannot add chip! ("+e->getLastError()+")"); + } else { + MARK_MODIFIED; + } + ImGui::CloseCurrentPopup(); + if (e->song.autoSystem) { + autoDetectSystem(); + } + updateWindowTitle(); + } + break; + + default: + logE("invalid command palette type"); + break; + }; + } + ImGui::CloseCurrentPopup(); + } +} diff --git a/src/gui/commandPalette.h b/src/gui/commandPalette.h new file mode 100644 index 000000000..7b748fd17 --- /dev/null +++ b/src/gui/commandPalette.h @@ -0,0 +1,31 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2024 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +enum CommandPaletteType { + CMDPAL_TYPE_MAIN = 0, + CMDPAL_TYPE_RECENT, + CMDPAL_TYPE_INSTRUMENTS, + CMDPAL_TYPE_SAMPLES, + CMDPAL_TYPE_INSTRUMENT_CHANGE, + CMDPAL_TYPE_ADD_CHIP, + // a menu to select wavetables is beyond scope (they can't be put as strings) + // TODO: are there more? + + CMDPAL_TYPE_MAX, +}; diff --git a/src/gui/doAction.cpp b/src/gui/doAction.cpp index 73f3ce2d3..e31eb289f 100644 --- a/src/gui/doAction.cpp +++ b/src/gui/doAction.cpp @@ -18,6 +18,7 @@ */ #include "gui.h" +#include "commandPalette.h" #include "../ta-log.h" #include #include @@ -195,7 +196,30 @@ void FurnaceGUI::doAction(int what) { case GUI_ACTION_CLEAR: showWarning("Select an option: (cannot be undone!)",GUI_WARN_CLEAR); break; - + case GUI_ACTION_COMMAND_PALETTE: + displayPalette=true; + curPaletteType=CMDPAL_TYPE_MAIN; + break; + case GUI_ACTION_CMDPAL_RECENT: + displayPalette=true; + curPaletteType=CMDPAL_TYPE_RECENT; + break; + case GUI_ACTION_CMDPAL_INSTRUMENTS: + displayPalette=true; + curPaletteType=CMDPAL_TYPE_INSTRUMENTS; + break; + case GUI_ACTION_CMDPAL_SAMPLES: + displayPalette=true; + curPaletteType=CMDPAL_TYPE_SAMPLES; + break; + case GUI_ACTION_CMDPAL_INSTRUMENT_CHANGE: + displayPalette=true; + curPaletteType=CMDPAL_TYPE_INSTRUMENT_CHANGE; + break; + case GUI_ACTION_CMDPAL_ADD_CHIP: + displayPalette=true; + curPaletteType=CMDPAL_TYPE_ADD_CHIP; + break; case GUI_ACTION_WINDOW_EDIT_CONTROLS: nextWindow=GUI_WINDOW_EDIT_CONTROLS; break; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index a5911f7ef..8babeec8a 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2264,6 +2264,17 @@ int FurnaceGUI::load(String path) { return 0; } +void FurnaceGUI::openRecentFile(String path) { + if (modified) { + nextFile=path; + showWarning("Unsaved changes! Save changes before opening file?",GUI_WARN_OPEN_DROP); + } else { + if (load(path)>0) { + showError(fmt::sprintf("Error while loading file! (%s)",lastError)); + } + } +} + void FurnaceGUI::pushRecentFile(String path) { if (path.empty()) return; if (path.find(backupPath)==0) return; @@ -4126,10 +4137,8 @@ bool FurnaceGUI::loop() { } else { recentFile.erase(i); i--; - if (load(item)>0) { - showError(fmt::sprintf("Error while loading file! (%s)",lastError)); - } } + openRecentFile(item); } } if (recentFile.empty()) { @@ -4382,6 +4391,8 @@ bool FurnaceGUI::loop() { ImGui::EndMenu(); } if (ImGui::BeginMenu(settings.capitalMenuBar?"Window":"window")) { + if (ImGui::MenuItem("command palette",BIND_FOR(GUI_ACTION_COMMAND_PALETTE))) + displayPalette=true; if (ImGui::MenuItem("song information",BIND_FOR(GUI_ACTION_WINDOW_SONG_INFO),songInfoOpen)) songInfoOpen=!songInfoOpen; if (ImGui::MenuItem("subsongs",BIND_FOR(GUI_ACTION_WINDOW_SUBSONGS),subSongsOpen)) subSongsOpen=!subSongsOpen; if (ImGui::MenuItem("speed",BIND_FOR(GUI_ACTION_WINDOW_SPEED),speedOpen)) speedOpen=!speedOpen; @@ -5437,6 +5448,15 @@ bool FurnaceGUI::loop() { } } + if (displayPalette) { + paletteSearchResults.clear(); + paletteQuery=""; + paletteFirstFrame=true; + curPaletteChoice=0; + displayPalette=false; + ImGui::OpenPopup("Command Palette"); + } + if (displayExport) { displayExport=false; ImGui::OpenPopup("Export"); @@ -5483,6 +5503,14 @@ bool FurnaceGUI::loop() { ImGui::EndPopup(); } + ImVec2 wsize=ImVec2(canvasW*0.9,canvasH*0.4); + ImGui::SetNextWindowPos(ImVec2((canvasW-wsize.x)*0.5,50*dpiScale)); + ImGui::SetNextWindowSize(wsize,ImGuiCond_Always); + if (ImGui::BeginPopup("Command Palette",ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings)) { + drawPalette(); + ImGui::EndPopup(); + } + if (ImGui::BeginPopupModal("Export",NULL,ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::SetWindowPos(ImVec2(((canvasW)-ImGui::GetWindowSize().x)*0.5,((canvasH)-ImGui::GetWindowSize().y)*0.5)); drawExport(); @@ -7289,6 +7317,7 @@ FurnaceGUI::FurnaceGUI(): oldWantCaptureKeyboard(false), displayMacroMenu(false), displayNew(false), + displayPalette(false), fullScreen(false), preserveChanPos(false), wantScrollList(false), @@ -7409,6 +7438,8 @@ FurnaceGUI::FurnaceGUI(): oldBar(-1), curGroove(-1), exitDisabledTimer(0), + curPaletteChoice(0), + curPaletteType(0), soloTimeout(0.0f), exportFadeOut(5.0), patExtraButtons(false), diff --git a/src/gui/gui.h b/src/gui/gui.h index 8be24fdd2..3d9a05e61 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -606,6 +606,15 @@ enum FurnaceGUIActions { GUI_ACTION_PANIC, GUI_ACTION_CLEAR, + GUI_ACTION_COMMAND_PALETTE, + GUI_ACTION_CMDPAL_MIN, + GUI_ACTION_CMDPAL_RECENT, + GUI_ACTION_CMDPAL_INSTRUMENTS, + GUI_ACTION_CMDPAL_SAMPLES, + GUI_ACTION_CMDPAL_INSTRUMENT_CHANGE, + GUI_ACTION_CMDPAL_ADD_CHIP, + GUI_ACTION_CMDPAL_MAX, + GUI_ACTION_WINDOW_EDIT_CONTROLS, GUI_ACTION_WINDOW_ORDERS, GUI_ACTION_WINDOW_INS_LIST, @@ -1452,7 +1461,7 @@ class FurnaceGUI { int sampleTexW, sampleTexH; bool updateSampleTex; - String workingDir, fileName, clipboard, warnString, errorString, lastError, curFileName, nextFile, sysSearchQuery, newSongQuery; + String workingDir, fileName, clipboard, warnString, errorString, lastError, curFileName, nextFile, sysSearchQuery, newSongQuery, paletteQuery; String workingDirSong, workingDirIns, workingDirWave, workingDirSample, workingDirAudioExport; String workingDirVGMExport, workingDirZSMExport, workingDirROMExport, workingDirFont, workingDirColors, workingDirKeybinds; String workingDirLayout, workingDirROM, workingDirTest; @@ -1463,6 +1472,7 @@ class FurnaceGUI { std::vector sysSearchResults; std::vector newSongSearchResults; + std::vector paletteSearchResults; FixedQueue recentFile; std::vector makeInsTypeList; std::vector waveSizeList; @@ -1473,7 +1483,7 @@ class FurnaceGUI { bool vgmExportDirectStream, displayInsTypeList, displayWaveSizeList; bool portrait, injectBackUp, mobileMenuOpen, warnColorPushed; bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu; - bool displayNew, displayExport, fullScreen, preserveChanPos, wantScrollList, noteInputPoly, notifyWaveChange; + bool displayNew, displayExport, displayPalette, fullScreen, preserveChanPos, wantScrollList, noteInputPoly, notifyWaveChange; bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString; bool mobileEdit; bool killGraphics; @@ -1991,6 +2001,7 @@ class FurnaceGUI { int loopOrder, loopRow, loopEnd, isClipping, newSongCategory, latchTarget; int wheelX, wheelY, dragSourceX, dragSourceXFine, dragSourceY, dragDestinationX, dragDestinationXFine, dragDestinationY, oldBeat, oldBar; int curGroove, exitDisabledTimer; + int curPaletteChoice, curPaletteType; float soloTimeout; double exportFadeOut; @@ -1998,7 +2009,7 @@ class FurnaceGUI { bool patExtraButtons, patChannelNames, patChannelPairs; unsigned char patChannelHints; - bool newSongFirstFrame, oldRowChanged; + bool newSongFirstFrame, paletteFirstFrame, oldRowChanged; bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen; bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen; bool mixerOpen, debugOpen, inspectorOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen; @@ -2510,6 +2521,7 @@ class FurnaceGUI { void drawSettings(); void drawDebug(); void drawNewSong(); + void drawPalette(); void drawExport(); void drawLog(); void drawEffectList(); @@ -2615,6 +2627,7 @@ class FurnaceGUI { int save(String path, int dmfVersion); int load(String path); int loadStream(String path); + void openRecentFile(String path); void pushRecentFile(String path); void pushRecentSys(const char* path); void exportAudio(String path, DivAudioExportModes mode); diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index 30bf33d20..9095451af 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -559,6 +559,15 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={ D("PANIC", "Panic", SDLK_F12), D("CLEAR", "Clear song data", 0), + D("COMMAND_PALETTE", "Command Palette", FURKMOD_CMD|SDLK_p), + D("CMDPAL_MIN", "", NOT_AN_ACTION), + D("CMDPAL_RECENT", "Recent files (Palette)", 0), + D("CMDPAL_INSTRUMENTS", "Instruments (Palette)", 0), + D("CMDPAL_SAMPLES", "Samples (Palette)", 0), + D("CMDPAL_INSTRUMENT_CHANGE", "Change instrument (Palette)", 0), + D("CMDPAL_ADD_CHIP", "Add chip (Palette)", 0), + D("CMDPAL_MAX", "", NOT_AN_ACTION), + D("WINDOW_EDIT_CONTROLS", "Edit Controls", 0), D("WINDOW_ORDERS", "Orders", 0), D("WINDOW_INS_LIST", "Instrument List", 0), @@ -669,111 +678,111 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={ D("PAT_MAX", "", NOT_AN_ACTION), D("INS_LIST_MIN", "---Instrument list", NOT_AN_ACTION), - D("INS_LIST_ADD", "Add", SDLK_INSERT), - D("INS_LIST_DUPLICATE", "Duplicate", FURKMOD_CMD|SDLK_d), - D("INS_LIST_OPEN", "Open", 0), - D("INS_LIST_OPEN_REPLACE", "Open (replace current)", 0), - D("INS_LIST_SAVE", "Save", 0), - D("INS_LIST_SAVE_DMP", "Save (.dmp)", 0), - D("INS_LIST_MOVE_UP", "Move up", FURKMOD_SHIFT|SDLK_UP), - D("INS_LIST_MOVE_DOWN", "Move down", FURKMOD_SHIFT|SDLK_DOWN), - D("INS_LIST_DELETE", "Delete", 0), - D("INS_LIST_EDIT", "Edit", FURKMOD_SHIFT|SDLK_RETURN), - D("INS_LIST_UP", "Cursor up", SDLK_UP), - D("INS_LIST_DOWN", "Cursor down", SDLK_DOWN), - D("INS_LIST_DIR_VIEW", "Toggle folders/standard view", FURKMOD_CMD|SDLK_v), + D("INS_LIST_ADD", "Add instrument", SDLK_INSERT), + D("INS_LIST_DUPLICATE", "Duplicate instrument", FURKMOD_CMD|SDLK_d), + D("INS_LIST_OPEN", "Open instrument", 0), + D("INS_LIST_OPEN_REPLACE", "Open instrument (replace current)", 0), + D("INS_LIST_SAVE", "Save instrument", 0), + D("INS_LIST_SAVE_DMP", "Save instrument (.dmp)", 0), + D("INS_LIST_MOVE_UP", "Move instrument up in list", FURKMOD_SHIFT|SDLK_UP), + D("INS_LIST_MOVE_DOWN", "Move instrument down in list", FURKMOD_SHIFT|SDLK_DOWN), + D("INS_LIST_DELETE", "Delete instrument", 0), + D("INS_LIST_EDIT", "Edit instrument", FURKMOD_SHIFT|SDLK_RETURN), + D("INS_LIST_UP", "Instrument cursor up", SDLK_UP), + D("INS_LIST_DOWN", "Instrument cursor down", SDLK_DOWN), + D("INS_LIST_DIR_VIEW", "Instruments: toggle folders/standard view", FURKMOD_CMD|SDLK_v), D("INS_LIST_MAX", "", NOT_AN_ACTION), D("WAVE_LIST_MIN", "---Wavetable list", NOT_AN_ACTION), - D("WAVE_LIST_ADD", "Add", SDLK_INSERT), - D("WAVE_LIST_DUPLICATE", "Duplicate", FURKMOD_CMD|SDLK_d), - D("WAVE_LIST_OPEN", "Open", 0), - D("WAVE_LIST_OPEN_REPLACE", "Open (replace current)", 0), - D("WAVE_LIST_SAVE", "Save", 0), - D("WAVE_LIST_SAVE_DMW", "Save (.dmw)", 0), - D("WAVE_LIST_SAVE_RAW", "Save (raw)", 0), - D("WAVE_LIST_MOVE_UP", "Move up", FURKMOD_SHIFT|SDLK_UP), - D("WAVE_LIST_MOVE_DOWN", "Move down", FURKMOD_SHIFT|SDLK_DOWN), - D("WAVE_LIST_DELETE", "Delete", 0), - D("WAVE_LIST_EDIT", "Edit", FURKMOD_SHIFT|SDLK_RETURN), - D("WAVE_LIST_UP", "Cursor up", SDLK_UP), - D("WAVE_LIST_DOWN", "Cursor down", SDLK_DOWN), - D("WAVE_LIST_DIR_VIEW", "Toggle folders/standard view", FURKMOD_CMD|SDLK_v), + D("WAVE_LIST_ADD", "Add wavetable", SDLK_INSERT), + D("WAVE_LIST_DUPLICATE", "Duplicate wavetable", FURKMOD_CMD|SDLK_d), + D("WAVE_LIST_OPEN", "Open wavetable", 0), + D("WAVE_LIST_OPEN_REPLACE", "Open wavetable (replace current)", 0), + D("WAVE_LIST_SAVE", "Save wavetable", 0), + D("WAVE_LIST_SAVE_DMW", "Save wavetable (.dmw)", 0), + D("WAVE_LIST_SAVE_RAW", "Save wavetable (raw)", 0), + D("WAVE_LIST_MOVE_UP", "Move wavetable up in list", FURKMOD_SHIFT|SDLK_UP), + D("WAVE_LIST_MOVE_DOWN", "Move wavetable down in list", FURKMOD_SHIFT|SDLK_DOWN), + D("WAVE_LIST_DELETE", "Delete wavetable", 0), + D("WAVE_LIST_EDIT", "Edit wavetable", FURKMOD_SHIFT|SDLK_RETURN), + D("WAVE_LIST_UP", "Wavetable cursor up", SDLK_UP), + D("WAVE_LIST_DOWN", "Wavetable cursor down", SDLK_DOWN), + D("WAVE_LIST_DIR_VIEW", "Wavetables: toggle folders/standard view", FURKMOD_CMD|SDLK_v), D("WAVE_LIST_MAX", "", NOT_AN_ACTION), D("SAMPLE_LIST_MIN", "---Sample list", NOT_AN_ACTION), - D("SAMPLE_LIST_ADD", "Add", SDLK_INSERT), - D("SAMPLE_LIST_DUPLICATE", "Duplicate", FURKMOD_CMD|SDLK_d), - D("SAMPLE_LIST_OPEN", "Open", 0), - D("SAMPLE_LIST_OPEN_REPLACE", "Open (replace current)", 0), - D("SAMPLE_LIST_OPEN_RAW", "Import raw data", 0), - D("SAMPLE_LIST_OPEN_REPLACE_RAW", "Import raw data (replace current)", 0), - D("SAMPLE_LIST_SAVE", "Save", 0), - D("SAMPLE_LIST_SAVE_RAW", "Save (raw)", 0), - D("SAMPLE_LIST_MOVE_UP", "Move up", FURKMOD_SHIFT|SDLK_UP), - D("SAMPLE_LIST_MOVE_DOWN", "Move down", FURKMOD_SHIFT|SDLK_DOWN), - D("SAMPLE_LIST_DELETE", "Delete", 0), - D("SAMPLE_LIST_EDIT", "Edit", FURKMOD_SHIFT|SDLK_RETURN), - D("SAMPLE_LIST_UP", "Cursor up", SDLK_UP), - D("SAMPLE_LIST_DOWN", "Cursor down", SDLK_DOWN), - D("SAMPLE_LIST_PREVIEW", "Preview", 0), - D("SAMPLE_LIST_STOP_PREVIEW", "Stop preview", 0), - D("SAMPLE_LIST_DIR_VIEW", "Toggle folders/standard view", FURKMOD_CMD|SDLK_v), - D("SAMPLE_LIST_MAKE_MAP", "Make me a drum kit", 0), + D("SAMPLE_LIST_ADD", "Add sample", SDLK_INSERT), + D("SAMPLE_LIST_DUPLICATE", "Duplicate sample", FURKMOD_CMD|SDLK_d), + D("SAMPLE_LIST_OPEN", "Open sample", 0), + D("SAMPLE_LIST_OPEN_REPLACE", "Open sample (replace current)", 0), + D("SAMPLE_LIST_OPEN_RAW", "Import raw sample data", 0), + D("SAMPLE_LIST_OPEN_REPLACE_RAW", "Import raw sample data (replace current)", 0), + D("SAMPLE_LIST_SAVE", "Save sample", 0), + D("SAMPLE_LIST_SAVE_RAW", "Save sample (raw)", 0), + D("SAMPLE_LIST_MOVE_UP", "Move sample up in list", FURKMOD_SHIFT|SDLK_UP), + D("SAMPLE_LIST_MOVE_DOWN", "Move sample down in list", FURKMOD_SHIFT|SDLK_DOWN), + D("SAMPLE_LIST_DELETE", "Delete sample", 0), + D("SAMPLE_LIST_EDIT", "Edit sample", FURKMOD_SHIFT|SDLK_RETURN), + D("SAMPLE_LIST_UP", "Sample cursor up", SDLK_UP), + D("SAMPLE_LIST_DOWN", "Sample cursor down", SDLK_DOWN), + D("SAMPLE_LIST_PREVIEW", "Sample preview", 0), + D("SAMPLE_LIST_STOP_PREVIEW", "Stop sample preview", 0), + D("SAMPLE_LIST_DIR_VIEW", "Samples: Toggle folders/standard view", FURKMOD_CMD|SDLK_v), + D("SAMPLE_LIST_MAKE_MAP", "Samples: Make me a drum kit", 0), D("SAMPLE_LIST_MAX", "", NOT_AN_ACTION), D("SAMPLE_MIN", "---Sample editor", NOT_AN_ACTION), - D("SAMPLE_SELECT", "Edit mode: Select", FURKMOD_SHIFT|SDLK_i), - D("SAMPLE_DRAW", "Edit mode: Draw", FURKMOD_SHIFT|SDLK_d), - D("SAMPLE_CUT", "Cut", FURKMOD_CMD|SDLK_x), - D("SAMPLE_COPY", "Copy", FURKMOD_CMD|SDLK_c), - D("SAMPLE_PASTE", "Paste", FURKMOD_CMD|SDLK_v), - D("SAMPLE_PASTE_REPLACE", "Paste replace", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_v), - D("SAMPLE_PASTE_MIX", "Paste mix", FURKMOD_CMD|FURKMOD_ALT|SDLK_v), - D("SAMPLE_SELECT_ALL", "Select all", FURKMOD_CMD|SDLK_a), - D("SAMPLE_RESIZE", "Resize", FURKMOD_CMD|SDLK_r), - D("SAMPLE_RESAMPLE", "Resample", FURKMOD_CMD|SDLK_e), - D("SAMPLE_AMPLIFY", "Amplify", FURKMOD_CMD|SDLK_b), - D("SAMPLE_NORMALIZE", "Normalize", FURKMOD_CMD|SDLK_n), - D("SAMPLE_FADE_IN", "Fade in", FURKMOD_CMD|SDLK_i), - D("SAMPLE_FADE_OUT", "Fade out", FURKMOD_CMD|SDLK_o), - D("SAMPLE_SILENCE", "Apply silence", FURKMOD_SHIFT|SDLK_DELETE), - D("SAMPLE_INSERT", "Insert silence", SDLK_INSERT), - D("SAMPLE_DELETE", "Delete", SDLK_DELETE), - D("SAMPLE_TRIM", "Trim", FURKMOD_CMD|SDLK_DELETE), - D("SAMPLE_REVERSE", "Reverse", FURKMOD_CMD|SDLK_t), - D("SAMPLE_INVERT", "Invert", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_t), - D("SAMPLE_SIGN", "Signed/unsigned exchange", FURKMOD_CMD|SDLK_u), - D("SAMPLE_FILTER", "Apply filter", FURKMOD_CMD|SDLK_f), - D("SAMPLE_CROSSFADE_LOOP", "Crossfade loop points", NOT_AN_ACTION), - D("SAMPLE_PREVIEW", "Preview sample", 0), - D("SAMPLE_STOP_PREVIEW", "Stop sample preview", 0), - D("SAMPLE_ZOOM_IN", "Zoom in", FURKMOD_CMD|SDLK_EQUALS), - D("SAMPLE_ZOOM_OUT", "Zoom out", FURKMOD_CMD|SDLK_MINUS), - D("SAMPLE_ZOOM_AUTO", "Toggle auto-zoom", FURKMOD_CMD|SDLK_0), - D("SAMPLE_MAKE_INS", "Create instrument from sample", 0), - D("SAMPLE_SET_LOOP", "Set loop to selection", FURKMOD_CMD|SDLK_l), - D("SAMPLE_CREATE_WAVE", "Create wavetable from selection", FURKMOD_CMD|SDLK_w), + D("SAMPLE_SELECT", "Sample editor mode: Select", FURKMOD_SHIFT|SDLK_i), + D("SAMPLE_DRAW", "Sample editor mode: Draw", FURKMOD_SHIFT|SDLK_d), + D("SAMPLE_CUT", "Sample editor: Cut", FURKMOD_CMD|SDLK_x), + D("SAMPLE_COPY", "Sample editor: Copy", FURKMOD_CMD|SDLK_c), + D("SAMPLE_PASTE", "Sample editor: Paste", FURKMOD_CMD|SDLK_v), + D("SAMPLE_PASTE_REPLACE", "Sample editor: Paste replace", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_v), + D("SAMPLE_PASTE_MIX", "Sample editor: Paste mix", FURKMOD_CMD|FURKMOD_ALT|SDLK_v), + D("SAMPLE_SELECT_ALL", "Sample editor: Select all", FURKMOD_CMD|SDLK_a), + D("SAMPLE_RESIZE", "Sample editor: Resize", FURKMOD_CMD|SDLK_r), + D("SAMPLE_RESAMPLE", "Sample editor: Resample", FURKMOD_CMD|SDLK_e), + D("SAMPLE_AMPLIFY", "Sample editor: Amplify", FURKMOD_CMD|SDLK_b), + D("SAMPLE_NORMALIZE", "Sample editor: Normalize", FURKMOD_CMD|SDLK_n), + D("SAMPLE_FADE_IN", "Sample editor: Fade in", FURKMOD_CMD|SDLK_i), + D("SAMPLE_FADE_OUT", "Sample editor: Fade out", FURKMOD_CMD|SDLK_o), + D("SAMPLE_SILENCE", "Sample editor: Apply silence", FURKMOD_SHIFT|SDLK_DELETE), + D("SAMPLE_INSERT", "Sample editor: Insert silence", SDLK_INSERT), + D("SAMPLE_DELETE", "Sample editor: Delete", SDLK_DELETE), + D("SAMPLE_TRIM", "Sample editor: Trim", FURKMOD_CMD|SDLK_DELETE), + D("SAMPLE_REVERSE", "Sample editor: Reverse", FURKMOD_CMD|SDLK_t), + D("SAMPLE_INVERT", "Sample editor: Invert", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_t), + D("SAMPLE_SIGN", "Sample editor: Signed/unsigned exchange", FURKMOD_CMD|SDLK_u), + D("SAMPLE_FILTER", "Sample editor: Apply filter", FURKMOD_CMD|SDLK_f), + D("SAMPLE_CROSSFADE_LOOP", "Sample editor: Crossfade loop points", NOT_AN_ACTION), + D("SAMPLE_PREVIEW", "Sample editor: Preview sample", 0), + D("SAMPLE_STOP_PREVIEW", "Sample editor: Stop sample preview", 0), + D("SAMPLE_ZOOM_IN", "Sample editor: Zoom in", FURKMOD_CMD|SDLK_EQUALS), + D("SAMPLE_ZOOM_OUT", "Sample editor: Zoom out", FURKMOD_CMD|SDLK_MINUS), + D("SAMPLE_ZOOM_AUTO", "Sample editor: Toggle auto-zoom", FURKMOD_CMD|SDLK_0), + D("SAMPLE_MAKE_INS", "Sample editor: Create instrument from sample", 0), + D("SAMPLE_SET_LOOP", "Sample editor: Set loop to selection", FURKMOD_CMD|SDLK_l), + D("SAMPLE_CREATE_WAVE", "Sample editor: Create wavetable from selection", FURKMOD_CMD|SDLK_w), D("SAMPLE_MAX", "", NOT_AN_ACTION), D("ORDERS_MIN", "---Orders", NOT_AN_ACTION), D("ORDERS_UP", "Previous order", SDLK_UP), D("ORDERS_DOWN", "Next order", SDLK_DOWN), - D("ORDERS_LEFT", "Cursor left", SDLK_LEFT), - D("ORDERS_RIGHT", "Cursor right", SDLK_RIGHT), - D("ORDERS_INCREASE", "Increase value", 0), - D("ORDERS_DECREASE", "Decrease value", 0), - D("ORDERS_EDIT_MODE", "Switch edit mode", 0), - D("ORDERS_LINK", "Toggle alter entire row", FURKMOD_CMD|SDLK_l), - D("ORDERS_ADD", "Add", SDLK_INSERT), - D("ORDERS_DUPLICATE", "Duplicate", FURKMOD_CMD|SDLK_d), - D("ORDERS_DEEP_CLONE", "Deep clone", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_d), - D("ORDERS_DUPLICATE_END", "Duplicate to end of song", FURKMOD_CMD|SDLK_e), - D("ORDERS_DEEP_CLONE_END", "Deep clone to end of song", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_e), - D("ORDERS_REMOVE", "Remove", SDLK_DELETE), - D("ORDERS_MOVE_UP", "Move up", FURKMOD_SHIFT|SDLK_UP), - D("ORDERS_MOVE_DOWN", "Move down", FURKMOD_SHIFT|SDLK_DOWN), - D("ORDERS_REPLAY", "Replay", 0), + D("ORDERS_LEFT", "Order cursor left", SDLK_LEFT), + D("ORDERS_RIGHT", "Order cursor right", SDLK_RIGHT), + D("ORDERS_INCREASE", "Increase order value", 0), + D("ORDERS_DECREASE", "Decrease order value", 0), + D("ORDERS_EDIT_MODE", "Switch order edit mode", 0), + D("ORDERS_LINK", "Order: toggle alter entire row", FURKMOD_CMD|SDLK_l), + D("ORDERS_ADD", "Add order", SDLK_INSERT), + D("ORDERS_DUPLICATE", "Duplicate order", FURKMOD_CMD|SDLK_d), + D("ORDERS_DEEP_CLONE", "Deep clone order", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_d), + D("ORDERS_DUPLICATE_END", "Duplicate order to end of song", FURKMOD_CMD|SDLK_e), + D("ORDERS_DEEP_CLONE_END", "Deep clone order to end of song", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_e), + D("ORDERS_REMOVE", "Remove order", SDLK_DELETE), + D("ORDERS_MOVE_UP", "Move order up", FURKMOD_SHIFT|SDLK_UP), + D("ORDERS_MOVE_DOWN", "Move order down", FURKMOD_SHIFT|SDLK_DOWN), + D("ORDERS_REPLAY", "Replay order", 0), D("ORDERS_MAX", "", NOT_AN_ACTION), }; #undef D diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 71f3cda80..4cc7dad56 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -1745,6 +1745,11 @@ void FurnaceGUI::drawSettings() { UI_KEYBIND_CONFIG(GUI_ACTION_COLLAPSE_WINDOW); UI_KEYBIND_CONFIG(GUI_ACTION_CLOSE_WINDOW); + UI_KEYBIND_CONFIG(GUI_ACTION_COMMAND_PALETTE); + UI_KEYBIND_CONFIG(GUI_ACTION_CMDPAL_RECENT); + UI_KEYBIND_CONFIG(GUI_ACTION_CMDPAL_INSTRUMENTS); + UI_KEYBIND_CONFIG(GUI_ACTION_CMDPAL_SAMPLES); + KEYBIND_CONFIG_END; ImGui::TreePop(); }