@@ -55,6 +55,12 @@ namespace {
5555 return (std::pow (curvature, normalized) - 1 ) / (curvature - 1 );
5656 }
5757
58+ float dial_scroll_atan (float curvature, float val, float dval) {
59+ float normalized = std::atan (val*curvature) / std::atan (curvature);
60+ normalized = std::clamp (normalized+dval, -1 .f , 1 .f );
61+ return std::tan (normalized*std::atan (curvature)) / curvature;
62+ }
63+
5864 float level_meter_scale (float a) noexcept {
5965 return std::sqrt (a);
6066 }
@@ -184,7 +190,7 @@ namespace Aether {
184190 size_t param_idx,
185191 const pugl::MotionEvent& e,
186192 float sensitivity = 1 .f,
187- float curvature = 1 .f
193+ std::function< float ( float , float )> rescale_add = []( float val, float delta) { return val+delta; }
188194 );
189195 void dial_scroll_cb (
190196 size_t param_idx,
@@ -205,6 +211,7 @@ namespace Aether {
205211 std::string fill;
206212 std::string font_size = " 16sp" ;
207213 std::function<float (float )> to_display_val = [](float x){return x;};
214+ enum class CurvatureType { log, atan } curvature_type = CurvatureType::log;
208215 float curvature = 1 .f;
209216 bool logarithmic = false ;
210217 };
@@ -1250,15 +1257,16 @@ namespace Aether {
12501257 .label = " RATE" , .units = " Hz" ,
12511258 .radius = 20 , .cx = 186 , .cy = 30 ,
12521259 .fill = " #1b1d23" , .font_size = " 15sp" ,
1253- .curvature = 5 .f ,
1260+ .curvature = 10 .f ,
12541261 .logarithmic = true
12551262 });
12561263 attach_dial (delay, {
12571264 .param_id = 30 ,
12581265 .label = " DEPTH" , .units = " ms" ,
12591266 .radius = 20 , .cx = 186 , .cy = 100 ,
12601267 .fill = " #1b1d23" , .font_size = " 15sp" ,
1261- .curvature = 5 .f ,
1268+ .curvature_type = DialInfo::CurvatureType::atan,
1269+ .curvature = 20 .f ,
12621270 .logarithmic = true
12631271 });
12641272
@@ -1658,7 +1666,7 @@ namespace Aether {
16581666 size_t param_idx,
16591667 const pugl::MotionEvent& e,
16601668 float sensitivity,
1661- float curvature
1669+ std::function< float ( float , float )> rescale_add
16621670 ) {
16631671 if (e.state & pugl::Mod::PUGL_MOD_SHIFT) {
16641672 update_dsp_param (param_idx, parameter_infos[param_idx].dflt );
@@ -1673,15 +1681,9 @@ namespace Aether {
16731681 float dval = dx + dy;
16741682
16751683 float new_value = get_parameter (param_idx);
1676- if (curvature == 1 .f ) {
1677- new_value += parameter_infos[param_idx].range ()*sensitivity*dval;
1678- } else {
1679- float normalized = (new_value - parameter_infos[param_idx].min )/parameter_infos[param_idx].range ();
1680- normalized = std::log1p (normalized*(curvature - 1 )) / std::log (curvature);
1681- normalized += sensitivity*dval;
1682- normalized = (std::pow (curvature, normalized) - 1 ) / (curvature - 1 );
1683- new_value = parameter_infos[param_idx].range ()*normalized + parameter_infos[param_idx].min ;
1684- }
1684+ float normalized = (new_value - parameter_infos[param_idx].min )/parameter_infos[param_idx].range ();
1685+ normalized = rescale_add (normalized, sensitivity*dval);
1686+ new_value = parameter_infos[param_idx].range ()*normalized + parameter_infos[param_idx].min ;
16851687
16861688 if (parameter_infos[param_idx].integer ) {
16871689 float dv = std::trunc (new_value - get_parameter (param_idx));
@@ -1908,6 +1910,19 @@ namespace Aether {
19081910 };
19091911 }
19101912
1913+ UIElement::Connection dial_atan (size_t param_idx, float curvature) {
1914+ return {
1915+ .param_idx = param_idx,
1916+ .style =" value" ,
1917+ .in_range = {parameter_infos[param_idx].min , parameter_infos[param_idx].max },
1918+ .out_range = {" 0" , " 1" },
1919+ .interpolate = [=](float t, auto out) {
1920+ t = std::atan (t*curvature) / std::atan (curvature);
1921+ return interpolate_style<float >(t, out);
1922+ }
1923+ };
1924+ }
1925+
19111926 UIElement::Connection dial_logarithmic (size_t param_idx, float curvature) {
19121927 return {
19131928 .param_idx = param_idx,
@@ -1945,6 +1960,21 @@ namespace Aether {
19451960 return val_s + info.units ;
19461961 };
19471962
1963+ const auto rescale_fn = [=]() -> std::function<float (float , float )> {
1964+ using namespace std ::placeholders;
1965+ switch (info.curvature_type ) {
1966+ case DialInfo::CurvatureType::log:
1967+ if (info.curvature == 1 )
1968+ return [](float x, float dx){ return x+dx; };
1969+ else
1970+ return std::bind (dial_scroll_log, info.curvature , _1, _2);
1971+ break ;
1972+ case DialInfo::CurvatureType::atan:
1973+ return std::bind (dial_scroll_atan, info.curvature , _1, _2);
1974+ break ;
1975+ }
1976+ return {};
1977+ }();
19481978 g->add_child <Dial>({
19491979 .visible = true , .inert = false ,
19501980 .btn_press_callback = [=, this ](UIElement* elem, const auto & e){
@@ -1955,18 +1985,14 @@ namespace Aether {
19551985 dial->style .insert_or_assign (" label" , val_to_str (info.param_id ));
19561986 },
19571987 .motion_callback = [=, this ](UIElement* elem, const auto & e){
1958- dial_btn_motion_cb (info.param_id , e, 1 .f , info. curvature );
1988+ dial_btn_motion_cb (info.param_id , e, 1 .f , rescale_fn );
19591989
19601990 auto * dial = dynamic_cast <Dial*>(elem);
19611991 if (!info.label .empty ())
19621992 dial->style .insert_or_assign (" label" , val_to_str (info.param_id ));
19631993 },
19641994 .scroll_callback = [=, this ](UIElement* elem, const auto & e) {
1965- using namespace std ::placeholders;
1966- if (info.curvature == 1 )
1967- dial_scroll_cb (info.param_id , e, 1 .f );
1968- else
1969- dial_scroll_cb (info.param_id , e, 1 .f , std::bind (dial_scroll_log, info.curvature , _1, _2));
1995+ dial_scroll_cb (info.param_id , e, 1 .f , rescale_fn);
19701996
19711997 auto * dial = dynamic_cast <Dial*>(elem);
19721998 if (!info.label .empty ())
@@ -1977,9 +2003,11 @@ namespace Aether {
19772003 dial->style .insert_or_assign (" label" , info.label );
19782004 },
19792005 .connections = {
1980- info.curvature == 1 .f ?
1981- dial_linear (info.param_id ) :
1982- dial_logarithmic (info.param_id , info.curvature )
2006+ info.curvature_type == DialInfo::CurvatureType::log ?
2007+ (info.curvature == 1 .f ?
2008+ dial_linear (info.param_id ) :
2009+ dial_logarithmic (info.param_id , info.curvature )) :
2010+ dial_atan (info.param_id , info.curvature )
19832011 },
19842012 .style = {
19852013 {" cx" , to_string (info.cx ) + " sp" }, {" cy" , to_string (info.cy ) + " sp" },
0 commit comments