furnace/src/gui/mixer.cpp

504 lines
19 KiB
C++
Raw Normal View History

/**
* Furnace Tracker - multi-system chiptune tracker
2025-01-28 18:49:19 -05:00
* Copyright (C) 2021-2025 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "gui.h"
#include "intConst.h"
2023-01-07 19:46:57 -05:00
#include <fmt/printf.h>
2023-02-24 03:24:17 -05:00
#include <imgui.h>
2023-01-08 19:23:17 -05:00
#include "../ta-log.h"
2023-01-07 19:46:57 -05:00
#include "imgui_internal.h"
2023-01-08 19:23:17 -05:00
const char* portNamesStereo[2]={
2024-05-26 19:31:17 -05:00
_N("left"),
_N("right")
2023-01-08 19:23:17 -05:00
};
2023-01-10 19:09:26 -05:00
ImVec2 FurnaceGUI::calcPortSetSize(String label, int ins, int outs) {
ImGuiStyle& style=ImGui::GetStyle();
ImVec2 labelSize=ImGui::CalcTextSize(label.c_str(),NULL,false,ImGui::GetWindowSize().x*0.6f);
ImVec2 size=labelSize;
// pad
size.x+=style.FramePadding.x*2.0f;
size.y+=style.FramePadding.y*2.0f;
// space for ports
size.y+=MAX(ins,outs)*(labelSize.y+style.FramePadding.y+style.ItemSpacing.y);
return size;
}
2023-01-08 19:23:17 -05:00
bool FurnaceGUI::portSet(String label, unsigned int portSetID, int ins, int outs, int activeIns, int activeOuts, int& clickedPort, std::map<unsigned int,ImVec2>& portPos) {
2023-01-07 19:46:57 -05:00
String portID=fmt::sprintf("portSet%.4x",portSetID);
ImDrawList* dl=ImGui::GetWindowDrawList();
ImGuiWindow* window=ImGui::GetCurrentWindow();
ImGuiStyle& style=ImGui::GetStyle();
2023-01-10 19:09:26 -05:00
ImVec2 labelSize=ImGui::CalcTextSize(label.c_str(),NULL,false,ImGui::GetWindowSize().x*0.6f);
2023-01-07 19:46:57 -05:00
ImVec2 size=labelSize;
// pad
size.x+=style.FramePadding.x*2.0f;
size.y+=style.FramePadding.y*2.0f;
// space for ports
2023-01-10 19:09:26 -05:00
size.y+=MAX(ins,outs)*(ImGui::GetFontSize()+style.FramePadding.y+style.ItemSpacing.y);
2023-01-07 19:46:57 -05:00
ImVec4 portSetBorderColor=uiColors[GUI_COLOR_PATCHBAY_PORTSET];
ImVec4 portSetColor=ImVec4(
portSetBorderColor.x*0.75f,
portSetBorderColor.y*0.75f,
portSetBorderColor.z*0.75f,
portSetBorderColor.w
);
ImVec4 portBorderColor=uiColors[GUI_COLOR_PATCHBAY_PORT];
ImVec4 portColor=ImVec4(
portBorderColor.x*0.75f,
portBorderColor.y*0.75f,
portBorderColor.z*0.75f,
portBorderColor.w
);
2023-01-11 13:37:26 -05:00
ImVec4 portBorderColorH=uiColors[GUI_COLOR_PATCHBAY_PORT_HIDDEN];
ImVec4 portColorH=ImVec4(
portBorderColorH.x*0.75f,
portBorderColorH.y*0.75f,
portBorderColorH.z*0.75f,
portBorderColorH.w
);
2023-01-07 19:46:57 -05:00
ImVec2 minArea=window->DC.CursorPos;
ImVec2 maxArea=ImVec2(
minArea.x+size.x,
minArea.y+size.y
);
ImRect rect=ImRect(minArea,maxArea);
ImVec2 textPos=ImVec2(
minArea.x+style.FramePadding.x,
minArea.y+style.FramePadding.y
);
ImGui::ItemSize(size,style.FramePadding.y);
bool visible=ImGui::ItemAdd(rect,ImGui::GetID(portID.c_str()));
bool hovered=false;
bool active=false;
if (visible) {
hovered=ImGui::ItemHoverable(rect,ImGui::GetID(portID.c_str()),0);
active=(hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left));
2023-01-08 19:23:17 -05:00
2023-01-12 03:56:18 -05:00
if (hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
ImGui::OpenPopup("SubPortOptions");
selectedPortSet=portSetID;
clickedPort=-1;
}
2023-01-08 19:23:17 -05:00
if (hovered) hoveredPortSet=portSetID;
2023-01-08 19:23:17 -05:00
if (active) clickedPort=-1;
2023-01-07 19:46:57 -05:00
// label
dl->AddRectFilled(minArea,maxArea,ImGui::GetColorU32(portSetColor),0.0f);
2023-01-12 03:56:18 -05:00
dl->AddRect(minArea,maxArea,ImGui::GetColorU32((selectedPortSet==portSetID)?uiColors[GUI_COLOR_TEXT]:portSetBorderColor),0.0f,0,dpiScale);
2023-01-10 19:09:26 -05:00
dl->AddText(ImGui::GetFont(),ImGui::GetFontSize(),textPos,ImGui::GetColorU32(uiColors[GUI_COLOR_TEXT]),label.c_str(),NULL,ImGui::GetWindowSize().x*0.6f);
}
2023-01-07 19:46:57 -05:00
// input ports
for (int i=0; i<ins; i++) {
2024-05-26 19:31:17 -05:00
String portLabel=_("input");
String subPortID=fmt::sprintf("subPort%.5x",(portSetID<<4)|i);
if (ins==2) {
2024-05-26 19:31:17 -05:00
portLabel=_(portNamesStereo[i&1]);
} else if (ins>2) {
portLabel=fmt::sprintf("%d",i+1);
}
ImVec2 portLabelSize=ImGui::CalcTextSize(portLabel.c_str());
ImVec2 portMin=ImVec2(
minArea.x,
minArea.y+style.FramePadding.y+labelSize.y+style.ItemSpacing.y+(style.ItemSpacing.y+portLabelSize.y+style.FramePadding.y)*i
);
ImVec2 portMax=ImVec2(
minArea.x+portLabelSize.x+style.FramePadding.x,
portMin.y+style.FramePadding.y+portLabelSize.y
);
ImRect portRect=ImRect(portMin,portMax);
ImVec2 portLabelPos=portMin;
portLabelPos.x+=style.FramePadding.x*0.5;
portLabelPos.y+=style.FramePadding.y*0.5;
portPos[(portSetID<<4)|i]=ImLerp(portMin,portMax,ImVec2(0.0f,0.5f));
if (visible) {
2023-01-08 19:23:17 -05:00
if (ImGui::ItemAdd(portRect,ImGui::GetID(subPortID.c_str()))) {
2023-01-11 13:37:26 -05:00
dl->AddRectFilled(portMin,portMax,ImGui::GetColorU32((i<activeIns)?portColor:portColorH),0.0f);
dl->AddRect(portMin,portMax,ImGui::GetColorU32((i<activeIns)?portBorderColor:portBorderColorH),0.0f,dpiScale);
2023-01-08 19:23:17 -05:00
dl->AddText(portLabelPos,ImGui::GetColorU32(uiColors[GUI_COLOR_TEXT]),portLabel.c_str());
}
if (ImGui::IsMouseHoveringRect(portMin,portMax)) {
hoveredSubPort=i;
if (active) clickedPort=i;
2023-01-08 19:23:17 -05:00
}
}
}
2023-01-08 19:23:17 -05:00
// output ports
for (int i=0; i<outs; i++) {
2024-05-26 19:31:17 -05:00
String portLabel=_("output");
String subPortID=fmt::sprintf("subPort%.5x",(portSetID<<4)|i);
if (outs==2) {
2024-05-26 19:31:17 -05:00
portLabel=_(portNamesStereo[i&1]);
} else if (outs>2) {
portLabel=fmt::sprintf("%d",i+1);
}
ImVec2 portLabelSize=ImGui::CalcTextSize(portLabel.c_str());
ImVec2 portMin=ImVec2(
maxArea.x-portLabelSize.x-style.FramePadding.x,
minArea.y+style.FramePadding.y+labelSize.y+style.ItemSpacing.y+(style.ItemSpacing.y+portLabelSize.y+style.FramePadding.y)*i
);
ImVec2 portMax=ImVec2(
maxArea.x,
portMin.y+style.FramePadding.y+portLabelSize.y
);
ImRect portRect=ImRect(portMin,portMax);
ImVec2 portLabelPos=portMin;
portLabelPos.x+=style.FramePadding.x*0.5;
portLabelPos.y+=style.FramePadding.y*0.5;
portPos[(portSetID<<4)|i]=ImLerp(portMin,portMax,ImVec2(1.0f,0.5f));
if (visible) {
2023-01-08 19:23:17 -05:00
if (ImGui::ItemAdd(portRect,ImGui::GetID(subPortID.c_str()))) {
2023-01-11 13:37:26 -05:00
dl->AddRectFilled(portMin,portMax,ImGui::GetColorU32((i<activeOuts)?portColor:portColorH),0.0f);
dl->AddRect(portMin,portMax,ImGui::GetColorU32((i<activeOuts)?portBorderColor:portBorderColorH),0.0f,dpiScale);
2023-01-08 19:23:17 -05:00
dl->AddText(portLabelPos,ImGui::GetColorU32(uiColors[GUI_COLOR_TEXT]),portLabel.c_str());
}
if (ImGui::IsMouseHoveringRect(portMin,portMax)) {
if (active) clickedPort=i;
hoveredSubPort=i;
2023-01-07 19:46:57 -05:00
}
}
2023-01-07 19:46:57 -05:00
}
if (visible && hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) return true;
2023-01-07 19:46:57 -05:00
return false;
}
void FurnaceGUI::drawMixer() {
if (nextWindow==GUI_WINDOW_MIXER) {
mixerOpen=true;
ImGui::SetNextWindowFocus();
nextWindow=GUI_WINDOW_NOTHING;
}
if (!mixerOpen) return;
2023-01-07 16:26:36 -05:00
if (mobileUI) {
patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*canvasH)):ImVec2((0.16*canvasH)+0.5*canvasW*mobileMenuPos,0.0f));
patWindowSize=(portrait?ImVec2(canvasW,canvasH-(0.16*canvasW)):ImVec2(canvasW-(0.16*canvasH),canvasH));
ImGui::SetNextWindowPos(patWindowPos);
ImGui::SetNextWindowSize(patWindowSize);
} else {
ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(canvasW,canvasH));
}
2024-05-27 17:53:46 -05:00
if (ImGui::Begin("Mixer",&mixerOpen,globalWinFlags|(settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking),_("Mixer"))) {
2023-02-24 03:24:17 -05:00
if (ImGui::BeginTabBar("MixerView")) {
2024-05-26 19:31:17 -05:00
if (ImGui::BeginTabItem(_("Mixer"))) {
float maxY=ImGui::GetContentRegionAvail().y;
VerticalText(maxY, true,_("Master Volume"));
ImGui::SameLine();
ImVec2 pos=ImGui::GetCursorScreenPos();
drawVolMeterInternal(ImGui::GetWindowDrawList(), ImRect(pos,pos+ImVec2(40*dpiScale,maxY)),peak,e->getAudioDescGot().outChans,false);
ImGui::PushStyleColor(ImGuiCol_FrameBg,0);
ImGui::PushStyleColor(ImGuiCol_FrameBgActive,0);
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered,127<<IM_COL32_A_SHIFT);
if (ImGui::VSliderFloat("##mixerMaster",ImVec2(40*dpiScale,maxY),&e->song.masterVol,0,3,"%.2fx")) {
2023-02-24 03:24:17 -05:00
if (e->song.masterVol<0) e->song.masterVol=0;
if (e->song.masterVol>3) e->song.masterVol=3;
2023-01-07 19:46:57 -05:00
MARK_MODIFIED;
} rightClickable
ImGui::PopStyleColor(3);
2025-10-06 00:43:45 +04:00
ImGui::SameLine();
const float itemWidth=60*dpiScale;
// figure out if we need to cut the height for the scrollbar
float calcWidth=(itemWidth+1.5f*ImGui::GetStyle().FramePadding.x+4*ImGui::GetStyle().FramePadding.x+dpiScale)*e->song.systemLen;
float realwidth=ImGui::GetWindowWidth()-ImGui::GetCursorPosX();
if (calcWidth>realwidth) maxY-=ImGui::GetStyle().ScrollbarSize;
if (ImGui::BeginChild("##mixerPerChipContainer", ImVec2(0,0),0,ImGuiWindowFlags_HorizontalScrollbar)) {
2023-02-24 03:24:17 -05:00
for (int i=0; i<e->song.systemLen; i++) {
ImGui::GetWindowDrawList()->AddRectFilled(
ImGui::GetCursorScreenPos(),
ImGui::GetCursorScreenPos()+ImVec2(dpiScale,maxY),
ImGui::GetColorU32(ImGuiCol_Separator)
);
ImGui::Dummy(ImVec2(dpiScale,maxY));
ImGui::SameLine();
if (chipMixer(i, ImVec2(itemWidth,maxY))) MARK_MODIFIED;
2025-10-06 00:43:45 +04:00
ImGui::SameLine();
2023-01-07 19:46:57 -05:00
}
2023-02-24 03:24:17 -05:00
}
ImGui::EndChild();
2023-02-24 03:24:17 -05:00
ImGui::EndTabItem();
2023-01-10 15:58:15 -05:00
}
2024-05-26 19:31:17 -05:00
if (ImGui::BeginTabItem(_("Patchbay"))) {
2023-02-24 03:24:17 -05:00
std::map<unsigned int,ImVec2> portPos;
if (ImGui::BeginTable("PatchbayOptions",3)) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
2024-05-26 19:31:17 -05:00
if (ImGui::Checkbox(_("Automatic patchbay"),&e->song.patchbayAuto)) {
2023-02-24 03:24:17 -05:00
if (e->song.patchbayAuto) e->autoPatchbayP();
MARK_MODIFIED;
}
ImGui::TableNextColumn();
2024-05-26 19:31:17 -05:00
ImGui::Checkbox(_("Display hidden ports"),&displayHiddenPorts);
2023-02-24 03:24:17 -05:00
ImGui::TableNextColumn();
2024-05-26 19:31:17 -05:00
ImGui::Checkbox(_("Display internal"),&displayInternalPorts);
2023-02-24 03:24:17 -05:00
ImGui::EndTable();
}
2023-02-24 03:24:17 -05:00
hoveredPortSet=0x1fff;
hoveredSubPort=-1;
2025-08-10 04:53:08 -05:00
if (ImGui::BeginChild("Patchbay",ImVec2(0,0),ImGuiChildFlags_Border)) {
2023-02-24 03:24:17 -05:00
ImDrawList* dl=ImGui::GetWindowDrawList();
ImVec2 topPos=ImGui::GetCursorPos();
2024-05-26 19:31:17 -05:00
ImVec2 sysSize=calcPortSetSize(_("System"),displayHiddenPorts?DIV_MAX_OUTPUTS:e->getAudioDescGot().outChans,0);
2023-02-24 03:24:17 -05:00
topPos.x+=ImGui::GetContentRegionAvail().x-sysSize.x;
if (ImGui::GetContentRegionAvail().y>sysSize.y) topPos.y+=(ImGui::GetContentRegionAvail().y-sysSize.y)*0.5+ImGui::GetScrollY();
2023-02-24 03:24:17 -05:00
if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) selectedPortSet=0x1fff;
2023-01-10 15:58:15 -05:00
2023-02-24 03:24:17 -05:00
if (portDragActive) {
dl->AddLine(subPortPos,ImGui::GetMousePos(),ImGui::GetColorU32(uiColors[GUI_COLOR_PATCHBAY_CONNECTION]),2.0f*dpiScale);
}
2023-02-24 03:24:17 -05:00
for (int i=0; i<e->song.systemLen; i++) {
DivDispatch* dispatch=e->getDispatch(i);
if (dispatch==NULL) continue;
int outputs=dispatch->getOutputCount();
if (portSet(fmt::sprintf("%d. %s",i+1,getSystemName(e->song.system[i])),i,0,outputs,0,outputs,selectedSubPort,portPos)) {
selectedPortSet=i;
if (selectedSubPort>=0) {
portDragActive=true;
ImGui::InhibitInertialScroll();
auto subPortI=portPos.find((selectedPortSet<<4)|selectedSubPort);
if (subPortI!=portPos.cend()) {
subPortPos=subPortI->second;
} else {
2023-02-24 03:24:17 -05:00
portDragActive=false;
}
}
2023-01-10 19:09:26 -05:00
}
}
2023-02-24 03:24:17 -05:00
// metronome/sample preview
if (displayInternalPorts) {
2024-05-26 19:31:17 -05:00
if (portSet(_("Sample Preview"),0xffd,0,1,0,1,selectedSubPort,portPos)) {
2023-02-24 03:24:17 -05:00
selectedPortSet=0xffd;
if (selectedSubPort>=0) {
portDragActive=true;
ImGui::InhibitInertialScroll();
auto subPortI=portPos.find((selectedPortSet<<4)|selectedSubPort);
if (subPortI!=portPos.cend()) {
subPortPos=subPortI->second;
} else {
2023-02-24 03:24:17 -05:00
portDragActive=false;
}
}
2023-01-10 19:09:26 -05:00
}
2024-05-26 19:31:17 -05:00
if (portSet(_("Metronome"),0xffe,0,1,0,1,selectedSubPort,portPos)) {
2023-02-24 03:24:17 -05:00
selectedPortSet=0xffe;
if (selectedSubPort>=0) {
portDragActive=true;
ImGui::InhibitInertialScroll();
auto subPortI=portPos.find((selectedPortSet<<4)|selectedSubPort);
if (subPortI!=portPos.cend()) {
subPortPos=subPortI->second;
} else {
2023-02-24 03:24:17 -05:00
portDragActive=false;
}
}
}
}
2023-01-10 19:09:26 -05:00
2023-02-24 03:24:17 -05:00
ImGui::SetCursorPos(topPos);
2024-05-26 19:31:17 -05:00
if (portSet(_("System"),0x1000,displayHiddenPorts?DIV_MAX_OUTPUTS:e->getAudioDescGot().outChans,0,e->getAudioDescGot().outChans,0,selectedSubPort,portPos)) {
2023-02-24 03:24:17 -05:00
selectedPortSet=0x1000;
if (selectedSubPort>=0) {
portDragActive=true;
ImGui::InhibitInertialScroll();
auto subPortI=portPos.find((selectedPortSet<<4)|selectedSubPort);
if (subPortI!=portPos.cend()) {
subPortPos=subPortI->second;
} else {
2023-02-24 03:24:17 -05:00
portDragActive=false;
}
}
}
2023-02-24 03:24:17 -05:00
if (portDragActive) {
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
portDragActive=false;
if (hoveredPortSet!=0x1fff && hoveredSubPort>=0 && selectedPortSet!=hoveredPortSet) {
unsigned int src=(selectedPortSet<<4)|selectedSubPort;
unsigned int dest=(hoveredPortSet<<4)|hoveredSubPort;
if (src&0x10000) {
src^=dest;
dest^=src;
src^=dest;
}
src&=0xffff;
dest&=0xffff;
if (!e->patchConnect(src,dest)) {
e->patchDisconnect(src,dest);
}
MARK_MODIFIED;
}
}
2023-02-24 03:24:17 -05:00
}
2023-02-24 03:24:17 -05:00
// draw connections
for (unsigned int i: e->song.patchbay) {
if ((i>>20)==selectedPortSet) continue;
auto portSrcI=portPos.find(i>>16);
auto portDestI=portPos.find(0x10000|(i&0xffff));
if (portSrcI!=portPos.cend() && portDestI!=portPos.cend()) {
ImVec2 portSrc=portSrcI->second;
ImVec2 portDest=portDestI->second;
2023-02-24 03:24:17 -05:00
dl->AddLine(portSrc,portDest,ImGui::GetColorU32(uiColors[GUI_COLOR_PATCHBAY_CONNECTION_BG]),2.0f*dpiScale);
}
}
2023-01-08 19:23:17 -05:00
2023-02-24 03:24:17 -05:00
// foreground
for (unsigned int i: e->song.patchbay) {
if ((i>>20)!=selectedPortSet) continue;
auto portSrcI=portPos.find(i>>16);
auto portDestI=portPos.find(0x10000|(i&0xffff));
if (portSrcI!=portPos.cend() && portDestI!=portPos.cend()) {
ImVec2 portSrc=portSrcI->second;
ImVec2 portDest=portDestI->second;
2023-02-24 03:24:17 -05:00
dl->AddLine(portSrc,portDest,ImGui::GetColorU32(uiColors[GUI_COLOR_PATCHBAY_CONNECTION]),2.0f*dpiScale);
}
}
2023-01-11 13:37:26 -05:00
}
2023-02-24 03:24:17 -05:00
if (ImGui::BeginPopup("SubPortOptions",ImGuiWindowFlags_NoMove|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings)) {
2024-05-26 19:31:17 -05:00
if (ImGui::MenuItem(_("disconnect all"))) {
2023-02-24 03:24:17 -05:00
e->patchDisconnectAll(selectedPortSet);
MARK_MODIFIED;
}
ImGui::EndPopup();
2023-01-08 19:23:17 -05:00
}
2023-02-24 03:24:17 -05:00
ImGui::EndChild();
ImGui::EndTabItem();
2023-01-08 19:23:17 -05:00
}
2023-02-24 03:24:17 -05:00
ImGui::EndTabBar();
}
2023-02-24 03:24:17 -05:00
}
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_MIXER;
ImGui::End();
2022-05-19 16:35:00 -05:00
}
bool FurnaceGUI::chipMixer(int which, ImVec2 size) {
bool ret=false;
ImGui::PushID(which);
ImGui::BeginGroup();
float textHeight=ImGui::GetFontSize();
float vol=fabs(e->song.systemVol[which]);
bool doInvert=e->song.systemVol[which]<0;
if (ImGui::Checkbox("##ChipInvert", &doInvert)) {
e->song.systemVol[which]=doInvert?-vol:vol;
2025-10-08 11:30:34 +04:00
ret=true;
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(_("Invert"));
}
2025-10-08 11:30:34 +04:00
// hack to get the same line from here
ImGui::SameLine();
ImVec2 curPos=ImGui::GetCursorPos();
ImGui::NewLine();
float volSliderHeight=size.y-ImGui::GetStyle().FramePadding.y*7-textHeight*2;
2025-10-08 11:30:34 +04:00
VerticalText(volSliderHeight-(ImGui::GetCursorPosY()-curPos.y), true,"%s",e->getSystemName(e->song.system[which]));
2025-10-08 11:30:34 +04:00
ImGui::SameLine();
float vTextWidth=textHeight+2*ImGui::GetStyle().FramePadding.x;
ImGui::SetCursorPos(curPos);
ImVec2 pos=ImGui::GetCursorScreenPos();
drawVolMeterInternal(ImGui::GetWindowDrawList(),ImRect(pos,pos+ImVec2(size.x-vTextWidth,volSliderHeight)),e->chipPeak[which],e->getDispatch(which)->getOutputCount(),false);
ImGui::PushStyleColor(ImGuiCol_FrameBg,0);
ImGui::PushStyleColor(ImGuiCol_FrameBgActive,0);
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered,127<<IM_COL32_A_SHIFT);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0);
2025-10-08 11:30:34 +04:00
if (ImGui::VSliderFloat("##ChipVol", ImVec2(size.x-vTextWidth,volSliderHeight), &vol, 0.0f, 2.0f)) {
if (doInvert) {
if (vol<0.0001) vol=0.0001;
}
if (vol<0) vol=0;
if (vol>10) vol=10;
e->song.systemVol[which]=doInvert?-vol:vol;
2025-10-08 11:30:34 +04:00
ret=true;
} rightClickable
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort)) {
ImGui::SetTooltip(_("Volume"));
2025-10-08 11:30:34 +04:00
}
ImGui::PopStyleVar(1);
ImGui::PopStyleColor(3);
ImGui::SetNextItemWidth(size.x+1.5f*ImGui::GetStyle().FramePadding.x);
if (ImGui::SliderFloat("##ChipPan", &e->song.systemPan[which], -1.0f, 1.0f)) {
if (e->song.systemPan[which]<-1.0f) e->song.systemPan[which]=-1.0f;
if (e->song.systemPan[which]>1.0f) e->song.systemPan[which]=1.0f;
ret=true;
} rightClickable
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort)) {
ImGui::SetTooltip(_("Panning"));
}
ImGui::SetNextItemWidth(size.x+1.5f*ImGui::GetStyle().FramePadding.x);
if (ImGui::SliderFloat("##ChipPanFR", &e->song.systemPanFR[which], -1.0f, 1.0f)) {
if (e->song.systemPanFR[which]<-1.0f) e->song.systemPanFR[which]=-1.0f;
if (e->song.systemPanFR[which]>1.0f) e->song.systemPanFR[which]=1.0f;
ret=true;
} rightClickable
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort)) {
ImGui::SetTooltip(_("Front/Rear"));
}
ImGui::EndGroup();
ImGui::PopID();
return ret;
}