diff --git a/TODO.md b/TODO.md index 7204a6d12..f9230306d 100644 --- a/TODO.md +++ b/TODO.md @@ -26,14 +26,13 @@ - add nightly.link - scroll instrument/wave/sample list when selecting item - unified data view -- separate "transpose note" and "transpose value" - see next point - volume commands should work on Game Boy - macro editor menu - refactor sysDef.cpp - add another FM editor layout - try to find out why does VSlider not accept keyboard input - finish lock layout -- note input latch! and separate edit masks +- note input latch! - if macros have release, note off should release them - add "don't scroll on cursor movement" option - add ability to select entire row when clicking on row number diff --git a/src/gui/doAction.cpp b/src/gui/doAction.cpp index fc0dbef90..c12df2fe4 100644 --- a/src/gui/doAction.cpp +++ b/src/gui/doAction.cpp @@ -301,16 +301,28 @@ void FurnaceGUI::doAction(int what) { break; case GUI_ACTION_PAT_NOTE_UP: - doTranspose(1); + doTranspose(1,opMaskTransposeNote); break; case GUI_ACTION_PAT_NOTE_DOWN: - doTranspose(-1); + doTranspose(-1,opMaskTransposeNote); break; case GUI_ACTION_PAT_OCTAVE_UP: - doTranspose(12); + doTranspose(12,opMaskTransposeNote); break; case GUI_ACTION_PAT_OCTAVE_DOWN: - doTranspose(-12); + doTranspose(-12,opMaskTransposeNote); + break; + case GUI_ACTION_PAT_VALUE_UP: + doTranspose(1,opMaskTransposeValue); + break; + case GUI_ACTION_PAT_VALUE_DOWN: + doTranspose(-1,opMaskTransposeValue); + break; + case GUI_ACTION_PAT_VALUE_UP_COARSE: + doTranspose(16,opMaskTransposeValue); + break; + case GUI_ACTION_PAT_VALUE_DOWN_COARSE: + doTranspose(-16,opMaskTransposeValue); break; case GUI_ACTION_PAT_SELECT_ALL: doSelectAll(); diff --git a/src/gui/editing.cpp b/src/gui/editing.cpp index ce1cb21c2..106ec61b1 100644 --- a/src/gui/editing.cpp +++ b/src/gui/editing.cpp @@ -201,7 +201,7 @@ void FurnaceGUI::doDelete() { if (!e->song.chanShow[iCoarse]) continue; DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true); for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarsedata[j][iFine]=0; @@ -238,7 +238,7 @@ void FurnaceGUI::doPullDelete() { if (!e->song.chanShow[iCoarse]) continue; DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true); for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarsesong.patLen; j++) { if (jsong.patLen-1) { if (iFine==0) { @@ -270,7 +270,7 @@ void FurnaceGUI::doInsert() { if (!e->song.chanShow[iCoarse]) continue; DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true); for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarsesong.patLen-1; j>=selStart.y; j--) { if (j==selStart.y) { if (iFine==0) { @@ -291,7 +291,7 @@ void FurnaceGUI::doInsert() { makeUndo(GUI_UNDO_PATTERN_PUSH); } -void FurnaceGUI::doTranspose(int amount) { +void FurnaceGUI::doTranspose(int amount, OperationMask& mask) { finishSelection(); prepareUndo(GUI_UNDO_PATTERN_DELETE); curNibble=false; @@ -302,7 +302,7 @@ void FurnaceGUI::doTranspose(int amount) { if (!e->song.chanShow[iCoarse]) continue; DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true); for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarsedata[j][0]; @@ -469,7 +469,7 @@ void FurnaceGUI::doPaste(PasteMode mode) { note[2]=line[charPos++]; note[3]=0; - if (iFine==0 && !opMask.note) { + if (iFine==0 && !opMaskPaste.note) { iFine++; continue; } @@ -498,22 +498,22 @@ void FurnaceGUI::doPaste(PasteMode mode) { note[2]=0; if (iFine==1) { - if (!opMask.ins) { + if (!opMaskPaste.ins) { iFine++; continue; } } else if (iFine==2) { - if (!opMask.vol) { + if (!opMaskPaste.vol) { iFine++; continue; } } else if ((iFine&1)==0) { - if (!opMask.effectVal) { + if (!opMaskPaste.effectVal) { iFine++; continue; } } else if ((iFine&1)==1) { - if (!opMask.effect) { + if (!opMaskPaste.effect) { iFine++; continue; } @@ -589,7 +589,7 @@ void FurnaceGUI::doInterpolate() { if (!e->song.chanShow[iCoarse]) continue; DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true); for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarsesong.chanShow[iCoarse]) continue; DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true); for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarsesong.chanShow[iCoarse]) continue; DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true); for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarsesong.chanShow[iCoarse]) continue; DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true); for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarsesong.chanShow[iCoarse]) continue; DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true); for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarsesong.chanShow[iCoarse]) continue; DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true); for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarsedata[j][0]; @@ -825,7 +825,7 @@ void FurnaceGUI::doCollapse(int divider) { if (!e->song.chanShow[iCoarse]) continue; DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true); for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarsedata[j][0]; @@ -882,7 +882,7 @@ void FurnaceGUI::doExpand(int multiplier) { if (!e->song.chanShow[iCoarse]) continue; DivPattern* pat=e->song.pat[iCoarse].getPattern(e->song.orders.ord[iCoarse][curOrder],true); for (; iFine<3+e->song.pat[iCoarse].effectRows*2 && (iCoarsedata[j][0]; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 83dbdce7b..09709b50b 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1772,6 +1772,44 @@ void FurnaceGUI::processDrags(int dragX, int dragY) { fileName+=fallback; \ } +#define drawOpMask(m) \ + ImGui::PushFont(patFont); \ + ImGui::PushID("om_" #m); \ + if (ImGui::BeginTable("opMaskTable",5,ImGuiTableFlags_Borders|ImGuiTableFlags_SizingFixedFit|ImGuiTableFlags_NoHostExtendX)) { \ + ImGui::TableNextRow(); \ + ImGui::TableNextColumn(); \ + ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_ACTIVE]); \ + if (ImGui::Selectable(m.note?"C-4##opMaskNote":"---##opMaskNote",m.note,ImGuiSelectableFlags_DontClosePopups)) { \ + m.note=!m.note; \ + } \ + ImGui::PopStyleColor(); \ + ImGui::TableNextColumn(); \ + ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INS]); \ + if (ImGui::Selectable(m.ins?"01##opMaskIns":"--##opMaskIns",m.ins,ImGuiSelectableFlags_DontClosePopups)) { \ + m.ins=!m.ins; \ + } \ + ImGui::PopStyleColor(); \ + ImGui::TableNextColumn(); \ + ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_VOLUME_MAX]); \ + if (ImGui::Selectable(m.vol?"7F##opMaskVol":"--##opMaskVol",m.vol,ImGuiSelectableFlags_DontClosePopups)) { \ + m.vol=!m.vol; \ + } \ + ImGui::PopStyleColor(); \ + ImGui::TableNextColumn(); \ + ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH]); \ + if (ImGui::Selectable(m.effect?"04##opMaskEffect":"--##opMaskEffect",m.effect,ImGuiSelectableFlags_DontClosePopups)) { \ + m.effect=!m.effect; \ + } \ + ImGui::TableNextColumn(); \ + if (ImGui::Selectable(m.effectVal?"72##opMaskEffectVal":"--##opMaskEffectVal",m.effectVal,ImGuiSelectableFlags_DontClosePopups)) { \ + m.effectVal=!m.effectVal; \ + } \ + ImGui::PopStyleColor(); \ + ImGui::EndTable(); \ + } \ + ImGui::PopID(); \ + ImGui::PopFont(); + void FurnaceGUI::editOptions(bool topMenu) { char id[4096]; if (ImGui::MenuItem("cut",BIND_FOR(GUI_ACTION_PAT_CUT))) doCopy(true); @@ -1790,43 +1828,61 @@ void FurnaceGUI::editOptions(bool topMenu) { } ImGui::Separator(); - ImGui::Text("operation mask"); - ImGui::SameLine(); + if (ImGui::BeginMenu("operation mask...")) { + drawOpMask(opMaskDelete); + ImGui::SameLine(); + ImGui::Text("delete"); - ImGui::PushFont(patFont); - if (ImGui::BeginTable("opMaskTable",5,ImGuiTableFlags_Borders|ImGuiTableFlags_SizingFixedFit|ImGuiTableFlags_NoHostExtendX)) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_ACTIVE]); - if (ImGui::Selectable(opMask.note?"C-4##opMaskNote":"---##opMaskNote",opMask.note,ImGuiSelectableFlags_DontClosePopups)) { - opMask.note=!opMask.note; - } - ImGui::PopStyleColor(); - ImGui::TableNextColumn(); - ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INS]); - if (ImGui::Selectable(opMask.ins?"01##opMaskIns":"--##opMaskIns",opMask.ins,ImGuiSelectableFlags_DontClosePopups)) { - opMask.ins=!opMask.ins; - } - ImGui::PopStyleColor(); - ImGui::TableNextColumn(); - ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_VOLUME_MAX]); - if (ImGui::Selectable(opMask.vol?"7F##opMaskVol":"--##opMaskVol",opMask.vol,ImGuiSelectableFlags_DontClosePopups)) { - opMask.vol=!opMask.vol; - } - ImGui::PopStyleColor(); - ImGui::TableNextColumn(); - ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH]); - if (ImGui::Selectable(opMask.effect?"04##opMaskEffect":"--##opMaskEffect",opMask.effect,ImGuiSelectableFlags_DontClosePopups)) { - opMask.effect=!opMask.effect; - } - ImGui::TableNextColumn(); - if (ImGui::Selectable(opMask.effectVal?"72##opMaskEffectVal":"--##opMaskEffectVal",opMask.effectVal,ImGuiSelectableFlags_DontClosePopups)) { - opMask.effectVal=!opMask.effectVal; - } - ImGui::PopStyleColor(); - ImGui::EndTable(); + drawOpMask(opMaskPullDelete); + ImGui::SameLine(); + ImGui::Text("pull delete"); + + drawOpMask(opMaskInsert); + ImGui::SameLine(); + ImGui::Text("insert"); + + drawOpMask(opMaskPaste); + ImGui::SameLine(); + ImGui::Text("paste"); + + drawOpMask(opMaskTransposeNote); + ImGui::SameLine(); + ImGui::Text("transpose (note)"); + + drawOpMask(opMaskTransposeValue); + ImGui::SameLine(); + ImGui::Text("transpose (value)"); + + drawOpMask(opMaskInterpolate); + ImGui::SameLine(); + ImGui::Text("interpolate"); + + drawOpMask(opMaskFade); + ImGui::SameLine(); + ImGui::Text("fade"); + + drawOpMask(opMaskInvertVal); + ImGui::SameLine(); + ImGui::Text("invert values"); + + drawOpMask(opMaskScale); + ImGui::SameLine(); + ImGui::Text("scale"); + + drawOpMask(opMaskRandomize); + ImGui::SameLine(); + ImGui::Text("randomize"); + + drawOpMask(opMaskFlip); + ImGui::SameLine(); + ImGui::Text("flip"); + + drawOpMask(opMaskCollapseExpand); + ImGui::SameLine(); + ImGui::Text("collapse/expand"); + + ImGui::EndMenu(); } - ImGui::PopFont(); ImGui::Text("input latch"); if (ImGui::MenuItem("set latch",BIND_FOR(GUI_ACTION_PAT_LATCH))) { @@ -1834,17 +1890,31 @@ void FurnaceGUI::editOptions(bool topMenu) { } ImGui::Separator(); - if (ImGui::MenuItem("note up",BIND_FOR(GUI_ACTION_PAT_NOTE_UP))) doTranspose(1); - if (ImGui::MenuItem("note down",BIND_FOR(GUI_ACTION_PAT_NOTE_DOWN))) doTranspose(-1); - if (ImGui::MenuItem("octave up",BIND_FOR(GUI_ACTION_PAT_OCTAVE_UP))) doTranspose(12); - if (ImGui::MenuItem("octave down",BIND_FOR(GUI_ACTION_PAT_OCTAVE_DOWN))) doTranspose(-12); + if (ImGui::MenuItem("note up",BIND_FOR(GUI_ACTION_PAT_NOTE_UP))) doTranspose(1,opMaskTransposeNote); + if (ImGui::MenuItem("note down",BIND_FOR(GUI_ACTION_PAT_NOTE_DOWN))) doTranspose(-1,opMaskTransposeNote); + if (ImGui::MenuItem("octave up",BIND_FOR(GUI_ACTION_PAT_OCTAVE_UP))) doTranspose(12,opMaskTransposeNote); + if (ImGui::MenuItem("octave down",BIND_FOR(GUI_ACTION_PAT_OCTAVE_DOWN))) doTranspose(-12,opMaskTransposeNote); + ImGui::Separator(); + if (ImGui::MenuItem("values up",BIND_FOR(GUI_ACTION_PAT_VALUE_UP))) doTranspose(1,opMaskTransposeValue); + if (ImGui::MenuItem("values down",BIND_FOR(GUI_ACTION_PAT_VALUE_DOWN))) doTranspose(-1,opMaskTransposeValue); + if (ImGui::MenuItem("values up (+16)",BIND_FOR(GUI_ACTION_PAT_VALUE_UP_COARSE))) doTranspose(16,opMaskTransposeValue); + if (ImGui::MenuItem("values down (-16)",BIND_FOR(GUI_ACTION_PAT_VALUE_DOWN_COARSE))) doTranspose(-16,opMaskTransposeValue); + ImGui::Separator(); + ImGui::Text("transpose"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(120.0f*dpiScale); if (ImGui::InputInt("##TransposeAmount",&transposeAmount,1,1)) { if (transposeAmount<-96) transposeAmount=-96; if (transposeAmount>96) transposeAmount=96; } ImGui::SameLine(); - if (ImGui::Button("Transpose")) { - doTranspose(transposeAmount); + if (ImGui::Button("Notes")) { + doTranspose(transposeAmount,opMaskTransposeNote); + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(); + if (ImGui::Button("Values")) { + doTranspose(transposeAmount,opMaskTransposeNote); ImGui::CloseCurrentPopup(); } @@ -3699,6 +3769,18 @@ FurnaceGUI::FurnaceGUI(): peak[0]=0; peak[1]=0; + opMaskTransposeNote.note=true; + opMaskTransposeNote.ins=false; + opMaskTransposeNote.vol=false; + opMaskTransposeNote.effect=false; + opMaskTransposeNote.effectVal=false; + + opMaskTransposeValue.note=false; + opMaskTransposeValue.ins=true; + opMaskTransposeValue.vol=true; + opMaskTransposeValue.effect=true; + opMaskTransposeValue.effectVal=true; + memset(actionKeys,0,GUI_ACTION_MAX*sizeof(int)); memset(patChanX,0,sizeof(float)*(DIV_MAX_CHANS+1)); diff --git a/src/gui/gui.h b/src/gui/gui.h index eaf52dc72..328ad6a71 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -335,6 +335,10 @@ enum FurnaceGUIActions { GUI_ACTION_PAT_NOTE_DOWN, GUI_ACTION_PAT_OCTAVE_UP, GUI_ACTION_PAT_OCTAVE_DOWN, + GUI_ACTION_PAT_VALUE_UP, + GUI_ACTION_PAT_VALUE_DOWN, + GUI_ACTION_PAT_VALUE_UP_COARSE, + GUI_ACTION_PAT_VALUE_DOWN_COARSE, GUI_ACTION_PAT_SELECT_ALL, GUI_ACTION_PAT_CUT, GUI_ACTION_PAT_COPY, @@ -947,7 +951,9 @@ class FurnaceGUI { float patChanSlideY[DIV_MAX_CHANS+1]; const int* nextDesc; - OperationMask opMask; + OperationMask opMaskDelete, opMaskPullDelete, opMaskInsert, opMaskPaste, opMaskTransposeNote, opMaskTransposeValue; + OperationMask opMaskInterpolate, opMaskFade, opMaskInvertVal, opMaskScale; + OperationMask opMaskRandomize, opMaskFlip, opMaskCollapseExpand; short latchNote, latchIns, latchVol, latchEffect, latchEffectVal; // bit 31: ctrl @@ -1178,7 +1184,7 @@ class FurnaceGUI { void doDelete(); void doPullDelete(); void doInsert(); - void doTranspose(int amount); + void doTranspose(int amount, OperationMask& mask); void doCopy(bool cut); void doPaste(PasteMode mode=GUI_PASTE_MODE_NORMAL); void doChangeIns(int ins); diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index 99068e95f..b5d437072 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -258,6 +258,10 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={ D("PAT_NOTE_DOWN", "Transpose (-1)", FURKMOD_CMD|SDLK_F1), D("PAT_OCTAVE_UP", "Transpose (+1 octave)", FURKMOD_CMD|SDLK_F4), D("PAT_OCTAVE_DOWN", "Transpose (-1 octave)", FURKMOD_CMD|SDLK_F3), + D("PAT_VALUE_UP", "Increase values (+1)", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_F2), + D("PAT_VALUE_DOWN", "Increase values (-1)", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_F1), + D("PAT_VALUE_UP_COARSE", "Increase values (+16)", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_F4), + D("PAT_VALUE_DOWN_COARSE", "Increase values (-16)", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_F3), D("PAT_SELECT_ALL", "Select all", FURKMOD_CMD|SDLK_a), D("PAT_CUT", "Cut", FURKMOD_CMD|SDLK_x), D("PAT_COPY", "Copy", FURKMOD_CMD|SDLK_c),