Merge branch 'master' of https://github.com/tildearrow/furnace into command-palette

This commit is contained in:
YohananDiamond 2023-12-27 20:57:24 -03:00
commit 34e18fffad
15 changed files with 1374 additions and 762 deletions

View file

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

View file

@ -1,15 +1,12 @@
# to-do
- add cheat code to insert bruno time (blank)
# THE REAL TO-DO LIST
- finish color import improvements (settings refactor)
- new undo stuff
- fix some bugs
- finish auto-clone
once you have done all of this (maybe not the first one), release 0.6.1
Furnace is like alcohol...
# and then
- new oscilloscope renderer - custom code that uses texture and fixes two issues: too many vertices, and broken anti-aliasing

View file

@ -498,7 +498,7 @@ below all the binds, select a key from the dropdown list to add it. it will appe
- **Rounded window corners**
- **Rounded buttons**
- **Rounded menu corners**
- **Borders around widgets**: draws thin borders on buttons, checkboxes, text widgets, and the like.
- **Borders around widgets**: draws borders on buttons, checkboxes, text widgets, and the like.
@ -509,6 +509,7 @@ below all the binds, select a key from the dropdown list to add it. it will appe
- **Import**
- **Export**
- **Reset defaults**
- **Guru mode**: exposes all color options (instead of accent colors).
- **General**
- **Color scheme type:**
- **Dark**

View file

@ -167,4 +167,8 @@ void DivEngine::setConf(String key, String value) {
bool DivEngine::hasConf(String key) {
return conf.has(key);
}
}
DivConfig& DivEngine::getConfObject() {
return conf;
}

View file

