GUI: prepare to add more macro editor layouts

This commit is contained in:
tildearrow 2022-11-10 19:21:01 -05:00
parent bf5b088a54
commit c7b2227ee0
3 changed files with 582 additions and 481 deletions

View file

@ -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<FurnaceGUIMacroDesc>& macros);
void actualWaveList();

View file

@ -1294,140 +1294,13 @@ void FurnaceGUI::kvsConfig(DivInstrument* ins) {
}
}
void FurnaceGUI::drawMacros(std::vector<FurnaceGUIMacroDesc>& 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",&macroPointSize,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",&macroDragScroll,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,&macroLen,&_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;
}
// 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;
}
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;
}
}
}
// macro area
ImGui::TableNextColumn();
if ((i.macro->open&6)==0) {
for (int j=0; j<256; j++) {
bit30Indicator[j]=0;
@ -1793,6 +1666,144 @@ void FurnaceGUI::drawMacros(std::vector<FurnaceGUIMacroDesc>& macros) {
}
}
}
}
#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<FurnaceGUIMacroDesc>& 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",&macroPointSize,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",&macroDragScroll,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,&macroLen,&_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++;
}
@ -1807,6 +1818,73 @@ void FurnaceGUI::drawMacros(std::vector<FurnaceGUIMacroDesc>& macros) {
}
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,&macroLen,&_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;
}
}
}
#define DRUM_FREQ(name,db,df,prop) \

View file

@ -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<GUI_COLOR_MAX; i++) {