From f8b92ce3aa08b1445c9f956d8166830946562d12 Mon Sep 17 00:00:00 2001 From: navewindre Date: Wed, 3 Sep 2025 20:10:09 +0200 Subject: a --- src/gui/floatinput.cpp | 257 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 src/gui/floatinput.cpp (limited to 'src/gui/floatinput.cpp') diff --git a/src/gui/floatinput.cpp b/src/gui/floatinput.cpp new file mode 100644 index 0000000..9f7fdfe --- /dev/null +++ b/src/gui/floatinput.cpp @@ -0,0 +1,257 @@ +#include "base.h" +#include + +U8 gui_floatinput_is_bound_val( GUI_FLOATINPUT* input ) { + if( input->wraparound ) + return 0; + if( !isfinite( input->min ) || isnan( input->min ) ) + return 0; + if( !isfinite( input->max ) || isnan( input->max ) ) + return 0; + if( input->min > input->max ) + return 0; + return 1; +} + +CLR gui_floatinput_get_progress_clr( GUI_FLOATINPUT* input ) { + if( input->customclr ) { + if( gui_is_fg_window( input ) ) return input->bgcol; + else return CLR::blend( input->bgcol, CLR::BLACK(), 0.333f ); + } + + CLR clr_border = gui_is_fg_window( input )? ui_clr.border : ui_clr.border_inactive; + return CLR::blend( clr_border, CLR::BLACK(), 0.5f ); +} + +void gui_floatinput_draw_bound( GUI_FLOATINPUT* input ) { + I32 x = gui_relx( input ); + I32 y = gui_rely( input ); + I32 w = input->w; + I32 h = input->h; + + F32 min = input->min; + F32 max = input->max; + + F32 val = *input->pval; + F32 percent = (val - min) / (max - min); + if( percent > 1.f ) percent = 1.f; + if( percent < 0.f ) percent = 0.f; + + CLR clr_progress = gui_floatinput_get_progress_clr( input ); + gui_draw_frect( x+1, y+1, (I32)( (w-2) * percent ), h-2, clr_progress ); + + gui_draw_push_clip( (x+1) + (I32)( (w-2) * percent ), (y+1), (I32)( (w-2) * (1.f - percent) ), h-2 ); + gui_draw_str( x + 2, y + 2, ALIGN_L, FNT_JPN12, ui_clr.txt, input->name ); + gui_draw_str( x + w - 2, y + 2, ALIGN_R, FNT_JPN12, ui_clr.txt, input->valfmt, val ); + gui_draw_set_clip( (x+1), (y+1), (I32)( (w-2) * percent ), h-2 ); + gui_draw_str( x + 2, y + 2, ALIGN_L, FNT_JPN12, ui_clr.bg_alt, input->name ); + gui_draw_str( x + w - 2, y + 2, ALIGN_R, FNT_JPN12, ui_clr.bg_alt, input->valfmt, val ); + gui_draw_pop_clip(); +} + +void gui_floatinput_draw_unbound( GUI_FLOATINPUT* input ) { + I32 x = gui_relx( input ); + I32 y = gui_rely( input ); + I32 w = input->w; + + F32 val = *input->pval; + + gui_draw_str( x + 2, y + 2, ALIGN_L, FNT_JPN12, ui_clr.txt, input->name ); + gui_draw_str( x + w - 2, y + 2, ALIGN_R, FNT_JPN12, ui_clr.txt, input->valfmt, val ); + + I32 t1w, t2w, t3w; + gui_draw_get_str_bounds( &t1w, 0, FNT_JPN12, input->name ); + gui_draw_get_str_bounds( &t2w, 0, FNT_JPN12, input->valfmt, val ); + gui_draw_get_str_bounds( &t3w, 0, FNT_JPN12, "<->" ); + + I32 stw = t2w + t3w - 2; + I32 pos = w/2; + if( stw > pos ) + pos = stw; + + CLR handleclr = CLR::blend( ui_clr.txt, CLR::BLACK(), .7f ); + + if( t1w < w / 2 && t1w + t2w + t3w + 8 < w ) { + gui_draw_str( + x + w - pos, + y + 2, + ALIGN_C, + FNT_JPN12, + handleclr, + "<->" + ); + } + else { + gui_draw_str( x + w - pos + 8, y, ALIGN_C, FNT_JPN12, handleclr, "-" ); + gui_draw_str( x + w - pos + 8, y + 5, ALIGN_C, FNT_JPN12, handleclr, "+" ); + } +} + +void gui_floatinput_draw_fn( void* ptr ) { + GUI_FLOATINPUT* input = (GUI_FLOATINPUT*)ptr; + + I32 x = gui_relx( input ); + I32 y = gui_rely( input ); + I32 w = input->w; + I32 h = input->h; + + CLR clr_border = gui_is_fg_window( input )? ui_clr.border : ui_clr.border_inactive; + + gui_draw_frect( x, y, w, h, clr_border ); + gui_draw_frect( x+1, y+1, w-2, h-2, ui_clr.bg_sec ); + + if( !gui_floatinput_is_bound_val( input ) ) + gui_floatinput_draw_unbound( input ); + else + gui_floatinput_draw_bound( input ); +} + +void gui_floatinput_input_bound( GUI_FLOATINPUT* input ) { + if( !gui_mbutton_down( GUI_MBTNLEFT ) ) + return; + + I32 x = gui_relx( input ); + I32 w = input->w; + + F32 min = input->min; + F32 max = input->max; + + I32 mx, my; + gui_cursor_pos( &mx, &my ); + + F32 progress = (F32)(mx - x) / w; + if( progress < 0.f ) progress = 0.f; + if( progress > 1.f ) progress = 1.f; + + F32 nval = min + (max - min) * progress; + F32 rmn = remainderf( nval, input->step ); + *input->pval = nval - rmn; +} + +void gui_floatinput_input_unbound( GUI_FLOATINPUT* input ) { + if( !gui_mbutton_down( GUI_MBTNLEFT ) ) + return; + + I32 mx, my; + gui_cursor_pos( &mx, &my ); + + I32 dx = mx - input->lastmx; + if( dx ) + *input->pval += dx * input->step; + + F32 min = input->min; + F32 max = input->max; + + if( isfinite( min ) && *input->pval < min ) + *input->pval = input->wraparound? max : min; + if( isfinite( max ) && *input->pval > max ) + *input->pval = input->wraparound? min : max; + + F32 rmn = remainderf( *input->pval, input->step ); + *input->pval -= rmn; +} + +void gui_floatinput_input_scroll( GUI_FLOATINPUT* input ) { + U8 scroll = gui_mbutton_down( GUI_MBTNSCROLL ); + gui_capture_scroll(); + F32 oldval = *input->pval; + F32 nval = oldval; + + if( !scroll ) + return; + + if( scroll == 1 ) + nval += input->step; + else if( scroll == (U8)-1 ) + nval -= input->step; + + if( isfinite( input->min ) && nval < input->min ) + nval = input->wraparound? input->max : input->min; + if( isfinite( input->max ) && nval > input->max ) + nval = input->wraparound? input->min : input->max; + + F32 rmn = remainderf( nval, input->step ); + *input->pval = nval - rmn; + + if( input->cb ) + input->cb( input ); +} + +void gui_floatinput_input_fn( void* ptr ) { + GUI_FLOATINPUT* input = (GUI_FLOATINPUT*)ptr; + + I32 m1 = gui_mbutton_down( 0 ); + + I32 x = gui_relx( input ); + I32 y = gui_rely( input ); + I32 w = input->w; + I32 h = input->h; + + I32 mx, my; + gui_cursor_pos( &mx, &my ); + U8 inbounds = mx >= x && mx <= x + w && my >= y && my <= y + h; + + if( inbounds ) + gui_floatinput_input_scroll( input ); + + if( !input->held && m1 && !inbounds ) + input->heldoutbounds = 1; + if( !input->heldoutbounds && m1 && inbounds ) { + if( !input->held ) { + input->lastmx = mx; + input->held = 1; + return; + } + } + + if( !m1 ) { + input->heldoutbounds = 0; + input->held = 0; + return; + } + + if( input->heldoutbounds ) + return; + + F32 oldv = *input->pval; + if( !gui_floatinput_is_bound_val( input ) ) + gui_floatinput_input_unbound( input ); + else + gui_floatinput_input_bound( input ); + + if( input->cb && oldv != *input->pval ) { + input->cb( input ); + } + + input->lastmx = mx; +} + +struct GUI_FLOATINPUT* gui_floatinput( I32 x, I32 y, I32 w, const char* title, F32* pval, F32 min, F32 max, F32 step, const char* valfmt ) { + if( !gui_check_target() ) return 0; + + GUI_FLOATINPUT* input = new GUI_FLOATINPUT; + input->x = x; + input->y = y; + input->xbound = input->w = w; + input->ybound = input->h = 20; + strcpy( input->name, title ); + input->input_fn = gui_floatinput_input_fn; + input->draw_fn = gui_floatinput_draw_fn; + + input->cb = 0; + input->pval = pval; + input->min = min; + input->max = max; + input->step = step; + input->valfmt = valfmt; + + input->wraparound = 0; + input->customclr = 0; + input->held = 0; + + GUI_VIEW* parent = gui_get_view(); + parent->children.push( input ); + input->parent = parent; + + return input; +} -- cgit v1.2.3