/** * Furnace Tracker - multi-system chiptune tracker * Copyright (C) 2021-2022 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 "fonts.h" #include "../ta-log.h" #include "../fileutils.h" #include "../utfutils.h" #include "util.h" #include "guiConst.h" #include "intConst.h" #include "ImGuiFileDialog.h" #include "IconsFontAwesome4.h" #include "misc/cpp/imgui_stdlib.h" #include #include #define DEFAULT_NOTE_KEYS "5:7;6:4;7:3;8:16;10:6;11:8;12:24;13:10;16:11;17:9;18:26;19:28;20:12;21:17;22:1;23:19;24:23;25:5;26:14;27:2;28:21;29:0;30:100;31:13;32:15;34:18;35:20;36:22;38:25;39:27;43:100;46:101;47:29;48:31;53:102;" #if defined(_WIN32) || defined(__APPLE__) #define POWER_SAVE_DEFAULT 1 #else // currently off on Linux/other due to Mesa catch-up behavior. #define POWER_SAVE_DEFAULT 0 #endif #ifdef __HAIKU__ // NFD doesn't support Haiku #define SYS_FILE_DIALOG_DEFAULT 0 #else #define SYS_FILE_DIALOG_DEFAULT 1 #endif const char* mainFonts[]={ "IBM Plex Sans", "Liberation Sans", "Exo", "Proggy Clean", "GNU Unifont", "", "" }; const char* patFonts[]={ "IBM Plex Mono", "Mononoki", "PT Mono", "Proggy Clean", "GNU Unifont", "", "" }; const char* audioBackends[]={ "JACK", "SDL" }; const char* audioQualities[]={ "High", "Low" }; const char* arcadeCores[]={ "ymfm", "Nuked-OPM" }; const char* ym2612Cores[]={ "Nuked-OPN2", "ymfm" }; const char* snCores[]={ "MAME", "Nuked-PSG Mod" }; const char* nesCores[]={ "puNES", "NSFplay" }; const char* c64Cores[]={ "reSID", "reSIDfp" }; const char* pcspkrOutMethods[]={ "evdev SND_TONE", "KIOCSOUND on /dev/tty1", "/dev/port", "KIOCSOUND on standard output", "outb()" }; const char* valueInputStyles[]={ "Disabled/custom", "Two octaves (0 is C-4, F is D#5)", "Raw (note number is value)", "Two octaves alternate (lower keys are 0-9, upper keys are A-F)", "Use dual control change (one for each nibble)", "Use 14-bit control change", "Use single control change (imprecise)" }; const char* valueSInputStyles[]={ "Disabled/custom", "Use dual control change (one for each nibble)", "Use 14-bit control change", "Use single control change (imprecise)" }; const char* messageTypes[]={ "--select--", "???", "???", "???", "???", "???", "???", "???", "Note Off", "Note On", "Aftertouch", "Control", "Program", "ChanPressure", "Pitch Bend", "SysEx" }; const char* messageChannels[]={ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "Any" }; const char* specificControls[18]={ "Instrument", "Volume", "Effect 1 type", "Effect 1 value", "Effect 2 type", "Effect 2 value", "Effect 3 type", "Effect 3 value", "Effect 4 type", "Effect 4 value", "Effect 5 type", "Effect 5 value", "Effect 6 type", "Effect 6 value", "Effect 7 type", "Effect 7 value", "Effect 8 type", "Effect 8 value" }; #define SAMPLE_RATE_SELECTABLE(x) \ if (ImGui::Selectable(#x,settings.audioRate==x)) { \ settings.audioRate=x; \ } #define BUFFER_SIZE_SELECTABLE(x) \ if (ImGui::Selectable(#x,settings.audioBufSize==x)) { \ settings.audioBufSize=x; \ } #define UI_COLOR_CONFIG(what,label) \ if (ImGui::ColorEdit4(label "##CC_" #what,(float*)&uiColors[what])) { \ applyUISettings(false); \ } #define KEYBIND_CONFIG_BEGIN(id) \ if (ImGui::BeginTable(id,2)) { #define KEYBIND_CONFIG_END \ ImGui::EndTable(); \ } #define UI_KEYBIND_CONFIG(what) \ ImGui::TableNextRow(); \ ImGui::TableNextColumn(); \ ImGui::TextUnformatted(guiActions[what].friendlyName); \ ImGui::TableNextColumn(); \ if (ImGui::Button(fmt::sprintf("%s##KC_" #what,(bindSetPending && bindSetTarget==what)?"Press key...":getKeyName(actionKeys[what])).c_str())) { \ promptKey(what); \ } \ if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) actionKeys[what]=0; String stripName(String what) { String ret; for (char& i: what) { if ((i>='A' && i<='Z') || (i>='a' && i<='z') || (i>='0' && i<='9')) { ret+=i; } else { ret+='-'; } } return ret; } void FurnaceGUI::promptKey(int which) { bindSetTarget=which; bindSetActive=true; bindSetPending=true; bindSetPrevValue=actionKeys[which]; actionKeys[which]=0; } struct MappedInput { int scan; int val; MappedInput(): scan(SDL_SCANCODE_UNKNOWN), val(0) {} MappedInput(int s, int v): scan(s), val(v) {} }; void FurnaceGUI::drawSettings() { if (nextWindow==GUI_WINDOW_SETTINGS) { settingsOpen=true; ImGui::SetNextWindowFocus(); nextWindow=GUI_WINDOW_NOTHING; } if (!settingsOpen) return; if (ImGui::Begin("Settings",&settingsOpen,ImGuiWindowFlags_NoDocking|globalWinFlags)) { if (!settingsOpen) { settingsOpen=true; showWarning("Do you want to save your settings?",GUI_WARN_CLOSE_SETTINGS); } if (ImGui::BeginTabBar("settingsTab")) { if (ImGui::BeginTabItem("General")) { ImVec2 settingsViewSize=ImGui::GetContentRegionAvail(); settingsViewSize.y-=ImGui::GetFrameHeight()+ImGui::GetStyle().WindowPadding.y; if (ImGui::BeginChild("SettingsView",settingsViewSize)) { ImGui::Text("Workspace layout:"); ImGui::SameLine(); if (ImGui::Button("Import")) { openFileDialog(GUI_FILE_IMPORT_LAYOUT); } ImGui::SameLine(); if (ImGui::Button("Export")) { openFileDialog(GUI_FILE_EXPORT_LAYOUT); } ImGui::SameLine(); if (ImGui::Button("Reset")) { showWarning("Are you sure you want to reset the workspace layout?",GUI_WARN_RESET_LAYOUT); } ImGui::Separator(); ImGui::Text("Initial system:"); ImGui::SameLine(); if (ImGui::Button("Current system")) { settings.initialSys.clear(); for (int i=0; isong.systemLen; i++) { settings.initialSys.push_back(e->song.system[i]); settings.initialSys.push_back(e->song.systemVol[i]); settings.initialSys.push_back(e->song.systemPan[i]); settings.initialSys.push_back(e->song.systemFlags[i]); } settings.initialSysName=e->song.systemName; } ImGui::SameLine(); if (ImGui::Button("Randomize")) { settings.initialSys.clear(); int howMany=1+rand()%3; int totalAvailSys=0; for (totalAvailSys=0; availableSystems[totalAvailSys]; totalAvailSys++); if (totalAvailSys>0) { for (int i=0; i wordPool[6]; for (size_t i=0; igetSystemName((DivSystem)settings.initialSys[i*4]); String nameWord; sName+=" "; for (char& i: sName) { if (i==' ') { if (nameWord!="") { wordPool[wpPos++].push_back(nameWord); if (wpPos>=6) break; nameWord=""; } } else { nameWord+=i; } } } settings.initialSysName=""; for (int i=0; i<6; i++) { if (wordPool[i].empty()) continue; settings.initialSysName+=wordPool[i][rand()%wordPool[i].size()]; settings.initialSysName+=" "; } } ImGui::SameLine(); if (ImGui::Button("Reset to defaults")) { settings.initialSys.clear(); settings.initialSys.push_back(DIV_SYSTEM_YM2612); settings.initialSys.push_back(64); settings.initialSys.push_back(0); settings.initialSys.push_back(0); settings.initialSys.push_back(DIV_SYSTEM_SMS); settings.initialSys.push_back(32); settings.initialSys.push_back(0); settings.initialSys.push_back(0); settings.initialSysName="Sega Genesis/Mega Drive"; } ImGui::Text("Name"); ImGui::SameLine(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::InputText("##InitSysName",&settings.initialSysName); for (size_t i=0; i=8) { settings.initialSys.erase(settings.initialSys.begin()+i,settings.initialSys.begin()+i+4); i-=4; } } if (ImGui::Button(ICON_FA_PLUS "##InitSysAdd")) { settings.initialSys.push_back(DIV_SYSTEM_YM2612); settings.initialSys.push_back(64); settings.initialSys.push_back(0); settings.initialSys.push_back(0); } ImGui::Separator(); ImGui::Text("Toggle channel solo on:"); if (ImGui::RadioButton("Right-click or double-click##soloA",settings.soloAction==0)) { settings.soloAction=0; } if (ImGui::RadioButton("Right-click##soloR",settings.soloAction==1)) { settings.soloAction=1; } if (ImGui::RadioButton("Double-click##soloD",settings.soloAction==2)) { settings.soloAction=2; } bool pushNibbleB=settings.pushNibble; if (ImGui::Checkbox("Push value when overwriting instead of clearing it",&pushNibbleB)) { settings.pushNibble=pushNibbleB; } bool pullDeleteBehaviorB=settings.pullDeleteBehavior; if (ImGui::Checkbox("Move cursor up on backspace-delete",&pullDeleteBehaviorB)) { settings.pullDeleteBehavior=pullDeleteBehaviorB; } bool stepOnDeleteB=settings.stepOnDelete; if (ImGui::Checkbox("Move cursor by edit step on delete",&stepOnDeleteB)) { settings.stepOnDelete=stepOnDeleteB; } bool absorbInsInputB=settings.absorbInsInput; if (ImGui::Checkbox("Change current instrument when changing instrument column (absorb)",&absorbInsInputB)) { settings.absorbInsInput=absorbInsInputB; } bool effectDeletionAltersValueB=settings.effectDeletionAltersValue; if (ImGui::Checkbox("Delete effect value when deleting effect",&effectDeletionAltersValueB)) { settings.effectDeletionAltersValue=effectDeletionAltersValueB; } bool scrollChangesOrderB=settings.scrollChangesOrder; if (ImGui::Checkbox("Change order when scrolling outside of pattern bounds",&scrollChangesOrderB)) { settings.scrollChangesOrder=scrollChangesOrderB; } bool stepOnInsertB=settings.stepOnInsert; if (ImGui::Checkbox("Move cursor by edit step on insert (push)",&stepOnInsertB)) { settings.stepOnInsert=stepOnInsertB; } bool cursorPastePosB=settings.cursorPastePos; if (ImGui::Checkbox("Move cursor to end of clipboard content when pasting",&cursorPastePosB)) { settings.cursorPastePos=cursorPastePosB; } bool cursorMoveNoScrollB=settings.cursorMoveNoScroll; if (ImGui::Checkbox("Don't scroll when moving cursor",&cursorMoveNoScrollB)) { settings.cursorMoveNoScroll=cursorMoveNoScrollB; } bool doubleClickColumnB=settings.doubleClickColumn; if (ImGui::Checkbox("Double click selects entire column",&doubleClickColumnB)) { settings.doubleClickColumn=doubleClickColumnB; } bool allowEditDockingB=settings.allowEditDocking; if (ImGui::Checkbox("Allow docking editors",&allowEditDockingB)) { settings.allowEditDocking=allowEditDockingB; } bool avoidRaisingPatternB=settings.avoidRaisingPattern; if (ImGui::Checkbox("Don't raise pattern editor on click",&avoidRaisingPatternB)) { settings.avoidRaisingPattern=avoidRaisingPatternB; } bool insFocusesPatternB=settings.insFocusesPattern; if (ImGui::Checkbox("Focus pattern editor when selecting instrument",&insFocusesPatternB)) { settings.insFocusesPattern=insFocusesPatternB; } bool restartOnFlagChangeB=settings.restartOnFlagChange; if (ImGui::Checkbox("Restart song when changing chip properties",&restartOnFlagChangeB)) { settings.restartOnFlagChange=restartOnFlagChangeB; } bool sysFileDialogB=settings.sysFileDialog; if (ImGui::Checkbox("Use system file picker",&sysFileDialogB)) { settings.sysFileDialog=sysFileDialogB; } bool moveWindowTitleB=settings.moveWindowTitle; if (ImGui::Checkbox("Only allow window movement when clicking on title bar",&moveWindowTitleB)) { settings.moveWindowTitle=moveWindowTitleB; applyUISettings(false); } bool eventDelayB=settings.eventDelay; if (ImGui::Checkbox("Enable event delay",&eventDelayB)) { settings.eventDelay=eventDelayB; applyUISettings(false); } if (ImGui::IsItemHovered()) { ImGui::SetTooltip("may cause issues with high-polling-rate mice when previewing notes."); } bool powerSaveB=settings.powerSave; if (ImGui::Checkbox("Power-saving mode",&powerSaveB)) { settings.powerSave=powerSaveB; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip("saves power by lowering the frame rate to 2fps when idle.\nmay cause issues under Mesa drivers!"); } bool noThreadedInputB=settings.noThreadedInput; if (ImGui::Checkbox("Disable threaded input (restart after changing!)",&noThreadedInputB)) { settings.noThreadedInput=noThreadedInputB; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip("threaded input processes key presses for note preview on a separate thread (on supported platforms), which reduces latency.\nhowever, crashes have been reported when threaded input is on. enable this option if that is the case."); } bool saveWindowPosB=settings.saveWindowPos; if (ImGui::Checkbox("Remember window location",&saveWindowPosB)) { settings.saveWindowPos=saveWindowPosB; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip("remembers where window was last located on start-up. When disabled, window will start in a defaul location."); } bool blankInsB=settings.blankIns; if (ImGui::Checkbox("New instruments are blank",&blankInsB)) { settings.blankIns=blankInsB; } bool saveUnusedPatternsB=settings.saveUnusedPatterns; if (ImGui::Checkbox("Save unused patterns",&saveUnusedPatternsB)) { settings.saveUnusedPatterns=saveUnusedPatternsB; } ImGui::Text("Note preview behavior:"); if (ImGui::RadioButton("Never##npb0",settings.notePreviewBehavior==0)) { settings.notePreviewBehavior=0; } if (ImGui::RadioButton("When cursor is in Note column##npb1",settings.notePreviewBehavior==1)) { settings.notePreviewBehavior=1; } if (ImGui::RadioButton("When cursor is in Note column or not in edit mode##npb2",settings.notePreviewBehavior==2)) { settings.notePreviewBehavior=2; } if (ImGui::RadioButton("Always##npb3",settings.notePreviewBehavior==3)) { settings.notePreviewBehavior=3; } ImGui::Text("Wrap pattern cursor horizontally:"); if (ImGui::RadioButton("No##wrapH0",settings.wrapHorizontal==0)) { settings.wrapHorizontal=0; } if (ImGui::RadioButton("Yes##wrapH1",settings.wrapHorizontal==1)) { settings.wrapHorizontal=1; } if (ImGui::RadioButton("Yes, and move to next/prev row##wrapH2",settings.wrapHorizontal==2)) { settings.wrapHorizontal=2; } ImGui::Text("Wrap pattern cursor vertically:"); if (ImGui::RadioButton("No##wrapV0",settings.wrapVertical==0)) { settings.wrapVertical=0; } if (ImGui::RadioButton("Yes##wrapV1",settings.wrapVertical==1)) { settings.wrapVertical=1; } if (ImGui::RadioButton("Yes, and move to next/prev pattern##wrapV2",settings.wrapVertical==2)) { settings.wrapVertical=2; } ImGui::Text("Cursor movement keys behavior:"); if (ImGui::RadioButton("Move by one##cmk0",settings.scrollStep==0)) { settings.scrollStep=0; } if (ImGui::RadioButton("Move by Edit Step##cmk1",settings.scrollStep==1)) { settings.scrollStep=1; } ImGui::Text("Effect input cursor behavior:"); if (ImGui::RadioButton("Move down##eicb0",settings.effectCursorDir==0)) { settings.effectCursorDir=0; } if (ImGui::RadioButton("Move to effect value (otherwise move down)##eicb1",settings.effectCursorDir==1)) { settings.effectCursorDir=1; } if (ImGui::RadioButton("Move to effect value/next effect and wrap around##eicb2",settings.effectCursorDir==2)) { settings.effectCursorDir=2; } ImGui::Text("Allow dragging selection:"); if (ImGui::RadioButton("No##dms0",settings.dragMovesSelection==0)) { settings.dragMovesSelection=0; } if (ImGui::RadioButton("Yes##dms1",settings.dragMovesSelection==1)) { settings.dragMovesSelection=1; } if (ImGui::RadioButton("Yes (while holding Ctrl only)##dms2",settings.dragMovesSelection==2)) { settings.dragMovesSelection=2; } } ImGui::EndChild(); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Audio/MIDI")) { ImVec2 settingsViewSize=ImGui::GetContentRegionAvail(); settingsViewSize.y-=ImGui::GetFrameHeight()+ImGui::GetStyle().WindowPadding.y; if (ImGui::BeginChild("SettingsView",settingsViewSize)) { ImGui::Text("Backend"); ImGui::SameLine(); ImGui::Combo("##Backend",&settings.audioEngine,audioBackends,2); ImGui::Text("Device"); ImGui::SameLine(); String audioDevName=settings.audioDevice.empty()?"":settings.audioDevice; if (ImGui::BeginCombo("##AudioDevice",audioDevName.c_str())) { if (ImGui::Selectable("",settings.audioDevice.empty())) { settings.audioDevice=""; } for (String& i: e->getAudioDevices()) { if (ImGui::Selectable(i.c_str(),i==settings.audioDevice)) { settings.audioDevice=i; } } ImGui::EndCombo(); } ImGui::Text("Sample rate"); ImGui::SameLine(); String sr=fmt::sprintf("%d",settings.audioRate); if (ImGui::BeginCombo("##SampleRate",sr.c_str())) { SAMPLE_RATE_SELECTABLE(8000); SAMPLE_RATE_SELECTABLE(16000); SAMPLE_RATE_SELECTABLE(22050); SAMPLE_RATE_SELECTABLE(32000); SAMPLE_RATE_SELECTABLE(44100); SAMPLE_RATE_SELECTABLE(48000); SAMPLE_RATE_SELECTABLE(88200); SAMPLE_RATE_SELECTABLE(96000); SAMPLE_RATE_SELECTABLE(192000); ImGui::EndCombo(); } ImGui::Text("Buffer size"); ImGui::SameLine(); String bs=fmt::sprintf("%d (latency: ~%.1fms)",settings.audioBufSize,2000.0*(double)settings.audioBufSize/(double)MAX(1,settings.audioRate)); if (ImGui::BeginCombo("##BufferSize",bs.c_str())) { BUFFER_SIZE_SELECTABLE(64); BUFFER_SIZE_SELECTABLE(128); BUFFER_SIZE_SELECTABLE(256); BUFFER_SIZE_SELECTABLE(512); BUFFER_SIZE_SELECTABLE(1024); BUFFER_SIZE_SELECTABLE(2048); ImGui::EndCombo(); } ImGui::Text("Quality"); ImGui::SameLine(); ImGui::Combo("##Quality",&settings.audioQuality,audioQualities,2); ImGui::Text("Metronome volume"); ImGui::SameLine(); if (ImGui::SliderInt("##MetroVol",&settings.metroVol,0,200,"%d%%")) { if (settings.metroVol<0) settings.metroVol=0; if (settings.metroVol>200) settings.metroVol=200; e->setMetronomeVol(((float)settings.metroVol)/100.0f); } bool lowLatencyB=settings.lowLatency; if (ImGui::Checkbox("Low-latency mode (experimental!)",&lowLatencyB)) { settings.lowLatency=lowLatencyB; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip("reduces latency by running the engine faster than the tick rate.\nuseful for live playback/jam mode.\n\nwarning: experimental! may produce glitches.\nonly enable if your buffer size is small (10ms or less)."); } bool forceMonoB=settings.forceMono; if (ImGui::Checkbox("Force mono audio",&forceMonoB)) { settings.forceMono=forceMonoB; } bool clampSamplesB=settings.clampSamples; if (ImGui::Checkbox("Software clipping",&clampSamplesB)) { settings.clampSamples=clampSamplesB; } TAAudioDesc& audioWant=e->getAudioDescWant(); TAAudioDesc& audioGot=e->getAudioDescGot(); ImGui::Text("want: %d samples @ %.0fHz",audioWant.bufsize,audioWant.rate); ImGui::Text("got: %d samples @ %.0fHz",audioGot.bufsize,audioGot.rate); ImGui::Separator(); ImGui::Text("MIDI input"); ImGui::SameLine(); String midiInName=settings.midiInDevice.empty()?"":settings.midiInDevice; bool hasToReloadMidi=false; if (ImGui::BeginCombo("##MidiInDevice",midiInName.c_str())) { if (ImGui::Selectable("",settings.midiInDevice.empty())) { settings.midiInDevice=""; hasToReloadMidi=true; } for (String& i: e->getMidiIns()) { if (ImGui::Selectable(i.c_str(),i==settings.midiInDevice)) { settings.midiInDevice=i; hasToReloadMidi=true; } } ImGui::EndCombo(); } if (hasToReloadMidi) { midiMap.read(e->getConfigPath()+DIR_SEPARATOR_STR+"midiIn_"+stripName(settings.midiInDevice)+".cfg"); midiMap.compile(); } ImGui::Text("MIDI output"); ImGui::SameLine(); String midiOutName=settings.midiOutDevice.empty()?"":settings.midiOutDevice; if (ImGui::BeginCombo("##MidiOutDevice",midiOutName.c_str())) { if (ImGui::Selectable("",settings.midiOutDevice.empty())) { settings.midiOutDevice=""; } for (String& i: e->getMidiIns()) { if (ImGui::Selectable(i.c_str(),i==settings.midiOutDevice)) { settings.midiOutDevice=i; } } ImGui::EndCombo(); } if (ImGui::TreeNode("MIDI input settings")) { ImGui::Checkbox("Note input",&midiMap.noteInput); ImGui::Checkbox("Velocity input",&midiMap.volInput); // TODO //ImGui::Checkbox("Use raw velocity value (don't map from linear to log)",&midiMap.rawVolume); //ImGui::Checkbox("Polyphonic/chord input",&midiMap.polyInput); ImGui::Checkbox("Map MIDI channels to direct channels",&midiMap.directChannel); ImGui::Checkbox("Map Yamaha FM voice data to instruments",&midiMap.yamahaFMResponse); ImGui::Checkbox("Program change is instrument selection",&midiMap.programChange); //ImGui::Checkbox("Listen to MIDI clock",&midiMap.midiClock); //ImGui::Checkbox("Listen to MIDI time code",&midiMap.midiTimeCode); ImGui::Combo("Value input style",&midiMap.valueInputStyle,valueInputStyles,7); if (midiMap.valueInputStyle>3) { if (midiMap.valueInputStyle==6) { if (ImGui::InputInt("Control##valueCCS",&midiMap.valueInputControlSingle,1,16)) { if (midiMap.valueInputControlSingle<0) midiMap.valueInputControlSingle=0; if (midiMap.valueInputControlSingle>127) midiMap.valueInputControlSingle=127; } } else { if (ImGui::InputInt((midiMap.valueInputStyle==4)?"CC of upper nibble##valueCC1":"MSB CC##valueCC1",&midiMap.valueInputControlMSB,1,16)) { if (midiMap.valueInputControlMSB<0) midiMap.valueInputControlMSB=0; if (midiMap.valueInputControlMSB>127) midiMap.valueInputControlMSB=127; } if (ImGui::InputInt((midiMap.valueInputStyle==4)?"CC of lower nibble##valueCC2":"LSB CC##valueCC2",&midiMap.valueInputControlLSB,1,16)) { if (midiMap.valueInputControlLSB<0) midiMap.valueInputControlLSB=0; if (midiMap.valueInputControlLSB>127) midiMap.valueInputControlLSB=127; } } } if (ImGui::TreeNode("Per-column control change")) { for (int i=0; i<18; i++) { ImGui::PushID(i); ImGui::Combo(specificControls[i],&midiMap.valueInputSpecificStyle[i],valueSInputStyles,4); if (midiMap.valueInputSpecificStyle[i]>0) { ImGui::Indent(); if (midiMap.valueInputSpecificStyle[i]==3) { if (ImGui::InputInt("Control##valueCCS",&midiMap.valueInputSpecificSingle[i],1,16)) { if (midiMap.valueInputSpecificSingle[i]<0) midiMap.valueInputSpecificSingle[i]=0; if (midiMap.valueInputSpecificSingle[i]>127) midiMap.valueInputSpecificSingle[i]=127; } } else { if (ImGui::InputInt((midiMap.valueInputSpecificStyle[i]==4)?"CC of upper nibble##valueCC1":"MSB CC##valueCC1",&midiMap.valueInputSpecificMSB[i],1,16)) { if (midiMap.valueInputSpecificMSB[i]<0) midiMap.valueInputSpecificMSB[i]=0; if (midiMap.valueInputSpecificMSB[i]>127) midiMap.valueInputSpecificMSB[i]=127; } if (ImGui::InputInt((midiMap.valueInputSpecificStyle[i]==4)?"CC of lower nibble##valueCC2":"LSB CC##valueCC2",&midiMap.valueInputSpecificLSB[i],1,16)) { if (midiMap.valueInputSpecificLSB[i]<0) midiMap.valueInputSpecificLSB[i]=0; if (midiMap.valueInputSpecificLSB[i]>127) midiMap.valueInputSpecificLSB[i]=127; } } ImGui::Unindent(); } ImGui::PopID(); } ImGui::TreePop(); } if (ImGui::SliderFloat("Volume curve",&midiMap.volExp,0.01,8.0,"%.2f")) { if (midiMap.volExp<0.01) midiMap.volExp=0.01; if (midiMap.volExp>8.0) midiMap.volExp=8.0; } rightClickable float curve[128]; for (int i=0; i<128; i++) { curve[i]=(int)(pow((double)i/127.0,midiMap.volExp)*127.0); } ImGui::PlotLines("##VolCurveDisplay",curve,128,0,"Volume curve",0.0,127.0,ImVec2(200.0f*dpiScale,200.0f*dpiScale)); ImGui::Text("Actions:"); ImGui::SameLine(); if (ImGui::Button(ICON_FA_PLUS "##AddAction")) { midiMap.binds.push_back(MIDIBind()); } ImGui::SameLine(); if (ImGui::Button(ICON_FA_EXTERNAL_LINK "##AddLearnAction")) { midiMap.binds.push_back(MIDIBind()); learning=midiMap.binds.size()-1; } if (learning!=-1) { ImGui::SameLine(); ImGui::Text("(learning! press a button or move a slider/knob/something on your device.)"); } if (ImGui::BeginTable("MIDIActions",7)) { ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthStretch,0.2); ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.1); ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.3); ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch,0.2); ImGui::TableSetupColumn("c4",ImGuiTableColumnFlags_WidthStretch,0.5); ImGui::TableSetupColumn("c5",ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("c6",ImGuiTableColumnFlags_WidthFixed); ImGui::TableNextRow(ImGuiTableRowFlags_Headers); ImGui::TableNextColumn(); ImGui::Text("Type"); ImGui::TableNextColumn(); ImGui::Text("Channel"); ImGui::TableNextColumn(); ImGui::Text("Note/Control"); ImGui::TableNextColumn(); ImGui::Text("Velocity/Value"); ImGui::TableNextColumn(); ImGui::Text("Action"); ImGui::TableNextColumn(); ImGui::Text("Learn"); ImGui::TableNextColumn(); ImGui::Text("Remove"); for (size_t i=0; i0 && (bind.data1+60)<180) { nName=noteNames[bind.data1+60]; } snprintf(bindID,1024,"%d (0x%.2X, %s)",bind.data1,bind.data1,nName); } ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); if (ImGui::BeginCombo("##BValue1",bindID)) { if (ImGui::Selectable("Any",bind.data1==128)) { bind.data1=128; } for (int j=0; j<128; j++) { const char* nName="???"; if ((j+60)>0 && (j+60)<180) { nName=noteNames[j+60]; } snprintf(bindID,1024,"%d (0x%.2X, %s)##BV1_%d",j,j,nName,j); if (ImGui::Selectable(bindID,bind.data1==j)) { bind.data1=j; } } ImGui::EndCombo(); } ImGui::TableNextColumn(); if (bind.data2==128) { snprintf(bindID,1024,"Any"); } else { snprintf(bindID,1024,"%d (0x%.2X)",bind.data2,bind.data2); } ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); if (ImGui::BeginCombo("##BValue2",bindID)) { if (ImGui::Selectable("Any",bind.data2==128)) { bind.data2=128; } for (int j=0; j<128; j++) { snprintf(bindID,1024,"%d (0x%.2X)##BV2_%d",j,j,j); if (ImGui::Selectable(bindID,bind.data2==j)) { bind.data2=j; } } ImGui::EndCombo(); } ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); if (ImGui::BeginCombo("##BAction",(bind.action==0)?"--none--":guiActions[bind.action].friendlyName)) { if (ImGui::Selectable("--none--",bind.action==0)) { bind.action=0; } for (int j=0; j3.0f) settings.dpiScale=3.0f; } rightClickable } ImGui::Text("Main font"); ImGui::SameLine(); ImGui::Combo("##MainFont",&settings.mainFont,mainFonts,7); if (settings.mainFont==6) { ImGui::InputText("##MainFontPath",&settings.mainFontPath); ImGui::SameLine(); if (ImGui::Button(ICON_FA_FOLDER "##MainFontLoad")) { openFileDialog(GUI_FILE_LOAD_MAIN_FONT); } } if (ImGui::InputInt("Size##MainFontSize",&settings.mainFontSize)) { if (settings.mainFontSize<3) settings.mainFontSize=3; if (settings.mainFontSize>96) settings.mainFontSize=96; } ImGui::Text("Pattern font"); ImGui::SameLine(); ImGui::Combo("##PatFont",&settings.patFont,patFonts,7); if (settings.patFont==6) { ImGui::InputText("##PatFontPath",&settings.patFontPath); ImGui::SameLine(); if (ImGui::Button(ICON_FA_FOLDER "##PatFontLoad")) { openFileDialog(GUI_FILE_LOAD_PAT_FONT); } } if (ImGui::InputInt("Size##PatFontSize",&settings.patFontSize)) { if (settings.patFontSize<3) settings.patFontSize=3; if (settings.patFontSize>96) settings.patFontSize=96; } if (ImGui::InputInt("Icon size",&settings.iconSize)) { if (settings.iconSize<3) settings.iconSize=3; if (settings.iconSize>48) settings.iconSize=48; } bool loadJapaneseB=settings.loadJapanese; if (ImGui::Checkbox("Display Japanese characters",&loadJapaneseB)) { settings.loadJapanese=loadJapaneseB; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip( "Only toggle this option if you have enough graphics memory.\n" "This is a temporary solution until dynamic font atlas is implemented in Dear ImGui.\n\n" "このオプションは、十分なグラフィックメモリがある場合にのみ切り替えてください。\n" "これは、Dear ImGuiにダイナミックフォントアトラスが実装されるまでの一時的な解決策です。" ); } bool loadChineseB=settings.loadChinese; if (ImGui::Checkbox("Display Chinese (Simplified) characters",&loadChineseB)) { settings.loadChinese=loadChineseB; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip( "Only toggle this option if you have enough graphics memory.\n" "This is a temporary solution until dynamic font atlas is implemented in Dear ImGui.\n\n" "请在确保你有足够的显存后再启动此设定\n" "这是一个在ImGui实现动态字体加载之前的临时解决方案" ); } bool loadChineseTraditionalB=settings.loadChineseTraditional; if (ImGui::Checkbox("Display Chinese (Traditional) characters",&loadChineseTraditionalB)) { settings.loadChineseTraditional=loadChineseTraditionalB; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip( "Only toggle this option if you have enough graphics memory.\n" "This is a temporary solution until dynamic font atlas is implemented in Dear ImGui.\n\n" "請在確保你有足夠的顯存后再啟動此設定\n" "這是一個在ImGui實現動態字體加載之前的臨時解決方案" ); } bool loadKoreanB=settings.loadKorean; if (ImGui::Checkbox("Display Korean characters",&loadKoreanB)) { settings.loadKorean=loadKoreanB; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip( "Only toggle this option if you have enough graphics memory.\n" "This is a temporary solution until dynamic font atlas is implemented in Dear ImGui.\n\n" "그래픽 메모리가 충분한 경우에만 이 옵션을 선택하십시오.\n" "이 옵션은 Dear ImGui에 동적 글꼴 아틀라스가 구현될 때까지 임시 솔루션입니다." ); } ImGui::Separator(); ImGui::Text("Pattern view labels:"); ImGui::InputTextWithHint("Note off (3-char)","OFF",&settings.noteOffLabel); ImGui::InputTextWithHint("Note release (3-char)","===",&settings.noteRelLabel); ImGui::InputTextWithHint("Macro release (3-char)","REL",&settings.macroRelLabel); ImGui::InputTextWithHint("Empty field (3-char)","...",&settings.emptyLabel); ImGui::InputTextWithHint("Empty field (2-char)","..",&settings.emptyLabel2); ImGui::Separator(); ImGui::Text("Orders row number format:"); if (ImGui::RadioButton("Decimal##orbD",settings.orderRowsBase==0)) { settings.orderRowsBase=0; } if (ImGui::RadioButton("Hexadecimal##orbH",settings.orderRowsBase==1)) { settings.orderRowsBase=1; } ImGui::Text("Pattern row number format:"); if (ImGui::RadioButton("Decimal##prbD",settings.patRowsBase==0)) { settings.patRowsBase=0; } if (ImGui::RadioButton("Hexadecimal##prbH",settings.patRowsBase==1)) { settings.patRowsBase=1; } ImGui::Text("FM parameter names:"); if (ImGui::RadioButton("Friendly##fmn0",settings.fmNames==0)) { settings.fmNames=0; } if (ImGui::RadioButton("Technical##fmn1",settings.fmNames==1)) { settings.fmNames=1; } if (ImGui::RadioButton("Technical (alternate)##fmn2",settings.fmNames==2)) { settings.fmNames=2; } ImGui::Separator(); ImGui::Text("Title bar:"); if (ImGui::RadioButton("Furnace##tbar0",settings.titleBarInfo==0)) { settings.titleBarInfo=0; updateWindowTitle(); } if (ImGui::RadioButton("Song Name - Furnace##tbar1",settings.titleBarInfo==1)) { settings.titleBarInfo=1; updateWindowTitle(); } if (ImGui::RadioButton("file_name.fur - Furnace##tbar2",settings.titleBarInfo==2)) { settings.titleBarInfo=2; updateWindowTitle(); } if (ImGui::RadioButton("/path/to/file.fur - Furnace##tbar3",settings.titleBarInfo==3)) { settings.titleBarInfo=3; updateWindowTitle(); } bool titleBarSysB=settings.titleBarSys; if (ImGui::Checkbox("Display system name on title bar",&titleBarSysB)) { settings.titleBarSys=titleBarSysB; updateWindowTitle(); } bool noMultiSystemB=settings.noMultiSystem; if (ImGui::Checkbox("Display chip names instead of \"multi-system\" in title bar",&noMultiSystemB)) { settings.noMultiSystem=noMultiSystemB; updateWindowTitle(); } ImGui::Text("Status bar:"); if (ImGui::RadioButton("Cursor details##sbar0",settings.statusDisplay==0)) { settings.statusDisplay=0; } if (ImGui::RadioButton("File path##sbar1",settings.statusDisplay==1)) { settings.statusDisplay=1; } if (ImGui::RadioButton("Cursor details or file path##sbar2",settings.statusDisplay==2)) { settings.statusDisplay=2; } if (ImGui::RadioButton("Nothing##sbar3",settings.statusDisplay==3)) { settings.statusDisplay=3; } ImGui::Text("Play/edit controls layout:"); if (ImGui::RadioButton("Classic##ecl0",settings.controlLayout==0)) { settings.controlLayout=0; } if (ImGui::RadioButton("Compact##ecl1",settings.controlLayout==1)) { settings.controlLayout=1; } if (ImGui::RadioButton("Compact (vertical)##ecl2",settings.controlLayout==2)) { settings.controlLayout=2; } if (ImGui::RadioButton("Split##ecl3",settings.controlLayout==3)) { settings.controlLayout=3; } ImGui::Text("FM parameter editor layout:"); if (ImGui::RadioButton("Modern##fml0",settings.fmLayout==0)) { settings.fmLayout=0; } if (ImGui::RadioButton("Compact (2x2, classic)##fml1",settings.fmLayout==1)) { settings.fmLayout=1; } if (ImGui::RadioButton("Compact (1x4)##fml2",settings.fmLayout==2)) { settings.fmLayout=2; } if (ImGui::RadioButton("Compact (4x1)##fml3",settings.fmLayout==3)) { settings.fmLayout=3; } if (ImGui::RadioButton("Alternate (2x2)##fml4",settings.fmLayout==4)) { settings.fmLayout=4; } if (ImGui::RadioButton("Alternate (1x4)##fml5",settings.fmLayout==5)) { settings.fmLayout=5; } if (ImGui::RadioButton("Alternate (4x1)##fml5",settings.fmLayout==6)) { settings.fmLayout=6; } ImGui::Text("Position of Sustain in FM editor:"); if (ImGui::RadioButton("Between Decay and Sustain Rate##susp0",settings.susPosition==0)) { settings.susPosition=0; } if (ImGui::RadioButton("After Release Rate##susp1",settings.susPosition==1)) { settings.susPosition=1; } ImGui::Separator(); ImGui::Text("Namco 163 chip name"); ImGui::SameLine(); ImGui::InputTextWithHint("##C163Name",DIV_C163_DEFAULT_NAME,&settings.c163Name); ImGui::Separator(); ImGui::Text("Channel colors:"); if (ImGui::RadioButton("Single##CHC0",settings.channelColors==0)) { settings.channelColors=0; } if (ImGui::RadioButton("Channel type##CHC1",settings.channelColors==1)) { settings.channelColors=1; } if (ImGui::RadioButton("Instrument type##CHC2",settings.channelColors==2)) { settings.channelColors=2; } ImGui::Text("Channel name colors:"); if (ImGui::RadioButton("Single##CTC0",settings.channelColors==0)) { settings.channelColors=0; } if (ImGui::RadioButton("Channel type##CTC1",settings.channelColors==1)) { settings.channelColors=1; } if (ImGui::RadioButton("Instrument type##CTC2",settings.channelColors==2)) { settings.channelColors=2; } ImGui::Text("Channel style:"); if (ImGui::RadioButton("Classic##CHS0",settings.channelStyle==0)) { settings.channelStyle=0; } if (ImGui::RadioButton("Line##CHS1",settings.channelStyle==1)) { settings.channelStyle=1; } if (ImGui::RadioButton("Round##CHS2",settings.channelStyle==2)) { settings.channelStyle=2; } if (ImGui::RadioButton("Split button##CHS3",settings.channelStyle==3)) { settings.channelStyle=3; } if (ImGui::RadioButton("Square border##CH42",settings.channelStyle==4)) { settings.channelStyle=4; } if (ImGui::RadioButton("Round border##CHS5",settings.channelStyle==5)) { settings.channelStyle=5; } ImGui::Text("Channel volume bar:"); if (ImGui::RadioButton("None##CHV0",settings.channelVolStyle==0)) { settings.channelVolStyle=0; } if (ImGui::RadioButton("Simple##CHV1",settings.channelVolStyle==1)) { settings.channelVolStyle=1; } if (ImGui::RadioButton("Stereo##CHV2",settings.channelVolStyle==2)) { settings.channelVolStyle=2; } if (ImGui::RadioButton("Real##CHV3",settings.channelVolStyle==3)) { settings.channelVolStyle=3; } ImGui::Text("Channel feedback style:"); if (ImGui::RadioButton("Off##CHF0",settings.channelFeedbackStyle==0)) { settings.channelFeedbackStyle=0; } if (ImGui::RadioButton("Note##CHF1",settings.channelFeedbackStyle==1)) { settings.channelFeedbackStyle=1; } if (ImGui::RadioButton("Volume##CHF2",settings.channelFeedbackStyle==2)) { settings.channelFeedbackStyle=2; } if (ImGui::RadioButton("Active##CHF3",settings.channelFeedbackStyle==3)) { settings.channelFeedbackStyle=3; } ImGui::Separator(); bool insEditColorizeB=settings.insEditColorize; if (ImGui::Checkbox("Colorize instrument editor using instrument type",&insEditColorizeB)) { settings.insEditColorize=insEditColorizeB; } bool separateFMColorsB=settings.separateFMColors; if (ImGui::Checkbox("Use separate colors for carriers/modulators in FM editor",&separateFMColorsB)) { settings.separateFMColors=separateFMColorsB; } bool unifiedDataViewB=settings.unifiedDataView; if (ImGui::Checkbox("Unified instrument/wavetable/sample list",&unifiedDataViewB)) { settings.unifiedDataView=unifiedDataViewB; } if (settings.unifiedDataView) { settings.horizontalDataView=0; } ImGui::BeginDisabled(settings.unifiedDataView); bool horizontalDataViewB=settings.horizontalDataView; if (ImGui::Checkbox("Horizontal instrument list",&horizontalDataViewB)) { settings.horizontalDataView=horizontalDataViewB; } ImGui::EndDisabled(); bool oplStandardWaveNamesB=settings.oplStandardWaveNames; if (ImGui::Checkbox("Use standard OPL waveform names",&oplStandardWaveNamesB)) { settings.oplStandardWaveNames=oplStandardWaveNamesB; } bool overflowHighlightB=settings.overflowHighlight; if (ImGui::Checkbox("Overflow pattern highlights",&overflowHighlightB)) { 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; } bool unsignedDetuneB=settings.unsignedDetune; if (ImGui::Checkbox("Unsigned FM detune values",&unsignedDetuneB)) { settings.unsignedDetune=unsignedDetuneB; } // sorry. temporarily disabled until ImGui has a way to add separators in tables arbitrarily. /*bool sysSeparatorsB=settings.sysSeparators; if (ImGui::Checkbox("Add separators between systems in Orders",&sysSeparatorsB)) { settings.sysSeparators=sysSeparatorsB; }*/ bool partyTimeB=settings.partyTime; if (ImGui::Checkbox("About screen party time",&partyTimeB)) { settings.partyTime=partyTimeB; } if (ImGui::IsItemHovered()) { ImGui::SetTooltip("Warning: may cause epileptic seizures."); } ImGui::Separator(); bool waveLayoutB=settings.waveLayout; if (ImGui::Checkbox("Use compact wave editor",&waveLayoutB)) { settings.waveLayout=waveLayoutB; } bool sampleLayoutB=settings.sampleLayout; if (ImGui::Checkbox("Use compact sample editor",&sampleLayoutB)) { settings.sampleLayout=sampleLayoutB; } bool oldMacroVSliderB=settings.oldMacroVSlider; if (ImGui::Checkbox("Use classic macro editor vertical slider",&oldMacroVSliderB)) { settings.oldMacroVSlider=oldMacroVSliderB; } bool roundedWindowsB=settings.roundedWindows; if (ImGui::Checkbox("Rounded window corners",&roundedWindowsB)) { settings.roundedWindows=roundedWindowsB; } bool roundedButtonsB=settings.roundedButtons; if (ImGui::Checkbox("Rounded buttons",&roundedButtonsB)) { settings.roundedButtons=roundedButtonsB; } bool roundedMenusB=settings.roundedMenus; if (ImGui::Checkbox("Rounded menu corners",&roundedMenusB)) { settings.roundedMenus=roundedMenusB; } bool frameBordersB=settings.frameBorders; if (ImGui::Checkbox("Borders around widgets",&frameBordersB)) { settings.frameBorders=frameBordersB; } ImGui::Separator(); ImGui::Text("Oscilloscope settings:"); bool oscRoundedCornersB=settings.oscRoundedCorners; if (ImGui::Checkbox("Rounded corners",&oscRoundedCornersB)) { settings.oscRoundedCorners=oscRoundedCornersB; } bool oscTakesEntireWindowB=settings.oscTakesEntireWindow; if (ImGui::Checkbox("Fill entire window",&oscTakesEntireWindowB)) { settings.oscTakesEntireWindow=oscTakesEntireWindowB; } bool oscEscapesBoundaryB=settings.oscEscapesBoundary; if (ImGui::Checkbox("Waveform goes out of bounds",&oscEscapesBoundaryB)) { settings.oscEscapesBoundary=oscEscapesBoundaryB; } bool oscBorderB=settings.oscBorder; if (ImGui::Checkbox("Border",&oscBorderB)) { settings.oscBorder=oscBorderB; } ImGui::Separator(); ImGui::Text("Pattern view spacing after:"); if (CWSliderInt("Note",&settings.noteCellSpacing,0,32)) { if (settings.noteCellSpacing<0) settings.noteCellSpacing=0; if (settings.noteCellSpacing>32) settings.noteCellSpacing=32; } if (CWSliderInt("Instrument",&settings.insCellSpacing,0,32)) { if (settings.insCellSpacing<0) settings.insCellSpacing=0; if (settings.insCellSpacing>32) settings.insCellSpacing=32; } if (CWSliderInt("Volume",&settings.volCellSpacing,0,32)) { if (settings.volCellSpacing<0) settings.volCellSpacing=0; if (settings.volCellSpacing>32) settings.volCellSpacing=32; } if (CWSliderInt("Effect",&settings.effectCellSpacing,0,32)) { if (settings.effectCellSpacing<0) settings.effectCellSpacing=0; if (settings.effectCellSpacing>32) settings.effectCellSpacing=32; } if (CWSliderInt("Effect value",&settings.effectValCellSpacing,0,32)) { if (settings.effectValCellSpacing<0) settings.effectValCellSpacing=0; if (settings.effectValCellSpacing>32) settings.effectValCellSpacing=32; } ImGui::Separator(); if (ImGui::TreeNode("Color scheme")) { if (ImGui::Button("Import")) { openFileDialog(GUI_FILE_IMPORT_COLORS); } ImGui::SameLine(); if (ImGui::Button("Export")) { openFileDialog(GUI_FILE_EXPORT_COLORS); } ImGui::SameLine(); if (ImGui::Button("Reset defaults")) { showWarning("Are you sure you want to reset the color scheme?",GUI_WARN_RESET_COLORS); } if (ImGui::TreeNode("General")) { ImGui::Text("Color scheme type:"); if (ImGui::RadioButton("Dark##gcb0",settings.guiColorsBase==0)) { settings.guiColorsBase=0; applyUISettings(false); } if (ImGui::RadioButton("Light##gcb1",settings.guiColorsBase==1)) { settings.guiColorsBase=1; applyUISettings(false); } if (ImGui::SliderInt("Frame shading",&settings.guiColorsShading,0,100,"%d%%")) { if (settings.guiColorsShading<0) settings.guiColorsShading=0; if (settings.guiColorsShading>100) settings.guiColorsShading=100; applyUISettings(false); } UI_COLOR_CONFIG(GUI_COLOR_BACKGROUND,"Background"); UI_COLOR_CONFIG(GUI_COLOR_FRAME_BACKGROUND,"Window background"); UI_COLOR_CONFIG(GUI_COLOR_MODAL_BACKDROP,"Modal backdrop"); UI_COLOR_CONFIG(GUI_COLOR_HEADER,"Header"); UI_COLOR_CONFIG(GUI_COLOR_TEXT,"Text"); UI_COLOR_CONFIG(GUI_COLOR_ACCENT_PRIMARY,"Primary"); UI_COLOR_CONFIG(GUI_COLOR_ACCENT_SECONDARY,"Secondary"); UI_COLOR_CONFIG(GUI_COLOR_BORDER,"Border"); UI_COLOR_CONFIG(GUI_COLOR_BORDER_SHADOW,"Border shadow"); UI_COLOR_CONFIG(GUI_COLOR_TOGGLE_ON,"Toggle on"); UI_COLOR_CONFIG(GUI_COLOR_TOGGLE_OFF,"Toggle off"); UI_COLOR_CONFIG(GUI_COLOR_EDITING,"Editing"); UI_COLOR_CONFIG(GUI_COLOR_SONG_LOOP,"Song loop"); UI_COLOR_CONFIG(GUI_COLOR_PLAYBACK_STAT,"Playback status"); ImGui::TreePop(); } if (ImGui::TreeNode("File Picker (built-in)")) { UI_COLOR_CONFIG(GUI_COLOR_FILE_DIR,"Directory"); UI_COLOR_CONFIG(GUI_COLOR_FILE_SONG_NATIVE,"Song (native)"); UI_COLOR_CONFIG(GUI_COLOR_FILE_SONG_IMPORT,"Song (import)"); UI_COLOR_CONFIG(GUI_COLOR_FILE_INSTR,"Instrument"); UI_COLOR_CONFIG(GUI_COLOR_FILE_AUDIO,"Audio"); UI_COLOR_CONFIG(GUI_COLOR_FILE_WAVE,"Wavetable"); UI_COLOR_CONFIG(GUI_COLOR_FILE_VGM,"VGM"); UI_COLOR_CONFIG(GUI_COLOR_FILE_FONT,"Font"); UI_COLOR_CONFIG(GUI_COLOR_FILE_OTHER,"Other"); ImGui::TreePop(); } if (ImGui::TreeNode("Oscilloscope")) { UI_COLOR_CONFIG(GUI_COLOR_OSC_BORDER,"Border"); UI_COLOR_CONFIG(GUI_COLOR_OSC_BG1,"Background (top-left)"); UI_COLOR_CONFIG(GUI_COLOR_OSC_BG2,"Background (top-right)"); UI_COLOR_CONFIG(GUI_COLOR_OSC_BG3,"Background (bottom-left)"); UI_COLOR_CONFIG(GUI_COLOR_OSC_BG4,"Background (bottom-right)"); UI_COLOR_CONFIG(GUI_COLOR_OSC_WAVE,"Waveform"); UI_COLOR_CONFIG(GUI_COLOR_OSC_WAVE_PEAK,"Waveform (clip)"); UI_COLOR_CONFIG(GUI_COLOR_OSC_REF,"Reference"); UI_COLOR_CONFIG(GUI_COLOR_OSC_GUIDE,"Guide"); ImGui::TreePop(); } if (ImGui::TreeNode("Volume Meter")) { UI_COLOR_CONFIG(GUI_COLOR_VOLMETER_LOW,"Low"); UI_COLOR_CONFIG(GUI_COLOR_VOLMETER_HIGH,"High"); UI_COLOR_CONFIG(GUI_COLOR_VOLMETER_PEAK,"Clip"); ImGui::TreePop(); } if (ImGui::TreeNode("Orders")) { UI_COLOR_CONFIG(GUI_COLOR_ORDER_ROW_INDEX,"Order number"); UI_COLOR_CONFIG(GUI_COLOR_ORDER_ACTIVE,"Current order background"); UI_COLOR_CONFIG(GUI_COLOR_ORDER_SIMILAR,"Similar patterns"); UI_COLOR_CONFIG(GUI_COLOR_ORDER_INACTIVE,"Inactive patterns"); ImGui::TreePop(); } if (ImGui::TreeNode("Envelope View")) { UI_COLOR_CONFIG(GUI_COLOR_FM_ENVELOPE,"Envelope"); UI_COLOR_CONFIG(GUI_COLOR_FM_ENVELOPE_SUS_GUIDE,"Sustain guide"); UI_COLOR_CONFIG(GUI_COLOR_FM_ENVELOPE_RELEASE,"Release"); ImGui::TreePop(); } if (ImGui::TreeNode("FM Editor")) { UI_COLOR_CONFIG(GUI_COLOR_FM_ALG_BG,"Algorithm background"); UI_COLOR_CONFIG(GUI_COLOR_FM_ALG_LINE,"Algorithm lines"); UI_COLOR_CONFIG(GUI_COLOR_FM_MOD,"Modulator"); UI_COLOR_CONFIG(GUI_COLOR_FM_CAR,"Carrier"); UI_COLOR_CONFIG(GUI_COLOR_FM_SSG,"SSG-EG"); UI_COLOR_CONFIG(GUI_COLOR_FM_WAVE,"Waveform"); ImGui::TextWrapped("(the following colors only apply when \"Use separate colors for carriers/modulators in FM editor\" is on!)"); UI_COLOR_CONFIG(GUI_COLOR_FM_PRIMARY_MOD,"Mod. accent (primary)"); UI_COLOR_CONFIG(GUI_COLOR_FM_SECONDARY_MOD,"Mod. accent (secondary)"); UI_COLOR_CONFIG(GUI_COLOR_FM_BORDER_MOD,"Mod. border"); UI_COLOR_CONFIG(GUI_COLOR_FM_BORDER_SHADOW_MOD,"Mod. border shadow"); UI_COLOR_CONFIG(GUI_COLOR_FM_PRIMARY_CAR,"Car. accent (primary"); UI_COLOR_CONFIG(GUI_COLOR_FM_SECONDARY_CAR,"Car. accent (secondary)"); UI_COLOR_CONFIG(GUI_COLOR_FM_BORDER_CAR,"Car. border"); UI_COLOR_CONFIG(GUI_COLOR_FM_BORDER_SHADOW_CAR,"Car. border shadow"); ImGui::TreePop(); } if (ImGui::TreeNode("Macro Editor")) { UI_COLOR_CONFIG(GUI_COLOR_MACRO_VOLUME,"Volume"); UI_COLOR_CONFIG(GUI_COLOR_MACRO_PITCH,"Pitch"); UI_COLOR_CONFIG(GUI_COLOR_MACRO_WAVE,"Wave"); UI_COLOR_CONFIG(GUI_COLOR_MACRO_OTHER,"Other"); ImGui::TreePop(); } if (ImGui::TreeNode("Instrument Types")) { UI_COLOR_CONFIG(GUI_COLOR_INSTR_FM,"FM (4-operator)"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_STD,"Standard"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_GB,"Game Boy"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_C64,"C64"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_AMIGA,"Amiga/Sample"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_PCE,"PC Engine"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_AY,"AY-3-8910/SSG"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_AY8930,"AY8930"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_TIA,"TIA"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_SAA1099,"SAA1099"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_VIC,"VIC"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_PET,"PET"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_VRC6,"VRC6"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_VRC6_SAW,"VRC6 (saw)"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_OPLL,"FM (OPLL)"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_OPL,"FM (OPL)"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_FDS,"FDS"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_VBOY,"Virtual Boy"); // special case String c163Label=fmt::sprintf("%s##CC_GUI_COLOR_INSTR_N163",settings.c163Name); if (ImGui::ColorEdit4(c163Label.c_str(),(float*)&uiColors[GUI_COLOR_INSTR_N163])) { applyUISettings(false); } UI_COLOR_CONFIG(GUI_COLOR_INSTR_SCC,"Konami SCC"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_OPZ,"FM (OPZ)"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_POKEY,"POKEY"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_BEEPER,"PC Beeper"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_SWAN,"WonderSwan"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_MIKEY,"Lynx"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_VERA,"VERA"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_X1_010,"X1-010"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_ES5506,"ES5506"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_MULTIPCM,"MultiPCM"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_SNES,"SNES"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_SU,"Sound Unit"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_NAMCO,"Namco WSG"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_UNKNOWN,"Other/Unknown"); ImGui::TreePop(); } if (ImGui::TreeNode("Channel")) { UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_FM,"FM"); UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_PULSE,"Pulse"); UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_NOISE,"Noise"); UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_PCM,"PCM"); UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_WAVE,"Wave"); UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_OP,"FM operator"); UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_MUTED,"Muted"); ImGui::TreePop(); } if (ImGui::TreeNode("Pattern")) { UI_COLOR_CONFIG(GUI_COLOR_PATTERN_PLAY_HEAD,"Playhead"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_CURSOR,"Cursor"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_CURSOR_HOVER,"Cursor (hovered)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_CURSOR_ACTIVE,"Cursor (clicked)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_SELECTION,"Selection"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_SELECTION_HOVER,"Selection (hovered)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_SELECTION_ACTIVE,"Selection (clicked)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_HI_1,"Highlight 1"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_HI_2,"Highlight 2"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_ROW_INDEX,"Row number"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_ROW_INDEX_HI1,"Row number (highlight 1)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_ROW_INDEX_HI2,"Row number (highlight 2)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_ACTIVE,"Note"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_ACTIVE_HI1,"Note (highlight 1)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_ACTIVE_HI2,"Note (highlight 2)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_INACTIVE,"Blank"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_INACTIVE_HI1,"Blank (highlight 1)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_INACTIVE_HI2,"Blank (highlight 2)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_INS,"Instrument"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_INS_WARN,"Instrument (invalid type)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_INS_ERROR,"Instrument (out of range)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_VOLUME_MIN,"Volume (0%)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_VOLUME_HALF,"Volume (50%)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_VOLUME_MAX,"Volume (100%)"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_INVALID,"Invalid effect"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_PITCH,"Pitch effect"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_VOLUME,"Volume effect"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_PANNING,"Panning effect"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_SONG,"Song effect"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_TIME,"Time effect"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_SPEED,"Speed effect"); UI_COLOR_CONFIG(GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY,"Primary specific effect"); 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"); ImGui::TreePop(); } if (ImGui::TreeNode("Pattern Manager")) { UI_COLOR_CONFIG(GUI_COLOR_PAT_MANAGER_NULL,"Unallocated"); UI_COLOR_CONFIG(GUI_COLOR_PAT_MANAGER_UNUSED,"Unused"); UI_COLOR_CONFIG(GUI_COLOR_PAT_MANAGER_USED,"Used"); UI_COLOR_CONFIG(GUI_COLOR_PAT_MANAGER_OVERUSED,"Overused"); UI_COLOR_CONFIG(GUI_COLOR_PAT_MANAGER_EXTREMELY_OVERUSED,"Really overused"); UI_COLOR_CONFIG(GUI_COLOR_PAT_MANAGER_COMBO_BREAKER,"Combo Breaker"); ImGui::TreePop(); } if (ImGui::TreeNode("Piano")) { UI_COLOR_CONFIG(GUI_COLOR_PIANO_BACKGROUND,"Background"); UI_COLOR_CONFIG(GUI_COLOR_PIANO_KEY_TOP,"Upper key"); UI_COLOR_CONFIG(GUI_COLOR_PIANO_KEY_TOP_HIT,"Upper key (feedback)"); UI_COLOR_CONFIG(GUI_COLOR_PIANO_KEY_TOP_ACTIVE,"Upper key (pressed)"); UI_COLOR_CONFIG(GUI_COLOR_PIANO_KEY_BOTTOM,"Lower key"); UI_COLOR_CONFIG(GUI_COLOR_PIANO_KEY_BOTTOM_HIT,"Lower key (feedback)"); UI_COLOR_CONFIG(GUI_COLOR_PIANO_KEY_BOTTOM_ACTIVE,"Lower key (pressed)"); ImGui::TreePop(); } if (ImGui::TreeNode("Log Viewer")) { UI_COLOR_CONFIG(GUI_COLOR_LOGLEVEL_ERROR,"Log level: Error"); UI_COLOR_CONFIG(GUI_COLOR_LOGLEVEL_WARNING,"Log level: Warning"); UI_COLOR_CONFIG(GUI_COLOR_LOGLEVEL_INFO,"Log level: Info"); UI_COLOR_CONFIG(GUI_COLOR_LOGLEVEL_DEBUG,"Log level: Debug"); UI_COLOR_CONFIG(GUI_COLOR_LOGLEVEL_TRACE,"Log level: Trace/Verbose"); ImGui::TreePop(); } ImGui::TreePop(); } } ImGui::EndChild(); ImGui::EndTabItem(); } if (ImGui::BeginTabItem("Keyboard")) { ImVec2 settingsViewSize=ImGui::GetContentRegionAvail(); settingsViewSize.y-=ImGui::GetFrameHeight()+ImGui::GetStyle().WindowPadding.y; if (ImGui::BeginChild("SettingsView",settingsViewSize)) { if (ImGui::Button("Import")) { openFileDialog(GUI_FILE_IMPORT_KEYBINDS); } ImGui::SameLine(); if (ImGui::Button("Export")) { openFileDialog(GUI_FILE_EXPORT_KEYBINDS); } ImGui::SameLine(); if (ImGui::Button("Reset defaults")) { showWarning("Are you sure you want to reset the keyboard settings?",GUI_WARN_RESET_KEYBINDS); } if (ImGui::TreeNode("Global hotkeys")) { KEYBIND_CONFIG_BEGIN("keysGlobal"); UI_KEYBIND_CONFIG(GUI_ACTION_OPEN); UI_KEYBIND_CONFIG(GUI_ACTION_OPEN_BACKUP); UI_KEYBIND_CONFIG(GUI_ACTION_SAVE); UI_KEYBIND_CONFIG(GUI_ACTION_SAVE_AS); UI_KEYBIND_CONFIG(GUI_ACTION_UNDO); UI_KEYBIND_CONFIG(GUI_ACTION_REDO); UI_KEYBIND_CONFIG(GUI_ACTION_PLAY_TOGGLE); UI_KEYBIND_CONFIG(GUI_ACTION_PLAY); UI_KEYBIND_CONFIG(GUI_ACTION_STOP); UI_KEYBIND_CONFIG(GUI_ACTION_PLAY_START); UI_KEYBIND_CONFIG(GUI_ACTION_PLAY_REPEAT); UI_KEYBIND_CONFIG(GUI_ACTION_PLAY_CURSOR); UI_KEYBIND_CONFIG(GUI_ACTION_STEP_ONE); UI_KEYBIND_CONFIG(GUI_ACTION_OCTAVE_UP); UI_KEYBIND_CONFIG(GUI_ACTION_OCTAVE_DOWN); UI_KEYBIND_CONFIG(GUI_ACTION_INS_UP); UI_KEYBIND_CONFIG(GUI_ACTION_INS_DOWN); UI_KEYBIND_CONFIG(GUI_ACTION_STEP_UP); UI_KEYBIND_CONFIG(GUI_ACTION_STEP_DOWN); UI_KEYBIND_CONFIG(GUI_ACTION_TOGGLE_EDIT); UI_KEYBIND_CONFIG(GUI_ACTION_METRONOME); UI_KEYBIND_CONFIG(GUI_ACTION_REPEAT_PATTERN); UI_KEYBIND_CONFIG(GUI_ACTION_FOLLOW_ORDERS); UI_KEYBIND_CONFIG(GUI_ACTION_FOLLOW_PATTERN); UI_KEYBIND_CONFIG(GUI_ACTION_FULLSCREEN); UI_KEYBIND_CONFIG(GUI_ACTION_PANIC); KEYBIND_CONFIG_END; ImGui::TreePop(); } if (ImGui::TreeNode("Window activation")) { KEYBIND_CONFIG_BEGIN("keysWindow"); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_EDIT_CONTROLS); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_ORDERS); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_INS_LIST); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_INS_EDIT); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_SONG_INFO); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_SUBSONGS); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_PATTERN); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_WAVE_LIST); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_WAVE_EDIT); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_SAMPLE_LIST); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_SAMPLE_EDIT); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_ABOUT); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_SETTINGS); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_MIXER); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_DEBUG); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_OSCILLOSCOPE); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_CHAN_OSC); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_EFFECT_LIST); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_VOL_METER); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_STATS); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_COMPAT_FLAGS); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_PIANO); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_NOTES); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_CHANNELS); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_REGISTER_VIEW); UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_LOG); UI_KEYBIND_CONFIG(GUI_ACTION_COLLAPSE_WINDOW); UI_KEYBIND_CONFIG(GUI_ACTION_CLOSE_WINDOW); KEYBIND_CONFIG_END; ImGui::TreePop(); } if (ImGui::TreeNode("Note input")) { std::vector sorted; if (ImGui::BeginTable("keysNoteInput",4)) { for (std::map::value_type& i: noteKeys) { std::vector::iterator j; for (j=sorted.begin(); j!=sorted.end(); j++) { if (j->val>i.second) { break; } } sorted.insert(j,MappedInput(i.first,i.second)); } static char id[4096]; ImGui::TableNextRow(ImGuiTableRowFlags_Headers); ImGui::TableNextColumn(); ImGui::Text("Key"); ImGui::TableNextColumn(); ImGui::Text("Type"); ImGui::TableNextColumn(); ImGui::Text("Value"); ImGui::TableNextColumn(); ImGui::Text("Remove"); for (MappedInput& i: sorted) { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text("%s",SDL_GetScancodeName((SDL_Scancode)i.scan)); ImGui::TableNextColumn(); if (i.val==102) { snprintf(id,4095,"Macro release##SNType_%d",i.scan); if (ImGui::Button(id)) { noteKeys[i.scan]=0; } } else if (i.val==101) { snprintf(id,4095,"Note release##SNType_%d",i.scan); if (ImGui::Button(id)) { noteKeys[i.scan]=102; } } else if (i.val==100) { snprintf(id,4095,"Note off##SNType_%d",i.scan); if (ImGui::Button(id)) { noteKeys[i.scan]=101; } } else { snprintf(id,4095,"Note##SNType_%d",i.scan); if (ImGui::Button(id)) { noteKeys[i.scan]=100; } } ImGui::TableNextColumn(); if (i.val<100) { snprintf(id,4095,"##SNValue_%d",i.scan); if (ImGui::InputInt(id,&i.val,1,1)) { if (i.val<0) i.val=0; if (i.val>96) i.val=96; noteKeys[i.scan]=i.val; } } ImGui::TableNextColumn(); snprintf(id,4095,ICON_FA_TIMES "##SNRemove_%d",i.scan); if (ImGui::Button(id)) { noteKeys.erase(i.scan); } } ImGui::EndTable(); if (ImGui::BeginCombo("##SNAddNew","Add...")) { for (int i=0; i