diff --git a/src/gui/doAction.cpp b/src/gui/doAction.cpp index bf5b89519..00bfe95ea 100644 --- a/src/gui/doAction.cpp +++ b/src/gui/doAction.cpp @@ -123,16 +123,16 @@ void FurnaceGUI::doAction(int what) { pendingStepUpdate=1; break; case GUI_ACTION_OCTAVE_UP: - if (++curOctave>7) { - curOctave=7; + if (++curOctave>GUI_EDIT_OCTAVE_MAX) { + curOctave=GUI_EDIT_OCTAVE_MAX; } else { e->autoNoteOffAll(); failedNoteOn=false; } break; case GUI_ACTION_OCTAVE_DOWN: - if (--curOctave<-5) { - curOctave=-5; + if (--curOctaveautoNoteOffAll(); failedNoteOn=false; @@ -679,10 +679,26 @@ void FurnaceGUI::doAction(int what) { case GUI_ACTION_PAT_ABSORB_INSTRUMENT: { DivPattern* pat=e->curPat[cursor.xCoarse].getPattern(e->curOrders->ord[cursor.xCoarse][curOrder],false); if (!pat) break; - for (int i=cursor.y; i>=0; i--) { - if (pat->data[i][2] >= 0) { + bool foundIns=false; + bool foundOctave=false; + for (int i=cursor.y; i>=0 && !(foundIns && foundOctave); i--) { + // absorb most recent instrument + if (!foundIns && pat->data[i][2] >= 0) { curIns=pat->data[i][2]; - break; + foundIns=true; + } + // absorb most recent octave (i.e. set curOctave such that the "main row" (QWERTY) of notes + // will result in an octave number equal to the previous note). + if (!foundOctave && pat->data[i][0] != 0) { + // decode octave data (was signed cast to unsigned char) + int octave=pat->data[i][1]; + if (octave>128) octave-=256; + // @NOTE the special handling when note==12, which is really an octave above what's + // stored in the octave data. without this handling, if you press Q, then + // "ABSORB_INSTRUMENT", then Q again, you'd get a different octave! + if (pat->data[i][0]==12) octave++; + curOctave=CLAMP(octave-1, GUI_EDIT_OCTAVE_MIN, GUI_EDIT_OCTAVE_MAX); + foundOctave=true; } } break; diff --git a/src/gui/editControls.cpp b/src/gui/editControls.cpp index c492a8e17..34beff48b 100644 --- a/src/gui/editControls.cpp +++ b/src/gui/editControls.cpp @@ -647,8 +647,8 @@ void FurnaceGUI::drawEditControls() { ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); if (ImGui::InputInt("##Octave",&curOctave,1,1)) { - if (curOctave>7) curOctave=7; - if (curOctave<-5) curOctave=-5; + if (curOctave>GUI_EDIT_OCTAVE_MAX) curOctave=GUI_EDIT_OCTAVE_MAX; + if (curOctaveautoNoteOffAll(); failedNoteOn=false; @@ -808,8 +808,8 @@ void FurnaceGUI::drawEditControls() { ImGui::SameLine(); ImGui::SetNextItemWidth(96.0f*dpiScale); if (ImGui::InputInt("##Octave",&curOctave,1,1)) { - if (curOctave>7) curOctave=7; - if (curOctave<-5) curOctave=-5; + if (curOctave>GUI_EDIT_OCTAVE_MAX) curOctave=GUI_EDIT_OCTAVE_MAX; + if (curOctaveautoNoteOffAll(); failedNoteOn=false; @@ -926,8 +926,8 @@ void FurnaceGUI::drawEditControls() { float avail=ImGui::GetContentRegionAvail().x; ImGui::SetNextItemWidth(avail); if (ImGui::InputInt("##Octave",&curOctave,0,0)) { - if (curOctave>7) curOctave=7; - if (curOctave<-5) curOctave=-5; + if (curOctave>GUI_EDIT_OCTAVE_MAX) curOctave=GUI_EDIT_OCTAVE_MAX; + if (curOctaveautoNoteOffAll(); failedNoteOn=false; @@ -1093,8 +1093,8 @@ void FurnaceGUI::drawEditControls() { float avail=ImGui::GetContentRegionAvail().x; ImGui::SetNextItemWidth(avail); if (ImGui::InputInt("##Octave",&curOctave,1,1)) { - if (curOctave>7) curOctave=7; - if (curOctave<-5) curOctave=-5; + if (curOctave>GUI_EDIT_OCTAVE_MAX) curOctave=GUI_EDIT_OCTAVE_MAX; + if (curOctaveautoNoteOffAll(); failedNoteOn=false; diff --git a/src/gui/gui.h b/src/gui/gui.h index adc066229..9ff06e013 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -137,6 +137,9 @@ enum FurnaceGUIRenderBackend { #define ngettext momo_ngettext #endif +#define GUI_EDIT_OCTAVE_MIN -5 +#define GUI_EDIT_OCTAVE_MAX 7 + // TODO: // - add colors for FM envelope and waveform // - maybe add "alternate" color for FM modulators/carriers (a bit difficult) diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index 13e8a9478..8fd662824 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -687,7 +687,7 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={ D("PAT_LATCH", _N("Set note input latch"), 0), D("PAT_SCROLL_MODE", _N("Change mobile scroll mode"), 0), D("PAT_CLEAR_LATCH", _N("Clear note input latch"), 0), - D("PAT_ABSORB_INSTRUMENT", _N("Set current instrument to channel's current instrument column"), 0), + D("PAT_ABSORB_INSTRUMENT", _N("Absorb instrument/octave from status at cursor"), 0), D("PAT_MAX", "", NOT_AN_ACTION), D("INS_LIST_MIN", _N("---Instrument list"), NOT_AN_ACTION),