From f362b1288c1af739e427d58ce2f4faef5633d99b Mon Sep 17 00:00:00 2001 From: BlastBrothers Date: Mon, 11 Apr 2022 21:27:23 -0400 Subject: [PATCH 1/3] Add (currently useless) menu option ofr compact editor --- src/gui/gui.h | 2 ++ src/gui/settings.cpp | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/gui/gui.h b/src/gui/gui.h index 53b2f171..41d3590e 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -775,6 +775,7 @@ class FurnaceGUI { int roundedMenus; int loadJapanese; int fmLayout; + int sampleLayout; int susPosition; int effectCursorDir; int cursorPastePos; @@ -838,6 +839,7 @@ class FurnaceGUI { roundedMenus(0), loadJapanese(0), fmLayout(0), + sampleLayout(0), susPosition(0), effectCursorDir(1), cursorPastePos(1), diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index d8070dc6..9c64f404 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -832,6 +832,8 @@ void FurnaceGUI::drawSettings() { settings.susPosition=1; } + ImGui::Separator(); + bool macroViewB=settings.macroView; if (ImGui::Checkbox("Classic macro view (standard macros only; deprecated!)",¯oViewB)) { settings.macroView=macroViewB; @@ -878,6 +880,11 @@ void FurnaceGUI::drawSettings() { ImGui::Separator(); + bool sampleLayoutB=settings.sampleLayout; + if (ImGui::Checkbox("Use compact sample editor",&sampleLayoutB)) { + settings.sampleLayout=sampleLayoutB; + } + bool roundedWindowsB=settings.roundedWindows; if (ImGui::Checkbox("Rounded window corners",&roundedWindowsB)) { settings.roundedWindows=roundedWindowsB; @@ -1502,6 +1509,7 @@ void FurnaceGUI::syncSettings() { settings.roundedMenus=e->getConfInt("roundedMenus",0); settings.loadJapanese=e->getConfInt("loadJapanese",0); settings.fmLayout=e->getConfInt("fmLayout",0); + settings.sampleLayout=e->getConfInt("sampleLayout",0); settings.susPosition=e->getConfInt("susPosition",0); settings.effectCursorDir=e->getConfInt("effectCursorDir",1); settings.cursorPastePos=e->getConfInt("cursorPastePos",1); @@ -1632,6 +1640,7 @@ void FurnaceGUI::commitSettings() { e->setConf("roundedMenus",settings.roundedMenus); e->setConf("loadJapanese",settings.loadJapanese); e->setConf("fmLayout",settings.fmLayout); + e->setConf("sampleLayout",settings.sampleLayout); e->setConf("susPosition",settings.susPosition); e->setConf("effectCursorDir",settings.effectCursorDir); e->setConf("cursorPastePos",settings.cursorPastePos); From 93b87cc65d7a179ca7fb7892d98555f53ba6fb64 Mon Sep 17 00:00:00 2001 From: BlastBrothers Date: Mon, 11 Apr 2022 21:51:43 -0400 Subject: [PATCH 2/3] Sample preview can only be so tall now --- src/gui/sampleEdit.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/gui/sampleEdit.cpp b/src/gui/sampleEdit.cpp index 34cb23d5..dbe5c2cb 100644 --- a/src/gui/sampleEdit.cpp +++ b/src/gui/sampleEdit.cpp @@ -561,7 +561,14 @@ void FurnaceGUI::drawSampleEdit() { ImGui::Separator(); ImVec2 avail=ImGui::GetContentRegionAvail(); + if(ImGui::GetContentRegionAvail().y > (ImGui::GetContentRegionAvail().x / 2.0f)) { + avail=ImVec2(ImGui::GetContentRegionAvail().x,ImGui::GetContentRegionAvail().x / 2.0f); + } avail.y-=ImGui::GetFontSize()+ImGui::GetStyle().ItemSpacing.y+ImGui::GetStyle().ScrollbarSize; + if (avail.y < 1.0){ //Prevents crash + avail.y = 1.0; + } + int availX=avail.x; int availY=avail.y; From 0771cdcdae12647a9c12e6ce3aadc8f922c83803 Mon Sep 17 00:00:00 2001 From: BlastBrothers Date: Mon, 11 Apr 2022 22:14:20 -0400 Subject: [PATCH 3/3] Add in the alternate editor as an option --- src/gui/sampleEdit.cpp | 776 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 775 insertions(+), 1 deletion(-) diff --git a/src/gui/sampleEdit.cpp b/src/gui/sampleEdit.cpp index dbe5c2cb..13e759c7 100644 --- a/src/gui/sampleEdit.cpp +++ b/src/gui/sampleEdit.cpp @@ -44,7 +44,7 @@ void FurnaceGUI::drawSampleEdit() { if (ImGui::Begin("Sample Editor",&sampleEditOpen,settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking)) { if (curSample<0 || curSample>=(int)e->song.sample.size()) { ImGui::Text("no sample selected"); - } else { + } else if (!settings.sampleLayout) { DivSample* sample=e->song.sample[curSample]; String sampleType="Invalid"; if (sample->depth<17) { @@ -856,6 +856,780 @@ void FurnaceGUI::drawSampleEdit() { ImGui::Text("- none"); }*/ } + else { + DivSample* sample=e->song.sample[curSample]; + String sampleType="Invalid"; + if (sample->depth<17) { + if (sampleDepths[sample->depth]!=NULL) { + sampleType=sampleDepths[sample->depth]; + } + } + ImGui::Text("Name"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::InputText("##SampleName",&sample->name)) { + MARK_MODIFIED; + } + + if (ImGui::BeginTable("SampleProps",2,ImGuiTableFlags_SizingStretchSame)) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Type"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::BeginCombo("##SampleType",sampleType.c_str())) { + for (int i=0; i<17; i++) { + if (sampleDepths[i]==NULL) continue; + if (ImGui::Selectable(sampleDepths[i])) { + sample->prepareUndo(true); + sample->depth=i; + e->renderSamplesP(); + updateSampleTex=true; + MARK_MODIFIED; + } + } + ImGui::EndCombo(); + } + + ImGui::TableNextColumn(); + ImGui::Text("Rate (Hz)"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::InputInt("##SampleRate",&sample->rate,10,200)) { MARK_MODIFIED + if (sample->rate<100) sample->rate=100; + if (sample->rate>96000) sample->rate=96000; + } + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("C-4 (Hz)"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::InputInt("##SampleCenter",&sample->centerRate,10,200)) { MARK_MODIFIED + if (sample->centerRate<100) sample->centerRate=100; + if (sample->centerRate>65535) sample->centerRate=65535; + } + + ImGui::TableNextColumn(); + bool doLoop=(sample->loopStart>=0); + if (ImGui::Checkbox("Loop",&doLoop)) { MARK_MODIFIED + if (doLoop) { + sample->loopStart=0; + } else { + sample->loopStart=-1; + } + updateSampleTex=true; + } + if (doLoop) { + ImGui::SameLine(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::InputInt("##LoopPosition",&sample->loopStart,1,10)) { MARK_MODIFIED + if (sample->loopStart<0 || sample->loopStart>=(int)sample->samples) { + sample->loopStart=0; + } + updateSampleTex=true; + } + } + ImGui::EndTable(); + } + + /* + if (ImGui::Button("Apply")) { + e->renderSamplesP(); + } + ImGui::SameLine(); + */ + ImGui::Separator(); + + ImGui::BeginDisabled(sample->depth!=8 && sample->depth!=16); + + ImGui::PushStyleColor(ImGuiCol_Button,TOGGLE_COLOR(!sampleDragMode)); + if (ImGui::Button(ICON_FA_I_CURSOR "##SSelect")) { + sampleDragMode=false; + } + ImGui::PopStyleColor(); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Edit mode: Select"); + } + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Button,TOGGLE_COLOR(sampleDragMode)); + if (ImGui::Button(ICON_FA_PENCIL "##SDraw")) { + sampleDragMode=true; + } + ImGui::PopStyleColor(); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Edit mode: Draw"); + } + ImGui::SameLine(); + ImGui::Dummy(ImVec2(7.0*dpiScale,dpiScale)); + ImGui::SameLine(); + ImGui::Button(ICON_FA_ARROWS_H "##SResize"); + if (ImGui::IsItemClicked()) { + resizeSize=sample->samples; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Resize"); + } + if (openSampleResizeOpt) { + openSampleResizeOpt=false; + ImGui::OpenPopup("SResizeOpt"); + } + if (ImGui::BeginPopupContextItem("SResizeOpt",ImGuiPopupFlags_MouseButtonLeft)) { + if (ImGui::InputInt("Samples",&resizeSize,1,64)) { + if (resizeSize<0) resizeSize=0; + if (resizeSize>16777215) resizeSize=16777215; + } + if (ImGui::Button("Resize")) { + sample->prepareUndo(true); + e->lockEngine([this,sample]() { + if (!sample->resize(resizeSize)) { + showError("couldn't resize! make sure your sample is 8 or 16-bit."); + } + e->renderSamples(); + }); + updateSampleTex=true; + sampleSelStart=-1; + sampleSelEnd=-1; + MARK_MODIFIED; + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } else { + resizeSize=sample->samples; + } + ImGui::SameLine(); + ImGui::Button(ICON_FA_EXPAND "##SResample"); + if (ImGui::IsItemClicked()) { + resampleTarget=sample->rate; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Resample"); + } + if (openSampleResampleOpt) { + openSampleResampleOpt=false; + ImGui::OpenPopup("SResampleOpt"); + } + if (ImGui::BeginPopupContextItem("SResampleOpt",ImGuiPopupFlags_MouseButtonLeft)) { + ImGui::Text("Rate"); + if (ImGui::InputDouble("##SRRate",&resampleTarget,1.0,50.0,"%g")) { + if (resampleTarget<0) resampleTarget=0; + if (resampleTarget>96000) resampleTarget=96000; + } + ImGui::SameLine(); + if (ImGui::Button("0.5x")) { + resampleTarget*=0.5; + } + ImGui::SameLine(); + if (ImGui::Button("==")) { + resampleTarget=sample->rate; + } + ImGui::SameLine(); + if (ImGui::Button("2.0x")) { + resampleTarget*=2.0; + } + double factor=resampleTarget/(double)sample->rate; + if (ImGui::InputDouble("Factor",&factor,0.125,0.5,"%g")) { + resampleTarget=(double)sample->rate*factor; + if (resampleTarget<0) resampleTarget=0; + if (resampleTarget>96000) resampleTarget=96000; + } + ImGui::Combo("Filter",&resampleStrat,resampleStrats,6); + if (ImGui::Button("Resample")) { + sample->prepareUndo(true); + e->lockEngine([this,sample]() { + if (!sample->resample(resampleTarget,resampleStrat)) { + showError("couldn't resample! make sure your sample is 8 or 16-bit."); + } + e->renderSamples(); + }); + updateSampleTex=true; + sampleSelStart=-1; + sampleSelEnd=-1; + MARK_MODIFIED; + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } else { + resampleTarget=sample->rate; + } + ImGui::SameLine(); + ImGui::Dummy(ImVec2(0.5*dpiScale,dpiScale)); + ImGui::SameLine(); + ImGui::Button(ICON_FA_INDUSTRY "##SFilter"); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Apply filter"); + } + if (openSampleFilterOpt) { + openSampleFilterOpt=false; + ImGui::OpenPopup("SFilterOpt"); + } + if (ImGui::BeginPopupContextItem("SFilterOpt",ImGuiPopupFlags_MouseButtonLeft)) { + float lowP=sampleFilterL*100.0f; + float bandP=sampleFilterB*100.0f; + float highP=sampleFilterH*100.0f; + float resP=sampleFilterRes*100.0f; + ImGui::Text("Cutoff:"); + if (ImGui::SliderFloat("From",&sampleFilterCutStart,0.0f,sample->rate*0.5,"%.0fHz")) { + if (sampleFilterCutStart<0.0) sampleFilterCutStart=0.0; + if (sampleFilterCutStart>sample->rate*0.5) sampleFilterCutStart=sample->rate*0.5; + } + if (ImGui::SliderFloat("To",&sampleFilterCutEnd,0.0f,sample->rate*0.5,"%.0fHz")) { + if (sampleFilterCutEnd<0.0) sampleFilterCutEnd=0.0; + if (sampleFilterCutEnd>sample->rate*0.5) sampleFilterCutEnd=sample->rate*0.5; + } + ImGui::Separator(); + if (ImGui::SliderFloat("Resonance",&resP,0.0f,99.0f,"%.1f%%")) { + sampleFilterRes=resP/100.0f; + if (sampleFilterRes<0.0f) sampleFilterRes=0.0f; + if (sampleFilterRes>0.99f) sampleFilterRes=0.99f; + } + ImGui::Text("Power"); + ImGui::SameLine(); + if (ImGui::RadioButton("1x",sampleFilterPower==1)) { + sampleFilterPower=1; + } + ImGui::SameLine(); + if (ImGui::RadioButton("2x",sampleFilterPower==2)) { + sampleFilterPower=2; + } + ImGui::SameLine(); + if (ImGui::RadioButton("3x",sampleFilterPower==3)) { + sampleFilterPower=3; + } + ImGui::Separator(); + if (ImGui::SliderFloat("Low-pass",&lowP,0.0f,100.0f,"%.1f%%")) { + sampleFilterL=lowP/100.0f; + if (sampleFilterL<0.0f) sampleFilterL=0.0f; + if (sampleFilterL>1.0f) sampleFilterL=1.0f; + } + if (ImGui::SliderFloat("Band-pass",&bandP,0.0f,100.0f,"%.1f%%")) { + sampleFilterB=bandP/100.0f; + if (sampleFilterB<0.0f) sampleFilterB=0.0f; + if (sampleFilterB>1.0f) sampleFilterB=1.0f; + } + if (ImGui::SliderFloat("High-pass",&highP,0.0f,100.0f,"%.1f%%")) { + sampleFilterH=highP/100.0f; + if (sampleFilterH<0.0f) sampleFilterH=0.0f; + if (sampleFilterH>1.0f) sampleFilterH=1.0f; + } + + if (ImGui::Button("Apply")) { + sample->prepareUndo(true); + e->lockEngine([this,sample]() { + SAMPLE_OP_BEGIN; + float res=1.0-pow(sampleFilterRes,0.5f); + float low=0; + float band=0; + float high=0; + + double power=(sampleFilterCutStart>sampleFilterCutEnd)?0.5:2.0; + + if (sample->depth==16) { + for (unsigned int i=start; irate))*M_PI); + + for (int j=0; jdata16[i])-low-(res*band); + band=cut*high+band; + } + + float val=low*sampleFilterL+band*sampleFilterB+high*sampleFilterH; + if (val<-32768) val=-32768; + if (val>32767) val=32767; + sample->data16[i]=val; + } + } else if (sample->depth==8) { + for (unsigned int i=start; irate))*M_PI); + + for (int j=0; jdata8[i])-low-(res*band); + band=cut*high+band; + } + + float val=low*sampleFilterL+band*sampleFilterB+high*sampleFilterH; + if (val<-128) val=-128; + if (val>127) val=127; + sample->data8[i]=val; + } + } + + updateSampleTex=true; + + e->renderSamples(); + }); + MARK_MODIFIED; + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + ImGui::SameLine(); + ImGui::Dummy(ImVec2(0.5*dpiScale,dpiScale)); + ImGui::SameLine(); + + + ImGui::Button(ICON_FA_VOLUME_UP "##SAmplify"); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Amplify"); + } + if (openSampleAmplifyOpt) { + openSampleAmplifyOpt=false; + ImGui::OpenPopup("SAmplifyOpt"); + } + if (ImGui::BeginPopupContextItem("SAmplifyOpt",ImGuiPopupFlags_MouseButtonLeft)) { + ImGui::Text("Volume"); + if (ImGui::InputFloat("##SRVolume",&lifyVol,10.0,50.0,"%g%%")) { + if (amplifyVol<0) amplifyVol=0; + if (amplifyVol>10000) amplifyVol=10000; + } + ImGui::SameLine(); + ImGui::Text("(%.1fdB)",20.0*log10(amplifyVol/100.0f)); + if (ImGui::Button("Apply")) { + sample->prepareUndo(true); + e->lockEngine([this,sample]() { + SAMPLE_OP_BEGIN; + float vol=amplifyVol/100.0f; + + if (sample->depth==16) { + for (unsigned int i=start; idata16[i]*vol; + if (val<-32768) val=-32768; + if (val>32767) val=32767; + sample->data16[i]=val; + } + } else if (sample->depth==8) { + for (unsigned int i=start; idata8[i]*vol; + if (val<-128) val=-128; + if (val>127) val=127; + sample->data8[i]=val; + } + } + + updateSampleTex=true; + + e->renderSamples(); + }); + MARK_MODIFIED; + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_ARROWS_V "##SNormalize")) { + doAction(GUI_ACTION_SAMPLE_NORMALIZE); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Normalize"); + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_ARROW_UP "##SFadeIn")) { + doAction(GUI_ACTION_SAMPLE_FADE_IN); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Fade in"); + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_ARROW_DOWN "##SFadeOut")) { + doAction(GUI_ACTION_SAMPLE_FADE_OUT); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Fade out"); + } + + if (ImGui::Button(ICON_FA_UNDO "##SUndo")) { + doUndoSample(); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Undo"); + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_REPEAT "##SRedo")) { + doRedoSample(); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Redo"); + } + ImGui::SameLine(); + ImGui::Dummy(ImVec2(7.0*dpiScale,dpiScale)); + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_BACKWARD "##SReverse")) { + doAction(GUI_ACTION_SAMPLE_REVERSE); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Reverse"); + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_SORT_AMOUNT_ASC "##SInvert")) { + doAction(GUI_ACTION_SAMPLE_INVERT); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Invert"); + } + ImGui::SameLine(); + ImGui::Dummy(ImVec2(0.5*dpiScale,dpiScale)); + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_LEVEL_DOWN "##SSign")) { + doAction(GUI_ACTION_SAMPLE_SIGN); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Signed/unsigned exchange"); + } + ImGui::SameLine(); + ImGui::Dummy(ImVec2(0.5*dpiScale,dpiScale)); + ImGui::SameLine(); + ImGui::Button(ICON_FA_ADJUST "##SInsertSilence"); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Insert silence"); + } + if (openSampleSilenceOpt) { + openSampleSilenceOpt=false; + ImGui::OpenPopup("SSilenceOpt"); + } + if (ImGui::BeginPopupContextItem("SSilenceOpt",ImGuiPopupFlags_MouseButtonLeft)) { + if (ImGui::InputInt("Samples",&silenceSize,1,64)) { + if (silenceSize<0) silenceSize=0; + if (silenceSize>16777215) silenceSize=16777215; + } + if (ImGui::Button("Resize")) { + int pos=(sampleSelStart==-1 || sampleSelStart==sampleSelEnd)?sample->samples:sampleSelStart; + sample->prepareUndo(true); + e->lockEngine([this,sample,pos]() { + if (!sample->insert(pos,silenceSize)) { + showError("couldn't insert! make sure your sample is 8 or 16-bit."); + } + e->renderSamples(); + }); + updateSampleTex=true; + sampleSelStart=pos; + sampleSelEnd=pos+silenceSize; + MARK_MODIFIED; + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_ERASER "##SSilence")) { + doAction(GUI_ACTION_SAMPLE_SILENCE); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Apply silence"); + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_TIMES "##SDelete")) { + doAction(GUI_ACTION_SAMPLE_DELETE); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Delete"); + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_CROP "##STrim")) { + doAction(GUI_ACTION_SAMPLE_TRIM); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Trim"); + } + + if (ImGui::Button(ICON_FA_PLAY "##PreviewSample")) { + e->previewSample(curSample); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Preview sample"); + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_STOP "##StopSample")) { + e->stopSamplePreview(); + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Stop sample preview"); + } + ImGui::SameLine(); + double zoomPercent=100.0/sampleZoom; + ImGui::Text("Zoom"); + ImGui::SameLine(); + ImGui::SetNextItemWidth(150.0f*dpiScale); + if (ImGui::InputDouble("##SZoom",&zoomPercent,5.0,20.0,"%g%%")) { + if (zoomPercent>10000.0) zoomPercent=10000.0; + if (zoomPercent<1.0) zoomPercent=1.0; + sampleZoom=100.0/zoomPercent; + if (sampleZoom<0.01) sampleZoom=0.01; + sampleZoomAuto=false; + updateSampleTex=true; + } + ImGui::SameLine(); + if (sampleZoomAuto) { + if (ImGui::Button("100%")) { + sampleZoom=1.0; + sampleZoomAuto=false; + updateSampleTex=true; + } + } else { + if (ImGui::Button("Auto")) { + sampleZoomAuto=true; + updateSampleTex=true; + } + } + + ImGui::Separator(); + + ImVec2 avail=ImGui::GetContentRegionAvail(); // graph size determined here + if (ImGui::GetContentRegionAvail().y > (ImGui::GetContentRegionAvail().x / 2.0f)) { + avail=ImVec2(ImGui::GetContentRegionAvail().x,ImGui::GetContentRegionAvail().x / 2.0f); + } + avail.y-=ImGui::GetFontSize()+ImGui::GetStyle().ItemSpacing.y+ImGui::GetStyle().ScrollbarSize; + if (avail.y < 1.0){ //Prevents crash + avail.y = 1.0; + } + int availX=avail.x; + int availY=avail.y; + + + if (sampleZoomAuto) { + samplePos=0; + if (sample->samples<1 || avail.x<=0) { + sampleZoom=1.0; + } else { + sampleZoom=(double)sample->samples/avail.x; + } + if (sampleZoom!=prevSampleZoom) { + prevSampleZoom=sampleZoom; + updateSampleTex=true; + } + } + + if (sampleTex==NULL || sampleTexW!=avail.x || sampleTexH!=avail.y) { + if (sampleTex!=NULL) { + SDL_DestroyTexture(sampleTex); + sampleTex=NULL; + } + if (avail.x>=1 && avail.y>=1) { + logD("recreating sample texture."); + sampleTex=SDL_CreateTexture(sdlRend,SDL_PIXELFORMAT_ABGR8888,SDL_TEXTUREACCESS_STREAMING,avail.x,avail.y); + sampleTexW=avail.x; + sampleTexH=avail.y; + if (sampleTex==NULL) { + logE("error while creating sample texture! %s",SDL_GetError()); + } else { + updateSampleTex=true; + } + } + } + + if (sampleTex!=NULL) { + if (updateSampleTex) { + unsigned int* data=NULL; + int pitch=0; + logD("updating sample texture."); + if (SDL_LockTexture(sampleTex,NULL,(void**)&data,&pitch)!=0) { + logE("error while locking sample texture! %s",SDL_GetError()); + } else { + ImU32 bgColor=ImGui::GetColorU32(ImGuiCol_FrameBg); + ImU32 bgColorLoop=ImAlphaBlendColors(bgColor,ImGui::GetColorU32(ImGuiCol_FrameBgHovered,0.5)); + ImU32 lineColor=ImGui::GetColorU32(ImGuiCol_PlotLines); + ImU32 centerLineColor=ImAlphaBlendColors(bgColor,ImGui::GetColorU32(ImGuiCol_PlotLines,0.25)); + for (int i=0; iloopStart>=0 && sample->loopStart<(int)sample->samples && ((j+samplePos)*sampleZoom)>sample->loopStart) { + data[i*availX+j]=bgColorLoop; + } else { + data[i*availX+j]=bgColor; + } + } + } + if (availY>0) { + for (int i=availX*(availY>>1); i>1)); i++) { + data[i]=centerLineColor; + } + } + unsigned int xCoarse=samplePos; + unsigned int xFine=0; + unsigned int xAdvanceCoarse=sampleZoom; + unsigned int xAdvanceFine=fmod(sampleZoom,1.0)*16777216; + for (unsigned int i=0; i<(unsigned int)availX; i++) { + if (xCoarse>=sample->samples) break; + int y1, y2; + int totalAdvance=0; + if (sample->depth==8) { + y1=((unsigned char)sample->data8[xCoarse]^0x80)*availY/256; + } else { + y1=((unsigned short)sample->data16[xCoarse]^0x8000)*availY/65536; + } + xFine+=xAdvanceFine; + if (xFine>=16777216) { + xFine-=16777216; + totalAdvance++; + } + totalAdvance+=xAdvanceCoarse; + if (xCoarse>=sample->samples) break; + do { + if (sample->depth==8) { + y2=((unsigned char)sample->data8[xCoarse]^0x80)*availY/256; + } else { + y2=((unsigned short)sample->data16[xCoarse]^0x8000)*availY/65536; + } + if (y1>y2) { + y2^=y1; + y1^=y2; + y2^=y1; + } + if (y1<0) y1=0; + if (y1>=availY) y1=availY-1; + if (y2<0) y2=0; + if (y2>=availY) y2=availY-1; + for (int j=y1; j<=y2; j++) { + data[i+availX*(availY-j-1)]=lineColor; + } + if (totalAdvance>0) xCoarse++; + } while ((totalAdvance--)>0); + } + SDL_UnlockTexture(sampleTex); + } + updateSampleTex=false; + } + + ImGui::ImageButton(sampleTex,avail,ImVec2(0,0),ImVec2(1,1),0); + + ImVec2 rectMin=ImGui::GetItemRectMin(); + ImVec2 rectMax=ImGui::GetItemRectMax(); + ImVec2 rectSize=ImGui::GetItemRectSize(); + + if (ImGui::IsItemClicked()) { + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { + sampleDragActive=false; + sampleSelStart=0; + sampleSelEnd=sample->samples; + } else { + if (sample->samples>0 && (sample->depth==16 || sample->depth==8)) { + sampleDragStart=rectMin; + sampleDragAreaSize=rectSize; + sampleDrag16=(sample->depth==16); + sampleDragTarget=(sample->depth==16)?((void*)sample->data16):((void*)sample->data8); + sampleDragLen=sample->samples; + sampleDragActive=true; + sampleSelStart=-1; + sampleSelEnd=-1; + if (sampleDragMode) sample->prepareUndo(true); + processDrags(ImGui::GetMousePos().x,ImGui::GetMousePos().y); + } + } + } + + if (!sampleDragMode && ImGui::IsItemClicked(ImGuiMouseButton_Right)) { + ImGui::OpenPopup("SRightClick"); + } + + if (ImGui::BeginPopup("SRightClick",ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_AlwaysAutoResize)) { + if (ImGui::MenuItem("cut",BIND_FOR(GUI_ACTION_SAMPLE_CUT))) { + doAction(GUI_ACTION_SAMPLE_CUT); + } + if (ImGui::MenuItem("copy",BIND_FOR(GUI_ACTION_SAMPLE_COPY))) { + doAction(GUI_ACTION_SAMPLE_COPY); + } + if (ImGui::MenuItem("paste",BIND_FOR(GUI_ACTION_SAMPLE_PASTE))) { + doAction(GUI_ACTION_SAMPLE_PASTE); + } + if (ImGui::MenuItem("paste (replace)",BIND_FOR(GUI_ACTION_SAMPLE_PASTE_REPLACE))) { + doAction(GUI_ACTION_SAMPLE_PASTE_REPLACE); + } + if (ImGui::MenuItem("paste (mix)",BIND_FOR(GUI_ACTION_SAMPLE_PASTE_MIX))) { + doAction(GUI_ACTION_SAMPLE_PASTE_MIX); + } + if (ImGui::MenuItem("select all",BIND_FOR(GUI_ACTION_SAMPLE_SELECT_ALL))) { + doAction(GUI_ACTION_SAMPLE_SELECT_ALL); + } + ImGui::EndPopup(); + } + + String statusBar=sampleDragMode?"Draw":"Select"; + bool drawSelection=false; + + if (!sampleDragMode) { + if (sampleSelStart>=0 && sampleSelEnd>=0) { + int start=sampleSelStart; + int end=sampleSelEnd; + if (start>end) { + start^=end; + end^=start; + start^=end; + } + statusBar+=fmt::sprintf(" (%d-%d)",start,end); + drawSelection=true; + } + } + + if (ImGui::IsItemHovered()) { + int posX=-1; + int posY=0; + ImVec2 pos=ImGui::GetMousePos(); + pos.x-=rectMin.x; + pos.y-=rectMin.y; + + if (sampleZoom>0) { + posX=samplePos+pos.x*sampleZoom; + if (posX>(int)sample->samples) posX=-1; + } + posY=(0.5-pos.y/rectSize.y)*((sample->depth==8)?255:32767); + if (posX>=0) { + statusBar+=fmt::sprintf(" | (%d, %d)",posX,posY); + } + } + + if (drawSelection) { + int start=sampleSelStart; + int end=sampleSelEnd; + if (start>end) { + start^=end; + end^=start; + start^=end; + } + ImDrawList* dl=ImGui::GetWindowDrawList(); + ImVec2 p1=rectMin; + p1.x+=(start-samplePos)/sampleZoom; + + ImVec2 p2=ImVec2(rectMin.x+(end-samplePos)/sampleZoom,rectMax.y); + ImVec4 boundColor=uiColors[GUI_COLOR_ACCENT_PRIMARY]; + ImVec4 selColor=uiColors[GUI_COLOR_ACCENT_SECONDARY]; + boundColor.w*=0.5; + selColor.w*=0.25; + + if (p1.xrectMax.x) p1.x=rectMax.x; + + if (p2.xrectMax.x) p2.x=rectMax.x; + + dl->AddRectFilled(p1,p2,ImGui::GetColorU32(selColor)); + dl->AddLine(ImVec2(p1.x,p1.y),ImVec2(p1.x,p2.y),ImGui::GetColorU32(boundColor)); + if (start!=end) { + dl->AddLine(ImVec2(p2.x,p1.y),ImVec2(p2.x,p2.y),ImGui::GetColorU32(boundColor)); + } + } + + ImS64 scrollV=samplePos; + ImS64 availV=round(rectSize.x*sampleZoom); + ImS64 contentsV=MAX(sample->samples,MAX(availV,1)); + + if (ImGui::ScrollbarEx(ImRect(ImVec2(rectMin.x,rectMax.y),ImVec2(rectMax.x,rectMax.y+ImGui::GetStyle().ScrollbarSize)),ImGui::GetID("sampleScroll"),ImGuiAxis_X,&scrollV,availV,contentsV,0)) { + if (!sampleZoomAuto && samplePos!=scrollV) { + samplePos=scrollV; + updateSampleTex=true; + } + } + + if (sample->depth!=8 && sample->depth!=16) { + statusBar="Non-8/16-bit samples cannot be edited without prior conversion."; + } + + ImGui::EndDisabled(); + + ImGui::SetCursorPosY(ImGui::GetCursorPosY()+ImGui::GetStyle().ScrollbarSize); + ImGui::Text("%s",statusBar.c_str()); + } + } } if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_SAMPLE_EDIT; ImGui::End();