Merge branch 'master' of https://github.com/tildearrow/furnace into sample_macro
This commit is contained in:
commit
e00758d67c
54 changed files with 1068 additions and 219 deletions
|
|
@ -23,16 +23,17 @@
|
|||
|
||||
const char* aboutLine[]={
|
||||
"tildearrow",
|
||||
"is proud to present",
|
||||
"is not so happy to present",
|
||||
"",
|
||||
("Furnace " DIV_VERSION),
|
||||
"",
|
||||
"the biggest multi-system chiptune tracker!",
|
||||
"featuring DefleMask song compatibility.",
|
||||
"",
|
||||
"zero disassembly.",
|
||||
"just clean-room design,",
|
||||
"time and dedication.",
|
||||
"what a mess of a versioning scheme we have...",
|
||||
"I mean it! these pre-releases are like normal releases",
|
||||
"by now but only because I promised you to have SNES in",
|
||||
"0.6pre2 I am doing this whole mess...",
|
||||
"",
|
||||
"> CREDITS <",
|
||||
"",
|
||||
|
|
|
|||
|
|
@ -63,12 +63,45 @@ float FurnaceGUI::computeGradPos(int type, int chan) {
|
|||
return chanOscBright[chan];
|
||||
break;
|
||||
case GUI_OSCREF_NOTE_TRIGGER:
|
||||
return keyHit[chan]*5.0f;
|
||||
return keyHit1[chan];
|
||||
break;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void FurnaceGUI::calcChanOsc() {
|
||||
std::vector<DivDispatchOscBuffer*> oscBufs;
|
||||
std::vector<ChanOscStatus*> oscFFTs;
|
||||
std::vector<int> oscChans;
|
||||
|
||||
int chans=e->getTotalChannelCount();
|
||||
|
||||
for (int i=0; i<chans; i++) {
|
||||
DivDispatchOscBuffer* buf=e->getOscBuffer(i);
|
||||
if (buf!=NULL && e->curSubSong->chanShow[i]) {
|
||||
// 30ms should be enough
|
||||
int displaySize=(float)(buf->rate)*0.03f;
|
||||
if (e->isRunning()) {
|
||||
float minLevel=1.0f;
|
||||
float maxLevel=-1.0f;
|
||||
unsigned short needlePos=buf->needle;
|
||||
needlePos-=displaySize;
|
||||
for (unsigned short i=0; i<512; i++) {
|
||||
float y=(float)buf->data[(unsigned short)(needlePos+(i*displaySize/512))]/65536.0f;
|
||||
if (minLevel>y) minLevel=y;
|
||||
if (maxLevel<y) maxLevel=y;
|
||||
}
|
||||
float estimate=pow(maxLevel-minLevel,0.5f);
|
||||
if (estimate>1.0f) estimate=1.0f;
|
||||
chanOscVol[i]=MAX(chanOscVol[i]*0.87f,estimate);
|
||||
}
|
||||
} else {
|
||||
chanOscVol[i]=MAX(chanOscVol[i]*0.87f,0.0f);
|
||||
}
|
||||
if (chanOscVol[i]<0.00001f) chanOscVol[i]=0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void FurnaceGUI::drawChanOsc() {
|
||||
if (nextWindow==GUI_WINDOW_CHAN_OSC) {
|
||||
chanOscOpen=true;
|
||||
|
|
@ -361,7 +394,6 @@ void FurnaceGUI::drawChanOsc() {
|
|||
if (maxLevel<y) maxLevel=y;
|
||||
}
|
||||
dcOff=(minLevel+maxLevel)*0.5f;
|
||||
chanOscVol[ch]=MAX(chanOscVol[ch]*0.87f,maxLevel-minLevel);
|
||||
for (unsigned short i=0; i<512; i++) {
|
||||
float x=(float)i/512.0f;
|
||||
float y=(float)buf->data[(unsigned short)(needlePos+(i*displaySize/512))]/65536.0f;
|
||||
|
|
|
|||
|
|
@ -645,6 +645,7 @@ void FurnaceGUI::doAction(int what) {
|
|||
} else {
|
||||
wantScrollList=true;
|
||||
MARK_MODIFIED;
|
||||
RESET_WAVE_MACRO_ZOOM;
|
||||
}
|
||||
break;
|
||||
case GUI_ACTION_WAVE_LIST_DUPLICATE:
|
||||
|
|
@ -657,6 +658,7 @@ void FurnaceGUI::doAction(int what) {
|
|||
(*e->song.wave[curWave])=(*e->song.wave[prevWave]);
|
||||
wantScrollList=true;
|
||||
MARK_MODIFIED;
|
||||
RESET_WAVE_MACRO_ZOOM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -1329,6 +1331,7 @@ void FurnaceGUI::doAction(int what) {
|
|||
}
|
||||
nextWindow=GUI_WINDOW_WAVE_EDIT;
|
||||
MARK_MODIFIED;
|
||||
RESET_WAVE_MACRO_ZOOM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -405,7 +405,7 @@ void FurnaceGUI::doCopy(bool cut) {
|
|||
}
|
||||
}
|
||||
|
||||
void FurnaceGUI::doPaste(PasteMode mode) {
|
||||
void FurnaceGUI::doPaste(PasteMode mode, int arg) {
|
||||
finishSelection();
|
||||
prepareUndo(GUI_UNDO_PATTERN_PASTE);
|
||||
char* clipText=SDL_GetClipboardText();
|
||||
|
|
@ -481,14 +481,16 @@ void FurnaceGUI::doPaste(PasteMode mode) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_MIX_FG) && strcmp(note,"...")==0) {
|
||||
if ((mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_MIX_FG ||
|
||||
mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) && strcmp(note,"...")==0) {
|
||||
// do nothing.
|
||||
} else {
|
||||
if (mode!=GUI_PASTE_MODE_MIX_BG || (pat->data[j][0]==0 && pat->data[j][1]==0)) {
|
||||
if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || (pat->data[j][0]==0 && pat->data[j][1]==0)) {
|
||||
if (!decodeNote(note,pat->data[j][0],pat->data[j][1])) {
|
||||
invalidData=true;
|
||||
break;
|
||||
}
|
||||
if (mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) pat->data[j][2]=arg;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -505,7 +507,7 @@ void FurnaceGUI::doPaste(PasteMode mode) {
|
|||
note[2]=0;
|
||||
|
||||
if (iFine==1) {
|
||||
if (!opMaskPaste.ins) {
|
||||
if (!opMaskPaste.ins || mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG) {
|
||||
iFine++;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -527,7 +529,8 @@ void FurnaceGUI::doPaste(PasteMode mode) {
|
|||
}
|
||||
|
||||
if (strcmp(note,"..")==0) {
|
||||
if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_MIX_FG)) {
|
||||
if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_MIX_FG ||
|
||||
mode==GUI_PASTE_MODE_INS_BG || mode==GUI_PASTE_MODE_INS_FG)) {
|
||||
pat->data[j][iFine+1]=-1;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -536,7 +539,7 @@ void FurnaceGUI::doPaste(PasteMode mode) {
|
|||
invalidData=true;
|
||||
break;
|
||||
}
|
||||
if (mode!=GUI_PASTE_MODE_MIX_BG || pat->data[j][iFine+1]==-1) {
|
||||
if (!(mode==GUI_PASTE_MODE_MIX_BG || mode==GUI_PASTE_MODE_INS_BG) || pat->data[j][iFine+1]==-1) {
|
||||
if (iFine<(3+e->curPat[iCoarse].effectCols*2)) pat->data[j][iFine+1]=val;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
225
src/gui/gui.cpp
225
src/gui/gui.cpp
|
|
@ -584,13 +584,117 @@ void FurnaceGUI::updateWindowTitle() {
|
|||
if (sdlWin!=NULL) SDL_SetWindowTitle(sdlWin,title.c_str());
|
||||
}
|
||||
|
||||
void FurnaceGUI::autoDetectSystem() {
|
||||
std::map<DivSystem,int> sysCountMap;
|
||||
for (int i=0; i<e->song.systemLen; i++) {
|
||||
try {
|
||||
sysCountMap.at(e->song.system[i])++;
|
||||
} catch (std::exception& ex) {
|
||||
sysCountMap[e->song.system[i]]=1;
|
||||
}
|
||||
}
|
||||
|
||||
logV("sysCountMap:");
|
||||
for (std::pair<DivSystem,int> k: sysCountMap) {
|
||||
logV("%s: %d",e->getSystemName(k.first),k.second);
|
||||
}
|
||||
|
||||
bool isMatch=false;
|
||||
std::map<DivSystem,int> defCountMap;
|
||||
for (FurnaceGUISysCategory& i: sysCategories) {
|
||||
for (FurnaceGUISysDef& j: i.systems) {
|
||||
defCountMap.clear();
|
||||
for (size_t k=0; k<j.definition.size(); k+=4) {
|
||||
if (j.definition[k]==0) break;
|
||||
try {
|
||||
defCountMap.at((DivSystem)j.definition[k])++;
|
||||
} catch (std::exception& ex) {
|
||||
defCountMap[(DivSystem)j.definition[k]]=1;
|
||||
}
|
||||
}
|
||||
if (defCountMap.size()!=sysCountMap.size()) continue;
|
||||
isMatch=true;
|
||||
logV("trying on defCountMap: %s",j.name);
|
||||
for (std::pair<DivSystem,int> k: defCountMap) {
|
||||
logV("- %s: %d",e->getSystemName(k.first),k.second);
|
||||
}
|
||||
for (std::pair<DivSystem,int> k: defCountMap) {
|
||||
try {
|
||||
if (sysCountMap.at(k.first)!=k.second) {
|
||||
isMatch=false;
|
||||
break;
|
||||
}
|
||||
} catch (std::exception& ex) {
|
||||
isMatch=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isMatch) {
|
||||
logV("match found!");
|
||||
e->song.systemName=j.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isMatch) break;
|
||||
}
|
||||
|
||||
if (!isMatch) {
|
||||
bool isFirst=true;
|
||||
e->song.systemName="";
|
||||
for (std::pair<DivSystem,int> k: sysCountMap) {
|
||||
if (!isFirst) e->song.systemName+=" + ";
|
||||
if (k.second>1) {
|
||||
e->song.systemName+=fmt::sprintf("%d×",k.second);
|
||||
}
|
||||
if (k.first==DIV_SYSTEM_N163) {
|
||||
e->song.systemName+=settings.c163Name;
|
||||
} else {
|
||||
e->song.systemName+=e->getSystemName(k.first);
|
||||
}
|
||||
isFirst=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImVec4 FurnaceGUI::channelColor(int ch) {
|
||||
switch (settings.channelColors) {
|
||||
case 0:
|
||||
return uiColors[GUI_COLOR_CHANNEL_BG];
|
||||
break;
|
||||
case 1:
|
||||
return uiColors[GUI_COLOR_CHANNEL_FM+e->getChannelType(ch)];
|
||||
break;
|
||||
case 2:
|
||||
return uiColors[GUI_COLOR_INSTR_STD+e->getPreferInsType(ch)];
|
||||
break;
|
||||
}
|
||||
// invalid
|
||||
return uiColors[GUI_COLOR_TEXT];
|
||||
}
|
||||
|
||||
ImVec4 FurnaceGUI::channelTextColor(int ch) {
|
||||
switch (settings.channelTextColors) {
|
||||
case 0:
|
||||
return uiColors[GUI_COLOR_CHANNEL_FG];
|
||||
break;
|
||||
case 1:
|
||||
return uiColors[GUI_COLOR_CHANNEL_FM+e->getChannelType(ch)];
|
||||
break;
|
||||
case 2:
|
||||
return uiColors[GUI_COLOR_INSTR_STD+e->getPreferInsType(ch)];
|
||||
break;
|
||||
}
|
||||
// invalid
|
||||
return uiColors[GUI_COLOR_TEXT];
|
||||
}
|
||||
|
||||
const char* defaultLayout="[Window][DockSpaceViewport_11111111]\n\
|
||||
Pos=0,24\n\
|
||||
Size=1280,731\n\
|
||||
Size=1280,776\n\
|
||||
Collapsed=0\n\
|
||||
\n\
|
||||
[Window][Debug##Default]\n\
|
||||
Pos=54,0\n\
|
||||
Pos=54,19\n\
|
||||
Size=400,400\n\
|
||||
Collapsed=0\n\
|
||||
\n\
|
||||
|
|
@ -601,9 +705,9 @@ Collapsed=0\n\
|
|||
\n\
|
||||
[Window][Song Information]\n\
|
||||
Pos=978,24\n\
|
||||
Size=302,217\n\
|
||||
Size=302,179\n\
|
||||
Collapsed=0\n\
|
||||
DockId=0x00000004,0\n\
|
||||
DockId=0x0000000F,0\n\
|
||||
\n\
|
||||
[Window][Orders]\n\
|
||||
Pos=0,24\n\
|
||||
|
|
@ -615,7 +719,7 @@ DockId=0x00000007,0\n\
|
|||
Pos=653,24\n\
|
||||
Size=323,217\n\
|
||||
Collapsed=0\n\
|
||||
DockId=0x00000006,2\n\
|
||||
DockId=0x00000006,0\n\
|
||||
\n\
|
||||
[Window][Wavetables]\n\
|
||||
Pos=653,24\n\
|
||||
|
|
@ -627,13 +731,13 @@ DockId=0x00000006,1\n\
|
|||
Pos=653,24\n\
|
||||
Size=323,217\n\
|
||||
Collapsed=0\n\
|
||||
DockId=0x00000006,0\n\
|
||||
DockId=0x00000006,2\n\
|
||||
\n\
|
||||
[Window][Pattern]\n\
|
||||
Pos=0,243\n\
|
||||
Size=1246,512\n\
|
||||
Size=1246,557\n\
|
||||
Collapsed=0\n\
|
||||
DockId=0x0000000B,0\n\
|
||||
DockId=0x00000013,0\n\
|
||||
\n\
|
||||
[Window][Instrument Editor]\n\
|
||||
Pos=372,102\n\
|
||||
|
|
@ -642,7 +746,7 @@ Collapsed=0\n\
|
|||
\n\
|
||||
[Window][Warning]\n\
|
||||
Pos=481,338\n\
|
||||
Size=346,71\n\
|
||||
Size=264,86\n\
|
||||
Collapsed=0\n\
|
||||
\n\
|
||||
[Window][Sample Editor]\n\
|
||||
|
|
@ -675,8 +779,8 @@ Size=514,71\n\
|
|||
Collapsed=0\n\
|
||||
\n\
|
||||
[Window][Mixer]\n\
|
||||
Pos=63,55\n\
|
||||
Size=450,215\n\
|
||||
Pos=429,198\n\
|
||||
Size=453,355\n\
|
||||
Collapsed=0\n\
|
||||
\n\
|
||||
[Window][Oscilloscope]\n\
|
||||
|
|
@ -687,7 +791,7 @@ DockId=0x0000000E,0\n\
|
|||
\n\
|
||||
[Window][Volume Meter]\n\
|
||||
Pos=1248,243\n\
|
||||
Size=32,512\n\
|
||||
Size=32,557\n\
|
||||
Collapsed=0\n\
|
||||
DockId=0x0000000C,0\n\
|
||||
\n\
|
||||
|
|
@ -762,9 +866,10 @@ Size=368,449\n\
|
|||
Collapsed=0\n\
|
||||
\n\
|
||||
[Window][Register View]\n\
|
||||
Pos=847,180\n\
|
||||
Size=417,393\n\
|
||||
Pos=829,243\n\
|
||||
Size=417,557\n\
|
||||
Collapsed=0\n\
|
||||
DockId=0x00000014,0\n\
|
||||
\n\
|
||||
[Window][New Song]\n\
|
||||
Pos=267,110\n\
|
||||
|
|
@ -783,8 +888,40 @@ Size=304,40\n\
|
|||
Collapsed=0\n\
|
||||
DockId=0x0000000A,0\n\
|
||||
\n\
|
||||
[Window][Subsongs]\n\
|
||||
Pos=978,205\n\
|
||||
Size=302,36\n\
|
||||
Collapsed=0\n\
|
||||
DockId=0x00000010,0\n\
|
||||
\n\
|
||||
[Window][Oscilloscope (per-channel)]\n\
|
||||
Pos=1095,243\n\
|
||||
Size=151,557\n\
|
||||
Collapsed=0\n\
|
||||
DockId=0x00000012,0\n\
|
||||
\n\
|
||||
[Window][Piano]\n\
|
||||
Pos=177,669\n\
|
||||
Size=922,118\n\
|
||||
Collapsed=0\n\
|
||||
\n\
|
||||
[Window][Log Viewer]\n\
|
||||
Pos=60,60\n\
|
||||
Size=541,637\n\
|
||||
Collapsed=0\n\
|
||||
\n\
|
||||
[Window][Pattern Manager]\n\
|
||||
Pos=60,60\n\
|
||||
Size=1099,366\n\
|
||||
Collapsed=0\n\
|
||||
\n\
|
||||
[Window][Chip Manager]\n\
|
||||
Pos=60,60\n\
|
||||
Size=490,407\n\
|
||||
Collapsed=0\n\
|
||||
\n\
|
||||
[Docking][Data]\n\
|
||||
DockSpace ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,24 Size=1280,731 Split=Y Selected=0x6C01C512\n\
|
||||
DockSpace ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,24 Size=1280,776 Split=Y Selected=0x6C01C512\n\
|
||||
DockNode ID=0x00000001 Parent=0x8B93E3BD SizeRef=1280,217 Split=X Selected=0xF3094A52\n\
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=976,231 Split=X Selected=0x65CC51DC\n\
|
||||
DockNode ID=0x00000007 Parent=0x00000003 SizeRef=345,231 HiddenTabBar=1 Selected=0x8F5BFC9A\n\
|
||||
|
|
@ -795,10 +932,17 @@ DockSpace ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,24 Size=1280,731 Spl
|
|||
DockNode ID=0x0000000E Parent=0x00000009 SizeRef=292,105 HiddenTabBar=1 Selected=0x6D682373\n\
|
||||
DockNode ID=0x0000000A Parent=0x00000005 SizeRef=292,40 HiddenTabBar=1 Selected=0x0DE44CFF\n\
|
||||
DockNode ID=0x00000006 Parent=0x00000008 SizeRef=323,406 Selected=0xD2AD486B\n\
|
||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=302,231 Selected=0x60B9D088\n\
|
||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=302,231 Split=Y Selected=0x60B9D088\n\
|
||||
DockNode ID=0x0000000F Parent=0x00000004 SizeRef=302,179 Selected=0x60B9D088\n\
|
||||
DockNode ID=0x00000010 Parent=0x00000004 SizeRef=302,36 HiddenTabBar=1 Selected=0x723A6369\n\
|
||||
DockNode ID=0x00000002 Parent=0x8B93E3BD SizeRef=1280,512 Split=X Selected=0x6C01C512\n\
|
||||
DockNode ID=0x0000000B Parent=0x00000002 SizeRef=1246,503 CentralNode=1 HiddenTabBar=1 Selected=0xB9ADD0D5\n\
|
||||
DockNode ID=0x0000000C Parent=0x00000002 SizeRef=32,503 HiddenTabBar=1 Selected=0x644DA2C1\n\n";
|
||||
DockNode ID=0x0000000B Parent=0x00000002 SizeRef=1246,503 Split=X Selected=0xB9ADD0D5\n\
|
||||
DockNode ID=0x00000011 Parent=0x0000000B SizeRef=1093,557 Split=X Selected=0xB9ADD0D5\n\
|
||||
DockNode ID=0x00000013 Parent=0x00000011 SizeRef=827,557 CentralNode=1 HiddenTabBar=1 Selected=0xB9ADD0D5\n\
|
||||
DockNode ID=0x00000014 Parent=0x00000011 SizeRef=417,557 Selected=0x425428FB\n\
|
||||
DockNode ID=0x00000012 Parent=0x0000000B SizeRef=151,557 HiddenTabBar=1 Selected=0x4C07BC58\n\
|
||||
DockNode ID=0x0000000C Parent=0x00000002 SizeRef=32,503 HiddenTabBar=1 Selected=0x644DA2C1\n";
|
||||
|
||||
|
||||
void FurnaceGUI::prepareLayout() {
|
||||
FILE* check;
|
||||
|
|
@ -2076,6 +2220,30 @@ void FurnaceGUI::editOptions(bool topMenu) {
|
|||
if (ImGui::BeginMenu("paste special...")) {
|
||||
if (ImGui::MenuItem("paste mix",BIND_FOR(GUI_ACTION_PAT_PASTE_MIX))) doPaste(GUI_PASTE_MODE_MIX_FG);
|
||||
if (ImGui::MenuItem("paste mix (background)",BIND_FOR(GUI_ACTION_PAT_PASTE_MIX_BG))) doPaste(GUI_PASTE_MODE_MIX_BG);
|
||||
if (ImGui::BeginMenu("paste with ins (foreground)")) {
|
||||
if (e->song.ins.empty()) {
|
||||
ImGui::Text("no instruments available");
|
||||
}
|
||||
for (size_t i=0; i<e->song.ins.size(); i++) {
|
||||
snprintf(id,4095,"%.2X: %s",(int)i,e->song.ins[i]->name.c_str());
|
||||
if (ImGui::MenuItem(id)) {
|
||||
doPaste(GUI_PASTE_MODE_INS_FG,i);
|
||||
}
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("paste with ins (background)")) {
|
||||
if (e->song.ins.empty()) {
|
||||
ImGui::Text("no instruments available");
|
||||
}
|
||||
for (size_t i=0; i<e->song.ins.size(); i++) {
|
||||
snprintf(id,4095,"%.2X: %s",(int)i,e->song.ins[i]->name.c_str());
|
||||
if (ImGui::MenuItem(id)) {
|
||||
doPaste(GUI_PASTE_MODE_INS_BG,i);
|
||||
}
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::MenuItem("paste flood",BIND_FOR(GUI_ACTION_PAT_PASTE_FLOOD))) doPaste(GUI_PASTE_MODE_FLOOD);
|
||||
if (ImGui::MenuItem("paste overflow",BIND_FOR(GUI_ACTION_PAT_PASTE_OVERFLOW))) doPaste(GUI_PASTE_MODE_OVERFLOW);
|
||||
ImGui::EndMenu();
|
||||
|
|
@ -3230,6 +3398,9 @@ bool FurnaceGUI::loop() {
|
|||
showError("cannot add chip! ("+e->getLastError()+")");
|
||||
}
|
||||
ImGui::CloseCurrentPopup();
|
||||
if (e->song.autoSystem) {
|
||||
autoDetectSystem();
|
||||
}
|
||||
updateWindowTitle();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
|
|
@ -3250,6 +3421,9 @@ bool FurnaceGUI::loop() {
|
|||
DivSystem picked=systemPicker();
|
||||
if (picked!=DIV_SYSTEM_NULL) {
|
||||
e->changeSystem(i,picked,preserveChanPos);
|
||||
if (e->song.autoSystem) {
|
||||
autoDetectSystem();
|
||||
}
|
||||
updateWindowTitle();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
|
@ -3265,6 +3439,10 @@ bool FurnaceGUI::loop() {
|
|||
if (!e->removeSystem(i,preserveChanPos)) {
|
||||
showError("cannot remove chip! ("+e->getLastError()+")");
|
||||
}
|
||||
if (e->song.autoSystem) {
|
||||
autoDetectSystem();
|
||||
updateWindowTitle();
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
|
|
@ -3439,6 +3617,8 @@ bool FurnaceGUI::loop() {
|
|||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
|
||||
calcChanOsc();
|
||||
|
||||
if (mobileUI) {
|
||||
globalWinFlags=ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoBringToFrontOnFocus;
|
||||
//globalWinFlags=ImGuiWindowFlags_NoTitleBar;
|
||||
|
|
@ -3884,6 +4064,7 @@ bool FurnaceGUI::loop() {
|
|||
showError("cannot load wavetable! ("+e->getLastError()+")");
|
||||
} else {
|
||||
MARK_MODIFIED;
|
||||
RESET_WAVE_MACRO_ZOOM;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -4380,6 +4561,10 @@ bool FurnaceGUI::loop() {
|
|||
case GUI_WARN_SYSTEM_DEL:
|
||||
if (ImGui::Button("Yes")) {
|
||||
e->removeSystem(sysToDelete,preserveChanPos);
|
||||
if (e->song.autoSystem) {
|
||||
autoDetectSystem();
|
||||
updateWindowTitle();
|
||||
}
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
|
@ -5034,6 +5219,7 @@ FurnaceGUI::FurnaceGUI():
|
|||
macroPointSize(16),
|
||||
waveEditStyle(0),
|
||||
mobileMenuPos(0.0f),
|
||||
autoButtonSize(0.0f),
|
||||
curSysSection(NULL),
|
||||
pendingRawSampleDepth(8),
|
||||
pendingRawSampleChannels(1),
|
||||
|
|
@ -5421,6 +5607,9 @@ FurnaceGUI::FurnaceGUI():
|
|||
waveGenFMCon2[0]=true;
|
||||
waveGenFMCon3[0]=true;
|
||||
|
||||
memset(keyHit,0,sizeof(float)*DIV_MAX_CHANS);
|
||||
memset(keyHit1,0,sizeof(float)*DIV_MAX_CHANS);
|
||||
|
||||
memset(pianoKeyHit,0,sizeof(float)*180);
|
||||
memset(pianoKeyPressed,0,sizeof(bool)*180);
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@
|
|||
#define MARK_MODIFIED modified=true;
|
||||
#define WAKE_UP drawHalt=16;
|
||||
|
||||
#define RESET_WAVE_MACRO_ZOOM \
|
||||
for (DivInstrument* _wi: e->song.ins) { \
|
||||
_wi->std.waveMacro.vZoom=-1; \
|
||||
_wi->std.waveMacro.vScroll=-1; \
|
||||
}
|
||||
|
||||
#define BIND_FOR(x) getKeyName(actionKeys[x],true).c_str()
|
||||
|
||||
// TODO:
|
||||
|
|
@ -163,6 +169,8 @@ enum FurnaceGUIColors {
|
|||
GUI_COLOR_INSTR_RF5C68,
|
||||
GUI_COLOR_INSTR_UNKNOWN,
|
||||
|
||||
GUI_COLOR_CHANNEL_BG,
|
||||
GUI_COLOR_CHANNEL_FG,
|
||||
GUI_COLOR_CHANNEL_FM,
|
||||
GUI_COLOR_CHANNEL_PULSE,
|
||||
GUI_COLOR_CHANNEL_NOISE,
|
||||
|
|
@ -596,7 +604,9 @@ enum PasteMode {
|
|||
GUI_PASTE_MODE_MIX_FG,
|
||||
GUI_PASTE_MODE_MIX_BG,
|
||||
GUI_PASTE_MODE_FLOOD,
|
||||
GUI_PASTE_MODE_OVERFLOW
|
||||
GUI_PASTE_MODE_OVERFLOW,
|
||||
GUI_PASTE_MODE_INS_FG,
|
||||
GUI_PASTE_MODE_INS_BG
|
||||
};
|
||||
|
||||
#define FURKMOD_CTRL (1U<<31)
|
||||
|
|
@ -1018,7 +1028,7 @@ class FurnaceGUI {
|
|||
int drawHalt;
|
||||
int macroPointSize;
|
||||
int waveEditStyle;
|
||||
float mobileMenuPos;
|
||||
float mobileMenuPos, autoButtonSize;
|
||||
const int* curSysSection;
|
||||
|
||||
String pendingRawSample;
|
||||
|
|
@ -1178,6 +1188,8 @@ class FurnaceGUI {
|
|||
int channelStyle;
|
||||
int channelVolStyle;
|
||||
int channelFeedbackStyle;
|
||||
int channelFont;
|
||||
int channelTextCenter;
|
||||
int maxRecentFile;
|
||||
unsigned int maxUndoSteps;
|
||||
String mainFontPath;
|
||||
|
|
@ -1296,9 +1308,11 @@ class FurnaceGUI {
|
|||
saveUnusedPatterns(0),
|
||||
channelColors(1),
|
||||
channelTextColors(0),
|
||||
channelStyle(0),
|
||||
channelStyle(1),
|
||||
channelVolStyle(0),
|
||||
channelFeedbackStyle(1),
|
||||
channelFont(1),
|
||||
channelTextCenter(1),
|
||||
maxRecentFile(10),
|
||||
maxUndoSteps(100),
|
||||
mainFontPath(""),
|
||||
|
|
@ -1556,6 +1570,7 @@ class FurnaceGUI {
|
|||
|
||||
// visualizer
|
||||
float keyHit[DIV_MAX_CHANS];
|
||||
float keyHit1[DIV_MAX_CHANS];
|
||||
int lastIns[DIV_MAX_CHANS];
|
||||
|
||||
// log window
|
||||
|
|
@ -1596,6 +1611,7 @@ class FurnaceGUI {
|
|||
void drawFMEnv(unsigned char tl, unsigned char ar, unsigned char dr, unsigned char d2r, unsigned char rr, unsigned char sl, unsigned char sus, unsigned char egt, unsigned char algOrGlobalSus, float maxTl, float maxArDr, const ImVec2& size, unsigned short instType);
|
||||
void drawGBEnv(unsigned char vol, unsigned char len, unsigned char sLen, bool dir, const ImVec2& size);
|
||||
void drawSysConf(int chan, DivSystem type, unsigned int& flags, bool modifyOnChange);
|
||||
void kvsConfig(DivInstrument* ins);
|
||||
|
||||
// these ones offer ctrl-wheel fine value changes.
|
||||
bool CWSliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format=NULL, ImGuiSliderFlags flags=0);
|
||||
|
|
@ -1605,9 +1621,13 @@ class FurnaceGUI {
|
|||
bool CWVSliderInt(const char* label, const ImVec2& size, int* v, int v_min, int v_max, const char* format="%d", ImGuiSliderFlags flags=0);
|
||||
|
||||
void updateWindowTitle();
|
||||
void autoDetectSystem();
|
||||
void prepareLayout();
|
||||
ImVec4 channelColor(int ch);
|
||||
ImVec4 channelTextColor(int ch);
|
||||
|
||||
void readOsc();
|
||||
void calcChanOsc();
|
||||
|
||||
void pushAccentColors(const ImVec4& one, const ImVec4& two, const ImVec4& border, const ImVec4& borderShadow);
|
||||
void popAccentColors();
|
||||
|
|
@ -1699,7 +1719,7 @@ class FurnaceGUI {
|
|||
void doInsert();
|
||||
void doTranspose(int amount, OperationMask& mask);
|
||||
void doCopy(bool cut);
|
||||
void doPaste(PasteMode mode=GUI_PASTE_MODE_NORMAL);
|
||||
void doPaste(PasteMode mode=GUI_PASTE_MODE_NORMAL, int arg=0);
|
||||
void doChangeIns(int ins);
|
||||
void doInterpolate();
|
||||
void doFade(int p0, int p1, bool mode);
|
||||
|
|
|
|||
|
|
@ -796,6 +796,8 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={
|
|||
D(GUI_COLOR_INSTR_RF5C68,"",ImVec4(1.0f,0.5f,0.5f,1.0f)),
|
||||
D(GUI_COLOR_INSTR_UNKNOWN,"",ImVec4(0.3f,0.3f,0.3f,1.0f)),
|
||||
|
||||
D(GUI_COLOR_CHANNEL_BG,"",ImVec4(0.4f,0.6f,0.8f,1.0f)),
|
||||
D(GUI_COLOR_CHANNEL_FG,"",ImVec4(1.0f,1.0f,1.0f,1.0f)),
|
||||
D(GUI_COLOR_CHANNEL_FM,"",ImVec4(0.2f,0.8f,1.0f,1.0f)),
|
||||
D(GUI_COLOR_CHANNEL_PULSE,"",ImVec4(0.4f,1.0f,0.2f,1.0f)),
|
||||
D(GUI_COLOR_CHANNEL_NOISE,"",ImVec4(0.8f,0.8f,0.8f,1.0f)),
|
||||
|
|
|
|||
|
|
@ -1211,6 +1211,46 @@ inline bool enBit30(const int val) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
void FurnaceGUI::kvsConfig(DivInstrument* ins) {
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("(click to configure KVS)");
|
||||
}
|
||||
int opCount=4;
|
||||
if (ins->type==DIV_INS_OPLL) opCount=2;
|
||||
if (ins->type==DIV_INS_OPL) opCount=(ins->fm.ops==4)?4:2;
|
||||
if (ImGui::BeginPopupContextItem("IKVSOpt",ImGuiPopupFlags_MouseButtonLeft)) {
|
||||
ImGui::Text("operator level changes with volume?");
|
||||
if (ImGui::BeginTable("KVSTable",4,ImGuiTableFlags_BordersInner)) {
|
||||
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch);
|
||||
for (int i=0; i<4; i++) {
|
||||
int o=(opCount==4)?orderedOps[i]:i;
|
||||
if (!(i&1)) ImGui::TableNextRow();
|
||||
const char* label="AUTO##OPKVS";
|
||||
if (ins->fm.op[o].kvs==0) {
|
||||
label="NO##OPKVS";
|
||||
} else if (ins->fm.op[o].kvs==1) {
|
||||
label="YES##OPKVS";
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d",i+1);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushID(o);
|
||||
if (ImGui::Button(label,ImVec2(ImGui::GetContentRegionAvail().x,0.0f))) {
|
||||
if (++ins->fm.op[o].kvs>2) ins->fm.op[o].kvs=0;
|
||||
PARAMETER;
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void FurnaceGUI::drawMacros(std::vector<FurnaceGUIMacroDesc>& macros) {
|
||||
float asFloat[256];
|
||||
int asInt[256];
|
||||
|
|
@ -1769,6 +1809,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
P(CWSliderScalar(FM_NAME(FM_AMS),ImGuiDataType_U8,&ins->fm.ams,&_ZERO,&_THREE)); rightClickable
|
||||
ImGui::TableNextColumn();
|
||||
drawAlgorithm(ins->fm.alg,FM_ALGS_4OP,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale));
|
||||
kvsConfig(ins);
|
||||
break;
|
||||
case DIV_INS_OPZ:
|
||||
ImGui::TableNextColumn();
|
||||
|
|
@ -1781,6 +1822,8 @@ void FurnaceGUI::drawInsEdit() {
|
|||
P(CWSliderScalar(FM_NAME(FM_AMS2),ImGuiDataType_U8,&ins->fm.ams2,&_ZERO,&_THREE)); rightClickable
|
||||
ImGui::TableNextColumn();
|
||||
drawAlgorithm(ins->fm.alg,FM_ALGS_4OP,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale));
|
||||
kvsConfig(ins);
|
||||
|
||||
if (ImGui::Button("Request from TX81Z")) {
|
||||
doAction(GUI_ACTION_TX81Z_REQUEST);
|
||||
}
|
||||
|
|
@ -1813,6 +1856,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
ImGui::TableNextColumn();
|
||||
drawAlgorithm(ins->fm.alg&algMax,fourOp?FM_ALGS_4OP_OPL:FM_ALGS_2OP_OPL,ImVec2(ImGui::GetContentRegionAvail().x,48.0*dpiScale));
|
||||
kvsConfig(ins);
|
||||
break;
|
||||
}
|
||||
case DIV_INS_OPLL: {
|
||||
|
|
@ -1837,6 +1881,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ImGui::EndDisabled();
|
||||
ImGui::TableNextColumn();
|
||||
drawAlgorithm(0,FM_ALGS_2OP_OPL,ImVec2(ImGui::GetContentRegionAvail().x,24.0*dpiScale));
|
||||
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
|
||||
bool isPresent[4];
|
||||
|
|
@ -2928,6 +2973,14 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
}
|
||||
|
||||
if (ins->type==DIV_INS_OPZ) {
|
||||
ImGui::SameLine();
|
||||
bool fixedOn=op.egt;
|
||||
if (ImGui::Checkbox("Fixed",&fixedOn)) { PARAMETER
|
||||
op.egt=fixedOn;
|
||||
}
|
||||
}
|
||||
|
||||
//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
|
||||
|
|
@ -3012,23 +3065,85 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ImGui::Text("%s",FM_NAME(FM_KSL));
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(CWSliderScalar(FM_NAME(FM_MULT),ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN)); rightClickable
|
||||
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)-(settings.unsignedDetune?0:3);
|
||||
if (ins->type==DIV_INS_OPZ) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (CWSliderInt("##DT",&detune,-3,4)) { PARAMETER
|
||||
op.dt=detune+(settings.unsignedDetune?0:3);
|
||||
} rightClickable
|
||||
P(CWSliderScalar(FM_NAME(FM_EGSHIFT),ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE)); rightClickable
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_DT));
|
||||
ImGui::Text("%s",FM_NAME(FM_EGSHIFT));
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(CWSliderScalar(FM_NAME(FM_REV),ImGuiDataType_U8,&op.dam,&_ZERO,&_SEVEN)); rightClickable
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_REV));
|
||||
}
|
||||
|
||||
if (ins->type==DIV_INS_OPZ) {
|
||||
if (op.egt) {
|
||||
int block=op.dt;
|
||||
int freqNum=(op.mult<<4)|(op.dvb&15);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (CWSliderInt(FM_NAME(FM_MULT),&block,0,7)) { PARAMETER
|
||||
if (block<0) block=0;
|
||||
if (block>7) block=7;
|
||||
op.dt=block;
|
||||
} rightClickable
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Block");
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (CWSliderInt(FM_NAME(FM_FINE),&freqNum,0,255)) { PARAMETER
|
||||
if (freqNum<0) freqNum=0;
|
||||
if (freqNum>255) freqNum=255;
|
||||
op.mult=freqNum>>4;
|
||||
op.dvb=freqNum&15;
|
||||
} rightClickable
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("FreqNum");
|
||||
} else {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(CWSliderScalar(FM_NAME(FM_MULT),ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN)); rightClickable
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_MULT));
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(CWSliderScalar(FM_NAME(FM_FINE),ImGuiDataType_U8,&op.dvb,&_ZERO,&_FIFTEEN)); rightClickable
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_FINE));
|
||||
}
|
||||
} else {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
P(CWSliderScalar(FM_NAME(FM_MULT),ImGuiDataType_U8,&op.mult,&_ZERO,&_FIFTEEN)); rightClickable
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_MULT));
|
||||
}
|
||||
|
||||
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ) {
|
||||
if (!(ins->type==DIV_INS_OPZ && op.egt)) {
|
||||
int detune=(op.dt&7)-(settings.unsignedDetune?0:3);
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (CWSliderInt("##DT",&detune,-3,4)) { PARAMETER
|
||||
op.dt=detune+(settings.unsignedDetune?0:3);
|
||||
} rightClickable
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s",FM_NAME(FM_DT));
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
|
@ -4277,7 +4392,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
|
||||
const char* waveLabel="Waveform";
|
||||
int waveMax=(ins->type==DIV_INS_VERA)?3:255;
|
||||
int waveMax=(ins->type==DIV_INS_VERA)?3:(MAX(1,e->song.waveLen-1));
|
||||
bool waveBitMode=false;
|
||||
if (ins->type==DIV_INS_C64 || ins->type==DIV_INS_SAA1099) {
|
||||
waveBitMode=true;
|
||||
|
|
@ -4295,7 +4410,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
waveBitMode=true;
|
||||
}
|
||||
if (ins->type==DIV_INS_VRC6) {
|
||||
waveMax=ins->amiga.useSample?255:0;
|
||||
waveMax=ins->amiga.useSample?(MAX(1,e->song.waveLen-1)):0;
|
||||
}
|
||||
|
||||
if (ins->type==DIV_INS_OPLL) {
|
||||
|
|
@ -4303,7 +4418,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
|
||||
if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930) {
|
||||
waveMax=ins->amiga.useSample?255:3;
|
||||
waveMax=ins->amiga.useSample?(MAX(1,e->song.waveLen-1)):3;
|
||||
waveBitMode=ins->amiga.useSample?false:true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
// for suck's fake Clang extension!
|
||||
#include <imgui.h>
|
||||
#define _USE_MATH_DEFINES
|
||||
#include "gui.h"
|
||||
#include "../ta-log.h"
|
||||
|
|
@ -24,6 +26,7 @@
|
|||
#include "IconsFontAwesome4.h"
|
||||
#include "misc/cpp/imgui_stdlib.h"
|
||||
#include "guiConst.h"
|
||||
#include "../utfutils.h"
|
||||
#include <fmt/printf.h>
|
||||
|
||||
inline float randRange(float min, float max) {
|
||||
|
|
@ -400,7 +403,7 @@ void FurnaceGUI::drawPattern() {
|
|||
ImGui::PushStyleColor(ImGuiCol_Header,uiColors[GUI_COLOR_PATTERN_SELECTION]);
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,uiColors[GUI_COLOR_PATTERN_SELECTION_HOVER]);
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive,uiColors[GUI_COLOR_PATTERN_SELECTION_ACTIVE]);
|
||||
if (ImGui::BeginTable("PatternView",displayChans+2,ImGuiTableFlags_BordersInnerV|ImGuiTableFlags_ScrollX|ImGuiTableFlags_ScrollY|ImGuiTableFlags_NoPadInnerX)) {
|
||||
if (ImGui::BeginTable("PatternView",displayChans+2,ImGuiTableFlags_BordersInnerV|ImGuiTableFlags_ScrollX|ImGuiTableFlags_ScrollY|ImGuiTableFlags_NoPadInnerX|ImGuiTableFlags_NoBordersInFrozenArea)) {
|
||||
ImGui::TableSetupColumn("pos",ImGuiTableColumnFlags_WidthFixed);
|
||||
char chanID[2048];
|
||||
float lineHeight=(ImGui::GetTextLineHeight()+2*dpiScale);
|
||||
|
|
@ -447,41 +450,46 @@ void FurnaceGUI::drawPattern() {
|
|||
if (!e->curSubSong->chanShow[i]) continue;
|
||||
ImGui::TableNextColumn();
|
||||
bool displayTooltip=false;
|
||||
if (e->curSubSong->chanCollapse[i]) {
|
||||
const char* chName=e->getChannelShortName(i);
|
||||
if (strlen(chName)>3) {
|
||||
snprintf(chanID,2048,"...##_CH%d",i);
|
||||
} else {
|
||||
snprintf(chanID,2048,"%s##_CH%d",chName,i);
|
||||
}
|
||||
displayTooltip=true;
|
||||
} else {
|
||||
const char* chName=e->getChannelName(i);
|
||||
size_t chNameLimit=6+4*e->curPat[i].effectCols;
|
||||
if (strlen(chName)>chNameLimit) {
|
||||
String shortChName=chName;
|
||||
shortChName.resize(chNameLimit-3);
|
||||
shortChName+="...";
|
||||
snprintf(chanID,2048," %s##_CH%d",shortChName.c_str(),i);
|
||||
displayTooltip=true;
|
||||
} else {
|
||||
snprintf(chanID,2048," %s##_CH%d",chName,i);
|
||||
}
|
||||
}
|
||||
|
||||
bool muted=e->isChannelMuted(i);
|
||||
ImVec4 chanHead=muted?uiColors[GUI_COLOR_CHANNEL_MUTED]:uiColors[GUI_COLOR_CHANNEL_FM+e->getChannelType(i)];
|
||||
ImVec4 chanHead=muted?uiColors[GUI_COLOR_CHANNEL_MUTED]:channelColor(i);
|
||||
ImVec4 chanHeadActive=chanHead;
|
||||
ImVec4 chanHeadHover=chanHead;
|
||||
ImVec4 chanHeadBase=chanHead;
|
||||
|
||||
if (e->keyHit[i]) {
|
||||
keyHit[i]=0.2;
|
||||
if (!muted) {
|
||||
int note=e->getChanState(i)->note+60;
|
||||
if (note>=0 && note<180) {
|
||||
pianoKeyHit[note]=1.0;
|
||||
keyHit1[i]=1.0f;
|
||||
if (settings.channelFeedbackStyle==1) {
|
||||
keyHit[i]=0.2;
|
||||
if (!muted) {
|
||||
int note=e->getChanState(i)->note+60;
|
||||
if (note>=0 && note<180) {
|
||||
pianoKeyHit[note]=1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
e->keyHit[i]=false;
|
||||
}
|
||||
if (settings.channelFeedbackStyle==2 && e->isRunning()) {
|
||||
float amount=((float)(e->getChanState(i)->volume>>8)/(float)e->getMaxVolumeChan(i));
|
||||
if (!e->getChanState(i)->keyOn) amount=0.0f;
|
||||
keyHit[i]=amount*0.2f;
|
||||
if (!muted) {
|
||||
int note=e->getChanState(i)->note+60;
|
||||
if (note>=0 && note<180) {
|
||||
pianoKeyHit[note]=amount;
|
||||
}
|
||||
}
|
||||
} else if (settings.channelFeedbackStyle==3 && e->isRunning()) {
|
||||
bool active=e->getChanState(i)->keyOn;
|
||||
keyHit[i]=active?0.2f:0.0f;
|
||||
if (!muted) {
|
||||
int note=e->getChanState(i)->note+60;
|
||||
if (note>=0 && note<180) {
|
||||
pianoKeyHit[note]=active?1.0f:0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (settings.guiColorsBase) {
|
||||
chanHead.x*=1.0-keyHit[i]; chanHead.y*=1.0-keyHit[i]; chanHead.z*=1.0-keyHit[i];
|
||||
chanHeadActive.x*=0.5; chanHeadActive.y*=0.5; chanHeadActive.z*=0.5;
|
||||
|
|
@ -491,17 +499,210 @@ void FurnaceGUI::drawPattern() {
|
|||
chanHeadActive.x*=0.8; chanHeadActive.y*=0.8; chanHeadActive.z*=0.8;
|
||||
chanHeadHover.x*=0.4+keyHit[i]; chanHeadHover.y*=0.4+keyHit[i]; chanHeadHover.z*=0.4+keyHit[i];
|
||||
}
|
||||
keyHit[i]-=0.02*60.0*ImGui::GetIO().DeltaTime;
|
||||
keyHit[i]-=((settings.channelStyle==0)?0.02:0.01)*60.0*ImGui::GetIO().DeltaTime;
|
||||
if (keyHit[i]<0) keyHit[i]=0;
|
||||
ImGui::PushStyleColor(ImGuiCol_Header,chanHead);
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderActive,chanHeadActive);
|
||||
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,chanHeadHover);
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(chanHead));
|
||||
ImGui::PushStyleColor(ImGuiCol_Text,ImGui::GetColorU32(channelTextColor(i)));
|
||||
if (settings.channelStyle==0) ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg,ImGui::GetColorU32(chanHead));
|
||||
if (muted) ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_CHANNEL_MUTED]);
|
||||
ImGui::Selectable(chanID,true,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale));
|
||||
if (settings.channelFont==0) ImGui::PushFont(mainFont);
|
||||
|
||||
// TODO: appearance
|
||||
ImGuiWindow* window=ImGui::GetCurrentWindow();
|
||||
ImVec2 size=ImVec2(
|
||||
1.0f,
|
||||
lineHeight+1.0f*dpiScale
|
||||
);
|
||||
ImDrawList* dl=ImGui::GetWindowDrawList();
|
||||
|
||||
if (settings.channelStyle!=0) {
|
||||
size.y+=6.0f*dpiScale;
|
||||
}
|
||||
|
||||
if (settings.channelStyle==2) {
|
||||
size.y+=6.0f*dpiScale;
|
||||
}
|
||||
|
||||
ImVec2 minArea=window->DC.CursorPos;
|
||||
ImVec2 maxArea=ImVec2(
|
||||
minArea.x+window->WorkRect.Max.x-window->WorkRect.Min.x,
|
||||
minArea.y+size.y
|
||||
);
|
||||
ImRect rect=ImRect(minArea,maxArea);
|
||||
float padding=ImGui::CalcTextSize("A").x;
|
||||
|
||||
ImVec2 minLabelArea=minArea;
|
||||
ImVec2 maxLabelArea=maxArea;
|
||||
|
||||
if (e->curSubSong->chanCollapse[i]) {
|
||||
const char* chName=e->getChannelShortName(i);
|
||||
if (strlen(chName)>3) {
|
||||
snprintf(chanID,2048,"...");
|
||||
} else {
|
||||
snprintf(chanID,2048,"%s",chName);
|
||||
}
|
||||
displayTooltip=true;
|
||||
} else {
|
||||
minLabelArea.x+=padding;
|
||||
maxLabelArea.x-=padding;
|
||||
if (settings.channelStyle==3) { // split button
|
||||
maxLabelArea.x-=ImGui::GetFrameHeightWithSpacing();
|
||||
}
|
||||
const char* chName=e->getChannelName(i);
|
||||
float chNameLimit=maxLabelArea.x-minLabelArea.x;
|
||||
if (ImGui::CalcTextSize(chName).x>chNameLimit) {
|
||||
String shortChName;
|
||||
float totalAdvanced=0.0f;
|
||||
float ellipsisSize=ImGui::CalcTextSize("...").x;
|
||||
for (const char* j=chName; *j;) {
|
||||
signed char l;
|
||||
int ch=decodeUTF8((const unsigned char*)j,l);
|
||||
|
||||
totalAdvanced+=ImGui::GetFont()->GetCharAdvance(ch);
|
||||
if (totalAdvanced>(chNameLimit-ellipsisSize)) break;
|
||||
|
||||
for (int k=0; k<l; k++) {
|
||||
shortChName+=j[k];
|
||||
}
|
||||
|
||||
j+=l;
|
||||
}
|
||||
shortChName+="...";
|
||||
snprintf(chanID,2048,"%s",shortChName.c_str());
|
||||
displayTooltip=true;
|
||||
} else {
|
||||
snprintf(chanID,2048,"%s",chName);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.channelTextCenter) {
|
||||
minLabelArea.x+=0.5f*(maxLabelArea.x-minLabelArea.x-ImGui::CalcTextSize(chanID).x);
|
||||
}
|
||||
|
||||
if (extraChannelButtons==0 || settings.channelVolStyle!=0) ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0.0f,0.0f));
|
||||
|
||||
ImGui::PushID(2048+i);
|
||||
switch (settings.channelStyle) {
|
||||
case 0: // classic
|
||||
ImGui::ItemSize(size,ImGui::GetStyle().FramePadding.y);
|
||||
if (ImGui::ItemAdd(rect,ImGui::GetID(chanID))) {
|
||||
bool hovered=ImGui::ItemHoverable(rect,ImGui::GetID(chanID));
|
||||
ImU32 col=hovered?ImGui::GetColorU32(ImGuiCol_HeaderHovered):ImGui::GetColorU32(ImGuiCol_Header);
|
||||
dl->AddRectFilled(rect.Min,rect.Max,col);
|
||||
dl->AddText(ImVec2(minLabelArea.x,rect.Min.y),ImGui::GetColorU32(channelTextColor(i)),chanID);
|
||||
}
|
||||
break;
|
||||
case 1: { // line
|
||||
ImGui::ItemSize(size,ImGui::GetStyle().FramePadding.y);
|
||||
if (ImGui::ItemAdd(rect,ImGui::GetID(chanID))) {
|
||||
bool hovered=ImGui::ItemHoverable(rect,ImGui::GetID(chanID));
|
||||
ImU32 fadeCol0=ImGui::GetColorU32(ImVec4(
|
||||
chanHeadBase.x,
|
||||
chanHeadBase.y,
|
||||
chanHeadBase.z,
|
||||
hovered?0.25f:0.0f
|
||||
));
|
||||
ImU32 fadeCol=ImGui::GetColorU32(ImVec4(
|
||||
chanHeadBase.x,
|
||||
chanHeadBase.y,
|
||||
chanHeadBase.z,
|
||||
hovered?0.5f:MIN(1.0f,chanHeadBase.w*keyHit[i]*4.0f)
|
||||
));
|
||||
dl->AddRectFilledMultiColor(rect.Min,rect.Max,fadeCol0,fadeCol0,fadeCol,fadeCol);
|
||||
dl->AddLine(ImVec2(rect.Min.x,rect.Max.y),ImVec2(rect.Max.x,rect.Max.y),ImGui::GetColorU32(chanHeadBase),2.0f*dpiScale);
|
||||
dl->AddText(ImVec2(minLabelArea.x,rect.Min.y+3.0*dpiScale),ImGui::GetColorU32(channelTextColor(i)),chanID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: { // round
|
||||
ImGui::ItemSize(size,ImGui::GetStyle().FramePadding.y);
|
||||
if (ImGui::ItemAdd(rect,ImGui::GetID(chanID))) {
|
||||
bool hovered=ImGui::ItemHoverable(rect,ImGui::GetID(chanID));
|
||||
ImU32 fadeCol0=ImGui::GetColorU32(ImVec4(
|
||||
chanHeadBase.x,
|
||||
chanHeadBase.y,
|
||||
chanHeadBase.z,
|
||||
hovered?0.5f:MIN(1.0f,0.3f+chanHeadBase.w*keyHit[i]*1.5f)
|
||||
));
|
||||
ImU32 fadeCol=ImGui::GetColorU32(ImVec4(
|
||||
chanHeadBase.x,
|
||||
chanHeadBase.y,
|
||||
chanHeadBase.z,
|
||||
hovered?0.3f:MIN(1.0f,0.2f+chanHeadBase.w*keyHit[i]*1.2f)
|
||||
));
|
||||
ImVec2 rMin=rect.Min;
|
||||
ImVec2 rMax=rect.Max;
|
||||
rMin.x+=3.0f*dpiScale;
|
||||
rMin.y+=6.0f*dpiScale;
|
||||
rMax.x-=3.0f*dpiScale;
|
||||
rMax.y-=6.0f*dpiScale;
|
||||
dl->AddRectFilledMultiColor(rMin,rMax,fadeCol0,fadeCol0,fadeCol,fadeCol,4.0f*dpiScale);
|
||||
dl->AddText(ImVec2(minLabelArea.x,rect.Min.y+6.0*dpiScale),ImGui::GetColorU32(channelTextColor(i)),chanID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: // split button
|
||||
ImGui::Dummy(ImVec2(1.0f,2.0f*dpiScale));
|
||||
ImGui::SetCursorPosX(minLabelArea.x);
|
||||
ImGui::TextUnformatted(chanID);
|
||||
ImGui::SameLine();
|
||||
ImGui::PushFont(mainFont);
|
||||
ImGui::SmallButton(muted?ICON_FA_VOLUME_OFF:ICON_FA_VOLUME_UP);
|
||||
ImGui::PopFont();
|
||||
break;
|
||||
case 4: { // square border
|
||||
ImGui::ItemSize(size,ImGui::GetStyle().FramePadding.y);
|
||||
if (ImGui::ItemAdd(rect,ImGui::GetID(chanID))) {
|
||||
bool hovered=ImGui::ItemHoverable(rect,ImGui::GetID(chanID));
|
||||
ImU32 fadeCol=ImGui::GetColorU32(ImVec4(
|
||||
chanHeadBase.x,
|
||||
chanHeadBase.y,
|
||||
chanHeadBase.z,
|
||||
hovered?1.0f:MIN(1.0f,0.2f+chanHeadBase.w*keyHit[i]*4.0f)
|
||||
));
|
||||
ImVec2 rMin=rect.Min;
|
||||
ImVec2 rMax=rect.Max;
|
||||
rMin.x+=2.0f*dpiScale;
|
||||
rMin.y+=3.0f*dpiScale;
|
||||
rMax.x-=3.0f*dpiScale;
|
||||
rMax.y-=3.0f*dpiScale;
|
||||
dl->AddRect(rMin,rMax,fadeCol,0.0f,2.0*dpiScale);
|
||||
dl->AddText(ImVec2(minLabelArea.x,rect.Min.y+3.0*dpiScale),ImGui::GetColorU32(channelTextColor(i)),chanID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 5: { // round border
|
||||
ImGui::ItemSize(size,ImGui::GetStyle().FramePadding.y);
|
||||
if (ImGui::ItemAdd(rect,ImGui::GetID(chanID))) {
|
||||
bool hovered=ImGui::ItemHoverable(rect,ImGui::GetID(chanID));
|
||||
ImU32 fadeCol=ImGui::GetColorU32(ImVec4(
|
||||
chanHeadBase.x,
|
||||
chanHeadBase.y,
|
||||
chanHeadBase.z,
|
||||
hovered?1.0f:MIN(1.0f,0.2f+chanHeadBase.w*keyHit[i]*4.0f)
|
||||
));
|
||||
ImVec2 rMin=rect.Min;
|
||||
ImVec2 rMax=rect.Max;
|
||||
rMin.x+=2.0f*dpiScale;
|
||||
rMin.y+=3.0f*dpiScale;
|
||||
rMax.x-=3.0f*dpiScale;
|
||||
rMax.y-=3.0f*dpiScale;
|
||||
dl->AddRect(rMin,rMax,fadeCol,4.0f*dpiScale,ImDrawFlags_RoundCornersAll,2.0*dpiScale);
|
||||
dl->AddText(ImVec2(minLabelArea.x,rect.Min.y+3.0*dpiScale),ImGui::GetColorU32(channelTextColor(i)),chanID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
ImGui::PopID();
|
||||
|
||||
if (extraChannelButtons==0 || settings.channelVolStyle!=0) ImGui::PopStyleVar();
|
||||
|
||||
if (displayTooltip && ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("%s",e->getChannelName(i));
|
||||
}
|
||||
if (settings.channelFont==0) ImGui::PopFont();
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
|
||||
if (settings.soloAction!=1 && soloTimeout>0 && soloChan==i) {
|
||||
e->toggleSolo(i);
|
||||
|
|
@ -513,11 +714,72 @@ void FurnaceGUI::drawPattern() {
|
|||
}
|
||||
}
|
||||
if (muted) ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::PopStyleColor(4);
|
||||
if (settings.soloAction!=2) if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
|
||||
inhibitMenu=true;
|
||||
e->toggleSolo(i);
|
||||
}
|
||||
|
||||
if (settings.channelStyle==3) {
|
||||
ImGui::Dummy(ImVec2(1.0f,2.0f*dpiScale));
|
||||
}
|
||||
|
||||
// volume bar
|
||||
if (settings.channelVolStyle!=0) {
|
||||
ImVec2 sizeV=ImVec2(
|
||||
1.0f,
|
||||
6.0*dpiScale
|
||||
);
|
||||
ImVec2 minAreaV=window->DC.CursorPos;
|
||||
ImVec2 maxAreaV=ImVec2(
|
||||
minAreaV.x+window->WorkRect.Max.x-window->WorkRect.Min.x,
|
||||
minAreaV.y+sizeV.y
|
||||
);
|
||||
ImRect rectV=ImRect(minAreaV,maxAreaV);
|
||||
ImGui::ItemSize(sizeV,ImGui::GetStyle().FramePadding.y);
|
||||
if (ImGui::ItemAdd(rectV,ImGui::GetID(chanID))) {
|
||||
float xLeft=0.0f;
|
||||
float xRight=1.0f;
|
||||
|
||||
if (e->keyHit[i]) {
|
||||
keyHit1[i]=1.0f;
|
||||
e->keyHit[i]=false;
|
||||
}
|
||||
|
||||
if (e->isRunning()) {
|
||||
DivChannelState* cs=e->getChanState(i);
|
||||
float stereoPan=(float)(e->convertPanSplitToLinearLR(cs->panL,cs->panR,256)-128)/128.0;
|
||||
switch (settings.channelVolStyle) {
|
||||
case 1: // simple
|
||||
xRight=((float)(e->getChanState(i)->volume>>8)/(float)e->getMaxVolumeChan(i))*0.9+(keyHit1[i]*0.1f);
|
||||
break;
|
||||
case 2: { // stereo
|
||||
float amount=((float)(e->getChanState(i)->volume>>8)/(float)e->getMaxVolumeChan(i))*0.4+(keyHit1[i]*0.1f);
|
||||
xRight=0.5+amount*(1.0+MIN(0.0,stereoPan));
|
||||
xLeft=0.5-amount*(1.0-MAX(0.0,stereoPan));
|
||||
break;
|
||||
}
|
||||
case 3: // real
|
||||
xRight=chanOscVol[i];
|
||||
break;
|
||||
case 4: // real (stereo)
|
||||
xRight=0.5+chanOscVol[i]*0.5*(1.0+MIN(0.0,stereoPan));
|
||||
xLeft=0.5-chanOscVol[i]*0.5*(1.0-MAX(0.0,stereoPan));
|
||||
break;
|
||||
}
|
||||
|
||||
dl->AddRectFilled(
|
||||
ImLerp(rectV.Min,rectV.Max,ImVec2(xLeft,0.0f)),
|
||||
ImLerp(rectV.Min,rectV.Max,ImVec2(xRight,1.0f)),
|
||||
ImGui::GetColorU32(chanHeadBase)
|
||||
);
|
||||
}
|
||||
keyHit1[i]-=0.2f;
|
||||
if (keyHit1[i]<0.0f) keyHit1[i]=0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// extra buttons
|
||||
if (extraChannelButtons==2) {
|
||||
DivPattern* pat=e->curPat[i].getPattern(e->curOrders->ord[i][ord],true);
|
||||
ImGui::PushFont(mainFont);
|
||||
|
|
|
|||
|
|
@ -960,11 +960,27 @@ void FurnaceGUI::initSystemPresets() {
|
|||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"NEC PC-98 (with PC-9801-86)", { // -73 also has OPNA
|
||||
DIV_SYSTEM_PC98, 64, 0, 1,
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16), // 2x 16-bit Burr Brown DAC
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16),
|
||||
0
|
||||
}
|
||||
));
|
||||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"NEC PC-98 (with PC-9801-86; extended channel 3)", { // -73 also has OPNA
|
||||
DIV_SYSTEM_PC98_EXT, 64, 0, 1,
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16),
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16),
|
||||
0
|
||||
}
|
||||
));
|
||||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"NEC PC-98 (with PC-9801-73)", {
|
||||
DIV_SYSTEM_PC98, 64, 0, 1,
|
||||
0
|
||||
}
|
||||
));
|
||||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"NEC PC-98 (with PC-9801-73; extended channel 3)", {
|
||||
DIV_SYSTEM_PC98_EXT, 64, 0, 1,
|
||||
0
|
||||
}
|
||||
|
|
@ -972,6 +988,7 @@ void FurnaceGUI::initSystemPresets() {
|
|||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible)", {
|
||||
DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16)|(1<<20),
|
||||
DIV_SYSTEM_OPL3, 64, 0, 0,
|
||||
0
|
||||
}
|
||||
|
|
@ -979,6 +996,7 @@ void FurnaceGUI::initSystemPresets() {
|
|||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible; extended channel 3)", {
|
||||
DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16)|(1<<20),
|
||||
DIV_SYSTEM_OPL3, 64, 0, 0,
|
||||
0
|
||||
}
|
||||
|
|
@ -986,6 +1004,7 @@ void FurnaceGUI::initSystemPresets() {
|
|||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible in drums mode)", {
|
||||
DIV_SYSTEM_OPN, 64, 0, 2, // 4MHz
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16)|(1<<20),
|
||||
DIV_SYSTEM_OPL3_DRUMS, 64, 0, 2,
|
||||
0
|
||||
}
|
||||
|
|
@ -993,6 +1012,7 @@ void FurnaceGUI::initSystemPresets() {
|
|||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"NEC PC-98 (with Sound Blaster 16 for PC-9800 w/PC-9801-26/K compatible in drums mode; extended channel 3)", {
|
||||
DIV_SYSTEM_OPN_EXT, 64, 0, 2, // 4MHz
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16)|(1<<20),
|
||||
DIV_SYSTEM_OPL3_DRUMS, 64, 0, 2,
|
||||
0
|
||||
}
|
||||
|
|
@ -1092,6 +1112,20 @@ void FurnaceGUI::initSystemPresets() {
|
|||
0
|
||||
}
|
||||
));
|
||||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"Atari ST", {
|
||||
DIV_SYSTEM_AY8910, 64, 0, 19,
|
||||
0
|
||||
}
|
||||
));
|
||||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"Atari STE", {
|
||||
DIV_SYSTEM_AY8910, 64, 0, 19,
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 50667|(7<<16),
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 50667|(7<<16),
|
||||
0
|
||||
}
|
||||
));
|
||||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"SAM Coupé", {
|
||||
DIV_SYSTEM_SAA1099, 64, 0, 0,
|
||||
|
|
@ -1146,17 +1180,33 @@ void FurnaceGUI::initSystemPresets() {
|
|||
0
|
||||
}
|
||||
));
|
||||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"PC + AdLib/Sound Blaster", {
|
||||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"PC + AdLib", {
|
||||
DIV_SYSTEM_OPL2, 64, 0, 0,
|
||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||
0
|
||||
}
|
||||
));
|
||||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"PC + AdLib (drums mode)", {
|
||||
DIV_SYSTEM_OPL2, 64, 0, 0,
|
||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||
0
|
||||
}
|
||||
));
|
||||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"PC + Sound Blaster", {
|
||||
DIV_SYSTEM_OPL2, 64, 0, 0,
|
||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 22049|(7<<16),
|
||||
0
|
||||
}
|
||||
));
|
||||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"PC + AdLib/Sound Blaster (drums mode)", {
|
||||
DIV_SYSTEM_OPL2_DRUMS, 64, 0, 0,
|
||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 22049|(7<<16),
|
||||
0
|
||||
}
|
||||
));
|
||||
|
|
@ -1165,6 +1215,7 @@ void FurnaceGUI::initSystemPresets() {
|
|||
DIV_SYSTEM_OPL2, 64, 0, 0,
|
||||
DIV_SYSTEM_SAA1099, 64, 0, 1,
|
||||
DIV_SYSTEM_SAA1099, 64, 0, 1,
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 22049|(7<<16),
|
||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||
0
|
||||
}
|
||||
|
|
@ -1174,6 +1225,7 @@ void FurnaceGUI::initSystemPresets() {
|
|||
DIV_SYSTEM_OPL2_DRUMS, 64, 0, 0,
|
||||
DIV_SYSTEM_SAA1099, 64, 0, 1,
|
||||
DIV_SYSTEM_SAA1099, 64, 0, 1,
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 22049|(7<<16),
|
||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||
0
|
||||
}
|
||||
|
|
@ -1182,6 +1234,7 @@ void FurnaceGUI::initSystemPresets() {
|
|||
"PC + Sound Blaster Pro", {
|
||||
DIV_SYSTEM_OPL2, 64, -127, 0,
|
||||
DIV_SYSTEM_OPL2, 64, 127, 0,
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 22049|(7<<16)|(1<<20), //alternatively 44.1 khz mono
|
||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||
0
|
||||
}
|
||||
|
|
@ -1190,6 +1243,7 @@ void FurnaceGUI::initSystemPresets() {
|
|||
"PC + Sound Blaster Pro (drums mode)", {
|
||||
DIV_SYSTEM_OPL2_DRUMS, 64, -127, 0,
|
||||
DIV_SYSTEM_OPL2_DRUMS, 64, 127, 0,
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 22049|(7<<16)|(1<<20), //alternatively 44.1 khz mono
|
||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||
0
|
||||
}
|
||||
|
|
@ -1197,6 +1251,7 @@ void FurnaceGUI::initSystemPresets() {
|
|||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"PC + Sound Blaster Pro 2", {
|
||||
DIV_SYSTEM_OPL3, 64, 0, 0,
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16)|(1<<20),
|
||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||
0
|
||||
}
|
||||
|
|
@ -1204,6 +1259,7 @@ void FurnaceGUI::initSystemPresets() {
|
|||
cat.systems.push_back(FurnaceGUISysDef(
|
||||
"PC + Sound Blaster Pro 2 (drums mode)", {
|
||||
DIV_SYSTEM_OPL3_DRUMS, 64, 0, 0,
|
||||
DIV_SYSTEM_PCM_DAC, 64, 0, 44099|(15<<16)|(1<<20),
|
||||
DIV_SYSTEM_PCSPKR, 64, 0, 0,
|
||||
0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1284,14 +1284,14 @@ void FurnaceGUI::drawSettings() {
|
|||
}
|
||||
|
||||
ImGui::Text("Channel name colors:");
|
||||
if (ImGui::RadioButton("Single##CTC0",settings.channelColors==0)) {
|
||||
settings.channelColors=0;
|
||||
if (ImGui::RadioButton("Single##CTC0",settings.channelTextColors==0)) {
|
||||
settings.channelTextColors=0;
|
||||
}
|
||||
if (ImGui::RadioButton("Channel type##CTC1",settings.channelColors==1)) {
|
||||
settings.channelColors=1;
|
||||
if (ImGui::RadioButton("Channel type##CTC1",settings.channelTextColors==1)) {
|
||||
settings.channelTextColors=1;
|
||||
}
|
||||
if (ImGui::RadioButton("Instrument type##CTC2",settings.channelColors==2)) {
|
||||
settings.channelColors=2;
|
||||
if (ImGui::RadioButton("Instrument type##CTC2",settings.channelTextColors==2)) {
|
||||
settings.channelTextColors=2;
|
||||
}
|
||||
|
||||
ImGui::Text("Channel style:");
|
||||
|
|
@ -1327,6 +1327,9 @@ void FurnaceGUI::drawSettings() {
|
|||
if (ImGui::RadioButton("Real##CHV3",settings.channelVolStyle==3)) {
|
||||
settings.channelVolStyle=3;
|
||||
}
|
||||
if (ImGui::RadioButton("Real (stereo)##CHV4",settings.channelVolStyle==4)) {
|
||||
settings.channelVolStyle=4;
|
||||
}
|
||||
|
||||
ImGui::Text("Channel feedback style:");
|
||||
|
||||
|
|
@ -1343,6 +1346,20 @@ void FurnaceGUI::drawSettings() {
|
|||
settings.channelFeedbackStyle=3;
|
||||
}
|
||||
|
||||
ImGui::Text("Channel font:");
|
||||
|
||||
if (ImGui::RadioButton("Regular##CHFont0",settings.channelFont==0)) {
|
||||
settings.channelFont=0;
|
||||
}
|
||||
if (ImGui::RadioButton("Monospace##CHFont1",settings.channelFont==1)) {
|
||||
settings.channelFont=1;
|
||||
}
|
||||
|
||||
bool channelTextCenterB=settings.channelTextCenter;
|
||||
if (ImGui::Checkbox("Center channel name",&channelTextCenterB)) {
|
||||
settings.channelTextCenter=channelTextCenterB;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
bool insEditColorizeB=settings.insEditColorize;
|
||||
|
|
@ -1668,6 +1685,8 @@ void FurnaceGUI::drawSettings() {
|
|||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNode("Channel")) {
|
||||
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_BG,"Single color (background)");
|
||||
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_FG,"Single color (text)");
|
||||
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_FM,"FM");
|
||||
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_PULSE,"Pulse");
|
||||
UI_COLOR_CONFIG(GUI_COLOR_CHANNEL_NOISE,"Noise");
|
||||
|
|
@ -2286,9 +2305,11 @@ void FurnaceGUI::syncSettings() {
|
|||
settings.saveUnusedPatterns=e->getConfInt("saveUnusedPatterns",0);
|
||||
settings.channelColors=e->getConfInt("channelColors",1);
|
||||
settings.channelTextColors=e->getConfInt("channelTextColors",0);
|
||||
settings.channelStyle=e->getConfInt("channelStyle",0);
|
||||
settings.channelStyle=e->getConfInt("channelStyle",1);
|
||||
settings.channelVolStyle=e->getConfInt("channelVolStyle",0);
|
||||
settings.channelFeedbackStyle=e->getConfInt("channelFeedbackStyle",1);
|
||||
settings.channelFont=e->getConfInt("channelFont",1);
|
||||
settings.channelTextCenter=e->getConfInt("channelTextCenter",1);
|
||||
settings.maxRecentFile=e->getConfInt("maxRecentFile",10);
|
||||
|
||||
clampSetting(settings.mainFontSize,2,96);
|
||||
|
|
@ -2386,8 +2407,10 @@ void FurnaceGUI::syncSettings() {
|
|||
clampSetting(settings.channelColors,0,2);
|
||||
clampSetting(settings.channelTextColors,0,2);
|
||||
clampSetting(settings.channelStyle,0,5);
|
||||
clampSetting(settings.channelVolStyle,0,3);
|
||||
clampSetting(settings.channelVolStyle,0,4);
|
||||
clampSetting(settings.channelFeedbackStyle,0,3);
|
||||
clampSetting(settings.channelFont,0,1);
|
||||
clampSetting(settings.channelTextCenter,0,1);
|
||||
clampSetting(settings.maxRecentFile,0,30);
|
||||
|
||||
settings.initialSys=e->decodeSysDesc(e->getConfString("initialSys",""));
|
||||
|
|
@ -2543,6 +2566,8 @@ void FurnaceGUI::commitSettings() {
|
|||
e->setConf("channelStyle",settings.channelStyle);
|
||||
e->setConf("channelVolStyle",settings.channelVolStyle);
|
||||
e->setConf("channelFeedbackStyle",settings.channelFeedbackStyle);
|
||||
e->setConf("channelFont",settings.channelFont);
|
||||
e->setConf("channelTextCenter",settings.channelTextCenter);
|
||||
e->setConf("maxRecentFile",settings.maxRecentFile);
|
||||
|
||||
// colors
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ void FurnaceGUI::drawSongInfo() {
|
|||
ImGui::TableNextColumn();
|
||||
float avail=ImGui::GetContentRegionAvail().x;
|
||||
ImGui::SetNextItemWidth(avail);
|
||||
if (ImGui::InputText("##Name",&e->song.name)) { MARK_MODIFIED
|
||||
if (ImGui::InputText("##Name",&e->song.name,ImGuiInputTextFlags_UndoRedo)) { MARK_MODIFIED
|
||||
updateWindowTitle();
|
||||
}
|
||||
if (e->song.insLen==2) {
|
||||
|
|
@ -61,7 +61,7 @@ void FurnaceGUI::drawSongInfo() {
|
|||
ImGui::Text("Author");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(avail);
|
||||
if (ImGui::InputText("##Author",&e->song.author)) {
|
||||
if (ImGui::InputText("##Author",&e->song.author,ImGuiInputTextFlags_UndoRedo)) {
|
||||
MARK_MODIFIED;
|
||||
}
|
||||
|
||||
|
|
@ -70,18 +70,30 @@ void FurnaceGUI::drawSongInfo() {
|
|||
ImGui::Text("Album");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(avail);
|
||||
if (ImGui::InputText("##Category",&e->song.category)) {
|
||||
if (ImGui::InputText("##Category",&e->song.category,ImGuiInputTextFlags_UndoRedo)) {
|
||||
MARK_MODIFIED;
|
||||
}
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("System");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(avail);
|
||||
if (ImGui::InputText("##SystemName",&e->song.systemName)) {
|
||||
ImGui::SetNextItemWidth(MAX(16.0f*dpiScale,avail-autoButtonSize-ImGui::GetStyle().ItemSpacing.x));
|
||||
if (ImGui::InputText("##SystemName",&e->song.systemName,ImGuiInputTextFlags_UndoRedo)) {
|
||||
MARK_MODIFIED;
|
||||
updateWindowTitle();
|
||||
e->song.autoSystem=false;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
pushToggleColors(e->song.autoSystem);
|
||||
if (ImGui::Button("Auto")) {
|
||||
e->song.autoSystem=!e->song.autoSystem;
|
||||
if (e->song.autoSystem) {
|
||||
autoDetectSystem();
|
||||
updateWindowTitle();
|
||||
}
|
||||
}
|
||||
popToggleColors();
|
||||
autoButtonSize=ImGui::GetItemRectSize().x;
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ void FurnaceGUI::drawNotes() {
|
|||
}
|
||||
if (!notesOpen) return;
|
||||
if (ImGui::Begin("Song Comments",¬esOpen,globalWinFlags)) {
|
||||
ImGui::InputTextMultiline("##SongNotes",&e->song.notes,ImGui::GetContentRegionAvail());
|
||||
ImGui::InputTextMultiline("##SongNotes",&e->song.notes,ImGui::GetContentRegionAvail(),ImGuiInputTextFlags_UndoRedo);
|
||||
}
|
||||
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_NOTES;
|
||||
ImGui::End();
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ void FurnaceGUI::drawSubSongs() {
|
|||
ImGui::Text("Name");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (ImGui::InputText("##SubSongName",&e->curSubSong->name)) {
|
||||
if (ImGui::InputText("##SubSongName",&e->curSubSong->name,ImGuiInputTextFlags_UndoRedo)) {
|
||||
MARK_MODIFIED;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool
|
|||
if (ImGui::RadioButton("PAL (3.55MHz)",(flags&15)==1)) {
|
||||
copyOfFlags=(flags&(~15))|1;
|
||||
}
|
||||
if (ImGui::RadioButton("BBC Micro (4MHz)",(flags&15)==2)) {
|
||||
if (ImGui::RadioButton("Arcade (4MHz)",(flags&15)==2)) {
|
||||
copyOfFlags=(flags&(~15))|2;
|
||||
}
|
||||
if (ImGui::RadioButton("Half NTSC (1.79MHz)",(flags&15)==3)) {
|
||||
|
|
@ -358,6 +358,14 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool
|
|||
if (ImGui::Checkbox("Stereo##_AY_STEREO",&stereo)) {
|
||||
copyOfFlags=(flags&(~0x40))|(stereo?0x40:0);
|
||||
}
|
||||
if (stereo) {
|
||||
int sep=256-((flags>>8)&255);
|
||||
if (CWSliderInt("Separation",&sep,1,256)) {
|
||||
if (sep<1) sep=1;
|
||||
if (sep>256) sep=256;
|
||||
copyOfFlags=(flags&(~0xff00))|((256-sep)<<8);
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
bool clockSel=flags&0x80;
|
||||
ImGui::BeginDisabled((type==DIV_SYSTEM_AY8910) && ((flags&0x30)!=16));
|
||||
|
|
@ -765,6 +773,9 @@ void FurnaceGUI::drawSysConf(int chan, DivSystem type, unsigned int& flags, bool
|
|||
if (copyOfFlags!=flags) {
|
||||
if (chan>=0) {
|
||||
e->setSysFlags(chan,copyOfFlags,restart);
|
||||
if (e->song.autoSystem) {
|
||||
autoDetectSystem();
|
||||
}
|
||||
updateWindowTitle();
|
||||
} else {
|
||||
flags=copyOfFlags;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ bool FurnaceGUI::parseSysEx(unsigned char* data, size_t len) {
|
|||
op.rs=reader.readC();
|
||||
reader.readC(); // EBS - ignore
|
||||
op.am=reader.readC();
|
||||
// TODO: don't ignore after I add KVS to Furnace
|
||||
reader.readC(); // KVS - ignore
|
||||
op.tl=3+((99-reader.readC())*124)/99;
|
||||
unsigned char freq=reader.readC();
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ void FurnaceGUI::drawSysManager() {
|
|||
DivSystem picked=systemPicker();
|
||||
if (picked!=DIV_SYSTEM_NULL) {
|
||||
e->changeSystem(i,picked,preserveChanPos);
|
||||
if (e->song.autoSystem) {
|
||||
autoDetectSystem();
|
||||
}
|
||||
updateWindowTitle();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
|
@ -110,6 +113,9 @@ void FurnaceGUI::drawSysManager() {
|
|||
if (!e->addSystem(picked)) {
|
||||
showError("cannot add chip! ("+e->getLastError()+")");
|
||||
}
|
||||
if (e->song.autoSystem) {
|
||||
autoDetectSystem();
|
||||
}
|
||||
updateWindowTitle();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue