X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=vg_console.h;h=1024b82ac468b0b6e6c08d557e7561e965ffc387;hb=76d234b7dc5e6500e8a54009b367e7620f11ef97;hp=5a137e3f05222366239791a68866745d474a0fda;hpb=fd8875baf8264b20731fb1bffaba4e1393beb189;p=vg.git diff --git a/vg_console.h b/vg_console.h index 5a137e3..1024b82 100644 --- a/vg_console.h +++ b/vg_console.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */ +/* Copyright (C) 2021-2023 Harry Godden (hgn) - All Rights Reserved */ #ifndef VG_CONSOLE_H #define VG_CONSOLE_H @@ -7,87 +7,49 @@ #define VG_GAME #endif -#include "vg/vg_ui.h" +#include "vg/vg_imgui.h" #include "vg/vg_log.h" -#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, \ - }); +#define VG_VAR_F32( NAME, ... ) \ + { u32 flags=0x00; __VA_ARGS__ ;\ + vg_console_reg_var( #NAME, &NAME, k_var_dtype_f32, flags ); } + +#define VG_VAR_I32( NAME, ... ) \ + { u32 flags=0x00; __VA_ARGS__ ;\ + vg_console_reg_var( #NAME, &NAME, k_var_dtype_i32, flags ); } + +#define VG_VAR_PERSISTENT 0x1 +#define VG_VAR_CHEAT 0x2 +#define VG_VAR_CHEATTOGGLE 0x4 typedef struct vg_var vg_var; typedef struct vg_cmd vg_cmd; -struct vg_console -{ - struct vg_var - { +struct vg_console{ + struct vg_var{ void *data; const char *name; - enum vg_var_dtype - { + enum vg_var_dtype{ k_var_dtype_i32, k_var_dtype_u32, k_var_dtype_f32 } data_type; - - union - { - struct - { - int min, max, clamp; - } - opt_i32; - - struct - { - float min, max; - int clamp; - } - opt_f32; - }; + u32 flags; - int persistent; /* Should this var be stored to cfg/auto.conf? */ + union{ u32 _u32; f32 _f32; i32 _i32; } defaults; } - vars[ 64 ]; + vars[ 128 ]; - struct vg_cmd - { + struct vg_cmd{ int (*function)( int argc, char const *argv[] ); void (*poll_suggest)( int argc, char const *argv[] ); const char *name; } functions[ 32 ]; - struct - { + struct { const char *str; int len; @@ -103,167 +65,80 @@ struct vg_console char input[96], input_copy[96]; - int cursor_user, cursor_pos, string_length; char history[32][96]; int history_last, history_pos, history_count; - int enabled; + i32 enabled, cheats; } -vg_console; - -VG_STATIC void vg_var_push( struct vg_var cv ); -VG_STATIC void vg_function_push( struct vg_cmd cmd ); +static vg_console; -VG_STATIC void _vg_console_draw( void ); +static void _vg_console_draw( void ); void _vg_console_println( const char *str ); -VG_STATIC int _vg_console_list( int argc, char const *argv[] ); -VG_STATIC void _vg_console_init(void); -VG_STATIC void _vg_console_write_persistent(void); -VG_STATIC void _vg_console_free(void); -VG_STATIC void vg_execute_console_input( const char *cmd ); +static int _vg_console_list( int argc, char const *argv[] ); +static void _vg_console_init(void); +static void _vg_console_write_persistent(void); +static void _vg_console_free(void); +static void vg_execute_console_input( const char *cmd ); /* * Console interface */ -VG_STATIC void console_make_selection( int* start, int* end ); -VG_STATIC void console_move_cursor( int* cursor0, int* cursor1, - int dir, int snap_together ); -VG_STATIC int console_makeroom( int datastart, int length ); -VG_STATIC int console_delete_char( int direction ); -VG_STATIC void console_to_clipboard(void); -VG_STATIC void console_clipboard_paste(void); -VG_STATIC void console_put_char( char c ); -VG_STATIC void console_history_get( char* buf, int entry_num ); -VG_STATIC int _vg_console_enabled(void); -VG_STATIC void console_proc_key( SDL_Keysym ev ); +static void console_history_get( char* buf, int entry_num ); +static int _vg_console_enabled(void); +static void console_proc_key( SDL_Keysym ev ); /* * Implementation */ -VG_STATIC int _vg_console_enabled(void) -{ +static int _vg_console_enabled(void){ return vg_console.enabled; } -VG_STATIC void vg_var_push( vg_var cv ) +static +void vg_console_reg_var( const char *alias, void *ptr, enum vg_var_dtype type, + u32 flags ) { if( vg_console.var_count > vg_list_size(vg_console.vars) ) - vg_fatal_exit_loop( "Too many vars registered" ); + vg_fatal_error( "Too many vars registered" ); - vg_info( "Console variable '%s' registered\n", cv.name ); - vg_console.vars[ vg_console.var_count ++ ] = cv; -} + vg_var *var = &vg_console.vars[ vg_console.var_count ++ ]; + var->name = alias; + var->data = ptr; + var->data_type = type; + var->flags = flags; -VG_STATIC void vg_function_push( struct vg_cmd cmd ) -{ - if( vg_console.function_count > vg_list_size(vg_console.functions) ) - vg_fatal_exit_loop( "Too many functions registered" ); + if ( type == k_var_dtype_f32 ) var->defaults._f32 = *((f32 *)ptr); + else if( type == k_var_dtype_i32 ) var->defaults._i32 = *((i32 *)ptr); + else if( type == k_var_dtype_u32 ) var->defaults._u32 = *((u32 *)ptr); - vg_console.functions[ vg_console.function_count ++ ] = cmd; + vg_info( "Console variable '%s' registered\n", alias ); } -VG_STATIC void _vg_console_draw( void ) +static +void vg_console_reg_cmd( const char *alias, + int (*function)(int argc, const char *argv[]), + void (*poll_suggest)(int argc, const char *argv[]) ) { - if( !vg_console.enabled ) - return; - - SDL_AtomicLock( &log_print_sl ); - - int ptr = vg_log.buffer_line_current; - int const fh = 14, - log_lines = 32; - int console_lines = VG_MIN( log_lines, vg_log.buffer_line_count ); - - vg_uictx.cursor[0] = 0; - vg_uictx.cursor[1] = 0; - vg_uictx.cursor[3] = log_lines*fh; - ui_fill_x(); - - /* - * log - */ - ui_new_node(); - { - ui_fill_rect( vg_uictx.cursor, 0x77181818 ); - - vg_uictx.cursor[3] = fh; - ui_align_bottom(); - - for( int i=0; i vg_list_size(vg_console.functions) ) + vg_fatal_error( "Too many functions registered" ); - vg_uictx.cursor[3] = fh; - for( int i=0; ifunction = function; + cmd->poll_suggest = poll_suggest; + cmd->name = alias; - SDL_AtomicUnlock( &log_print_sl ); + vg_info( "Console function '%s' registered\n", alias ); } -VG_STATIC int _vg_console_list( int argc, char const *argv[] ) -{ - for( int i=0; iname ); } - for( int i=0; iname ); } @@ -271,61 +146,80 @@ VG_STATIC int _vg_console_list( int argc, char const *argv[] ) return 0; } -int _test_break( int argc, const char *argv[] ) -{ - vg_fatal_exit_loop( "Test crash from main, after loading (console)" ); +int _test_break( int argc, const char *argv[] ){ + vg_fatal_error( "Test crash from main, after loading (console)" ); return 0; } -VG_STATIC void _vg_console_init(void) -{ - vg_function_push( (struct vg_cmd) - { - .name = "list", - .function = _vg_console_list - }); - - vg_function_push( (struct vg_cmd) - { - .name = "crash", - .function = _test_break - }); -} +int _vg_console_exec( int argc, const char *argv[] ){ + if( argc < 1 ) return 0; -VG_STATIC void vg_console_load_autos(void) -{ - /* Read and exec persistent commands */ - FILE *fp = fopen( "cfg/auto.conf", "r" ); - if( fp ) - { + char path[256]; + strcpy( path, "cfg/" ); + strncat( path, argv[0], 250 ); + + FILE *fp = fopen( path, "r" ); + if( fp ){ char line[256]; - while( fgets( line, sizeof( line ), fp ) ) - { + while( fgets( line, sizeof( line ), fp ) ){ line[ strcspn( line, "\r\n#" ) ] = 0x00; - if( line[0] != 0x00 ) - { + if( line[0] != 0x00 ){ vg_execute_console_input( line ); } } fclose( fp ); } + else{ + vg_error( "Could not open '%s'\n", path ); + } + + return 0; } -VG_STATIC void _vg_console_write_persistent(void) -{ +int _ccmd_vg_console_defaults( int argc, const char *argv[] ){ + for( int i=0; idata_type; + void *ptr = cv->data; + + if ( type == k_var_dtype_f32 ) *((f32 *)ptr) = cv->defaults._f32; + else if( type == k_var_dtype_i32 ) *((i32 *)ptr) = cv->defaults._i32; + else if( type == k_var_dtype_u32 ) *((u32 *)ptr) = cv->defaults._u32; + } + + return 0; +} + +static void _vg_console_init(void){ + vg_console_reg_cmd( "list", _vg_console_list, NULL ); + vg_console_reg_cmd( "crash", _test_break, NULL ); + vg_console_reg_cmd( "exec", _vg_console_exec, NULL ); + vg_console_reg_cmd( "defaults", _ccmd_vg_console_defaults, NULL ); + vg_console_reg_var( "cheats", &vg_console.cheats, k_var_dtype_i32, +#ifdef VG_DEVWINDOW + VG_VAR_PERSISTENT +#else + 0 +#endif + ); +} + +static void vg_console_load_autos(void){ + _vg_console_exec( 1, (const char *[]){ "auto.conf" } ); +} + +static void _vg_console_write_persistent(void){ FILE *fp = fopen( "cfg/auto.conf", "w" ); - for( int i=0; ipersistent ) - { - switch( cv->data_type ) - { + if( cv->flags & VG_VAR_PERSISTENT ){ + switch( cv->data_type ){ case k_var_dtype_i32: fprintf( fp, "%s %d\n", cv->name, *(i32 *)(cv->data) ); break; @@ -342,7 +236,7 @@ VG_STATIC void _vg_console_write_persistent(void) fclose( fp ); } -VG_STATIC void _vg_console_free(void) +static void _vg_console_free(void) { _vg_console_write_persistent(); } @@ -352,18 +246,15 @@ VG_STATIC void _vg_console_free(void) * returns number of tokens * dst must be as long as src */ -VG_STATIC int vg_console_tokenize( const char *src, char *dst, +static int vg_console_tokenize( const char *src, char *dst, const char *args[8] ) { int arg_count = 0, in_token = 0; - for( int i=0; 1; i ++ ) - { - if( src[i] ) - { - if( src[i] == ' ' || src[i] == '\t' ) - { + for( int i=0;; i ++ ){ + if( src[i] ){ + if( src[i] == ' ' || src[i] == '\t' ){ if( in_token ) dst[i] = '\0'; @@ -372,19 +263,16 @@ VG_STATIC int vg_console_tokenize( const char *src, char *dst, if( arg_count == 8 ) break; } - else - { + else{ dst[i] = src[i]; - if( !in_token ) - { + if( !in_token ){ args[ arg_count ++ ] = &dst[i]; in_token = 1; } } } - else - { + else{ dst[i] = '\0'; break; } @@ -393,13 +281,11 @@ VG_STATIC int vg_console_tokenize( const char *src, char *dst, return arg_count; } -VG_STATIC vg_var *vg_console_match_var( const char *kw ) +static vg_var *vg_console_match_var( const char *kw ) { - for( int i=0; iname, kw ) ) - { + if( !strcmp( cv->name, kw ) ){ return cv; } } @@ -407,13 +293,11 @@ VG_STATIC vg_var *vg_console_match_var( const char *kw ) return NULL; } -VG_STATIC vg_cmd *vg_console_match_cmd( const char *kw ) +static vg_cmd *vg_console_match_cmd( const char *kw ) { - for( int i=0; iname, kw ) ) - { + if( !strcmp( cmd->name, kw ) ){ return cmd; } } @@ -421,7 +305,7 @@ VG_STATIC vg_cmd *vg_console_match_cmd( const char *kw ) return NULL; } -VG_STATIC void vg_execute_console_input( const char *cmd ) +static void vg_execute_console_input( const char *cmd ) { char temp[512]; char const *args[8]; @@ -429,40 +313,40 @@ VG_STATIC void vg_execute_console_input( const char *cmd ) 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 ) - { + if( cv ){ /* Cvar Matched, try get value */ - if( arg_count >= 2 ) - { + if( arg_count >= 2 ){ + if( cv->flags & VG_VAR_CHEAT ){ + if( !vg_console.cheats ){ + vg_error( "variable is cheat protected\n" ); + return; + } + } + 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; + int *ptr = cv->data; + *ptr = atoi( args[1] ); + + if( cv->flags & VG_VAR_CHEATTOGGLE ){ + if( *ptr ){ + _ccmd_vg_console_defaults( 0, NULL ); + } + } } - 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_f32 ){ + float *ptr = cv->data; + *ptr = atof( args[1] ); } } - else - { + 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 ) @@ -473,8 +357,7 @@ VG_STATIC void vg_execute_console_input( const char *cmd ) return; } - else if( fn ) - { + else if( fn ){ fn->function( arg_count-1, args+1 ); return; } @@ -482,8 +365,7 @@ VG_STATIC void vg_execute_console_input( const char *cmd ) vg_error( "No command/var named '%s'. Use 'list' to view all\n", args[0] ); } -u32 str_lev_distance( const char *s1, const char *s2 ) -{ +u32 str_lev_distance( const char *s1, const char *s2 ){ u32 m = strlen( s1 ), n = strlen( s2 ); @@ -498,20 +380,17 @@ u32 str_lev_distance( const char *s1, const char *s2 ) costs[k] = k; u32 i = 0; - for( u32 i=0; ibest_pos; j -- ) @@ -588,8 +462,12 @@ VG_STATIC void console_suggest_score_text( const char *str, const char *input, } } -VG_STATIC void console_update_suggestions(void) +static void console_update_suggestions(void) { + if( vg_ui.focused_control_type != k_ui_control_textbox || + vg_ui.textbuf != vg_console.input ) + return; + vg_console.suggestion_count = 0; vg_console.suggestion_select = -1; vg_console.suggestion_maxlen = 0; @@ -601,43 +479,34 @@ VG_STATIC void console_update_suggestions(void) * - cursors should match */ - if( vg_console.cursor_pos == 0 ) - return; - - if( vg_console.cursor_pos != vg_console.cursor_user ) - return; - - if( vg_console.input[ vg_console.cursor_pos ] != '\0' ) - return; + if( vg_ui.textbox.cursor_pos == 0 ) return; + if( vg_ui.textbox.cursor_pos != vg_ui.textbox.cursor_user ) return; + if( vg_console.input[ vg_ui.textbox.cursor_pos ] != '\0' ) return; - if( (vg_console.input[ vg_console.cursor_pos -1 ] == ' ') || - (vg_console.input[ vg_console.cursor_pos -1 ] == '\t') ) + if( (vg_console.input[ vg_ui.textbox.cursor_pos -1 ] == ' ') || + (vg_console.input[ vg_ui.textbox.cursor_pos -1 ] == '\t') ) return; char temp[128]; const char *args[8]; int token_count = vg_console_tokenize( vg_console.input, temp, args ); - + if( !token_count ) return; vg_console.suggestion_pastepos = args[token_count-1]-temp; /* Score all our commands and cvars */ - if( token_count == 1 ) - { - for( int i=0; iname, args[0], 1 ); } - for( int i=0; iname, args[0], 1 ); } } - else - { + else{ vg_cmd *cmd = vg_console_match_cmd( args[0] ); vg_var *var = vg_console_match_var( args[0] ); @@ -649,8 +518,7 @@ VG_STATIC void console_update_suggestions(void) } /* some post processing */ - for( int i=0; iterminator to start */ - int remaining_length = strlen( vg_console.input )+1-end; - memmove( &vg_console.input[ start ], - &vg_console.input[ end ], - remaining_length ); - return start; + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, + &vg_ui.textbox.cursor_pos, 10000, 1 ); + _ui_textbox_put_char( ' ' ); + } } -VG_STATIC void console_to_clipboard(void) +static void _console_suggest_store_normal(void) { - int start, end; - console_make_selection( &start, &end ); - char buffer[512]; - - if( end-start ) - { - memcpy( buffer, &vg_console.input[ start ], end-start ); - buffer[ end-start ] = 0x00; - SDL_SetClipboardText( buffer ); - } + if( vg_console.suggestion_select == -1 ){ + char *target = &vg_console.input[ vg_console.suggestion_pastepos ]; + strcpy( vg_console.input_copy, target ); + } } -VG_STATIC void console_clipboard_paste(void) +static void _console_suggest_next(void) { - if( !SDL_HasClipboardText() ) - return; + if( vg_console.suggestion_count ){ + _console_suggest_store_normal(); - char *text = SDL_GetClipboardText(); + vg_console.suggestion_select ++; - if( !text ) - return; + if( vg_console.suggestion_select >= vg_console.suggestion_count ) + vg_console.suggestion_select = -1; + + _console_fetch_suggestion(); + } +} - int datastart = console_delete_char( 0 ); - int length = strlen( text ); - int cpylength = console_makeroom( datastart, length ); +static void _console_suggest_prev(void) +{ + if( vg_console.suggestion_count ){ + _console_suggest_store_normal(); + + vg_console.suggestion_select --; - memcpy( vg_console.input + datastart, text, cpylength); - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, cpylength, 1 ); - SDL_free( text ); + if( vg_console.suggestion_select < -1 ) + vg_console.suggestion_select = vg_console.suggestion_count-1; - console_update_suggestions(); + _console_fetch_suggestion(); + } } -VG_STATIC void console_put_char( char c ) +static void _vg_console_on_update( char *buf, u32 len ) { - if( !vg_console.enabled ) - return; - - vg_console.cursor_user = console_delete_char(0); - - if( console_makeroom( vg_console.cursor_user, 1 ) ) - vg_console.input[ vg_console.cursor_user ] = c; - - console_move_cursor( &vg_console.cursor_user, &vg_console.cursor_pos, 1, 1 ); + if( buf == vg_console.input ){ + console_update_suggestions(); + } } -VG_STATIC void console_history_get( char* buf, int entry_num ) +static void console_history_get( char* buf, int entry_num ) { if( !vg_console.history_count ) return; @@ -787,307 +608,151 @@ VG_STATIC void console_history_get( char* buf, int entry_num ) strcpy( buf, vg_console.history[ pick ] ); } -/* Receed secondary cursor */ -VG_STATIC void _console_left_select(void) -{ - console_move_cursor( &vg_console.cursor_user, NULL, -1, 0 ); -} - -/* Match and receed both cursors */ -VG_STATIC void _console_left(void) -{ - int cursor_diff = vg_console.cursor_pos - vg_console.cursor_user? 0: 1; - - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, -cursor_diff, 1 ); -} - -VG_STATIC void _console_right_select(void) -{ - console_move_cursor( &vg_console.cursor_user, NULL, 1, 0 ); -} - -VG_STATIC void _console_right(void) -{ - int cursor_diff = vg_console.cursor_pos - vg_console.cursor_user? 0: 1; - - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, +cursor_diff, 1 ); -} - -VG_STATIC void _console_down(void) -{ - vg_console.history_pos = VG_MAX( 0, vg_console.history_pos-1 ); - console_history_get( vg_console.input, vg_console.history_pos ); - - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, - vg_list_size(vg_console.input)-1, 1 ); -} - -VG_STATIC void _console_up(void) +static void _vg_console_on_up( char *buf, u32 len ) { - vg_console.history_pos = VG_MAX - ( - 0, - VG_MIN - ( - vg_console.history_pos+1, - VG_MIN - ( + if( buf == vg_console.input ){ + vg_console.history_pos = + VG_MAX + ( + 0, + VG_MIN + ( + vg_console.history_pos+1, + VG_MIN + ( vg_list_size( vg_console.history ), vg_console.history_count - 1 - ) - ) - ); - - console_history_get( vg_console.input, vg_console.history_pos ); - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, - vg_list_size(vg_console.input)-1, 1); -} - -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) -{ - console_move_cursor( &vg_console.cursor_user, NULL, -10000, 0 ); + ) + ) + ); + + console_history_get( vg_console.input, vg_console.history_pos ); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, + &vg_ui.textbox.cursor_pos, + vg_list_size(vg_console.input)-1, 1); + } } -VG_STATIC void _console_home(void) +static void _vg_console_on_down( char *buf, u32 len ) { - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, -10000, 1 ); -} + if( buf == vg_console.input ){ + vg_console.history_pos = VG_MAX( 0, vg_console.history_pos-1 ); + console_history_get( vg_console.input, vg_console.history_pos ); -VG_STATIC void _console_end_select(void) -{ - console_move_cursor( &vg_console.cursor_user, NULL, 10000, 0 ); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, + &vg_ui.textbox.cursor_pos, + vg_list_size(vg_console.input)-1, 1 ); + } } -VG_STATIC void _console_end(void) +static void _vg_console_on_enter( char *buf, u32 len ) { - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, - vg_list_size(vg_console.input)-1, 1 ); -} + if( buf == vg_console.input ){ + if( !strlen( vg_console.input ) ) + return; -VG_STATIC void _console_select_all(void) -{ - console_move_cursor( &vg_console.cursor_user, NULL, 10000, 0); - console_move_cursor( &vg_console.cursor_pos, NULL, -10000, 0); -} + vg_info( "%s\n", vg_console.input ); -VG_STATIC void _console_cut(void) -{ - console_to_clipboard(); - vg_console.cursor_user = console_delete_char(0); - vg_console.cursor_pos = vg_console.cursor_user; -} + if( strcmp( vg_console.input, + vg_console.history[ vg_console.history_last ]) ) + { + vg_console.history_last = ( vg_console.history_last + 1) % + vg_list_size(vg_console.history ); + vg_console.history_count = + VG_MIN( vg_list_size( vg_console.history ), + vg_console.history_count + 1 ); + strcpy( vg_console.history[ vg_console.history_last ], + vg_console.input ); + } -VG_STATIC void _console_enter(void) -{ - if( !strlen( vg_console.input ) ) - return; + vg_console.history_pos = -1; + vg_execute_console_input( vg_console.input ); + _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user, + &vg_ui.textbox.cursor_pos, -10000, 1 ); - vg_info( "%s\n", vg_console.input ); - - if( strcmp( vg_console.input, - vg_console.history[ vg_console.history_last ]) ) - { - vg_console.history_last = ( vg_console.history_last + 1) % - vg_list_size(vg_console.history ); - vg_console.history_count = - VG_MIN( vg_list_size( vg_console.history ), - vg_console.history_count + 1 ); - strcpy( vg_console.history[ vg_console.history_last ], - vg_console.input ); + vg_console.input[0] = '\0'; + console_update_suggestions(); } - - vg_console.history_pos = -1; - vg_execute_console_input( vg_console.input ); - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, -10000, 1 ); - vg_console.input[0] = '\0'; - - console_update_suggestions(); } -/* - * Suggestion controls - */ -VG_STATIC void _console_fetch_suggestion(void) +static void _vg_console_draw(void) { - char *target = &vg_console.input[ vg_console.suggestion_pastepos ]; + if( !vg_console.enabled ) return; - if( vg_console.suggestion_select == -1 ) - { - strcpy( target, vg_console.input_copy ); - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, 10000, 1 ); - } - else - { - strncpy( target, - vg_console.suggestions[ vg_console.suggestion_select ].str, - vg_list_size( vg_console.input )-1 ); + SDL_AtomicLock( &log_print_sl ); - console_move_cursor( &vg_console.cursor_user, - &vg_console.cursor_pos, 10000, 1 ); - console_put_char( ' ' ); - } -} + int ptr = vg_log.log_line_current; + int const fh = vg_ui.font->line_height, log_lines = 32; + int console_lines = VG_MIN( log_lines, vg_log.log_line_count ); -VG_STATIC void _console_suggest_store_normal(void) -{ - if( vg_console.suggestion_select == -1 ) - { - char *target = &vg_console.input[ vg_console.suggestion_pastepos ]; - strcpy( vg_console.input_copy, target ); - } -} + ui_rect rect_log = { 0, 0, vg.window_x, log_lines*fh }, + rect_input = { 0, log_lines*fh + 1, vg.window_x, fh*2 }, + rect_line = { 0, 0, vg.window_x, fh }; + + /* + * log + */ + u32 bg_colour = (ui_colour( k_ui_bg )&0x00ffffff)|0x9f000000; -VG_STATIC void _console_suggest_next(void) -{ - if( vg_console.suggestion_count ) - { - _console_suggest_store_normal(); + ui_fill( rect_log, bg_colour ); + rect_line[1] = rect_log[1]+rect_log[3]-fh; - vg_console.suggestion_select ++; + for( int i=0; i= vg_console.suggestion_count ) - vg_console.suggestion_select = -1; + if( ptr < 0 ) ptr = vg_list_size( vg_log.log )-1; - _console_fetch_suggestion(); - } -} - -VG_STATIC void _console_suggest_prev(void) -{ - if( vg_console.suggestion_count ) - { - _console_suggest_store_normal(); - - vg_console.suggestion_select --; - - if( vg_console.suggestion_select < -1 ) - vg_console.suggestion_select = vg_console.suggestion_count-1; - - _console_fetch_suggestion(); - } -} - -/* - * Handles binds - */ -VG_STATIC void console_proc_key( SDL_Keysym ev ) -{ - /* Open / close console */ - if( ev.sym == SDLK_BACKQUOTE ) - { - vg_console.enabled = !vg_console.enabled; - - if( vg_console.enabled ) - SDL_StartTextInput(); - else - SDL_StopTextInput(); + ui_text( rect_line, vg_log.log[ptr], 1, k_ui_align_left, 0 ); + rect_line[1] -= fh; } - - if( !vg_console.enabled ) return; + + /* + * Input area + */ - struct console_mapping - { - u16 mod; - SDL_Keycode key; - - void (*handler)(void); - } - mappings[] = - { - { 0, SDLK_LEFT, _console_left }, - { KMOD_SHIFT, SDLK_LEFT, _console_left_select }, - { 0, SDLK_RIGHT, _console_right }, - { KMOD_SHIFT, SDLK_RIGHT, _console_right_select }, - { 0, SDLK_DOWN, _console_down }, - { 0, SDLK_UP, _console_up }, - { 0, SDLK_BACKSPACE, _console_backspace }, - { 0, SDLK_DELETE, _console_delete }, - { 0, SDLK_HOME, _console_home }, - { KMOD_SHIFT, SDLK_HOME, _console_home_select }, - { 0, SDLK_END, _console_end }, - { KMOD_SHIFT, SDLK_END, _console_end_select }, - { KMOD_CTRL, SDLK_a, _console_select_all }, - { KMOD_CTRL, SDLK_c, console_to_clipboard }, - { KMOD_CTRL, SDLK_x, _console_cut }, - { KMOD_CTRL, SDLK_v, console_clipboard_paste }, - { 0, SDLK_RETURN, _console_enter }, - { KMOD_CTRL, SDLK_n, _console_suggest_next }, - { KMOD_CTRL, SDLK_p, _console_suggest_prev } + struct ui_textbox_callbacks callbacks = { + .up = _vg_console_on_up, + .down = _vg_console_on_down, + .change = _vg_console_on_update, + .enter = _vg_console_on_enter }; + ui_textbox( rect_input, NULL, + vg_console.input, vg_list_size(vg_console.input), 1, + UI_TEXTBOX_AUTOFOCUS, &callbacks ); - SDL_Keymod mod = 0; - - if( ev.mod & KMOD_SHIFT ) - mod |= KMOD_SHIFT; + /* + * suggestions + */ + if( vg_console.suggestion_count ){ + ui_rect rect_suggest; + rect_copy( rect_input, rect_suggest ); - if( ev.mod & KMOD_CTRL ) - mod |= KMOD_CTRL; + rect_suggest[0] += 6 + vg_ui.font->spacing*vg_console.suggestion_pastepos; + rect_suggest[1] += rect_input[3]; + rect_suggest[2] = vg_ui.font->spacing * vg_console.suggestion_maxlen; + rect_suggest[3] = vg_console.suggestion_count * fh; - if( ev.mod & KMOD_ALT ) - mod |= KMOD_ALT; + ui_fill( rect_suggest, bg_colour ); - for( int i=0; ikey == ev.sym ) - { - if( mapping->mod == 0 ) - { - if( mod == 0 ) - { - mapping->handler(); - return; - } - } - else if( (mod & mapping->mod) == mapping->mod ) - { - mapping->handler(); - return; + for( int i=0; i