Merge pull request #1623 from Eknous-P/exportwin

Export Window
This commit is contained in:
tildearrow 2023-12-22 14:29:32 -05:00 committed by GitHub
commit a642cb4d4b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 353 additions and 181 deletions

View file

@ -779,6 +779,7 @@ src/gui/doAction.cpp
src/gui/editing.cpp src/gui/editing.cpp
src/gui/editControls.cpp src/gui/editControls.cpp
src/gui/effectList.cpp src/gui/effectList.cpp
src/gui/exportOptions.cpp
src/gui/findReplace.cpp src/gui/findReplace.cpp
src/gui/fmPreview.cpp src/gui/fmPreview.cpp
src/gui/gradient.cpp src/gui/gradient.cpp

View file

@ -65,6 +65,9 @@ void FurnaceGUI::doAction(int what) {
case GUI_ACTION_SAVE_AS: case GUI_ACTION_SAVE_AS:
openFileDialog(GUI_FILE_SAVE); openFileDialog(GUI_FILE_SAVE);
break; break;
case GUI_ACTION_EXPORT:
displayExport=true;
break;
case GUI_ACTION_UNDO: case GUI_ACTION_UNDO:
if (curWindow==GUI_WINDOW_SAMPLE_EDIT) { if (curWindow==GUI_WINDOW_SAMPLE_EDIT) {
doUndoSample(); doUndoSample();

270
src/gui/exportOptions.cpp Normal file
View file

@ -0,0 +1,270 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "gui.h"
#include "guiConst.h"
#include "../fileutils.h"
#include "misc/cpp/imgui_stdlib.h"
void FurnaceGUI::drawExportAudio() {
exitDisabledTimer=1;
ImGui::RadioButton("one file",&audioExportType,0);
ImGui::RadioButton("multiple files (one per chip)",&audioExportType,1);
ImGui::RadioButton("multiple files (one per channel)",&audioExportType,2);
if (ImGui::InputInt("Loops",&exportLoops,1,2)) {
if (exportLoops<0) exportLoops=0;
}
if (ImGui::InputDouble("Fade out (seconds)",&exportFadeOut,1.0,2.0,"%.1f")) {
if (exportFadeOut<0.0) exportFadeOut=0.0;
}
if (ImGui::Button("Export")) {
switch (audioExportType) {
case 0:
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
break;
case 1:
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS);
break;
case 2:
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_CHANNEL);
break;
}
ImGui::CloseCurrentPopup();
}
}
void FurnaceGUI::drawExportVGM() {
exitDisabledTimer=1;
ImGui::Text("settings:");
if (ImGui::BeginCombo("format version",fmt::sprintf("%d.%.2x",vgmExportVersion>>8,vgmExportVersion&0xff).c_str())) {
for (int i=0; i<7; i++) {
if (ImGui::Selectable(fmt::sprintf("%d.%.2x",vgmVersions[i]>>8,vgmVersions[i]&0xff).c_str(),vgmExportVersion==vgmVersions[i])) {
vgmExportVersion=vgmVersions[i];
}
}
ImGui::EndCombo();
}
ImGui::Checkbox("loop",&vgmExportLoop);
if (vgmExportLoop && e->song.loopModality==2) {
ImGui::Text("loop trail:");
ImGui::Indent();
if (ImGui::RadioButton("auto-detect",vgmExportTrailingTicks==-1)) {
vgmExportTrailingTicks=-1;
}
if (ImGui::RadioButton("add one loop",vgmExportTrailingTicks==-2)) {
vgmExportTrailingTicks=-2;
}
if (ImGui::RadioButton("custom",vgmExportTrailingTicks>=0)) {
vgmExportTrailingTicks=0;
}
if (vgmExportTrailingTicks>=0) {
ImGui::SameLine();
if (ImGui::InputInt("##TrailTicks",&vgmExportTrailingTicks,1,100)) {
if (vgmExportTrailingTicks<0) vgmExportTrailingTicks=0;
}
}
ImGui::Unindent();
}
ImGui::Checkbox("add pattern change hints",&vgmExportPatternHints);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(
"inserts data blocks on pattern changes.\n"
"useful if you are writing a playback routine.\n\n"
"the format of a pattern change data block is:\n"
"67 66 FE ll ll ll ll 01 oo rr pp pp pp ...\n"
"- ll: length, a 32-bit little-endian number\n"
"- oo: order\n"
"- rr: initial row (a 0Dxx effect is able to select a different row)\n"
"- pp: pattern index (one per channel)\n\n"
"pattern indexes are ordered as they appear in the song."
);
}
ImGui::Checkbox("direct stream mode",&vgmExportDirectStream);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(
"required for DualPCM and MSM6258 export.\n\n"
"allows for volume/direction changes when playing samples,\n"
"at the cost of a massive increase in file size."
);
}
ImGui::Text("chips to export:");
bool hasOneAtLeast=false;
for (int i=0; i<e->song.systemLen; i++) {
int minVersion=e->minVGMVersion(e->song.system[i]);
ImGui::BeginDisabled(minVersion>vgmExportVersion || minVersion==0);
ImGui::Checkbox(fmt::sprintf("%d. %s##_SYSV%d",i+1,getSystemName(e->song.system[i]),i).c_str(),&willExport[i]);
ImGui::EndDisabled();
if (minVersion>vgmExportVersion) {
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
ImGui::SetTooltip("this chip is only available in VGM %d.%.2x and higher!",minVersion>>8,minVersion&0xff);
}
} else if (minVersion==0) {
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
ImGui::SetTooltip("this chip is not supported by the VGM format!");
}
} else {
if (willExport[i]) hasOneAtLeast=true;
}
}
ImGui::Text("select the chip you wish to export, but only up to %d of each type.",(vgmExportVersion>=0x151)?2:1);
if (hasOneAtLeast) {
if (ImGui::Button("Export")) {
openFileDialog(GUI_FILE_EXPORT_VGM);
ImGui::CloseCurrentPopup();
}
} else {
ImGui::Text("nothing to export");
}
}
void FurnaceGUI::drawExportZSM() {
exitDisabledTimer=1;
ImGui::Text("Commander X16 Zsound Music File");
if (ImGui::InputInt("Tick Rate (Hz)",&zsmExportTickRate,1,2)) {
if (zsmExportTickRate<1) zsmExportTickRate=1;
if (zsmExportTickRate>44100) zsmExportTickRate=44100;
}
ImGui::Checkbox("loop",&zsmExportLoop);
ImGui::SameLine();
ImGui::Checkbox("optimize size",&zsmExportOptimize);
if (ImGui::Button("Export")) {
openFileDialog(GUI_FILE_EXPORT_ZSM);
ImGui::CloseCurrentPopup();
}
}
void FurnaceGUI::drawExportAmigaVal() {
exitDisabledTimer=1;
ImGui::Text(
"this is NOT ROM export! only use for making sure the\n"
"Furnace Amiga emulator is working properly by\n"
"comparing it with real Amiga output."
);
ImGui::AlignTextToFramePadding();
ImGui::Text("Directory");
ImGui::SameLine();
ImGui::InputText("##AVDPath",&workingDirROMExport);
if (ImGui::Button("Bake Data")) {
std::vector<DivROMExportOutput> out=e->buildROM(DIV_ROM_AMIGA_VALIDATION);
if (workingDirROMExport.size()>0) {
if (workingDirROMExport[workingDirROMExport.size()-1]!=DIR_SEPARATOR) workingDirROMExport+=DIR_SEPARATOR_STR;
}
for (DivROMExportOutput& i: out) {
String path=workingDirROMExport+i.name;
FILE* outFile=ps_fopen(path.c_str(),"wb");
if (outFile!=NULL) {
fwrite(i.data->getFinalBuf(),1,i.data->size(),outFile);
fclose(outFile);
}
i.data->finish();
delete i.data;
}
showError(fmt::sprintf("Done! Baked %d files.",(int)out.size()));
ImGui::CloseCurrentPopup();
}
}
void FurnaceGUI::drawExportText() {
exitDisabledTimer=1;
ImGui::Text(
"this option exports the song to a text file.\n"
);
if (ImGui::Button("Export")) {
openFileDialog(GUI_FILE_EXPORT_TEXT);
ImGui::CloseCurrentPopup();
}
}
void FurnaceGUI::drawExportCommand() {
exitDisabledTimer=1;
ImGui::Text(
"this option exports a text or binary file which\n"
"contains a dump of the internal command stream\n"
"produced when playing the song.\n\n"
"technical/development use only!"
);
if (ImGui::Button("Export (binary)")) {
openFileDialog(GUI_FILE_EXPORT_CMDSTREAM_BINARY);
ImGui::CloseCurrentPopup();
}
if (ImGui::Button("Export (text)")) {
openFileDialog(GUI_FILE_EXPORT_CMDSTREAM);
ImGui::CloseCurrentPopup();
}
}
void FurnaceGUI::drawExport() {
ImVec2 avail=ImGui::GetContentRegionAvail();
avail.y-=ImGui::GetFrameHeightWithSpacing();
if (ImGui::BeginChild("sysPickerC",avail,false,ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar)) {
if (ImGui::BeginTabBar("ExportTypes")) {
if (ImGui::BeginTabItem("Audio")) {
drawExportAudio();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("VGM")) {
drawExportVGM();
ImGui::EndTabItem();
}
int numZSMCompat=0;
for (int i=0; i<e->song.systemLen; i++) {
if ((e->song.system[i]==DIV_SYSTEM_VERA) || (e->song.system[i]==DIV_SYSTEM_YM2151)) numZSMCompat++;
}
if (numZSMCompat>0) {
if (ImGui::BeginTabItem("ZSM")) {
drawExportZSM();
ImGui::EndTabItem();
}
}
int numAmiga=0;
for (int i=0; i<e->song.systemLen; i++) {
if (e->song.system[i]==DIV_SYSTEM_AMIGA) numAmiga++;
}
if (numAmiga && settings.iCannotWait) {
if (ImGui::BeginTabItem("Amiga Validation")) {
drawExportAmigaVal();
ImGui::EndTabItem();
}
}
if (ImGui::BeginTabItem("Text")) {
drawExportText();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Command Stream")) {
drawExportCommand();
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
ImGui::EndChild();
}
ImGui::Separator();
if (ImGui::Button("Cancel")) ImGui::CloseCurrentPopup();
}

View file

@ -4101,197 +4101,47 @@ bool FurnaceGUI::loop() {
openFileDialog(GUI_FILE_SAVE_DMF_LEGACY); openFileDialog(GUI_FILE_SAVE_DMF_LEGACY);
} }
ImGui::Separator(); ImGui::Separator();
if (ImGui::BeginMenu("export audio...")) { if (settings.exportOptionsLayout) {
exitDisabledTimer=1; if (ImGui::BeginMenu("export audio...")) {
if (ImGui::MenuItem("one file")) { drawExportAudio();
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE); ImGui::EndMenu();
} }
if (ImGui::MenuItem("multiple files (one per chip)")) { if (ImGui::BeginMenu("export VGM...")) {
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS); drawExportVGM();
ImGui::EndMenu();
} }
if (ImGui::MenuItem("multiple files (one per channel)")) { int numZSMCompat=0;
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_CHANNEL);
}
if (ImGui::InputInt("Loops",&exportLoops,1,2)) {
if (exportLoops<0) exportLoops=0;
}
if (ImGui::InputDouble("Fade out (seconds)",&exportFadeOut,1.0,2.0,"%.1f")) {
if (exportFadeOut<0.0) exportFadeOut=0.0;
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("export VGM...")) {
exitDisabledTimer=1;
ImGui::Text("settings:");
if (ImGui::BeginCombo("format version",fmt::sprintf("%d.%.2x",vgmExportVersion>>8,vgmExportVersion&0xff).c_str())) {
for (int i=0; i<7; i++) {
if (ImGui::Selectable(fmt::sprintf("%d.%.2x",vgmVersions[i]>>8,vgmVersions[i]&0xff).c_str(),vgmExportVersion==vgmVersions[i])) {
vgmExportVersion=vgmVersions[i];
}
}
ImGui::EndCombo();
}
ImGui::Checkbox("loop",&vgmExportLoop);
if (vgmExportLoop && e->song.loopModality==2) {
ImGui::Text("loop trail:");
ImGui::Indent();
if (ImGui::RadioButton("auto-detect",vgmExportTrailingTicks==-1)) {
vgmExportTrailingTicks=-1;
}
if (ImGui::RadioButton("add one loop",vgmExportTrailingTicks==-2)) {
vgmExportTrailingTicks=-2;
}
if (ImGui::RadioButton("custom",vgmExportTrailingTicks>=0)) {
vgmExportTrailingTicks=0;
}
if (vgmExportTrailingTicks>=0) {
ImGui::SameLine();
if (ImGui::InputInt("##TrailTicks",&vgmExportTrailingTicks,1,100)) {
if (vgmExportTrailingTicks<0) vgmExportTrailingTicks=0;
}
}
ImGui::Unindent();
}
ImGui::Checkbox("add pattern change hints",&vgmExportPatternHints);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(
"inserts data blocks on pattern changes.\n"
"useful if you are writing a playback routine.\n\n"
"the format of a pattern change data block is:\n"
"67 66 FE ll ll ll ll 01 oo rr pp pp pp ...\n"
"- ll: length, a 32-bit little-endian number\n"
"- oo: order\n"
"- rr: initial row (a 0Dxx effect is able to select a different row)\n"
"- pp: pattern index (one per channel)\n\n"
"pattern indexes are ordered as they appear in the song."
);
}
ImGui::Checkbox("direct stream mode",&vgmExportDirectStream);
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip(
"required for DualPCM and MSM6258 export.\n\n"
"allows for volume/direction changes when playing samples,\n"
"at the cost of a massive increase in file size."
);
}
ImGui::Text("chips to export:");
bool hasOneAtLeast=false;
for (int i=0; i<e->song.systemLen; i++) { for (int i=0; i<e->song.systemLen; i++) {
int minVersion=e->minVGMVersion(e->song.system[i]); if ((e->song.system[i]==DIV_SYSTEM_VERA) || (e->song.system[i]==DIV_SYSTEM_YM2151)) numZSMCompat++;
ImGui::BeginDisabled(minVersion>vgmExportVersion || minVersion==0); }
ImGui::Checkbox(fmt::sprintf("%d. %s##_SYSV%d",i+1,getSystemName(e->song.system[i]),i).c_str(),&willExport[i]); if (numZSMCompat > 0) {
ImGui::EndDisabled(); if (ImGui::BeginMenu("export ZSM...")) {
if (minVersion>vgmExportVersion) { drawExportZSM();
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { ImGui::EndMenu();
ImGui::SetTooltip("this chip is only available in VGM %d.%.2x and higher!",minVersion>>8,minVersion&0xff);
}
} else if (minVersion==0) {
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
ImGui::SetTooltip("this chip is not supported by the VGM format!");
}
} else {
if (willExport[i]) hasOneAtLeast=true;
} }
} }
ImGui::Text("select the chip you wish to export,"); int numAmiga=0;
ImGui::Text("but only up to %d of each type.",(vgmExportVersion>=0x151)?2:1); for (int i=0; i<e->song.systemLen; i++) {
if (hasOneAtLeast) { if (e->song.system[i]==DIV_SYSTEM_AMIGA) numAmiga++;
if (ImGui::MenuItem("click to export")) {
openFileDialog(GUI_FILE_EXPORT_VGM);
}
} else {
ImGui::Text("nothing to export");
} }
ImGui::EndMenu(); if (numAmiga && settings.iCannotWait) {
} if (ImGui::BeginMenu("export Amiga validation data...")) {
int numZSMCompat=0; drawExportAmigaVal();
for (int i=0; i<e->song.systemLen; i++) { ImGui::EndMenu();
if ((e->song.system[i] == DIV_SYSTEM_VERA) || (e->song.system[i] == DIV_SYSTEM_YM2151)) numZSMCompat++;
}
if (numZSMCompat > 0) {
if (ImGui::BeginMenu("export ZSM...")) {
exitDisabledTimer=1;
ImGui::Text("Commander X16 Zsound Music File");
if (ImGui::InputInt("Tick Rate (Hz)",&zsmExportTickRate,1,10)) {
if (zsmExportTickRate<1) zsmExportTickRate=1;
if (zsmExportTickRate>44100) zsmExportTickRate=44100;
}
ImGui::Checkbox("loop",&zsmExportLoop);
ImGui::SameLine();
ImGui::Checkbox("optimize size",&zsmExportOptimize);
ImGui::SameLine();
if (ImGui::Button("Begin Export")) {
openFileDialog(GUI_FILE_EXPORT_ZSM);
ImGui::CloseCurrentPopup();
} }
}
if (ImGui::BeginMenu("export text...")) {
drawExportText();
ImGui::EndMenu(); ImGui::EndMenu();
} }
} if (ImGui::BeginMenu("export command stream...")) {
int numAmiga=0; drawExportCommand();
for (int i=0; i<e->song.systemLen; i++) {
if (e->song.system[i]==DIV_SYSTEM_AMIGA) numAmiga++;
}
if (numAmiga && settings.iCannotWait) {
if (ImGui::BeginMenu("export Amiga validation data...")) {
exitDisabledTimer=1;
ImGui::Text(
"this is NOT ROM export! only use for making sure the\n"
"Furnace Amiga emulator is working properly by\n"
"comparing it with real Amiga output."
);
ImGui::AlignTextToFramePadding();
ImGui::Text("Directory");
ImGui::SameLine();
ImGui::InputText("##AVDPath",&workingDirROMExport);
if (ImGui::Button("Bake Data")) {
std::vector<DivROMExportOutput> out=e->buildROM(DIV_ROM_AMIGA_VALIDATION);
if (workingDirROMExport.size()>0) {
if (workingDirROMExport[workingDirROMExport.size()-1]!=DIR_SEPARATOR) workingDirROMExport+=DIR_SEPARATOR_STR;
}
for (DivROMExportOutput& i: out) {
String path=workingDirROMExport+i.name;
FILE* outFile=ps_fopen(path.c_str(),"wb");
if (outFile!=NULL) {
fwrite(i.data->getFinalBuf(),1,i.data->size(),outFile);
fclose(outFile);
}
i.data->finish();
delete i.data;
}
showError(fmt::sprintf("Done! Baked %d files.",(int)out.size()));
ImGui::CloseCurrentPopup();
}
ImGui::EndMenu(); ImGui::EndMenu();
} }
} } else {
if (ImGui::BeginMenu("export text...")) { if (ImGui::MenuItem("export...",BIND_FOR(GUI_ACTION_EXPORT))) {
exitDisabledTimer=1; displayExport=true;
ImGui::Text(
"this option exports the song to a text file.\n"
);
if (ImGui::Button("export")) {
openFileDialog(GUI_FILE_EXPORT_TEXT);
} }
ImGui::EndMenu();
}
if (ImGui::BeginMenu("export command stream...")) {
exitDisabledTimer=1;
ImGui::Text(
"this option exports a text or binary file which\n"
"contains a dump of the internal command stream\n"
"produced when playing the song.\n\n"
"technical/development use only!"
);
if (ImGui::Button("export (binary)")) {
openFileDialog(GUI_FILE_EXPORT_CMDSTREAM_BINARY);
}
if (ImGui::Button("export (text)")) {
openFileDialog(GUI_FILE_EXPORT_CMDSTREAM);
}
ImGui::EndMenu();
} }
ImGui::Separator(); ImGui::Separator();
if (!settings.classicChipOptions) { if (!settings.classicChipOptions) {
@ -5487,6 +5337,11 @@ bool FurnaceGUI::loop() {
} }
} }
if (displayExport) {
displayExport=false;
ImGui::OpenPopup("Export");
}
if (displayEditString) { if (displayEditString) {
ImGui::OpenPopup("EditString"); ImGui::OpenPopup("EditString");
} }
@ -5528,6 +5383,15 @@ bool FurnaceGUI::loop() {
ImGui::EndPopup(); ImGui::EndPopup();
} }
if (ImGui::BeginPopupModal("Export",NULL,ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar)) {
ImGui::SetWindowPos(ImVec2(((canvasW)-ImGui::GetWindowSize().x)*0.5,((canvasH)-ImGui::GetWindowSize().y)*0.5));
if (ImGui::GetWindowSize().x<newSongMinSize.x || ImGui::GetWindowSize().y<newSongMinSize.y) {
ImGui::SetWindowSize(newSongMinSize,ImGuiCond_Always);
}
drawExport();
ImGui::EndPopup();
}
centerNextWindow("Error",canvasW,canvasH); centerNextWindow("Error",canvasW,canvasH);
if (ImGui::BeginPopupModal("Error",NULL,ImGuiWindowFlags_AlwaysAutoResize)) { if (ImGui::BeginPopupModal("Error",NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("%s",errorString.c_str()); ImGui::Text("%s",errorString.c_str());
@ -7729,7 +7593,8 @@ FurnaceGUI::FurnaceGUI():
introSkipDo(false), introSkipDo(false),
introStopped(false), introStopped(false),
curTutorial(-1), curTutorial(-1),
curTutorialStep(0) { curTutorialStep(0),
audioExportType(0) {
// value keys // value keys
valueKeys[SDLK_0]=0; valueKeys[SDLK_0]=0;
valueKeys[SDLK_1]=1; valueKeys[SDLK_1]=1;

View file

@ -562,6 +562,7 @@ enum FurnaceGUIActions {
GUI_ACTION_OPEN_BACKUP, GUI_ACTION_OPEN_BACKUP,
GUI_ACTION_SAVE, GUI_ACTION_SAVE,
GUI_ACTION_SAVE_AS, GUI_ACTION_SAVE_AS,
GUI_ACTION_EXPORT,
GUI_ACTION_UNDO, GUI_ACTION_UNDO,
GUI_ACTION_REDO, GUI_ACTION_REDO,
GUI_ACTION_PLAY_TOGGLE, GUI_ACTION_PLAY_TOGGLE,
@ -1433,7 +1434,7 @@ class FurnaceGUI {
bool vgmExportDirectStream, displayInsTypeList, displayWaveSizeList; bool vgmExportDirectStream, displayInsTypeList, displayWaveSizeList;
bool portrait, injectBackUp, mobileMenuOpen, warnColorPushed; bool portrait, injectBackUp, mobileMenuOpen, warnColorPushed;
bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu; bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu;
bool displayNew, fullScreen, preserveChanPos, wantScrollList, noteInputPoly, notifyWaveChange; bool displayNew, displayExport, fullScreen, preserveChanPos, wantScrollList, noteInputPoly, notifyWaveChange;
bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString; bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString;
bool mobileEdit; bool mobileEdit;
bool killGraphics; bool killGraphics;
@ -1688,6 +1689,7 @@ class FurnaceGUI {
int centerPopup; int centerPopup;
int insIconsStyle; int insIconsStyle;
int classicChipOptions; int classicChipOptions;
int exportOptionsLayout;
int wasapiEx; int wasapiEx;
int chanOscThreads; int chanOscThreads;
int renderPoolThreads; int renderPoolThreads;
@ -1884,6 +1886,7 @@ class FurnaceGUI {
centerPopup(1), centerPopup(1),
insIconsStyle(1), insIconsStyle(1),
classicChipOptions(0), classicChipOptions(0),
exportOptionsLayout(1),
wasapiEx(0), wasapiEx(0),
chanOscThreads(0), chanOscThreads(0),
renderPoolThreads(0), renderPoolThreads(0),
@ -2331,6 +2334,16 @@ class FurnaceGUI {
// tutorial // tutorial
int curTutorial, curTutorialStep; int curTutorial, curTutorialStep;
// audio export types (export options)
int audioExportType;
void drawExportAudio();
void drawExportVGM();
void drawExportZSM();
void drawExportAmigaVal();
void drawExportText();
void drawExportCommand();
void drawSSGEnv(unsigned char type, const ImVec2& size); void drawSSGEnv(unsigned char type, const ImVec2& size);
void drawWaveform(unsigned char type, bool opz, const ImVec2& size); void drawWaveform(unsigned char type, bool opz, const ImVec2& size);
void drawAlgorithm(unsigned char alg, FurnaceGUIFMAlgs algType, const ImVec2& size); void drawAlgorithm(unsigned char alg, FurnaceGUIFMAlgs algType, const ImVec2& size);
@ -2442,6 +2455,7 @@ class FurnaceGUI {
void drawSettings(); void drawSettings();
void drawDebug(); void drawDebug();
void drawNewSong(); void drawNewSong();
void drawExport();
void drawLog(); void drawLog();
void drawEffectList(); void drawEffectList();
void drawSubSongs(bool asChild=false); void drawSubSongs(bool asChild=false);

View file

@ -537,6 +537,7 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={
D("OPEN_BACKUP", "Restore backup", 0), D("OPEN_BACKUP", "Restore backup", 0),
D("SAVE", "Save file", FURKMOD_CMD|SDLK_s), D("SAVE", "Save file", FURKMOD_CMD|SDLK_s),
D("SAVE_AS", "Save as", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_s), D("SAVE_AS", "Save as", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_s),
D("EXPORT", "Export", FURKMOD_CMD|SDLK_e),
D("UNDO", "Undo", FURKMOD_CMD|SDLK_z), D("UNDO", "Undo", FURKMOD_CMD|SDLK_z),
#ifdef __APPLE__ #ifdef __APPLE__
D("REDO", "Redo", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_z), D("REDO", "Redo", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_z),

View file

@ -1672,6 +1672,7 @@ void FurnaceGUI::drawSettings() {
UI_KEYBIND_CONFIG(GUI_ACTION_OPEN_BACKUP); UI_KEYBIND_CONFIG(GUI_ACTION_OPEN_BACKUP);
UI_KEYBIND_CONFIG(GUI_ACTION_SAVE); UI_KEYBIND_CONFIG(GUI_ACTION_SAVE);
UI_KEYBIND_CONFIG(GUI_ACTION_SAVE_AS); UI_KEYBIND_CONFIG(GUI_ACTION_SAVE_AS);
UI_KEYBIND_CONFIG(GUI_ACTION_EXPORT);
UI_KEYBIND_CONFIG(GUI_ACTION_UNDO); UI_KEYBIND_CONFIG(GUI_ACTION_UNDO);
UI_KEYBIND_CONFIG(GUI_ACTION_REDO); UI_KEYBIND_CONFIG(GUI_ACTION_REDO);
UI_KEYBIND_CONFIG(GUI_ACTION_PLAY_TOGGLE); UI_KEYBIND_CONFIG(GUI_ACTION_PLAY_TOGGLE);
@ -2659,6 +2660,20 @@ void FurnaceGUI::drawSettings() {
} }
ImGui::Unindent(); ImGui::Unindent();
ImGui::Text("Export options layout:");
if (ImGui::RadioButton("Sub-menus in File menu##eol0",settings.exportOptionsLayout==0)) {
settings.exportOptionsLayout=0;
settingsChanged=true;
}
if (ImGui::RadioButton("Modal window with tabs##eol1",settings.exportOptionsLayout==1)) {
settings.exportOptionsLayout=1;
settingsChanged=true;
}
if (ImGui::RadioButton("Modal windows with options in File menu##eol2",settings.exportOptionsLayout==2)) {
settings.exportOptionsLayout=2;
settingsChanged=true;
}
bool capitalMenuBarB=settings.capitalMenuBar; bool capitalMenuBarB=settings.capitalMenuBar;
if (ImGui::Checkbox("Capitalize menu bar",&capitalMenuBarB)) { if (ImGui::Checkbox("Capitalize menu bar",&capitalMenuBarB)) {
settings.capitalMenuBar=capitalMenuBarB; settings.capitalMenuBar=capitalMenuBarB;
@ -3866,6 +3881,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
settings.centerPopup=conf.getInt("centerPopup",1); settings.centerPopup=conf.getInt("centerPopup",1);
settings.insIconsStyle=conf.getInt("insIconsStyle",1); settings.insIconsStyle=conf.getInt("insIconsStyle",1);
settings.classicChipOptions=conf.getInt("classicChipOptions",0); settings.classicChipOptions=conf.getInt("classicChipOptions",0);
settings.exportOptionsLayout=conf.getInt("exportOptionsLayout",1);
settings.wasapiEx=conf.getInt("wasapiEx",0); settings.wasapiEx=conf.getInt("wasapiEx",0);
settings.chanOscThreads=conf.getInt("chanOscThreads",0); settings.chanOscThreads=conf.getInt("chanOscThreads",0);
settings.renderPoolThreads=conf.getInt("renderPoolThreads",0); settings.renderPoolThreads=conf.getInt("renderPoolThreads",0);
@ -4034,6 +4050,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
clampSetting(settings.centerPopup,0,1); clampSetting(settings.centerPopup,0,1);
clampSetting(settings.insIconsStyle,0,2); clampSetting(settings.insIconsStyle,0,2);
clampSetting(settings.classicChipOptions,0,1); clampSetting(settings.classicChipOptions,0,1);
clampSetting(settings.exportOptionsLayout,0,2);
clampSetting(settings.wasapiEx,0,1); clampSetting(settings.wasapiEx,0,1);
clampSetting(settings.chanOscThreads,0,256); clampSetting(settings.chanOscThreads,0,256);
clampSetting(settings.renderPoolThreads,0,DIV_MAX_CHIPS); clampSetting(settings.renderPoolThreads,0,DIV_MAX_CHIPS);
@ -4283,6 +4300,7 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
conf.set("centerPopup",settings.centerPopup); conf.set("centerPopup",settings.centerPopup);
conf.set("insIconsStyle",settings.insIconsStyle); conf.set("insIconsStyle",settings.insIconsStyle);
conf.set("classicChipOptions",settings.classicChipOptions); conf.set("classicChipOptions",settings.classicChipOptions);
conf.set("exportOptionsLayout",settings.exportOptionsLayout);
conf.set("wasapiEx",settings.wasapiEx); conf.set("wasapiEx",settings.wasapiEx);
conf.set("chanOscThreads",settings.chanOscThreads); conf.set("chanOscThreads",settings.chanOscThreads);
conf.set("renderPoolThreads",settings.renderPoolThreads); conf.set("renderPoolThreads",settings.renderPoolThreads);