diff --git a/CMakeLists.txt b/CMakeLists.txt index 80e2c2fd..458cd448 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -613,6 +613,7 @@ src/gui/scaling.cpp src/gui/settings.cpp src/gui/songInfo.cpp src/gui/songNotes.cpp +src/gui/speed.cpp src/gui/spoiler.cpp src/gui/stats.cpp src/gui/subSongs.cpp diff --git a/src/gui/doAction.cpp b/src/gui/doAction.cpp index b9bb5841..60511f09 100644 --- a/src/gui/doAction.cpp +++ b/src/gui/doAction.cpp @@ -193,6 +193,9 @@ void FurnaceGUI::doAction(int what) { case GUI_ACTION_WINDOW_SONG_INFO: nextWindow=GUI_WINDOW_SONG_INFO; break; + case GUI_ACTION_WINDOW_SPEED: + nextWindow=GUI_WINDOW_SPEED; + break; case GUI_ACTION_WINDOW_PATTERN: nextWindow=GUI_WINDOW_PATTERN; break; @@ -274,6 +277,9 @@ void FurnaceGUI::doAction(int what) { case GUI_WINDOW_SONG_INFO: songInfoOpen=false; break; + case GUI_WINDOW_SPEED: + speedOpen=false; + break; case GUI_WINDOW_ORDERS: ordersOpen=false; break; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index ed21ad99..67df8c87 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -3729,6 +3729,7 @@ bool FurnaceGUI::loop() { if (ImGui::BeginMenu("window")) { if (ImGui::MenuItem("song information",BIND_FOR(GUI_ACTION_WINDOW_SONG_INFO),songInfoOpen)) songInfoOpen=!songInfoOpen; if (ImGui::MenuItem("subsongs",BIND_FOR(GUI_ACTION_WINDOW_SUBSONGS),subSongsOpen)) subSongsOpen=!subSongsOpen; + if (ImGui::MenuItem("speed",BIND_FOR(GUI_ACTION_WINDOW_SPEED),speedOpen)) speedOpen=!speedOpen; if (settings.unifiedDataView) { if (ImGui::MenuItem("assets",BIND_FOR(GUI_ACTION_WINDOW_INS_LIST),insListOpen)) insListOpen=!insListOpen; } else { @@ -3915,6 +3916,7 @@ bool FurnaceGUI::loop() { drawSpoiler(); drawPattern(); drawEditControls(); + drawSpeed(); drawSongInfo(); drawOrders(); drawSampleList(); @@ -5245,6 +5247,7 @@ bool FurnaceGUI::init() { patManagerOpen=e->getConfBool("patManagerOpen",false); sysManagerOpen=e->getConfBool("sysManagerOpen",false); clockOpen=e->getConfBool("clockOpen",false); + speedOpen=e->getConfBool("speedOpen",true); regViewOpen=e->getConfBool("regViewOpen",false); logOpen=e->getConfBool("logOpen",false); effectListOpen=e->getConfBool("effectListOpen",false); @@ -5619,6 +5622,7 @@ void FurnaceGUI::commitState() { e->setConf("patManagerOpen",patManagerOpen); e->setConf("sysManagerOpen",sysManagerOpen); e->setConf("clockOpen",clockOpen); + e->setConf("speedOpen",speedOpen); e->setConf("regViewOpen",regViewOpen); e->setConf("logOpen",logOpen); e->setConf("effectListOpen",effectListOpen); @@ -5865,6 +5869,7 @@ FurnaceGUI::FurnaceGUI(): patManagerOpen(false), sysManagerOpen(false), clockOpen(false), + speedOpen(true), clockShowReal(true), clockShowRow(true), clockShowBeat(true), diff --git a/src/gui/gui.h b/src/gui/gui.h index 1b53be44..440581a7 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -292,6 +292,7 @@ enum FurnaceGUIWindows { GUI_WINDOW_NOTHING=0, GUI_WINDOW_EDIT_CONTROLS, GUI_WINDOW_SONG_INFO, + GUI_WINDOW_SPEED, GUI_WINDOW_ORDERS, GUI_WINDOW_INS_LIST, GUI_WINDOW_PATTERN, @@ -439,6 +440,7 @@ enum FurnaceGUIActions { GUI_ACTION_WINDOW_INS_LIST, GUI_ACTION_WINDOW_INS_EDIT, GUI_ACTION_WINDOW_SONG_INFO, + GUI_ACTION_WINDOW_SPEED, GUI_ACTION_WINDOW_PATTERN, GUI_ACTION_WINDOW_WAVE_LIST, GUI_ACTION_WINDOW_WAVE_EDIT, @@ -1462,7 +1464,7 @@ class FurnaceGUI { bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen; bool mixerOpen, debugOpen, inspectorOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen; bool pianoOpen, notesOpen, channelsOpen, regViewOpen, logOpen, effectListOpen, chanOscOpen; - bool subSongsOpen, findOpen, spoilerOpen, patManagerOpen, sysManagerOpen, clockOpen; + bool subSongsOpen, findOpen, spoilerOpen, patManagerOpen, sysManagerOpen, clockOpen, speedOpen; bool clockShowReal, clockShowRow, clockShowBeat, clockShowMetro, clockShowTime; float clockMetroTick[16]; @@ -1818,6 +1820,7 @@ class FurnaceGUI { void drawMobileOrderSel(); void drawEditControls(); void drawSongInfo(bool asChild=false); + void drawSpeed(bool asChild=false); void drawOrders(); void drawPattern(); void drawInsList(bool asChild=false); diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index d3129170..2ffdbbbc 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -494,6 +494,7 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={ D("WINDOW_INS_LIST", "Instrument List", 0), D("WINDOW_INS_EDIT", "Instrument Editor", 0), D("WINDOW_SONG_INFO", "Song Information", 0), + D("WINDOW_SPEED", "Speed", 0), D("WINDOW_PATTERN", "Pattern", 0), D("WINDOW_WAVE_LIST", "Wavetable List", 0), D("WINDOW_WAVE_EDIT", "Wavetable Editor", 0), diff --git a/src/gui/songInfo.cpp b/src/gui/songInfo.cpp index fc25d63e..6a04b778 100644 --- a/src/gui/songInfo.cpp +++ b/src/gui/songInfo.cpp @@ -100,138 +100,16 @@ void FurnaceGUI::drawSongInfo(bool asChild) { ImGui::EndTable(); } - if (ImGui::BeginTable("OtherProps",3,ImGuiTableFlags_SizingStretchProp)) { + if (ImGui::BeginTable("OtherProps",2,ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,0.0); ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0); - ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.0); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("TimeBase"); - ImGui::TableNextColumn(); - float avail=ImGui::GetContentRegionAvail().x; - ImGui::SetNextItemWidth(avail); - unsigned char realTB=e->curSubSong->timeBase+1; - if (ImGui::InputScalar("##TimeBase",ImGuiDataType_U8,&realTB,&_ONE,&_THREE)) { MARK_MODIFIED - if (realTB<1) realTB=1; - if (realTB>16) realTB=16; - e->curSubSong->timeBase=realTB-1; - } - ImGui::TableNextColumn(); - ImGui::Text("%.2f BPM",calcBPM(e->curSubSong->speed1,e->curSubSong->speed2,e->curSubSong->hz,e->curSubSong->virtualTempoN,e->curSubSong->virtualTempoD)); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Speed"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(avail); - if (ImGui::InputScalar("##Speed1",ImGuiDataType_U8,&e->curSubSong->speed1,&_ONE,&_THREE)) { MARK_MODIFIED - if (e->curSubSong->speed1<1) e->curSubSong->speed1=1; - if (e->isPlaying()) play(); - } - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(avail); - if (ImGui::InputScalar("##Speed2",ImGuiDataType_U8,&e->curSubSong->speed2,&_ONE,&_THREE)) { MARK_MODIFIED - if (e->curSubSong->speed2<1) e->curSubSong->speed2=1; - if (e->isPlaying()) play(); - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Virtual Tempo"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(avail); - if (ImGui::InputScalar("##VTempoN",ImGuiDataType_S16,&e->curSubSong->virtualTempoN,&_ONE,&_THREE)) { MARK_MODIFIED - if (e->curSubSong->virtualTempoN<1) e->curSubSong->virtualTempoN=1; - if (e->curSubSong->virtualTempoN>255) e->curSubSong->virtualTempoN=255; - } - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Numerator"); - } - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(avail); - if (ImGui::InputScalar("##VTempoD",ImGuiDataType_S16,&e->curSubSong->virtualTempoD,&_ONE,&_THREE)) { MARK_MODIFIED - if (e->curSubSong->virtualTempoD<1) e->curSubSong->virtualTempoD=1; - if (e->curSubSong->virtualTempoD>255) e->curSubSong->virtualTempoD=255; - } - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("Denominator (set to base tempo)"); - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Highlight"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(avail); - if (ImGui::InputScalar("##Highlight1",ImGuiDataType_U8,&e->curSubSong->hilightA,&_ONE,&_THREE)) { - MARK_MODIFIED; - } - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(avail); - if (ImGui::InputScalar("##Highlight2",ImGuiDataType_U8,&e->curSubSong->hilightB,&_ONE,&_THREE)) { - MARK_MODIFIED; - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Pattern Length"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(avail); - int patLen=e->curSubSong->patLen; - if (ImGui::InputInt("##PatLength",&patLen,1,3)) { MARK_MODIFIED - if (patLen<1) patLen=1; - if (patLen>DIV_MAX_PATTERNS) patLen=DIV_MAX_PATTERNS; - e->curSubSong->patLen=patLen; - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("Song Length"); - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(avail); - int ordLen=e->curSubSong->ordersLen; - if (ImGui::InputInt("##OrdLength",&ordLen,1,3)) { MARK_MODIFIED - if (ordLen<1) ordLen=1; - if (ordLen>DIV_MAX_PATTERNS) ordLen=DIV_MAX_PATTERNS; - e->curSubSong->ordersLen=ordLen; - if (curOrder>=ordLen) { - setOrder(ordLen-1); - } - } - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - if (ImGui::Selectable(tempoView?"Base Tempo##TempoOrHz":"Tick Rate##TempoOrHz")) { - tempoView=!tempoView; - } - ImGui::TableNextColumn(); - ImGui::SetNextItemWidth(avail); - float setHz=tempoView?e->curSubSong->hz*2.5:e->curSubSong->hz; - if (ImGui::InputFloat("##Rate",&setHz,1.0f,1.0f,"%g")) { MARK_MODIFIED - if (tempoView) setHz/=2.5; - if (setHz<1) setHz=1; - if (setHz>999) setHz=999; - e->setSongRate(setHz,setHz<52); - } - if (tempoView) { - ImGui::TableNextColumn(); - ImGui::Text("= %gHz",e->curSubSong->hz); - } else { - if (e->curSubSong->hz>=49.98 && e->curSubSong->hz<=50.02) { - ImGui::TableNextColumn(); - ImGui::Text("PAL"); - } - if (e->curSubSong->hz>=59.9 && e->curSubSong->hz<=60.11) { - ImGui::TableNextColumn(); - ImGui::Text("NTSC"); - } - } ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text("Tuning (A-4)"); ImGui::TableNextColumn(); float tune=e->song.tuning; + float avail=ImGui::GetContentRegionAvail().x; ImGui::SetNextItemWidth(avail); if (ImGui::InputFloat("##Tuning",&tune,1.0f,3.0f,"%g")) { MARK_MODIFIED if (tune<220.0f) tune=220.0f; diff --git a/src/gui/speed.cpp b/src/gui/speed.cpp new file mode 100644 index 00000000..1d09331b --- /dev/null +++ b/src/gui/speed.cpp @@ -0,0 +1,179 @@ +/** + * 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 "imgui.h" +#include "misc/cpp/imgui_stdlib.h" +#include "intConst.h" + +void FurnaceGUI::drawSpeed(bool asChild) { + if (nextWindow==GUI_WINDOW_SPEED) { + speedOpen=true; + ImGui::SetNextWindowFocus(); + nextWindow=GUI_WINDOW_NOTHING; + } + if (!speedOpen && !asChild) return; + bool began=asChild?ImGui::BeginChild("Speed"):ImGui::Begin("Speed",&speedOpen,globalWinFlags); + if (began) { + if (ImGui::BeginTable("Props",3,ImGuiTableFlags_SizingStretchProp)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,0.0); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.0); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + if (ImGui::Selectable(tempoView?"Base Tempo##TempoOrHz":"Tick Rate##TempoOrHz")) { + tempoView=!tempoView; + } + ImGui::TableNextColumn(); + float avail=ImGui::GetContentRegionAvail().x; + ImGui::SetNextItemWidth(avail); + float setHz=tempoView?e->curSubSong->hz*2.5:e->curSubSong->hz; + if (ImGui::InputFloat("##Rate",&setHz,1.0f,1.0f,"%g")) { MARK_MODIFIED + if (tempoView) setHz/=2.5; + if (setHz<1) setHz=1; + if (setHz>999) setHz=999; + e->setSongRate(setHz,setHz<52); + } + if (tempoView) { + ImGui::TableNextColumn(); + ImGui::Text("= %gHz",e->curSubSong->hz); + } else { + if (e->curSubSong->hz>=49.98 && e->curSubSong->hz<=50.02) { + ImGui::TableNextColumn(); + ImGui::Text("PAL"); + } + if (e->curSubSong->hz>=59.9 && e->curSubSong->hz<=60.11) { + ImGui::TableNextColumn(); + ImGui::Text("NTSC"); + } + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Speed"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(avail); + if (ImGui::InputScalar("##Speed1",ImGuiDataType_U8,&e->curSubSong->speed1,&_ONE,&_THREE)) { MARK_MODIFIED + if (e->curSubSong->speed1<1) e->curSubSong->speed1=1; + if (e->isPlaying()) play(); + } + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(avail); + if (ImGui::InputScalar("##Speed2",ImGuiDataType_U8,&e->curSubSong->speed2,&_ONE,&_THREE)) { MARK_MODIFIED + if (e->curSubSong->speed2<1) e->curSubSong->speed2=1; + if (e->isPlaying()) play(); + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Virtual Tempo"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(avail); + if (ImGui::InputScalar("##VTempoN",ImGuiDataType_S16,&e->curSubSong->virtualTempoN,&_ONE,&_THREE)) { MARK_MODIFIED + if (e->curSubSong->virtualTempoN<1) e->curSubSong->virtualTempoN=1; + if (e->curSubSong->virtualTempoN>255) e->curSubSong->virtualTempoN=255; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Numerator"); + } + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(avail); + if (ImGui::InputScalar("##VTempoD",ImGuiDataType_S16,&e->curSubSong->virtualTempoD,&_ONE,&_THREE)) { MARK_MODIFIED + if (e->curSubSong->virtualTempoD<1) e->curSubSong->virtualTempoD=1; + if (e->curSubSong->virtualTempoD>255) e->curSubSong->virtualTempoD=255; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Denominator (set to base tempo)"); + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("TimeBase"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(avail); + unsigned char realTB=e->curSubSong->timeBase+1; + if (ImGui::InputScalar("##TimeBase",ImGuiDataType_U8,&realTB,&_ONE,&_THREE)) { MARK_MODIFIED + if (realTB<1) realTB=1; + if (realTB>16) realTB=16; + e->curSubSong->timeBase=realTB-1; + } + ImGui::TableNextColumn(); + ImGui::Text("%.2f BPM",calcBPM(e->curSubSong->speed1,e->curSubSong->speed2,e->curSubSong->hz,e->curSubSong->virtualTempoN,e->curSubSong->virtualTempoD)); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Highlight"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(avail); + if (ImGui::InputScalar("##Highlight1",ImGuiDataType_U8,&e->curSubSong->hilightA,&_ONE,&_THREE)) { + MARK_MODIFIED; + } + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(avail); + if (ImGui::InputScalar("##Highlight2",ImGuiDataType_U8,&e->curSubSong->hilightB,&_ONE,&_THREE)) { + MARK_MODIFIED; + } + ImGui::EndTable(); + } + + ImGui::Separator(); + + if (ImGui::BeginTable("Props2",3,ImGuiTableFlags_SizingStretchProp)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,0.0); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.0); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.0); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Pattern Length"); + ImGui::TableNextColumn(); + float avail=ImGui::GetContentRegionAvail().x; + ImGui::SetNextItemWidth(avail); + int patLen=e->curSubSong->patLen; + if (ImGui::InputInt("##PatLength",&patLen,1,3)) { MARK_MODIFIED + if (patLen<1) patLen=1; + if (patLen>DIV_MAX_PATTERNS) patLen=DIV_MAX_PATTERNS; + e->curSubSong->patLen=patLen; + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Song Length"); + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(avail); + int ordLen=e->curSubSong->ordersLen; + if (ImGui::InputInt("##OrdLength",&ordLen,1,3)) { MARK_MODIFIED + if (ordLen<1) ordLen=1; + if (ordLen>DIV_MAX_PATTERNS) ordLen=DIV_MAX_PATTERNS; + e->curSubSong->ordersLen=ordLen; + if (curOrder>=ordLen) { + setOrder(ordLen-1); + } + } + + ImGui::EndTable(); + } + } + if (!asChild && ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_SPEED; + if (asChild) { + ImGui::EndChild(); + } else { + ImGui::End(); + } +}