From a30c628a2975f7fd82b5a6904e6ae54791dd169c Mon Sep 17 00:00:00 2001 From: Adam Lederer Date: Mon, 26 Aug 2024 22:21:35 -0700 Subject: [PATCH] bind multiple keys to same action --- src/gui/commandPalette.cpp | 2 +- src/gui/gui.cpp | 24 +- src/gui/gui.h | 8 +- src/gui/guiConst.cpp | 2 +- src/gui/guiConst.h | 14 +- src/gui/settings.cpp | 894 +++++++++++++++++++------------------ src/gui/util.cpp | 19 + src/gui/util.h | 3 +- 8 files changed, 514 insertions(+), 452 deletions(-) diff --git a/src/gui/commandPalette.cpp b/src/gui/commandPalette.cpp index e4cca5bf9..e97b6a650 100644 --- a/src/gui/commandPalette.cpp +++ b/src/gui/commandPalette.cpp @@ -73,7 +73,7 @@ void FurnaceGUI::drawPalette() { switch (curPaletteType) { case CMDPAL_TYPE_MAIN: for (int i=0; i actionKeys[GUI_ACTION_MAX]; std::map actionMapGlobal; std::map actionMapPat; @@ -2457,7 +2457,7 @@ class FurnaceGUI { int waveDragMin, waveDragMax; bool waveDragActive; - int bindSetTarget, bindSetPrevValue; + int bindSetTarget, bindSetTargetIdx, bindSetPrevValue; bool bindSetActive, bindSetPending; float nextScroll, nextAddScroll, orderScroll, orderScrollSlideOrigin; @@ -2856,7 +2856,7 @@ class FurnaceGUI { void drawUserPresets(); void parseKeybinds(); - void promptKey(int which); + void promptKey(int which, int bindIdx); void doAction(int what); bool importColors(String path); diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index fbfdadc0c..78f517c11 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -536,7 +536,7 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={ D("EXPORT", _N("Export"), 0), D("UNDO", _N("Undo"), FURKMOD_CMD|SDLK_z), #ifdef __APPLE__ - D("REDO", _N("Redo"), FURKMOD_CMD|FURKMOD_SHIFT|SDLK_z), + D("REDO", _N("Redo"), FURKMOD_CMD|FURKMOD_SHIFT|SDLK_z, FURKMOD_CMD|SDLK_y), #else D("REDO", _N("Redo"), FURKMOD_CMD|SDLK_y), #endif diff --git a/src/gui/guiConst.h b/src/gui/guiConst.h index 4456ebd3c..d26e2a0f9 100644 --- a/src/gui/guiConst.h +++ b/src/gui/guiConst.h @@ -22,9 +22,17 @@ struct FurnaceGUIActionDef { const char* name; const char* friendlyName; - int defaultBind; - FurnaceGUIActionDef(const char* n, const char* fn, int db): - name(n), friendlyName(fn), defaultBind(db) {} + std::vector defaultBind; + bool isNotABind() const { return defaultBind.size()==1 && defaultBind[0]==-1; } + FurnaceGUIActionDef(const char* n, const char* fn, int db) : + name(n), friendlyName(fn) { + if (db!=0) defaultBind.push_back(db); + } + FurnaceGUIActionDef(const char* n, const char* fn, int db, int db2): + name(n), friendlyName(fn) { + if (db!=0) defaultBind.push_back(db); + if (db2!=0) defaultBind.push_back(db); + } }; struct FurnaceGUIColorDef { diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index e2efb91e7..ba3e0ae22 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -303,24 +303,12 @@ const char* specificControls[18]={ ImGui::PopID(); #define KEYBIND_CONFIG_BEGIN(id) \ - if (ImGui::BeginTable(id,2)) { + if (ImGui::BeginTable(id,2,ImGuiTableFlags_SizingFixedFit|ImGuiTableFlags_NoHostExtendX|ImGuiTableFlags_NoClip)) { #define KEYBIND_CONFIG_END \ ImGui::EndTable(); \ } -#define UI_KEYBIND_CONFIG(what) \ - ImGui::TableNextRow(); \ - ImGui::TableNextColumn(); \ - ImGui::AlignTextToFramePadding();\ - ImGui::TextUnformatted(guiActions[what].friendlyName); \ - ImGui::TableNextColumn(); \ - if (ImGui::Button(fmt::sprintf("%s##KC_" #what,(bindSetPending && bindSetTarget==what)?_N("Press key..."):getKeyName(actionKeys[what])).c_str())) { \ - promptKey(what); \ - settingsChanged=true; \ - } \ - if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) actionKeys[what]=0; - #define CONFIG_SUBSECTION(what) \ if (_subInit) { \ ImGui::Separator(); \ @@ -336,7 +324,7 @@ const char* specificControls[18]={ bool _subInit=false; \ ImVec2 settingsViewSize=ImGui::GetContentRegionAvail(); \ settingsViewSize.y-=ImGui::GetFrameHeight()+ImGui::GetStyle().WindowPadding.y; \ - if (ImGui::BeginChild("SettingsView",settingsViewSize)) + if (ImGui::BeginChild("SettingsView",settingsViewSize,false)) #define END_SECTION } \ ImGui::EndChild(); \ @@ -528,12 +516,18 @@ void FurnaceGUI::purgeBackups(int year, int month, int day) { refreshBackups=true; } -void FurnaceGUI::promptKey(int which) { +void FurnaceGUI::promptKey(int which, int bindIdx) { bindSetTarget=which; + bindSetTargetIdx=bindIdx; bindSetActive=true; bindSetPending=true; - bindSetPrevValue=actionKeys[which]; - actionKeys[which]=0; + if (bindIdx>=(int)actionKeys[which].size()) { + bindSetPrevValue=0; + actionKeys[which].push_back(0); + } else { + bindSetPrevValue=actionKeys[which][bindIdx]; + actionKeys[which][bindIdx]=0; + } } struct MappedInput { @@ -2172,6 +2166,45 @@ void FurnaceGUI::drawSettings() { END_SECTION; } CONFIG_SECTION(_("Keyboard")) { + auto uiKeybindConfig=[&](FurnaceGUIActions actionIdx) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::AlignTextToFramePadding(); + ImGui::TextUnformatted(guiActions[actionIdx].friendlyName); + ImGui::TableNextColumn(); + ImGui::PushID(actionIdx); + for (size_t i=0; i0) ImGui::SameLine(); + bool isPending=bindSetPending && bindSetTarget==actionIdx && bindSetTargetIdx==(int)i; + if (i sorted; - if (ImGui::BeginTable("keysNoteInput",4)) { - for (std::map::value_type& i: noteKeys) { - std::vector::iterator j; - for (j=sorted.begin(); j!=sorted.end(); j++) { - if (j->val>i.second) { - break; - } - } - sorted.insert(j,MappedInput(i.first,i.second)); - } - - static char id[4096]; - - ImGui::TableNextRow(ImGuiTableRowFlags_Headers); - ImGui::TableNextColumn(); - ImGui::Text(_("Key")); - ImGui::TableNextColumn(); - ImGui::Text(_("Type")); - ImGui::TableNextColumn(); - ImGui::Text(_("Value")); - ImGui::TableNextColumn(); - ImGui::Text(_("Remove")); - - for (MappedInput& i: sorted) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("%s",SDL_GetScancodeName((SDL_Scancode)i.scan)); - ImGui::TableNextColumn(); - if (i.val==102) { - snprintf(id,4095,_("Macro release##SNType_%d"),i.scan); - if (ImGui::Button(id)) { - noteKeys[i.scan]=0; - } - } else if (i.val==101) { - snprintf(id,4095,_("Note release##SNType_%d"),i.scan); - if (ImGui::Button(id)) { - noteKeys[i.scan]=102; - } - } else if (i.val==100) { - snprintf(id,4095,_("Note off##SNType_%d"),i.scan); - if (ImGui::Button(id)) { - noteKeys[i.scan]=101; - } - } else { - snprintf(id,4095,_("Note##SNType_%d"),i.scan); - if (ImGui::Button(id)) { - noteKeys[i.scan]=100; - } - } - ImGui::TableNextColumn(); - if (i.val<100) { - snprintf(id,4095,"##SNValue_%d",i.scan); - if (ImGui::InputInt(id,&i.val,1,12)) { - if (i.val<0) i.val=0; - if (i.val>96) i.val=96; - noteKeys[i.scan]=i.val; - settingsChanged=true; - } - } - ImGui::TableNextColumn(); - snprintf(id,4095,ICON_FA_TIMES "##SNRemove_%d",i.scan); - if (ImGui::Button(id)) { - noteKeys.erase(i.scan); - settingsChanged=true; - } - } - ImGui::EndTable(); - - if (ImGui::BeginCombo("##SNAddNew",_("Add..."))) { - for (int i=0; i sorted; + if (ImGui::BeginTable("keysNoteInput",4)) { + for (std::map::value_type& i: noteKeys) { + std::vector::iterator j; + for (j=sorted.begin(); j!=sorted.end(); j++) { + if (j->val>i.second) { + break; + } + } + sorted.insert(j,MappedInput(i.first,i.second)); + } + + static char id[4096]; + + ImGui::TableNextRow(ImGuiTableRowFlags_Headers); + ImGui::TableNextColumn(); + ImGui::Text(_("Key")); + ImGui::TableNextColumn(); + ImGui::Text(_("Type")); + ImGui::TableNextColumn(); + ImGui::Text(_("Value")); + ImGui::TableNextColumn(); + ImGui::Text(_("Remove")); + + for (MappedInput& i: sorted) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("%s",SDL_GetScancodeName((SDL_Scancode)i.scan)); + ImGui::TableNextColumn(); + if (i.val==102) { + snprintf(id,4095,_("Macro release##SNType_%d"),i.scan); + if (ImGui::Button(id)) { + noteKeys[i.scan]=0; + } + } else if (i.val==101) { + snprintf(id,4095,_("Note release##SNType_%d"),i.scan); + if (ImGui::Button(id)) { + noteKeys[i.scan]=102; + } + } else if (i.val==100) { + snprintf(id,4095,_("Note off##SNType_%d"),i.scan); + if (ImGui::Button(id)) { + noteKeys[i.scan]=101; + } + } else { + snprintf(id,4095,_("Note##SNType_%d"),i.scan); + if (ImGui::Button(id)) { + noteKeys[i.scan]=100; + } + } + ImGui::TableNextColumn(); + if (i.val<100) { + snprintf(id,4095,"##SNValue_%d",i.scan); + if (ImGui::InputInt(id,&i.val,1,12)) { + if (i.val<0) i.val=0; + if (i.val>96) i.val=96; + noteKeys[i.scan]=i.val; + settingsChanged=true; + } + } + ImGui::TableNextColumn(); + snprintf(id,4095,ICON_FA_TIMES "##SNRemove_%d",i.scan); + if (ImGui::Button(id)) { + noteKeys.erase(i.scan); + settingsChanged=true; + } + } + ImGui::EndTable(); + + if (ImGui::BeginCombo("##SNAddNew",_("Add..."))) { + for (int i=0; i& actionMap, int first, int last) { + actionMap.clear(); + for (int i=first; i<=last; i++) { + for (int key : actionKeys[i]) { + if (key&FURK_MASK) { + actionMap[key]=i; + } + } } - } + }; - for (int i=GUI_ACTION_INS_LIST_MIN+1; i"); + } + } else { + return ret; + } +} \ No newline at end of file diff --git a/src/gui/util.h b/src/gui/util.h index d82466a25..c7e96faa9 100644 --- a/src/gui/util.h +++ b/src/gui/util.h @@ -30,4 +30,5 @@ #endif String getHomeDir(); -String getKeyName(int key, bool emptyNone=false); \ No newline at end of file +String getKeyName(int key, bool emptyNone=false); +String getMultiKeysName(const int* keys, int keyCount, bool emptyNone=false); \ No newline at end of file