diff options
| author | Stijn Kuipers <stijnkuipers@gmail.com> | 2023-06-29 16:26:07 +0200 |
|---|---|---|
| committer | Stijn Kuipers <stijnkuipers@gmail.com> | 2023-06-29 16:26:07 +0200 |
| commit | fb5a321dd7c2848128b04b306f3e1e59c87a3f70 (patch) | |
| tree | a8ef6273f9f331ebb1971a9baf20a8c897955612 /sw/emu/knob.cpp | |
| parent | bae7568fd4dd0676b370be8548c7ec95d6521ba1 (diff) | |
| download | plinky-fb5a321dd7c2848128b04b306f3e1e59c87a3f70.tar.gz | |
Initial Filedump
Tadaaa!!
Diffstat (limited to 'sw/emu/knob.cpp')
| -rwxr-xr-x | sw/emu/knob.cpp | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/sw/emu/knob.cpp b/sw/emu/knob.cpp new file mode 100755 index 0000000..0883ab3 --- /dev/null +++ b/sw/emu/knob.cpp @@ -0,0 +1,123 @@ +#include "imgui.h" +#include <math.h> +#include <stdio.h> +#define PI 3.1415926535897932384626433832795f +typedef unsigned int u32; + +inline float lerp(float a, float b, float t) { return a+(b-a)*t; } +inline float saturate(float a) { return (a<0.f)?0.f:(a>1.f)?1.f:a; } +inline float length(float x, float y ){ return sqrtf(x*x+y*y); } + +int TactileButton(const char *label, float size) { + ImVec4 hilitecol = ImGui::GetStyle().Colors[ImGuiCol_FrameBg]; + hilitecol.x+=0.1f; + auto style=ImGui::GetStyle(); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + ImVec2 mouse_pos = ImGui::GetIO().MousePos; + ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates! + float w=size,/*ImGui::CalcItemWidth(),*/ h=size; + ImVec2 canvas_size = ImVec2(w,h); + ImVec2 centre=ImVec2(canvas_pos.x+w*0.5f,canvas_pos.y+h*0.45f); + ImGui::InvisibleButton(label, canvas_size); + draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y),true); // clip lines within the canvas (if we resize it, etc.) + bool active=ImGui::IsItemActive(); + draw_list->AddCircleFilled(ImVec2(centre.x,centre.y),h*0.45f,active ? 0x80ffffff : 0x40ffffff, 32); + ImVec2 labelsize=ImGui::CalcTextSize(label); + draw_list->AddText(ImVec2(centre.x-labelsize.x*0.5f,canvas_pos.y-labelsize.y+h*0.5f),ImColor(style.Colors[ImGuiCol_Text]),label); + draw_list->PopClipRect(); + return active; +} + +int Knob(const char *label, float &curval, float *randamount, float minval, float maxval, u32 encodercol, float size) +{ + + ImVec4 hilitecol = ImGui::GetStyle().Colors[ImGuiCol_FrameBg]; + hilitecol.x+=0.1f*(curval-minval)/(maxval-minval); +// hilitecol.z-=0.3f; + static ImVec2 click_pos; + static float click_val,click_rand; + static int grabrand; + static bool clickedbutton; + auto style=ImGui::GetStyle(); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + ImVec2 mouse_pos = ImGui::GetIO().MousePos; + ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates! + float w=size,/*ImGui::CalcItemWidth(),*/ h=size; + ImVec2 canvas_size = ImVec2(w,h); + ImVec2 centre=ImVec2(canvas_pos.x+w*0.5f,canvas_pos.y+h*0.45f); + ImGui::InvisibleButton(label, canvas_size); + draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y),true); // clip lines within the canvas (if we resize it, etc.) + float rad=h*0.4f; + ImColor bg= hilitecol;// : style.Colors[ImGuiCol_FrameBg]; + u32 tickcol=0x80ffffff; + if (encodercol==1) + encodercol=bg; + float angrange=encodercol ? 3.141592f : 2.5f; + float curang=lerp(-angrange,angrange,(curval-minval)/(maxval-minval)); + + draw_list->PathClear(); + draw_list->PathArcTo(centre,rad,-angrange - PI/2,angrange - PI/2,20); + draw_list->PathStroke(bg,false,rad*0.2f); + bool active=ImGui::IsItemActive(); + if (active && ImGui::IsMouseClicked(0)) { + clickedbutton=false; + click_pos=mouse_pos; click_val=curval; click_rand=randamount ? *randamount : 0.f; + grabrand=randamount && ImGui::GetIO().KeyShift; + if (length(mouse_pos.x-centre.x, mouse_pos.y-centre.y)<h*0.3f) + clickedbutton=true; + } + + if (!encodercol) { + draw_list->PathClear(); + draw_list->PathArcTo(centre,rad,-angrange-PI/2,curang-PI/2,20); + draw_list->PathStroke(tickcol,false,rad*0.2f); + } else { + draw_list->AddCircleFilled(ImVec2(centre.x,centre.y),h*0.3f,active && clickedbutton ? tickcol : encodercol, 32); + } + draw_list->AddCircleFilled(ImVec2(centre.x+0.f,centre.y-h*0.48f),h*0.02f,tickcol); + + ImColor barcol=(style.Colors[ImGuiCol_SliderGrabActive]); //:(i==hover)?ImGuiCol_CheckMark:ImGuiCol_ScrollbarGrab])) + if (randamount && *randamount>0.f) { + float minang=curang-angrange**randamount; if (minang<-angrange) minang=-angrange; + float maxang=minang+angrange**randamount; if (maxang>angrange) { maxang=angrange; minang=maxang-angrange**randamount*2.f; } + draw_list->PathClear(); + draw_list->PathArcTo(centre,rad,minang,maxang,20); + draw_list->PathStroke(barcol,false,rad*0.05f); + } + float rad0=rad*0.4f; + float rad2=rad+0.05f*h; + draw_list->AddLine(ImVec2(centre.x+rad0*sinf(curang),centre.y-rad0*cosf(curang)), ImVec2(centre.x+rad2*sinf(curang),centre.y-rad2*cosf(curang)),tickcol, 2.f); + int rv=0; + if (active) { + float angdelta = -atan2f(mouse_pos.x-centre.x, mouse_pos.y-centre.y) + atan2f(click_pos.x-centre.x,click_pos.y-centre.y); +// if (clickedbutton) +// angdelta=0.f; + if (angdelta>PI) angdelta-=PI*2.f; + if (angdelta<-PI) angdelta+=PI*2.f; + angdelta*=1.f/(angrange*2.f); +// ImVec2 delta(mouse_pos.x-click_pos.x,mouse_pos.y-click_pos.y); +// float angdelta=((fabsf(delta.x)>fabsf(delta.y)) ? delta.x : -delta.y) / h; + if (grabrand && randamount) + *randamount=saturate(click_rand+angdelta); + else + { + curval=click_val+angdelta*(maxval-minval); + if (!encodercol) { + if (curval<minval) curval=minval; + if (curval>maxval) curval=maxval; + } + } + click_pos=mouse_pos; click_val=curval; click_rand=randamount ? *randamount : 0.f; + } + draw_list->PopClipRect(); + +// char valuebuf[64]; + //snprintf(valuebuf,sizeof(valuebuf),"%.1f%%",curval*100.f); + ImVec2 labelsize=ImGui::CalcTextSize(label); +// ImVec2 valuesize=ImGui::CalcTextSize(valuebuf); + + draw_list->AddText(ImVec2(centre.x-labelsize.x*0.5f,canvas_pos.y-labelsize.y+h*0.5f),ImColor(style.Colors[ImGuiCol_Text]),label); +// if (!encodercol) +// draw_list->AddText(ImVec2(centre.x-valuesize.x*0.5f,canvas_pos.y+canvas_size.y-valuesize.y-2.f),ImColor(style.Colors[ImGuiCol_Text]),valuebuf); + return clickedbutton && active; +} |
