diff --git a/src/gui/commandPalette.cpp b/src/gui/commandPalette.cpp index 868b5f1af..c44fd176d 100644 --- a/src/gui/commandPalette.cpp +++ b/src/gui/commandPalette.cpp @@ -192,7 +192,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; @@ -2492,7 +2492,7 @@ class FurnaceGUI { int waveDragMin, waveDragMax; bool waveDragActive; - int bindSetTarget, bindSetPrevValue; + int bindSetTarget, bindSetTargetIdx, bindSetPrevValue; bool bindSetActive, bindSetPending; float nextScroll, nextAddScroll, orderScroll, orderScrollSlideOrigin; @@ -2895,8 +2895,10 @@ class FurnaceGUI { void drawXYOsc(); void drawUserPresets(); + void assignActionMap(std::map& actionMap, int first, int last); + void drawKeybindSettingsTableRow(FurnaceGUIActions actionIdx); 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 ef6d71ba8..32978b5e6 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -539,7 +539,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 f56e178ca..e4c19bb49 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -308,24 +308,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(); \ @@ -341,7 +329,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(); \ @@ -533,12 +521,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 { @@ -2196,382 +2190,385 @@ void FurnaceGUI::drawSettings() { if (ImGui::Button(_("Reset defaults"))) { showWarning(_("Are you sure you want to reset the keyboard settings?"),GUI_WARN_RESET_KEYBINDS); } - if (ImGui::TreeNode(_("Global hotkeys"))) { - KEYBIND_CONFIG_BEGIN("keysGlobal"); + if (ImGui::BeginChild("##HotkeysList",ImVec2(0,0),false,ImGuiWindowFlags_HorizontalScrollbar)) { + if (ImGui::TreeNode(_("Global hotkeys"))) { + KEYBIND_CONFIG_BEGIN("keysGlobal"); - UI_KEYBIND_CONFIG(GUI_ACTION_NEW); - UI_KEYBIND_CONFIG(GUI_ACTION_CLEAR); - UI_KEYBIND_CONFIG(GUI_ACTION_OPEN); - UI_KEYBIND_CONFIG(GUI_ACTION_OPEN_BACKUP); - UI_KEYBIND_CONFIG(GUI_ACTION_SAVE); - UI_KEYBIND_CONFIG(GUI_ACTION_SAVE_AS); - UI_KEYBIND_CONFIG(GUI_ACTION_EXPORT); - UI_KEYBIND_CONFIG(GUI_ACTION_UNDO); - UI_KEYBIND_CONFIG(GUI_ACTION_REDO); - UI_KEYBIND_CONFIG(GUI_ACTION_PLAY_TOGGLE); - UI_KEYBIND_CONFIG(GUI_ACTION_PLAY); - UI_KEYBIND_CONFIG(GUI_ACTION_STOP); - UI_KEYBIND_CONFIG(GUI_ACTION_PLAY_START); - UI_KEYBIND_CONFIG(GUI_ACTION_PLAY_REPEAT); - UI_KEYBIND_CONFIG(GUI_ACTION_PLAY_CURSOR); - UI_KEYBIND_CONFIG(GUI_ACTION_STEP_ONE); - UI_KEYBIND_CONFIG(GUI_ACTION_OCTAVE_UP); - UI_KEYBIND_CONFIG(GUI_ACTION_OCTAVE_DOWN); - UI_KEYBIND_CONFIG(GUI_ACTION_INS_UP); - UI_KEYBIND_CONFIG(GUI_ACTION_INS_DOWN); - UI_KEYBIND_CONFIG(GUI_ACTION_STEP_UP); - UI_KEYBIND_CONFIG(GUI_ACTION_STEP_DOWN); - UI_KEYBIND_CONFIG(GUI_ACTION_TOGGLE_EDIT); - UI_KEYBIND_CONFIG(GUI_ACTION_METRONOME); - UI_KEYBIND_CONFIG(GUI_ACTION_REPEAT_PATTERN); - UI_KEYBIND_CONFIG(GUI_ACTION_FOLLOW_ORDERS); - UI_KEYBIND_CONFIG(GUI_ACTION_FOLLOW_PATTERN); - UI_KEYBIND_CONFIG(GUI_ACTION_FULLSCREEN); - UI_KEYBIND_CONFIG(GUI_ACTION_TX81Z_REQUEST); - UI_KEYBIND_CONFIG(GUI_ACTION_PANIC); + drawKeybindSettingsTableRow(GUI_ACTION_NEW); + drawKeybindSettingsTableRow(GUI_ACTION_CLEAR); + drawKeybindSettingsTableRow(GUI_ACTION_OPEN); + drawKeybindSettingsTableRow(GUI_ACTION_OPEN_BACKUP); + drawKeybindSettingsTableRow(GUI_ACTION_SAVE); + drawKeybindSettingsTableRow(GUI_ACTION_SAVE_AS); + drawKeybindSettingsTableRow(GUI_ACTION_EXPORT); + drawKeybindSettingsTableRow(GUI_ACTION_UNDO); + drawKeybindSettingsTableRow(GUI_ACTION_REDO); + drawKeybindSettingsTableRow(GUI_ACTION_PLAY_TOGGLE); + drawKeybindSettingsTableRow(GUI_ACTION_PLAY); + drawKeybindSettingsTableRow(GUI_ACTION_STOP); + drawKeybindSettingsTableRow(GUI_ACTION_PLAY_START); + drawKeybindSettingsTableRow(GUI_ACTION_PLAY_REPEAT); + drawKeybindSettingsTableRow(GUI_ACTION_PLAY_CURSOR); + drawKeybindSettingsTableRow(GUI_ACTION_STEP_ONE); + drawKeybindSettingsTableRow(GUI_ACTION_OCTAVE_UP); + drawKeybindSettingsTableRow(GUI_ACTION_OCTAVE_DOWN); + drawKeybindSettingsTableRow(GUI_ACTION_INS_UP); + drawKeybindSettingsTableRow(GUI_ACTION_INS_DOWN); + drawKeybindSettingsTableRow(GUI_ACTION_STEP_UP); + drawKeybindSettingsTableRow(GUI_ACTION_STEP_DOWN); + drawKeybindSettingsTableRow(GUI_ACTION_TOGGLE_EDIT); + drawKeybindSettingsTableRow(GUI_ACTION_METRONOME); + drawKeybindSettingsTableRow(GUI_ACTION_REPEAT_PATTERN); + drawKeybindSettingsTableRow(GUI_ACTION_FOLLOW_ORDERS); + drawKeybindSettingsTableRow(GUI_ACTION_FOLLOW_PATTERN); + drawKeybindSettingsTableRow(GUI_ACTION_FULLSCREEN); + drawKeybindSettingsTableRow(GUI_ACTION_TX81Z_REQUEST); + drawKeybindSettingsTableRow(GUI_ACTION_PANIC); - KEYBIND_CONFIG_END; - ImGui::TreePop(); - } - if (ImGui::TreeNode(_("Window activation"))) { - KEYBIND_CONFIG_BEGIN("keysWindow"); - - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_FIND); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_SETTINGS); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_SONG_INFO); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_SUBSONGS); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_SPEED); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_INS_LIST); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_WAVE_LIST); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_SAMPLE_LIST); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_ORDERS); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_PATTERN); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_MIXER); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_GROOVES); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_CHANNELS); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_PAT_MANAGER); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_SYS_MANAGER); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_COMPAT_FLAGS); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_NOTES); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_INS_EDIT); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_WAVE_EDIT); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_SAMPLE_EDIT); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_EDIT_CONTROLS); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_PIANO); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_OSCILLOSCOPE); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_CHAN_OSC); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_XY_OSC); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_VOL_METER); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_CLOCK); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_REGISTER_VIEW); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_LOG); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_STATS); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_MEMORY); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_EFFECT_LIST); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_DEBUG); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_CS_PLAYER); - UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_ABOUT); - 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(); - } - if (ImGui::TreeNode(_("Note input"))) { - std::vector 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; i0) ImGui::SameLine(); + bool isPending=bindSetPending && bindSetTarget==actionIdx && bindSetTargetIdx==(int)i; + if (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; + } + } + } +} + + void FurnaceGUI::parseKeybinds() { - actionMapGlobal.clear(); - actionMapPat.clear(); - actionMapInsList.clear(); - actionMapWaveList.clear(); - actionMapSampleList.clear(); - actionMapSample.clear(); - actionMapOrders.clear(); - - for (int i=GUI_ACTION_GLOBAL_MIN+1; i"); + } + } else { + return ret; + } +} diff --git a/src/gui/util.h b/src/gui/util.h index f21fc0312..c8437543e 100644 --- a/src/gui/util.h +++ b/src/gui/util.h @@ -63,4 +63,6 @@ double cubRectTri(double x); double cubAbsTri(double x); double cubQuartTri(double x); double cubSquiTri(double x); -double absCubSquiTri(double x); \ No newline at end of file +double absCubSquiTri(double x); + +String getMultiKeysName(const int* keys, int keyCount, bool emptyNone=false);