From 79f92fab68b9b17583c3382faba38df105577fa8 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 3 Oct 2023 04:38:28 -0500 Subject: [PATCH] GUI: prepare for status view --- src/engine/engine.h | 3 +- src/engine/playback.cpp | 4 + src/gui/gui.cpp | 22 +++++- src/gui/gui.h | 12 ++- src/gui/guiConst.cpp | 5 ++ src/gui/pattern.cpp | 166 +++++++++++++++++++++++++++++++++++----- src/gui/settings.cpp | 4 + 7 files changed, 190 insertions(+), 26 deletions(-) diff --git a/src/engine/engine.h b/src/engine/engine.h index 734d10daf..cdb35e97f 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -105,7 +105,7 @@ struct DivChannelState { int vibratoDepth, vibratoRate, vibratoPos, vibratoPosGiant, vibratoDir, vibratoFine; int tremoloDepth, tremoloRate, tremoloPos; unsigned char arp, arpStage, arpTicks, panL, panR, panRL, panRR, lastVibrato, lastPorta; - bool doNote, legato, portaStop, keyOn, keyOff, nowYouCanStop, stopOnOff; + bool doNote, legato, portaStop, keyOn, keyOff, nowYouCanStop, stopOnOff, releasing; bool arpYield, delayLocked, inPorta, scheduledSlideReset, shorthandPorta, wasShorthandPorta, noteOnInhibit, resetArp; bool wentThroughNote, goneThroughNote; @@ -154,6 +154,7 @@ struct DivChannelState { keyOff(false), nowYouCanStop(true), stopOnOff(false), + releasing(false), arpYield(false), delayLocked(false), inPorta(false), diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index affd720e8..eaf3f7a5e 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -591,8 +591,10 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].scheduledSlideReset=true; } dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF_ENV,i)); + chan[i].releasing=true; } else if (pat->data[whatRow][0]==102) { // env release dispatchCmd(DivCommand(DIV_CMD_ENV_RELEASE,i)); + chan[i].releasing=true; } else if (!(pat->data[whatRow][0]==0 && pat->data[whatRow][1]==0)) { chan[i].oldNote=chan[i].note; chan[i].note=pat->data[whatRow][0]+((signed char)pat->data[whatRow][1])*12; @@ -1067,6 +1069,7 @@ void DivEngine::processRow(int i, bool afterDelay) { } } else if (!chan[i].noteOnInhibit) { dispatchCmd(DivCommand(DIV_CMD_NOTE_ON,i,chan[i].note,chan[i].volume>>8)); + chan[i].releasing=false; chan[i].goneThroughNote=true; chan[i].wentThroughNote=true; keyHit[i]=true; @@ -1366,6 +1369,7 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { //dispatchCmd(DivCommand(DIV_CMD_VOLUME,note.channel,(note.volume*(chan[note.channel].volMax>>8))/127)); dispatchCmd(DivCommand(DIV_CMD_NOTE_ON,note.channel,note.note)); keyHit[note.channel]=true; + chan[note.channel].releasing=false; chan[note.channel].noteOnInhibit=true; chan[note.channel].lastIns=note.ins; } else { diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 08f5ca9f0..4fa69a16a 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -6342,7 +6342,18 @@ bool FurnaceGUI::init() { waveSigned=e->getConfBool("waveSigned",false); waveGenVisible=e->getConfBool("waveGenVisible",false); waveEditStyle=e->getConfInt("waveEditStyle",0); - extraChannelButtons=e->getConfInt("extraChannelButtons",0); + int extraChannelButtons=e->getConfInt("extraChannelButtons",0); + if (!e->hasConf("patExtraButtons")) { + patExtraButtons=(extraChannelButtons==1); + } else { + patExtraButtons=e->getConfBool("patExtraButtons",false); + } + if (!e->hasConf("patChannelNames")) { + patChannelNames=(extraChannelButtons==2); + } else { + patChannelNames=e->getConfBool("patChannelNames",false); + } + patChannelHints=e->getConfInt("patChannelHints",0); lockLayout=e->getConfBool("lockLayout",false); #ifdef IS_MOBILE fullScreen=true; @@ -6880,7 +6891,9 @@ void FurnaceGUI::commitState() { e->setConf("waveSigned",waveSigned); e->setConf("waveGenVisible",waveGenVisible); e->setConf("waveEditStyle",waveEditStyle); - e->setConf("extraChannelButtons",extraChannelButtons); + e->setConf("patExtraButtons",patExtraButtons); + e->setConf("patChannelNames",patChannelNames); + e->setConf("patChannelHints",(int)patChannelHints); e->setConf("lockLayout",lockLayout); e->setConf("fullScreen",fullScreen); e->setConf("mobileUI",mobileUI); @@ -7116,7 +7129,6 @@ FurnaceGUI::FurnaceGUI(): loopRow(-1), loopEnd(-1), isClipping(0), - extraChannelButtons(0), newSongCategory(0), latchTarget(0), wheelX(0), @@ -7131,6 +7143,10 @@ FurnaceGUI::FurnaceGUI(): exitDisabledTimer(0), soloTimeout(0.0f), exportFadeOut(5.0), + patExtraButtons(false), + patChannelNames(false), + patChannelPairs(false), + patChannelHints(0), newSongFirstFrame(false), oldRowChanged(false), editControlsOpen(true), diff --git a/src/gui/gui.h b/src/gui/gui.h index f0e2e7555..c87eafebc 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -305,6 +305,11 @@ enum FurnaceGUIColors { GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY, GUI_COLOR_PATTERN_EFFECT_MISC, + GUI_COLOR_PATTERN_STATUS_OFF, + GUI_COLOR_PATTERN_STATUS_REL, + GUI_COLOR_PATTERN_STATUS_REL_ON, + GUI_COLOR_PATTERN_STATUS_ON, + GUI_COLOR_SAMPLE_BG, GUI_COLOR_SAMPLE_FG, GUI_COLOR_SAMPLE_LOOP, @@ -1811,14 +1816,17 @@ class FurnaceGUI { DivInstrument* prevInsData; - int curIns, curWave, curSample, curOctave, curOrder, playOrder, prevIns, oldRow, editStep, exportLoops, soloChan,orderEditMode, orderCursor; - int loopOrder, loopRow, loopEnd, isClipping, extraChannelButtons, newSongCategory, latchTarget; + int curIns, curWave, curSample, curOctave, curOrder, playOrder, prevIns, oldRow, editStep, exportLoops, soloChan, orderEditMode, orderCursor; + int loopOrder, loopRow, loopEnd, isClipping, newSongCategory, latchTarget; int wheelX, wheelY, dragSourceX, dragSourceXFine, dragSourceY, dragDestinationX, dragDestinationXFine, dragDestinationY, oldBeat, oldBar; int curGroove, exitDisabledTimer; float soloTimeout; double exportFadeOut; + bool patExtraButtons, patChannelNames, patChannelPairs; + unsigned char patChannelHints; + bool newSongFirstFrame, oldRowChanged; bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen; bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen; diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index 954c29496..a4af8261d 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -988,6 +988,11 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={ D(GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY,"",ImVec4(0.0f,1.0f,0.5f,1.0f)), D(GUI_COLOR_PATTERN_EFFECT_MISC,"",ImVec4(0.3f,0.3f,1.0f,1.0f)), + D(GUI_COLOR_PATTERN_STATUS_OFF,"",ImVec4(0.2f,0.2f,0.2f,1.0f)), + D(GUI_COLOR_PATTERN_STATUS_REL,"",ImVec4(0.7f,0.1f,0.1f,1.0f)), + D(GUI_COLOR_PATTERN_STATUS_REL_ON,"",ImVec4(1.0f,0.8f,0.1f,1.0f)), + D(GUI_COLOR_PATTERN_STATUS_ON,"",ImVec4(0.3f,1.0f,0.1f,1.0f)), + D(GUI_COLOR_SAMPLE_BG,"",ImVec4(0.04f,0.13f,0.2f,1.0f)), D(GUI_COLOR_SAMPLE_FG,"",ImVec4(0.7f,0.7f,0.7f,1.0f)), D(GUI_COLOR_SAMPLE_LOOP,"",ImVec4(0.1f,0.22f,0.35f,1.0f)), diff --git a/src/gui/pattern.cpp b/src/gui/pattern.cpp index efb949867..39c38f9a3 100644 --- a/src/gui/pattern.cpp +++ b/src/gui/pattern.cpp @@ -408,6 +408,7 @@ void FurnaceGUI::drawPattern() { sel1.xFine^=sel2.xFine; sel2.xFine^=sel1.xFine; } + ImVec2 origWinPadding=ImGui::GetStyle().WindowPadding; ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0.0f,0.0f)); if (mobileUI) { patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*canvasH)+(0.12*canvasW)):ImVec2((0.16*canvasH)+0.5*canvasW*mobileMenuPos,0.0f)); @@ -465,17 +466,11 @@ void FurnaceGUI::drawPattern() { ImGui::TableNextRow(); ImGui::TableNextColumn(); float lpwStart=ImGui::GetCursorPosX(); - if (ImGui::Selectable((extraChannelButtons==2)?" --##ExtraChannelButtons":" ++##ExtraChannelButtons",false,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale))) { - if (++extraChannelButtons>2) extraChannelButtons=0; + if (ImGui::Selectable(" ++##ExtraChannelButtons",false,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale))) { + ImGui::OpenPopup("PatternOpt"); } if (ImGui::IsItemHovered() && !mobileUI) { - if (extraChannelButtons==2) { - ImGui::SetTooltip("Pattern names (click to collapse)\nRight-click for visualizer"); - } else if (extraChannelButtons==1) { - ImGui::SetTooltip("Expanded (click for pattern names)\nRight-click for visualizer"); - } else { - ImGui::SetTooltip("Compact (click to expand)\nRight-click for visualizer"); - } + ImGui::SetTooltip("click for pattern options (effect columns/pattern names/visualizer)"); } if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { fancyPattern=!fancyPattern; @@ -484,6 +479,41 @@ void FurnaceGUI::drawPattern() { e->getCommandStream(cmdStream); cmdStream.clear(); } + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,origWinPadding); + ImGui::PushFont(mainFont); + if (ImGui::BeginPopup("PatternOpt",ImGuiWindowFlags_NoMove|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings)) { + ImGui::Text("Options:"); + ImGui::Indent(); + ImGui::Checkbox("Effect columns/collapse",&patExtraButtons); + ImGui::Checkbox("Pattern names",&patChannelNames); + ImGui::Checkbox("Channel group hints",&patChannelPairs); + if (ImGui::Checkbox("Visualizer",&fancyPattern)) { + inhibitMenu=true; + e->enableCommandStream(fancyPattern); + e->getCommandStream(cmdStream); + cmdStream.clear(); + } + ImGui::Unindent(); + + ImGui::Text("Channel status:"); + ImGui::Indent(); + if (ImGui::RadioButton("No##_PCS0",patChannelHints==0)) { + patChannelHints=0; + } + if (ImGui::RadioButton("Basic##_PCS0",patChannelHints==1)) { + patChannelHints=1; + } + if (ImGui::RadioButton("Regular##_PCS0",patChannelHints==2)) { + patChannelHints=2; + } + if (ImGui::RadioButton("Detailed##_PCS0",patChannelHints==3)) { + patChannelHints=3; + } + ImGui::Unindent(); + ImGui::EndPopup(); + } + ImGui::PopFont(); + ImGui::PopStyleVar(); for (int i=0; icurSubSong->chanShow[i]) continue; ImGui::TableNextColumn(); @@ -619,7 +649,7 @@ void FurnaceGUI::drawPattern() { minLabelArea.x+=0.5f*(maxLabelArea.x-minLabelArea.x-ImGui::CalcTextSize(chanID).x); } - if (extraChannelButtons==0 || settings.channelVolStyle!=0) ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0.0f,0.0f)); + if ((!patExtraButtons && !patChannelNames && !patChannelHints) || settings.channelVolStyle!=0) ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0.0f,0.0f)); ImGui::PushID(2048+i); switch (settings.channelStyle) { @@ -735,7 +765,7 @@ void FurnaceGUI::drawPattern() { } ImGui::PopID(); - if (extraChannelButtons==0 || settings.channelVolStyle!=0) ImGui::PopStyleVar(); + if ((!patExtraButtons && !patChannelNames && !patChannelHints) || settings.channelVolStyle!=0) ImGui::PopStyleVar(); if (displayTooltip && ImGui::IsItemHovered() && !mobileUI) { ImGui::SetTooltip("%s",e->getChannelName(i)); @@ -834,15 +864,7 @@ void FurnaceGUI::drawPattern() { } // extra buttons - if (extraChannelButtons==2) { - DivPattern* pat=e->curPat[i].getPattern(e->curOrders->ord[i][ord],true); - ImGui::PushFont(mainFont); - snprintf(chanID,2048," %s##PatName%d",pat->name.c_str(),i); - if (ImGui::Selectable(chanID,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale))) { - editStr(&pat->name); - } - ImGui::PopFont(); - } else if (extraChannelButtons==1) { + if (patExtraButtons) { snprintf(chanID,2048,"%c##_HCH%d",e->curSubSong->chanCollapse[i]?'+':'-',i); ImGui::SetCursorPosX(ImGui::GetCursorPosX()+4.0f*dpiScale); if (ImGui::SmallButton(chanID)) { @@ -872,6 +894,110 @@ void FurnaceGUI::drawPattern() { } ImGui::Spacing(); } + + if (patChannelNames) { + DivPattern* pat=e->curPat[i].getPattern(e->curOrders->ord[i][ord],true); + ImGui::PushFont(mainFont); + snprintf(chanID,2048," %s##PatName%d",pat->name.c_str(),i); + if (ImGui::Selectable(chanID,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale))) { + editStr(&pat->name); + } + ImGui::PopFont(); + } + + if (patChannelHints) { + DivChannelState* cs=e->getChanState(i); + if (cs!=NULL) { + ImGui::PushFont(mainFont); + if (cs->keyOn) { + if (cs->releasing) { + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_STATUS_REL_ON])); + } else { + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_STATUS_ON])); + } + ImGui::Text(ICON_FA_SQUARE); + ImGui::PopStyleColor(); + } else { + if (cs->releasing) { + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_STATUS_REL])); + } else { + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_STATUS_OFF])); + } + ImGui::Text(ICON_FA_SQUARE); + ImGui::PopStyleColor(); + } + ImGui::PopFont(); + + if (e->curSubSong->chanCollapse[i]==0) { + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_VOLUME_MAX])); + ImGui::Text("%.2X",cs->volume>>8); + ImGui::PopStyleColor(); + + if (cs->volSpeed!=0) { + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_EFFECT_VOLUME])); + ImGui::Text("%+2d",cs->volSpeed/4); + ImGui::PopStyleColor(); + } else { + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_STATUS_OFF])); + ImGui::Text(" 00"); + ImGui::PopStyleColor(); + } + + if (cs->vibratoDepth>0) { + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH])); + ImGui::Text("~%.1X%.1X",cs->vibratoRate,cs->vibratoDepth); + ImGui::PopStyleColor(); + } else { + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_STATUS_OFF])); + ImGui::Text("~00"); + ImGui::PopStyleColor(); + } + + /* + if (cs->legato) { + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH])); + ImGui::Text("="); + ImGui::PopStyleColor(); + } else { + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_STATUS_OFF])); + ImGui::Text("="); + ImGui::PopStyleColor(); + }*/ + + if (cs->inPorta) { + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH])); + if (cs->portaNote<-60 || cs->portaNote>=120) { + ImGui::Text("???@%.2X",cs->portaSpeed); + } else { + ImGui::Text("%s@%.2X",noteNames[60+cs->portaNote],cs->portaSpeed); + } + ImGui::PopStyleColor(); + } else { + if (cs->portaSpeed>0) { + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH])); + if (cs->portaNote<60) { + ImGui::Text(" v%.2X ",cs->portaSpeed); + } else { + ImGui::Text(" ^%.2X ",cs->portaSpeed); + } + ImGui::PopStyleColor(); + } else { + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_STATUS_OFF])); + ImGui::Text(" --- "); + ImGui::PopStyleColor(); + } + } + } + } + } } ImGui::TableNextColumn(); lastPatternWidth=ImGui::GetCursorPosX()-lpwStart+ImGui::GetStyle().ScrollbarSize; diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 086793ae0..728b5bd47 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -3020,6 +3020,10 @@ void FurnaceGUI::drawSettings() { UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY,"Secondary specific effect"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_MISC,"Miscellaneous"); UI_COLOR_CONFIG(GUI_COLOR_EE_VALUE,"External command output"); + UI_COLOR_CONFIG(GUI_COLOR_PATTERN_STATUS_OFF,"Status: off"); + UI_COLOR_CONFIG(GUI_COLOR_PATTERN_STATUS_REL,"Status: off + macro rel"); + UI_COLOR_CONFIG(GUI_COLOR_PATTERN_STATUS_REL_ON,"Status: on + macro rel"); + UI_COLOR_CONFIG(GUI_COLOR_PATTERN_STATUS_ON,"Status: on"); ImGui::TreePop(); } if (ImGui::TreeNode("Sample Editor")) {