summaryrefslogtreecommitdiff
path: root/src/gui/floatinput.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/floatinput.cpp')
-rw-r--r--src/gui/floatinput.cpp257
1 files changed, 257 insertions, 0 deletions
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 <math.h>
+
+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;
+}