new mixer part 2

separate each "channel" into a group function, prepare vol meters
This commit is contained in:
Eknous-P 2025-10-07 15:46:21 +04:00
parent bc2505ea13
commit 22f0b3f4e6
3 changed files with 78 additions and 17 deletions

View file

@ -2876,6 +2876,7 @@ class FurnaceGUI {
bool NoteSelector(int* value, bool showOffRel, int octaveMin=-5, int octaveMax=9);
// mixer stuff
bool chipMixer(int which, ImVec2 size=ImVec2(0.0f,0.0f));
ImVec2 calcPortSetSize(String label, int ins, int outs);
bool portSet(String label, unsigned int portSetID, int ins, int outs, int activeIns, int activeOuts, int& clickedPort, std::map<unsigned int,ImVec2>& portPos);
@ -2984,8 +2985,10 @@ class FurnaceGUI {
void drawTutorial();
void drawXYOsc();
void drawUserPresets();
float drawSystemChannelInfo(const DivSysDef* whichDef, int keyHitOffset=-1, float width=-1.0f);
void drawSystemChannelInfoText(const DivSysDef* whichDef);
void drawVolMeterInternal(ImDrawList* dl, ImRect rect, float* data, int chans);
void assignActionMap(std::map<int,int>& actionMap, int first, int last);
void drawKeybindSettingsTableRow(FurnaceGUIActions actionIdx);

View file

@ -235,23 +235,7 @@ void FurnaceGUI::drawMixer() {
if (ImGui::BeginChild("##mixerPerChipContainer",ImGui::GetContentRegionAvail())) {
const float childWidth=60*dpiScale;
for (int i=0; i<e->song.systemLen; i++) {
ImGui::PushID(i);
if (ImGui::BeginChild(fmt::sprintf("##MixerChip%d", i).c_str(), ImVec2(childWidth,0))) {
float textHeight=ImGui::GetFontSize();
ImGui::ScrollText(ImGui::GetID(i),fmt::sprintf("%d. %s",i+1,getSystemName(e->song.system[i])).c_str(),ImGui::GetCursorPos(),ImVec2(childWidth,textHeight));
ImGui::Dummy(ImVec2(childWidth,textHeight));
float volSliderHeight=ImGui::GetContentRegionAvail().y-ImGui::GetStyle().FramePadding.y*7-textHeight*2;
// ImGui::PushStyleColor(ImGuiCol_FrameBg,0);
// ImGui::PushStyleColor(ImGuiCol_FrameBgActive,0);
ImGui::VSliderFloat("##mixerVol", ImVec2(childWidth,volSliderHeight), &e->song.systemVol[i], 0.0f, 2.0f);
// ImGui::PopStyleColor(2);
ImGui::SetNextItemWidth(childWidth);
ImGui::SliderFloat("##mixerPan", &e->song.systemPan[i], -1.0f, 1.0f);
ImGui::SetNextItemWidth(childWidth);
ImGui::SliderFloat("##mixerPanFR", &e->song.systemPanFR[i], -1.0f, 1.0f);
}
ImGui::EndChild();
ImGui::PopID();
if (chipMixer(i, ImVec2(childWidth, ImGui::GetContentRegionAvail().y))) MARK_MODIFIED;
ImGui::SameLine();
}
}
@ -420,3 +404,32 @@ void FurnaceGUI::drawMixer() {
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_MIXER;
ImGui::End();
}
bool FurnaceGUI::chipMixer(int which, ImVec2 size) {
bool ret=false;
ImGui::PushID(which);
ImGui::BeginGroup();
float textHeight=ImGui::GetFontSize();
float volSliderHeight=size.y-ImGui::GetStyle().FramePadding.y*8-textHeight*3;
// TODO: per-chip per-out peak
float vol[2];
ImVec2 pos=ImGui::GetWindowPos()+ImGui::GetCursorPos();
drawVolMeterInternal(ImGui::GetWindowDrawList(),ImRect(pos,pos+ImVec2(size.x,volSliderHeight)),vol,2);
ImGui::PushStyleColor(ImGuiCol_FrameBg,0);
ImGui::PushStyleColor(ImGuiCol_FrameBgActive,0);
if (ImGui::VSliderFloat("##ChipVol", ImVec2(size.x,volSliderHeight), &e->song.systemVol[which], 0.0f, 2.0f)) ret=true;
ImGui::PopStyleColor(2);
ImGui::SetNextItemWidth(size.x);
if (ImGui::SliderFloat("##ChipPan", &e->song.systemPan[which], -1.0f, 1.0f)) ret=true;
ImGui::SetNextItemWidth(size.x);
if (ImGui::SliderFloat("##ChipPanFR", &e->song.systemPanFR[which], -1.0f, 1.0f)) ret=true;
ImGui::ScrollText(ImGui::GetID(which),fmt::sprintf("%d. %s",which+1,getSystemName(e->song.system[which])).c_str(),ImGui::GetCursorPos(),ImVec2(size.x,textHeight));
ImGui::Dummy(ImVec2(size.x,textHeight));
ImGui::EndGroup();
ImGui::PopID();
return ret;
}

View file

@ -102,3 +102,48 @@ void FurnaceGUI::drawVolMeter() {
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_VOL_METER;
ImGui::End();
}
void FurnaceGUI::drawVolMeterInternal(ImDrawList* dl, ImRect rect, float* data, int chans) {
bool aspectRatio=(ImGui::GetWindowSize().x/ImGui::GetWindowSize().y)>1.0;
ImU32 lowColor=ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_LOW]);
ImGuiStyle& style=ImGui::GetStyle();
ImGui::RenderFrame(rect.Min,rect.Max,ImGui::GetColorU32(ImGuiCol_FrameBg),true,style.FrameRounding);
int isClipping=0;
for (int i=0; i<chans; i++) {
float logPeak=(20*log10(data[i])/36.0);
if (logPeak==NAN) logPeak=0.0;
if (logPeak<-1.0) logPeak=-1.0;
if (logPeak>0.0) {
isClipping=8;
logPeak=0.0;
}
logPeak+=1.0;
ImU32 highColor=ImGui::GetColorU32(
ImLerp(uiColors[GUI_COLOR_VOLMETER_LOW],uiColors[GUI_COLOR_VOLMETER_HIGH],logPeak)
);
ImRect s;
if (aspectRatio) {
s=ImRect(
ImLerp(rect.Min,rect.Max,ImVec2(0,float(i)/chans)),
ImLerp(rect.Min,rect.Max,ImVec2(logPeak,float(i+1)/chans))
);
if (i!=(chans-1)) s.Max.y-=dpiScale;
if (isClipping) {
dl->AddRectFilled(s.Min,s.Max,ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_PEAK]));
} else {
dl->AddRectFilledMultiColor(s.Min,s.Max,lowColor,highColor,highColor,lowColor);
}
} else {
s=ImRect(
ImLerp(rect.Min,rect.Max,ImVec2(float(i)/chans,1.0-logPeak)),
ImLerp(rect.Min,rect.Max,ImVec2(float(i+1)/chans,1.0))
);
if (i!=(chans-1)) s.Max.x-=dpiScale;
if (isClipping) {
dl->AddRectFilled(s.Min,s.Max,ImGui::GetColorU32(uiColors[GUI_COLOR_VOLMETER_PEAK]));
} else {
dl->AddRectFilledMultiColor(s.Min,s.Max,highColor,highColor,lowColor,lowColor);
}
}
}
}