From c7b2227ee0173476a4228c38d57fa7e1858795c0 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 10 Nov 2022 19:21:01 -0500 Subject: [PATCH] GUI: prepare to add more macro editor layouts --- src/gui/gui.h | 3 + src/gui/insEdit.cpp | 1040 +++++++++++++++++++++++------------------- src/gui/settings.cpp | 20 + 3 files changed, 582 insertions(+), 481 deletions(-) diff --git a/src/gui/gui.h b/src/gui/gui.h index 996fe1482..422bf856d 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1222,6 +1222,7 @@ class FurnaceGUI { int persistFadeOut; int exportLoops; double exportFadeOut; + int macroLayout; unsigned int maxUndoSteps; String mainFontPath; String patFontPath; @@ -1352,6 +1353,7 @@ class FurnaceGUI { persistFadeOut(1), exportLoops(0), exportFadeOut(0.0), + macroLayout(0), maxUndoSteps(100), mainFontPath(""), patFontPath(""), @@ -1684,6 +1686,7 @@ class FurnaceGUI { void patternRow(int i, bool isPlaying, float lineHeight, int chans, int ord, const DivPattern** patCache, bool inhibitSel); + void drawMacroEdit(FurnaceGUIMacroDesc& i, int totalFit, float availableWidth, int index); void drawMacros(std::vector& macros); void actualWaveList(); diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 609c4c0e6..3321bfeb2 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -1294,518 +1294,596 @@ void FurnaceGUI::kvsConfig(DivInstrument* ins) { } } -void FurnaceGUI::drawMacros(std::vector& macros) { - float asFloat[256]; - int asInt[256]; - float loopIndicator[256]; - float bit30Indicator[256]; - bool doHighlight[256]; - int index=0; +void FurnaceGUI::drawMacroEdit(FurnaceGUIMacroDesc& i, int totalFit, float availableWidth, int index) { + static float asFloat[256]; + static int asInt[256]; + static float loopIndicator[256]; + static float bit30Indicator[256]; + static bool doHighlight[256]; - float reservedSpace=(settings.oldMacroVSlider)?(20.0f*dpiScale+ImGui::GetStyle().ItemSpacing.x):ImGui::GetStyle().ScrollbarSize; - - if (ImGui::BeginTable("MacroSpace",2)) { - ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,0.0); - ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - float lenAvail=ImGui::GetContentRegionAvail().x; - //ImGui::Dummy(ImVec2(120.0f*dpiScale,dpiScale)); - ImGui::SetNextItemWidth(120.0f*dpiScale); - if (ImGui::InputInt("##MacroPointSize",¯oPointSize,1,16)) { - if (macroPointSize<1) macroPointSize=1; - if (macroPointSize>256) macroPointSize=256; - } - ImGui::TableNextColumn(); - float availableWidth=ImGui::GetContentRegionAvail().x-reservedSpace; - int totalFit=MIN(255,availableWidth/MAX(1,macroPointSize*dpiScale)); - if (macroDragScroll>255-totalFit) { - macroDragScroll=255-totalFit; - } - ImGui::SetNextItemWidth(availableWidth); - if (CWSliderInt("##MacroScroll",¯oDragScroll,0,255-totalFit,"")) { - if (macroDragScroll<0) macroDragScroll=0; - if (macroDragScroll>255-totalFit) macroDragScroll=255-totalFit; - } - - // draw macros - for (FurnaceGUIMacroDesc& i: macros) { - ImGui::PushID(index); - ImGui::TableNextRow(); - - // description - ImGui::TableNextColumn(); - ImGui::Text("%s",i.displayName); - ImGui::SameLine(); - if (ImGui::SmallButton((i.macro->open&1)?(ICON_FA_CHEVRON_UP "##IMacroOpen"):(ICON_FA_CHEVRON_DOWN "##IMacroOpen"))) { - i.macro->open^=1; + if ((i.macro->open&6)==0) { + for (int j=0; j<256; j++) { + bit30Indicator[j]=0; + if (j+macroDragScroll>=i.macro->len) { + asFloat[j]=0; + asInt[j]=0; + } else { + asFloat[j]=deBit30(i.macro->val[j+macroDragScroll]); + asInt[j]=deBit30(i.macro->val[j+macroDragScroll])+i.bitOffset; + if (i.bit30) bit30Indicator[j]=enBit30(i.macro->val[j+macroDragScroll]); } - if (i.macro->open&1) { - if ((i.macro->open&6)==0) { - ImGui::SetNextItemWidth(lenAvail); - int macroLen=i.macro->len; - if (ImGui::InputScalar("##IMacroLen",ImGuiDataType_U8,¯oLen,&_ONE,&_THREE)) { MARK_MODIFIED - if (macroLen<0) macroLen=0; - if (macroLen>255) macroLen=255; - i.macro->len=macroLen; - } - } - if (ImGui::Button(macroTypeLabels[(i.macro->open>>1)&3])) { - unsigned char prevOpen=i.macro->open; - i.macro->open+=2; - if (i.macro->open>=6) { - i.macro->open-=6; - } + if (j+macroDragScroll>=i.macro->len || (j+macroDragScroll>i.macro->rel && i.macro->looprel)) { + loopIndicator[j]=0; + } else { + loopIndicator[j]=((i.macro->loop!=255 && (j+macroDragScroll)>=i.macro->loop))|((i.macro->rel!=255 && (j+macroDragScroll)==i.macro->rel)<<1); + } + } + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f)); - // check whether macro type is now ADSR/LFO or sequence - if (((prevOpen&6)?1:0)!=((i.macro->open&6)?1:0)) { - // swap memory - // this way the macro isn't corrupted if the user decides to go - // back to sequence mode - i.macro->len^=i.macro->lenMemory; - i.macro->lenMemory^=i.macro->len; - i.macro->len^=i.macro->lenMemory; + if (i.macro->vZoom<1) { + if (i.macro->name=="arp") { + i.macro->vZoom=24; + i.macro->vScroll=120-12; + } else if (i.macro->name=="pitch") { + i.macro->vZoom=128; + i.macro->vScroll=2048-64; + } else { + i.macro->vZoom=i.max-i.min; + i.macro->vScroll=0; + } + } + if (i.macro->vZoom>(i.max-i.min)) { + i.macro->vZoom=i.max-i.min; + } - for (int j=0; j<16; j++) { - i.macro->val[j]^=i.macro->typeMemory[j]; - i.macro->typeMemory[j]^=i.macro->val[j]; - i.macro->val[j]^=i.macro->typeMemory[j]; - } - - // if ADSR/LFO, populate min/max - if (i.macro->open&6) { - i.macro->val[0]=i.min; - i.macro->val[1]=i.max; + memset(doHighlight,0,256*sizeof(bool)); + if (e->isRunning()) for (int j=0; jgetTotalChannelCount(); j++) { + DivChannelState* chanState=e->getChanState(j); + if (chanState==NULL) continue; + + if (chanState->keyOff) continue; + if (chanState->lastIns!=curIns) continue; + + DivMacroInt* macroInt=e->getMacroInt(j); + if (macroInt==NULL) continue; + + DivMacroStruct* macroStruct=macroInt->structByName(i.macro->name); + if (macroStruct==NULL) continue; + + if (macroStruct->lastPos>i.macro->len) continue; + if (macroStruct->lastPoslastPos>255) continue; + if (!macroStruct->actualHad) continue; + + doHighlight[macroStruct->lastPos-macroDragScroll]=true; + } + + if (i.isBitfield) { + PlotBitfield("##IMacro",asInt,totalFit,0,i.bitfieldBits,i.max,ImVec2(availableWidth,(i.macro->open&1)?(i.height*dpiScale):(32.0f*dpiScale)),sizeof(float),doHighlight); + } else { + PlotCustom("##IMacro",asFloat,totalFit,macroDragScroll,NULL,i.min+i.macro->vScroll,i.min+i.macro->vScroll+i.macro->vZoom,ImVec2(availableWidth,(i.macro->open&1)?(i.height*dpiScale):(32.0f*dpiScale)),sizeof(float),i.color,i.macro->len-macroDragScroll,i.hoverFunc,i.hoverFuncUser,i.blockMode,(i.macro->open&1)?genericGuide:NULL,doHighlight); + } + if ((i.macro->open&1) && (ImGui::IsItemClicked(ImGuiMouseButton_Left) || ImGui::IsItemClicked(ImGuiMouseButton_Right))) { + macroDragStart=ImGui::GetItemRectMin(); + macroDragAreaSize=ImVec2(availableWidth,i.height*dpiScale); + if (i.isBitfield) { + macroDragMin=i.min; + macroDragMax=i.max; + } else { + macroDragMin=i.min+i.macro->vScroll; + macroDragMax=i.min+i.macro->vScroll+i.macro->vZoom; + } + macroDragBitOff=i.bitOffset; + macroDragBitMode=i.isBitfield; + macroDragInitialValueSet=false; + macroDragInitialValue=false; + macroDragLen=totalFit; + macroDragActive=true; + macroDragBit30=i.bit30; + macroDragSettingBit30=false; + macroDragTarget=i.macro->val; + macroDragChar=false; + macroDragLineMode=(i.isBitfield)?false:ImGui::IsItemClicked(ImGuiMouseButton_Right); + macroDragLineInitial=ImVec2(0,0); + lastMacroDesc=i; + processDrags(ImGui::GetMousePos().x,ImGui::GetMousePos().y); + } + if ((i.macro->open&1)) { + if (ImGui::IsItemHovered()) { + if (ctrlWheeling) { + if (ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift)) { + i.macro->vZoom+=wheelY*(1+(i.macro->vZoom>>4)); + if (i.macro->vZoom<1) i.macro->vZoom=1; + if (i.macro->vZoom>(i.max-i.min)) i.macro->vZoom=i.max-i.min; + if ((i.macro->vScroll+i.macro->vZoom)>(i.max-i.min)) { + i.macro->vScroll=(i.max-i.min)-i.macro->vZoom; } + } else { + macroPointSize+=wheelY; + if (macroPointSize<1) macroPointSize=1; + if (macroPointSize>256) macroPointSize=256; } - PARAMETER; - } - if (ImGui::IsItemHovered()) { - switch (i.macro->open&6) { - case 0: - ImGui::SetTooltip("Macro type: Sequence"); - break; - case 2: - ImGui::SetTooltip("Macro type: ADSR"); - break; - case 4: - ImGui::SetTooltip("Macro type: LFO"); - break; - default: - ImGui::SetTooltip("Macro type: What's going on here?"); - break; - } - } - if (i.macro->open&6) { - i.macro->len=16; - } - ImGui::SameLine(); - ImGui::Button(ICON_FA_ELLIPSIS_H "##IMacroSet"); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Delay/Step Length"); - } - if (ImGui::BeginPopupContextItem("IMacroSetP",ImGuiPopupFlags_MouseButtonLeft)) { - if (ImGui::InputScalar("Step Length (ticks)##IMacroSpeed",ImGuiDataType_U8,&i.macro->speed,&_ONE,&_THREE)) { - if (i.macro->speed<1) i.macro->speed=1; - MARK_MODIFIED; - } - if (ImGui::InputScalar("Delay##IMacroDelay",ImGuiDataType_U8,&i.macro->delay,&_ONE,&_THREE)) { - MARK_MODIFIED; - } - ImGui::EndPopup(); - } - // do not change this! - // anything other than a checkbox will look ugly! - // if you really need more than two macro modes please tell me. - if (i.modeName!=NULL) { - bool modeVal=i.macro->mode; - String modeName=fmt::sprintf("%s##IMacroMode",i.modeName); - if (ImGui::Checkbox(modeName.c_str(),&modeVal)) { - i.macro->mode=modeVal; - } + } else if ((ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift)) && wheelY!=0) { + i.macro->vScroll+=wheelY*(1+(i.macro->vZoom>>4)); + if (i.macro->vScroll<0) i.macro->vScroll=0; + if (i.macro->vScroll>((i.max-i.min)-i.macro->vZoom)) i.macro->vScroll=(i.max-i.min)-i.macro->vZoom; } } - // macro area - ImGui::TableNextColumn(); - if ((i.macro->open&6)==0) { - for (int j=0; j<256; j++) { - bit30Indicator[j]=0; - if (j+macroDragScroll>=i.macro->len) { - asFloat[j]=0; - asInt[j]=0; - } else { - asFloat[j]=deBit30(i.macro->val[j+macroDragScroll]); - asInt[j]=deBit30(i.macro->val[j+macroDragScroll])+i.bitOffset; - if (i.bit30) bit30Indicator[j]=enBit30(i.macro->val[j+macroDragScroll]); + // slider + if (!i.isBitfield) { + if (settings.oldMacroVSlider) { + ImGui::SameLine(0.0f); + if (ImGui::VSliderInt("IMacroVScroll",ImVec2(20.0f*dpiScale,i.height*dpiScale),&i.macro->vScroll,0,(i.max-i.min)-i.macro->vZoom,"")) { + if (i.macro->vScroll<0) i.macro->vScroll=0; + if (i.macro->vScroll>((i.max-i.min)-i.macro->vZoom)) i.macro->vScroll=(i.max-i.min)-i.macro->vZoom; } - if (j+macroDragScroll>=i.macro->len || (j+macroDragScroll>i.macro->rel && i.macro->looprel)) { - loopIndicator[j]=0; - } else { - loopIndicator[j]=((i.macro->loop!=255 && (j+macroDragScroll)>=i.macro->loop))|((i.macro->rel!=255 && (j+macroDragScroll)==i.macro->rel)<<1); + if (ImGui::IsItemHovered() && ctrlWheeling) { + i.macro->vScroll+=wheelY*(1+(i.macro->vZoom>>4)); + if (i.macro->vScroll<0) i.macro->vScroll=0; + if (i.macro->vScroll>((i.max-i.min)-i.macro->vZoom)) i.macro->vScroll=(i.max-i.min)-i.macro->vZoom; } - } - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f)); - - if (i.macro->vZoom<1) { - if (i.macro->name=="arp") { - i.macro->vZoom=24; - i.macro->vScroll=120-12; - } else if (i.macro->name=="pitch") { - i.macro->vZoom=128; - i.macro->vScroll=2048-64; - } else { - i.macro->vZoom=i.max-i.min; - i.macro->vScroll=0; - } - } - if (i.macro->vZoom>(i.max-i.min)) { - i.macro->vZoom=i.max-i.min; - } - - memset(doHighlight,0,256*sizeof(bool)); - if (e->isRunning()) for (int j=0; jgetTotalChannelCount(); j++) { - DivChannelState* chanState=e->getChanState(j); - if (chanState==NULL) continue; - - if (chanState->keyOff) continue; - if (chanState->lastIns!=curIns) continue; - - DivMacroInt* macroInt=e->getMacroInt(j); - if (macroInt==NULL) continue; - - DivMacroStruct* macroStruct=macroInt->structByName(i.macro->name); - if (macroStruct==NULL) continue; - - if (macroStruct->lastPos>i.macro->len) continue; - if (macroStruct->lastPoslastPos>255) continue; - if (!macroStruct->actualHad) continue; - - doHighlight[macroStruct->lastPos-macroDragScroll]=true; - } - - if (i.isBitfield) { - PlotBitfield("##IMacro",asInt,totalFit,0,i.bitfieldBits,i.max,ImVec2(availableWidth,(i.macro->open&1)?(i.height*dpiScale):(32.0f*dpiScale)),sizeof(float),doHighlight); } else { - PlotCustom("##IMacro",asFloat,totalFit,macroDragScroll,NULL,i.min+i.macro->vScroll,i.min+i.macro->vScroll+i.macro->vZoom,ImVec2(availableWidth,(i.macro->open&1)?(i.height*dpiScale):(32.0f*dpiScale)),sizeof(float),i.color,i.macro->len-macroDragScroll,i.hoverFunc,i.hoverFuncUser,i.blockMode,(i.macro->open&1)?genericGuide:NULL,doHighlight); - } - if ((i.macro->open&1) && (ImGui::IsItemClicked(ImGuiMouseButton_Left) || ImGui::IsItemClicked(ImGuiMouseButton_Right))) { - macroDragStart=ImGui::GetItemRectMin(); - macroDragAreaSize=ImVec2(availableWidth,i.height*dpiScale); - if (i.isBitfield) { - macroDragMin=i.min; - macroDragMax=i.max; - } else { - macroDragMin=i.min+i.macro->vScroll; - macroDragMax=i.min+i.macro->vScroll+i.macro->vZoom; + ImS64 scrollV=(i.max-i.min-i.macro->vZoom)-i.macro->vScroll; + ImS64 availV=i.macro->vZoom; + ImS64 contentsV=(i.max-i.min); + + ImGui::SameLine(0.0f); + ImGui::SetCursorPosX(ImGui::GetCursorPosX()-ImGui::GetStyle().ItemSpacing.x); + ImRect scrollbarPos=ImRect(ImGui::GetCursorScreenPos(),ImGui::GetCursorScreenPos()); + scrollbarPos.Max.x+=ImGui::GetStyle().ScrollbarSize; + scrollbarPos.Max.y+=i.height*dpiScale; + ImGui::Dummy(ImVec2(ImGui::GetStyle().ScrollbarSize,i.height*dpiScale)); + if (ImGui::IsItemHovered() && ctrlWheeling) { + i.macro->vScroll+=wheelY*(1+(i.macro->vZoom>>4)); + if (i.macro->vScroll<0) i.macro->vScroll=0; + if (i.macro->vScroll>((i.max-i.min)-i.macro->vZoom)) i.macro->vScroll=(i.max-i.min)-i.macro->vZoom; } - macroDragBitOff=i.bitOffset; - macroDragBitMode=i.isBitfield; + + ImGuiID scrollbarID=ImGui::GetID("IMacroVScroll"); + ImGui::KeepAliveID(scrollbarID); + if (ImGui::ScrollbarEx(scrollbarPos,scrollbarID,ImGuiAxis_Y,&scrollV,availV,contentsV,0)) { + i.macro->vScroll=(i.max-i.min-i.macro->vZoom)-scrollV; + } + } + } + + // bit 30 area + if (i.bit30) { + PlotCustom("##IMacroBit30",bit30Indicator,totalFit,macroDragScroll,NULL,0,1,ImVec2(availableWidth,12.0f*dpiScale),sizeof(float),i.color,i.macro->len-macroDragScroll,¯oHoverBit30); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + macroDragStart=ImGui::GetItemRectMin(); + macroDragAreaSize=ImVec2(availableWidth,12.0f*dpiScale); macroDragInitialValueSet=false; macroDragInitialValue=false; macroDragLen=totalFit; macroDragActive=true; macroDragBit30=i.bit30; - macroDragSettingBit30=false; + macroDragSettingBit30=true; macroDragTarget=i.macro->val; macroDragChar=false; - macroDragLineMode=(i.isBitfield)?false:ImGui::IsItemClicked(ImGuiMouseButton_Right); + macroDragLineMode=false; macroDragLineInitial=ImVec2(0,0); lastMacroDesc=i; processDrags(ImGui::GetMousePos().x,ImGui::GetMousePos().y); } - if ((i.macro->open&1)) { - if (ImGui::IsItemHovered()) { - if (ctrlWheeling) { - if (ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift)) { - i.macro->vZoom+=wheelY*(1+(i.macro->vZoom>>4)); - if (i.macro->vZoom<1) i.macro->vZoom=1; - if (i.macro->vZoom>(i.max-i.min)) i.macro->vZoom=i.max-i.min; - if ((i.macro->vScroll+i.macro->vZoom)>(i.max-i.min)) { - i.macro->vScroll=(i.max-i.min)-i.macro->vZoom; - } - } else { - macroPointSize+=wheelY; - if (macroPointSize<1) macroPointSize=1; - if (macroPointSize>256) macroPointSize=256; - } - } else if ((ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift)) && wheelY!=0) { - i.macro->vScroll+=wheelY*(1+(i.macro->vZoom>>4)); - if (i.macro->vScroll<0) i.macro->vScroll=0; - if (i.macro->vScroll>((i.max-i.min)-i.macro->vZoom)) i.macro->vScroll=(i.max-i.min)-i.macro->vZoom; - } - } + } - // slider - if (!i.isBitfield) { - if (settings.oldMacroVSlider) { - ImGui::SameLine(0.0f); - if (ImGui::VSliderInt("IMacroVScroll",ImVec2(20.0f*dpiScale,i.height*dpiScale),&i.macro->vScroll,0,(i.max-i.min)-i.macro->vZoom,"")) { - if (i.macro->vScroll<0) i.macro->vScroll=0; - if (i.macro->vScroll>((i.max-i.min)-i.macro->vZoom)) i.macro->vScroll=(i.max-i.min)-i.macro->vZoom; - } - if (ImGui::IsItemHovered() && ctrlWheeling) { - i.macro->vScroll+=wheelY*(1+(i.macro->vZoom>>4)); - if (i.macro->vScroll<0) i.macro->vScroll=0; - if (i.macro->vScroll>((i.max-i.min)-i.macro->vZoom)) i.macro->vScroll=(i.max-i.min)-i.macro->vZoom; - } - } else { - ImS64 scrollV=(i.max-i.min-i.macro->vZoom)-i.macro->vScroll; - ImS64 availV=i.macro->vZoom; - ImS64 contentsV=(i.max-i.min); - - ImGui::SameLine(0.0f); - ImGui::SetCursorPosX(ImGui::GetCursorPosX()-ImGui::GetStyle().ItemSpacing.x); - ImRect scrollbarPos=ImRect(ImGui::GetCursorScreenPos(),ImGui::GetCursorScreenPos()); - scrollbarPos.Max.x+=ImGui::GetStyle().ScrollbarSize; - scrollbarPos.Max.y+=i.height*dpiScale; - ImGui::Dummy(ImVec2(ImGui::GetStyle().ScrollbarSize,i.height*dpiScale)); - if (ImGui::IsItemHovered() && ctrlWheeling) { - i.macro->vScroll+=wheelY*(1+(i.macro->vZoom>>4)); - if (i.macro->vScroll<0) i.macro->vScroll=0; - if (i.macro->vScroll>((i.max-i.min)-i.macro->vZoom)) i.macro->vScroll=(i.max-i.min)-i.macro->vZoom; - } - - ImGuiID scrollbarID=ImGui::GetID("IMacroVScroll"); - ImGui::KeepAliveID(scrollbarID); - if (ImGui::ScrollbarEx(scrollbarPos,scrollbarID,ImGuiAxis_Y,&scrollV,availV,contentsV,0)) { - i.macro->vScroll=(i.max-i.min-i.macro->vZoom)-scrollV; - } - } - } - - // bit 30 area - if (i.bit30) { - PlotCustom("##IMacroBit30",bit30Indicator,totalFit,macroDragScroll,NULL,0,1,ImVec2(availableWidth,12.0f*dpiScale),sizeof(float),i.color,i.macro->len-macroDragScroll,¯oHoverBit30); - if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { - macroDragStart=ImGui::GetItemRectMin(); - macroDragAreaSize=ImVec2(availableWidth,12.0f*dpiScale); - macroDragInitialValueSet=false; - macroDragInitialValue=false; - macroDragLen=totalFit; - macroDragActive=true; - macroDragBit30=i.bit30; - macroDragSettingBit30=true; - macroDragTarget=i.macro->val; - macroDragChar=false; - macroDragLineMode=false; - macroDragLineInitial=ImVec2(0,0); - lastMacroDesc=i; - processDrags(ImGui::GetMousePos().x,ImGui::GetMousePos().y); - } - } - - // loop area - PlotCustom("##IMacroLoop",loopIndicator,totalFit,macroDragScroll,NULL,0,2,ImVec2(availableWidth,12.0f*dpiScale),sizeof(float),i.color,i.macro->len-macroDragScroll,¯oHoverLoop); - if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { - macroLoopDragStart=ImGui::GetItemRectMin(); - macroLoopDragAreaSize=ImVec2(availableWidth,12.0f*dpiScale); - macroLoopDragLen=totalFit; - if (ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift)) { - macroLoopDragTarget=&i.macro->rel; - } else { - macroLoopDragTarget=&i.macro->loop; - } - macroLoopDragActive=true; - processDrags(ImGui::GetMousePos().x,ImGui::GetMousePos().y); - } - if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { - if (ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift)) { - i.macro->rel=255; - } else { - i.macro->loop=255; - } - } - ImGui::SetNextItemWidth(availableWidth); - String& mmlStr=mmlString[index]; - if (ImGui::InputText("##IMacroMML",&mmlStr)) { - decodeMMLStr(mmlStr,i.macro->val,i.macro->len,i.macro->loop,i.min,(i.isBitfield)?((1<<(i.isBitfield?i.max:0))-1):i.max,i.macro->rel,i.bit30); - } - if (!ImGui::IsItemActive()) { - encodeMMLStr(mmlStr,i.macro->val,i.macro->len,i.macro->loop,i.macro->rel,false,i.bit30); - } + // loop area + PlotCustom("##IMacroLoop",loopIndicator,totalFit,macroDragScroll,NULL,0,2,ImVec2(availableWidth,12.0f*dpiScale),sizeof(float),i.color,i.macro->len-macroDragScroll,¯oHoverLoop); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + macroLoopDragStart=ImGui::GetItemRectMin(); + macroLoopDragAreaSize=ImVec2(availableWidth,12.0f*dpiScale); + macroLoopDragLen=totalFit; + if (ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift)) { + macroLoopDragTarget=&i.macro->rel; + } else { + macroLoopDragTarget=&i.macro->loop; } - ImGui::PopStyleVar(); - } else { - if (i.macro->open&2) { - if (ImGui::BeginTable("MacroADSR",4)) { - ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.3); - ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch,0.3); - //ImGui::TableSetupColumn("c4",ImGuiTableColumnFlags_WidthStretch,0.4); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Bottom"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::InputInt("##MABottom",&i.macro->val[0],1,16)) { PARAMETER - if (i.macro->val[0]val[0]=i.min; - if (i.macro->val[0]>i.max) i.macro->val[0]=i.max; - } - - ImGui::TableNextColumn(); - ImGui::Text("Top"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::InputInt("##MATop",&i.macro->val[1],1,16)) { PARAMETER - if (i.macro->val[1]val[1]=i.min; - if (i.macro->val[1]>i.max) i.macro->val[1]=i.max; - } - - /*ImGui::TableNextColumn(); - ImGui::Text("the envelope goes here");*/ - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Attack"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##MAAR",&i.macro->val[2],0,255)) { PARAMETER - if (i.macro->val[2]<0) i.macro->val[2]=0; - if (i.macro->val[2]>255) i.macro->val[2]=255; - } - - ImGui::TableNextColumn(); - ImGui::Text("Sustain"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##MASL",&i.macro->val[5],0,255)) { PARAMETER - if (i.macro->val[5]<0) i.macro->val[5]=0; - if (i.macro->val[5]>255) i.macro->val[5]=255; - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Hold"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##MAHT",&i.macro->val[3],0,255)) { PARAMETER - if (i.macro->val[3]<0) i.macro->val[3]=0; - if (i.macro->val[3]>255) i.macro->val[3]=255; - } - - ImGui::TableNextColumn(); - ImGui::Text("SusTime"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##MAST",&i.macro->val[6],0,255)) { PARAMETER - if (i.macro->val[6]<0) i.macro->val[6]=0; - if (i.macro->val[6]>255) i.macro->val[6]=255; - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Decay"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##MADR",&i.macro->val[4],0,255)) { PARAMETER - if (i.macro->val[4]<0) i.macro->val[4]=0; - if (i.macro->val[4]>255) i.macro->val[4]=255; - } - - ImGui::TableNextColumn(); - ImGui::Text("SusDecay"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##MASR",&i.macro->val[7],0,255)) { PARAMETER - if (i.macro->val[7]<0) i.macro->val[7]=0; - if (i.macro->val[7]>255) i.macro->val[7]=255; - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::TableNextColumn(); - - ImGui::TableNextColumn(); - ImGui::Text("Release"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##MARR",&i.macro->val[8],0,255)) { PARAMETER - if (i.macro->val[8]<0) i.macro->val[8]=0; - if (i.macro->val[8]>255) i.macro->val[8]=255; - } - - ImGui::EndTable(); - } - } - if (i.macro->open&4) { - if (ImGui::BeginTable("MacroLFO",4)) { - ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.3); - ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch,0.3); - //ImGui::TableSetupColumn("c4",ImGuiTableColumnFlags_WidthStretch,0.4); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Bottom"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::InputInt("##MABottom",&i.macro->val[0],1,16)) { PARAMETER - if (i.macro->val[0]val[0]=i.min; - if (i.macro->val[0]>i.max) i.macro->val[0]=i.max; - } - - ImGui::TableNextColumn(); - ImGui::Text("Top"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::InputInt("##MATop",&i.macro->val[1],1,16)) { PARAMETER - if (i.macro->val[1]val[1]=i.min; - if (i.macro->val[1]>i.max) i.macro->val[1]=i.max; - } - - /*ImGui::TableNextColumn(); - ImGui::Text("the envelope goes here");*/ - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Speed"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##MLSpeed",&i.macro->val[11],0,255)) { PARAMETER - if (i.macro->val[11]<0) i.macro->val[11]=0; - if (i.macro->val[11]>255) i.macro->val[11]=255; - } - - ImGui::TableNextColumn(); - ImGui::Text("Phase"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##MLPhase",&i.macro->val[13],0,1023)) { PARAMETER - if (i.macro->val[13]<0) i.macro->val[13]=0; - if (i.macro->val[13]>1023) i.macro->val[13]=1023; - } - - ImGui::TableNextColumn(); - ImGui::Text("Shape"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##MLShape",&i.macro->val[12],0,2,macroLFOShapes[i.macro->val[12]&3])) { PARAMETER - if (i.macro->val[12]<0) i.macro->val[12]=0; - if (i.macro->val[12]>2) i.macro->val[12]=2; - } - - ImGui::EndTable(); - } + macroLoopDragActive=true; + processDrags(ImGui::GetMousePos().x,ImGui::GetMousePos().y); + } + if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { + if (ImGui::IsKeyDown(ImGuiKey_LeftShift) || ImGui::IsKeyDown(ImGuiKey_RightShift)) { + i.macro->rel=255; + } else { + i.macro->loop=255; } } - ImGui::PopID(); - index++; + ImGui::SetNextItemWidth(availableWidth); + String& mmlStr=mmlString[index]; + if (ImGui::InputText("##IMacroMML",&mmlStr)) { + decodeMMLStr(mmlStr,i.macro->val,i.macro->len,i.macro->loop,i.min,(i.isBitfield)?((1<<(i.isBitfield?i.max:0))-1):i.max,i.macro->rel,i.bit30); + } + if (!ImGui::IsItemActive()) { + encodeMMLStr(mmlStr,i.macro->val,i.macro->len,i.macro->loop,i.macro->rel,false,i.bit30); + } } + ImGui::PopStyleVar(); + } else { + if (i.macro->open&2) { + if (ImGui::BeginTable("MacroADSR",4)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.3); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch,0.3); + //ImGui::TableSetupColumn("c4",ImGuiTableColumnFlags_WidthStretch,0.4); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(availableWidth); - if (CWSliderInt("##MacroScroll",¯oDragScroll,0,255-totalFit,"")) { - if (macroDragScroll<0) macroDragScroll=0; - if (macroDragScroll>255-totalFit) macroDragScroll=255-totalFit; + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Bottom"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::InputInt("##MABottom",&i.macro->val[0],1,16)) { PARAMETER + if (i.macro->val[0]val[0]=i.min; + if (i.macro->val[0]>i.max) i.macro->val[0]=i.max; + } + + ImGui::TableNextColumn(); + ImGui::Text("Top"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::InputInt("##MATop",&i.macro->val[1],1,16)) { PARAMETER + if (i.macro->val[1]val[1]=i.min; + if (i.macro->val[1]>i.max) i.macro->val[1]=i.max; + } + + /*ImGui::TableNextColumn(); + ImGui::Text("the envelope goes here");*/ + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Attack"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderInt("##MAAR",&i.macro->val[2],0,255)) { PARAMETER + if (i.macro->val[2]<0) i.macro->val[2]=0; + if (i.macro->val[2]>255) i.macro->val[2]=255; + } + + ImGui::TableNextColumn(); + ImGui::Text("Sustain"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderInt("##MASL",&i.macro->val[5],0,255)) { PARAMETER + if (i.macro->val[5]<0) i.macro->val[5]=0; + if (i.macro->val[5]>255) i.macro->val[5]=255; + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Hold"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderInt("##MAHT",&i.macro->val[3],0,255)) { PARAMETER + if (i.macro->val[3]<0) i.macro->val[3]=0; + if (i.macro->val[3]>255) i.macro->val[3]=255; + } + + ImGui::TableNextColumn(); + ImGui::Text("SusTime"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderInt("##MAST",&i.macro->val[6],0,255)) { PARAMETER + if (i.macro->val[6]<0) i.macro->val[6]=0; + if (i.macro->val[6]>255) i.macro->val[6]=255; + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Decay"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderInt("##MADR",&i.macro->val[4],0,255)) { PARAMETER + if (i.macro->val[4]<0) i.macro->val[4]=0; + if (i.macro->val[4]>255) i.macro->val[4]=255; + } + + ImGui::TableNextColumn(); + ImGui::Text("SusDecay"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderInt("##MASR",&i.macro->val[7],0,255)) { PARAMETER + if (i.macro->val[7]<0) i.macro->val[7]=0; + if (i.macro->val[7]>255) i.macro->val[7]=255; + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TableNextColumn(); + + ImGui::TableNextColumn(); + ImGui::Text("Release"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderInt("##MARR",&i.macro->val[8],0,255)) { PARAMETER + if (i.macro->val[8]<0) i.macro->val[8]=0; + if (i.macro->val[8]>255) i.macro->val[8]=255; + } + + ImGui::EndTable(); + } + } + if (i.macro->open&4) { + if (ImGui::BeginTable("MacroLFO",4)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.3); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch,0.3); + //ImGui::TableSetupColumn("c4",ImGuiTableColumnFlags_WidthStretch,0.4); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Bottom"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::InputInt("##MABottom",&i.macro->val[0],1,16)) { PARAMETER + if (i.macro->val[0]val[0]=i.min; + if (i.macro->val[0]>i.max) i.macro->val[0]=i.max; + } + + ImGui::TableNextColumn(); + ImGui::Text("Top"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::InputInt("##MATop",&i.macro->val[1],1,16)) { PARAMETER + if (i.macro->val[1]val[1]=i.min; + if (i.macro->val[1]>i.max) i.macro->val[1]=i.max; + } + + /*ImGui::TableNextColumn(); + ImGui::Text("the envelope goes here");*/ + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Speed"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderInt("##MLSpeed",&i.macro->val[11],0,255)) { PARAMETER + if (i.macro->val[11]<0) i.macro->val[11]=0; + if (i.macro->val[11]>255) i.macro->val[11]=255; + } + + ImGui::TableNextColumn(); + ImGui::Text("Phase"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderInt("##MLPhase",&i.macro->val[13],0,1023)) { PARAMETER + if (i.macro->val[13]<0) i.macro->val[13]=0; + if (i.macro->val[13]>1023) i.macro->val[13]=1023; + } + + ImGui::TableNextColumn(); + ImGui::Text("Shape"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderInt("##MLShape",&i.macro->val[12],0,2,macroLFOShapes[i.macro->val[12]&3])) { PARAMETER + if (i.macro->val[12]<0) i.macro->val[12]=0; + if (i.macro->val[12]>2) i.macro->val[12]=2; + } + + ImGui::EndTable(); + } + } + } +} + +#define BUTTON_TO_SET_MODE(buttonType) \ + if (buttonType(macroTypeLabels[(i.macro->open>>1)&3])) { \ + unsigned char prevOpen=i.macro->open; \ + i.macro->open+=2; \ + if (i.macro->open>=6) { \ + i.macro->open-=6; \ + } \ +\ + /* check whether macro type is now ADSR/LFO or sequence */ \ + if (((prevOpen&6)?1:0)!=((i.macro->open&6)?1:0)) { \ + /* swap memory */ \ + /* this way the macro isn't corrupted if the user decides to go */ \ + /* back to sequence mode */ \ + i.macro->len^=i.macro->lenMemory; \ + i.macro->lenMemory^=i.macro->len; \ + i.macro->len^=i.macro->lenMemory; \ +\ + for (int j=0; j<16; j++) { \ + i.macro->val[j]^=i.macro->typeMemory[j]; \ + i.macro->typeMemory[j]^=i.macro->val[j]; \ + i.macro->val[j]^=i.macro->typeMemory[j]; \ + } \ +\ + /* if ADSR/LFO, populate min/max */ \ + if (i.macro->open&6) { \ + i.macro->val[0]=i.min; \ + i.macro->val[1]=i.max; \ + } \ + } \ + PARAMETER; \ + } \ + if (ImGui::IsItemHovered()) { \ + switch (i.macro->open&6) { \ + case 0: \ + ImGui::SetTooltip("Macro type: Sequence"); \ + break; \ + case 2: \ + ImGui::SetTooltip("Macro type: ADSR"); \ + break; \ + case 4: \ + ImGui::SetTooltip("Macro type: LFO"); \ + break; \ + default: \ + ImGui::SetTooltip("Macro type: What's going on here?"); \ + break; \ + } \ + } \ + if (i.macro->open&6) { \ + i.macro->len=16; \ + } + +#define BUTTON_TO_SET_PROPS \ + ImGui::Button(ICON_FA_ELLIPSIS_H "##IMacroSet"); \ + if (ImGui::IsItemHovered()) { \ + ImGui::SetTooltip("Delay/Step Length"); \ + } \ + if (ImGui::BeginPopupContextItem("IMacroSetP",ImGuiPopupFlags_MouseButtonLeft)) { \ + if (ImGui::InputScalar("Step Length (ticks)##IMacroSpeed",ImGuiDataType_U8,&i.macro->speed,&_ONE,&_THREE)) { \ + if (i.macro->speed<1) i.macro->speed=1; \ + MARK_MODIFIED; \ + } \ + if (ImGui::InputScalar("Delay##IMacroDelay",ImGuiDataType_U8,&i.macro->delay,&_ONE,&_THREE)) { \ + MARK_MODIFIED; \ + } \ + ImGui::EndPopup(); \ + } + +void FurnaceGUI::drawMacros(std::vector& macros) { + int index=0; + float reservedSpace=(settings.oldMacroVSlider)?(20.0f*dpiScale+ImGui::GetStyle().ItemSpacing.x):ImGui::GetStyle().ScrollbarSize; + switch (settings.macroLayout) { + case 0: { + if (ImGui::BeginTable("MacroSpace",2)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,0.0); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + float lenAvail=ImGui::GetContentRegionAvail().x; + //ImGui::Dummy(ImVec2(120.0f*dpiScale,dpiScale)); + ImGui::SetNextItemWidth(120.0f*dpiScale); + if (ImGui::InputInt("##MacroPointSize",¯oPointSize,1,16)) { + if (macroPointSize<1) macroPointSize=1; + if (macroPointSize>256) macroPointSize=256; + } + ImGui::TableNextColumn(); + float availableWidth=ImGui::GetContentRegionAvail().x-reservedSpace; + int totalFit=MIN(255,availableWidth/MAX(1,macroPointSize*dpiScale)); + if (macroDragScroll>255-totalFit) { + macroDragScroll=255-totalFit; + } + ImGui::SetNextItemWidth(availableWidth); + if (CWSliderInt("##MacroScroll",¯oDragScroll,0,255-totalFit,"")) { + if (macroDragScroll<0) macroDragScroll=0; + if (macroDragScroll>255-totalFit) macroDragScroll=255-totalFit; + } + + // draw macros + for (FurnaceGUIMacroDesc& i: macros) { + ImGui::PushID(index); + ImGui::TableNextRow(); + + // description + ImGui::TableNextColumn(); + ImGui::Text("%s",i.displayName); + ImGui::SameLine(); + if (ImGui::SmallButton((i.macro->open&1)?(ICON_FA_CHEVRON_UP "##IMacroOpen"):(ICON_FA_CHEVRON_DOWN "##IMacroOpen"))) { + i.macro->open^=1; + } + if (i.macro->open&1) { + if ((i.macro->open&6)==0) { + ImGui::SetNextItemWidth(lenAvail); + int macroLen=i.macro->len; + if (ImGui::InputScalar("##IMacroLen",ImGuiDataType_U8,¯oLen,&_ONE,&_THREE)) { MARK_MODIFIED + if (macroLen<0) macroLen=0; + if (macroLen>255) macroLen=255; + i.macro->len=macroLen; + } + } + BUTTON_TO_SET_MODE(ImGui::Button); + ImGui::SameLine(); + BUTTON_TO_SET_PROPS; + // do not change this! + // anything other than a checkbox will look ugly! + // if you really need more than two macro modes please tell me. + if (i.modeName!=NULL) { + bool modeVal=i.macro->mode; + String modeName=fmt::sprintf("%s##IMacroMode",i.modeName); + if (ImGui::Checkbox(modeName.c_str(),&modeVal)) { + i.macro->mode=modeVal; + } + } + } + + // macro area + ImGui::TableNextColumn(); + drawMacroEdit(i,totalFit,availableWidth,index); + ImGui::PopID(); + index++; + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(availableWidth); + if (CWSliderInt("##MacroScroll",¯oDragScroll,0,255-totalFit,"")) { + if (macroDragScroll<0) macroDragScroll=0; + if (macroDragScroll>255-totalFit) macroDragScroll=255-totalFit; + } + ImGui::EndTable(); + } + break; + } + case 1: { + ImGui::Text("Mobile"); + break; + } + case 2: { + for (FurnaceGUIMacroDesc& i: macros) { + if (index>0) ImGui::Separator(); + + float availableWidth=ImGui::GetContentRegionAvail().x-reservedSpace; + int totalFit=i.macro->len; + if (totalFit<1) totalFit=1; + + ImGui::PushID(index); + + ImGui::TextUnformatted(i.displayName); + ImGui::SameLine(); + if (ImGui::SmallButton((i.macro->open&1)?(ICON_FA_CHEVRON_UP "##IMacroOpen"):(ICON_FA_CHEVRON_DOWN "##IMacroOpen"))) { + i.macro->open^=1; + } + + if (i.macro->open&1) { + ImGui::SameLine(); + BUTTON_TO_SET_MODE(ImGui::Button); + } + + drawMacroEdit(i,totalFit,availableWidth,index); + + if (i.macro->open&1) { + if ((i.macro->open&6)==0) { + ImGui::Text("Length"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(120.0f*dpiScale); + int macroLen=i.macro->len; + if (ImGui::InputScalar("##IMacroLen",ImGuiDataType_U8,¯oLen,&_ONE,&_THREE)) { MARK_MODIFIED + if (macroLen<0) macroLen=0; + if (macroLen>255) macroLen=255; + i.macro->len=macroLen; + } + ImGui::SameLine(); + } + BUTTON_TO_SET_PROPS; + if (i.modeName!=NULL) { + bool modeVal=i.macro->mode; + String modeName=fmt::sprintf("%s##IMacroMode",i.modeName); + ImGui::SameLine(); + if (ImGui::Checkbox(modeName.c_str(),&modeVal)) { + i.macro->mode=modeVal; + } + } + } + + ImGui::PopID(); + index++; + } + break; + } + case 3: { + ImGui::Text("Single (with list)"); + break; + } + case 4: { + ImGui::Text("Single (combo box)"); + break; } - ImGui::EndTable(); } } diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 02cd387cf..74bd1cb8e 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -1326,6 +1326,23 @@ void FurnaceGUI::drawSettings() { settings.susPosition=1; } + ImGui::Text("Macro editor layout:"); + if (ImGui::RadioButton("Unified##mel0",settings.macroLayout==0)) { + settings.macroLayout=0; + } + if (ImGui::RadioButton("Mobile##mel1",settings.macroLayout==1)) { + settings.macroLayout=1; + } + if (ImGui::RadioButton("Grid##mel2",settings.macroLayout==2)) { + settings.macroLayout=2; + } + if (ImGui::RadioButton("Single (with list)##mel3",settings.macroLayout==3)) { + settings.macroLayout=3; + } + if (ImGui::RadioButton("Single (combo box)##mel4",settings.macroLayout==4)) { + settings.macroLayout=4; + } + ImGui::Separator(); ImGui::Text("Namco 163 chip name"); @@ -2405,6 +2422,7 @@ void FurnaceGUI::syncSettings() { settings.persistFadeOut=e->getConfInt("persistFadeOut",1); settings.exportLoops=e->getConfInt("exportLoops",0); settings.exportFadeOut=e->getConfDouble("exportFadeOut",0.0); + settings.macroLayout=e->getConfInt("macroLayout",0); clampSetting(settings.mainFontSize,2,96); clampSetting(settings.patFontSize,2,96); @@ -2511,6 +2529,7 @@ void FurnaceGUI::syncSettings() { clampSetting(settings.centerPattern,0,1); clampSetting(settings.ordersCursor,0,1); clampSetting(settings.persistFadeOut,0,1); + clampSetting(settings.macroLayout,0,4); if (settings.exportLoops<0.0) settings.exportLoops=0.0; if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0; @@ -2683,6 +2702,7 @@ void FurnaceGUI::commitSettings() { e->setConf("persistFadeOut",settings.persistFadeOut); e->setConf("exportLoops",settings.exportLoops); e->setConf("exportFadeOut",settings.exportFadeOut); + e->setConf("macroLayout",settings.macroLayout); // colors for (int i=0; i