diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index b2c0257f6..a95b2e2b6 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -644,10 +644,79 @@ void DivEngine::createNew(const int* description) { BUSY_END; } -void DivEngine::changeSystem(int index, DivSystem which) { +void DivEngine::swapChannels(int src, int dest) { + logV("swapping channel %d with %d",src,dest); + if (src==dest) { + logV("not swapping channels because it's the same channel!",src,dest); + return; + } + + for (int i=0; i<256; i++) { + song.orders.ord[dest][i]^=song.orders.ord[src][i]; + song.orders.ord[src][i]^=song.orders.ord[dest][i]; + song.orders.ord[dest][i]^=song.orders.ord[src][i]; + + DivPattern* prev=song.pat[src].data[i]; + song.pat[src].data[i]=song.pat[dest].data[i]; + song.pat[dest].data[i]=prev; + } + + song.pat[src].effectCols^=song.pat[dest].effectCols; + song.pat[dest].effectCols^=song.pat[src].effectCols; + song.pat[src].effectCols^=song.pat[dest].effectCols; +} + +void DivEngine::stompChannel(int ch) { + logV("stomping channel %d",ch); + for (int i=0; i<256; i++) { + song.orders.ord[ch][i]=0; + } + song.pat[ch].wipePatterns(); + song.pat[ch].effectCols=1; +} + +void DivEngine::swapChannelsP(int src, int dest) { + if (src<0 || src>=chans) return; + if (dest<0 || dest>=chans) return; + BUSY_BEGIN; + saveLock.lock(); + swapChannels(src,dest); + saveLock.unlock(); + BUSY_END; +} + +void DivEngine::changeSystem(int index, DivSystem which, bool preserveOrder) { + int chanCount=chans; quitDispatch(); BUSY_BEGIN; saveLock.lock(); + + if (!preserveOrder) { + int firstChan=0; + int chanMovement=getChannelCount(which)-getChannelCount(song.system[index]); + while (dispatchOfChan[firstChan]!=index) firstChan++; + int lastChan=firstChan+getChannelCount(song.system[index]); + if (chanMovement!=0) { + if (chanMovement>0) { + // add channels + for (int i=chanCount+chanMovement-1; i>=lastChan+chanMovement; i--) { + swapChannels(i,i-chanMovement); + } + for (int i=lastChan; ichanInsType[j][0]!=DIV_INS_NULL) { isInsTypePossible[sysDefs[song.system[i]]->chanInsType[j][0]]=true; - logV("Marking"); } if (sysDefs[song.system[i]]->chanInsType[j][1]!=DIV_INS_NULL) { diff --git a/src/engine/engine.h b/src/engine/engine.h index 7aa94fc58..ea11f9830 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -395,6 +395,8 @@ class DivEngine { void registerSystems(); void exchangeIns(int one, int two); + void swapChannels(int src, int dest); + void stompChannel(int ch); public: DivSong song; @@ -762,14 +764,17 @@ class DivEngine { // public render samples void renderSamplesP(); + // public swap channels + void swapChannelsP(int src, int dest); + // change system - void changeSystem(int index, DivSystem which); + void changeSystem(int index, DivSystem which, bool preserveOrder=true); // add system bool addSystem(DivSystem which); // remove system - bool removeSystem(int index); + bool removeSystem(int index, bool preserveOrder=true); // write to register on system void poke(int sys, unsigned int addr, unsigned short val); diff --git a/src/gui/channels.cpp b/src/gui/channels.cpp index 5b2a7e0c6..397ac2f65 100644 --- a/src/gui/channels.cpp +++ b/src/gui/channels.cpp @@ -19,6 +19,8 @@ #include "gui.h" #include "misc/cpp/imgui_stdlib.h" +#include "IconsFontAwesome4.h" +#include void FurnaceGUI::drawChannels() { if (nextWindow==GUI_WINDOW_CHANNELS) { @@ -37,6 +39,18 @@ void FurnaceGUI::drawChannels() { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Checkbox("##Visible",&e->song.chanShow[i]); + ImGui::SameLine(); + ImGui::BeginDisabled(i==0); + if (ImGui::Button(ICON_FA_CHEVRON_UP)) { + e->swapChannelsP(i,i-1); + } + ImGui::EndDisabled(); + ImGui::SameLine(); + ImGui::BeginDisabled(i==(e->getTotalChannelCount()-1)); + if (ImGui::Button(ICON_FA_CHEVRON_DOWN)) { + e->swapChannelsP(i,i+1); + } + ImGui::EndDisabled(); ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::InputTextWithHint("##ChanName",e->getChannelName(i),&e->song.chanName[i]); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 5ef9a5640..56e046f08 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1812,7 +1812,7 @@ void FurnaceGUI::processDrags(int dragX, int dragY) { #define sysChangeOption(x,y) \ if (ImGui::MenuItem(getSystemName(y),NULL,e->song.system[x]==y)) { \ - e->changeSystem(x,y); \ + e->changeSystem(x,y,preserveChanPos); \ updateWindowTitle(); \ } @@ -2687,6 +2687,7 @@ bool FurnaceGUI::loop() { ImGui::EndMenu(); } if (ImGui::BeginMenu("change system...")) { + ImGui::Checkbox("Preserve channel positions",&preserveChanPos); for (int i=0; isong.systemLen; i++) { if (ImGui::BeginMenu(fmt::sprintf("%d. %s##_SYSC%d",i+1,getSystemName(e->song.system[i]),i).c_str())) { for (int j=0; availableSystems[j]; j++) { @@ -2699,9 +2700,10 @@ bool FurnaceGUI::loop() { ImGui::EndMenu(); } if (ImGui::BeginMenu("remove system...")) { + ImGui::Checkbox("Preserve channel positions",&preserveChanPos); for (int i=0; isong.systemLen; i++) { if (ImGui::MenuItem(fmt::sprintf("%d. %s##_SYSR%d",i+1,getSystemName(e->song.system[i]),i).c_str())) { - if (!e->removeSystem(i)) { + if (!e->removeSystem(i,preserveChanPos)) { showError("cannot remove system! ("+e->getLastError()+")"); } } @@ -3782,6 +3784,7 @@ FurnaceGUI::FurnaceGUI(): wantCaptureKeyboard(false), displayNew(false), fullScreen(false), + preserveChanPos(false), vgmExportVersion(0x171), drawHalt(10), curFileDialog(GUI_FILE_OPEN), diff --git a/src/gui/gui.h b/src/gui/gui.h index 3b9911c71..14b735b22 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -735,7 +735,7 @@ class FurnaceGUI { String mmlStringW; bool quit, warnQuit, willCommit, edit, modified, displayError, displayExporting, vgmExportLoop, wantCaptureKeyboard; - bool displayNew, fullScreen; + bool displayNew, fullScreen, preserveChanPos; bool willExport[32]; int vgmExportVersion; int drawHalt;