GUI: add ability to see previous orders in the pattern

editor

closes #161
This commit is contained in:
tildearrow 2022-02-17 02:44:17 -05:00
parent 810ee33d11
commit 09144b95f9
2 changed files with 366 additions and 240 deletions

View file

@ -3103,6 +3103,246 @@ void FurnaceGUI::drawVolMeter() {
ImGui::End();
}
// draw a pattern row
inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int chans, int ord) {
static char id[32];
bool selectedRow=(i>=sel1.y && i<=sel2.y);
ImGui::TableNextRow(0,lineHeight);
ImGui::TableNextColumn();
float cursorPosY=ImGui::GetCursorPos().y-ImGui::GetScrollY();
// check if the row is visible
if (cursorPosY<-lineHeight || cursorPosY>ImGui::GetWindowSize().y) {
return;
}
// check if we are in range
if (ord<0 || ord>=e->song.ordersLen) {
return;
}
if (i<0 || i>=e->song.patLen) {
return;
}
// check overflow highlight
if (settings.overflowHighlight) {
if (edit && cursor.y==i) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,ImGui::GetColorU32(uiColors[GUI_COLOR_EDITING]));
} else if (isPlaying && oldRow==i) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,0x40ffffff);
} else if (e->song.hilightB>0 && !(i%e->song.hilightB)) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_2]));
} else if (e->song.hilightA>0 && !(i%e->song.hilightA)) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_1]));
}
}
// row number
if (settings.patRowsBase==1) {
ImGui::TextColored(uiColors[GUI_COLOR_PATTERN_ROW_INDEX]," %.2X ",i);
} else {
ImGui::TextColored(uiColors[GUI_COLOR_PATTERN_ROW_INDEX],"%3d ",i);
}
// for each column
for (int j=0; j<chans; j++) {
// check if channel is not hidden
if (!e->song.chanShow[j]) {
patChanX[j]=ImGui::GetCursorPosX();
continue;
}
int chanVolMax=e->getMaxVolumeChan(j);
if (chanVolMax<1) chanVolMax=1;
DivPattern* pat=e->song.pat[j].getPattern(e->song.orders.ord[j][ord],true);
ImGui::TableNextColumn();
patChanX[j]=ImGui::GetCursorPosX();
// check overflow highlight
if (!settings.overflowHighlight) {
if (edit && cursor.y==i) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(uiColors[GUI_COLOR_EDITING]));
} else if (isPlaying && oldRow==i) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,0x40ffffff);
} else if (e->song.hilightB>0 && !(i%e->song.hilightB)) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_2]));
} else if (e->song.hilightA>0 && !(i%e->song.hilightA)) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_1]));
}
}
// selection highlight flags
int sel1XSum=sel1.xCoarse*32+sel1.xFine;
int sel2XSum=sel2.xCoarse*32+sel2.xFine;
int j32=j*32;
bool selectedNote=selectedRow && (j32>=sel1XSum && j32<=sel2XSum);
bool selectedIns=selectedRow && (j32+1>=sel1XSum && j32+1<=sel2XSum);
bool selectedVol=selectedRow && (j32+2>=sel1XSum && j32+2<=sel2XSum);
bool cursorNote=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==0);
bool cursorIns=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==1);
bool cursorVol=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==2);
// note
sprintf(id,"%s##PN_%d_%d",noteName(pat->data[i][0],pat->data[i][1]),i,j);
if (pat->data[i][0]==0 && pat->data[i][1]==0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INACTIVE]);
} else {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_ACTIVE]);
}
if (cursorNote) {
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedNote,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
}
if (ImGui::IsItemClicked()) {
startSelection(j,0,i);
}
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,0,i);
}
ImGui::PopStyleColor();
// the following is only visible when the channel is not collapsed
if (!e->song.chanCollapse[j]) {
// instrument
if (pat->data[i][2]==-1) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INACTIVE]);
sprintf(id,"..##PI_%d_%d",i,j);
} else {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INS]);
sprintf(id,"%.2X##PI_%d_%d",pat->data[i][2],i,j);
}
ImGui::SameLine(0.0f,0.0f);
if (cursorIns) {
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedIns,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
}
if (ImGui::IsItemClicked()) {
startSelection(j,1,i);
}
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,1,i);
}
ImGui::PopStyleColor();
// volume
if (pat->data[i][3]==-1) {
sprintf(id,"..##PV_%d_%d",i,j);
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INACTIVE]);
} else {
int volColor=(pat->data[i][3]*127)/chanVolMax;
if (volColor>127) volColor=127;
if (volColor<0) volColor=0;
sprintf(id,"%.2X##PV_%d_%d",pat->data[i][3],i,j);
ImGui::PushStyleColor(ImGuiCol_Text,volColors[volColor]);
}
ImGui::SameLine(0.0f,0.0f);
if (cursorVol) {
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedVol,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
}
if (ImGui::IsItemClicked()) {
startSelection(j,2,i);
}
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,2,i);
}
ImGui::PopStyleColor();
// effects
for (int k=0; k<e->song.pat[j].effectRows; k++) {
int index=4+(k<<1);
bool selectedEffect=selectedRow && (j32+index-1>=sel1XSum && j32+index-1<=sel2XSum);
bool selectedEffectVal=selectedRow && (j32+index>=sel1XSum && j32+index<=sel2XSum);
bool cursorEffect=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==index-1);
bool cursorEffectVal=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==index);
// effect
if (pat->data[i][index]==-1) {
sprintf(id,"..##PE%d_%d_%d",k,i,j);
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INACTIVE]);
} else {
sprintf(id,"%.2X##PE%d_%d_%d",pat->data[i][index],k,i,j);
if (pat->data[i][index]<0x10) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[fxColors[pat->data[i][index]]]);
} else if (pat->data[i][index]<0x20) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY]);
} else if (pat->data[i][index]<0x30) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY]);
} else if (pat->data[i][index]<0x48) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY]);
} else if (pat->data[i][index]<0xc0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
} else if (pat->data[i][index]<0xd0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SPEED]);
} else if (pat->data[i][index]<0xe0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
} else if (pat->data[i][index]<0xf0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[extFxColors[pat->data[i][index]-0xe0]]);
} else {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
}
}
ImGui::SameLine(0.0f,0.0f);
if (cursorEffect) {
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedEffect,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
}
if (ImGui::IsItemClicked()) {
startSelection(j,index-1,i);
}
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,index-1,i);
}
// effect value
if (pat->data[i][index+1]==-1) {
sprintf(id,"..##PF%d_%d_%d",k,i,j);
} else {
sprintf(id,"%.2X##PF%d_%d_%d",pat->data[i][index+1],k,i,j);
}
ImGui::SameLine(0.0f,0.0f);
if (cursorEffectVal) {
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedEffectVal,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
}
if (ImGui::IsItemClicked()) {
startSelection(j,index,i);
}
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,index,i);
}
ImGui::PopStyleColor();
}
}
}
ImGui::TableNextColumn();
patChanX[chans]=ImGui::GetCursorPosX();
}
void FurnaceGUI::drawPattern() {
if (nextWindow==GUI_WINDOW_PATTERN) {
patternOpen=true;
@ -3111,9 +3351,9 @@ void FurnaceGUI::drawPattern() {
}
if (!patternOpen) return;
if (e->isPlaying() && followPattern) cursor.y=oldRow;
int demandX=0;
SelectionPoint sel1=selStart;
SelectionPoint sel2=selEnd;
demandX=0;
sel1=selStart;
sel2=selEnd;
if (sel2.y<sel1.y) {
sel2.y^=sel1.y;
sel1.y^=sel2.y;
@ -3137,9 +3377,9 @@ void FurnaceGUI::drawPattern() {
//ImGui::SetWindowSize(ImVec2(scrW*dpiScale,scrH*dpiScale));
patWindowPos=ImGui::GetWindowPos();
patWindowSize=ImGui::GetWindowSize();
char id[32];
//char id[32];
ImGui::PushFont(patFont);
unsigned char ord=e->isPlaying()?oldOrder:e->getOrder();
int ord=e->isPlaying()?oldOrder:e->getOrder();
oldOrder=e->getOrder();
int chans=e->getTotalChannelCount();
int displayChans=0;
@ -3277,236 +3517,41 @@ void FurnaceGUI::drawPattern() {
ImGui::TextColored(uiColors[GUI_COLOR_EE_VALUE]," %.2X",e->getExtValue());
}
float oneCharSize=ImGui::CalcTextSize("A").x;
ImVec2 threeChars=ImVec2(oneCharSize*3.0f,lineHeight);
ImVec2 twoChars=ImVec2(oneCharSize*2.0f,lineHeight);
threeChars=ImVec2(oneCharSize*3.0f,lineHeight);
twoChars=ImVec2(oneCharSize*2.0f,lineHeight);
//ImVec2 oneChar=ImVec2(oneCharSize,lineHeight);
int dummyRows=(ImGui::GetWindowSize().y/lineHeight)/2;
for (int i=0; i<dummyRows-1; i++) {
ImGui::TableNextRow(0,lineHeight);
ImGui::TableNextColumn();
}
for (int i=0; i<e->song.patLen; i++) {
bool selectedRow=(i>=sel1.y && i<=sel2.y);
ImGui::TableNextRow(0,lineHeight);
if ((lineHeight*(i+dummyRows+1))-ImGui::GetScrollY()<0) {
continue;
dummyRows=(ImGui::GetWindowSize().y/lineHeight)/2;
// オップナー2608 i owe you one more for this horrible code
// previous pattern
ImGui::BeginDisabled();
if (settings.viewPrevPattern) {
for (int i=0; i<dummyRows-1; i++) {
patternRow(e->song.patLen+i-dummyRows+1,e->isPlaying(),lineHeight,chans,ord-1);
}
if ((lineHeight*(i+dummyRows))-ImGui::GetScrollY()>ImGui::GetWindowSize().y) {
continue;
}
ImGui::TableNextColumn();
bool isPlaying=e->isPlaying();
if (settings.overflowHighlight) {
if (edit && cursor.y==i) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,ImGui::GetColorU32(uiColors[GUI_COLOR_EDITING]));
} else if (isPlaying && oldRow==i) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,0x40ffffff);
} else if (e->song.hilightB>0 && !(i%e->song.hilightB)) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_2]));
} else if (e->song.hilightA>0 && !(i%e->song.hilightA)) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_1]));
}
}
if (settings.patRowsBase==1) {
ImGui::TextColored(uiColors[GUI_COLOR_PATTERN_ROW_INDEX]," %.2X ",i);
} else {
ImGui::TextColored(uiColors[GUI_COLOR_PATTERN_ROW_INDEX],"%3d ",i);
}
for (int j=0; j<chans; j++) {
if (!e->song.chanShow[j]) {
patChanX[j]=ImGui::GetCursorPosX();
continue;
}
int chanVolMax=e->getMaxVolumeChan(j);
if (chanVolMax<1) chanVolMax=1;
DivPattern* pat=e->song.pat[j].getPattern(e->song.orders.ord[j][ord],true);
} else {
for (int i=0; i<dummyRows-1; i++) {
ImGui::TableNextRow(0,lineHeight);
ImGui::TableNextColumn();
patChanX[j]=ImGui::GetCursorPosX();
if (!settings.overflowHighlight) {
if (edit && cursor.y==i) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(uiColors[GUI_COLOR_EDITING]));
} else if (isPlaying && oldRow==i) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,0x40ffffff);
} else if (e->song.hilightB>0 && !(i%e->song.hilightB)) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_2]));
} else if (e->song.hilightA>0 && !(i%e->song.hilightA)) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_1]));
}
}
int sel1XSum=sel1.xCoarse*32+sel1.xFine;
int sel2XSum=sel2.xCoarse*32+sel2.xFine;
int j32=j*32;
bool selectedNote=selectedRow && (j32>=sel1XSum && j32<=sel2XSum);
bool selectedIns=selectedRow && (j32+1>=sel1XSum && j32+1<=sel2XSum);
bool selectedVol=selectedRow && (j32+2>=sel1XSum && j32+2<=sel2XSum);
bool cursorNote=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==0);
bool cursorIns=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==1);
bool cursorVol=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==2);
sprintf(id,"%s##PN_%d_%d",noteName(pat->data[i][0],pat->data[i][1]),i,j);
if (pat->data[i][0]==0 && pat->data[i][1]==0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INACTIVE]);
} else {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_ACTIVE]);
}
if (cursorNote) {
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedNote,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
}
if (ImGui::IsItemClicked()) {
startSelection(j,0,i);
}
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
//ImGui::SetTooltip("N: %d O: %d",pat->data[i][0],pat->data[i][1]);
updateSelection(j,0,i);
}
ImGui::PopStyleColor();
if (!e->song.chanCollapse[j]) {
if (pat->data[i][2]==-1) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INACTIVE]);
sprintf(id,"..##PI_%d_%d",i,j);
} else {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INS]);
sprintf(id,"%.2X##PI_%d_%d",pat->data[i][2],i,j);
}
ImGui::SameLine(0.0f,0.0f);
if (cursorIns) {
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedIns,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
}
if (ImGui::IsItemClicked()) {
startSelection(j,1,i);
}
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,1,i);
}
ImGui::PopStyleColor();
if (pat->data[i][3]==-1) {
sprintf(id,"..##PV_%d_%d",i,j);
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INACTIVE]);
} else {
int volColor=(pat->data[i][3]*127)/chanVolMax;
if (volColor>127) volColor=127;
if (volColor<0) volColor=0;
sprintf(id,"%.2X##PV_%d_%d",pat->data[i][3],i,j);
ImGui::PushStyleColor(ImGuiCol_Text,volColors[volColor]);
}
ImGui::SameLine(0.0f,0.0f);
if (cursorVol) {
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedVol,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
}
if (ImGui::IsItemClicked()) {
startSelection(j,2,i);
}
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,2,i);
}
ImGui::PopStyleColor();
for (int k=0; k<e->song.pat[j].effectRows; k++) {
int index=4+(k<<1);
bool selectedEffect=selectedRow && (j32+index-1>=sel1XSum && j32+index-1<=sel2XSum);
bool selectedEffectVal=selectedRow && (j32+index>=sel1XSum && j32+index<=sel2XSum);
bool cursorEffect=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==index-1);
bool cursorEffectVal=(cursor.y==i && cursor.xCoarse==j && cursor.xFine==index);
if (pat->data[i][index]==-1) {
sprintf(id,"..##PE%d_%d_%d",k,i,j);
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_INACTIVE]);
} else {
sprintf(id,"%.2X##PE%d_%d_%d",pat->data[i][index],k,i,j);
if (pat->data[i][index]<0x10) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[fxColors[pat->data[i][index]]]);
} else if (pat->data[i][index]<0x20) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY]);
} else if (pat->data[i][index]<0x30) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY]);
} else if (pat->data[i][index]<0x48) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY]);
} else if (pat->data[i][index]<0xc0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
} else if (pat->data[i][index]<0xd0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SPEED]);
} else if (pat->data[i][index]<0xe0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
} else if (pat->data[i][index]<0xf0) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[extFxColors[pat->data[i][index]-0xe0]]);
} else {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]);
}
}
ImGui::SameLine(0.0f,0.0f);
if (cursorEffect) {
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedEffect,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
}
if (ImGui::IsItemClicked()) {
startSelection(j,index-1,i);
}
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,index-1,i);
}
if (pat->data[i][index+1]==-1) {
sprintf(id,"..##PF%d_%d_%d",k,i,j);
} else {
sprintf(id,"%.2X##PF%d_%d_%d",pat->data[i][index+1],k,i,j);
}
ImGui::SameLine(0.0f,0.0f);
if (cursorEffectVal) {
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_CURSOR]);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_CURSOR_ACTIVE]);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_CURSOR_HOVER]);
ImGui::Selectable(id,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedEffectVal,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
}
if (ImGui::IsItemClicked()) {
startSelection(j,index,i);
}
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
updateSelection(j,index,i);
}
ImGui::PopStyleColor();
}
}
}
ImGui::TableNextColumn();
patChanX[chans]=ImGui::GetCursorPosX();
}
for (int i=0; i<=dummyRows; i++) {
ImGui::TableNextRow(0,lineHeight);
ImGui::TableNextColumn();
ImGui::EndDisabled();
// active area
for (int i=0; i<e->song.patLen; i++) {
patternRow(i,e->isPlaying(),lineHeight,chans,ord);
}
// next pattern
ImGui::BeginDisabled();
if (settings.viewPrevPattern) {
for (int i=0; i<=dummyRows; i++) {
patternRow(i,e->isPlaying(),lineHeight,chans,ord+1);
}
} else {
for (int i=0; i<=dummyRows; i++) {
ImGui::TableNextRow(0,lineHeight);
ImGui::TableNextColumn();
}
}
ImGui::EndDisabled();
oldRow=curRow;
if (demandScrollX) {
int totalDemand=demandX-ImGui::GetScrollX();
@ -3528,33 +3573,102 @@ void FurnaceGUI::drawPattern() {
// commands
for (DivCommand& i: cmdStream) {
if (i.cmd==DIV_CMD_PITCH) continue;
if (i.cmd==DIV_CMD_NOTE_PORTA) continue;
//if (i.cmd==DIV_CMD_NOTE_ON) continue;
if (i.cmd==DIV_CMD_PRE_NOTE) continue;
if (i.cmd==DIV_CMD_INSTRUMENT) continue;
if (i.cmd==DIV_CMD_SAMPLE_BANK) continue;
float width=patChanX[i.chan+1]-patChanX[i.chan];
float speedX=0.0f;
float speedY=-18.0f;
float grav=0.6f;
float frict=1.0f;
float life=255.0f;
float lifeSpeed=8.0f;
float spread=5.0f;
int num=3;
const char* partIcon=ICON_FA_MICROCHIP;
ImU32* color=noteGrad;
if (i.cmd==DIV_CMD_VOLUME) {
speedY=-18.0f-(10.0f*((float)i.value/(float)e->getMaxVolumeChan(i.chan)));
partIcon=ICON_FA_VOLUME_UP;
num=12.0f*((float)i.value/(float)e->getMaxVolumeChan(i.chan));
switch (i.cmd) {
case DIV_CMD_NOTE_ON:
partIcon=ICON_FA_ASTERISK;
life=64.0f;
lifeSpeed=2.0f;
break;
case DIV_CMD_LEGATO:
partIcon=ICON_FA_COG;
color=insGrad;
life=64.0f;
lifeSpeed=2.0f;
break;
case DIV_CMD_NOTE_OFF:
case DIV_CMD_NOTE_OFF_ENV:
case DIV_CMD_ENV_RELEASE:
partIcon=ICON_FA_ASTERISK;
speedX=0.0f;
speedY=0.0f;
grav=0.0f;
life=24.0f;
lifeSpeed=4.0f;
break;
case DIV_CMD_VOLUME:
speedY=-18.0f-(10.0f*((float)i.value/(float)e->getMaxVolumeChan(i.chan)));
partIcon=ICON_FA_VOLUME_UP;
num=12.0f*((float)i.value/(float)e->getMaxVolumeChan(i.chan));
color=volGrad;
break;
case DIV_CMD_PANNING: {
if (i.value==0) {
num=0;
break;
}
float ratio=float(((i.value>>4)&15)-(i.value&15))/MAX(((i.value>>4)&15),(i.value&15));
speedX=-22.0f*sin(ratio*M_PI*0.5);
speedY=-22.0f*cos(ratio*M_PI*0.5);
spread=5.0f+fabs(sin(ratio*M_PI*0.5))*7.0f;
grav=0.0f;
frict=0.96f;
if (((i.value>>4)&15)==(i.value&15)) {
partIcon=ICON_FA_ARROWS_H;
} else if (ratio>0) {
partIcon=ICON_FA_ARROW_LEFT;
} else {
partIcon=ICON_FA_ARROW_RIGHT;
}
num=9;
color=panGrad;
break;
}
case DIV_CMD_SAMPLE_FREQ:
speedX=0.0f;
speedY=0.0f;
grav=0.0f;
frict=0.98;
spread=19.0f;
life=128.0f;
lifeSpeed=3.0f;
color=sysCmd2Grad;
num=10+pow(i.value,0.6);
break;
default:
color=sysCmd1Grad;
break;
}
for (int j=0; j<num; j++) {
particles.push_back(Particle(
noteGrad,
color,
partIcon,
off.x+patChanX[i.chan]+fmod(rand(),width),
off.y+(ImGui::GetWindowHeight()*0.5f)+randRange(0,patFont->FontSize),
randRange(-5,5),
speedY+randRange(-5,5),
0.6f,
1.0f,
255.0f,
8.0f
speedX+randRange(-spread,spread),
speedY+randRange(-spread,spread),
grav,
frict,
life-randRange(0,8),
lifeSpeed
));
}
}
@ -4139,6 +4253,11 @@ void FurnaceGUI::drawSettings() {
settings.overflowHighlight=overflowHighlightB;
}
bool viewPrevPatternB=settings.viewPrevPattern;
if (ImGui::Checkbox("Display previous/next pattern",&viewPrevPatternB)) {
settings.viewPrevPattern=viewPrevPatternB;
}
bool germanNotationB=settings.germanNotation;
if (ImGui::Checkbox("Use German notation",&germanNotationB)) {
settings.germanNotation=germanNotationB;

View file

@ -592,6 +592,11 @@ class FurnaceGUI {
ImVec2 patWindowPos, patWindowSize;
// pattern view specific
ImVec2 threeChars, twoChars;
SelectionPoint sel1, sel2;
int dummyRows, demandX;
int oldOrdersLen;
DivOrders oldOrders;
DivPattern* oldPat[128];
@ -606,6 +611,8 @@ class FurnaceGUI {
void updateWindowTitle();
void prepareLayout();
void patternRow(int i, bool isPlaying, float lineHeight, int chans, int ord);
void drawEditControls();
void drawSongInfo();
void drawOrders();