Merge pull request #1160 from YohananDiamond/command-palette

undefined

WAHAHA nice one GitHub
see? that's why I hate JavaScript. couldn't you throw exception on out of bounds/undefined result, like EVERY normal language?
This commit is contained in:
tildearrow 2024-02-07 02:53:33 -05:00 committed by GitHub
commit a6aa4b66d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 465 additions and 98 deletions

View file

@ -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

253
src/gui/commandPalette.cpp Normal file
View file

@ -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 <fmt/printf.h>
#include <algorithm>
#include <ctype.h>
#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; i<GUI_ACTION_MAX; i++) {
if (guiActions[i].defaultBind==-1) continue;
if (matchFuzzy(guiActions[i].friendlyName,paletteQuery.c_str())) {
paletteSearchResults.push_back(i);
}
}
break;
case CMDPAL_TYPE_RECENT:
for (int i=0; i<(int)recentFile.size(); i++) {
if (matchFuzzy(recentFile[i].c_str(),paletteQuery.c_str())) {
paletteSearchResults.push_back(i);
}
}
break;
case CMDPAL_TYPE_INSTRUMENTS:
case CMDPAL_TYPE_INSTRUMENT_CHANGE:
if (matchFuzzy("- None -",paletteQuery.c_str())) {
paletteSearchResults.push_back(0);
}
for (int i=0; i<e->song.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; i<e->song.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();
}
}

31
src/gui/commandPalette.h Normal file
View file

@ -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,
};

View file

@ -18,6 +18,7 @@
*/
#include "gui.h"
#include "commandPalette.h"
#include "../ta-log.h"
#include <fmt/printf.h>
#include <imgui.h>
@ -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;

View file

@ -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),

View file

@ -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<DivSystem> sysSearchResults;
std::vector<FurnaceGUISysDef> newSongSearchResults;
std::vector<int> paletteSearchResults;
FixedQueue<String,32> recentFile;
std::vector<DivInstrumentType> makeInsTypeList;
std::vector<FurnaceGUIWaveSizeEntry> 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);

View file

@ -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

View file

@ -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();
}