diff --git a/TODO.md b/TODO.md index 907e1aee..c11d4755 100644 --- a/TODO.md +++ b/TODO.md @@ -17,7 +17,6 @@ - scroll instrument/wave/sample list when selecting item - unified data view - volume commands should work on Game Boy -- macro editor menu - add another FM editor layout - try to find out why does VSlider not accept keyboard input - finish lock layout diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 19fff8bb..451f89b2 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1717,21 +1717,26 @@ void FurnaceGUI::showError(String what) { if (!macroDragInitialValueSet) { \ macroDragLineInitial=ImVec2(x,y); \ macroDragInitialValueSet=true; \ + macroDragMouseMoved=false; \ + } else if (!macroDragMouseMoved) { \ + macroDragMouseMoved=true; \ } \ - if ((int)round(x-macroDragLineInitial.x)==0) { \ - t[x]=macroDragLineInitial.y; \ - } else { \ - if ((int)round(x-macroDragLineInitial.x)<0) { \ - for (int i=0; i<=(int)round(macroDragLineInitial.x-x); i++) { \ - int index=(int)round(x+i); \ - if (index<0) continue; \ - t[index]=y+(macroDragLineInitial.y-y)*((float)i/(float)(macroDragLineInitial.x-x)); \ - } \ + if (macroDragMouseMoved) { \ + if ((int)round(x-macroDragLineInitial.x)==0) { \ + t[x]=macroDragLineInitial.y; \ } else { \ - for (int i=0; i<=(int)round(x-macroDragLineInitial.x); i++) { \ - int index=(int)round(i+macroDragLineInitial.x); \ - if (index<0) continue; \ - t[index]=macroDragLineInitial.y+(y-macroDragLineInitial.y)*((float)i/(x-macroDragLineInitial.x)); \ + if ((int)round(x-macroDragLineInitial.x)<0) { \ + for (int i=0; i<=(int)round(macroDragLineInitial.x-x); i++) { \ + int index=(int)round(x+i); \ + if (index<0) continue; \ + t[index]=y+(macroDragLineInitial.y-y)*((float)i/(float)(macroDragLineInitial.x-x)); \ + } \ + } else { \ + for (int i=0; i<=(int)round(x-macroDragLineInitial.x); i++) { \ + int index=(int)round(i+macroDragLineInitial.x); \ + if (index<0) continue; \ + t[index]=macroDragLineInitial.y+(y-macroDragLineInitial.y)*((float)i/(x-macroDragLineInitial.x)); \ + } \ } \ } \ } \ @@ -2342,6 +2347,9 @@ bool FurnaceGUI::loop() { if (macroDragActive || macroLoopDragActive || waveDragActive || (sampleDragActive && sampleDragMode)) { MARK_MODIFIED; } + if (macroDragActive && macroDragLineMode && !macroDragMouseMoved) { + displayMacroMenu=true; + } macroDragActive=false; macroDragBitMode=false; macroDragInitialValue=false; @@ -3851,6 +3859,7 @@ FurnaceGUI::FurnaceGUI(): displayExporting(false), vgmExportLoop(true), wantCaptureKeyboard(false), + displayMacroMenu(false), displayNew(false), fullScreen(false), preserveChanPos(false), @@ -4004,8 +4013,14 @@ FurnaceGUI::FurnaceGUI(): macroDragInitialValue(false), macroDragChar(false), macroDragLineMode(false), + macroDragMouseMoved(false), macroDragLineInitial(0,0), macroDragActive(false), + lastMacroDesc(NULL,NULL,0,0,0.0f), + macroOffX(0), + macroOffY(0), + macroScaleX(100.0f), + macroScaleY(100.0f), macroLoopDragStart(0,0), macroLoopDragAreaSize(0,0), macroLoopDragTarget(NULL), diff --git a/src/gui/gui.h b/src/gui/gui.h index 365c15e0..cc0f1c42 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -768,7 +768,7 @@ class FurnaceGUI { String mmlString[17]; String mmlStringW; - bool quit, warnQuit, willCommit, edit, modified, displayError, displayExporting, vgmExportLoop, wantCaptureKeyboard; + bool quit, warnQuit, willCommit, edit, modified, displayError, displayExporting, vgmExportLoop, wantCaptureKeyboard, displayMacroMenu; bool displayNew, fullScreen, preserveChanPos; bool willExport[32]; int vgmExportVersion; @@ -1080,8 +1080,12 @@ class FurnaceGUI { bool macroDragInitialValue; bool macroDragChar; bool macroDragLineMode; + bool macroDragMouseMoved; ImVec2 macroDragLineInitial; bool macroDragActive; + FurnaceGUIMacroDesc lastMacroDesc; + int macroOffX, macroOffY; + float macroScaleX, macroScaleY; ImVec2 macroLoopDragStart; ImVec2 macroLoopDragAreaSize; diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 6c13dde1..a1b78bd1 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -1192,6 +1192,7 @@ void FurnaceGUI::drawMacros(std::vector& macros) { macroDragChar=false; macroDragLineMode=(i.isBitfield)?false:ImGui::IsItemClicked(ImGuiMouseButton_Right); macroDragLineInitial=ImVec2(0,0); + lastMacroDesc=i; processDrags(ImGui::GetMousePos().x,ImGui::GetMousePos().y); } if (i.macro->open) { @@ -3123,8 +3124,108 @@ void FurnaceGUI::drawInsEdit() { popAccentColors(); } } + if (displayMacroMenu) { + displayMacroMenu=false; + if (lastMacroDesc.macro!=NULL) { + ImGui::OpenPopup("macroMenu"); + } + } if (ImGui::BeginPopup("macroMenu",ImGuiWindowFlags_NoMove|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings)) { - ImGui::Text("Macro menu here..."); + if (ImGui::MenuItem("copy")) { + String mmlStr; + encodeMMLStr(mmlStr,lastMacroDesc.macro->val,lastMacroDesc.macro->len,lastMacroDesc.macro->loop,lastMacroDesc.macro->rel); + SDL_SetClipboardText(mmlStr.c_str()); + } + if (ImGui::MenuItem("paste")) { + String mmlStr; + char* clipText=SDL_GetClipboardText(); + if (clipText!=NULL) { + if (clipText[0]) { + mmlStr=clipText; + } + SDL_free(clipText); + } + if (!mmlStr.empty()) { + decodeMMLStr(mmlStr,lastMacroDesc.macro->val,lastMacroDesc.macro->len,lastMacroDesc.macro->loop,lastMacroDesc.min,(lastMacroDesc.isBitfield)?((1<<(lastMacroDesc.isBitfield?lastMacroDesc.max:0))-1):lastMacroDesc.max,lastMacroDesc.macro->rel); + } + } + ImGui::Separator(); + if (ImGui::MenuItem("clear")) { + lastMacroDesc.macro->len=0; + lastMacroDesc.macro->loop=-1; + lastMacroDesc.macro->rel=-1; + for (int i=0; i<256; i++) { + lastMacroDesc.macro->val[i]=0; + } + } + if (ImGui::MenuItem("clear contents")) { + for (int i=0; i<256; i++) { + lastMacroDesc.macro->val[i]=0; + } + } + ImGui::Separator(); + if (ImGui::BeginMenu("offset...")) { + ImGui::InputInt("X",¯oOffX,1,10); + ImGui::InputInt("Y",¯oOffY,1,10); + if (ImGui::Button("offset")) { + int oldData[256]; + memset(oldData,0,256*sizeof(int)); + memcpy(oldData,lastMacroDesc.macro->val,lastMacroDesc.macro->len*sizeof(int)); + + for (int i=0; ilen; i++) { + int val=0; + if ((i-macroOffX)>=0 && (i-macroOffX)len) { + val=oldData[i-macroOffX]+macroOffY; + if (vallastMacroDesc.max) val=lastMacroDesc.max; + } + lastMacroDesc.macro->val[i]=val; + } + + if (lastMacroDesc.macro->loop>=0 && lastMacroDesc.macro->looplen) { + lastMacroDesc.macro->loop+=macroOffX; + } else { + lastMacroDesc.macro->loop=-1; + } + if ((lastMacroDesc.macro->rel+macroOffX)>=0 && (lastMacroDesc.macro->rel+macroOffX)len) { + lastMacroDesc.macro->rel+=macroOffX; + } else { + lastMacroDesc.macro->rel=-1; + } + + ImGui::CloseCurrentPopup(); + } + ImGui::EndMenu(); + } + if (ImGui::BeginMenu("scale...")) { + if (ImGui::InputFloat("X",¯oScaleX,1.0f,10.0f,"%.2f%%")) { + if (macroScaleX<0.1) macroScaleX=0.1; + if (macroScaleX>12800.0) macroScaleX=12800.0; + } + ImGui::InputFloat("Y",¯oScaleY,1.0f,10.0f,"%.2f%%"); + if (ImGui::Button("scale")) { + int oldData[256]; + memset(oldData,0,256*sizeof(int)); + memcpy(oldData,lastMacroDesc.macro->val,lastMacroDesc.macro->len*sizeof(int)); + + lastMacroDesc.macro->len=MIN(128,((double)lastMacroDesc.macro->len*(macroScaleX/100.0))); + + for (int i=0; ilen; i++) { + int val=0; + double posX=round((double)i*(100.0/macroScaleX)-0.01); + if (posX>=0 && posXlen) { + val=round((double)oldData[(int)posX]*(macroScaleY/100.0)); + if (vallastMacroDesc.max) val=lastMacroDesc.max; + } + lastMacroDesc.macro->val[i]=val; + } + + ImGui::CloseCurrentPopup(); + } + ImGui::EndMenu(); + } + ImGui::EndPopup(); } }