GUI_ACTION_PAT_ABSORB_INSTRUMENT search through prior orders (also set instrument to none if no instrument found

This commit is contained in:
Adam Lederer 2024-08-22 02:43:30 -07:00 committed by tildearrow
parent c5310d1855
commit d0f3e0fa58
3 changed files with 48 additions and 24 deletions

View file

@ -681,30 +681,7 @@ void FurnaceGUI::doAction(int what) {
latchNibble=false; latchNibble=false;
break; break;
case GUI_ACTION_PAT_ABSORB_INSTRUMENT: { case GUI_ACTION_PAT_ABSORB_INSTRUMENT: {
DivPattern* pat=e->curPat[cursor.xCoarse].getPattern(e->curOrders->ord[cursor.xCoarse][curOrder],false); doAbsorbInstrument();
if (!pat) break;
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];
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; break;
} }

View file

@ -1823,6 +1823,52 @@ void FurnaceGUI::doExpandSong(int multiplier) {
if (e->isPlaying()) e->play(); if (e->isPlaying()) e->play();
} }
void FurnaceGUI::doAbsorbInstrument() {
bool foundIns=false;
bool foundOctave=false;
auto foundAll = [&]() { return foundIns && foundOctave; };
// search this order and all prior until we find all the data we need
int orderIdx=curOrder;
for (; orderIdx>=0 && !foundAll(); orderIdx--) {
DivPattern* pat=e->curPat[cursor.xCoarse].getPattern(e->curOrders->ord[cursor.xCoarse][orderIdx],false);
if (!pat) continue;
// start on current row when searching current order, but start from end when searching
// prior orders.
int searchStartRow=orderIdx==curOrder ? cursor.y : e->curSubSong->patLen-1;
for (int i=searchStartRow; i>=0 && !foundAll(); i--) {
// absorb most recent instrument
if (!foundIns && pat->data[i][2] >= 0) {
foundIns=true;
curIns=pat->data[i][2];
}
// 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) {
foundOctave=true;
// 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);
}
}
}
// if no instrument has been set at this point, the only way to match it is to use "none"
if (!foundIns) curIns=-1;
logD("doAbsorbInstrument -- searched %d orders", curOrder-orderIdx);
}
void FurnaceGUI::doDrag() { void FurnaceGUI::doDrag() {
int len=dragEnd.xCoarse-dragStart.xCoarse+1; int len=dragEnd.xCoarse-dragStart.xCoarse+1;

View file

@ -2922,6 +2922,7 @@ class FurnaceGUI {
void doExpand(int multiplier, const SelectionPoint& sStart, const SelectionPoint& sEnd); void doExpand(int multiplier, const SelectionPoint& sStart, const SelectionPoint& sEnd);
void doCollapseSong(int divider); void doCollapseSong(int divider);
void doExpandSong(int multiplier); void doExpandSong(int multiplier);
void doAbsorbInstrument();
void doUndo(); void doUndo();
void doRedo(); void doRedo();
void doFind(); void doFind();