@ -54,8 +54,8 @@ class DivWorkPool;
#define DIV_UNSTABLE
#define DIV_VERSION "dev189"
#define DIV_ENGINE_VERSION 189
#define DIV_VERSION "dev190"
#define DIV_ENGINE_VERSION 190
// for imports
#define DIV_VERSION_MOD 0xff01
#define DIV_VERSION_FC 0xff02
@ -702,6 +702,9 @@ class DivEngine {
double getConfDouble(String key, double fallback);
String getConfString(String key, String fallback);
// get config object
DivConfig& getConfObject();
// set a config value
void setConf(String key, bool value);
void setConf(String key, int value);

View file

@ -6492,7 +6492,7 @@ SafeWriter* DivEngine::saveText(bool separatePatterns) {
if (ins->type==DIV_INS_GB) {
w->writeText("- Game Boy parameters:\n");
w->writeText(fmt::sprintf(" - volume: %d\n",ins->gb.envVol));
w->writeText(fmt::sprintf(" - direction: %d\n",gbEnvDir[ins->gb.envDir?1:0]));
w->writeText(fmt::sprintf(" - direction: %s\n",gbEnvDir[ins->gb.envDir?1:0]));
w->writeText(fmt::sprintf(" - length: %d\n",ins->gb.envLen));
w->writeText(fmt::sprintf(" - sound length: %d\n",ins->gb.soundLen));
w->writeText(fmt::sprintf(" - use software envelope: %s\n",trueFalse[ins->gb.softEnv?1:0]));

View file

@ -199,7 +199,7 @@ void DivPlatformNamcoWSG::tick(bool sysTick) {
for (int i=0; i<chans; i++) {
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=((chan[i].vol&15)*MIN(15,chan[i].std.vol.val))>>4;
chan[i].outVol=VOL_SCALE_LINEAR(chan[i].vol,chan[i].std.vol.val,15);
}
if (chan[i].std.duty.had) {
chan[i].noise=chan[i].std.duty.val;

View file

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

View file

@ -519,24 +519,8 @@ void FurnaceGUI::drawMobileControls() {
openFileDialog(GUI_FILE_SAVE_DMF_LEGACY);
}
ImGui::SameLine();
if (ImGui::Button("Export Audio")) {
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
}
ImGui::SameLine();
if (ImGui::Button("Export VGM")) {
openFileDialog(GUI_FILE_EXPORT_VGM);
}
if (ImGui::Button("CmdStream")) {
openFileDialog(GUI_FILE_EXPORT_CMDSTREAM_BINARY);
}
ImGui::SameLine();
if (ImGui::Button("CmdStream Text")) {
openFileDialog(GUI_FILE_EXPORT_CMDSTREAM);
}
ImGui::SameLine();
if (ImGui::Button("Text")) {
openFileDialog(GUI_FILE_EXPORT_TEXT);
if (ImGui::Button("Export")) {
doAction(GUI_ACTION_EXPORT);
}
if (ImGui::Button("Restore Backup")) {

View file

@ -771,10 +771,10 @@ unsigned int convertEffectMPT_S3M(unsigned char symbol, unsigned int val) {
return (0x80<<8)|((val&0xf)<<4);
break;
case 0xC:
return (0xFC<<8)|(val&0xf);
return (0xEC<<8)|(val&0xf);
break;
case 0xD:
return (0xFD<<8)|(val&0xf);
return (0xED<<8)|(val&0xf);
break;
default:
break;
@ -1117,7 +1117,7 @@ void FurnaceGUI::doPasteMPT(PasteMode mode, int arg, bool readClipboard, String
if (invalidData)
{
logW("invalid OpenMPT clipboard data! failed at line %d char %d",i,charPos);
logW("invalid clipboard data! failed at line %d char %d",i,charPos);
logW("%s",line.c_str());
break;
}

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

@ -0,0 +1,357 @@
/**
* 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"
#include <imgui.h>
void FurnaceGUI::drawExportAudio(bool onWindow) {
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 (onWindow) {
ImGui::Separator();
if (ImGui::Button("Cancel",ImVec2(200.0f*dpiScale,0))) ImGui::CloseCurrentPopup();
ImGui::SameLine();
}
if (ImGui::Button("Export",ImVec2(200.0f*dpiScale,0))) {
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(bool onWindow) {
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 (onWindow) {
ImGui::Separator();
if (ImGui::Button("Cancel",ImVec2(200.0f*dpiScale,0))) ImGui::CloseCurrentPopup();
ImGui::SameLine();
}
if (ImGui::Button("Export",ImVec2(200.0f*dpiScale,0))) {
openFileDialog(GUI_FILE_EXPORT_VGM);
ImGui::CloseCurrentPopup();
}
} else {
ImGui::Text("nothing to export");
if (onWindow) {
ImGui::Separator();
if (ImGui::Button("Cancel",ImVec2(400.0f*dpiScale,0))) ImGui::CloseCurrentPopup();
}
}
}
void FurnaceGUI::drawExportZSM(bool onWindow) {
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 (onWindow) {
ImGui::Separator();
if (ImGui::Button("Cancel",ImVec2(200.0f*dpiScale,0))) ImGui::CloseCurrentPopup();
ImGui::SameLine();
}
if (ImGui::Button("Export",ImVec2(200.0f*dpiScale,0))) {
openFileDialog(GUI_FILE_EXPORT_ZSM);
ImGui::CloseCurrentPopup();
}
}
void FurnaceGUI::drawExportAmigaVal(bool onWindow) {
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 (onWindow) {
ImGui::Separator();
if (ImGui::Button("Cancel",ImVec2(200.0f*dpiScale,0))) ImGui::CloseCurrentPopup();
ImGui::SameLine();
}
if (ImGui::Button("Bake Data",ImVec2(200.0f*dpiScale,0))) {
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(bool onWindow) {
exitDisabledTimer=1;
ImGui::Text(
"this option exports the song to a text file.\n"
);
if (onWindow) {
ImGui::Separator();
if (ImGui::Button("Cancel",ImVec2(200.0f*dpiScale,0))) ImGui::CloseCurrentPopup();
ImGui::SameLine();
}
if (ImGui::Button("Export",ImVec2(200.0f*dpiScale,0))) {
openFileDialog(GUI_FILE_EXPORT_TEXT);
ImGui::CloseCurrentPopup();
}
}
void FurnaceGUI::drawExportCommand(bool onWindow) {
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 (onWindow) {
ImGui::Separator();
if (ImGui::Button("Cancel",ImVec2(133.3f*dpiScale,0))) ImGui::CloseCurrentPopup();
ImGui::SameLine();
}
if (ImGui::Button("Export (binary)",ImVec2(133.3f*dpiScale,0))) {
openFileDialog(GUI_FILE_EXPORT_CMDSTREAM_BINARY);
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("Export (text)",ImVec2(133.3f*dpiScale,0))) {
openFileDialog(GUI_FILE_EXPORT_CMDSTREAM);
ImGui::CloseCurrentPopup();
}
}
void FurnaceGUI::drawExport() {
if (settings.exportOptionsLayout==1 || curExportType==GUI_EXPORT_NONE) {
if (ImGui::BeginTabBar("ExportTypes")) {
if (ImGui::BeginTabItem("Audio")) {
drawExportAudio(true);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("VGM")) {
drawExportVGM(true);
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(true);
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(true);
ImGui::EndTabItem();
}
}
if (ImGui::BeginTabItem("Text")) {
drawExportText(true);
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Command Stream")) {
drawExportCommand(true);
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
} else switch (curExportType) {
case GUI_EXPORT_AUDIO:
drawExportAudio(true);
break;
case GUI_EXPORT_VGM:
drawExportVGM(true);
break;
case GUI_EXPORT_ZSM:
drawExportZSM(true);
break;
case GUI_EXPORT_AMIGA_VAL:
drawExportAmigaVal(true);
break;
case GUI_EXPORT_TEXT:
drawExportText(true);
break;
case GUI_EXPORT_CMD_STREAM:
drawExportCommand(true);
break;
default:
ImGui::Text("congratulations! you've unlocked a secret panel.");
if (ImGui::Button("Toggle hidden systems")) {
settings.hiddenSystems=!settings.hiddenSystems;
ImGui::CloseCurrentPopup();
}
if (ImGui::Button("Toggle all instrument types")) {
settings.displayAllInsTypes=!settings.displayAllInsTypes;
ImGui::CloseCurrentPopup();
}
if (ImGui::Button("Set pitch linearity to Partial")) {
e->song.linearPitch=1;
ImGui::CloseCurrentPopup();
}
if (ImGui::Button("Enable multi-threading settings")) {
settings.showPool=1;
ImGui::CloseCurrentPopup();
}
if (ImGui::Button("Set fat to max")) {
ImGuiStyle& sty=ImGui::GetStyle();
sty.FramePadding=ImVec2(20.0f*dpiScale,20.0f*dpiScale);
sty.ItemSpacing=ImVec2(10.0f*dpiScale,10.0f*dpiScale);
sty.ItemInnerSpacing=ImVec2(10.0f*dpiScale,10.0f*dpiScale);
ImGui::CloseCurrentPopup();
}
if (ImGui::Button("Set muscle and fat to zero")) {
ImGuiStyle& sty=ImGui::GetStyle();
sty.FramePadding=ImVec2(0,0);
sty.ItemSpacing=ImVec2(0,0);
sty.ItemInnerSpacing=ImVec2(0,0);
ImGui::CloseCurrentPopup();
}
if (ImGui::Button("Tell tildearrow this must be a mistake")) {
showError("yeah, it's a bug. write a bug report in the GitHub page and tell me how did you get here.");
ImGui::CloseCurrentPopup();
}
break;
}
}

View file

@ -4110,197 +4110,84 @@ bool FurnaceGUI::loop() {
openFileDialog(GUI_FILE_SAVE_DMF_LEGACY);
}
ImGui::Separator();
if (ImGui::BeginMenu("export audio...")) {
exitDisabledTimer=1;
if (ImGui::MenuItem("one file")) {
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
if (settings.exportOptionsLayout==0) {
if (ImGui::BeginMenu("export audio...")) {
drawExportAudio();
ImGui::EndMenu();
}
if (ImGui::MenuItem("multiple files (one per chip)")) {
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS);
if (ImGui::BeginMenu("export VGM...")) {
drawExportVGM();
ImGui::EndMenu();
}
if (ImGui::MenuItem("multiple files (one per channel)")) {
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;
int numZSMCompat=0;
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;
if ((e->song.system[i]==DIV_SYSTEM_VERA) || (e->song.system[i]==DIV_SYSTEM_YM2151)) numZSMCompat++;
}
if (numZSMCompat>0) {
if (ImGui::BeginMenu("export ZSM...")) {
drawExportZSM();
ImGui::EndMenu();
}
}
ImGui::Text("select the chip you wish to export,");
ImGui::Text("but only up to %d of each type.",(vgmExportVersion>=0x151)?2:1);
if (hasOneAtLeast) {
if (ImGui::MenuItem("click to export")) {
openFileDialog(GUI_FILE_EXPORT_VGM);
}
} else {
ImGui::Text("nothing to export");
int numAmiga=0;
for (int i=0; i<e->song.systemLen; i++) {
if (e->song.system[i]==DIV_SYSTEM_AMIGA) numAmiga++;
}
ImGui::EndMenu();
}
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::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 (numAmiga && settings.iCannotWait) {
if (ImGui::BeginMenu("export Amiga validation data...")) {
drawExportAmigaVal();
ImGui::EndMenu();
}
}
if (ImGui::BeginMenu("export text...")) {
drawExportText();
ImGui::EndMenu();
}
}
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::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();
}
if (ImGui::BeginMenu("export command stream...")) {
drawExportCommand();
ImGui::EndMenu();
}
}
if (ImGui::BeginMenu("export text...")) {
exitDisabledTimer=1;
ImGui::Text(
"this option exports the song to a text file.\n"
);
if (ImGui::Button("export")) {
openFileDialog(GUI_FILE_EXPORT_TEXT);
} else if (settings.exportOptionsLayout==2) {
if (ImGui::MenuItem("export audio...")) {
curExportType=GUI_EXPORT_AUDIO;
displayExport=true;
}
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::MenuItem("export VGM...")) {
curExportType=GUI_EXPORT_VGM;
displayExport=true;
}
if (ImGui::Button("export (text)")) {
openFileDialog(GUI_FILE_EXPORT_CMDSTREAM);
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::MenuItem("export ZSM...")) {
curExportType=GUI_EXPORT_ZSM;
displayExport=true;
}
}
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::MenuItem("export Amiga validation data...")) {
curExportType=GUI_EXPORT_AMIGA_VAL;
displayExport=true;
}
}
if (ImGui::MenuItem("export text...")) {
curExportType=GUI_EXPORT_TEXT;
displayExport=true;
}
if (ImGui::MenuItem("export command stream...")) {
curExportType=GUI_EXPORT_CMD_STREAM;
displayExport=true;
}
} else {
if (ImGui::MenuItem("export...",BIND_FOR(GUI_ACTION_EXPORT))) {
displayExport=true;
}
ImGui::EndMenu();
}
ImGui::Separator();
if (!settings.classicChipOptions) {
@ -5507,6 +5394,11 @@ bool FurnaceGUI::loop() {
ImGui::OpenPopup("Command Palette");
}
if (displayExport) {
displayExport=false;
ImGui::OpenPopup("Export");
}
if (displayEditString) {
ImGui::OpenPopup("EditString");
}
@ -5556,6 +5448,12 @@ bool FurnaceGUI::loop() {
ImGui::EndPopup();
}
if (ImGui::BeginPopupModal("Export",NULL,ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::SetWindowPos(ImVec2(((canvasW)-ImGui::GetWindowSize().x)*0.5,((canvasH)-ImGui::GetWindowSize().y)*0.5));
drawExport();
ImGui::EndPopup();
}
centerNextWindow("Error",canvasW,canvasH);
if (ImGui::BeginPopupModal("Error",NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("%s",errorString.c_str());
@ -7760,7 +7658,9 @@ FurnaceGUI::FurnaceGUI():
introSkipDo(false),
introStopped(false),
curTutorial(-1),
curTutorialStep(0) {
curTutorialStep(0),
audioExportType(0),
curExportType(GUI_EXPORT_NONE) {
// value keys
valueKeys[SDLK_0]=0;
valueKeys[SDLK_1]=1;

View file

@ -101,6 +101,7 @@ enum FurnaceGUIColors {
GUI_COLOR_MODAL_BACKDROP,
GUI_COLOR_HEADER,
GUI_COLOR_TEXT,
GUI_COLOR_TEXT_DISABLED,
GUI_COLOR_ACCENT_PRIMARY,
GUI_COLOR_ACCENT_SECONDARY,
GUI_COLOR_TITLE_INACTIVE,
@ -124,6 +125,36 @@ enum FurnaceGUIColors {
GUI_COLOR_NAV_HIGHLIGHT,
GUI_COLOR_NAV_WIN_HIGHLIGHT,
GUI_COLOR_NAV_WIN_BACKDROP,
GUI_COLOR_PLOT_LINES,
GUI_COLOR_PLOT_LINES_HOVER,
GUI_COLOR_PLOT_HISTOGRAM,
GUI_COLOR_PLOT_HISTOGRAM_HOVER,
GUI_COLOR_BUTTON,
GUI_COLOR_BUTTON_HOVER,
GUI_COLOR_BUTTON_ACTIVE,
GUI_COLOR_TAB,
GUI_COLOR_TAB_HOVER,
GUI_COLOR_TAB_ACTIVE,
GUI_COLOR_TAB_UNFOCUSED,
GUI_COLOR_TAB_UNFOCUSED_ACTIVE,
GUI_COLOR_IMGUI_HEADER,
GUI_COLOR_IMGUI_HEADER_HOVER,
GUI_COLOR_IMGUI_HEADER_ACTIVE,
GUI_COLOR_RESIZE_GRIP,
GUI_COLOR_RESIZE_GRIP_HOVER,
GUI_COLOR_RESIZE_GRIP_ACTIVE,
GUI_COLOR_WIDGET_BACKGROUND,
GUI_COLOR_WIDGET_BACKGROUND_HOVER,
GUI_COLOR_WIDGET_BACKGROUND_ACTIVE,
GUI_COLOR_SLIDER_GRAB,
GUI_COLOR_SLIDER_GRAB_ACTIVE,
GUI_COLOR_TITLE_BACKGROUND_ACTIVE,
GUI_COLOR_CHECK_MARK,
GUI_COLOR_TEXT_SELECTION,
GUI_COLOR_TABLE_ROW_EVEN,
GUI_COLOR_TABLE_ROW_ODD,
GUI_COLOR_TOGGLE_OFF,
GUI_COLOR_TOGGLE_ON,
GUI_COLOR_EDITING,
@ -437,6 +468,21 @@ enum FurnaceGUIMobileScenes {
GUI_SCENE_OTHER,
};
enum FurnaceGUISettingGroups: unsigned int {
GUI_SETTINGS_GENERAL=1,
GUI_SETTINGS_AUDIO=2,
GUI_SETTINGS_MIDI=4,
GUI_SETTINGS_KEYBOARD=8,
GUI_SETTINGS_BEHAVIOR=16,
GUI_SETTINGS_FONT=32,
GUI_SETTINGS_APPEARANCE=64,
GUI_SETTINGS_LAYOUTS=128,
GUI_SETTINGS_COLOR=256,
GUI_SETTINGS_EMULATION=512,
GUI_SETTINGS_ALL=0xffffffff
};
enum FurnaceGUIFileDialogs {
GUI_FILE_OPEN,
GUI_FILE_OPEN_BACKUP,
@ -504,6 +550,17 @@ enum FurnaceGUIWarnings {
GUI_WARN_GENERIC
};
enum FurnaceGUIExportTypes {
GUI_EXPORT_NONE=-1,
GUI_EXPORT_AUDIO=0,
GUI_EXPORT_VGM,
GUI_EXPORT_ZSM,
GUI_EXPORT_CMD_STREAM,
GUI_EXPORT_AMIGA_VAL,
GUI_EXPORT_TEXT
};
enum FurnaceGUIFMAlgs {
FM_ALGS_4OP,
FM_ALGS_2OP_OPL,
@ -517,6 +574,7 @@ enum FurnaceGUIActions {
GUI_ACTION_OPEN_BACKUP,
GUI_ACTION_SAVE,
GUI_ACTION_SAVE_AS,
GUI_ACTION_EXPORT,
GUI_ACTION_UNDO,
GUI_ACTION_REDO,
GUI_ACTION_PLAY_TOGGLE,
@ -836,6 +894,14 @@ struct SelectionPoint {
xCoarse(0), xFine(0), y(0) {}
};
struct UndoRegion {
struct UndoRegionPoint {
int ord, x, y;
UndoRegionPoint():
ord(0), x(0), y(0) {}
} begin, end;
};
enum ActionType {
GUI_UNDO_CHANGE_ORDER,
GUI_UNDO_PATTERN_EDIT,
@ -1398,7 +1464,11 @@ class FurnaceGUI {
bool vgmExportDirectStream, displayInsTypeList, displayWaveSizeList;
bool portrait, injectBackUp, mobileMenuOpen, warnColorPushed;
bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu;
<<<<<<< HEAD
bool displayNew, displayPalette, fullScreen, preserveChanPos, wantScrollList, noteInputPoly, notifyWaveChange;
=======
bool displayNew, displayExport, fullScreen, preserveChanPos, wantScrollList, noteInputPoly, notifyWaveChange;
>>>>>>> 07b037349b2419736359f25e114e5798e17bb327
bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString;
bool mobileEdit;
bool killGraphics;
@ -1653,6 +1723,7 @@ class FurnaceGUI {
int centerPopup;
int insIconsStyle;
int classicChipOptions;
int exportOptionsLayout;
int wasapiEx;
int chanOscThreads;
int renderPoolThreads;
@ -1665,6 +1736,7 @@ class FurnaceGUI {
int fontAutoHint;
int fontAntiAlias;
int selectAssetOnLoad;
int basicColors;
unsigned int maxUndoSteps;
String mainFontPath;
String headFontPath;
@ -1848,11 +1920,12 @@ class FurnaceGUI {
centerPopup(1),
insIconsStyle(1),
classicChipOptions(0),
exportOptionsLayout(1),
wasapiEx(0),
chanOscThreads(0),
renderPoolThreads(0),
showPool(0),
writeInsNames(1),
writeInsNames(0),
readInsNames(1),
fontBackend(1),
fontHinting(0),
@ -1860,6 +1933,7 @@ class FurnaceGUI {
fontAutoHint(1),
fontAntiAlias(1),
selectAssetOnLoad(1),
basicColors(1),
maxUndoSteps(100),
mainFontPath(""),
headFontPath(""),
@ -2255,7 +2329,7 @@ class FurnaceGUI {
int pianoOffset, pianoOffsetEdit;
int pianoView, pianoInputPadMode;
//effect sorting
// effect sorting
bool effectsShow[10];
// TX81Z
@ -2295,6 +2369,17 @@ class FurnaceGUI {
// tutorial
int curTutorial, curTutorialStep;
// export options
int audioExportType;
FurnaceGUIExportTypes curExportType;
void drawExportAudio(bool onWindow=false);
void drawExportVGM(bool onWindow=false);
void drawExportZSM(bool onWindow=false);
void drawExportAmigaVal(bool onWindow=false);
void drawExportText(bool onWindow=false);
void drawExportCommand(bool onWindow=false);
void drawSSGEnv(unsigned char type, const ImVec2& size);
void drawWaveform(unsigned char type, bool opz, const ImVec2& size);
void drawAlgorithm(unsigned char alg, FurnaceGUIFMAlgs algType, const ImVec2& size);
@ -2406,7 +2491,11 @@ class FurnaceGUI {
void drawSettings();
void drawDebug();
void drawNewSong();
<<<<<<< HEAD
void drawPalette();
=======
void drawExport();
>>>>>>> 07b037349b2419736359f25e114e5798e17bb327
void drawLog();
void drawEffectList();
void drawSubSongs(bool asChild=false);
@ -2432,6 +2521,9 @@ class FurnaceGUI {
void resetColors();
void resetKeybinds();
void readConfig(DivConfig& conf, FurnaceGUISettingGroups groups=GUI_SETTINGS_ALL);
void writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups=GUI_SETTINGS_ALL);
void syncSettings();
void commitSettings();
void syncTutorial();

View file

@ -537,6 +537,7 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={
D("OPEN_BACKUP", "Restore backup", 0),
D("SAVE", "Save file", FURKMOD_CMD|SDLK_s),
D("SAVE_AS", "Save as", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_s),
D("EXPORT", "Export", 0),
D("UNDO", "Undo", FURKMOD_CMD|SDLK_z),
#ifdef __APPLE__
D("REDO", "Redo", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_z),
@ -804,6 +805,7 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={
D(GUI_COLOR_MODAL_BACKDROP,"",ImVec4(0.0f,0.0f,0.0f,0.55f)),
D(GUI_COLOR_HEADER,"",ImVec4(0.2f,0.2f,0.2f,1.0f)),
D(GUI_COLOR_TEXT,"",ImVec4(1.0f,1.0f,1.0f,1.0f)),
D(GUI_COLOR_TEXT_DISABLED,"",ImVec4(0.5f,0.5f,0.5f,1.0f)),
D(GUI_COLOR_ACCENT_PRIMARY,"",ImVec4(0.06f,0.53f,0.98f,1.0f)),
D(GUI_COLOR_ACCENT_SECONDARY,"",ImVec4(0.26f,0.59f,0.98f,1.0f)),
D(GUI_COLOR_TITLE_INACTIVE,"",ImVec4(0.04f,0.04f,0.04f,1.0f)),
@ -827,6 +829,36 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={
D(GUI_COLOR_NAV_HIGHLIGHT,"",ImVec4(0.26f,0.59f,0.98f,1.0f)),
D(GUI_COLOR_NAV_WIN_HIGHLIGHT,"",ImVec4(1.0f,1.0f,1.0f,0.7f)),
D(GUI_COLOR_NAV_WIN_BACKDROP,"",ImVec4(0.8f,0.8f,0.8f,0.2f)),
D(GUI_COLOR_PLOT_LINES,"",ImVec4(0.61f,0.61f,0.61f,1.0f)),
D(GUI_COLOR_PLOT_LINES_HOVER,"",ImVec4(1.00f,0.43f,0.35f,1.00f)),
D(GUI_COLOR_PLOT_HISTOGRAM,"",ImVec4(0.0f,0.9f,1.0f,1.0f)),
D(GUI_COLOR_PLOT_HISTOGRAM_HOVER,"",ImVec4(0.0f,0.9f,1.0f,1.0f)),
D(GUI_COLOR_BUTTON,"",ImVec4(0.085f,0.216f,0.343f,1.0f)),
D(GUI_COLOR_BUTTON_HOVER,"",ImVec4(0.075f,0.287f,0.49f,1.0f)),
D(GUI_COLOR_BUTTON_ACTIVE,"",ImVec4(0.06f,0.53f,0.98f,1.0f)),
D(GUI_COLOR_TAB,"",ImVec4(0.085f,0.216f,0.343f,1.0f)),
D(GUI_COLOR_TAB_HOVER,"",ImVec4(0.165f,0.313f,0.49f,1.0f)),
D(GUI_COLOR_TAB_ACTIVE,"",ImVec4(0.25f,0.47f,0.735f,1.0f)),
D(GUI_COLOR_TAB_UNFOCUSED,"",ImVec4(0.085f,0.216f,0.343f,1.0f)),
D(GUI_COLOR_TAB_UNFOCUSED_ACTIVE,"",ImVec4(0.075f,0.287f,0.49f,1.0f)),
D(GUI_COLOR_IMGUI_HEADER,"",ImVec4(0.083f,0.156f,0.245f,1.0f)),
D(GUI_COLOR_IMGUI_HEADER_HOVER,"",ImVec4(0.165f,0.313f,0.49f,1.0f)),
D(GUI_COLOR_IMGUI_HEADER_ACTIVE,"",ImVec4(0.26f,0.59f,0.98f,1.0f)),
D(GUI_COLOR_RESIZE_GRIP,"",ImVec4(0.083f,0.156f,0.245f,1.0f)),
D(GUI_COLOR_RESIZE_GRIP_HOVER,"",ImVec4(0.165f,0.313f,0.49f,1.0f)),
D(GUI_COLOR_RESIZE_GRIP_ACTIVE,"",ImVec4(0.26f,0.59f,0.98f,1.0f)),
D(GUI_COLOR_WIDGET_BACKGROUND,"",ImVec4(0.083f,0.156f,0.245f,1.0f)),
D(GUI_COLOR_WIDGET_BACKGROUND_HOVER,"",ImVec4(0.165f,0.313f,0.49f,1.0f)),
D(GUI_COLOR_WIDGET_BACKGROUND_ACTIVE,"",ImVec4(0.26f,0.59f,0.98f,1.0f)),
D(GUI_COLOR_SLIDER_GRAB,"",ImVec4(0.06f,0.53f,0.98f,1.0f)),
D(GUI_COLOR_SLIDER_GRAB_ACTIVE,"",ImVec4(0.06f,0.53f,0.98f,1.0f)),
D(GUI_COLOR_TITLE_BACKGROUND_ACTIVE,"",ImVec4(0.085f,0.216f,0.343f,1.0f)),
D(GUI_COLOR_CHECK_MARK,"",ImVec4(0.06f,0.53f,0.98f,1.0f)),
D(GUI_COLOR_TEXT_SELECTION,"",ImVec4(0.165f,0.313f,0.49f,1.0f)),
D(GUI_COLOR_TABLE_ROW_EVEN,"",ImVec4(0.0f,0.0f,0.0f,0.0f)),
D(GUI_COLOR_TABLE_ROW_ODD,"",ImVec4(1.0f,1.0f,1.0f,0.06f)),
D(GUI_COLOR_TOGGLE_OFF,"",ImVec4(0.2f,0.2f,0.2f,1.0f)),
D(GUI_COLOR_TOGGLE_ON,"",ImVec4(0.2f,0.6f,0.2f,1.0f)),
D(GUI_COLOR_EDITING,"",ImVec4(0.2f,0.1f,0.1f,1.0f)),

File diff suppressed because it is too large Load diff