X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=vg_console.h;h=26c6a6d20c00414eef330fa18f7500b4caf52dd9;hb=3b3420de0251e489082814e60dcc45e5e8842224;hp=8f8517cb7d41662a7afce1f31ca2e9c1d97d4fce;hpb=382274fcde3b501fa3979ef70d53dae2b02857ba;p=vg.git diff --git a/vg_console.h b/vg_console.h index 8f8517c..26c6a6d 100644 --- a/vg_console.h +++ b/vg_console.h @@ -10,22 +10,51 @@ #include "vg/vg_ui.h" #include "vg/vg_log.h" -typedef struct vg_convar vg_convar; +#define VG_VAR_F32_PERSISTENT( NAME ) \ + vg_var_push( (struct vg_var){ \ + .name = #NAME, \ + .data = &NAME, \ + .data_type = k_var_dtype_f32, \ + .persistent = 1 \ + }); + +#define VG_VAR_F32( NAME ) \ + vg_var_push( (struct vg_var){ \ + .name = #NAME, \ + .data = &NAME, \ + .data_type = k_var_dtype_f32, \ + }); + +#define VG_VAR_I32_PERSISTENT( NAME ) \ + vg_var_push( (struct vg_var){ \ + .name = #NAME, \ + .data = &NAME, \ + .data_type = k_var_dtype_i32, \ + .persistent = 1 \ + }); + +#define VG_VAR_I32( NAME ) \ + vg_var_push( (struct vg_var){ \ + .name = #NAME, \ + .data = &NAME, \ + .data_type = k_var_dtype_i32, \ + }); + +typedef struct vg_var vg_var; typedef struct vg_cmd vg_cmd; struct vg_console { - struct vg_convar + struct vg_var { void *data; - void (*update)(void); const char *name; - enum vg_convar_dtype + enum vg_var_dtype { - k_convar_dtype_i32, - k_convar_dtype_u32, - k_convar_dtype_f32 + k_var_dtype_i32, + k_var_dtype_u32, + k_var_dtype_f32 } data_type; @@ -47,11 +76,12 @@ struct vg_console int persistent; /* Should this var be stored to cfg/auto.conf? */ } - convars[ 32 ]; + vars[ 128 ]; struct vg_cmd { - int (*function)( int argc, char const *argv[] ); + int (*function)( int argc, char const *argv[] ); + void (*poll_suggest)( int argc, char const *argv[] ); const char *name; } functions[ 32 ]; @@ -69,7 +99,7 @@ struct vg_console suggestion_pastepos, suggestion_maxlen; - u32 convar_count, function_count; + u32 var_count, function_count; char input[96], input_copy[96]; @@ -82,7 +112,7 @@ struct vg_console } vg_console; -VG_STATIC void vg_convar_push( struct vg_convar cv ); +VG_STATIC void vg_var_push( struct vg_var cv ); VG_STATIC void vg_function_push( struct vg_cmd cmd ); VG_STATIC void _vg_console_draw( void ); @@ -116,13 +146,13 @@ VG_STATIC int _vg_console_enabled(void) return vg_console.enabled; } -VG_STATIC void vg_convar_push( vg_convar cv ) +VG_STATIC void vg_var_push( vg_var cv ) { - if( vg_console.convar_count > vg_list_size(vg_console.convars) ) - vg_fatal_exit_loop( "Too many convars registered" ); + if( vg_console.var_count > vg_list_size(vg_console.vars) ) + vg_fatal_exit_loop( "Too many vars registered" ); vg_info( "Console variable '%s' registered\n", cv.name ); - vg_console.convars[ vg_console.convar_count ++ ] = cv; + vg_console.vars[ vg_console.var_count ++ ] = cv; } VG_STATIC void vg_function_push( struct vg_cmd cmd ) @@ -196,10 +226,10 @@ VG_STATIC void _vg_console_draw( void ) ui_end_down(); - /* suggestions */ if( vg_console.suggestion_count ) { + vg_uictx.cursor[0] += UI_GLYPH_SPACING_X * vg_console.suggestion_pastepos; vg_uictx.cursor[1] += 2; vg_uictx.cursor[3] = vg_console.suggestion_count * fh; vg_uictx.cursor[2] = UI_GLYPH_SPACING_X * vg_console.suggestion_maxlen; @@ -232,9 +262,9 @@ VG_STATIC int _vg_console_list( int argc, char const *argv[] ) vg_info( "* %s\n", cmd->name ); } - for( int i=0; iname ); } @@ -288,21 +318,21 @@ VG_STATIC void _vg_console_write_persistent(void) { FILE *fp = fopen( "cfg/auto.conf", "w" ); - for( int i=0; ipersistent ) { switch( cv->data_type ) { - case k_convar_dtype_i32: + case k_var_dtype_i32: fprintf( fp, "%s %d\n", cv->name, *(i32 *)(cv->data) ); break; - case k_convar_dtype_u32: + case k_var_dtype_u32: fprintf( fp, "%s %u\n", cv->name, *(u32 *)(cv->data) ); break; - case k_convar_dtype_f32: + case k_var_dtype_f32: fprintf( fp, "%s %.5f\n", cv->name, *(float *)(cv->data ) ); break; } @@ -317,115 +347,137 @@ VG_STATIC void _vg_console_free(void) _vg_console_write_persistent(); } -VG_STATIC void vg_execute_console_input( const char *cmd ) +/* + * splits src into tokens and fills out args as pointers to those tokens + * returns number of tokens + * dst must be as long as src + */ +VG_STATIC int vg_console_tokenize( const char *src, char *dst, + const char *args[8] ) { - char temp[512]; - char const *args[9]; - int arg_count = 0; - - int in_token = 0; + int arg_count = 0, + in_token = 0; - /* Split string into tokens */ - for( int i = 0; i < vg_list_size( temp ); i ++ ) + for( int i=0; 1; i ++ ) { - if( cmd[i] ) + if( src[i] ) { - if( cmd[i] == ' ' || cmd[i] == '\t' ) + if( src[i] == ' ' || src[i] == '\t' ) { - temp[i] = '\0'; + if( in_token ) + dst[i] = '\0'; + in_token = 0; - if( arg_count == vg_list_size( args ) ) + if( arg_count == 8 ) break; } else { - temp[i] = cmd[i]; + dst[i] = src[i]; if( !in_token ) { - args[ arg_count ++ ] = temp + i; + args[ arg_count ++ ] = &dst[i]; in_token = 1; } } } else { - temp[i] = '\0'; + dst[i] = '\0'; break; } } - - if( arg_count == 0 ) - return; - - int data_int; - float data_float; - - for( int i=0; iname, args[0] ) ) + struct vg_var *cv = &vg_console.vars[ i ]; + if( !strcmp( cv->name, kw ) ) { - /* Cvar Matched, try get value */ - if( arg_count >= 2 ) - { - switch( cv->data_type ) - { - case k_convar_dtype_u32: - case k_convar_dtype_i32: - - data_int = atoi( args[1] ); - - *((int *)cv->data) = cv->opt_i32.clamp? - VG_MIN( VG_MAX(data_int, cv->opt_i32.min), cv->opt_i32.max ): - data_int; - - break; - case k_convar_dtype_f32: - data_float = atof( args[1] ); - *((float *)cv->data) = cv->opt_f32.clamp? - vg_minf( vg_maxf( data_float, cv->opt_f32.min), - cv->opt_f32.max ): - data_float; - break; - } + return cv; + } + } - if( cv->update ) - cv->update(); - } - else - { - switch( cv->data_type ) - { - case k_convar_dtype_i32: - vg_info( "= %d\n", *((int *)cv->data) ); - break; - case k_convar_dtype_u32: - vg_info( "= %u\n", *((u32 *)cv->data) ); - break; - case k_convar_dtype_f32: - vg_info( "= %.4f\n", *((float *)cv->data) ); - break; - } - } - - return; - } - } - - /* - * Find and excecute command - */ + return NULL; +} + +VG_STATIC vg_cmd *vg_console_match_cmd( const char *kw ) +{ for( int i=0; iname, args[0] ) ) + if( !strcmp( cmd->name, kw ) ) { - cmd->function( arg_count-1, args+1 ); - return; - } + return cmd; + } + } + + return NULL; +} + +VG_STATIC void vg_execute_console_input( const char *cmd ) +{ + char temp[512]; + char const *args[8]; + int arg_count = vg_console_tokenize( cmd, temp, args ); + + if( arg_count == 0 ) + return; + + int data_int; + float data_float; + + vg_var *cv = vg_console_match_var( args[0] ); + vg_cmd *fn = vg_console_match_cmd( args[0] ); + + assert( !(cv && fn) ); + + if( cv ) + { + /* Cvar Matched, try get value */ + if( arg_count >= 2 ) + { + if( (cv->data_type == k_var_dtype_u32) || + (cv->data_type == k_var_dtype_i32) ) + { + data_int = atoi( args[1] ); + + *((int *)cv->data) = cv->opt_i32.clamp? + VG_MIN( VG_MAX(data_int, cv->opt_i32.min), cv->opt_i32.max ): + data_int; + } + else if( cv->data_type == k_var_dtype_f32 ) + { + data_float = atof( args[1] ); + *((float *)cv->data) = cv->opt_f32.clamp? + vg_minf( vg_maxf( data_float, cv->opt_f32.min), + cv->opt_f32.max ): + data_float; + } + } + else + { + if( cv->data_type == k_var_dtype_i32 ) + vg_info( "= %d\n", *((int *)cv->data) ); + else if( cv->data_type == k_var_dtype_u32 ) + vg_info( "= %u\n", *((u32 *)cv->data) ); + else if( cv->data_type == k_var_dtype_f32 ) + vg_info( "= %.4f\n", *((float *)cv->data) ); + } + + return; } + else if( fn ) + { + fn->function( arg_count-1, args+1 ); + return; + } vg_error( "No command/var named '%s'. Use 'list' to view all\n", args[0] ); } @@ -499,12 +551,18 @@ u32 str_lcs( const char *s1, const char *s2 ) } /* str must not fuckoff ever! */ -VG_STATIC void console_suggest_score_text( const char *input, const char *str ) +VG_STATIC void console_suggest_score_text( const char *str, const char *input, + int minscore ) { + /* filter duplicates */ + for( int i=0; iname ); - } + for( int i=0; iname, args[0], 1 ); + } - for( int i=0; iname, args[0], 1 ); + } + } + else { - vg_cmd *cmd = &vg_console.functions[i]; - console_suggest_score_text( input_ref, cmd->name ); + vg_cmd *cmd = vg_console_match_cmd( args[0] ); + vg_var *var = vg_console_match_var( args[0] ); + + assert( !( cmd && var ) ); + + if( cmd ) + if( cmd->poll_suggest ) + cmd->poll_suggest( token_count-1, &args[1] ); } /* some post processing */ @@ -647,8 +724,6 @@ VG_STATIC int console_delete_char( int direction ) memmove( &vg_console.input[ start ], &vg_console.input[ end ], remaining_length ); - - console_update_suggestions(); return start; } @@ -776,12 +851,16 @@ VG_STATIC void _console_backspace(void) { vg_console.cursor_user = console_delete_char( -1 ); vg_console.cursor_pos = vg_console.cursor_user; + + console_update_suggestions(); } VG_STATIC void _console_delete(void) { vg_console.cursor_user = console_delete_char( 1 ); vg_console.cursor_pos = vg_console.cursor_user; + + console_update_suggestions(); } VG_STATIC void _console_home_select(void) @@ -853,15 +932,17 @@ VG_STATIC void _console_enter(void) */ VG_STATIC void _console_fetch_suggestion(void) { + char *target = &vg_console.input[ vg_console.suggestion_pastepos ]; + if( vg_console.suggestion_select == -1 ) { - strcpy( vg_console.input, vg_console.input_copy ); + strcpy( target, vg_console.input_copy ); console_move_cursor( &vg_console.cursor_user, &vg_console.cursor_pos, 10000, 1 ); } else { - strncpy( vg_console.input, + strncpy( target, vg_console.suggestions[ vg_console.suggestion_select ].str, vg_list_size( vg_console.input )-1 ); @@ -874,7 +955,10 @@ VG_STATIC void _console_fetch_suggestion(void) VG_STATIC void _console_suggest_store_normal(void) { if( vg_console.suggestion_select == -1 ) - strcpy( vg_console.input_copy, vg_console.input ); + { + char *target = &vg_console.input[ vg_console.suggestion_pastepos ]; + strcpy( vg_console.input_copy, target ); + } } VG_STATIC void _console_suggest_next(void)