diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 9cfbc18d92..f50bbc7539 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -3248,6 +3248,53 @@ bool DivEngine::moveSampleDown(int which) { return true; } +bool DivEngine::swapInstruments(int a, int b) { + if (a<0 || a>=(int)song.ins.size() || b<0 || b>=(int)song.ins.size()) return false; + BUSY_BEGIN; + DivInstrument* temp=song.ins[a]; + saveLock.lock(); + song.ins[a]=song.ins[b]; + song.ins[b]=temp; + moveAsset(song.insDir,a,b); + exchangeIns(a,b); + saveLock.unlock(); + BUSY_END; + return true; +} + +bool DivEngine::swapWaves(int a, int b) { + if (a<0 || a>=(int)song.wave.size() || b<0 || b>=(int)song.wave.size()) return false; + BUSY_BEGIN; + DivWavetable* temp=song.wave[a]; + saveLock.lock(); + song.wave[a]=song.wave[b]; + song.wave[b]=temp; + exchangeWave(a,b); + moveAsset(song.waveDir,a,b); + saveLock.unlock(); + BUSY_END; + return true; +} + +bool DivEngine::swapSamples(int a, int b) { + if (a<0 || a>=(int)song.sample.size() || b<0 || b>=(int)song.sample.size()) return false; + BUSY_BEGIN; + sPreview.sample=-1; + sPreview.pos=0; + sPreview.dir=false; + DivSample* temp=song.sample[a]; + saveLock.lock(); + song.sample[a]=song.sample[b]; + song.sample[b]=temp; + exchangeSample(a,b); + moveAsset(song.sampleDir,a,b); + saveLock.unlock(); + renderSamples(); + BUSY_END; + return true; +} + + void DivEngine::autoPatchbay() { song.patchbay.clear(); for (unsigned int i=0; itarget) { \ + if (_moveUpFn(_toMoveVar)) { \ + _toMoveVar--; \ + } else { \ + break; \ + } \ + } \ + while (_toMoveVartype]); insIcon=insTypes[ins->type]; } - + switch (settings.insIconsStyle) { case 1: name=fmt::sprintf("%s##_INS%d",insIcon[1],i); @@ -125,8 +168,11 @@ void FurnaceGUI::insListItem(int i, int dir, int asset) { } if (i>=0) { if (insListDir) { - DRAG_SOURCE(dir,asset,"FUR_INSDIR"); - DRAG_TARGET(dir,asset,e->song.insDir,"FUR_INSDIR"); + DIR_DRAG_SOURCE(dir,asset,"FUR_INSDIR"); + DIR_DRAG_TARGET(dir,asset,e->song.insDir,"FUR_INSDIR"); + } else { + SIMPLE_DRAG_SOURCE("FUR_INS",insToMove); + SIMPLE_DRAG_TARGET("FUR_INS",insToMove,curIns,e->swapInstruments,e->moveInsUp,e->moveInsDown); } if (ImGui::BeginPopupContextItem("InsRightMenu")) { @@ -191,8 +237,11 @@ void FurnaceGUI::waveListItem(int i, float* wavePreview, int dir, int asset) { } } if (waveListDir || (settings.unifiedDataView && insListDir)) { - DRAG_SOURCE(dir,asset,"FUR_WAVEDIR"); - DRAG_TARGET(dir,asset,e->song.waveDir,"FUR_WAVEDIR"); + DIR_DRAG_SOURCE(dir,asset,"FUR_WAVEDIR"); + DIR_DRAG_TARGET(dir,asset,e->song.waveDir,"FUR_WAVEDIR"); + } else { + SIMPLE_DRAG_SOURCE("FUR_WAVE",waveToMove); + SIMPLE_DRAG_TARGET("FUR_WAVE",waveToMove,curWave,e->swapWaves,e->moveWaveUp,e->moveWaveDown); } ImGui::SameLine(); ImGui::SetCursorPos(curPos); @@ -232,8 +281,11 @@ void FurnaceGUI::sampleListItem(int i, int dir, int asset) { } } if (sampleListDir || (settings.unifiedDataView && insListDir)) { - DRAG_SOURCE(dir,asset,"FUR_SDIR"); - DRAG_TARGET(dir,asset,e->song.sampleDir,"FUR_SDIR"); + DIR_DRAG_SOURCE(dir,asset,"FUR_SDIR"); + DIR_DRAG_TARGET(dir,asset,e->song.sampleDir,"FUR_SDIR"); + } else { + SIMPLE_DRAG_SOURCE("FUR_SAMPLE",sampleToMove); + SIMPLE_DRAG_TARGET("FUR_SAMPLE",sampleToMove,curSample,e->swapSamples,e->moveSampleUp,e->moveSampleDown); } ImGui::SameLine(); ImGui::TextNoHashHide("%s",sample->name.c_str()); @@ -626,8 +678,8 @@ void FurnaceGUI::drawInsList(bool asChild) { String nodeName=fmt::sprintf("%s %s##_ADI%d",i.name.empty()?ICON_FA_FOLDER_O:ICON_FA_FOLDER,i.name.empty()?_(""):i.name,i.name.empty()?-1:dirIndex); String popupID=fmt::sprintf("DirRightMenu%d",dirIndex); bool treeNode=ImGui::TreeNodeEx(nodeName.c_str(),ImGuiTreeNodeFlags_SpanAvailWidth|(i.name.empty()?ImGuiTreeNodeFlags_DefaultOpen:0)); - DRAG_SOURCE(dirIndex,-1,"FUR_INSDIR"); - DRAG_TARGET(dirIndex,-1,e->song.insDir,"FUR_INSDIR"); + DIR_DRAG_SOURCE(dirIndex,-1,"FUR_INSDIR"); + DIR_DRAG_TARGET(dirIndex,-1,e->song.insDir,"FUR_INSDIR"); if (ImGui::BeginPopupContextItem(popupID.c_str())) { if (ImGui::MenuItem(_("rename..."))) { editStr(&i.name); @@ -1040,8 +1092,8 @@ void FurnaceGUI::actualWaveList() { String nodeName=fmt::sprintf("%s %s##_ADW%d",i.name.empty()?ICON_FA_FOLDER_O:ICON_FA_FOLDER,i.name.empty()?_(""):i.name,i.name.empty()?-1:dirIndex); String popupID=fmt::sprintf("DirRightMenu%d",dirIndex); bool treeNode=ImGui::TreeNodeEx(nodeName.c_str(),ImGuiTreeNodeFlags_SpanAvailWidth|(i.name.empty()?ImGuiTreeNodeFlags_DefaultOpen:0)); - DRAG_SOURCE(dirIndex,-1,"FUR_WAVEDIR"); - DRAG_TARGET(dirIndex,-1,e->song.waveDir,"FUR_WAVEDIR"); + DIR_DRAG_SOURCE(dirIndex,-1,"FUR_WAVEDIR"); + DIR_DRAG_TARGET(dirIndex,-1,e->song.waveDir,"FUR_WAVEDIR"); if (ImGui::BeginPopupContextItem(popupID.c_str())) { if (ImGui::MenuItem(_("rename..."))) { editStr(&i.name); @@ -1102,8 +1154,8 @@ void FurnaceGUI::actualSampleList() { String nodeName=fmt::sprintf("%s %s##_ADS%d",i.name.empty()?ICON_FA_FOLDER_O:ICON_FA_FOLDER,i.name.empty()?_(""):i.name,i.name.empty()?-1:dirIndex); String popupID=fmt::sprintf("DirRightMenu%d",dirIndex); bool treeNode=ImGui::TreeNodeEx(nodeName.c_str(),ImGuiTreeNodeFlags_SpanAvailWidth|(i.name.empty()?ImGuiTreeNodeFlags_DefaultOpen:0)); - DRAG_SOURCE(dirIndex,-1,"FUR_SDIR"); - DRAG_TARGET(dirIndex,-1,e->song.sampleDir,"FUR_SDIR"); + DIR_DRAG_SOURCE(dirIndex,-1,"FUR_SDIR"); + DIR_DRAG_TARGET(dirIndex,-1,e->song.sampleDir,"FUR_SDIR"); if (ImGui::BeginPopupContextItem(popupID.c_str())) { if (ImGui::MenuItem(_("rename..."))) { editStr(&i.name); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 879c28939c..6ae5ce8f41 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -8653,6 +8653,9 @@ FurnaceGUI::FurnaceGUI(): opToMove(-1), assetToMove(-1), dirToMove(-1), + insToMove(-1), + waveToMove(-1), + sampleToMove(-1), transposeAmount(0), randomizeMin(0), randomizeMax(255), diff --git a/src/gui/gui.h b/src/gui/gui.h index 0757db41a7..37a836e735 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1791,7 +1791,7 @@ class FurnaceGUI { int pnQuality; int saaQuality; int sccQuality; - int smQuality; + int smQuality; int swanQuality; int vbQuality; int arcadeCoreRender; @@ -1818,7 +1818,7 @@ class FurnaceGUI { int pnQualityRender; int saaQualityRender; int sccQualityRender; - int smQualityRender; + int smQualityRender; int swanQualityRender; int vbQualityRender; int pcSpeakerOutMethod; @@ -1914,6 +1914,7 @@ class FurnaceGUI { int doubleClickColumn; int blankIns; int dragMovesSelection; + int draggableDataView; int cursorFollowsOrder; int unsignedDetune; int noThreadedInput; @@ -2176,6 +2177,7 @@ class FurnaceGUI { doubleClickColumn(1), blankIns(0), dragMovesSelection(1), + draggableDataView(1), cursorFollowsOrder(1), unsignedDetune(0), noThreadedInput(0), @@ -2524,6 +2526,7 @@ class FurnaceGUI { int chanToMove, sysToMove, sysToDelete, opToMove; int assetToMove, dirToMove; + int insToMove, waveToMove, sampleToMove; ImVec2 patWindowPos, patWindowSize; @@ -2689,7 +2692,7 @@ class FurnaceGUI { bool pianoReadonly; int pianoOffset, pianoOffsetEdit; int pianoView, pianoInputPadMode; - + // effect sorting / searching bool effectsShow[10]; ImGuiTextFilter effectSearch; diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 56b2de38a6..9ca4b9d2b0 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -1493,7 +1493,7 @@ void FurnaceGUI::drawSettings() { ImGui::Text(_("Quality")); ImGui::SameLine(); if (ImGui::Combo("##Quality",&settings.audioQuality,LocalizedComboGetter,audioQualities,2)) settingsChanged=true; - + bool clampSamplesB=settings.clampSamples; if (ImGui::Checkbox(_("Software clipping"),&clampSamplesB)) { settings.clampSamples=clampSamplesB; @@ -2688,6 +2688,12 @@ void FurnaceGUI::drawSettings() { settingsChanged=true; } + bool draggableDataViewB=settings.draggableDataView; + if (ImGui::Checkbox(_("Draggable instruments/samples/waves"),&draggableDataViewB)) { + settings.draggableDataView=draggableDataViewB; + settingsChanged=true; + } + ImGui::Text(_("Note preview behavior:")); ImGui::Indent(); if (ImGui::RadioButton(_("Never##npb0"),settings.notePreviewBehavior==0)) { @@ -4953,13 +4959,14 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { settings.cursorMoveNoScroll=conf.getInt("cursorMoveNoScroll",0); settings.notePreviewBehavior=conf.getInt("notePreviewBehavior",1); - + settings.absorbInsInput=conf.getInt("absorbInsInput",0); - + settings.moveWindowTitle=conf.getInt("moveWindowTitle",1); settings.doubleClickColumn=conf.getInt("doubleClickColumn",1); settings.dragMovesSelection=conf.getInt("dragMovesSelection",2); + settings.draggableDataView=conf.getInt("draggableDataView",1); settings.cursorFollowsOrder=conf.getInt("cursorFollowsOrder",1); @@ -5397,7 +5404,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { clampSetting(settings.backgroundPlay,0,1); if (settings.exportLoops<0.0) settings.exportLoops=0.0; - if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0; + if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0; } void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { @@ -5446,10 +5453,10 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { conf.set("blankIns",settings.blankIns); conf.set("saveWindowPos",settings.saveWindowPos); - + conf.set("saveUnusedPatterns",settings.saveUnusedPatterns); conf.set("maxRecentFile",settings.maxRecentFile); - + conf.set("persistFadeOut",settings.persistFadeOut); conf.set("exportLoops",settings.exportLoops); conf.set("exportFadeOut",settings.exportFadeOut); @@ -5532,7 +5539,7 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { conf.set("pullDeleteBehavior",settings.pullDeleteBehavior); conf.set("wrapHorizontal",settings.wrapHorizontal); conf.set("wrapVertical",settings.wrapVertical); - + conf.set("stepOnDelete",settings.stepOnDelete); conf.set("scrollStep",settings.scrollStep); conf.set("avoidRaisingPattern",settings.avoidRaisingPattern); @@ -5540,7 +5547,7 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { conf.set("stepOnInsert",settings.stepOnInsert); conf.set("effectCursorDir",settings.effectCursorDir); conf.set("cursorPastePos",settings.cursorPastePos); - + conf.set("effectDeletionAltersValue",settings.effectDeletionAltersValue); conf.set("pushNibble",settings.pushNibble); @@ -5548,16 +5555,17 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { conf.set("cursorMoveNoScroll",settings.cursorMoveNoScroll); conf.set("notePreviewBehavior",settings.notePreviewBehavior); - + conf.set("absorbInsInput",settings.absorbInsInput); - + conf.set("moveWindowTitle",settings.moveWindowTitle); - + conf.set("doubleClickColumn",settings.doubleClickColumn); conf.set("dragMovesSelection",settings.dragMovesSelection); - + conf.set("draggableDataView",settings.draggableDataView); + conf.set("cursorFollowsOrder",settings.cursorFollowsOrder); - + conf.set("insertBehavior",settings.insertBehavior); conf.set("pullDeleteRow",settings.pullDeleteRow); conf.set("cursorFollowsWheel",settings.cursorFollowsWheel); @@ -5565,7 +5573,7 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { conf.set("removeInsOff",settings.removeInsOff); conf.set("removeVolOff",settings.removeVolOff); conf.set("insTypeMenu",settings.insTypeMenu); - + conf.set("selectAssetOnLoad",settings.selectAssetOnLoad); conf.set("inputRepeat",settings.inputRepeat); @@ -6307,7 +6315,7 @@ void FurnaceGUI::applyUISettings(bool updateFonts) { } } } - + if (updateFonts) { // chan osc work pool if (chanOscWorkPool!=NULL) { @@ -6503,7 +6511,7 @@ void FurnaceGUI::applyUISettings(bool updateFonts) { sty.ScaleAllSizes(dpiScale); ImGui::GetStyle()=sty; - + updateSampleTex=true; ImGui::GetIO().ConfigInputTrickleEventQueue=settings.eventDelay;