From 95b536f47e69ac3b3e5371ea5a2363db37d7913a Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 30 Dec 2025 01:45:57 -0500 Subject: [PATCH] GUI: new pattern renderer, part 2 some scrolling --- src/gui/newPattern.cpp | 237 +++++++++++++++++++++++------------------ 1 file changed, 133 insertions(+), 104 deletions(-) diff --git a/src/gui/newPattern.cpp b/src/gui/newPattern.cpp index 81b6efb87..383dc3597 100644 --- a/src/gui/newPattern.cpp +++ b/src/gui/newPattern.cpp @@ -84,7 +84,7 @@ void FurnaceGUI::drawPatternNew() { ImGui::SetNextWindowPos(patWindowPos); ImGui::SetNextWindowSize(patWindowSize); } - if (ImGui::Begin("PatternNew",&patternOpen,globalWinFlags|(settings.avoidRaisingPattern?ImGuiWindowFlags_NoBringToFrontOnFocus:0)|((settings.cursorFollowsWheel && !selecting)?ImGuiWindowFlags_NoScrollWithMouse:0),_("Pattern"))) { + if (ImGui::Begin("PatternNew",&patternOpen,globalWinFlags|ImGuiWindowFlags_HorizontalScrollbar|(settings.avoidRaisingPattern?ImGuiWindowFlags_NoBringToFrontOnFocus:0)|((settings.cursorFollowsWheel && !selecting)?ImGuiWindowFlags_NoScrollWithMouse:0),_("Pattern"))) { if (!mobileUI) { patWindowPos=ImGui::GetWindowPos(); patWindowSize=ImGui::GetWindowSize(); @@ -106,6 +106,7 @@ void FurnaceGUI::drawPatternNew() { ImGui::PushFont(patFont); float lineHeight=(ImGui::GetTextLineHeight()+2*dpiScale); + dummyRows=(ImGui::GetWindowSize().y/lineHeight)/2; // this could be moved somewhere else for performance... float oneCharSize=ImGui::CalcTextSize("A").x; @@ -128,21 +129,11 @@ void FurnaceGUI::drawPatternNew() { ImVec2 top=ImGui::GetCursorScreenPos(); ImVec2 pos=top; - ImU32 activeColor=ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_ACTIVE]); - ImU32 inactiveColor=ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_INACTIVE]); - ImU32 rowIndexColor=ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_ROW_INDEX]); + ImVec2 size=ImVec2(0.0f,lineHeight*e->curSubSong->patLen); - // row number - for (int j=0; jcurSubSong->patLen; j++) { - snprintf(id,63,"%3d",j); - dl->AddText(pos,rowIndexColor,id); - pos.y+=lineHeight; - } + size.x+=threeChars.x+oneChar.x; - top.x+=threeChars.x+oneChar.x; - pos=top; - - // channels + // TODO: simplify for (int i=0; icurSubSong->chanShow[i]) continue; int chanVolMax=e->getMaxVolumeChan(i); @@ -153,98 +144,136 @@ void FurnaceGUI::drawPatternNew() { if (e->curSubSong->chanCollapse[i]<2) thisChannelSize+=volCellSize.x; if (e->curSubSong->chanCollapse[i]<1) thisChannelSize+=(effectCellSize.x+effectValCellSize.x)*e->curSubSong->pat[i].effectCols; - // rows - for (int j=0; jcurSubSong->patLen; j++) { - const DivPattern* pat=patCache[i]; - - // note - snprintf(id,63,"%.31s",noteName(pat->newData[j][DIV_PAT_NOTE])); - if (pat->newData[j][DIV_PAT_NOTE]==-1) { - dl->AddText(pos,inactiveColor,id); - } else { - dl->AddText(pos,activeColor,id); - } - - // instrument - if (e->curSubSong->chanCollapse[i]<3) { - pos.x+=threeChars.x; - if (pat->newData[j][DIV_PAT_INS]==-1) { - dl->AddText(pos,inactiveColor,emptyLabel2); - } else { - snprintf(id,63,"%.2X",pat->newData[j][DIV_PAT_INS]); - if (pat->newData[j][DIV_PAT_INS]<0 || pat->newData[j][DIV_PAT_INS]>=e->song.insLen) { - dl->AddText(pos,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_INS_ERROR]),id); - } else { - DivInstrumentType t=e->song.ins[pat->newData[j][DIV_PAT_INS]]->type; - if (t!=DIV_INS_AMIGA && t!=e->getPreferInsType(i)) { - dl->AddText(pos,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_INS_WARN]),id); - } else { - dl->AddText(pos,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_INS]),id); - } - } - } - } - - // volume - if (e->curSubSong->chanCollapse[i]<2) { - pos.x+=twoChars.x; - if (pat->newData[j][DIV_PAT_VOL]==-1) { - dl->AddText(pos,inactiveColor,emptyLabel2); - } else { - int volColor=(pat->newData[j][DIV_PAT_VOL]*127)/chanVolMax; - if (volColor>127) volColor=127; - if (volColor<0) volColor=0; - snprintf(id,63,"%.2X",pat->newData[j][DIV_PAT_VOL]); - dl->AddText(pos,ImGui::GetColorU32(volColors[volColor]),id); - } - } - - // effects - if (e->curSubSong->chanCollapse[i]<1) { - for (int k=0; kcurPat[i].effectCols; k++) { - int index=DIV_PAT_FX(k); - int indexVal=DIV_PAT_FXVAL(k); - ImU32 effectColor=inactiveColor; - - // effect - pos.x+=twoChars.x; - if (pat->newData[j][index]==-1) { - dl->AddText(pos,inactiveColor,emptyLabel2); - } else { - if (pat->newData[j][index]>0xff) { - snprintf(id,63,"??"); - effectColor=ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]); - } else { - const unsigned char data=pat->newData[j][index]; - effectColor=ImGui::GetColorU32(uiColors[fxColors[data]]); - if (pat->newData[j][index]>=0x10 || settings.oneDigitEffects==0) { - snprintf(id,63,"%.2X",data); - } else { - snprintf(id,63," %.1X",data); - } - } - dl->AddText(pos,effectColor,id); - } - - // effect value - pos.x+=twoChars.x; - if (pat->newData[j][indexVal]==-1) { - dl->AddText(pos,effectColor,emptyLabel2); - } else { - snprintf(id,63,"%.2X",pat->newData[j][indexVal]); - dl->AddText(pos,effectColor,id); - } - } - } - - // go to next row - pos.x=top.x; - pos.y+=lineHeight; - } - top.x+=thisChannelSize; - pos=top; + size.x+=thisChannelSize; } + ImVec2 minArea=top; + ImVec2 maxArea=ImVec2( + minArea.x+size.x, + minArea.y+size.y + ); + ImRect rect=ImRect(minArea,maxArea); + + // create the view + ImGui::ItemSize(size,ImGui::GetStyle().FramePadding.y); + if (ImGui::ItemAdd(rect,ImGui::GetID("PatternView"))) { + ImU32 activeColor=ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_ACTIVE]); + ImU32 inactiveColor=ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_INACTIVE]); + ImU32 rowIndexColor=ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_ROW_INDEX]); + + // row number + for (int j=0; jcurSubSong->patLen; j++) { + snprintf(id,63,"%3d",j); + dl->AddText(pos,rowIndexColor,id); + pos.y+=lineHeight; + } + + top.x+=threeChars.x+oneChar.x; + pos=top; + + // channels + for (int i=0; icurSubSong->chanShow[i]) continue; + int chanVolMax=e->getMaxVolumeChan(i); + if (chanVolMax<1) chanVolMax=1; + + float thisChannelSize=noteCellSize.x; + if (e->curSubSong->chanCollapse[i]<3) thisChannelSize+=insCellSize.x; + if (e->curSubSong->chanCollapse[i]<2) thisChannelSize+=volCellSize.x; + if (e->curSubSong->chanCollapse[i]<1) thisChannelSize+=(effectCellSize.x+effectValCellSize.x)*e->curSubSong->pat[i].effectCols; + + // rows + for (int j=0; jcurSubSong->patLen; j++) { + const DivPattern* pat=patCache[i]; + + // note + snprintf(id,63,"%.31s",noteName(pat->newData[j][DIV_PAT_NOTE])); + if (pat->newData[j][DIV_PAT_NOTE]==-1) { + dl->AddText(pos,inactiveColor,id); + } else { + dl->AddText(pos,activeColor,id); + } + + // instrument + if (e->curSubSong->chanCollapse[i]<3) { + pos.x+=threeChars.x; + if (pat->newData[j][DIV_PAT_INS]==-1) { + dl->AddText(pos,inactiveColor,emptyLabel2); + } else { + snprintf(id,63,"%.2X",pat->newData[j][DIV_PAT_INS]); + if (pat->newData[j][DIV_PAT_INS]<0 || pat->newData[j][DIV_PAT_INS]>=e->song.insLen) { + dl->AddText(pos,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_INS_ERROR]),id); + } else { + DivInstrumentType t=e->song.ins[pat->newData[j][DIV_PAT_INS]]->type; + if (t!=DIV_INS_AMIGA && t!=e->getPreferInsType(i)) { + dl->AddText(pos,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_INS_WARN]),id); + } else { + dl->AddText(pos,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_INS]),id); + } + } + } + } + + // volume + if (e->curSubSong->chanCollapse[i]<2) { + pos.x+=twoChars.x; + if (pat->newData[j][DIV_PAT_VOL]==-1) { + dl->AddText(pos,inactiveColor,emptyLabel2); + } else { + int volColor=(pat->newData[j][DIV_PAT_VOL]*127)/chanVolMax; + if (volColor>127) volColor=127; + if (volColor<0) volColor=0; + snprintf(id,63,"%.2X",pat->newData[j][DIV_PAT_VOL]); + dl->AddText(pos,ImGui::GetColorU32(volColors[volColor]),id); + } + } + + // effects + if (e->curSubSong->chanCollapse[i]<1) { + for (int k=0; kcurPat[i].effectCols; k++) { + int index=DIV_PAT_FX(k); + int indexVal=DIV_PAT_FXVAL(k); + ImU32 effectColor=inactiveColor; + + // effect + pos.x+=twoChars.x; + if (pat->newData[j][index]==-1) { + dl->AddText(pos,inactiveColor,emptyLabel2); + } else { + if (pat->newData[j][index]>0xff) { + snprintf(id,63,"??"); + effectColor=ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]); + } else { + const unsigned char data=pat->newData[j][index]; + effectColor=ImGui::GetColorU32(uiColors[fxColors[data]]); + if (pat->newData[j][index]>=0x10 || settings.oneDigitEffects==0) { + snprintf(id,63,"%.2X",data); + } else { + snprintf(id,63," %.1X",data); + } + } + dl->AddText(pos,effectColor,id); + } + + // effect value + pos.x+=twoChars.x; + if (pat->newData[j][indexVal]==-1) { + dl->AddText(pos,effectColor,emptyLabel2); + } else { + snprintf(id,63,"%.2X",pat->newData[j][indexVal]); + dl->AddText(pos,effectColor,id); + } + } + } + + // go to next row + pos.x=top.x; + pos.y+=lineHeight; + } + top.x+=thisChannelSize; + pos=top; + } + } ImGui::PopFont(); } ImGui::PopStyleVar();