Merge branch 'tildearrow:master' into master

This commit is contained in:
BlastBrothers 2022-02-22 20:09:41 -05:00 committed by GitHub
commit 9237a0f6fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
64 changed files with 3580 additions and 148 deletions

View file

@ -154,7 +154,7 @@ bool FurnaceGUI::decodeNote(const char* what, short& note, short& octave) {
String FurnaceGUI::encodeKeyMap(std::map<int,int>& map) {
String ret;
for (std::map<int,int>::value_type& i: map) {
ret+=fmt::printf("%d:%d;",i.first,i.second);
ret+=fmt::sprintf("%d:%d;",i.first,i.second);
}
return ret;
}
@ -1156,6 +1156,10 @@ void FurnaceGUI::drawInsList() {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_SWAN]);
name=fmt::sprintf(ICON_FA_GAMEPAD " %.2X: %s##_INS%d\n",i,ins->name,i);
break;
case DIV_INS_MIKEY:
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_MIKEY]);
name=fmt::sprintf(ICON_FA_BAR_CHART " %.2X: %s##_INS%d\n",i,ins->name,i);
break;
default:
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_UNKNOWN]);
name=fmt::sprintf(ICON_FA_QUESTION " %.2X: %s##_INS%d\n",i,ins->name,i);
@ -1267,11 +1271,11 @@ void FurnaceGUI::drawSampleEdit() {
ImGui::Text("Length: %d",sample->length);
if (ImGui::InputInt("Rate (Hz)",&sample->rate,10,200)) {
if (sample->rate<100) sample->rate=100;
if (sample->rate>32000) sample->rate=32000;
if (sample->rate>96000) sample->rate=96000;
}
if (ImGui::InputInt("Pitch of C-4 (Hz)",&sample->centerRate,10,200)) {
if (sample->centerRate<100) sample->centerRate=100;
if (sample->centerRate>32000) sample->centerRate=32000;
if (sample->centerRate>65535) sample->centerRate=65535;
}
ImGui::Text("effective rate: %dHz",e->getEffectiveSampleRate(sample->rate));
bool doLoop=(sample->loopStart>=0);
@ -1379,7 +1383,6 @@ void FurnaceGUI::drawOsc() {
if (!oscOpen) return;
ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0,0));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0,0));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0));
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing,ImVec2(0,0));
if (ImGui::Begin("Oscilloscope",&oscOpen)) {
@ -1393,7 +1396,7 @@ void FurnaceGUI::drawOsc() {
ImGui::PlotLines("##SingleOsc",values,512,0,NULL,-1.0f,1.0f,ImGui::GetContentRegionAvail());
ImGui::EndDisabled();
}
ImGui::PopStyleVar(4);
ImGui::PopStyleVar(3);
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_OSCILLOSCOPE;
ImGui::End();
}
@ -1487,7 +1490,7 @@ void FurnaceGUI::drawVolMeter() {
ImGui::End();
}
const char* aboutLine[57]={
const char* aboutLine[]={
"tildearrow",
"is proud to present",
"",
@ -1497,8 +1500,39 @@ const char* aboutLine[57]={
"compatible with DefleMask modules.",
"",
"zero disassembly.",
"zero reverse-engineering.",
"only time and dedication.",
"just clean-room design,",
"time and dedication.",
"",
"> CREDITS <",
"",
"-- program --",
"tildearrow",
"",
"-- graphics --",
"tildearrow",
"",
"-- documentation --",
"tildearrow",
"freq-mod",
"nicco1690",
"DeMOSic",
"cam900",
"",
"-- demo songs --",
"0x5066",
"breakthetargets",
"kleeder",
"NikonTeen",
"SuperJet Spade",
"TheDuccinator",
"tildearrow",
"Ultraprogramer",
"",
"-- additional feedback/fixes --",
"fd",
"OPNA2608",
"plane",
"TheEssem",
"",
"powered by:",
"Dear ImGui by Omar Cornut",
@ -1518,6 +1552,7 @@ const char* aboutLine[57]={
"puNES by FHorse",
"reSID by Dag Lem",
"Stella by Stella Team",
"QSound emulator by Ian Karlsson and Valley Bell",
"",
"greetings to:",
"Delek",
@ -1525,7 +1560,8 @@ const char* aboutLine[57]={
"ILLUMIDARO",
"all members of Deflers of Noice!",
"",
"copyright © 2021-2022 tildearrow.",
"copyright © 2021-2022 tildearrow",
"(and contributors).",
"licensed under GPLv2+! see",
"LICENSE for more information.",
"",
@ -1544,9 +1580,15 @@ const char* aboutLine[57]={
"",
"it also comes with ABSOLUTELY NO WARRANTY.",
"",
"thanks to all contributors!"
"look out for Furnace 0.6 coming somewhere",
"before the equinox with more systems",
"and plenty of other things...",
"",
"thanks to all contributors/bug reporters!"
};
const size_t aboutCount = sizeof(aboutLine)/sizeof(aboutLine[0]);
void FurnaceGUI::drawAbout() {
// do stuff
if (ImGui::Begin("About Furnace",NULL,ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoDocking|ImGuiWindowFlags_NoTitleBar)) {
@ -1586,7 +1628,7 @@ void FurnaceGUI::drawAbout() {
skip=false;
skip2=false;
for (int i=(-fmod(160-(aboutSin*2),160))*2; i<scrW; i+=160) {
for (int i=(-160+fmod(aboutSin*2,160))*2; i<scrW; i+=160) {
skip2=!skip2;
skip=skip2;
for (int j=(-240-cos(double(aboutSin*M_PI/300.0))*240.0)*2; j<scrH; j+=160) {
@ -1596,7 +1638,7 @@ void FurnaceGUI::drawAbout() {
}
}
for (int i=0; i<56; i++) {
for (size_t i=0; i<aboutCount; i++) {
double posX=(scrW*dpiScale/2.0)+(sin(double(i)*0.5+double(aboutScroll)/90.0)*120*dpiScale)-(ImGui::CalcTextSize(aboutLine[i]).x*0.5);
double posY=(scrH-aboutScroll+42*i)*dpiScale;
if (posY<-80*dpiScale || posY>scrH*dpiScale) continue;
@ -1626,7 +1668,7 @@ void FurnaceGUI::drawAbout() {
while (aboutHue>1) aboutHue--;
while (aboutSin>=2400) aboutSin-=2400;
if (aboutScroll>(42*57+scrH)) aboutScroll=-20;
if (aboutScroll>(42*aboutCount+scrH)) aboutScroll=-20;
}
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_ABOUT;
ImGui::End();
@ -1863,12 +1905,16 @@ void FurnaceGUI::drawStats() {
if (ImGui::Begin("Statistics",&statsOpen)) {
String adpcmUsage=fmt::sprintf("%d/16384KB",e->adpcmMemLen/1024);
String adpcmBUsage=fmt::sprintf("%d/16384KB",e->adpcmBMemLen/1024);
String qsoundUsage=fmt::sprintf("%d/16384KB",e->qsoundMemLen/1024);
ImGui::Text("ADPCM-A");
ImGui::SameLine();
ImGui::ProgressBar(((float)e->adpcmMemLen)/16777216.0f,ImVec2(-FLT_MIN,0),adpcmUsage.c_str());
ImGui::Text("ADPCM-B");
ImGui::SameLine();
ImGui::ProgressBar(((float)e->adpcmBMemLen)/16777216.0f,ImVec2(-FLT_MIN,0),adpcmBUsage.c_str());
ImGui::Text("QSound");
ImGui::SameLine();
ImGui::ProgressBar(((float)e->qsoundMemLen)/16777216.0f,ImVec2(-FLT_MIN,0),qsoundUsage.c_str());
}
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_STATS;
ImGui::End();
@ -2039,6 +2085,56 @@ void FurnaceGUI::drawChannels() {
ImGui::End();
}
void FurnaceGUI::drawRegView() {
if (nextWindow==GUI_WINDOW_REGISTER_VIEW) {
channelsOpen=true;
ImGui::SetNextWindowFocus();
nextWindow=GUI_WINDOW_NOTHING;
}
if (!regViewOpen) return;
if (ImGui::Begin("Register View",&regViewOpen)) {
for (int i=0; i<e->song.systemLen; i++) {
ImGui::Text("%d. %s",i+1,getSystemName(e->song.system[i]));
int size=0;
int depth=8;
unsigned char* regPool=e->getRegisterPool(i,size,depth);
unsigned short* regPoolW=(unsigned short*) regPool;
if (regPool==NULL) {
ImGui::Text("- no register pool available");
} else {
ImGui::PushFont(patFont);
if (ImGui::BeginTable("Memory",17)) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
for (int i=0; i<16; i++) {
ImGui::TableNextColumn();
ImGui::TextColored(uiColors[GUI_COLOR_PATTERN_ROW_INDEX]," %X",i);
}
for (int i=0; i<=((size-1)>>4); i++) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextColored(uiColors[GUI_COLOR_PATTERN_ROW_INDEX],"%.2X",i*16);
for (int j=0; j<16; j++) {
ImGui::TableNextColumn();
if (i*16+j>=size) continue;
if(depth == 8)
ImGui::Text("%.2x",regPool[i*16+j]);
else if(depth == 16)
ImGui::Text("%.4x",regPoolW[i*16+j]);
else
ImGui::Text("??");
}
}
ImGui::EndTable();
}
ImGui::PopFont();
}
}
}
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_REGISTER_VIEW;
ImGui::End();
}
void FurnaceGUI::startSelection(int xCoarse, int xFine, int y) {
if (xCoarse!=selStart.xCoarse || xFine!=selStart.xFine || y!=selStart.y) {
curNibble=false;
@ -2728,7 +2824,7 @@ void FurnaceGUI::doPaste() {
invalidData=true;
break;
}
if (iFine<(3+e->song.pat[cursor.xCoarse].effectRows*2)) pat->data[j][iFine+1]=val;
if (iFine<(3+e->song.pat[iCoarse].effectRows*2)) pat->data[j][iFine+1]=val;
}
}
iFine++;
@ -2822,6 +2918,7 @@ void FurnaceGUI::doRedo() {
void FurnaceGUI::play(int row) {
e->walkSong(loopOrder,loopRow,loopEnd);
memset(lastIns,-1,sizeof(int)*DIV_MAX_CHANS);
if (row>0) {
e->playToRow(row);
} else {
@ -3052,6 +3149,9 @@ void FurnaceGUI::doAction(int what) {
case GUI_ACTION_WINDOW_CHANNELS:
nextWindow=GUI_WINDOW_CHANNELS;
break;
case GUI_ACTION_WINDOW_REGISTER_VIEW:
nextWindow=GUI_WINDOW_REGISTER_VIEW;
break;
case GUI_ACTION_COLLAPSE_WINDOW:
collapseWindow=true;
@ -3121,6 +3221,9 @@ void FurnaceGUI::doAction(int what) {
case GUI_WINDOW_CHANNELS:
channelsOpen=false;
break;
case GUI_WINDOW_REGISTER_VIEW:
regViewOpen=false;
break;
default:
break;
}
@ -4390,6 +4493,8 @@ bool FurnaceGUI::loop() {
sysAddOption(DIV_SYSTEM_TIA);
sysAddOption(DIV_SYSTEM_SAA1099);
sysAddOption(DIV_SYSTEM_AY8930);
sysAddOption(DIV_SYSTEM_LYNX);
sysAddOption(DIV_SYSTEM_QSOUND);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("configure system...")) {
@ -4555,6 +4660,23 @@ bool FurnaceGUI::loop() {
}
break;
}
case DIV_SYSTEM_QSOUND: {
ImGui::Text("Echo delay:");
int echoBufSize=2725 - (flags & 4095);
if (ImGui::SliderInt("##EchoBufSize",&echoBufSize,0,2725)) {
if (echoBufSize<0) echoBufSize=0;
if (echoBufSize>2725) echoBufSize=2725;
e->setSysFlags(i,(flags & ~4095) | ((2725 - echoBufSize) & 4095),restart);
}
ImGui::Text("Echo feedback:");
int echoFeedback=(flags>>12)&255;
if (ImGui::SliderInt("##EchoFeedback",&echoFeedback,0,255)) {
if (echoFeedback<0) echoFeedback=0;
if (echoFeedback>255) echoFeedback=255;
e->setSysFlags(i,(flags & ~(255 << 12)) | ((echoFeedback & 255) << 12),restart);
}
break;
}
case DIV_SYSTEM_GB:
case DIV_SYSTEM_YM2610:
case DIV_SYSTEM_YM2610_EXT:
@ -4597,6 +4719,8 @@ bool FurnaceGUI::loop() {
sysChangeOption(i,DIV_SYSTEM_TIA);
sysChangeOption(i,DIV_SYSTEM_SAA1099);
sysChangeOption(i,DIV_SYSTEM_AY8930);
sysChangeOption(i,DIV_SYSTEM_LYNX);
sysChangeOption(i,DIV_SYSTEM_QSOUND);
ImGui::EndMenu();
}
}
@ -4641,6 +4765,10 @@ bool FurnaceGUI::loop() {
ImGui::EndMenu();
}
if (ImGui::BeginMenu("settings")) {
if (ImGui::MenuItem("reset layout")) {
ImGui::LoadIniSettingsFromMemory(defaultLayout);
ImGui::SaveIniSettingsToDisk(finalLayoutPath);
}
if (ImGui::MenuItem("settings...",BIND_FOR(GUI_ACTION_WINDOW_SETTINGS))) {
syncSettings();
settingsOpen=true;
@ -4667,6 +4795,7 @@ bool FurnaceGUI::loop() {
if (ImGui::MenuItem("piano/input pad",BIND_FOR(GUI_ACTION_WINDOW_PIANO),pianoOpen)) pianoOpen=!pianoOpen;
if (ImGui::MenuItem("oscilloscope",BIND_FOR(GUI_ACTION_WINDOW_OSCILLOSCOPE),oscOpen)) oscOpen=!oscOpen;
if (ImGui::MenuItem("volume meter",BIND_FOR(GUI_ACTION_WINDOW_VOL_METER),volMeterOpen)) volMeterOpen=!volMeterOpen;
if (ImGui::MenuItem("register view",BIND_FOR(GUI_ACTION_WINDOW_REGISTER_VIEW),regViewOpen)) regViewOpen=!regViewOpen;
if (ImGui::MenuItem("statistics",BIND_FOR(GUI_ACTION_WINDOW_STATS),statsOpen)) statsOpen=!statsOpen;
ImGui::EndMenu();
@ -4770,6 +4899,7 @@ bool FurnaceGUI::loop() {
drawPiano();
drawNotes();
drawChannels();
drawRegView();
if (ImGuiFileDialog::Instance()->Display("FileDialog",ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove,ImVec2(600.0f*dpiScale,400.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale))) {
//ImGui::GetIO().ConfigFlags&=~ImGuiConfigFlags_NavEnableKeyboard;
@ -5132,6 +5262,7 @@ void FurnaceGUI::applyUISettings() {
GET_UI_COLOR(GUI_COLOR_INSTR_POKEY,ImVec4(0.5f,1.0f,0.3f,1.0f));
GET_UI_COLOR(GUI_COLOR_INSTR_BEEPER,ImVec4(0.0f,1.0f,0.0f,1.0f));
GET_UI_COLOR(GUI_COLOR_INSTR_SWAN,ImVec4(0.3f,0.5f,1.0f,1.0f));
GET_UI_COLOR(GUI_COLOR_INSTR_MIKEY,ImVec4(0.5f,1.0f,0.3f,1.0f));
GET_UI_COLOR(GUI_COLOR_INSTR_UNKNOWN,ImVec4(0.3f,0.3f,0.3f,1.0f));
GET_UI_COLOR(GUI_COLOR_CHANNEL_FM,ImVec4(0.2f,0.8f,1.0f,1.0f));
GET_UI_COLOR(GUI_COLOR_CHANNEL_PULSE,ImVec4(0.4f,1.0f,0.2f,1.0f));
@ -5380,6 +5511,7 @@ bool FurnaceGUI::init() {
pianoOpen=e->getConfBool("pianoOpen",false);
notesOpen=e->getConfBool("notesOpen",false);
channelsOpen=e->getConfBool("channelsOpen",false);
regViewOpen=e->getConfBool("regViewOpen",false);
syncSettings();
@ -5533,6 +5665,7 @@ bool FurnaceGUI::finish() {
e->setConf("pianoOpen",pianoOpen);
e->setConf("notesOpen",notesOpen);
e->setConf("channelsOpen",channelsOpen);
e->setConf("regViewOpen",regViewOpen);
// commit last window size
e->setConf("lastWindowWidth",scrW);
@ -5602,6 +5735,7 @@ FurnaceGUI::FurnaceGUI():
pianoOpen(false),
notesOpen(false),
channelsOpen(false),
regViewOpen(false),
selecting(false),
curNibble(false),
orderNibble(false),
@ -5658,6 +5792,7 @@ FurnaceGUI::FurnaceGUI():
oldOrdersLen(0) {
// octave 1
/*
noteKeys[SDL_SCANCODE_Z]=0;
noteKeys[SDL_SCANCODE_S]=1;
noteKeys[SDL_SCANCODE_X]=2;
@ -5703,6 +5838,7 @@ FurnaceGUI::FurnaceGUI():
// env release
noteKeys[SDL_SCANCODE_GRAVE]=102;
*/
// value keys
valueKeys[SDLK_0]=0;
@ -5741,4 +5877,5 @@ FurnaceGUI::FurnaceGUI():
memset(patChanX,0,sizeof(float)*(DIV_MAX_CHANS+1));
memset(patChanSlideY,0,sizeof(float)*(DIV_MAX_CHANS+1));
memset(lastIns,-1,sizeof(int)*DIV_MAX_CHANS);
}

View file

@ -66,6 +66,7 @@ enum FurnaceGUIColors {
GUI_COLOR_INSTR_POKEY,
GUI_COLOR_INSTR_BEEPER,
GUI_COLOR_INSTR_SWAN,
GUI_COLOR_INSTR_MIKEY,
GUI_COLOR_INSTR_UNKNOWN,
GUI_COLOR_CHANNEL_FM,
GUI_COLOR_CHANNEL_PULSE,
@ -127,6 +128,7 @@ enum FurnaceGUIWindows {
GUI_WINDOW_PIANO,
GUI_WINDOW_NOTES,
GUI_WINDOW_CHANNELS,
GUI_WINDOW_REGISTER_VIEW
};
enum FurnaceGUIFileDialogs {
@ -209,6 +211,7 @@ enum FurnaceGUIActions {
GUI_ACTION_WINDOW_PIANO,
GUI_ACTION_WINDOW_NOTES,
GUI_ACTION_WINDOW_CHANNELS,
GUI_ACTION_WINDOW_REGISTER_VIEW,
GUI_ACTION_COLLAPSE_WINDOW,
GUI_ACTION_CLOSE_WINDOW,
@ -520,7 +523,7 @@ class FurnaceGUI {
bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen;
bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen;
bool mixerOpen, debugOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen;
bool pianoOpen, notesOpen, channelsOpen;
bool pianoOpen, notesOpen, channelsOpen, regViewOpen;
SelectionPoint selStart, selEnd, cursor;
bool selecting, curNibble, orderNibble, followOrders, followPattern, changeAllOrders;
bool collapseWindow, demandScrollX, fancyPattern, wantPatName;
@ -567,9 +570,9 @@ class FurnaceGUI {
int samplePreviewNote;
// SDL_Scancode,int
std::map<SDL_Scancode,int> noteKeys;
std::map<int,int> noteKeys;
// SDL_Keycode,int
std::map<SDL_Keycode,int> valueKeys;
std::map<int,int> valueKeys;
int arpMacroScroll;
@ -620,6 +623,7 @@ class FurnaceGUI {
std::deque<UndoStep> redoHist;
float keyHit[DIV_MAX_CHANS];
int lastIns[DIV_MAX_CHANS];
void drawAlgorithm(unsigned char alg, FurnaceGUIFMAlgs algType, const ImVec2& size);
void drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr, unsigned char d2r, unsigned char rr, unsigned char sl, const ImVec2& size);
@ -647,6 +651,7 @@ class FurnaceGUI {
void drawPiano();
void drawNotes();
void drawChannels();
void drawRegView();
void drawAbout();
void drawSettings();
void drawDebug();

View file

@ -26,7 +26,7 @@
#include <fmt/printf.h>
#include "plot_nolerp.h"
const char* insTypes[23]={
const char* insTypes[24]={
"Standard",
"FM (4-operator)",
"Game Boy",
@ -49,7 +49,8 @@ const char* insTypes[23]={
"FM (OPZ)",
"POKEY",
"PC Beeper",
"WonderSwan"
"WonderSwan",
"Atari Lynx"
};
const char* ssgEnvTypes[8]={
@ -131,6 +132,10 @@ const char* c64SpecialBits[3]={
"sync", "ring", NULL
};
const char* mikeyFeedbackBits[11] = {
"0", "1", "2", "3", "4", "5", "7", "10", "11", "int", NULL
};
const int orderedOps[4]={
0, 2, 1, 3
};
@ -506,7 +511,7 @@ void FurnaceGUI::drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr,
#define PARAMETER modified=true; e->notifyInsChange(curIns);
#define NORMAL_MACRO(macro,macroLen,macroLoop,macroRel,macroMin,macroHeight,macroName,displayName,displayHeight,displayLoop,bitfield,bfVal,drawSlider,sliderVal,sliderLow,macroDispMin,bitOff,macroMode,macroColor,mmlStr,macroAMin,macroAMax,hoverFunc) \
#define NORMAL_MACRO(macro,macroLen,macroLoop,macroRel,macroMin,macroHeight,macroName,displayName,displayHeight,displayLoop,bitfield,bfVal,drawSlider,sliderVal,sliderLow,macroDispMin,bitOff,macroMode,macroColor,mmlStr,macroAMin,macroAMax,hoverFunc,blockMode) \
ImGui::TableNextRow(); \
ImGui::TableNextColumn(); \
ImGui::Text("%s",displayName); \
@ -543,7 +548,7 @@ void FurnaceGUI::drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr,
if (bitfield) { \
PlotBitfield("##IMacro_" macroName,asInt,totalFit,0,bfVal,macroHeight,ImVec2(availableWidth,(displayLoop)?(displayHeight*dpiScale):(32.0f*dpiScale))); \
} else { \
PlotCustom("##IMacro_" macroName,asFloat,totalFit,macroDragScroll,NULL,macroDispMin+macroMin,macroHeight+macroDispMin,ImVec2(availableWidth,(displayLoop)?(displayHeight*dpiScale):(32.0f*dpiScale)),sizeof(float),macroColor,macroLen-macroDragScroll,hoverFunc); \
PlotCustom("##IMacro_" macroName,asFloat,totalFit,macroDragScroll,NULL,macroDispMin+macroMin,macroHeight+macroDispMin,ImVec2(availableWidth,(displayLoop)?(displayHeight*dpiScale):(32.0f*dpiScale)),sizeof(float),macroColor,macroLen-macroDragScroll,hoverFunc,blockMode); \
} \
if (displayLoop && ImGui::IsItemClicked(ImGuiMouseButton_Left)) { \
macroDragStart=ImGui::GetItemRectMin(); \
@ -722,9 +727,9 @@ void FurnaceGUI::drawInsEdit() {
} else {
DivInstrument* ins=e->song.ins[curIns];
ImGui::InputText("Name",&ins->name);
if (ins->type<0 || ins->type>22) ins->type=DIV_INS_FM;
if (ins->type<0 || ins->type>23) ins->type=DIV_INS_FM;
int insType=ins->type;
if (ImGui::Combo("Type",&insType,insTypes,23)) {
if (ImGui::Combo("Type",&insType,insTypes,24)) {
ins->type=(DivInstrumentType)insType;
}
@ -812,15 +817,15 @@ void FurnaceGUI::drawInsEdit() {
}
if (ImGui::BeginTabItem("FM Macros")) {
MACRO_BEGIN(0);
NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel,0,7,"alg",FM_NAME(FM_ALG),96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[0],0,7,NULL);
NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,7,"fb",FM_NAME(FM_FB),96,ins->std.fbMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[1],0,7,NULL);
NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,7,"fms",FM_NAME(FM_FMS),96,ins->std.fmsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,7,NULL);
NORMAL_MACRO(ins->std.amsMacro,ins->std.amsMacroLen,ins->std.amsMacroLoop,ins->std.amsMacroRel,0,3,"ams",FM_NAME(FM_AMS),48,ins->std.amsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[3],0,3,NULL);
NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel,0,7,"alg",FM_NAME(FM_ALG),96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[0],0,7,NULL,false);
NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,7,"fb",FM_NAME(FM_FB),96,ins->std.fbMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[1],0,7,NULL,false);
NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,7,"fms",FM_NAME(FM_FMS),96,ins->std.fmsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,7,NULL,false);
NORMAL_MACRO(ins->std.amsMacro,ins->std.amsMacroLen,ins->std.amsMacroLoop,ins->std.amsMacroRel,0,3,"ams",FM_NAME(FM_AMS),48,ins->std.amsMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[3],0,3,NULL,false);
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,127,"ex1","AM Depth",128,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,127,NULL);
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,127,"ex2","PM Depth",128,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,127,NULL);
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,255,"ex3","LFO Speed",128,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,255,NULL);
NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,3,"wave","LFO Shape",48,ins->std.waveMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[7],0,3,&macroLFOWaves);
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,127,"ex1","AM Depth",128,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,127,NULL,false);
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,127,"ex2","PM Depth",128,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,127,NULL,false);
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,255,"ex3","LFO Speed",128,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,255,NULL,false);
NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,3,"wave","LFO Shape",48,ins->std.waveMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[7],0,3,&macroLFOWaves,false);
MACRO_END;
ImGui::EndTabItem();
}
@ -987,7 +992,7 @@ void FurnaceGUI::drawInsEdit() {
if (ins->type==DIV_INS_AMIGA) {
volMax=64;
}
if (ins->type==DIV_INS_FM) {
if (ins->type==DIV_INS_FM || ins->type == DIV_INS_MIKEY) {
volMax=127;
}
if (ins->type==DIV_INS_GB) {
@ -1012,6 +1017,10 @@ void FurnaceGUI::drawInsEdit() {
if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930 || ins->type==DIV_INS_FM) {
dutyLabel="Noise Freq";
}
if (ins->type == DIV_INS_MIKEY) {
dutyLabel = "Duty/Int";
dutyMax = 10;
}
if (ins->type==DIV_INS_AY8930) {
dutyMax=255;
}
@ -1030,6 +1039,7 @@ void FurnaceGUI::drawInsEdit() {
if (ins->type==DIV_INS_C64) waveMax=4;
if (ins->type==DIV_INS_SAA1099) waveMax=2;
if (ins->type==DIV_INS_FM) waveMax=0;
if (ins->type==DIV_INS_MIKEY) waveMax=0;
const char** waveNames=ayShapeBits;
if (ins->type==DIV_INS_C64) waveNames=c64ShapeBits;
@ -1046,42 +1056,47 @@ void FurnaceGUI::drawInsEdit() {
if (settings.macroView==0) { // modern view
MACRO_BEGIN(28*dpiScale);
if (volMax>0) {
NORMAL_MACRO(ins->std.volMacro,ins->std.volMacroLen,ins->std.volMacroLoop,ins->std.volMacroRel,volMin,volMax,"vol",volumeLabel,160,ins->std.volMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_VOLUME],mmlString[0],volMin,volMax,NULL);
NORMAL_MACRO(ins->std.volMacro,ins->std.volMacroLen,ins->std.volMacroLoop,ins->std.volMacroRel,volMin,volMax,"vol",volumeLabel,160,ins->std.volMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_VOLUME],mmlString[0],volMin,volMax,NULL,false);
}
NORMAL_MACRO(ins->std.arpMacro,ins->std.arpMacroLen,ins->std.arpMacroLoop,ins->std.arpMacroRel,arpMacroScroll,arpMacroScroll+24,"arp","Arpeggio",160,ins->std.arpMacroOpen,false,NULL,true,&arpMacroScroll,(arpMode?0:-80),0,0,&ins->std.arpMacroMode,uiColors[GUI_COLOR_MACRO_PITCH],mmlString[1],-92,94,(ins->std.arpMacroMode?(&macroHoverNote):NULL));
NORMAL_MACRO(ins->std.arpMacro,ins->std.arpMacroLen,ins->std.arpMacroLoop,ins->std.arpMacroRel,arpMacroScroll,arpMacroScroll+24,"arp","Arpeggio",160,ins->std.arpMacroOpen,false,NULL,true,&arpMacroScroll,(arpMode?0:-80),0,0,&ins->std.arpMacroMode,uiColors[GUI_COLOR_MACRO_PITCH],mmlString[1],-92,94,(ins->std.arpMacroMode?(&macroHoverNote):NULL),true);
if (dutyMax>0) {
NORMAL_MACRO(ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,ins->std.dutyMacroRel,0,dutyMax,"duty",dutyLabel,160,ins->std.dutyMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,dutyMax,NULL);
if (ins->type == DIV_INS_MIKEY) {
NORMAL_MACRO(ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,ins->std.dutyMacroRel,0,dutyMax,"duty",dutyLabel,160,ins->std.dutyMacroOpen,true,mikeyFeedbackBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,dutyMax,NULL,false);
}
else {
NORMAL_MACRO(ins->std.dutyMacro,ins->std.dutyMacroLen,ins->std.dutyMacroLoop,ins->std.dutyMacroRel,0,dutyMax,"duty",dutyLabel,160,ins->std.dutyMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[2],0,dutyMax,NULL,false);
}
}
if (waveMax>0) {
NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,waveMax,"wave","Waveform",bitMode?64:160,ins->std.waveMacroOpen,bitMode,waveNames,false,NULL,0,0,((ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930)?1:0),NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[3],0,waveMax,NULL);
NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,waveMax,"wave","Waveform",bitMode?64:160,ins->std.waveMacroOpen,bitMode,waveNames,false,NULL,0,0,((ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930)?1:0),NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[3],0,waveMax,NULL,false);
}
if (ex1Max>0) {
if (ins->type==DIV_INS_C64) {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Filter Mode",64,ins->std.ex1MacroOpen,true,filtModeBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL);
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Filter Mode",64,ins->std.ex1MacroOpen,true,filtModeBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL,false);
} else if (ins->type==DIV_INS_SAA1099) {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Envelope",160,ins->std.ex1MacroOpen,true,saaEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL);
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Envelope",160,ins->std.ex1MacroOpen,true,saaEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL,false);
} else {
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Duty",160,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL);
NORMAL_MACRO(ins->std.ex1Macro,ins->std.ex1MacroLen,ins->std.ex1MacroLoop,ins->std.ex1MacroRel,0,ex1Max,"ex1","Duty",160,ins->std.ex1MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[4],0,ex1Max,NULL,false);
}
}
if (ex2Max>0) {
if (ins->type==DIV_INS_C64) {
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Resonance",64,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max,NULL);
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Resonance",64,ins->std.ex2MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max,NULL,false);
} else {
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Envelope",64,ins->std.ex2MacroOpen,true,ayEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max,NULL);
NORMAL_MACRO(ins->std.ex2Macro,ins->std.ex2MacroLen,ins->std.ex2MacroLoop,ins->std.ex2MacroRel,0,ex2Max,"ex2","Envelope",64,ins->std.ex2MacroOpen,true,ayEnvBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[5],0,ex2Max,NULL,false);
}
}
if (ins->type==DIV_INS_C64) {
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,2,"ex3","Special",32,ins->std.ex3MacroOpen,true,c64SpecialBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,2,NULL);
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,2,"ex3","Special",32,ins->std.ex3MacroOpen,true,c64SpecialBits,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,2,NULL,false);
}
if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930) {
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,15,"ex3","AutoEnv Num",96,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,15,NULL);
NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel,0,15,"alg","AutoEnv Den",96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[7],0,15,NULL);
NORMAL_MACRO(ins->std.ex3Macro,ins->std.ex3MacroLen,ins->std.ex3MacroLoop,ins->std.ex3MacroRel,0,15,"ex3","AutoEnv Num",96,ins->std.ex3MacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[6],0,15,NULL,false);
NORMAL_MACRO(ins->std.algMacro,ins->std.algMacroLen,ins->std.algMacroLoop,ins->std.algMacroRel,0,15,"alg","AutoEnv Den",96,ins->std.algMacroOpen,false,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[7],0,15,NULL,false);
}
if (ins->type==DIV_INS_AY8930) {
// oh my i am running out of macros
NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,8,"fb","Noise AND Mask",96,ins->std.fbMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[8],0,8,NULL);
NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,8,"fms","Noise OR Mask",96,ins->std.fmsMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[9],0,8,NULL);
NORMAL_MACRO(ins->std.fbMacro,ins->std.fbMacroLen,ins->std.fbMacroLoop,ins->std.fbMacroRel,0,8,"fb","Noise AND Mask",96,ins->std.fbMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[8],0,8,NULL,false);
NORMAL_MACRO(ins->std.fmsMacro,ins->std.fmsMacroLen,ins->std.fmsMacroLoop,ins->std.fmsMacroRel,0,8,"fms","Noise OR Mask",96,ins->std.fmsMacroOpen,true,NULL,false,NULL,0,0,0,NULL,uiColors[GUI_COLOR_MACRO_OTHER],mmlString[9],0,8,NULL,false);
}
MACRO_END;

View file

@ -86,6 +86,7 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
if (i<0 || i>=e->song.patLen) {
return;
}
bool isPushing=false;
// check overflow highlight
if (settings.overflowHighlight) {
if (edit && cursor.y==i) {
@ -97,6 +98,19 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
} else if (e->song.hilightA>0 && !(i%e->song.hilightA)) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_1]));
}
} else {
isPushing=true;
if (edit && cursor.y==i) {
ImGui::PushStyleColor(ImGuiCol_Header,ImGui::GetColorU32(uiColors[GUI_COLOR_EDITING]));
} else if (isPlaying && oldRow==i) {
ImGui::PushStyleColor(ImGuiCol_Header,0x40ffffff);
} else if (e->song.hilightB>0 && !(i%e->song.hilightB)) {
ImGui::PushStyleColor(ImGuiCol_Header,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_2]));
} else if (e->song.hilightA>0 && !(i%e->song.hilightA)) {
ImGui::PushStyleColor(ImGuiCol_Header,ImGui::GetColorU32(uiColors[GUI_COLOR_PATTERN_HI_1]));
} else {
isPushing=false;
}
}
// row number
if (settings.patRowsBase==1) {
@ -117,19 +131,6 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
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;
@ -141,6 +142,8 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
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) {
@ -156,7 +159,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedNote,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
if (selectedNote) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedNote,ImGuiSelectableFlags_NoPadWithHalfSpacing,threeChars);
if (selectedNote) ImGui::PopStyleColor();
}
if (ImGui::IsItemClicked()) {
startSelection(j,0,i);
@ -185,7 +190,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedIns,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
if (selectedIns) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedIns,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
if (selectedIns) ImGui::PopStyleColor();
}
if (ImGui::IsItemClicked()) {
startSelection(j,1,i);
@ -215,7 +222,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedVol,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
if (selectedVol) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedVol,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
if (selectedVol) ImGui::PopStyleColor();
}
if (ImGui::IsItemClicked()) {
startSelection(j,2,i);
@ -268,7 +277,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedEffect,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
if (selectedEffect) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedEffect,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
if (selectedEffect) ImGui::PopStyleColor();
}
if (ImGui::IsItemClicked()) {
startSelection(j,index-1,i);
@ -292,7 +303,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
demandX=ImGui::GetCursorPosX();
ImGui::PopStyleColor(3);
} else {
ImGui::Selectable(id,selectedEffectVal,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
if (selectedEffectVal) ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
ImGui::Selectable(id,isPushing || selectedEffectVal,ImGuiSelectableFlags_NoPadWithHalfSpacing,twoChars);
if (selectedEffectVal) ImGui::PopStyleColor();
}
if (ImGui::IsItemClicked()) {
startSelection(j,index,i);
@ -304,6 +317,9 @@ inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int
}
}
}
if (isPushing) {
ImGui::PopStyleColor();
}
ImGui::TableNextColumn();
patChanX[chans]=ImGui::GetCursorPosX();
}
@ -315,6 +331,9 @@ void FurnaceGUI::drawPattern() {
nextWindow=GUI_WINDOW_NOTHING;
}
if (!patternOpen) return;
float scrollX=0;
if (e->isPlaying() && followPattern) cursor.y=oldRow;
demandX=0;
sel1=selStart;
@ -381,6 +400,15 @@ void FurnaceGUI::drawPattern() {
if (ImGui::Selectable((extraChannelButtons==2)?" --##ExtraChannelButtons":" ++##ExtraChannelButtons",false,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale))) {
if (++extraChannelButtons>2) extraChannelButtons=0;
}
if (ImGui::IsItemHovered()) {
if (extraChannelButtons==2) {
ImGui::SetTooltip("Pattern names (click to collapse)\nRight-click for visualizer");
} else if (extraChannelButtons==1) {
ImGui::SetTooltip("Expanded (click for pattern names)\nRight-click for visualizer");
} else {
ImGui::SetTooltip("Compact (click to expand)\nRight-click for visualizer");
}
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
fancyPattern=!fancyPattern;
e->enableCommandStream(fancyPattern);
@ -428,7 +456,6 @@ void FurnaceGUI::drawPattern() {
ImGui::PushStyleColor(ImGuiCol_Header,chanHead);
ImGui::PushStyleColor(ImGuiCol_HeaderActive,chanHeadActive);
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,chanHeadHover);
// help me why is the color leakingggggggg
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(chanHead));
if (muted) ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_CHANNEL_MUTED]);
ImGui::Selectable(chanID,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale));
@ -554,6 +581,7 @@ void FurnaceGUI::drawPattern() {
}
demandScrollX=false;
}
scrollX=ImGui::GetScrollX();
ImGui::EndTable();
}
@ -569,7 +597,6 @@ void FurnaceGUI::drawPattern() {
//if (i.cmd==DIV_CMD_NOTE_ON) continue;
if (i.cmd==DIV_CMD_PRE_PORTA) continue;
if (i.cmd==DIV_CMD_PRE_NOTE) continue;
if (i.cmd==DIV_CMD_INSTRUMENT) continue;
if (i.cmd==DIV_CMD_SAMPLE_BANK) continue;
if (i.cmd==DIV_CMD_GET_VOLUME) continue;
if (i.cmd==DIV_ALWAYS_SET_VOLUME) continue;
@ -589,8 +616,8 @@ void FurnaceGUI::drawPattern() {
switch (i.cmd) {
case DIV_CMD_NOTE_ON:
partIcon=ICON_FA_ASTERISK;
life=64.0f;
lifeSpeed=2.0f;
life=96.0f;
lifeSpeed=3.0f;
break;
case DIV_CMD_LEGATO:
partIcon=ICON_FA_COG;
@ -618,6 +645,23 @@ void FurnaceGUI::drawPattern() {
color=volGrad;
break;
}
case DIV_CMD_INSTRUMENT: {
if (lastIns[i.chan]==i.value) {
num=0;
break;
}
lastIns[i.chan]=i.value;
speedX=0.0f;
speedY=0.0f;
grav=0.0f;
frict=0.98;
spread=30.0f;
life=128.0f;
lifeSpeed=6.0f;
color=insGrad;
num=7+pow(i.value,0.6);
break;
}
case DIV_CMD_PANNING: {
if (i.value==0) {
num=0;
@ -661,7 +705,7 @@ void FurnaceGUI::drawPattern() {
particles.push_back(Particle(
color,
partIcon,
off.x+patChanX[i.chan]+fmod(rand(),width),
off.x+patChanX[i.chan]+fmod(rand(),width)-scrollX,
off.y+(ImGui::GetWindowHeight()*0.5f)+randRange(0,patFont->FontSize),
(speedX+randRange(-spread,spread))*0.5*dpiScale,
(speedY+randRange(-spread,spread))*0.5*dpiScale,
@ -675,31 +719,30 @@ void FurnaceGUI::drawPattern() {
// note slides
ImVec2 arrowPoints[7];
for (int i=0; i<chans; i++) {
if (e->isPlaying()) for (int i=0; i<chans; i++) {
if (!e->song.chanShow[i]) continue;
DivChannelState* ch=e->getChanState(i);
if (ch->portaSpeed>0) {
ImVec4 col=uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH];
col.w*=0.2;
float width=patChanX[i+1]-patChanX[i];
if (e->isPlaying()) {
particles.push_back(Particle(
pitchGrad,
(ch->portaNote<=ch->note)?ICON_FA_CHEVRON_DOWN:ICON_FA_CHEVRON_UP,
off.x+patChanX[i]+fmod(rand(),width),
off.y+fmod(rand(),MAX(1,ImGui::GetWindowHeight())),
0.0f,
(7.0f+(rand()%5)+pow(ch->portaSpeed,0.7f))*((ch->portaNote<=ch->note)?1:-1),
0.0f,
1.0f,
255.0f,
15.0f
));
}
particles.push_back(Particle(
pitchGrad,
(ch->portaNote<=ch->note)?ICON_FA_CHEVRON_DOWN:ICON_FA_CHEVRON_UP,
off.x+patChanX[i]+fmod(rand(),width)-scrollX,
off.y+fmod(rand(),MAX(1,ImGui::GetWindowHeight())),
0.0f,
(7.0f+(rand()%5)+pow(ch->portaSpeed,0.7f))*((ch->portaNote<=ch->note)?1:-1),
0.0f,
1.0f,
255.0f,
15.0f
));
for (float j=-patChanSlideY[i]; j<ImGui::GetWindowHeight(); j+=width*0.7) {
ImVec2 tMin=ImVec2(off.x+patChanX[i],off.y+j);
ImVec2 tMax=ImVec2(off.x+patChanX[i+1],off.y+j+width*0.6);
if (width>0.1) for (float j=-patChanSlideY[i]; j<ImGui::GetWindowHeight(); j+=width*0.7) {
ImVec2 tMin=ImVec2(off.x+patChanX[i]-scrollX,off.y+j);
ImVec2 tMax=ImVec2(off.x+patChanX[i+1]-scrollX,off.y+j+width*0.6);
if (ch->portaNote<=ch->note) {
arrowPoints[0]=ImLerp(tMin,tMax,ImVec2(0.1,1.0-0.8));
arrowPoints[1]=ImLerp(tMin,tMax,ImVec2(0.5,1.0-0.0));

View file

@ -289,7 +289,7 @@ void PlotBitfield(const char* label, const int* values, int values_count, int va
PlotBitfieldEx(label, &Plot_IntArrayGetter, (void*)&data, values_count, values_offset, overlay_text, bits, graph_size);
}
int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_display_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size, ImVec4 color, int highlight, std::string (*hoverFunc)(int,float))
int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_display_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size, ImVec4 color, int highlight, std::string (*hoverFunc)(int,float), bool blockMode)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = ImGui::GetCurrentWindow();
@ -384,6 +384,10 @@ int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_gett
bgColor);
}
if (blockMode) {
window->DrawList->AddLine(ImLerp(inner_bb.Min,inner_bb.Max,ImVec2(0.0f,histogram_zero_line_t)),ImLerp(inner_bb.Min,inner_bb.Max,ImVec2(1.0f,histogram_zero_line_t)),col_base);
}
for (int n = 0; n < res_w; n++)
{
const float t1 = t0 + t_step;
@ -394,7 +398,7 @@ int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_gett
// NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU.
ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0);
ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, histogram_zero_line_t));
ImVec2 pos1 = ImLerp(inner_bb.Min, inner_bb.Max, (plot_type == ImGuiPlotType_Lines) ? tp1 : ImVec2(tp1.x, blockMode?tp0.y:histogram_zero_line_t));
if (plot_type == ImGuiPlotType_Lines)
{
window->DrawList->AddLine(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base);
@ -403,6 +407,10 @@ int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_gett
{
if (pos1.x >= pos0.x + 2.0f)
pos1.x -= 1.0f;
if (blockMode) {
pos0.y-=(inner_bb.Max.y-inner_bb.Min.y)*inv_scale;
//pos1.y+=1.0f;
}
window->DrawList->AddRectFilled(pos0, pos1, idx_hovered == v1_idx ? col_hovered : col_base);
}
@ -423,8 +431,8 @@ int PlotCustomEx(ImGuiPlotType plot_type, const char* label, float (*values_gett
return idx_hovered;
}
void PlotCustom(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride, ImVec4 color, int highlight, std::string (*hoverFunc)(int,float))
void PlotCustom(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride, ImVec4 color, int highlight, std::string (*hoverFunc)(int,float), bool blockMode)
{
FurnacePlotArrayGetterData data(values, stride);
PlotCustomEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size, color, highlight, hoverFunc);
PlotCustomEx(ImGuiPlotType_Histogram, label, &Plot_ArrayGetter, (void*)&data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size, color, highlight, hoverFunc, blockMode);
}

View file

@ -22,4 +22,4 @@
void PlotNoLerp(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float));
void PlotBitfield(const char* label, const int* values, int values_count, int values_offset = 0, const char** overlay_text = NULL, int bits = 8, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float));
void PlotCustom(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float), ImVec4 fgColor = ImVec4(1.0f,1.0f,1.0f,1.0f), int highlight = 0, std::string (*hoverFunc)(int,float) = NULL);
void PlotCustom(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0, 0), int stride = sizeof(float), ImVec4 fgColor = ImVec4(1.0f,1.0f,1.0f,1.0f), int highlight = 0, std::string (*hoverFunc)(int,float) = NULL, bool blockMode=false);

View file

@ -22,7 +22,9 @@
#include "util.h"
#include "IconsFontAwesome4.h"
#include "misc/cpp/imgui_stdlib.h"
#include <SDL_scancode.h>
#include <fmt/printf.h>
#include <imgui.h>
#ifdef __APPLE__
#define FURKMOD_CMD FURKMOD_META
@ -30,6 +32,8 @@
#define FURKMOD_CMD FURKMOD_CTRL
#endif
#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;"
const char* mainFonts[]={
"IBM Plex Sans",
"Liberation Sans",
@ -113,6 +117,15 @@ void FurnaceGUI::promptKey(int 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;
@ -461,6 +474,7 @@ void FurnaceGUI::drawSettings() {
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_UNKNOWN,"Other/Unknown");
ImGui::TreePop();
}
@ -563,6 +577,7 @@ void FurnaceGUI::drawSettings() {
UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_PIANO,"Piano");
UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_NOTES,"Song Comments");
UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_CHANNELS,"Channels");
UI_KEYBIND_CONFIG(GUI_ACTION_WINDOW_REGISTER_VIEW,"Register View");
UI_KEYBIND_CONFIG(GUI_ACTION_COLLAPSE_WINDOW,"Collapse/expand current window");
UI_KEYBIND_CONFIG(GUI_ACTION_CLOSE_WINDOW,"Close current window");
@ -570,6 +585,89 @@ void FurnaceGUI::drawSettings() {
KEYBIND_CONFIG_END;
ImGui::TreePop();
}
if (ImGui::TreeNode("Note input")) {
std::vector<MappedInput> sorted;
if (ImGui::BeginTable("keysNoteInput",4)) {
for (std::map<int,int>::value_type& i: noteKeys) {
std::vector<MappedInput>::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,"Envelope 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<SDL_NUM_SCANCODES; i++) {
const char* sName=SDL_GetScancodeName((SDL_Scancode)i);
if (sName==NULL) continue;
if (sName[0]==0) continue;
snprintf(id,4095,"%s##SNNewKey_%d",sName,i);
if (ImGui::Selectable(id)) {
noteKeys[(SDL_Scancode)i]=0;
}
}
ImGui::EndCombo();
}
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Pattern")) {
KEYBIND_CONFIG_BEGIN("keysPattern");
@ -805,6 +903,7 @@ void FurnaceGUI::syncSettings() {
LOAD_KEYBIND(GUI_ACTION_WINDOW_PIANO,0);
LOAD_KEYBIND(GUI_ACTION_WINDOW_NOTES,0);
LOAD_KEYBIND(GUI_ACTION_WINDOW_CHANNELS,0);
LOAD_KEYBIND(GUI_ACTION_WINDOW_REGISTER_VIEW,0);
LOAD_KEYBIND(GUI_ACTION_COLLAPSE_WINDOW,0);
LOAD_KEYBIND(GUI_ACTION_CLOSE_WINDOW,FURKMOD_SHIFT|SDLK_ESCAPE);
@ -906,6 +1005,8 @@ void FurnaceGUI::syncSettings() {
LOAD_KEYBIND(GUI_ACTION_ORDERS_MOVE_DOWN,FURKMOD_SHIFT|SDLK_DOWN);
LOAD_KEYBIND(GUI_ACTION_ORDERS_REPLAY,0);
decodeKeyMap(noteKeys,e->getConfString("noteKeys",DEFAULT_NOTE_KEYS));
parseKeybinds();
}
@ -990,6 +1091,7 @@ void FurnaceGUI::commitSettings() {
PUT_UI_COLOR(GUI_COLOR_INSTR_POKEY);
PUT_UI_COLOR(GUI_COLOR_INSTR_BEEPER);
PUT_UI_COLOR(GUI_COLOR_INSTR_SWAN);
PUT_UI_COLOR(GUI_COLOR_INSTR_MIKEY);
PUT_UI_COLOR(GUI_COLOR_INSTR_UNKNOWN);
PUT_UI_COLOR(GUI_COLOR_CHANNEL_FM);
PUT_UI_COLOR(GUI_COLOR_CHANNEL_PULSE);
@ -1071,6 +1173,7 @@ void FurnaceGUI::commitSettings() {
SAVE_KEYBIND(GUI_ACTION_WINDOW_PIANO);
SAVE_KEYBIND(GUI_ACTION_WINDOW_NOTES);
SAVE_KEYBIND(GUI_ACTION_WINDOW_CHANNELS);
SAVE_KEYBIND(GUI_ACTION_WINDOW_REGISTER_VIEW);
SAVE_KEYBIND(GUI_ACTION_COLLAPSE_WINDOW);
SAVE_KEYBIND(GUI_ACTION_CLOSE_WINDOW);
@ -1172,6 +1275,8 @@ void FurnaceGUI::commitSettings() {
SAVE_KEYBIND(GUI_ACTION_ORDERS_MOVE_DOWN);
SAVE_KEYBIND(GUI_ACTION_ORDERS_REPLAY);
e->setConf("noteKeys",encodeKeyMap(noteKeys));
e->saveConf();
if (!e->switchMaster()) {