From 38f4b75b128178d27bcedc8fb48a8d04b0721efc Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 8 Jun 2022 18:02:04 -0500 Subject: [PATCH 01/31] GUI: find and replace, part 4 --- src/gui/findReplace.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index 0daf34125..8c05be991 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -366,7 +366,24 @@ void FurnaceGUI::drawFindReplace() { if (ImGui::BeginTable("QueryReplace",3)) { ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("..."); + ImGui::Text("Note"); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Ins"); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Volume"); + + /*ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Effect"); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Value");*/ + ImGui::EndTable(); } if (ImGui::Button("Replace##QueryReplace")) { From caf548c6394126748b1e233ee162c132620d17df Mon Sep 17 00:00:00 2001 From: itsragedev <66060223+itsragedev@users.noreply.github.com> Date: Thu, 9 Jun 2022 15:43:19 +0200 Subject: [PATCH 02/31] add terrible demo (#520) --- demos/the_erfngjt.fur | Bin 0 -> 739 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 demos/the_erfngjt.fur diff --git a/demos/the_erfngjt.fur b/demos/the_erfngjt.fur new file mode 100644 index 0000000000000000000000000000000000000000..5d70dca8e8a0e47841c913bab96be83b1a14c033 GIT binary patch literal 739 zcmV<90v!E#ob6c6Zqq;zo?Y7{b^=C7oRElxkdTln^@hZSwm_vys8kSfu0_I6MAFJ7 z7fu}d47>s_zytKeQ}7_%V0SIYpINX1!49{Z#r+eGrfpybXu502thkWc5pkVobNB_excpkl*ydQmrQ8@fE z6~13jfyZ|lOX3*&DeOmWfQuUdk8cC~xC7wa1$Ywxe7^_q`@X2=0~x8nIk(kM&X^?~ zvy@+-%(&&ZofY&=d|^=v2Zyiw^7R%M%=I~W+XucQcOi7e*W7CS3n%OZe+m%i1L%S(oO&(dVE7CTQKUzwFILv%sv?)^ z+Pb6aTAK1Vd5ZD`&XIG$6d?rG+H6n{M%W6zA72#kz zNeq3s4)M@&A+CeG80a63^E_=aC8#YauP|FyrW7Aop%Vy#~%qf*;)h-#=@U}ao2l-nWPD>k){T#*H$fh`5!k^_&{hdqL7sb;d{4Sw~Iv4Ec>J30r9|zUPL3;Fl z9FO@aPD&4IsQ3-V0NG4YBVoT^Lvqx+%qlaah zW%2rCYLzw=&uyq~=5a?IK90dcC_g1oAHNQIr~||!hB`nzV#@4mnTDeDSQ)>*q0H-} VZ73_Zp{N<#*o~dB{{lA$)Q>%Rau)yq literal 0 HcmV?d00001 From 0e05f3b67bc6895bdca0d69b463256a1e350827b Mon Sep 17 00:00:00 2001 From: LoKiToon <98922449+LoKiToon@users.noreply.github.com> Date: Thu, 9 Jun 2022 20:41:01 +0300 Subject: [PATCH 03/31] Add files via upload --- demos/E1M4OPL2.fur | Bin 0 -> 4122 bytes demos/FDS TEST.fur | Bin 0 -> 1574 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 demos/E1M4OPL2.fur create mode 100644 demos/FDS TEST.fur diff --git a/demos/E1M4OPL2.fur b/demos/E1M4OPL2.fur new file mode 100644 index 0000000000000000000000000000000000000000..19f8ce54f34c5214eac28024ce513c961d392c01 GIT binary patch literal 4122 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 AZvX%Q literal 0 HcmV?d00001 diff --git a/demos/FDS TEST.fur b/demos/FDS TEST.fur new file mode 100644 index 0000000000000000000000000000000000000000..54b6d3b40607fd0367a5de8f511989df758bb900 GIT binary patch literal 1574 zcmV+>2HE*|ob6mqOdCfOezVwsf!07t)Ssl;P>>QNDoC5EQq=}1(Aa7ye+J1G2TFYa zvJeGGRYhqz^pHlX)LOLXRDud@nM9QgQjtQAJ@!JXV5R9fRYOnhp&{;!ch}y+j+Zgp zWCzbPPky|adEc8i^Y-m}42_*L7bk{C!m={?(aia9;|KuAkR@MN=Lcz_xEKLkXlsEo za8;H70tviCeGPI_iv{H#{q(7GSQ#CeROI&2sd2gQld0*jBKL=*A#V-{Ux)ISjCP1mNvg@b4!9yiEYtF@M<%@Zl+dsnYA)N-br*RX0Nj)) zA9Ep8-jt)g47t43^i?|MK_0I}ZT5oHl8#HM#ydvS4ezFu1?^>wdARMtH}@w$M1i#% zi*+pTWOpoC?F$?$9NFFNzKzlbK`wI41kDLuMQ{_%nm2mAD$^)iXuw!#nz<}A_>Lg$ za|Oi~iM87xo2`Ra<7YK~M&k;N%QY_3*rT!TUWvxV8oM>teL@;b8tcCUrQK`}Mxxzm z?1l2%rw6+jJxMIqvAmPrv1GL`aIA3nDtx&b^DKO)xGa3Mf~V77)cPv@$3mhw)f-g+3aaowGD4%uM*+&!_ez91`@=kWglGVPz zvBD|%Li0M8g@!z(&@HL!gn+(Yqz{7sejK+`CY0-=MI-IwQ#o!f-Uk(nbu8~>cPv@$ z3mhw)LM%!yV^KQIWl^%CeAZ!SAMy0VFBa=q-pTG*vf39oRyYM;Xx`wW(4ePKXjt%A z@y)Rg_Qn56VzG|po$QV!t9^lEg;O|%X0UajBQ5AxZ1P@-`8iO(vGxMymoOjI+Kl`% z<|CM2#QZ$wLzqcPAqVy3fS%L^awty@;`aoa- zgUiQj+G^V>tG+%PnTtjT5_j&5jmKh&GCmYie!rYrTT5P2Ldngs_)0LbF%VJ`SX|y5 zOAII*!SO`Y-{bFzL?ZJiI($8m`MTq%rL^@cxwa}&*WT6}si|LzVrmEkHpXI!jg7<~ zTlbU8Yb(Lf>MuX8#S<7K9*-|C2b4hlwMbp0uI7uYXRA&Gc1*SzX5G6d`?w@k^e29j zdX)0Q&xaQYP*j51^v)rXgLN$6P(DtjpSNz~H}XCH-&8HYb<%NAmVs>4&$j-)v`W_V zQR-nZ7OlnuQujYyZK!Sq>95p!((kLO>ZtYAZQolNN{%UwRo}Ioymdo~1!8_*m9O{V z%H}|PVXn7f!N2r_qQrws{sn)aArMMLqkbIh1?*dQYk#kCixuN_Mv&d<#$9hFyYPNt z>5mxuv--ok|B}P}XZ447{~?ZQ6IUksfzAy$8Q_a8ZIL$Uh9yZ@PlFy6V?;RySc z{r?V3VfoK`WfcBvayB8dDPhNiSg(vuTM*v;XT35C|20`p2;&EkR>p)Z98j7ILA<*@RGUnaG!;$^Wq0uVI>< zGC(=>9*Vw%qId7ov-(f#ZHPDrXZytq?Ap^={a| zVVa!^Aa`&3*R$fX_P5J_yZjOH&(BZhcxDqq5((je1rhPL*MAm&$k|gSA&lRmwwi>H zg?wP;Y(nVg5ZPv9N2lp&vWL>&X?mJ0QTjVgPm`UtPgwVlAtCg02y+8Y)6+K;GVSj) YJxxZG{!Y`=WEZ8s)AUsNUy`BxAD+J{f&c&j literal 0 HcmV?d00001 From 6ccd2e222b97abc0fa5f28b17c46e07aaacaab4c Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 9 Jun 2022 16:10:51 -0500 Subject: [PATCH 04/31] try CoInitializeEx on Windows --- src/main.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 079058528..8c90c7c8e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,6 +30,7 @@ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include +#include #include #else #include @@ -243,6 +244,12 @@ void initParams() { // TODO: add crash log int main(int argc, char** argv) { initLog(); +#ifdef _WIN32 + HRESULT coResult=CoInitializeEx(NULL,COINIT_MULTITHREADED); + if (coResult!=S_OK) { + logE("CoInitializeEx failed!"); + } +#endif #if !(defined(__APPLE__) || defined(_WIN32) || defined(ANDROID)) // workaround for Wayland HiDPI issue if (getenv("SDL_VIDEODRIVER")==NULL) { @@ -446,6 +453,12 @@ int main(int argc, char** argv) { logI("stopping engine."); e.quit(); + +#ifdef _WIN32 + if (coResult==S_OK || coResult==S_FALSE) { + CoUninitialize(); + } +#endif return 0; } From 7dc3dc96c4c0bec8e13f32feba056ba040c60239 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 9 Jun 2022 16:41:54 -0500 Subject: [PATCH 05/31] GUI: find and replace, part 5 --- src/gui/findReplace.cpp | 41 +++++++++++++++++++++++++++++++++++------ src/gui/gui.h | 19 +++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index 8c05be991..071d05ea0 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -17,6 +17,7 @@ const char* queryModes[GUI_QUERY_MAX]={ const char* queryReplaceModes[GUI_QUERY_REPLACE_MAX]={ "set", "add", + "add (overflow)", "clear" }; @@ -363,18 +364,33 @@ void FurnaceGUI::drawFindReplace() { } if (ImGui::TreeNode("Replace")) { - if (ImGui::BeginTable("QueryReplace",3)) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Note"); + if (ImGui::BeginTable("QueryReplace",3,ImGuiTableFlags_BordersOuter)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.5); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.5); ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("Ins"); + ImGui::Checkbox("Note",&queryReplaceNoteDo); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::Combo("##NRMode",&queryReplaceNoteMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); + ImGui::TableNextColumn(); + ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("Volume"); + ImGui::Checkbox("Ins",&queryReplaceInsDo); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::Combo("##IRMode",&queryReplaceInsMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Checkbox("Volume",&queryReplaceVolDo); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::Combo("##VRMode",&queryReplaceVolMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); /*ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -386,6 +402,19 @@ void FurnaceGUI::drawFindReplace() { ImGui::EndTable(); } + ImGui::Text("Effect replace mode:"); + if (ImGui::RadioButton("Clear effects",queryReplaceEffectPos==0)) { + queryReplaceEffectPos=0; + } + if (ImGui::RadioButton("Replace matches only",queryReplaceEffectPos==1)) { + queryReplaceEffectPos=1; + } + if (ImGui::RadioButton("Replace matches, then free spaces",queryReplaceEffectPos==2)) { + queryReplaceEffectPos=2; + } + if (ImGui::RadioButton("Insert in free spaces",queryReplaceEffectPos==3)) { + queryReplaceEffectPos=3; + } if (ImGui::Button("Replace##QueryReplace")) { // TODO } diff --git a/src/gui/gui.h b/src/gui/gui.h index 2ee6170aa..107deb9d2 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -818,6 +818,7 @@ enum FurnaceGUIFindQueryModes { enum FurnaceGUIFindQueryReplaceModes { GUI_QUERY_REPLACE_SET=0, GUI_QUERY_REPLACE_ADD, + GUI_QUERY_REPLACE_ADD_OVERFLOW, GUI_QUERY_REPLACE_CLEAR, GUI_QUERY_REPLACE_MAX @@ -1175,6 +1176,24 @@ class FurnaceGUI { int curQueryRangeY; int curQueryEffectPos; + int queryReplaceEffectCount; + int queryReplaceEffectPos; + int queryReplaceNoteMode; + int queryReplaceInsMode; + int queryReplaceVolMode; + int queryReplaceEffectMode[8]; + int queryReplaceEffectValMode[8]; + int queryReplaceNote; + int queryReplaceIns; + int queryReplaceVol; + int queryReplaceEffect[8]; + int queryReplaceEffectVal[8]; + bool queryReplaceNoteDo; + bool queryReplaceInsDo; + bool queryReplaceVolDo; + bool queryReplaceEffectDo[8]; + bool queryReplaceEffectValDo[8]; + struct ActiveNote { int chan; int note; From 04bbffac13e4bbf3773b925be6b9ae884ef6d1af Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 9 Jun 2022 16:54:14 -0500 Subject: [PATCH 06/31] more MIDI debug messages --- src/audio/rtmidi.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/audio/rtmidi.cpp b/src/audio/rtmidi.cpp index a5c5bad02..b431a89d8 100644 --- a/src/audio/rtmidi.cpp +++ b/src/audio/rtmidi.cpp @@ -75,8 +75,12 @@ bool TAMidiInRtMidi::openDevice(String name) { try { bool portOpen=false; unsigned int count=port->getPortCount(); + logD("finding port %s...",name); for (unsigned int i=0; igetPortName(i)==name) { + String portName=port->getPortName(i); + logV("- %d: %s",i,portName); + if (portName==name) { + logD("opening port %d...",i); port->openPort(i); portOpen=true; break; @@ -184,8 +188,12 @@ bool TAMidiOutRtMidi::openDevice(String name) { try { bool portOpen=false; unsigned int count=port->getPortCount(); + logD("finding port %s...",name); for (unsigned int i=0; igetPortName(i)==name) { + String portName=port->getPortName(i); + logV("- %d: %s",i,portName); + if (portName==name) { + logD("opening port %d...",i); port->openPort(i); portOpen=true; break; @@ -248,4 +256,4 @@ bool TAMidiOutRtMidi::quit() { port=NULL; } return true; -} \ No newline at end of file +} From eac4f50d9297f5478c8ca596389193f305f4cd19 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 9 Jun 2022 18:04:50 -0500 Subject: [PATCH 07/31] sanitize MIDI port names on Windows/Linux --- src/audio/rtmidi.cpp | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/audio/rtmidi.cpp b/src/audio/rtmidi.cpp index b431a89d8..31a3e66ae 100644 --- a/src/audio/rtmidi.cpp +++ b/src/audio/rtmidi.cpp @@ -21,6 +21,26 @@ #include "../ta-log.h" #include "taAudio.h" +String sanitizePortName(const String& name) { +#if defined(_WIN32) + // remove port number + size_t namePos=name.rfind(' '); + if (namePos!=String::npos) { + return name.substr(0,namePos); + } + return name; +#elif defined(__linux__) + // remove port location + size_t namePos=name.rfind(' '); + if (namePos!=String::npos) { + return name.substr(0,namePos); + } + return name; +#else + return name; +#endif +} + // --- IN --- bool TAMidiInRtMidi::gather() { @@ -56,7 +76,7 @@ std::vector TAMidiInRtMidi::listDevices() { unsigned int count=port->getPortCount(); logD("got port count."); for (unsigned int i=0; igetPortName(i); + String name=sanitizePortName(port->getPortName(i)); if (name!="") ret.push_back(name); } } catch (RtMidiError& e) { @@ -77,7 +97,7 @@ bool TAMidiInRtMidi::openDevice(String name) { unsigned int count=port->getPortCount(); logD("finding port %s...",name); for (unsigned int i=0; igetPortName(i); + String portName=sanitizePortName(port->getPortName(i)); logV("- %d: %s",i,portName); if (portName==name) { logD("opening port %d...",i); @@ -190,7 +210,7 @@ bool TAMidiOutRtMidi::openDevice(String name) { unsigned int count=port->getPortCount(); logD("finding port %s...",name); for (unsigned int i=0; igetPortName(i); + String portName=sanitizePortName(port->getPortName(i)); logV("- %d: %s",i,portName); if (portName==name) { logD("opening port %d...",i); @@ -230,7 +250,7 @@ std::vector TAMidiOutRtMidi::listDevices() { try { unsigned int count=port->getPortCount(); for (unsigned int i=0; igetPortName(i); + String name=sanitizePortName(port->getPortName(i)); if (name!="") ret.push_back(name); } } catch (RtMidiError& e) { From dd05429c0eb8da08f329bb0f8d37d2cd94915b1f Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 9 Jun 2022 18:16:51 -0500 Subject: [PATCH 08/31] WaveSynth: initialize wave to 0 on SCC/Bubble Syst --- src/engine/platform/bubsyswsg.cpp | 2 +- src/engine/platform/scc.cpp | 2 +- src/engine/waveSynth.cpp | 7 ++++++- src/engine/waveSynth.h | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/engine/platform/bubsyswsg.cpp b/src/engine/platform/bubsyswsg.cpp index 85d50e668..48a078803 100644 --- a/src/engine/platform/bubsyswsg.cpp +++ b/src/engine/platform/bubsyswsg.cpp @@ -306,7 +306,7 @@ void DivPlatformBubSysWSG::reset() { for (int i=0; i<2; i++) { chan[i]=DivPlatformBubSysWSG::Channel(); chan[i].std.setEngine(parent); - chan[i].ws.setEngine(parent); + chan[i].ws.setEngine(parent,8); chan[i].ws.init(NULL,32,15,false); } if (dumpWrites) { diff --git a/src/engine/platform/scc.cpp b/src/engine/platform/scc.cpp index 011f63bca..0cfe5a462 100644 --- a/src/engine/platform/scc.cpp +++ b/src/engine/platform/scc.cpp @@ -332,7 +332,7 @@ void DivPlatformSCC::reset() { for (int i=0; i<5; i++) { chan[i]=DivPlatformSCC::Channel(); chan[i].std.setEngine(parent); - chan[i].ws.setEngine(parent); + chan[i].ws.setEngine(parent,128); chan[i].ws.init(NULL,32,255,false); chan[i].vol=15; chan[i].outVol=15; diff --git a/src/engine/waveSynth.cpp b/src/engine/waveSynth.cpp index e69031686..82b5d5ddc 100644 --- a/src/engine/waveSynth.cpp +++ b/src/engine/waveSynth.cpp @@ -243,8 +243,13 @@ void DivWaveSynth::changeWave2(int num) { first=true; } -void DivWaveSynth::setEngine(DivEngine* engine) { +void DivWaveSynth::setEngine(DivEngine* engine, int waveFloor) { e=engine; + memset(wave1,waveFloor,256); + memset(wave2,waveFloor,256); + for (int i=0; i<256; i++) { + output[i]=waveFloor; + } } void DivWaveSynth::init(DivInstrument* which, int w, int h, bool insChanged) { diff --git a/src/engine/waveSynth.h b/src/engine/waveSynth.h index 8709b0846..26f5b259b 100644 --- a/src/engine/waveSynth.h +++ b/src/engine/waveSynth.h @@ -70,7 +70,7 @@ class DivWaveSynth { * @param insChanged whether the instrument has changed. */ void init(DivInstrument* which, int width, int height, bool insChanged=false); - void setEngine(DivEngine* engine); + void setEngine(DivEngine* engine, int waveFloor=0); DivWaveSynth(): e(NULL), pos(0), From 936d9dfa49f996910ff54b72abc3d13c8569865c Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 9 Jun 2022 18:52:38 -0500 Subject: [PATCH 09/31] GUI: find and replace, part 6 --- src/gui/findReplace.cpp | 85 +++++++++++++++++++++++++++++++++++++---- src/gui/gui.cpp | 26 +++++++++++++ src/gui/gui.h | 2 +- src/gui/intConst.cpp | 1 + src/gui/intConst.h | 1 + 5 files changed, 106 insertions(+), 9 deletions(-) diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index 071d05ea0..7ac12d1de 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -3,6 +3,7 @@ #include "IconsFontAwesome4.h" #include "misc/cpp/imgui_stdlib.h" #include "guiConst.h" +#include "intConst.h" const char* queryModes[GUI_QUERY_MAX]={ "ignore", @@ -290,7 +291,11 @@ void FurnaceGUI::drawFindReplace() { curQuery.push_back(FurnaceGUIFindQuery()); } - if (ImGui::BeginTable("QueryLimits",2)) { + if (ImGui::BeginTable("QueryLimits",3)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.5f); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.5f); + ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -333,6 +338,7 @@ void FurnaceGUI::drawFindReplace() { } ImGui::EndDisabled(); + ImGui::TableNextColumn(); ImGui::Text("Match effect position:"); if (ImGui::RadioButton("No",curQueryEffectPos==0)) { @@ -356,8 +362,6 @@ void FurnaceGUI::drawFindReplace() { ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Checkbox("From start",&curQueryFromStart); - ImGui::TableNextColumn(); ImGui::Checkbox("Backwards",&curQueryBackwards); ImGui::EndTable(); @@ -373,10 +377,49 @@ void FurnaceGUI::drawFindReplace() { ImGui::TableNextColumn(); ImGui::Checkbox("Note",&queryReplaceNoteDo); ImGui::TableNextColumn(); + ImGui::BeginDisabled(!queryReplaceNoteDo); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::Combo("##NRMode",&queryReplaceNoteMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); ImGui::TableNextColumn(); - + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (queryReplaceNoteMode==GUI_QUERY_REPLACE_SET) { + if (queryReplaceNote==130) { + snprintf(tempID,1024,"REL"); + } else if (queryReplaceNote==129) { + snprintf(tempID,1024,"==="); + } else if (queryReplaceNote==128) { + snprintf(tempID,1024,"OFF"); + } else if (queryReplaceNote>=-60 && queryReplaceNote<120) { + snprintf(tempID,1024,"%s",noteNames[queryReplaceNote+60]); + } else { + snprintf(tempID,1024,"???"); + queryReplaceNote=0; + } + if (ImGui::BeginCombo("##NRValueC",tempID)) { + for (int j=0; j<180; j++) { + snprintf(tempID,1024,"%s",noteNames[j]); + if (ImGui::Selectable(tempID,queryReplaceNote==(j-60))) { + queryReplaceNote=j-60; + } + } + if (ImGui::Selectable("OFF",queryReplaceNote==128)) { + queryReplaceNote=128; + } + if (ImGui::Selectable("===",queryReplaceNote==129)) { + queryReplaceNote=129; + } + if (ImGui::Selectable("REL",queryReplaceNote==130)) { + queryReplaceNote=130; + } + ImGui::EndCombo(); + } + } else if (queryReplaceNoteMode==GUI_QUERY_REPLACE_ADD || queryReplaceNoteMode==GUI_QUERY_REPLACE_ADD_OVERFLOW) { + if (ImGui::InputInt("##NRValue",&queryReplaceNote,1,12)) { + if (queryReplaceNote<-180) queryReplaceNote=-180; + if (queryReplaceNote>180) queryReplaceNote=180; + } + } + ImGui::EndDisabled(); ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -384,6 +427,19 @@ void FurnaceGUI::drawFindReplace() { ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::Combo("##IRMode",&queryReplaceInsMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (queryReplaceInsMode==GUI_QUERY_REPLACE_SET) { + if (ImGui::InputScalar("##IRValueH",ImGuiDataType_S32,&queryReplaceIns,&_ONE,&_SIXTEEN,"%.2X",ImGuiInputTextFlags_CharsHexadecimal)) { + if (queryReplaceIns<0) queryReplaceIns=0; + if (queryReplaceIns>255) queryReplaceIns=255; + } + } else if (queryReplaceInsMode==GUI_QUERY_REPLACE_ADD || queryReplaceInsMode==GUI_QUERY_REPLACE_ADD_OVERFLOW) { + if (ImGui::InputInt("##IRValue",&queryReplaceIns,1,12)) { + if (queryReplaceIns<-255) queryReplaceIns=-255; + if (queryReplaceIns>255) queryReplaceIns=255; + } + } ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -391,14 +447,27 @@ void FurnaceGUI::drawFindReplace() { ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::Combo("##VRMode",&queryReplaceVolMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); - - /*ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("Effect"); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (queryReplaceVolMode==GUI_QUERY_REPLACE_SET) { + if (ImGui::InputScalar("##VRValueH",ImGuiDataType_S32,&queryReplaceVol,&_ONE,&_SIXTEEN,"%.2X",ImGuiInputTextFlags_CharsHexadecimal)) { + if (queryReplaceVol<0) queryReplaceVol=0; + if (queryReplaceVol>255) queryReplaceVol=255; + } + } else if (queryReplaceVolMode==GUI_QUERY_REPLACE_ADD || queryReplaceVolMode==GUI_QUERY_REPLACE_ADD_OVERFLOW) { + if (ImGui::InputInt("##VRValue",&queryReplaceVol,1,12)) { + if (queryReplaceVol<-255) queryReplaceVol=-255; + if (queryReplaceVol>255) queryReplaceVol=255; + } + } ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("Value");*/ + ImGui::Text("Later"); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Later"); ImGui::EndTable(); } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index ed1805f7d..c1107d2e7 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4431,6 +4431,25 @@ FurnaceGUI::FurnaceGUI(): wavePreviewLen(32), wavePreviewHeight(255), wavePreviewInit(true), + pgSys(0), + pgAddr(0), + pgVal(0), + curQueryRangeX(false), + curQueryBackwards(false), + curQueryRangeXMin(0), curQueryRangeXMax(0), + curQueryRangeY(0), + curQueryEffectPos(0), + queryReplaceEffectCount(0), + queryReplaceEffectPos(0), + queryReplaceNoteMode(0), + queryReplaceInsMode(0), + queryReplaceVolMode(0), + queryReplaceNote(0), + queryReplaceIns(0), + queryReplaceVol(0), + queryReplaceNoteDo(false), + queryReplaceInsDo(false), + queryReplaceVolDo(false), wavePreviewOn(false), wavePreviewKey((SDL_Scancode)0), wavePreviewNote(0), @@ -4624,4 +4643,11 @@ FurnaceGUI::FurnaceGUI(): memset(pianoKeyHit,0,sizeof(float)*180); memset(pianoKeyPressed,0,sizeof(bool)*180); + + memset(queryReplaceEffectMode,0,sizeof(int)*8); + memset(queryReplaceEffectValMode,0,sizeof(int)*8); + memset(queryReplaceEffect,0,sizeof(int)*8); + memset(queryReplaceEffectVal,0,sizeof(int)*8); + memset(queryReplaceEffectDo,0,sizeof(bool)*8); + memset(queryReplaceEffectValDo,0,sizeof(bool)*8); } diff --git a/src/gui/gui.h b/src/gui/gui.h index 107deb9d2..8d565da28 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1171,7 +1171,7 @@ class FurnaceGUI { int pgSys, pgAddr, pgVal; std::vector curQuery; - bool curQueryRangeX, curQueryFromStart, curQueryBackwards; + bool curQueryRangeX, curQueryBackwards; int curQueryRangeXMin, curQueryRangeXMax; int curQueryRangeY; int curQueryEffectPos; diff --git a/src/gui/intConst.cpp b/src/gui/intConst.cpp index 9c7f53b94..8bee0f88c 100644 --- a/src/gui/intConst.cpp +++ b/src/gui/intConst.cpp @@ -25,6 +25,7 @@ const int _THREE=3; const int _SEVEN=7; const int _TEN=10; const int _FIFTEEN=15; +const int _SIXTEEN=16; const int _THIRTY_ONE=31; const int _SIXTY_FOUR=64; const int _ONE_HUNDRED=100; diff --git a/src/gui/intConst.h b/src/gui/intConst.h index c6b13b9af..98c6c34ff 100644 --- a/src/gui/intConst.h +++ b/src/gui/intConst.h @@ -27,6 +27,7 @@ extern const int _THREE; extern const int _SEVEN; extern const int _TEN; extern const int _FIFTEEN; +extern const int _SIXTEEN; extern const int _THIRTY_ONE; extern const int _SIXTY_FOUR; extern const int _ONE_HUNDRED; From 30bd73f83a5306fecfe2cc33591addf8f1f653cb Mon Sep 17 00:00:00 2001 From: tildearrow Date: Fri, 10 Jun 2022 02:17:17 -0500 Subject: [PATCH 10/31] GUI: find and replace, part 7 the next parts will be dedicated on getting it working --- src/gui/findReplace.cpp | 69 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index 7ac12d1de..36048737e 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -425,6 +425,7 @@ void FurnaceGUI::drawFindReplace() { ImGui::TableNextColumn(); ImGui::Checkbox("Ins",&queryReplaceInsDo); ImGui::TableNextColumn(); + ImGui::BeginDisabled(!queryReplaceInsDo); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::Combo("##IRMode",&queryReplaceInsMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); ImGui::TableNextColumn(); @@ -440,11 +441,13 @@ void FurnaceGUI::drawFindReplace() { if (queryReplaceIns>255) queryReplaceIns=255; } } + ImGui::EndDisabled(); ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Checkbox("Volume",&queryReplaceVolDo); ImGui::TableNextColumn(); + ImGui::BeginDisabled(!queryReplaceVolDo); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::Combo("##VRMode",&queryReplaceVolMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); ImGui::TableNextColumn(); @@ -460,14 +463,72 @@ void FurnaceGUI::drawFindReplace() { if (queryReplaceVol>255) queryReplaceVol=255; } } + ImGui::EndDisabled(); + + for (int i=0; i255) queryReplaceEffect[i]=255; + } + } else if (queryReplaceEffectMode[i]==GUI_QUERY_REPLACE_ADD || queryReplaceEffectMode[i]==GUI_QUERY_REPLACE_ADD_OVERFLOW) { + if (ImGui::InputInt("##ERValue",&queryReplaceEffect[i],1,12)) { + if (queryReplaceEffect[i]<-255) queryReplaceEffect[i]=-255; + if (queryReplaceEffect[i]>255) queryReplaceEffect[i]=255; + } + } + ImGui::EndDisabled(); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Checkbox("Value",&queryReplaceEffectValDo[i]); + ImGui::TableNextColumn(); + ImGui::BeginDisabled(!queryReplaceEffectValDo[i]); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::Combo("##ERMode",&queryReplaceEffectValMode[i],queryReplaceModes,GUI_QUERY_REPLACE_MAX); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (queryReplaceEffectValMode[i]==GUI_QUERY_REPLACE_SET) { + if (ImGui::InputScalar("##ERValueH",ImGuiDataType_S32,&queryReplaceEffectVal[i],&_ONE,&_SIXTEEN,"%.2X",ImGuiInputTextFlags_CharsHexadecimal)) { + if (queryReplaceEffectVal[i]<0) queryReplaceEffectVal[i]=0; + if (queryReplaceEffectVal[i]>255) queryReplaceEffectVal[i]=255; + } + } else if (queryReplaceEffectValMode[i]==GUI_QUERY_REPLACE_ADD || queryReplaceEffectValMode[i]==GUI_QUERY_REPLACE_ADD_OVERFLOW) { + if (ImGui::InputInt("##ERValue",&queryReplaceEffectVal[i],1,12)) { + if (queryReplaceEffectVal[i]<-255) queryReplaceEffectVal[i]=-255; + if (queryReplaceEffectVal[i]>255) queryReplaceEffectVal[i]=255; + } + } + ImGui::EndDisabled(); + + + ImGui::PopID(); + } ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("Later"); - - ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("Later"); + if (queryReplaceEffectCount<8) { + if (ImGui::Button("Add effect")) { + queryReplaceEffectCount++; + } + } + ImGui::TableNextColumn(); + if (queryReplaceEffectCount>0) { + if (ImGui::Button("Remove effect")) { + queryReplaceEffectCount--; + } + } ImGui::EndTable(); } From fa9fb6f8f5e79488f4739b3497b6b74d10df4237 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Fri, 10 Jun 2022 18:27:47 -0500 Subject: [PATCH 11/31] GUI: find and replace, part 8 --- src/gui/findReplace.cpp | 127 ++++++++++++++++++++++++++++++++++++++++ src/gui/gui.h | 16 +++++ 2 files changed, 143 insertions(+) diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index 36048737e..a7dad8e83 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -22,6 +22,133 @@ const char* queryReplaceModes[GUI_QUERY_REPLACE_MAX]={ "clear" }; +int queryNote(int note, int octave) { + if (note==100) { + return 128; + } else if (note==101) { // note off and envelope release + return 129; + } else if (note==102) { // envelope release only + return 130; + } else if (octave==0 && note==0) { + return -1; + } else if (note==0 && octave!=0) { + return -1; // bug note? + } + int seek=(note+(signed char)octave*12); + if (seek<-60 || seek>=120) { + return -1; // out of range note + } + return seek; +} + +bool checkCondition(int mode, int arg, int argMax, int val, bool noteMode=false) { + switch (mode) { + case GUI_QUERY_IGNORE: + return true; + break; + case GUI_QUERY_MATCH: + return (val==arg); + break; + case GUI_QUERY_MATCH_NOT: + return (val!=-1 && val!=arg); + break; + case GUI_QUERY_RANGE: + return (val>=arg && val<=argMax); + break; + case GUI_QUERY_RANGE_NOT: + return (val!=-1 && (valargMax) && (!noteMode || val<120)); + break; + case GUI_QUERY_ANY: + return (val!=-1); + break; + case GUI_QUERY_NONE: + return (val==-1); + break; + } + return false; +} + +void FurnaceGUI::doFind() { + int firstOrder=0; + int lastOrder=e->curSubSong->ordersLen-1; + + if (curQueryRangeY==1 || curQueryRangeY==2) { + firstOrder=curOrder; + lastOrder=curOrder; + } + + int firstRow=0; + int lastRow=e->curSubSong->patLen-1; + + if (curQueryRangeY==1) { + firstRow=selStart.y; + lastRow=selEnd.y; + } + + int firstChan=0; + int lastChan=e->getTotalChannelCount()-1; + + if (curQueryRangeX) { + firstChan=curQueryRangeXMin; + lastChan=curQueryRangeXMax; + } + + curQueryResults.clear(); + + for (int i=firstOrder; i<=lastOrder; i++) { + for (int j=firstRow; j<=lastRow; j++) { + for (int k=firstChan; k<=lastChan; k++) { + DivPattern* p=e->curPat[k].getPattern(e->curOrders->ord[k][i],false); + bool matched=false; + for (FurnaceGUIFindQuery& l: curQuery) { + if (matched) break; + + if (!checkCondition(l.noteMode,l.note,l.noteMax,queryNote(p->data[j][0],p->data[j][1]),true)) continue; + if (!checkCondition(l.insMode,l.ins,l.insMax,p->data[j][2])) continue; + if (!checkCondition(l.volMode,l.vol,l.volMax,p->data[j][3])) continue; + + if (l.effectCount>0) { + bool notMatched=false; + switch (curQueryEffectPos) { + case 0: // no + // TODO + for (int m=0; mcurPat[k].effectCols; n++) { + if (!checkCondition(l.effectMode[m],l.effect[m],l.effectMax[m],p->data[j][4+m*2])) continue; + if (!checkCondition(l.effectValMode[m],l.effectVal[m],l.effectValMax[m],p->data[j][5+m*2])) continue; + } + } + break; + case 1: // lax + break; + case 2: // strict + for (int m=0; mdata[j][4+m*2])) { + notMatched=true; + break; + } + if (!checkCondition(l.effectValMode[m],l.effectVal[m],l.effectValMax[m],p->data[j][5+m*2])) { + notMatched=true; + break; + } + } + break; + } + if (notMatched) continue; + } + + matched=true; + } + if (matched) { + curQueryResults.push_back(FurnaceGUIQueryResult(e->getCurrentSubSong(),i,j,k)); + } + } + } + } + + printf("%d %d %d %d\n",firstOrder,lastOrder,firstRow,lastRow); +} + #define FIRST_VISIBLE(x) (x==GUI_QUERY_MATCH || x==GUI_QUERY_MATCH_NOT || x==GUI_QUERY_RANGE || x==GUI_QUERY_RANGE_NOT) #define SECOND_VISIBLE(x) (x==GUI_QUERY_RANGE || x==GUI_QUERY_RANGE_NOT) diff --git a/src/gui/gui.h b/src/gui/gui.h index 8d565da28..260a73419 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -856,6 +856,20 @@ struct FurnaceGUIFindQuery { } }; +struct FurnaceGUIQueryResult { + int subsong, order, x, y; + FurnaceGUIQueryResult(): + subsong(0), + order(0), + x(0), + y(0) {} + FurnaceGUIQueryResult(int ss, int o, int xPos, int yPos): + subsong(ss), + order(o), + x(xPos), + y(yPos) {} +}; + class FurnaceGUI { DivEngine* e; @@ -1171,6 +1185,7 @@ class FurnaceGUI { int pgSys, pgAddr, pgVal; std::vector curQuery; + std::vector curQueryResults; bool curQueryRangeX, curQueryBackwards; int curQueryRangeXMin, curQueryRangeXMax; int curQueryRangeY; @@ -1475,6 +1490,7 @@ class FurnaceGUI { void doExpand(int multiplier); void doUndo(); void doRedo(); + void doFind(); void editOptions(bool topMenu); void noteInput(int num, int key, int vol=-1); void valueInput(int num, bool direct=false, int target=-1); From 7354b1221ce7b9f554fabc78076ae7870e42b2c9 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 11 Jun 2022 02:14:30 -0500 Subject: [PATCH 12/31] GUI: find and replace, part 9 --- src/gui/findReplace.cpp | 1022 +++++++++++++++++++++------------------ src/gui/gui.cpp | 1 + src/gui/gui.h | 1 + 3 files changed, 549 insertions(+), 475 deletions(-) diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index a7dad8e83..700078bb5 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -4,6 +4,7 @@ #include "misc/cpp/imgui_stdlib.h" #include "guiConst.h" #include "intConst.h" +#include "../ta-log.h" const char* queryModes[GUI_QUERY_MAX]={ "ignore", @@ -140,13 +141,12 @@ void FurnaceGUI::doFind() { matched=true; } if (matched) { - curQueryResults.push_back(FurnaceGUIQueryResult(e->getCurrentSubSong(),i,j,k)); + curQueryResults.push_back(FurnaceGUIQueryResult(e->getCurrentSubSong(),i,k,j)); } } } } - - printf("%d %d %d %d\n",firstOrder,lastOrder,firstRow,lastRow); + queryViewingResults=true; } #define FIRST_VISIBLE(x) (x==GUI_QUERY_MATCH || x==GUI_QUERY_MATCH_NOT || x==GUI_QUERY_RANGE || x==GUI_QUERY_RANGE_NOT) @@ -167,515 +167,587 @@ void FurnaceGUI::drawFindReplace() { int index=0; int eraseIndex=-1; char tempID[1024]; - for (FurnaceGUIFindQuery& i: curQuery) { - if (ImGui::BeginTable("FindRep",4,ImGuiTableFlags_BordersOuter)) { - ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.5); - ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.25); - ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch,0.25); - ImGui::PushID(index); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Note"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - ImGui::Combo("##NCondition",&i.noteMode,queryModes,GUI_QUERY_MAX); - ImGui::TableNextColumn(); - if (FIRST_VISIBLE(i.noteMode)) { - if ((i.noteMode==GUI_QUERY_RANGE || i.noteMode==GUI_QUERY_RANGE_NOT) && i.note>=120) { - i.note=0; - } - if (i.note==130) { - snprintf(tempID,1024,"REL"); - } else if (i.note==129) { - snprintf(tempID,1024,"==="); - } else if (i.note==128) { - snprintf(tempID,1024,"OFF"); - } else if (i.note>=-60 && i.note<120) { - snprintf(tempID,1024,"%s",noteNames[i.note+60]); + if (ImGui::BeginTabBar("FindOrReplace")) { + if (ImGui::BeginTabItem("Find")) { + if (queryViewingResults) { + if (!curQueryResults.empty()) { + ImVec2 avail=ImGui::GetContentRegionAvail(); + avail.y-=ImGui::GetFrameHeightWithSpacing(); + if (ImGui::BeginTable("FindResults",4,ImGuiTableFlags_Borders|ImGuiTableFlags_ScrollY,avail)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,ImGui::CalcTextSize("order").x); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed,ImGui::CalcTextSize("row").x); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthFixed); + + ImGui::TableSetupScrollFreeze(0,1); + + ImGui::TableNextRow(ImGuiTableRowFlags_Headers); + ImGui::TableNextColumn(); + ImGui::Text("order"); + ImGui::TableNextColumn(); + ImGui::Text("row"); + ImGui::TableNextColumn(); + ImGui::Text("channel"); + ImGui::TableNextColumn(); + ImGui::Text("go"); + + int index=0; + for (FurnaceGUIQueryResult& i: curQueryResults) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + if (settings.orderRowsBase==1) { + ImGui::Text("%.2X",i.order); + } else { + ImGui::Text("%d",i.order); + } + ImGui::TableNextColumn(); + if (settings.patRowsBase==1) { + ImGui::Text("%.2X",i.y); + } else { + ImGui::Text("%d",i.y); + } + ImGui::TableNextColumn(); + ImGui::Text("%d (%s)",i.x+1,e->getChannelName(i.x)); + if (ImGui::TableNextColumn()) { + snprintf(tempID,1024,ICON_FA_CHEVRON_RIGHT "##_FR%d",index); + if (ImGui::Selectable(tempID)) { + e->changeSongP(i.subsong); + if (e->isPlaying()) { + followPattern=false; + } else { + e->setOrder(i.order); + } + curOrder=i.order; + cursor.xCoarse=i.x; + cursor.xFine=0; + cursor.y=i.y; + selStart=cursor; + selEnd=cursor; + demandScrollX=true; + updateScroll(cursor.y); + nextWindow=GUI_WINDOW_PATTERN; + } + } + index++; + } + ImGui::EndTable(); + } } else { - snprintf(tempID,1024,"???"); - i.note=0; + ImGui::Text("no matches found!"); } - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::BeginCombo("##NN1",tempID)) { - for (int j=0; j<180; j++) { - snprintf(tempID,1024,"%s",noteNames[j]); - if (ImGui::Selectable(tempID,i.note==(j-60))) { - i.note=j-60; - } - } - if (i.noteMode!=GUI_QUERY_RANGE && i.noteMode!=GUI_QUERY_RANGE_NOT) { - if (ImGui::Selectable("OFF",i.note==128)) { - i.note=128; - } - if (ImGui::Selectable("===",i.note==129)) { - i.note=129; - } - if (ImGui::Selectable("REL",i.note==130)) { - i.note=130; - } - } - ImGui::EndCombo(); + if (ImGui::Button("Back")) { + queryViewingResults=false; } - } - ImGui::TableNextColumn(); - if (SECOND_VISIBLE(i.noteMode)) { - if (i.noteMax<-60 || i.noteMax>=120) { - i.noteMax=0; - } - if (i.noteMax>=-60 && i.noteMax<120) { - snprintf(tempID,1024,"%s",noteNames[i.noteMax+60]); - } else { - snprintf(tempID,1024,"???"); - } - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::BeginCombo("##NN2",tempID)) { - for (int j=0; j<180; j++) { - snprintf(tempID,1024,"%s",noteNames[j]); - if (ImGui::Selectable(tempID,i.noteMax==(j-60))) { - i.noteMax=j-60; + } else { + for (FurnaceGUIFindQuery& i: curQuery) { + ImGui::PushID(index+0x100); + if (ImGui::BeginTable("FindRep",4,ImGuiTableFlags_BordersOuter)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.5); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.25); + ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch,0.25); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Note"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::Combo("##NCondition",&i.noteMode,queryModes,GUI_QUERY_MAX); + ImGui::TableNextColumn(); + if (FIRST_VISIBLE(i.noteMode)) { + if ((i.noteMode==GUI_QUERY_RANGE || i.noteMode==GUI_QUERY_RANGE_NOT) && i.note>=120) { + i.note=0; + } + if (i.note==130) { + snprintf(tempID,1024,"REL"); + } else if (i.note==129) { + snprintf(tempID,1024,"==="); + } else if (i.note==128) { + snprintf(tempID,1024,"OFF"); + } else if (i.note>=-60 && i.note<120) { + snprintf(tempID,1024,"%s",noteNames[i.note+60]); + } else { + snprintf(tempID,1024,"???"); + i.note=0; + } + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::BeginCombo("##NN1",tempID)) { + for (int j=0; j<180; j++) { + snprintf(tempID,1024,"%s",noteNames[j]); + if (ImGui::Selectable(tempID,i.note==(j-60))) { + i.note=j-60; + } + } + if (i.noteMode!=GUI_QUERY_RANGE && i.noteMode!=GUI_QUERY_RANGE_NOT) { + if (ImGui::Selectable("OFF",i.note==128)) { + i.note=128; + } + if (ImGui::Selectable("===",i.note==129)) { + i.note=129; + } + if (ImGui::Selectable("REL",i.note==130)) { + i.note=130; + } + } + ImGui::EndCombo(); + } + } + ImGui::TableNextColumn(); + if (SECOND_VISIBLE(i.noteMode)) { + if (i.noteMax<-60 || i.noteMax>=120) { + i.noteMax=0; + } + if (i.noteMax>=-60 && i.noteMax<120) { + snprintf(tempID,1024,"%s",noteNames[i.noteMax+60]); + } else { + snprintf(tempID,1024,"???"); + } + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::BeginCombo("##NN2",tempID)) { + for (int j=0; j<180; j++) { + snprintf(tempID,1024,"%s",noteNames[j]); + if (ImGui::Selectable(tempID,i.noteMax==(j-60))) { + i.noteMax=j-60; + } + } + ImGui::EndCombo(); + } } - } - ImGui::EndCombo(); - } - } - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Ins"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - ImGui::Combo("##ICondition",&i.insMode,queryModes,GUI_QUERY_MAX); - ImGui::TableNextColumn(); - if (FIRST_VISIBLE(i.insMode)) { - snprintf(tempID,1024,"%.2X",i.ins); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::BeginCombo("II1",tempID)) { - for (int j=0; j<256; j++) { - snprintf(tempID,1024,"%.2X",j); - if (ImGui::Selectable(tempID,i.ins==j)) { - i.ins=j; + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Ins"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::Combo("##ICondition",&i.insMode,queryModes,GUI_QUERY_MAX); + ImGui::TableNextColumn(); + if (FIRST_VISIBLE(i.insMode)) { + snprintf(tempID,1024,"%.2X",i.ins); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::BeginCombo("II1",tempID)) { + for (int j=0; j<256; j++) { + snprintf(tempID,1024,"%.2X",j); + if (ImGui::Selectable(tempID,i.ins==j)) { + i.ins=j; + } + } + ImGui::EndCombo(); + } } - } - ImGui::EndCombo(); - } - } - ImGui::TableNextColumn(); - if (SECOND_VISIBLE(i.insMode)) { - snprintf(tempID,1024,"%.2X",i.insMax); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::BeginCombo("II2",tempID)) { - for (int j=0; j<256; j++) { - snprintf(tempID,1024,"%.2X",j); - if (ImGui::Selectable(tempID,i.insMax==j)) { - i.insMax=j; + ImGui::TableNextColumn(); + if (SECOND_VISIBLE(i.insMode)) { + snprintf(tempID,1024,"%.2X",i.insMax); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::BeginCombo("II2",tempID)) { + for (int j=0; j<256; j++) { + snprintf(tempID,1024,"%.2X",j); + if (ImGui::Selectable(tempID,i.insMax==j)) { + i.insMax=j; + } + } + ImGui::EndCombo(); + } } - } - ImGui::EndCombo(); - } - } - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Volume"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - ImGui::Combo("##VCondition",&i.volMode,queryModes,GUI_QUERY_MAX); - ImGui::TableNextColumn(); - if (FIRST_VISIBLE(i.volMode)) { - snprintf(tempID,1024,"%.2X",i.vol); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::BeginCombo("VV1",tempID)) { - for (int j=0; j<256; j++) { - snprintf(tempID,1024,"%.2X",j); - if (ImGui::Selectable(tempID,i.vol==j)) { - i.vol=j; + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Volume"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::Combo("##VCondition",&i.volMode,queryModes,GUI_QUERY_MAX); + ImGui::TableNextColumn(); + if (FIRST_VISIBLE(i.volMode)) { + snprintf(tempID,1024,"%.2X",i.vol); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::BeginCombo("VV1",tempID)) { + for (int j=0; j<256; j++) { + snprintf(tempID,1024,"%.2X",j); + if (ImGui::Selectable(tempID,i.vol==j)) { + i.vol=j; + } + } + ImGui::EndCombo(); + } } - } - ImGui::EndCombo(); - } - } - ImGui::TableNextColumn(); - if (SECOND_VISIBLE(i.volMode)) { - snprintf(tempID,1024,"%.2X",i.volMax); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::BeginCombo("VV2",tempID)) { - for (int j=0; j<256; j++) { - snprintf(tempID,1024,"%.2X",j); - if (ImGui::Selectable(tempID,i.volMax==j)) { - i.volMax=j; + ImGui::TableNextColumn(); + if (SECOND_VISIBLE(i.volMode)) { + snprintf(tempID,1024,"%.2X",i.volMax); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::BeginCombo("VV2",tempID)) { + for (int j=0; j<256; j++) { + snprintf(tempID,1024,"%.2X",j); + if (ImGui::Selectable(tempID,i.volMax==j)) { + i.volMax=j; + } + } + ImGui::EndCombo(); + } } - } - ImGui::EndCombo(); - } - } - for (int j=0; j0) { + if (ImGui::Button("Remove effect")) { + i.effectCount--; + } + } + ImGui::EndTable(); + } + ImGui::PopID(); + index++; + } + if (eraseIndex>=0) { + curQuery.erase(curQuery.begin()+eraseIndex); + } + if (ImGui::Button(ICON_FA_PLUS "##AddQuery")) { + curQuery.push_back(FurnaceGUIFindQuery()); + } + + if (ImGui::BeginTable("QueryLimits",3)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.5f); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.5f); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + ImGui::Text("Search range:"); + + if (ImGui::RadioButton("Song",curQueryRangeY==0)) { + curQueryRangeY=0; + } + if (ImGui::RadioButton("Selection",curQueryRangeY==1)) { + curQueryRangeY=1; + } + if (ImGui::RadioButton("Pattern",curQueryRangeY==2)) { + curQueryRangeY=2; + } + + ImGui::TableNextColumn(); + ImGui::Checkbox("Confine to channels",&curQueryRangeX); + + ImGui::BeginDisabled(!curQueryRangeX); + snprintf(tempID,1024,"%d: %s",curQueryRangeXMin+1,e->getChannelName(curQueryRangeXMin)); + if (ImGui::BeginCombo("From",tempID)) { + for (int i=0; igetTotalChannelCount(); i++) { + snprintf(tempID,1024,"%d: %s",i+1,e->getChannelName(i)); + if (ImGui::Selectable(tempID,curQueryRangeXMin==i)) { + curQueryRangeXMin=i; + } + } + ImGui::EndCombo(); + } + + snprintf(tempID,1024,"%d: %s",curQueryRangeXMax+1,e->getChannelName(curQueryRangeXMax)); + if (ImGui::BeginCombo("To",tempID)) { + for (int i=0; igetTotalChannelCount(); i++) { + snprintf(tempID,1024,"%d: %s",i+1,e->getChannelName(i)); + if (ImGui::Selectable(tempID,curQueryRangeXMax==i)) { + curQueryRangeXMax=i; + } + } + ImGui::EndCombo(); + } + ImGui::EndDisabled(); + + ImGui::TableNextColumn(); + ImGui::Text("Match effect position:"); + + if (ImGui::RadioButton("No",curQueryEffectPos==0)) { + curQueryEffectPos=0; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("match effects regardless of position."); + } + if (ImGui::RadioButton("Lax",curQueryEffectPos==1)) { + curQueryEffectPos=1; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("match effects only if they appear in-order."); + } + if (ImGui::RadioButton("Strict",curQueryEffectPos==2)) { + curQueryEffectPos=2; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("match effects only if they appear exactly as specified."); + } + + ImGui::EndTable(); + } + + if (ImGui::Button("Find")) { + doFind(); + } + } + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Replace")) { + if (ImGui::BeginTable("QueryReplace",3,ImGuiTableFlags_BordersOuter)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.5); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.5); + ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("Effect"); + ImGui::Checkbox("Note",&queryReplaceNoteDo); + ImGui::TableNextColumn(); + ImGui::BeginDisabled(!queryReplaceNoteDo); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::Combo("##NRMode",&queryReplaceNoteMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - ImGui::Combo("##ECondition",&i.effectMode[j],queryModes,GUI_QUERY_MAX); - ImGui::TableNextColumn(); - if (FIRST_VISIBLE(i.effectMode[j])) { - snprintf(tempID,1024,"%.2X",i.effect[j]); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::BeginCombo("EE1",tempID)) { - for (int k=0; k<256; k++) { - snprintf(tempID,1024,"%.2X",k); - if (ImGui::Selectable(tempID,i.effect[j]==k)) { - i.effect[j]=k; + if (queryReplaceNoteMode==GUI_QUERY_REPLACE_SET) { + if (queryReplaceNote==130) { + snprintf(tempID,1024,"REL"); + } else if (queryReplaceNote==129) { + snprintf(tempID,1024,"==="); + } else if (queryReplaceNote==128) { + snprintf(tempID,1024,"OFF"); + } else if (queryReplaceNote>=-60 && queryReplaceNote<120) { + snprintf(tempID,1024,"%s",noteNames[queryReplaceNote+60]); + } else { + snprintf(tempID,1024,"???"); + queryReplaceNote=0; + } + if (ImGui::BeginCombo("##NRValueC",tempID)) { + for (int j=0; j<180; j++) { + snprintf(tempID,1024,"%s",noteNames[j]); + if (ImGui::Selectable(tempID,queryReplaceNote==(j-60))) { + queryReplaceNote=j-60; } } + if (ImGui::Selectable("OFF",queryReplaceNote==128)) { + queryReplaceNote=128; + } + if (ImGui::Selectable("===",queryReplaceNote==129)) { + queryReplaceNote=129; + } + if (ImGui::Selectable("REL",queryReplaceNote==130)) { + queryReplaceNote=130; + } ImGui::EndCombo(); } - } - ImGui::TableNextColumn(); - if (SECOND_VISIBLE(i.effectMode[j])) { - snprintf(tempID,1024,"%.2X",i.effectMax[j]); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::BeginCombo("EE2",tempID)) { - for (int k=0; k<256; k++) { - snprintf(tempID,1024,"%.2X",k); - if (ImGui::Selectable(tempID,i.effectMax[j]==k)) { - i.effectMax[j]=k; - } - } - ImGui::EndCombo(); - } - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Value"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - ImGui::Combo("##EVCondition",&i.effectValMode[j],queryModes,GUI_QUERY_MAX); - ImGui::TableNextColumn(); - if (FIRST_VISIBLE(i.effectValMode[j])) { - snprintf(tempID,1024,"%.2X",i.effectVal[j]); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::BeginCombo("EV1",tempID)) { - for (int k=0; k<256; k++) { - snprintf(tempID,1024,"%.2X",k); - if (ImGui::Selectable(tempID,i.effectVal[j]==k)) { - i.effectVal[j]=k; - } - } - ImGui::EndCombo(); - } - } - ImGui::TableNextColumn(); - if (SECOND_VISIBLE(i.effectValMode[j])) { - snprintf(tempID,1024,"%.2X",i.effectValMax[j]); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ImGui::BeginCombo("EV2",tempID)) { - for (int k=0; k<256; k++) { - snprintf(tempID,1024,"%.2X",k); - if (ImGui::Selectable(tempID,i.effectValMax[j]==k)) { - i.effectValMax[j]=k; - } - } - ImGui::EndCombo(); - } - } - - ImGui::PopID(); - } - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - if (ImGui::Button(ICON_FA_MINUS "##DelQuery")) { - eraseIndex=index; - } - ImGui::TableNextColumn(); - if (i.effectCount<8) { - if (ImGui::Button("Add effect")) { - i.effectCount++; - } - } - ImGui::TableNextColumn(); - if (i.effectCount>0) { - if (ImGui::Button("Remove effect")) { - i.effectCount--; - } - } - ImGui::PopID(); - ImGui::EndTable(); - } - index++; - } - if (ImGui::Button("Find")) { - - } - ImGui::SameLine(); - if (eraseIndex>=0) { - curQuery.erase(curQuery.begin()+eraseIndex); - } - if (ImGui::Button(ICON_FA_PLUS "##AddQuery")) { - curQuery.push_back(FurnaceGUIFindQuery()); - } - - if (ImGui::BeginTable("QueryLimits",3)) { - ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.5f); - ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.5f); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - - ImGui::Text("Search range:"); - - if (ImGui::RadioButton("Song",curQueryRangeY==0)) { - curQueryRangeY=0; - } - if (ImGui::RadioButton("Selection",curQueryRangeY==1)) { - curQueryRangeY=1; - } - if (ImGui::RadioButton("Pattern",curQueryRangeY==2)) { - curQueryRangeY=2; - } - - ImGui::TableNextColumn(); - ImGui::Checkbox("Confine to channels",&curQueryRangeX); - - ImGui::BeginDisabled(!curQueryRangeX); - snprintf(tempID,1024,"%d: %s",curQueryRangeXMin+1,e->getChannelName(curQueryRangeXMin)); - if (ImGui::BeginCombo("From",tempID)) { - for (int i=0; igetTotalChannelCount(); i++) { - snprintf(tempID,1024,"%d: %s",i+1,e->getChannelName(i)); - if (ImGui::Selectable(tempID,curQueryRangeXMin==i)) { - curQueryRangeXMin=i; - } - } - ImGui::EndCombo(); - } - - snprintf(tempID,1024,"%d: %s",curQueryRangeXMax+1,e->getChannelName(curQueryRangeXMax)); - if (ImGui::BeginCombo("To",tempID)) { - for (int i=0; igetTotalChannelCount(); i++) { - snprintf(tempID,1024,"%d: %s",i+1,e->getChannelName(i)); - if (ImGui::Selectable(tempID,curQueryRangeXMax==i)) { - curQueryRangeXMax=i; - } - } - ImGui::EndCombo(); - } - ImGui::EndDisabled(); - - ImGui::TableNextColumn(); - ImGui::Text("Match effect position:"); - - if (ImGui::RadioButton("No",curQueryEffectPos==0)) { - curQueryEffectPos=0; - } - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("match effects regardless of position."); - } - if (ImGui::RadioButton("Lax",curQueryEffectPos==1)) { - curQueryEffectPos=1; - } - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("match effects only if they appear in-order."); - } - if (ImGui::RadioButton("Strict",curQueryEffectPos==2)) { - curQueryEffectPos=2; - } - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("match effects only if they appear exactly as specified."); - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Checkbox("Backwards",&curQueryBackwards); - - ImGui::EndTable(); - } - - if (ImGui::TreeNode("Replace")) { - if (ImGui::BeginTable("QueryReplace",3,ImGuiTableFlags_BordersOuter)) { - ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); - ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.5); - ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.5); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Checkbox("Note",&queryReplaceNoteDo); - ImGui::TableNextColumn(); - ImGui::BeginDisabled(!queryReplaceNoteDo); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - ImGui::Combo("##NRMode",&queryReplaceNoteMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (queryReplaceNoteMode==GUI_QUERY_REPLACE_SET) { - if (queryReplaceNote==130) { - snprintf(tempID,1024,"REL"); - } else if (queryReplaceNote==129) { - snprintf(tempID,1024,"==="); - } else if (queryReplaceNote==128) { - snprintf(tempID,1024,"OFF"); - } else if (queryReplaceNote>=-60 && queryReplaceNote<120) { - snprintf(tempID,1024,"%s",noteNames[queryReplaceNote+60]); - } else { - snprintf(tempID,1024,"???"); - queryReplaceNote=0; - } - if (ImGui::BeginCombo("##NRValueC",tempID)) { - for (int j=0; j<180; j++) { - snprintf(tempID,1024,"%s",noteNames[j]); - if (ImGui::Selectable(tempID,queryReplaceNote==(j-60))) { - queryReplaceNote=j-60; - } - } - if (ImGui::Selectable("OFF",queryReplaceNote==128)) { - queryReplaceNote=128; - } - if (ImGui::Selectable("===",queryReplaceNote==129)) { - queryReplaceNote=129; - } - if (ImGui::Selectable("REL",queryReplaceNote==130)) { - queryReplaceNote=130; - } - ImGui::EndCombo(); - } - } else if (queryReplaceNoteMode==GUI_QUERY_REPLACE_ADD || queryReplaceNoteMode==GUI_QUERY_REPLACE_ADD_OVERFLOW) { - if (ImGui::InputInt("##NRValue",&queryReplaceNote,1,12)) { - if (queryReplaceNote<-180) queryReplaceNote=-180; - if (queryReplaceNote>180) queryReplaceNote=180; - } - } - ImGui::EndDisabled(); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Checkbox("Ins",&queryReplaceInsDo); - ImGui::TableNextColumn(); - ImGui::BeginDisabled(!queryReplaceInsDo); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - ImGui::Combo("##IRMode",&queryReplaceInsMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (queryReplaceInsMode==GUI_QUERY_REPLACE_SET) { - if (ImGui::InputScalar("##IRValueH",ImGuiDataType_S32,&queryReplaceIns,&_ONE,&_SIXTEEN,"%.2X",ImGuiInputTextFlags_CharsHexadecimal)) { - if (queryReplaceIns<0) queryReplaceIns=0; - if (queryReplaceIns>255) queryReplaceIns=255; - } - } else if (queryReplaceInsMode==GUI_QUERY_REPLACE_ADD || queryReplaceInsMode==GUI_QUERY_REPLACE_ADD_OVERFLOW) { - if (ImGui::InputInt("##IRValue",&queryReplaceIns,1,12)) { - if (queryReplaceIns<-255) queryReplaceIns=-255; - if (queryReplaceIns>255) queryReplaceIns=255; - } - } - ImGui::EndDisabled(); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Checkbox("Volume",&queryReplaceVolDo); - ImGui::TableNextColumn(); - ImGui::BeginDisabled(!queryReplaceVolDo); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - ImGui::Combo("##VRMode",&queryReplaceVolMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (queryReplaceVolMode==GUI_QUERY_REPLACE_SET) { - if (ImGui::InputScalar("##VRValueH",ImGuiDataType_S32,&queryReplaceVol,&_ONE,&_SIXTEEN,"%.2X",ImGuiInputTextFlags_CharsHexadecimal)) { - if (queryReplaceVol<0) queryReplaceVol=0; - if (queryReplaceVol>255) queryReplaceVol=255; - } - } else if (queryReplaceVolMode==GUI_QUERY_REPLACE_ADD || queryReplaceVolMode==GUI_QUERY_REPLACE_ADD_OVERFLOW) { - if (ImGui::InputInt("##VRValue",&queryReplaceVol,1,12)) { - if (queryReplaceVol<-255) queryReplaceVol=-255; - if (queryReplaceVol>255) queryReplaceVol=255; - } - } - ImGui::EndDisabled(); - - for (int i=0; i255) queryReplaceEffect[i]=255; - } - } else if (queryReplaceEffectMode[i]==GUI_QUERY_REPLACE_ADD || queryReplaceEffectMode[i]==GUI_QUERY_REPLACE_ADD_OVERFLOW) { - if (ImGui::InputInt("##ERValue",&queryReplaceEffect[i],1,12)) { - if (queryReplaceEffect[i]<-255) queryReplaceEffect[i]=-255; - if (queryReplaceEffect[i]>255) queryReplaceEffect[i]=255; + } else if (queryReplaceNoteMode==GUI_QUERY_REPLACE_ADD || queryReplaceNoteMode==GUI_QUERY_REPLACE_ADD_OVERFLOW) { + if (ImGui::InputInt("##NRValue",&queryReplaceNote,1,12)) { + if (queryReplaceNote<-180) queryReplaceNote=-180; + if (queryReplaceNote>180) queryReplaceNote=180; } } ImGui::EndDisabled(); ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Checkbox("Value",&queryReplaceEffectValDo[i]); + ImGui::Checkbox("Ins",&queryReplaceInsDo); ImGui::TableNextColumn(); - ImGui::BeginDisabled(!queryReplaceEffectValDo[i]); + ImGui::BeginDisabled(!queryReplaceInsDo); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - ImGui::Combo("##ERMode",&queryReplaceEffectValMode[i],queryReplaceModes,GUI_QUERY_REPLACE_MAX); + ImGui::Combo("##IRMode",&queryReplaceInsMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (queryReplaceEffectValMode[i]==GUI_QUERY_REPLACE_SET) { - if (ImGui::InputScalar("##ERValueH",ImGuiDataType_S32,&queryReplaceEffectVal[i],&_ONE,&_SIXTEEN,"%.2X",ImGuiInputTextFlags_CharsHexadecimal)) { - if (queryReplaceEffectVal[i]<0) queryReplaceEffectVal[i]=0; - if (queryReplaceEffectVal[i]>255) queryReplaceEffectVal[i]=255; + if (queryReplaceInsMode==GUI_QUERY_REPLACE_SET) { + if (ImGui::InputScalar("##IRValueH",ImGuiDataType_S32,&queryReplaceIns,&_ONE,&_SIXTEEN,"%.2X",ImGuiInputTextFlags_CharsHexadecimal)) { + if (queryReplaceIns<0) queryReplaceIns=0; + if (queryReplaceIns>255) queryReplaceIns=255; } - } else if (queryReplaceEffectValMode[i]==GUI_QUERY_REPLACE_ADD || queryReplaceEffectValMode[i]==GUI_QUERY_REPLACE_ADD_OVERFLOW) { - if (ImGui::InputInt("##ERValue",&queryReplaceEffectVal[i],1,12)) { - if (queryReplaceEffectVal[i]<-255) queryReplaceEffectVal[i]=-255; - if (queryReplaceEffectVal[i]>255) queryReplaceEffectVal[i]=255; + } else if (queryReplaceInsMode==GUI_QUERY_REPLACE_ADD || queryReplaceInsMode==GUI_QUERY_REPLACE_ADD_OVERFLOW) { + if (ImGui::InputInt("##IRValue",&queryReplaceIns,1,12)) { + if (queryReplaceIns<-255) queryReplaceIns=-255; + if (queryReplaceIns>255) queryReplaceIns=255; } } ImGui::EndDisabled(); - - ImGui::PopID(); - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::TableNextColumn(); - if (queryReplaceEffectCount<8) { - if (ImGui::Button("Add effect")) { - queryReplaceEffectCount++; + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Checkbox("Volume",&queryReplaceVolDo); + ImGui::TableNextColumn(); + ImGui::BeginDisabled(!queryReplaceVolDo); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::Combo("##VRMode",&queryReplaceVolMode,queryReplaceModes,GUI_QUERY_REPLACE_MAX); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (queryReplaceVolMode==GUI_QUERY_REPLACE_SET) { + if (ImGui::InputScalar("##VRValueH",ImGuiDataType_S32,&queryReplaceVol,&_ONE,&_SIXTEEN,"%.2X",ImGuiInputTextFlags_CharsHexadecimal)) { + if (queryReplaceVol<0) queryReplaceVol=0; + if (queryReplaceVol>255) queryReplaceVol=255; + } + } else if (queryReplaceVolMode==GUI_QUERY_REPLACE_ADD || queryReplaceVolMode==GUI_QUERY_REPLACE_ADD_OVERFLOW) { + if (ImGui::InputInt("##VRValue",&queryReplaceVol,1,12)) { + if (queryReplaceVol<-255) queryReplaceVol=-255; + if (queryReplaceVol>255) queryReplaceVol=255; + } } - } - ImGui::TableNextColumn(); - if (queryReplaceEffectCount>0) { - if (ImGui::Button("Remove effect")) { - queryReplaceEffectCount--; - } - } + ImGui::EndDisabled(); - ImGui::EndTable(); + for (int i=0; i255) queryReplaceEffect[i]=255; + } + } else if (queryReplaceEffectMode[i]==GUI_QUERY_REPLACE_ADD || queryReplaceEffectMode[i]==GUI_QUERY_REPLACE_ADD_OVERFLOW) { + if (ImGui::InputInt("##ERValue",&queryReplaceEffect[i],1,12)) { + if (queryReplaceEffect[i]<-255) queryReplaceEffect[i]=-255; + if (queryReplaceEffect[i]>255) queryReplaceEffect[i]=255; + } + } + ImGui::EndDisabled(); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Checkbox("Value",&queryReplaceEffectValDo[i]); + ImGui::TableNextColumn(); + ImGui::BeginDisabled(!queryReplaceEffectValDo[i]); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::Combo("##ERMode",&queryReplaceEffectValMode[i],queryReplaceModes,GUI_QUERY_REPLACE_MAX); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (queryReplaceEffectValMode[i]==GUI_QUERY_REPLACE_SET) { + if (ImGui::InputScalar("##ERValueH",ImGuiDataType_S32,&queryReplaceEffectVal[i],&_ONE,&_SIXTEEN,"%.2X",ImGuiInputTextFlags_CharsHexadecimal)) { + if (queryReplaceEffectVal[i]<0) queryReplaceEffectVal[i]=0; + if (queryReplaceEffectVal[i]>255) queryReplaceEffectVal[i]=255; + } + } else if (queryReplaceEffectValMode[i]==GUI_QUERY_REPLACE_ADD || queryReplaceEffectValMode[i]==GUI_QUERY_REPLACE_ADD_OVERFLOW) { + if (ImGui::InputInt("##ERValue",&queryReplaceEffectVal[i],1,12)) { + if (queryReplaceEffectVal[i]<-255) queryReplaceEffectVal[i]=-255; + if (queryReplaceEffectVal[i]>255) queryReplaceEffectVal[i]=255; + } + } + ImGui::EndDisabled(); + + + ImGui::PopID(); + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TableNextColumn(); + if (queryReplaceEffectCount<8) { + if (ImGui::Button("Add effect")) { + queryReplaceEffectCount++; + } + } + ImGui::TableNextColumn(); + if (queryReplaceEffectCount>0) { + if (ImGui::Button("Remove effect")) { + queryReplaceEffectCount--; + } + } + + ImGui::EndTable(); + } + ImGui::Text("Effect replace mode:"); + if (ImGui::RadioButton("Clear effects",queryReplaceEffectPos==0)) { + queryReplaceEffectPos=0; + } + if (ImGui::RadioButton("Replace matches only",queryReplaceEffectPos==1)) { + queryReplaceEffectPos=1; + } + if (ImGui::RadioButton("Replace matches, then free spaces",queryReplaceEffectPos==2)) { + queryReplaceEffectPos=2; + } + if (ImGui::RadioButton("Insert in free spaces",queryReplaceEffectPos==3)) { + queryReplaceEffectPos=3; + } + if (ImGui::Button("Replace##QueryReplace")) { + // TODO + } + ImGui::EndTabItem(); } - ImGui::Text("Effect replace mode:"); - if (ImGui::RadioButton("Clear effects",queryReplaceEffectPos==0)) { - queryReplaceEffectPos=0; - } - if (ImGui::RadioButton("Replace matches only",queryReplaceEffectPos==1)) { - queryReplaceEffectPos=1; - } - if (ImGui::RadioButton("Replace matches, then free spaces",queryReplaceEffectPos==2)) { - queryReplaceEffectPos=2; - } - if (ImGui::RadioButton("Insert in free spaces",queryReplaceEffectPos==3)) { - queryReplaceEffectPos=3; - } - if (ImGui::Button("Replace##QueryReplace")) { - // TODO - } - ImGui::TreePop(); + ImGui::EndTabBar(); } } if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_FIND; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index c1107d2e7..b982987c3 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4450,6 +4450,7 @@ FurnaceGUI::FurnaceGUI(): queryReplaceNoteDo(false), queryReplaceInsDo(false), queryReplaceVolDo(false), + queryViewingResults(false), wavePreviewOn(false), wavePreviewKey((SDL_Scancode)0), wavePreviewNote(0), diff --git a/src/gui/gui.h b/src/gui/gui.h index 260a73419..300fa8fca 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1208,6 +1208,7 @@ class FurnaceGUI { bool queryReplaceVolDo; bool queryReplaceEffectDo[8]; bool queryReplaceEffectValDo[8]; + bool queryViewingResults; struct ActiveNote { int chan; From 44341d8ccd6134b44a44f28fd7e4b177eaa65c37 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 11 Jun 2022 03:53:34 -0500 Subject: [PATCH 13/31] GUI: find and replace, part 10 find kind of works (only lax mode left to do) then i'll do replace --- src/gui/findReplace.cpp | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index 700078bb5..77c1a7e3a 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -112,25 +112,36 @@ void FurnaceGUI::doFind() { bool notMatched=false; switch (curQueryEffectPos) { case 0: // no - // TODO for (int m=0; mcurPat[k].effectCols; n++) { - if (!checkCondition(l.effectMode[m],l.effect[m],l.effectMax[m],p->data[j][4+m*2])) continue; - if (!checkCondition(l.effectValMode[m],l.effectVal[m],l.effectValMax[m],p->data[j][5+m*2])) continue; + if (!checkCondition(l.effectMode[m],l.effect[m],l.effectMax[m],p->data[j][4+n*2])) continue; + if (!checkCondition(l.effectValMode[m],l.effectVal[m],l.effectValMax[m],p->data[j][5+n*2])) continue; + allGood=true; + break; + } + if (!allGood) { + notMatched=true; + break; } } break; case 1: // lax break; case 2: // strict - for (int m=0; mdata[j][4+m*2])) { - notMatched=true; - break; - } - if (!checkCondition(l.effectValMode[m],l.effectVal[m],l.effectValMax[m],p->data[j][5+m*2])) { - notMatched=true; - break; + int effectMax=l.effectCount; + if (effectMax>e->curPat[k].effectCols) { + notMatched=true; + } else { + for (int m=0; mdata[j][4+m*2])) { + notMatched=true; + break; + } + if (!checkCondition(l.effectValMode[m],l.effectVal[m],l.effectValMax[m],p->data[j][5+m*2])) { + notMatched=true; + break; + } } } break; From 3ebbb85f4c265c9106a8612761484fe619259fb2 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 11 Jun 2022 22:36:49 -0500 Subject: [PATCH 14/31] add another demo song MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit requested by AURORA✭FIELDS --- demos/Funky_Bubbles_OPL3.fur | Bin 0 -> 6660 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 demos/Funky_Bubbles_OPL3.fur diff --git a/demos/Funky_Bubbles_OPL3.fur b/demos/Funky_Bubbles_OPL3.fur new file mode 100644 index 0000000000000000000000000000000000000000..5f2ffd24433d6661622af33ad8ab6daad526d037 GIT binary patch literal 6660 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 XSj>`qvZn83JNwIIoSw#wI{5z=(2Gnk literal 0 HcmV?d00001 From 19251e84f6033e859a3a514e4674510e8cd193e4 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 11 Jun 2022 22:37:06 -0500 Subject: [PATCH 15/31] add yet another demo song by Laagy --- demos/going_up_a_step_at_time.fur | Bin 0 -> 7710 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 demos/going_up_a_step_at_time.fur diff --git a/demos/going_up_a_step_at_time.fur b/demos/going_up_a_step_at_time.fur new file mode 100644 index 0000000000000000000000000000000000000000..7d52d155aa1735f1343056be174d1d9044509d30 GIT binary patch literal 7710 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 Date: Sat, 11 Jun 2022 22:42:30 -0500 Subject: [PATCH 16/31] GUI: find and replace, part 11 lax mode done now replace time... --- src/gui/findReplace.cpp | 36 ++++++++++++++++++++++++++++++++++-- src/gui/gui.h | 1 + 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index 77c1a7e3a..3f877242f 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -126,8 +126,37 @@ void FurnaceGUI::doFind() { } } break; - case 1: // lax + case 1: { // lax + // locate first effect + int posOfFirst=-1; + for (int m=0; mcurPat[k].effectCols; m++) { + if (!checkCondition(l.effectMode[0],l.effect[0],l.effectMax[0],p->data[j][4+m*2])) continue; + if (!checkCondition(l.effectValMode[0],l.effectVal[0],l.effectValMax[0],p->data[j][5+m*2])) continue; + posOfFirst=m; + break; + } + if (posOfFirst<0) { + notMatched=true; + break; + } + // make sure we aren't too far to the right + if ((posOfFirst+l.effectCount)>e->curPat[k].effectCols) { + notMatched=true; + break; + } + // search from first effect location + for (int m=0; mdata[j][4+(m+posOfFirst)*2])) { + notMatched=true; + break; + } + if (!checkCondition(l.effectValMode[m],l.effectVal[m],l.effectValMax[m],p->data[j][5+(m+posOfFirst)*2])) { + notMatched=true; + break; + } + } break; + } case 2: // strict int effectMax=l.effectCount; if (effectMax>e->curPat[k].effectCols) { @@ -160,6 +189,9 @@ void FurnaceGUI::doFind() { queryViewingResults=true; } +void FurnaceGUI::doReplace() { +} + #define FIRST_VISIBLE(x) (x==GUI_QUERY_MATCH || x==GUI_QUERY_MATCH_NOT || x==GUI_QUERY_RANGE || x==GUI_QUERY_RANGE_NOT) #define SECOND_VISIBLE(x) (x==GUI_QUERY_RANGE || x==GUI_QUERY_RANGE_NOT) @@ -754,7 +786,7 @@ void FurnaceGUI::drawFindReplace() { queryReplaceEffectPos=3; } if (ImGui::Button("Replace##QueryReplace")) { - // TODO + doReplace(); } ImGui::EndTabItem(); } diff --git a/src/gui/gui.h b/src/gui/gui.h index 300fa8fca..55ea989c8 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1492,6 +1492,7 @@ class FurnaceGUI { void doUndo(); void doRedo(); void doFind(); + void doReplace(); void editOptions(bool topMenu); void noteInput(int num, int key, int vol=-1); void valueInput(int num, bool direct=false, int target=-1); From 74b524a912387a83cd985350c97163f2cae93146 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 12 Jun 2022 03:50:05 -0500 Subject: [PATCH 17/31] GUI: find and replace, part 12 replace is almost complete - some refinements left to do though --- TODO.md | 1 - src/gui/findReplace.cpp | 201 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 198 insertions(+), 4 deletions(-) diff --git a/TODO.md b/TODO.md index 5bd4e8925..12a7e47ec 100644 --- a/TODO.md +++ b/TODO.md @@ -3,7 +3,6 @@ - rewrite the system name detection function anyway - add another FM editor layout - add ability to move selection by dragging -- find and replace - implement Defle slide bug when using E1xy/E2xy and repeating origin note (requires format change) # to-do for 0.6pre2 (as this requires new data structures) diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index 3f877242f..9ab75f6fb 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -31,13 +31,13 @@ int queryNote(int note, int octave) { } else if (note==102) { // envelope release only return 130; } else if (octave==0 && note==0) { - return -1; + return -61; } else if (note==0 && octave!=0) { - return -1; // bug note? + return -61; // bug note? } int seek=(note+(signed char)octave*12); if (seek<-60 || seek>=120) { - return -1; // out of range note + return -61; // out of range note } return seek; } @@ -190,6 +190,201 @@ void FurnaceGUI::doFind() { } void FurnaceGUI::doReplace() { + doFind(); + queryViewingResults=false; + + for (FurnaceGUIQueryResult& i: curQueryResults) { + DivPattern* p=e->song.subsong[i.subsong]->pat[i.x].getPattern(e->song.subsong[i.subsong]->orders.ord[i.x][i.order],true); + if (queryReplaceNoteDo) { + switch (queryReplaceNoteMode) { + case GUI_QUERY_REPLACE_SET: + if (queryReplaceNote==130) { // macro release + p->data[i.y][0]=102; + p->data[i.y][1]=0; + } else if (queryReplaceNote==129) { // note release + p->data[i.y][0]=101; + p->data[i.y][1]=0; + } else if (queryReplaceNote==128) { // note off + p->data[i.y][0]=100; + p->data[i.y][1]=0; + } else if (queryReplaceNote>=-60 && queryReplaceNote<120) { // note + p->data[i.y][0]=(queryReplaceNote+60)%12; + if (p->data[i.y][0]==0) p->data[i.y][0]=12; + p->data[i.y][1]=(unsigned char)((queryReplaceNote-1)/12); + } else { // invalid + p->data[i.y][0]=0; + p->data[i.y][1]=0; + } + break; + case GUI_QUERY_REPLACE_ADD: + if (p->data[i.y][0]<100) { + int note=queryNote(p->data[i.y][0],p->data[i.y][1]); + if (note>=-60 && note<120) { + note+=queryReplaceNote; + if (note<-60) note=-60; + if (note>119) note=119; + + p->data[i.y][0]=(note+60)%12; + if (p->data[i.y][0]==0) p->data[i.y][0]=12; + p->data[i.y][1]=(unsigned char)((note-1)/12); + } + } + break; + case GUI_QUERY_REPLACE_ADD_OVERFLOW: + if (p->data[i.y][0]<100) { + int note=queryNote(p->data[i.y][0],p->data[i.y][1]); + if (note>=-60 && note<120) { + note+=queryReplaceNote; + if (note<-60) { + while (note<-60) note+=180; + } else if (note>119) { + while (note>119) note-=180; + } + + p->data[i.y][0]=(note+60)%12; + if (p->data[i.y][0]==0) p->data[i.y][0]=12; + p->data[i.y][1]=(unsigned char)((note-1)/12); + } + } + break; + case GUI_QUERY_REPLACE_CLEAR: + p->data[i.y][0]=0; + p->data[i.y][1]=0; + break; + } + } + + if (queryReplaceInsDo) { + switch (queryReplaceInsMode) { + case GUI_QUERY_REPLACE_SET: + p->data[i.y][2]=queryReplaceIns; + break; + case GUI_QUERY_REPLACE_ADD: + if (p->data[i.y][2]>=0) { + p->data[i.y][2]+=queryReplaceIns; + if (p->data[i.y][2]<0) p->data[i.y][2]=0; + if (p->data[i.y][2]>255) p->data[i.y][2]=255; + } + break; + case GUI_QUERY_REPLACE_ADD_OVERFLOW: + if (p->data[i.y][2]>=0) p->data[i.y][2]=(p->data[i.y][2]+queryReplaceIns)&0xff; + break; + case GUI_QUERY_REPLACE_CLEAR: + p->data[i.y][2]=-1; + break; + } + } + + if (queryReplaceVolDo) { + switch (queryReplaceVolMode) { + case GUI_QUERY_REPLACE_SET: + p->data[i.y][3]=queryReplaceVol; + break; + case GUI_QUERY_REPLACE_ADD: + if (p->data[i.y][3]>=0) { + p->data[i.y][3]+=queryReplaceVol; + if (p->data[i.y][3]<0) p->data[i.y][3]=0; + if (p->data[i.y][3]>255) p->data[i.y][3]=255; + } + break; + case GUI_QUERY_REPLACE_ADD_OVERFLOW: + if (p->data[i.y][3]>=0) p->data[i.y][3]=(p->data[i.y][3]+queryReplaceVol)&0xff; + break; + case GUI_QUERY_REPLACE_CLEAR: + p->data[i.y][3]=-1; + break; + } + } + + signed char effectOrder[8]; + memset(effectOrder,-1,8); + + switch (queryReplaceEffectPos) { + case 0: // clear + for (int j=0; jsong.subsong[i.subsong]->pat[i.x].effectCols; j++) { + effectOrder[j]=j; + } + break; + case 1: { // replace matches + int placementIndex=0; + for (int j=0; jsong.subsong[i.subsong]->pat[i.x].effectCols; j++) { + if (p->data[i.y][4+j*2]!=-1 || p->data[i.y][5+j*2]!=-1) { + effectOrder[placementIndex++]=j; + } + } + break; + } + case 2: { // replace matches then free spaces + int placementIndex=0; + for (int j=0; jsong.subsong[i.subsong]->pat[i.x].effectCols; j++) { + if (p->data[i.y][4+j*2]!=-1 || p->data[i.y][5+j*2]!=-1) { + effectOrder[placementIndex++]=j; + } + } + for (int j=0; jsong.subsong[i.subsong]->pat[i.x].effectCols; j++) { + if (p->data[i.y][4+j*2]==-1 && p->data[i.y][5+j*2]==-1) { + effectOrder[placementIndex++]=j; + } + } + break; + } + case 3: { // insert in free spaces + int placementIndex=0; + for (int j=0; jsong.subsong[i.subsong]->pat[i.x].effectCols; j++) { + if (p->data[i.y][4+j*2]==-1 && p->data[i.y][5+j*2]==-1) { + effectOrder[placementIndex++]=j; + } + } + break; + } + } + + for (int j=0; jdata[i.y][4+pos*2]=queryReplaceEffect[j]; + break; + case GUI_QUERY_REPLACE_ADD: + if (p->data[i.y][4+pos*2]>=0) { + p->data[i.y][4+pos*2]+=queryReplaceEffect[j]; + if (p->data[i.y][4+pos*2]<0) p->data[i.y][4+pos*2]=0; + if (p->data[i.y][4+pos*2]>255) p->data[i.y][4+pos*2]=255; + } + break; + case GUI_QUERY_REPLACE_ADD_OVERFLOW: + if (p->data[i.y][4+pos*2]>=0) p->data[i.y][4+pos*2]=(p->data[i.y][4+pos*2]+queryReplaceEffect[j])&0xff; + break; + case GUI_QUERY_REPLACE_CLEAR: + p->data[i.y][4+pos*2]=-1; + break; + } + } + + if (queryReplaceEffectValDo[j]) { + switch (queryReplaceEffectValMode[j]) { + case GUI_QUERY_REPLACE_SET: + p->data[i.y][5+pos*2]=queryReplaceEffectVal[j]; + break; + case GUI_QUERY_REPLACE_ADD: + if (p->data[i.y][5+pos*2]>=0) { + p->data[i.y][5+pos*2]+=queryReplaceEffectVal[j]; + if (p->data[i.y][5+pos*2]<0) p->data[i.y][5+pos*2]=0; + if (p->data[i.y][5+pos*2]>255) p->data[i.y][5+pos*2]=255; + } + break; + case GUI_QUERY_REPLACE_ADD_OVERFLOW: + if (p->data[i.y][5+pos*2]>=0) p->data[i.y][5+pos*2]=(p->data[i.y][5+pos*2]+queryReplaceEffectVal[j])&0xff; + break; + case GUI_QUERY_REPLACE_CLEAR: + p->data[i.y][5+pos*2]=-1; + break; + } + } + } + } } #define FIRST_VISIBLE(x) (x==GUI_QUERY_MATCH || x==GUI_QUERY_MATCH_NOT || x==GUI_QUERY_RANGE || x==GUI_QUERY_RANGE_NOT) From f3f8804f47995956f8a1f69c869bece471032e69 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 12 Jun 2022 14:39:08 -0500 Subject: [PATCH 18/31] GUI: find and replace, part 13 one more part coming or maybe not --- src/gui/findReplace.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index 9ab75f6fb..d5548c0fb 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -193,8 +193,18 @@ void FurnaceGUI::doReplace() { doFind(); queryViewingResults=false; + bool* touched[DIV_MAX_CHANS]; + memset(touched,0,DIV_MAX_CHANS*sizeof(bool*)); + for (FurnaceGUIQueryResult& i: curQueryResults) { - DivPattern* p=e->song.subsong[i.subsong]->pat[i.x].getPattern(e->song.subsong[i.subsong]->orders.ord[i.x][i.order],true); + int patIndex=e->song.subsong[i.subsong]->orders.ord[i.x][i.order]; + DivPattern* p=e->song.subsong[i.subsong]->pat[i.x].getPattern(patIndex,true); + if (touched[i.x]==NULL) { + touched[i.x]=new bool[256*256]; + memset(touched[i.x],0,256*256*sizeof(bool)); + } + if (touched[i.x][(patIndex<<8)|i.y]) continue; + touched[i.x][(patIndex<<8)|i.y]=true; if (queryReplaceNoteDo) { switch (queryReplaceNoteMode) { case GUI_QUERY_REPLACE_SET: @@ -385,6 +395,10 @@ void FurnaceGUI::doReplace() { } } } + + for (int i=0; i Date: Sun, 12 Jun 2022 23:22:45 -0500 Subject: [PATCH 19/31] OPL: fix 4-op channel muting --- src/engine/platform/opl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index fbf914484..e6f730c26 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -677,6 +677,9 @@ void DivPlatformOPL::muteChannel(int ch, bool mute) { fm.channel[outChanMap[ch]].muted=mute; } int ops=(slots[3][ch]!=255 && chan[ch].state.ops==4 && oplType==3)?4:2; + if (ch&1 && ch<12) { + if (chan[ch-1].fourOp) return; + } chan[ch].fourOp=(ops==4); update4OpMask=true; for (int i=0; i Date: Mon, 13 Jun 2022 03:54:42 -0500 Subject: [PATCH 20/31] GUI: work on alternate FM layout --- TODO.md | 4 +- src/gui/insEdit.cpp | 555 ++++++++++++++++++++++++++++++++++++++++++- src/gui/settings.cpp | 11 +- 3 files changed, 567 insertions(+), 3 deletions(-) diff --git a/TODO.md b/TODO.md index 12a7e47ec..d667201ec 100644 --- a/TODO.md +++ b/TODO.md @@ -1,11 +1,13 @@ # to-do for 0.6pre1 -- rewrite the system name detection function anyway - add another FM editor layout - add ability to move selection by dragging - implement Defle slide bug when using E1xy/E2xy and repeating origin note (requires format change) # to-do for 0.6pre2 (as this requires new data structures) +- rewrite the system name detection function anyway + - this involves the addition of a new "system" field in the song (which solves the problem) + - songs made in older versions will go through old system name detection for compatibility - Game Boy envelope macro/sequence - volume commands should work on Game Boy diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 7d7fa050b..81edbfe19 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -1345,6 +1345,9 @@ void FurnaceGUI::drawMacros(std::vector& macros) { #define CENTER_VSLIDER \ ImGui::SetCursorPosX(ImGui::GetCursorPosX()+0.5f*ImGui::GetContentRegionAvail().x-10.0f*dpiScale); +#define CENTER_TEXT_20(text) \ + ImGui::SetCursorPosX(ImGui::GetCursorPosX()+0.5*(20.0f*dpiScale-ImGui::CalcTextSize(text).x)); + void FurnaceGUI::drawInsEdit() { if (nextWindow==GUI_WINDOW_INS_EDIT) { insEditOpen=true; @@ -2016,7 +2019,557 @@ void FurnaceGUI::drawInsEdit() { ImGui::EndTable(); } - } else { + } else if (settings.fmLayout>=4 && settings.fmLayout<=6) { // alternate + int columns=2; + switch (settings.fmLayout) { + case 4: // 2x2 + columns=2; + break; + case 5: // 1x4 + columns=1; + break; + case 6: // 4x1 + columns=opCount; + break; + } + char tempID[1024]; + if (ImGui::BeginTable("KGE93BSIEO3NOWBDJZBA",columns,ImGuiTableFlags_SizingStretchSame)) { + for (int i=0; ifm.op[(opCount==4 && ins->type!=DIV_INS_OPL_DRUMS)?opOrder[i]:i]; + if ((settings.fmLayout!=3 && ((i+1)&1)) || i==0 || settings.fmLayout==2) ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Separator(); + ImGui::PushID(fmt::sprintf("op%d",i).c_str()); + + // push colors + if (settings.separateFMColors) { + bool mod=true; + if (ins->type==DIV_INS_OPL_DRUMS) { + mod=false; + } else if (opCount==4) { + if (ins->type==DIV_INS_OPL) { + if (opIsOutputOPL[ins->fm.alg&3][i]) mod=false; + } else { + if (opIsOutput[ins->fm.alg&7][i]) mod=false; + } + } else { + if (i==1 || (ins->type==DIV_INS_OPL && (ins->fm.alg&1))) mod=false; + } + if (mod) { + pushAccentColors( + uiColors[GUI_COLOR_FM_PRIMARY_MOD], + uiColors[GUI_COLOR_FM_SECONDARY_MOD], + uiColors[GUI_COLOR_FM_BORDER_MOD], + uiColors[GUI_COLOR_FM_BORDER_SHADOW_MOD] + ); + } else { + pushAccentColors( + uiColors[GUI_COLOR_FM_PRIMARY_CAR], + uiColors[GUI_COLOR_FM_SECONDARY_CAR], + uiColors[GUI_COLOR_FM_BORDER_CAR], + uiColors[GUI_COLOR_FM_BORDER_SHADOW_CAR] + ); + } + } + + ImGui::Dummy(ImVec2(dpiScale,dpiScale)); + if (ins->type==DIV_INS_OPL_DRUMS) { + ImGui::Text("%s",oplDrumNames[i]); + } else if (ins->type==DIV_INS_OPL && ins->fm.opllPreset==16) { + if (i==1) { + ImGui::Text("Envelope 2 (kick only)"); + } else { + ImGui::Text("Envelope"); + } + } else { + ImGui::Text("OP%d",i+1); + } + + float sliderHeight=200.0f*dpiScale; + float waveWidth=140.0*dpiScale; + float waveHeight=sliderHeight-ImGui::GetFrameHeightWithSpacing()*5.5f; + + int maxTl=127; + if (ins->type==DIV_INS_OPLL) { + if (i==1) { + maxTl=15; + } else { + maxTl=63; + } + } + if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) { + maxTl=63; + } + int maxArDr=(ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ)?31:15; + + bool ssgOn=op.ssgEnv&8; + bool ksrOn=op.ksr; + bool vibOn=op.vib; + bool egtOn=op.egt; + bool susOn=op.sus; // don't you make fun of this one + unsigned char ssgEnv=op.ssgEnv&7; + + if (ImGui::BeginTable("opParams",ins->type==DIV_INS_OPLL?3:4,ImGuiTableFlags_BordersInnerV)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); + if (ins->type!=DIV_INS_OPLL) { + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed); + } + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch); + ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthFixed); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + float textY=ImGui::GetCursorPosY(); + CENTER_TEXT_20(FM_SHORT_NAME(FM_AR)); + ImGui::TextUnformatted(FM_SHORT_NAME(FM_AR)); + if (ins->type!=DIV_INS_OPLL) { + ImGui::TableNextColumn(); + if (ins->type==DIV_INS_FM) { + ImGui::Text("SSG-EG"); + } else { + ImGui::Text("Waveform"); + } + } + ImGui::TableNextColumn(); + ImGui::Text("Envelope"); + ImGui::TableNextColumn(); + CENTER_TEXT(FM_SHORT_NAME(FM_TL)); + ImGui::Text("TL"); + + // A/D/S/R + ImGui::TableNextColumn(); + + op.ar&=maxArDr; + P(CWVSliderScalar("##AR",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.ar,&maxArDr,&_ZERO)); + + ImGui::SameLine(); + op.dr&=maxArDr; + float textX_DR=ImGui::GetCursorPosX(); + P(CWVSliderScalar("##DR",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.dr,&maxArDr,&_ZERO)); + + float textX_SL=0.0f; + if (settings.susPosition==0) { + ImGui::SameLine(); + op.sl&=15; + textX_SL=ImGui::GetCursorPosX(); + P(CWVSliderScalar("##SL",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.sl,&_FIFTEEN,&_ZERO)); + } + + float textX_D2R=0.0f; + if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) { + ImGui::SameLine(); + op.d2r&=31; + textX_D2R=ImGui::GetCursorPosX(); + P(CWVSliderScalar("##D2R",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.d2r,&_THIRTY_ONE,&_ZERO)); + } + + ImGui::SameLine(); + op.rr&=15; + float textX_RR=ImGui::GetCursorPosX(); + P(CWVSliderScalar("##RR",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.rr,&_FIFTEEN,&_ZERO)); + + if (settings.susPosition==1) { + ImGui::SameLine(); + op.sl&=15; + textX_SL=ImGui::GetCursorPosX(); + P(CWVSliderScalar("##SL",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.sl,&_FIFTEEN,&_ZERO)); + } + + ImVec2 prevCurPos=ImGui::GetCursorPos(); + + // labels + ImGui::SetCursorPos(ImVec2(textX_DR,textY)); + CENTER_TEXT_20(FM_SHORT_NAME(FM_DR)); + ImGui::TextUnformatted(FM_SHORT_NAME(FM_DR)); + + ImGui::SetCursorPos(ImVec2(textX_SL,textY)); + CENTER_TEXT_20(FM_SHORT_NAME(FM_SL)); + ImGui::TextUnformatted(FM_SHORT_NAME(FM_SL)); + + ImGui::SetCursorPos(ImVec2(textX_RR,textY)); + CENTER_TEXT_20(FM_SHORT_NAME(FM_RR)); + ImGui::TextUnformatted(FM_SHORT_NAME(FM_RR)); + + if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) { + ImGui::SetCursorPos(ImVec2(textX_D2R,textY)); + CENTER_TEXT_20(FM_SHORT_NAME(FM_D2R)); + ImGui::TextUnformatted(FM_SHORT_NAME(FM_D2R)); + } + + ImGui::SetCursorPos(prevCurPos); + + if (ins->type!=DIV_INS_OPLL) { + ImGui::TableNextColumn(); + switch (ins->type) { + case DIV_INS_FM: { + // SSG + ImGui::BeginDisabled(!ssgOn); + drawSSGEnv(op.ssgEnv&7,ImVec2(waveWidth,waveHeight)); + ImGui::EndDisabled(); + if (ImGui::Checkbox("##SSGOn",&ssgOn)) { PARAMETER + op.ssgEnv=(op.ssgEnv&7)|(ssgOn<<3); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Only for OPN family chips"); + } + + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderScalar("##SSG",ImGuiDataType_U8,&ssgEnv,&_ZERO,&_SEVEN,ssgEnvTypes[ssgEnv])) { PARAMETER + op.ssgEnv=(op.ssgEnv&8)|(ssgEnv&7); + } + + // params + ImGui::Separator(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT)); + P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable + + int detune=(op.dt&7)-3; + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT)); + if (CWSliderInt("##DT",&detune,-3,4,tempID)) { PARAMETER + op.dt=detune+3; + } rightClickable + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT2)); + P(CWSliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE,tempID)); rightClickable + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Only on YM2151 (OPM)"); + } + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_RS)); + P(CWSliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE,tempID)); rightClickable + + break; + } + case DIV_INS_OPL: + // waveform + drawWaveform(op.ws&7,ins->type==DIV_INS_OPZ,ImVec2(waveWidth,waveHeight)); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + P(CWSliderScalar("##WS",ImGuiDataType_U8,&op.ws,&_ZERO,&_SEVEN,(ins->type==DIV_INS_OPZ)?opzWaveforms[op.ws&7]:(settings.oplStandardWaveNames?oplWaveformsStandard[op.ws&7]:oplWaveforms[op.ws&7]))); rightClickable + if ((ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) && ImGui::IsItemHovered()) { + ImGui::SetTooltip("OPL2/3 only (last 4 waveforms are OPL3 only)"); + } + + // params + ImGui::Separator(); + if (ImGui::BeginTable("FMParamsInner",2)) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + bool amOn=op.am; + if (ImGui::Checkbox(FM_NAME(FM_AM),&amOn)) { PARAMETER + op.am=amOn; + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox(FM_NAME(FM_KSR),&ksrOn)) { PARAMETER + op.ksr=ksrOn; + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + if (ImGui::Checkbox(FM_NAME(FM_VIB),&vibOn)) { PARAMETER + op.vib=vibOn; + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox(FM_NAME(FM_SUS),&susOn)) { PARAMETER + op.sus=susOn; + } + + ImGui::EndTable(); + } + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT)); + P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_KSL)); + P(CWSliderScalar("##KSL",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE,tempID)); rightClickable + + break; + case DIV_INS_OPZ: { + // waveform + drawWaveform(op.ws&7,ins->type==DIV_INS_OPZ,ImVec2(waveWidth,waveHeight)); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + P(CWSliderScalar("##WS",ImGuiDataType_U8,&op.ws,&_ZERO,&_SEVEN,(ins->type==DIV_INS_OPZ)?opzWaveforms[op.ws&7]:(settings.oplStandardWaveNames?oplWaveformsStandard[op.ws&7]:oplWaveforms[op.ws&7]))); rightClickable + if ((ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) && ImGui::IsItemHovered()) { + ImGui::SetTooltip("OPL2/3 only (last 4 waveforms are OPL3 only)"); + } + + // params + ImGui::Separator(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT)); + P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable + + int detune=(op.dt&7)-3; + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT)); + if (CWSliderInt("##DT",&detune,-3,4,tempID)) { PARAMETER + op.dt=detune+3; + } rightClickable + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT2)); + P(CWSliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE,tempID)); rightClickable + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Only on YM2151 (OPM)"); + } + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_RS)); + P(CWSliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE,tempID)); rightClickable + break; + } + default: + break; + } + } + + ImGui::TableNextColumn(); + float envHeight=sliderHeight-ImGui::GetStyle().ItemSpacing.y*2.0f; + if (ins->type==DIV_INS_OPZ) { + envHeight-=ImGui::GetFrameHeightWithSpacing()*2.0f; + } + drawFMEnv(op.tl&maxTl,op.ar&maxArDr,op.dr&maxArDr,(ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPLL)?((op.rr&15)*2):op.d2r&31,op.rr&15,op.sl&15,op.sus,op.ssgEnv&8,ins->fm.alg,maxTl,maxArDr,ImVec2(ImGui::GetContentRegionAvail().x,envHeight),ins->type); + + if (ins->type==DIV_INS_OPZ) { + ImGui::Separator(); + if (ImGui::BeginTable("FMParamsInnerOPZ",2)) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_FINE)); + P(CWSliderScalar("##FINE",ImGuiDataType_U8,&op.dvb,&_ZERO,&_FIFTEEN,tempID)); rightClickable + + ImGui::TableNextColumn(); + bool amOn=op.am; + if (ImGui::Checkbox(FM_NAME(FM_AM),&amOn)) { PARAMETER + op.am=amOn; + } + ImGui::SameLine(); + if (ImGui::Checkbox("Fixed",&egtOn)) { PARAMETER + op.egt=egtOn; + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_EGSHIFT)); + P(CWSliderScalar("##EGShift",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE,tempID)); rightClickable + + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_REV)); + P(CWSliderScalar("##REV",ImGuiDataType_U8,&op.dam,&_ZERO,&_SEVEN,tempID)); rightClickable + + ImGui::TableNextColumn(); + + + ImGui::EndTable(); + } + } + + ImGui::TableNextColumn(); + op.tl&=maxTl; + P(CWVSliderScalar("##TL",ImVec2(20.0f*dpiScale,sliderHeight-(ins->type==DIV_INS_FM?(ImGui::GetFrameHeightWithSpacing()+ImGui::CalcTextSize(FM_SHORT_NAME(FM_AM)).y+ImGui::GetStyle().ItemSpacing.y):0.0f)),ImGuiDataType_U8,&op.tl,&maxTl,&_ZERO)); + + if (ins->type==DIV_INS_FM) { + CENTER_TEXT(FM_SHORT_NAME(FM_AM)); + ImGui::TextUnformatted(FM_SHORT_NAME(FM_AM)); + bool amOn=op.am; + if (ImGui::Checkbox("##AM",&amOn)) { PARAMETER + op.am=amOn; + } + } + + ImGui::EndTable(); + } + + /* + ImGui::SameLine(); + + bool amOn=op.am; + if (ImGui::Checkbox(FM_NAME(FM_AM),&amOn)) { PARAMETER + op.am=amOn; + } + + if (ins->type!=DIV_INS_OPL && ins->type!=DIV_INS_OPL_DRUMS && ins->type!=DIV_INS_OPZ) { + ImGui::SameLine(); + if (ImGui::Checkbox((ins->type==DIV_INS_OPLL)?FM_NAME(FM_EGS):"SSG On",&ssgOn)) { PARAMETER + op.ssgEnv=(op.ssgEnv&7)|(ssgOn<<3); + } + if (ins->type==DIV_INS_FM) { + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Only for OPN family chips"); + } + } + } + + if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) { + ImGui::SameLine(); + if (ImGui::Checkbox(FM_NAME(FM_SUS),&susOn)) { PARAMETER + op.sus=susOn; + } + } + + //52.0 controls vert scaling; default 96 + drawFMEnv(op.tl&maxTl,op.ar&maxArDr,op.dr&maxArDr,(ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPLL)?((op.rr&15)*2):op.d2r&31,op.rr&15,op.sl&15,op.sus,op.ssgEnv&8,ins->fm.alg,maxTl,maxArDr,ImVec2(ImGui::GetContentRegionAvail().x,52.0*dpiScale),ins->type); + //P(CWSliderScalar(FM_NAME(FM_AR),ImGuiDataType_U8,&op.ar,&_ZERO,&_THIRTY_ONE)); rightClickable + if (ImGui::BeginTable("opParams",2,ImGuiTableFlags_SizingStretchProp)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthStretch,0.0); \ + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed,0.0); \ + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + op.ar&=maxArDr; + P(CWSliderScalar("##AR",ImGuiDataType_U8,&op.ar,&maxArDr,&_ZERO)); rightClickable + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_AR)); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + op.dr&=maxArDr; + P(CWSliderScalar("##DR",ImGuiDataType_U8,&op.dr,&maxArDr,&_ZERO)); rightClickable + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_DR)); + + if (settings.susPosition==0) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + P(CWSliderScalar("##SL",ImGuiDataType_U8,&op.sl,&_FIFTEEN,&_ZERO)); rightClickable + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_SL)); + } + + if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + P(CWSliderScalar("##D2R",ImGuiDataType_U8,&op.d2r,&_THIRTY_ONE,&_ZERO)); rightClickable + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_D2R)); + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + P(CWSliderScalar("##RR",ImGuiDataType_U8,&op.rr,&_FIFTEEN,&_ZERO)); rightClickable + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_RR)); + + if (settings.susPosition==1) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + P(CWSliderScalar("##SL",ImGuiDataType_U8,&op.sl,&_FIFTEEN,&_ZERO)); rightClickable + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_SL)); + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + op.tl&=maxTl; + P(CWSliderScalar("##TL",ImGuiDataType_U8,&op.tl,&maxTl,&_ZERO)); rightClickable + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_TL)); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Separator(); + ImGui::TableNextColumn(); + ImGui::Separator(); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) { + P(CWSliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE)); rightClickable + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_RS)); + } else { + P(CWSliderScalar("##KSL",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE)); rightClickable + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_KSL)); + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_MULT)); + + if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) { + int detune=(op.dt&7)-3; + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderInt("##DT",&detune,-3,4)) { PARAMETER + op.dt=detune+3; + } rightClickable + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_DT)); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + P(CWSliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE)); rightClickable + if (ImGui::IsItemHovered() && ins->type==DIV_INS_FM) { + ImGui::SetTooltip("Only on YM2151 (OPM)"); + } + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_DT2)); + + if (ins->type==DIV_INS_FM) { // OPN only + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderScalar("##SSG",ImGuiDataType_U8,&ssgEnv,&_ZERO,&_SEVEN,ssgEnvTypes[ssgEnv])) { PARAMETER + op.ssgEnv=(op.ssgEnv&8)|(ssgEnv&7); + } rightClickable + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_SSG)); + } + } + + if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPZ) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + + ImGui::TableNextColumn(); + ImGui::Text("%s",FM_NAME(FM_WS)); + } + + ImGui::EndTable(); + } + + if (ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) { + if (ImGui::Checkbox(FM_NAME(FM_VIB),&vibOn)) { PARAMETER + op.vib=vibOn; + } + ImGui::SameLine(); + if (ImGui::Checkbox(FM_NAME(FM_KSR),&ksrOn)) { PARAMETER + op.ksr=ksrOn; + } + } + */ + + if (settings.separateFMColors) { + popAccentColors(); + } + + ImGui::PopID(); + } + ImGui::EndTable(); + } + } else { // classic int columns=2; switch (settings.fmLayout) { case 1: // 2x2 diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index ea1d92748..da3b0f277 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -1117,6 +1117,15 @@ void FurnaceGUI::drawSettings() { 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)) { @@ -2077,7 +2086,7 @@ void FurnaceGUI::syncSettings() { clampSetting(settings.roundedMenus,0,1); clampSetting(settings.loadJapanese,0,1); clampSetting(settings.loadChinese,0,1); - clampSetting(settings.fmLayout,0,3); + clampSetting(settings.fmLayout,0,6); clampSetting(settings.susPosition,0,1); clampSetting(settings.effectCursorDir,0,2); clampSetting(settings.cursorPastePos,0,1); From bd7710991b58e72bd0c40d17d8a64bb2371b9891 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 13 Jun 2022 03:57:31 -0500 Subject: [PATCH 21/31] GUI: a bit more to it --- src/gui/insEdit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 81edbfe19..681ae10d4 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -2036,7 +2036,7 @@ void FurnaceGUI::drawInsEdit() { if (ImGui::BeginTable("KGE93BSIEO3NOWBDJZBA",columns,ImGuiTableFlags_SizingStretchSame)) { for (int i=0; ifm.op[(opCount==4 && ins->type!=DIV_INS_OPL_DRUMS)?opOrder[i]:i]; - if ((settings.fmLayout!=3 && ((i+1)&1)) || i==0 || settings.fmLayout==2) ImGui::TableNextRow(); + if ((settings.fmLayout!=6 && ((i+1)&1)) || i==0 || settings.fmLayout==5) ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Separator(); ImGui::PushID(fmt::sprintf("op%d",i).c_str()); From 327a013186358c17162863ecfaf66fc571bf828f Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 13 Jun 2022 23:22:17 -0500 Subject: [PATCH 22/31] GUI: finish alternate FM layout --- TODO.md | 2 +- src/gui/insEdit.cpp | 505 ++++++++++++++++++-------------------------- 2 files changed, 201 insertions(+), 306 deletions(-) diff --git a/TODO.md b/TODO.md index d667201ec..b0fc02d37 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,5 @@ # to-do for 0.6pre1 -- add another FM editor layout - add ability to move selection by dragging - implement Defle slide bug when using E1xy/E2xy and repeating origin note (requires format change) @@ -11,3 +10,4 @@ - songs made in older versions will go through old system name detection for compatibility - Game Boy envelope macro/sequence - volume commands should work on Game Boy +- ability to customize `OFF`, `===` and `REL` diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 681ae10d4..be09eb6d6 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -2033,12 +2033,13 @@ void FurnaceGUI::drawInsEdit() { break; } char tempID[1024]; - if (ImGui::BeginTable("KGE93BSIEO3NOWBDJZBA",columns,ImGuiTableFlags_SizingStretchSame)) { + ImVec2 oldPadding=ImGui::GetStyle().CellPadding; + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding,ImVec2(8.0f*dpiScale,4.0f*dpiScale)); + if (ImGui::BeginTable("KGE93BSIEO3NOWBDJZBA",columns,ImGuiTableFlags_SizingStretchSame|ImGuiTableFlags_BordersInner)) { for (int i=0; ifm.op[(opCount==4 && ins->type!=DIV_INS_OPL_DRUMS)?opOrder[i]:i]; if ((settings.fmLayout!=6 && ((i+1)&1)) || i==0 || settings.fmLayout==5) ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Separator(); ImGui::PushID(fmt::sprintf("op%d",i).c_str()); // push colors @@ -2074,20 +2075,22 @@ void FurnaceGUI::drawInsEdit() { ImGui::Dummy(ImVec2(dpiScale,dpiScale)); if (ins->type==DIV_INS_OPL_DRUMS) { - ImGui::Text("%s",oplDrumNames[i]); + snprintf(tempID,1024,"%s",oplDrumNames[i]); } else if (ins->type==DIV_INS_OPL && ins->fm.opllPreset==16) { if (i==1) { - ImGui::Text("Envelope 2 (kick only)"); + snprintf(tempID,1024,"Envelope 2 (kick only)"); } else { - ImGui::Text("Envelope"); + snprintf(tempID,1024,"Envelope"); } } else { - ImGui::Text("OP%d",i+1); + snprintf(tempID,1024,"Operator %d",i+1); } + CENTER_TEXT(tempID); + ImGui::TextUnformatted(tempID); float sliderHeight=200.0f*dpiScale; float waveWidth=140.0*dpiScale; - float waveHeight=sliderHeight-ImGui::GetFrameHeightWithSpacing()*5.5f; + float waveHeight=sliderHeight-ImGui::GetFrameHeightWithSpacing()*(ins->type==DIV_INS_OPLL?4.5f:5.5f); int maxTl=127; if (ins->type==DIV_INS_OPLL) { @@ -2106,14 +2109,13 @@ void FurnaceGUI::drawInsEdit() { bool ksrOn=op.ksr; bool vibOn=op.vib; bool egtOn=op.egt; - bool susOn=op.sus; // don't you make fun of this one + bool susOn=op.sus; // yawn unsigned char ssgEnv=op.ssgEnv&7; - if (ImGui::BeginTable("opParams",ins->type==DIV_INS_OPLL?3:4,ImGuiTableFlags_BordersInnerV)) { + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding,oldPadding); + if (ImGui::BeginTable("opParams",4,ImGuiTableFlags_BordersInnerV)) { ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed); - if (ins->type!=DIV_INS_OPLL) { - ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed); - } + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed,waveWidth); ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthFixed); @@ -2122,13 +2124,11 @@ void FurnaceGUI::drawInsEdit() { float textY=ImGui::GetCursorPosY(); CENTER_TEXT_20(FM_SHORT_NAME(FM_AR)); ImGui::TextUnformatted(FM_SHORT_NAME(FM_AR)); - if (ins->type!=DIV_INS_OPLL) { - ImGui::TableNextColumn(); - if (ins->type==DIV_INS_FM) { - ImGui::Text("SSG-EG"); - } else { - ImGui::Text("Waveform"); - } + ImGui::TableNextColumn(); + if (ins->type==DIV_INS_FM) { + ImGui::Text("SSG-EG"); + } else { + ImGui::Text("Waveform"); } ImGui::TableNextColumn(); ImGui::Text("Envelope"); @@ -2198,29 +2198,172 @@ void FurnaceGUI::drawInsEdit() { ImGui::SetCursorPos(prevCurPos); - if (ins->type!=DIV_INS_OPLL) { - ImGui::TableNextColumn(); - switch (ins->type) { - case DIV_INS_FM: { - // SSG - ImGui::BeginDisabled(!ssgOn); - drawSSGEnv(op.ssgEnv&7,ImVec2(waveWidth,waveHeight)); - ImGui::EndDisabled(); - if (ImGui::Checkbox("##SSGOn",&ssgOn)) { PARAMETER + ImGui::TableNextColumn(); + switch (ins->type) { + case DIV_INS_FM: { + // SSG + ImGui::BeginDisabled(!ssgOn); + drawSSGEnv(op.ssgEnv&7,ImVec2(waveWidth,waveHeight)); + ImGui::EndDisabled(); + if (ImGui::Checkbox("##SSGOn",&ssgOn)) { PARAMETER + op.ssgEnv=(op.ssgEnv&7)|(ssgOn<<3); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Only for OPN family chips"); + } + + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderScalar("##SSG",ImGuiDataType_U8,&ssgEnv,&_ZERO,&_SEVEN,ssgEnvTypes[ssgEnv])) { PARAMETER + op.ssgEnv=(op.ssgEnv&8)|(ssgEnv&7); + } + + // params + ImGui::Separator(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT)); + P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable + + int detune=(op.dt&7)-3; + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT)); + if (CWSliderInt("##DT",&detune,-3,4,tempID)) { PARAMETER + op.dt=detune+3; + } rightClickable + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT2)); + P(CWSliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE,tempID)); rightClickable + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Only on YM2151 (OPM)"); + } + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_RS)); + P(CWSliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE,tempID)); rightClickable + + break; + } + case DIV_INS_OPLL: + // waveform + drawWaveform(i==0?(ins->fm.ams&1):(ins->fm.fms&1),ins->type==DIV_INS_OPZ,ImVec2(waveWidth,waveHeight)); + + // params + ImGui::Separator(); + if (ImGui::BeginTable("FMParamsInner",2)) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + bool amOn=op.am; + if (ImGui::Checkbox(FM_NAME(FM_AM),&amOn)) { PARAMETER + op.am=amOn; + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox(FM_NAME(FM_KSR),&ksrOn)) { PARAMETER + op.ksr=ksrOn; + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + if (ImGui::Checkbox(FM_NAME(FM_VIB),&vibOn)) { PARAMETER + op.vib=vibOn; + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox(FM_NAME(FM_EGS),&ssgOn)) { PARAMETER op.ssgEnv=(op.ssgEnv&7)|(ssgOn<<3); } - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Only for OPN family chips"); + + ImGui::EndTable(); + } + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT)); + P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_KSL)); + P(CWSliderScalar("##KSL",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE,tempID)); rightClickable + + break; + case DIV_INS_OPL: + // waveform + drawWaveform(op.ws&7,ins->type==DIV_INS_OPZ,ImVec2(waveWidth,waveHeight)); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + P(CWSliderScalar("##WS",ImGuiDataType_U8,&op.ws,&_ZERO,&_SEVEN,(ins->type==DIV_INS_OPZ)?opzWaveforms[op.ws&7]:(settings.oplStandardWaveNames?oplWaveformsStandard[op.ws&7]:oplWaveforms[op.ws&7]))); rightClickable + if ((ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) && ImGui::IsItemHovered()) { + ImGui::SetTooltip("OPL2/3 only (last 4 waveforms are OPL3 only)"); + } + + // params + ImGui::Separator(); + if (ImGui::BeginTable("FMParamsInner",2)) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + bool amOn=op.am; + if (ImGui::Checkbox(FM_NAME(FM_AM),&amOn)) { PARAMETER + op.am=amOn; + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox(FM_NAME(FM_KSR),&ksrOn)) { PARAMETER + op.ksr=ksrOn; } - ImGui::SameLine(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderScalar("##SSG",ImGuiDataType_U8,&ssgEnv,&_ZERO,&_SEVEN,ssgEnvTypes[ssgEnv])) { PARAMETER - op.ssgEnv=(op.ssgEnv&8)|(ssgEnv&7); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + if (ImGui::Checkbox(FM_NAME(FM_VIB),&vibOn)) { PARAMETER + op.vib=vibOn; + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox(FM_NAME(FM_SUS),&susOn)) { PARAMETER + op.sus=susOn; } - // params - ImGui::Separator(); + ImGui::EndTable(); + } + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT)); + P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_KSL)); + P(CWSliderScalar("##KSL",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE,tempID)); rightClickable + + break; + case DIV_INS_OPZ: { + // waveform + drawWaveform(op.ws&7,ins->type==DIV_INS_OPZ,ImVec2(waveWidth,waveHeight)); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + P(CWSliderScalar("##WS",ImGuiDataType_U8,&op.ws,&_ZERO,&_SEVEN,(ins->type==DIV_INS_OPZ)?opzWaveforms[op.ws&7]:(settings.oplStandardWaveNames?oplWaveformsStandard[op.ws&7]:oplWaveforms[op.ws&7]))); rightClickable + if ((ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) && ImGui::IsItemHovered()) { + ImGui::SetTooltip("OPL2/3 only (last 4 waveforms are OPL3 only)"); + } + + // params + ImGui::Separator(); + if (egtOn) { + int block=op.dt; + int freqNum=(op.mult<<4)|(op.dvb&15); + ImGui::Text("Block"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImVec2 cursorAlign=ImGui::GetCursorPos(); + if (ImGui::InputInt("##Block",&block,1,1)) { + if (block<0) block=0; + if (block>7) block=7; + op.dt=block; + } + + ImGui::Text("Freq"); + ImGui::SameLine(); + ImGui::SetCursorPos(ImVec2(cursorAlign.x,ImGui::GetCursorPosY())); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::InputInt("##FreqNum",&freqNum,1,16)) { + if (freqNum<0) freqNum=0; + if (freqNum>255) freqNum=255; + op.mult=freqNum>>4; + op.dvb=freqNum&15; + } + } else { ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT)); P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable @@ -2231,106 +2374,26 @@ void FurnaceGUI::drawInsEdit() { if (CWSliderInt("##DT",&detune,-3,4,tempID)) { PARAMETER op.dt=detune+3; } rightClickable - - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT2)); - P(CWSliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE,tempID)); rightClickable - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Only on YM2151 (OPM)"); - } - - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_RS)); - P(CWSliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE,tempID)); rightClickable - - break; } - case DIV_INS_OPL: - // waveform - drawWaveform(op.ws&7,ins->type==DIV_INS_OPZ,ImVec2(waveWidth,waveHeight)); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(CWSliderScalar("##WS",ImGuiDataType_U8,&op.ws,&_ZERO,&_SEVEN,(ins->type==DIV_INS_OPZ)?opzWaveforms[op.ws&7]:(settings.oplStandardWaveNames?oplWaveformsStandard[op.ws&7]:oplWaveforms[op.ws&7]))); rightClickable - if ((ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) && ImGui::IsItemHovered()) { - ImGui::SetTooltip("OPL2/3 only (last 4 waveforms are OPL3 only)"); - } - // params - ImGui::Separator(); - if (ImGui::BeginTable("FMParamsInner",2)) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - bool amOn=op.am; - if (ImGui::Checkbox(FM_NAME(FM_AM),&amOn)) { PARAMETER - op.am=amOn; - } - ImGui::TableNextColumn(); - if (ImGui::Checkbox(FM_NAME(FM_KSR),&ksrOn)) { PARAMETER - op.ksr=ksrOn; - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - if (ImGui::Checkbox(FM_NAME(FM_VIB),&vibOn)) { PARAMETER - op.vib=vibOn; - } - ImGui::TableNextColumn(); - if (ImGui::Checkbox(FM_NAME(FM_SUS),&susOn)) { PARAMETER - op.sus=susOn; - } - - ImGui::EndTable(); - } - - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT)); - P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable - - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_KSL)); - P(CWSliderScalar("##KSL",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE,tempID)); rightClickable - - break; - case DIV_INS_OPZ: { - // waveform - drawWaveform(op.ws&7,ins->type==DIV_INS_OPZ,ImVec2(waveWidth,waveHeight)); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(CWSliderScalar("##WS",ImGuiDataType_U8,&op.ws,&_ZERO,&_SEVEN,(ins->type==DIV_INS_OPZ)?opzWaveforms[op.ws&7]:(settings.oplStandardWaveNames?oplWaveformsStandard[op.ws&7]:oplWaveforms[op.ws&7]))); rightClickable - if ((ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) && ImGui::IsItemHovered()) { - ImGui::SetTooltip("OPL2/3 only (last 4 waveforms are OPL3 only)"); - } - - // params - ImGui::Separator(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_MULT)); - P(CWSliderScalar("##MULT",ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN,tempID)); rightClickable - - int detune=(op.dt&7)-3; - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT)); - if (CWSliderInt("##DT",&detune,-3,4,tempID)) { PARAMETER - op.dt=detune+3; - } rightClickable - - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT2)); - P(CWSliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE,tempID)); rightClickable - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Only on YM2151 (OPM)"); - } - - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_RS)); - P(CWSliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE,tempID)); rightClickable - break; + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT2)); + P(CWSliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE,tempID)); rightClickable + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Only on YM2151 (OPM)"); } - default: - break; + + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_RS)); + P(CWSliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE,tempID)); rightClickable + break; } + default: + break; } ImGui::TableNextColumn(); - float envHeight=sliderHeight-ImGui::GetStyle().ItemSpacing.y*2.0f; + float envHeight=sliderHeight;//-ImGui::GetStyle().ItemSpacing.y*2.0f; if (ins->type==DIV_INS_OPZ) { envHeight-=ImGui::GetFrameHeightWithSpacing()*2.0f; } @@ -2341,9 +2404,11 @@ void FurnaceGUI::drawInsEdit() { if (ImGui::BeginTable("FMParamsInnerOPZ",2)) { ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_FINE)); - P(CWSliderScalar("##FINE",ImGuiDataType_U8,&op.dvb,&_ZERO,&_FIFTEEN,tempID)); rightClickable + if (!egtOn) { + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_FINE)); + P(CWSliderScalar("##FINE",ImGuiDataType_U8,&op.dvb,&_ZERO,&_FIFTEEN,tempID)); rightClickable + } ImGui::TableNextColumn(); bool amOn=op.am; @@ -2375,7 +2440,7 @@ void FurnaceGUI::drawInsEdit() { ImGui::TableNextColumn(); op.tl&=maxTl; - P(CWVSliderScalar("##TL",ImVec2(20.0f*dpiScale,sliderHeight-(ins->type==DIV_INS_FM?(ImGui::GetFrameHeightWithSpacing()+ImGui::CalcTextSize(FM_SHORT_NAME(FM_AM)).y+ImGui::GetStyle().ItemSpacing.y):0.0f)),ImGuiDataType_U8,&op.tl,&maxTl,&_ZERO)); + P(CWVSliderScalar("##TL",ImVec2(ImGui::GetFrameHeight(),sliderHeight-(ins->type==DIV_INS_FM?(ImGui::GetFrameHeightWithSpacing()+ImGui::CalcTextSize(FM_SHORT_NAME(FM_AM)).y+ImGui::GetStyle().ItemSpacing.y):0.0f)),ImGuiDataType_U8,&op.tl,&maxTl,&_ZERO)); if (ins->type==DIV_INS_FM) { CENTER_TEXT(FM_SHORT_NAME(FM_AM)); @@ -2388,178 +2453,7 @@ void FurnaceGUI::drawInsEdit() { ImGui::EndTable(); } - - /* - ImGui::SameLine(); - - bool amOn=op.am; - if (ImGui::Checkbox(FM_NAME(FM_AM),&amOn)) { PARAMETER - op.am=amOn; - } - - if (ins->type!=DIV_INS_OPL && ins->type!=DIV_INS_OPL_DRUMS && ins->type!=DIV_INS_OPZ) { - ImGui::SameLine(); - if (ImGui::Checkbox((ins->type==DIV_INS_OPLL)?FM_NAME(FM_EGS):"SSG On",&ssgOn)) { PARAMETER - op.ssgEnv=(op.ssgEnv&7)|(ssgOn<<3); - } - if (ins->type==DIV_INS_FM) { - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Only for OPN family chips"); - } - } - } - - if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) { - ImGui::SameLine(); - if (ImGui::Checkbox(FM_NAME(FM_SUS),&susOn)) { PARAMETER - op.sus=susOn; - } - } - - //52.0 controls vert scaling; default 96 - drawFMEnv(op.tl&maxTl,op.ar&maxArDr,op.dr&maxArDr,(ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPLL)?((op.rr&15)*2):op.d2r&31,op.rr&15,op.sl&15,op.sus,op.ssgEnv&8,ins->fm.alg,maxTl,maxArDr,ImVec2(ImGui::GetContentRegionAvail().x,52.0*dpiScale),ins->type); - //P(CWSliderScalar(FM_NAME(FM_AR),ImGuiDataType_U8,&op.ar,&_ZERO,&_THIRTY_ONE)); rightClickable - if (ImGui::BeginTable("opParams",2,ImGuiTableFlags_SizingStretchProp)) { - ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthStretch,0.0); \ - ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed,0.0); \ - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - op.ar&=maxArDr; - P(CWSliderScalar("##AR",ImGuiDataType_U8,&op.ar,&maxArDr,&_ZERO)); rightClickable - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_AR)); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - op.dr&=maxArDr; - P(CWSliderScalar("##DR",ImGuiDataType_U8,&op.dr,&maxArDr,&_ZERO)); rightClickable - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_DR)); - - if (settings.susPosition==0) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(CWSliderScalar("##SL",ImGuiDataType_U8,&op.sl,&_FIFTEEN,&_ZERO)); rightClickable - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_SL)); - } - - if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(CWSliderScalar("##D2R",ImGuiDataType_U8,&op.d2r,&_THIRTY_ONE,&_ZERO)); rightClickable - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_D2R)); - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(CWSliderScalar("##RR",ImGuiDataType_U8,&op.rr,&_FIFTEEN,&_ZERO)); rightClickable - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_RR)); - - if (settings.susPosition==1) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(CWSliderScalar("##SL",ImGuiDataType_U8,&op.sl,&_FIFTEEN,&_ZERO)); rightClickable - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_SL)); - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - op.tl&=maxTl; - P(CWSliderScalar("##TL",ImGuiDataType_U8,&op.tl,&maxTl,&_ZERO)); rightClickable - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_TL)); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Separator(); - ImGui::TableNextColumn(); - ImGui::Separator(); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) { - P(CWSliderScalar("##RS",ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE)); rightClickable - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_RS)); - } else { - P(CWSliderScalar("##KSL",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE)); rightClickable - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_KSL)); - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_MULT)); - - if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) { - int detune=(op.dt&7)-3; - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##DT",&detune,-3,4)) { PARAMETER - op.dt=detune+3; - } rightClickable - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_DT)); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - P(CWSliderScalar("##DT2",ImGuiDataType_U8,&op.dt2,&_ZERO,&_THREE)); rightClickable - if (ImGui::IsItemHovered() && ins->type==DIV_INS_FM) { - ImGui::SetTooltip("Only on YM2151 (OPM)"); - } - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_DT2)); - - if (ins->type==DIV_INS_FM) { // OPN only - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderScalar("##SSG",ImGuiDataType_U8,&ssgEnv,&_ZERO,&_SEVEN,ssgEnvTypes[ssgEnv])) { PARAMETER - op.ssgEnv=(op.ssgEnv&8)|(ssgEnv&7); - } rightClickable - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_SSG)); - } - } - - if (ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS || ins->type==DIV_INS_OPZ) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - - ImGui::TableNextColumn(); - ImGui::Text("%s",FM_NAME(FM_WS)); - } - - ImGui::EndTable(); - } - - if (ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPL_DRUMS) { - if (ImGui::Checkbox(FM_NAME(FM_VIB),&vibOn)) { PARAMETER - op.vib=vibOn; - } - ImGui::SameLine(); - if (ImGui::Checkbox(FM_NAME(FM_KSR),&ksrOn)) { PARAMETER - op.ksr=ksrOn; - } - } - */ + ImGui::PopStyleVar(); if (settings.separateFMColors) { popAccentColors(); @@ -2569,6 +2463,7 @@ void FurnaceGUI::drawInsEdit() { } ImGui::EndTable(); } + ImGui::PopStyleVar(); } else { // classic int columns=2; switch (settings.fmLayout) { From 500e73b2a8e3cd91b70673b34305e0c42f4359b8 Mon Sep 17 00:00:00 2001 From: LoKiToon <98922449+LoKiToon@users.noreply.github.com> Date: Tue, 14 Jun 2022 11:58:43 +0300 Subject: [PATCH 23/31] Add files via upload --- demos/FDS TEST.fur | Bin 1574 -> 1587 bytes demos/Fake Gameboy.fur | Bin 0 -> 1255 bytes demos/c64 ring test.fur | Bin 0 -> 961 bytes demos/game boy thing.fur | Bin 0 -> 1204 bytes demos/thick bass test.fur | Bin 0 -> 17608 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 demos/Fake Gameboy.fur create mode 100644 demos/c64 ring test.fur create mode 100644 demos/game boy thing.fur create mode 100644 demos/thick bass test.fur diff --git a/demos/FDS TEST.fur b/demos/FDS TEST.fur index 54b6d3b40607fd0367a5de8f511989df758bb900..54bdd36cd1ff9a0592b9072fff0960ea4336ce18 100644 GIT binary patch literal 1587 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 YJxxZG{!Y`=WEZ8s)AUsNUy`BxAD+J{f&c&j diff --git a/demos/Fake Gameboy.fur b/demos/Fake Gameboy.fur new file mode 100644 index 0000000000000000000000000000000000000000..50d7e36d90ecb33bde6b355e27588de842d1de79 GIT binary patch literal 1255 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 literal 0 HcmV?d00001 diff --git a/demos/thick bass test.fur b/demos/thick bass test.fur new file mode 100644 index 0000000000000000000000000000000000000000..13268e48bccb66cf5215b095a12af357a1f7361f GIT binary patch literal 17608 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%0Ad+f=45MvJpCdz5>I_YD8gu=$~%eP@a8V)qG! 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 Date: Tue, 14 Jun 2022 04:41:31 -0500 Subject: [PATCH 24/31] GUI: slight visualizer tweaks --- src/engine/engine.h | 3 ++- src/engine/playback.cpp | 4 +++ src/gui/gui.h | 2 ++ src/gui/pattern.cpp | 55 ++++++++++++++++++++++++++++++++++++++--- 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/engine/engine.h b/src/engine/engine.h index dc16584de..1fa88a915 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -83,7 +83,7 @@ struct DivChannelState { int note, oldNote, lastIns, pitch, portaSpeed, portaNote; int volume, volSpeed, cut, rowDelay, volMax; int delayOrder, delayRow, retrigSpeed, retrigTick; - int vibratoDepth, vibratoRate, vibratoPos, vibratoDir, vibratoFine; + int vibratoDepth, vibratoRate, vibratoPos, vibratoPosGiant, vibratoDir, vibratoFine; int tremoloDepth, tremoloRate, tremoloPos; unsigned char arp, arpStage, arpTicks, panL, panR; bool doNote, legato, portaStop, keyOn, keyOff, nowYouCanStop, stopOnOff; @@ -112,6 +112,7 @@ struct DivChannelState { vibratoDepth(0), vibratoRate(0), vibratoPos(0), + vibratoPosGiant(0), vibratoDir(0), vibratoFine(15), tremoloDepth(0), diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index ed70da94b..f8cb79ac0 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -988,6 +988,10 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) { if (chan[i].vibratoDepth>0) { chan[i].vibratoPos+=chan[i].vibratoRate; if (chan[i].vibratoPos>=64) chan[i].vibratoPos-=64; + + chan[i].vibratoPosGiant+=chan[i].vibratoRate; + if (chan[i].vibratoPos>=512) chan[i].vibratoPos-=512; + switch (chan[i].vibratoDir) { case 1: // up dispatchCmd(DivCommand(DIV_CMD_PITCH,i,chan[i].pitch+(MAX(0,(chan[i].vibratoDepth*vibTable[chan[i].vibratoPos]*chan[i].vibratoFine)>>4)/15))); diff --git a/src/gui/gui.h b/src/gui/gui.h index 55ea989c8..e5ad4a943 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1539,6 +1539,8 @@ class FurnaceGUI { void addScroll(int amount); void setFileName(String name); void runBackupThread(); + void pushPartBlend(); + void popPartBlend(); int processEvent(SDL_Event* ev); bool loop(); bool finish(); diff --git a/src/gui/pattern.cpp b/src/gui/pattern.cpp index fa00243c3..1d220795a 100644 --- a/src/gui/pattern.cpp +++ b/src/gui/pattern.cpp @@ -17,6 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include +#include #include #define _USE_MATH_DEFINES #include "gui.h" @@ -31,6 +33,30 @@ inline float randRange(float min, float max) { return min+((float)rand()/(float)RAND_MAX)*(max-min); } +void _pushPartBlend(const ImDrawList* drawList, const ImDrawCmd* cmd) { + if (cmd!=NULL) { + if (cmd->UserCallbackData!=NULL) { + ((FurnaceGUI*)cmd->UserCallbackData)->pushPartBlend(); + } + } +} + +void _popPartBlend(const ImDrawList* drawList, const ImDrawCmd* cmd) { + if (cmd!=NULL) { + if (cmd->UserCallbackData!=NULL) { + ((FurnaceGUI*)cmd->UserCallbackData)->popPartBlend(); + } + } +} + +void FurnaceGUI::pushPartBlend() { + SDL_SetRenderDrawBlendMode(sdlRend,SDL_BLENDMODE_ADD); +} + +void FurnaceGUI::popPartBlend() { + SDL_SetRenderDrawBlendMode(sdlRend,SDL_BLENDMODE_BLEND); +} + // draw a pattern row inline void FurnaceGUI::patternRow(int i, bool isPlaying, float lineHeight, int chans, int ord, const DivPattern** patCache, bool inhibitSel) { static char id[32]; @@ -692,11 +718,14 @@ void FurnaceGUI::drawPattern() { ImU32* color=noteGrad; switch (i.cmd) { - case DIV_CMD_NOTE_ON: + case DIV_CMD_NOTE_ON: { + float strength=CLAMP(i.value,0,119); partIcon=ICON_FA_ASTERISK; - life=96.0f; + life=80.0f+((i.value==DIV_NOTE_NULL)?0.0f:(strength*0.3f)); lifeSpeed=3.0f; + num=6+(strength/16); break; + } case DIV_CMD_LEGATO: partIcon=ICON_FA_COG; color=insGrad; @@ -794,7 +823,7 @@ void FurnaceGUI::drawPattern() { float frameTime=ImGui::GetIO().DeltaTime*60.0f; - // note slides + // note slides and vibrato ImVec2 arrowPoints[7]; if (e->isPlaying()) for (int i=0; icurSubSong->chanShow[i]) continue; @@ -849,11 +878,30 @@ void FurnaceGUI::drawPattern() { } } } + if (ch->vibratoDepth>0) { + ImVec4 col=uiColors[GUI_COLOR_PATTERN_EFFECT_PITCH]; + col.w*=0.2; + float width=patChanX[i+1]-patChanX[i]; + + particles.push_back(Particle( + pitchGrad, + ICON_FA_GLASS, + off.x+patChanX[i]+(width*0.5+0.5*sin(M_PI*(float)ch->vibratoPosGiant/64.0f)*width)-scrollX, + off.y+(ImGui::GetWindowHeight()*0.5f)+randRange(0,patFont->FontSize), + randRange(-4.0f,4.0f), + 2.0f*(3.0f+(rand()%5)+ch->vibratoRate), + 0.4f, + 1.0f, + 128.0f, + 4.0f + )); + } } // particle simulation ImDrawList* fdl=ImGui::GetForegroundDrawList(); if (!particles.empty()) WAKE_UP; + fdl->AddCallback(_pushPartBlend,this); for (size_t i=0; iAddCallback(_popPartBlend,this); } ImGui::PopStyleColor(3); From cc06f36c92b8535c93a72e58bc3adc048a94b146 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 14 Jun 2022 14:08:28 -0500 Subject: [PATCH 25/31] GUI: fix dumb header insertion --- src/gui/pattern.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/gui/pattern.cpp b/src/gui/pattern.cpp index 1d220795a..b7940a9e8 100644 --- a/src/gui/pattern.cpp +++ b/src/gui/pattern.cpp @@ -17,9 +17,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include -#include -#include #define _USE_MATH_DEFINES #include "gui.h" #include "../ta-log.h" From dc9f1112d15f45168a388de6bae475dab9060aa6 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 14 Jun 2022 23:00:20 -0500 Subject: [PATCH 26/31] MSM6258: fix rate being twice #541 --- src/engine/platform/msm6258.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/platform/msm6258.cpp b/src/engine/platform/msm6258.cpp index db1848cfa..731bf8f28 100644 --- a/src/engine/platform/msm6258.cpp +++ b/src/engine/platform/msm6258.cpp @@ -380,7 +380,7 @@ void DivPlatformMSM6258::setFlags(unsigned int flags) { chipClock=4000000; break; } - rate=chipClock/128; + rate=chipClock/256; for (int i=0; i<1; i++) { oscBuf[i]->rate=rate; } From 64f534328924013a93bda360bc0682315546b023 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 15 Jun 2022 02:03:20 -0500 Subject: [PATCH 27/31] I give up trying to fix this file dialog for now --- extern/igfd/ImGuiFileDialog.cpp | 10 ++++++---- src/gui/gui.cpp | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/extern/igfd/ImGuiFileDialog.cpp b/extern/igfd/ImGuiFileDialog.cpp index f7a2be5b1..776ad3738 100644 --- a/extern/igfd/ImGuiFileDialog.cpp +++ b/extern/igfd/ImGuiFileDialog.cpp @@ -1287,8 +1287,6 @@ namespace IGFD std::sort(prFileList.begin(), prFileList.end(), [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool { - if (a==NULL || b==NULL) - return false; if (!a.use_count() || !b.use_count()) return false; @@ -1760,7 +1758,7 @@ namespace IGFD struct stat statInfos = {}; char timebuf[100]; int result = stat(fpn.c_str(), &statInfos); - if (!result) + if (result!=-1) { if (vInfos->fileType != 'd') { @@ -1781,7 +1779,11 @@ namespace IGFD { vInfos->fileModifDate = std::string(timebuf, len); } - } + } else { + vInfos->fileSize=0; + vInfos->formatedFileSize = prFormatFileSize(vInfos->fileSize); + vInfos->fileModifDate="???"; + } } } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index b982987c3..fd904649c 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4105,6 +4105,7 @@ bool FurnaceGUI::init() { #ifndef __APPLE__ if (settings.dpiScale<0.5f) { + // TODO: replace with a function to actually detect the display scaling factor as it's unreliable. SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(sdlWin),&dpiScaleF,NULL,NULL); dpiScale=round(dpiScaleF/96.0f); if (dpiScale<1) dpiScale=1; From 491109e765812e725995087d2b3e606f0f35a8c9 Mon Sep 17 00:00:00 2001 From: LoKiToon <98922449+LoKiToon@users.noreply.github.com> Date: Wed, 15 Jun 2022 23:38:18 +0300 Subject: [PATCH 28/31] Add files via upload --- demos/Fusion.fur | Bin 0 -> 1881 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 demos/Fusion.fur diff --git a/demos/Fusion.fur b/demos/Fusion.fur new file mode 100644 index 0000000000000000000000000000000000000000..a69f26e815e1ada047d94f642a76a8c0e204c657 GIT binary patch literal 1881 zcmZ8ec{tPwA7_wZS|mq~oDE@wMJzJ8k}G9%6;?!M3a^gO+Pe~$0x^ZDK-v3zDTbWB4M;1~~|dK?oj(({hG+ z70g6e0Uoni0X!0f_{ig?!?)hS=M6AkPlCb$LC%gjdsDD8VjKh1@jc1H2!@09%?0pr zN7|wx#{1C74XwG}@y^s)9%_d`2TdEF>PztlXZq?lWTT@Qk1jATu8h2V99XPqCUvCY zucJmy5&1is zzMTak@|(UTEoN=N*LRnVIsjkeXBSQHVnq7y)uYrVnzwQrE=*4IJB-+d?Tj*PKQ}hw zBtndHgOStPE6=YklpEVcd5&qU2)DUXr~cG8JH1~)UHW;}d|(zu?5t#2U12FyNfJ@HqatHN;C7T`weY8dVm^cZRT$2YWr6~ zku}W4#AIP^W~Pv|DNN0ARLShPrW(faXnv&LqbX=wdm&fBz@C`1+w}VX+AiaARiKoq zl`JcAC=GZ%(io8LO@^zEX!HNL9jQBGu;hVf6<)b*CS!Tk=|gdXPf5fN`6X;`Upnby zrrlw5u52EatWhu{ef0`!3N4m*iuH7%-fkxZi*{nbaZfj84AHLLNT+!?&LMky= z30`a}^zebPNwLA99}W7ZCz}lsm>(adyv)&^C;KAA;sPGVx+DpGPJV?ItEb&`PS>4p z)71eZ#INAhU?;jvHz>W?P1SoDEK0}4F4aCjZJ<&7L*24YbKjndKo*Q!mGrBW!zeN| zZ_7!)h{6d=Lt71hhcAmozp*An0!s8)NQ=4+Are85w&p;8m0d+Hhu&ZRLecCfJX4*r zVeRdBwT z!fBe;&o#SaY9wh9h$V+_>ANe^%AhTF z?2C}>Od-S&%}_tA*|kxSxy00wNRsgqtC4#7oE` Date: Thu, 16 Jun 2022 01:26:19 -0500 Subject: [PATCH 29/31] GUI: prepare for replace undo --- src/gui/editing.cpp | 8 +++++++- src/gui/findReplace.cpp | 10 ++++++++++ src/gui/gui.h | 3 ++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/gui/editing.cpp b/src/gui/editing.cpp index ea12eb591..f299b1af2 100644 --- a/src/gui/editing.cpp +++ b/src/gui/editing.cpp @@ -66,6 +66,8 @@ void FurnaceGUI::prepareUndo(ActionType action) { e->curPat[i].getPattern(e->curOrders->ord[i][curOrder],false)->copyOn(oldPat[i]); } break; + case GUI_UNDO_REPLACE: // this is handled by doReplace() + break; } } @@ -86,7 +88,7 @@ void FurnaceGUI::makeUndo(ActionType action) { if (oldOrders.ord[i][j]!=e->curOrders->ord[i][j]) { s.ord.push_back(UndoOrderData(subSong,i,j,oldOrders.ord[i][j],e->curOrders->ord[i][j])); } - } + }SATGDIOPTASDIOKP;ASDTG } s.oldOrdersLen=oldOrdersLen; s.newOrdersLen=e->curSubSong->ordersLen; @@ -126,6 +128,8 @@ void FurnaceGUI::makeUndo(ActionType action) { doPush=true; } break; + case GUI_UNDO_REPLACE: // this is handled by doReplace() + break; } if (doPush) { MARK_MODIFIED; @@ -943,6 +947,7 @@ void FurnaceGUI::doUndo() { case GUI_UNDO_PATTERN_FLIP: case GUI_UNDO_PATTERN_COLLAPSE: case GUI_UNDO_PATTERN_EXPAND: + case GUI_UNDO_REPLACE: for (UndoPatternData& i: us.pat) { e->changeSongP(i.subSong); DivPattern* p=e->curPat[i.chan].getPattern(i.pat,true); @@ -991,6 +996,7 @@ void FurnaceGUI::doRedo() { case GUI_UNDO_PATTERN_FLIP: case GUI_UNDO_PATTERN_COLLAPSE: case GUI_UNDO_PATTERN_EXPAND: + case GUI_UNDO_REPLACE: for (UndoPatternData& i: us.pat) { e->changeSongP(i.subSong); DivPattern* p=e->curPat[i.chan].getPattern(i.pat,true); diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index d5548c0fb..5dae95bc5 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -189,6 +189,12 @@ void FurnaceGUI::doFind() { queryViewingResults=true; } +/* issues with the find and replace function: + - doesn't mark the module as modified + - can't undo + - replace notes to anything starting from C-0 to lower notes will have an octave higher, so set it to replace to C-0 it will becom C-1, b_1 will become B-0 and so on +*/ + void FurnaceGUI::doReplace() { doFind(); queryViewingResults=false; @@ -399,6 +405,10 @@ void FurnaceGUI::doReplace() { for (int i=0; i Date: Thu, 16 Jun 2022 02:09:57 -0500 Subject: [PATCH 30/31] fix build --- src/gui/editing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/editing.cpp b/src/gui/editing.cpp index f299b1af2..8b30d2514 100644 --- a/src/gui/editing.cpp +++ b/src/gui/editing.cpp @@ -88,7 +88,7 @@ void FurnaceGUI::makeUndo(ActionType action) { if (oldOrders.ord[i][j]!=e->curOrders->ord[i][j]) { s.ord.push_back(UndoOrderData(subSong,i,j,oldOrders.ord[i][j],e->curOrders->ord[i][j])); } - }SATGDIOPTASDIOKP;ASDTG + } } s.oldOrdersLen=oldOrdersLen; s.newOrdersLen=e->curSubSong->ordersLen; From c44ca95b92277578661f9d317b4ae80f4fc9bf07 Mon Sep 17 00:00:00 2001 From: Natt Akuma Date: Fri, 17 Jun 2022 03:06:07 +0700 Subject: [PATCH 31/31] Make volume command handling consistent For WonderSwan and VIC-20 --- src/engine/platform/swan.cpp | 2 +- src/engine/platform/vic20.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/platform/swan.cpp b/src/engine/platform/swan.cpp index 73dc79281..905fa82a5 100644 --- a/src/engine/platform/swan.cpp +++ b/src/engine/platform/swan.cpp @@ -347,7 +347,7 @@ int DivPlatformSwan::dispatch(DivCommand c) { case DIV_CMD_VOLUME: if (chan[c.chan].vol!=c.value) { chan[c.chan].vol=c.value; - if (!chan[c.chan].std.vol.had) { + if (!chan[c.chan].std.vol.has) { calcAndWriteOutVol(c.chan,15); } } diff --git a/src/engine/platform/vic20.cpp b/src/engine/platform/vic20.cpp index a766ba443..8475b0e53 100644 --- a/src/engine/platform/vic20.cpp +++ b/src/engine/platform/vic20.cpp @@ -195,7 +195,7 @@ int DivPlatformVIC20::dispatch(DivCommand c) { case DIV_CMD_VOLUME: if (chan[c.chan].vol!=c.value) { chan[c.chan].vol=c.value; - if (!chan[c.chan].std.vol.had) { + if (!chan[c.chan].std.vol.has) { calcAndWriteOutVol(c.chan,15); } }