-/* 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
#include "vg/vg_ui.h"
#include "vg/vg_log.h"
+#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
+
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;
- };
- int persistent; /* Should this var be stored to cfg/auto.conf? */
+ u32 flags;
}
- vars[ 32 ];
+ 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;
}
vg_console;
-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 );
void _vg_console_println( const char *str );
return vg_console.enabled;
}
-VG_STATIC void vg_var_push( vg_var cv )
+VG_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_info( "Console variable '%s' registered\n", alias );
}
-VG_STATIC void vg_function_push( struct vg_cmd cmd )
+VG_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.function_count > vg_list_size(vg_console.functions) )
- vg_fatal_exit_loop( "Too many functions registered" );
+ vg_fatal_error( "Too many functions registered" );
+
+ vg_cmd *cmd = &vg_console.functions[ vg_console.function_count ++ ];
+
+ cmd->function = function;
+ cmd->poll_suggest = poll_suggest;
+ cmd->name = alias;
- vg_console.functions[ vg_console.function_count ++ ] = cmd;
+ vg_info( "Console function '%s' registered\n", alias );
}
-VG_STATIC void _vg_console_draw( void )
+VG_STATIC void _vg_console_draw(void)
{
+#if 0
if( !vg_console.enabled )
return;
vg_uictx.cursor[3] = fh;
ui_align_bottom();
- for( int i=0; i<console_lines; i ++ )
- {
+ for( int i=0; i<console_lines; i ++ ){
ptr --;
if( ptr < 0 )
/* suggestions */
- if( vg_console.suggestion_count )
- {
+ 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;
ui_fill_rect( vg_uictx.cursor, 0x77040404 );
vg_uictx.cursor[3] = fh;
- for( int i=0; i<vg_console.suggestion_count; i ++ )
- {
+ for( int i=0; i<vg_console.suggestion_count; i ++ ){
if( i == vg_console.suggestion_select )
ui_fill_rect( vg_uictx.cursor, 0x66a0e508 );
}
SDL_AtomicUnlock( &log_print_sl );
+#endif
}
VG_STATIC int _vg_console_list( int argc, char const *argv[] )
{
- for( int i=0; i<vg_console.function_count; i ++ )
- {
+ for( int i=0; i<vg_console.function_count; i ++ ){
struct vg_cmd *cmd = &vg_console.functions[ i ];
vg_info( "* %s\n", cmd->name );
}
- for( int i=0; i<vg_console.var_count; i ++ )
- {
+ for( int i=0; i<vg_console.var_count; i ++ ){
struct vg_var *cv = &vg_console.vars[ i ];
vg_info( "%s\n", cv->name );
}
int _test_break( int argc, const char *argv[] )
{
- vg_fatal_exit_loop( "Test crash from main, after loading (console)" );
+ vg_fatal_error( "Test crash from main, after loading (console)" );
return 0;
}
-VG_STATIC void _vg_console_init(void)
+int _vg_console_exec( int argc, const char *argv[] )
{
- vg_function_push( (struct vg_cmd)
- {
- .name = "list",
- .function = _vg_console_list
- });
+ if( argc < 1 ) return 0;
- vg_function_push( (struct vg_cmd)
- {
- .name = "crash",
- .function = _test_break
- });
-}
+ char path[256];
+ strcpy( path, "cfg/" );
+ strncat( path, argv[0], 250 );
-VG_STATIC void vg_console_load_autos(void)
-{
- /* Read and exec persistent commands */
- FILE *fp = fopen( "cfg/auto.conf", "r" );
- if( fp )
- {
+ 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_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_STATIC void vg_console_load_autos(void)
+{
+ _vg_console_exec( 1, (const char *[]){ "auto.conf" } );
}
VG_STATIC void _vg_console_write_persistent(void)
{
FILE *fp = fopen( "cfg/auto.conf", "w" );
- for( int i=0; i<vg_console.var_count; i ++ )
- {
+ for( int i=0; i<vg_console.var_count; i ++ ){
struct vg_var *cv = &vg_console.vars[i];
- if( cv->persistent )
- {
- 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;
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';
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;
}
VG_STATIC vg_var *vg_console_match_var( const char *kw )
{
- for( int i=0; i<vg_console.var_count; i ++ )
- {
+ for( int i=0; i<vg_console.var_count; i ++ ){
struct vg_var *cv = &vg_console.vars[ i ];
- if( !strcmp( cv->name, kw ) )
- {
+ if( !strcmp( cv->name, kw ) ){
return cv;
}
}
VG_STATIC vg_cmd *vg_console_match_cmd( const char *kw )
{
- for( int i=0; i<vg_console.function_count; i ++ )
- {
+ for( int i=0; i<vg_console.function_count; i ++ ){
struct vg_cmd *cmd = &vg_console.functions[ i ];
- if( !strcmp( cmd->name, kw ) )
- {
+ if( !strcmp( cmd->name, kw ) ){
return 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->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] );
}
- 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 )
return;
}
- else if( fn )
- {
+ else if( fn ){
fn->function( arg_count-1, args+1 );
return;
}
costs[k] = k;
u32 i = 0;
- for( u32 i=0; i<m; i++ )
- {
+ for( u32 i=0; i<m; i++ ){
costs[0] = i+1;
u32 corner = i;
- for( u32 j=0; j<n; j++ )
- {
+ for( u32 j=0; j<n; j++ ){
u32 upper = costs[j+1];
if( s1[i] == s2[j] )
costs[ j+1 ] = corner;
- else
- {
+ else{
u32 t = (upper < corner)? upper: corner;
costs[j+1] = ((costs[j] < t)? costs[j]: t) + 1;
}
int suff[32][32],
result = 0;
- for( int i=0; i<=m; i++ )
- {
- for( int j=0; j<=n; j++ )
- {
+ for( int i=0; i<=m; i++ ){
+ for( int j=0; j<=n; j++ ){
if( i == 0 || j == 0 )
suff[i][j] = 0;
- else if( s1[i-1] == s2[j-1] )
- {
+ else if( s1[i-1] == s2[j-1] ){
suff[i][j] = suff[i-1][j-1] + 1;
result = VG_MAX( result, suff[i][j] );
}
best_pos = j;
/* insert if good score */
- if( best_pos < vg_list_size( vg_console.suggestions ) )
- {
+ if( best_pos < vg_list_size( vg_console.suggestions ) ){
int start = VG_MIN( vg_console.suggestion_count,
vg_list_size( vg_console.suggestions )-1 );
for( int j=start; j>best_pos; j -- )
vg_console.suggestion_pastepos = args[token_count-1]-temp;
/* Score all our commands and cvars */
- if( token_count == 1 )
- {
- for( int i=0; i<vg_console.var_count; i++ )
- {
+ if( token_count == 1 ){
+ for( int i=0; i<vg_console.var_count; i++ ){
vg_var *cvar = &vg_console.vars[i];
console_suggest_score_text( cvar->name, args[0], 1 );
}
- for( int i=0; i<vg_console.function_count; i++ )
- {
+ for( int i=0; i<vg_console.function_count; i++ ){
vg_cmd *cmd = &vg_console.functions[i];
console_suggest_score_text( cmd->name, args[0], 1 );
}
}
- else
- {
+ else{
vg_cmd *cmd = vg_console_match_cmd( args[0] );
vg_var *var = vg_console_match_var( args[0] );
}
/* some post processing */
- for( int i=0; i<vg_console.suggestion_count; i++ )
- {
+ for( int i=0; i<vg_console.suggestion_count; i++ ){
vg_console.suggestion_maxlen = VG_MAX( vg_console.suggestion_maxlen,
vg_console.suggestions[i].len );
console_make_selection( &start, &end );
/* There is no selection */
- if( !(end-start) )
- {
+ if( !(end-start) ){
if( direction == 1 ) end = VG_MIN( end+1, strlen( vg_console.input ) );
else if( direction == -1 ) start = VG_MAX( start-1, 0 );
}
console_make_selection( &start, &end );
char buffer[512];
- if( end-start )
- {
+ if( end-start ){
memcpy( buffer, &vg_console.input[ start ], end-start );
buffer[ end-start ] = 0x00;
SDL_SetClipboardText( buffer );
{
char *target = &vg_console.input[ vg_console.suggestion_pastepos ];
- if( vg_console.suggestion_select == -1 )
- {
+ 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
- {
+ else{
strncpy( target,
vg_console.suggestions[ vg_console.suggestion_select ].str,
vg_list_size( vg_console.input )-1 );
VG_STATIC void _console_suggest_store_normal(void)
{
- if( vg_console.suggestion_select == -1 )
- {
+ 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_suggest_next(void)
{
- if( vg_console.suggestion_count )
- {
+ if( vg_console.suggestion_count ){
_console_suggest_store_normal();
vg_console.suggestion_select ++;
VG_STATIC void _console_suggest_prev(void)
{
- if( vg_console.suggestion_count )
- {
+ if( vg_console.suggestion_count ){
_console_suggest_store_normal();
vg_console.suggestion_select --;
VG_STATIC void console_proc_key( SDL_Keysym ev )
{
/* Open / close console */
- if( ev.sym == SDLK_BACKQUOTE )
- {
+ if( ev.sym == SDLK_BACKQUOTE ){
vg_console.enabled = !vg_console.enabled;
- if( vg_console.enabled )
+ if( vg_console.enabled ){
+ vg_info( "SDL_StartTextInput()\n" );
SDL_StartTextInput();
- else
+ }
+ else{
SDL_StopTextInput();
+ }
}
if( !vg_console.enabled ) return;
if( ev.mod & KMOD_ALT )
mod |= KMOD_ALT;
- for( int i=0; i<vg_list_size( mappings ); i++ )
- {
+ for( int i=0; i<vg_list_size( mappings ); i++ ){
struct console_mapping *mapping = &mappings[i];
- if( mapping->key == ev.sym )
- {
- if( mapping->mod == 0 )
- {
- if( mod == 0 )
- {
+ if( mapping->key == ev.sym ){
+ if( mapping->mod == 0 ){
+ if( mod == 0 ){
mapping->handler();
return;
}
}
- else if( (mod & mapping->mod) == mapping->mod )
- {
+ else if( (mod & mapping->mod) == mapping->mod ){
mapping->handler();
return;
}
{
const char *ptr = text;
- while( *ptr )
- {
+ while( *ptr ){
if( *ptr != '`' )
console_put_char( *ptr );
ptr ++;