From 08e4dd88fcb98ecb988af914fa7bdb00c5a59d0a Mon Sep 17 00:00:00 2001 From: hgn Date: Sun, 26 May 2024 17:32:01 +0100 Subject: [PATCH] ui api --- vg_audio.c | 37 +++--- vg_audio.h | 2 +- vg_console.c | 222 +++++++++++++++++++------------ vg_console.h | 6 +- vg_engine.c | 267 ++++++++++++++++++++++---------------- vg_engine.h | 34 ++++- vg_profiler.c | 29 +++-- vg_profiler.h | 2 +- vg_ui/imgui.c | 11 +- vg_ui/imgui.h | 10 +- vg_ui/imgui_impl_opengl.c | 21 +-- 11 files changed, 381 insertions(+), 260 deletions(-) diff --git a/vg_audio.c b/vg_audio.c index de57c9f..99b4382 100644 --- a/vg_audio.c +++ b/vg_audio.c @@ -1088,8 +1088,7 @@ static void audio_require_clip_loaded( audio_clip *clip ) * Debugging */ -void audio_debug_ui( - +void audio_debug_ui( ui_context *ctx, #ifdef VG_3D m4x4f #else @@ -1113,7 +1112,8 @@ void audio_debug_ui( */ float budget = ((double)vg_audio.samples_last / 44100.0) * 1000.0; - vg_profile_drawn( (struct vg_profile *[]){ &vg_prof_audio_decode, + vg_profile_drawn( ctx, + (struct vg_profile *[]){ &vg_prof_audio_decode, &vg_prof_audio_mix, &vg_prof_audio_dsp}, 3, budget, (ui_rect){ 4, VG_PROFILE_SAMPLE_COUNT*2 + 8, @@ -1130,23 +1130,26 @@ void audio_debug_ui( AUDIO_CHANNELS * 18 }; - if( vg_audio.debug_dsp ){ + if( vg_audio.debug_dsp ) + { ui_rect view_thing = { 4, vg.window_y-512-4, 512, 512 }; - ui_image( view_thing, vg_dsp.view_texture ); + ui_image( ctx, view_thing, &vg_dsp.view_texture ); } ui_rect overlap_buffer[ AUDIO_CHANNELS ]; u32 overlap_length = 0; /* Draw audio stack */ - for( int i=0; iallocated ){ - ui_fill( row, 0x50333333 ); + if( !ch->allocated ) + { + ui_fill( ctx, row, 0x50333333 ); continue; } @@ -1192,18 +1195,20 @@ void audio_debug_ui( ch->editable_state.volume, ch->name ); - ui_fill( row, 0xa0000000 | ch->colour ); - ui_text( row, perf, 1, k_ui_align_middle_left, 0 ); + ui_fill( ctx, row, 0xa0000000 | ch->colour ); + ui_text( ctx, row, perf, 1, k_ui_align_middle_left, 0 ); #ifdef VG_3D - if( AUDIO_FLAG_SPACIAL_3D ){ + if( AUDIO_FLAG_SPACIAL_3D ) + { v4f wpos; v3_copy( ch->editable_state.spacial_falloff, wpos ); wpos[3] = 1.0f; m4x4_mulv( mtx_pv, wpos, wpos ); - if( wpos[3] > 0.0f ){ + if( wpos[3] > 0.0f ) + { v2_muls( wpos, (1.0f/wpos[3]) * 0.5f, wpos ); v2_add( wpos, (v2f){ 0.5f, 0.5f }, wpos ); @@ -1213,9 +1218,11 @@ void audio_debug_ui( wr[2] = 1000; wr[3] = 17; - for( int j=0; j<12; j++ ){ + for( int j=0; j<12; j++ ) + { int collide = 0; - for( int k=0; k= wk[0])) && ((wr[1] <= wk[1]+wk[3]) && (wr[1]+wr[3] >= wk[1])) ) @@ -1231,7 +1238,7 @@ void audio_debug_ui( wr[1] += 18; } - ui_text( wr, perf, 1, k_ui_align_middle_left, 0 ); + ui_text( ctx, wr, perf, 1, k_ui_align_middle_left, 0 ); rect_copy( wr, overlap_buffer[ overlap_length ++ ] ); } } diff --git a/vg_audio.h b/vg_audio.h index ba10348..2787423 100644 --- a/vg_audio.h +++ b/vg_audio.h @@ -219,7 +219,7 @@ void audio_set_lfo_wave( int id, enum lfo_wave_type type, f32 coefficient ); void audio_set_lfo_frequency( int id, float freq ); int audio_channel_load_source( audio_channel *ch ); -void audio_debug_ui( +void audio_debug_ui( ui_context *ctx, #ifdef VG_3D m4x4f diff --git a/vg_console.c b/vg_console.c index 1913757..c3e1d0d 100644 --- a/vg_console.c +++ b/vg_console.c @@ -46,12 +46,14 @@ void vg_console_reg_cmd( const char *alias, static int _vg_console_list( int argc, char const *argv[] ) { - for( int i=0; iname ); } - for( int i=0; idata_type], @@ -65,25 +67,32 @@ static void vg_console_write_persistent(void) { FILE *fp = fopen( "cfg/auto.conf", "w" ); - if( !fp ){ + if( !fp ) + { vg_error( "Cannot open cfg/auto.conf\n" ); return; } - for( int i=0; iflags & VG_VAR_PERSISTENT ){ - if( cv->data_type == k_var_dtype_i32 ){ + if( cv->flags & VG_VAR_PERSISTENT ) + { + if( cv->data_type == k_var_dtype_i32 ) + { fprintf( fp, "%s %d\n", cv->name, *(i32 *)(cv->data) ); } - else if( cv->data_type == k_var_dtype_u32 ){ + else if( cv->data_type == k_var_dtype_u32 ) + { fprintf( fp, "%s %u\n", cv->name, *(u32 *)(cv->data) ); } - else if( cv->data_type == k_var_dtype_f32 ){ + else if( cv->data_type == k_var_dtype_f32 ) + { fprintf( fp, "%s %.5f\n", cv->name, *(float *)(cv->data ) ); } - else if( cv->data_type == k_var_dtype_str ){ + else if( cv->data_type == k_var_dtype_str ) + { vg_str *str = cv->data; if( str->buffer && (str->i > 0) ) fprintf( fp, "%s %s\n", cv->name, str->buffer ); @@ -110,9 +119,12 @@ static int vg_console_tokenize( const char *src, char *dst, int arg_count = 0, in_token = 0; - for( int i=0;; 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'; @@ -121,16 +133,19 @@ 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; } @@ -141,9 +156,11 @@ static int vg_console_tokenize( const char *src, char *dst, vg_var *vg_console_match_var( const char *kw ) { - for( int i=0; iname, kw ) ){ + if( !strcmp( cv->name, kw ) ) + { return cv; } } @@ -153,9 +170,11 @@ vg_var *vg_console_match_var( const char *kw ) vg_cmd *vg_console_match_cmd( const char *kw ) { - for( int i=0; iname, kw ) ){ + if( !strcmp( cmd->name, kw ) ) + { return cmd; } } @@ -175,26 +194,33 @@ void vg_execute_console_input( const char *cmd, bool silent ) vg_var *cv = vg_console_match_var( args[0] ); vg_cmd *fn = vg_console_match_cmd( args[0] ); - if( cv ){ + if( cv ) + { /* Cvar Matched, try get value */ - if( arg_count >= 2 ){ - if( cv->flags & VG_VAR_CHEAT ){ - if( !vg_console.cheats && !silent ){ + if( arg_count >= 2 ) + { + if( cv->flags & VG_VAR_CHEAT ) + { + if( !vg_console.cheats && !silent ) + { vg_error( "variable is cheat protected\n" ); return; } } if( (cv->data_type == k_var_dtype_u32) || - (cv->data_type == k_var_dtype_i32) ){ + (cv->data_type == k_var_dtype_i32) ) + { int *ptr = cv->data; *ptr = atoi( args[1] ); } - else if( cv->data_type == k_var_dtype_f32 ){ + else if( cv->data_type == k_var_dtype_f32 ) + { float *ptr = cv->data; *ptr = atof( args[1] ); } - else if( cv->data_type == k_var_dtype_str ){ + else if( cv->data_type == k_var_dtype_str ) + { vg_str *str = cv->data; vg_strfree( str ); vg_strnull( str, NULL, -1 ); @@ -205,14 +231,16 @@ void vg_execute_console_input( const char *cmd, bool silent ) } } } - 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 ) vg_info( "= %u\n", *((u32 *)cv->data) ); else if( cv->data_type == k_var_dtype_f32 ) vg_info( "= %.4f\n", *((float *)cv->data) ); - else if( cv->data_type == k_var_dtype_str ){ + else if( cv->data_type == k_var_dtype_str ) + { vg_str *str = cv->data; vg_info( "= '%s'\n", str->buffer ); } @@ -220,7 +248,8 @@ void vg_execute_console_input( const char *cmd, bool silent ) return; } - else if( fn ){ + else if( fn ) + { fn->function( arg_count-1, args+1 ); return; } @@ -229,7 +258,8 @@ void vg_execute_console_input( const char *cmd, bool silent ) 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 ); @@ -264,18 +294,22 @@ u32 str_lev_distance( const char *s1, const char *s2 ){ return costs[n]; } -u32 str_lcs( const char *s1, const char *s2 ){ +u32 str_lcs( const char *s1, const char *s2 ) +{ u32 m = VG_MIN( 31, strlen( s1 ) ), n = VG_MIN( 31, strlen( s2 ) ); 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] ); } @@ -308,7 +342,8 @@ void console_suggest_score_text( const char *str, const char *input, 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 -- ) @@ -324,10 +359,8 @@ void console_suggest_score_text( const char *str, const char *input, } } -static void console_update_suggestions(void) +static void console_update_suggestions( ui_context *ctx ) { - ui_context *ctx = ui_current_context(); - if( ctx->focused_control_type != k_ui_control_textbox || ctx->textbuf != vg_console.input ) return; @@ -359,18 +392,22 @@ static void console_update_suggestions(void) 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] ); @@ -380,7 +417,8 @@ static void console_update_suggestions(void) } /* some post processing */ - for( int i=0; itextbox.cursor_user, + _ui_textbox_move_cursor( ctx, + &ctx->textbox.cursor_user, &ctx->textbox.cursor_pos, 10000, 1 ); } - else{ + else + { strncpy( target, vg_console.suggestions[ vg_console.suggestion_select ].str, vg_list_size( vg_console.input )-1 ); - _ui_textbox_move_cursor( &ctx->textbox.cursor_user, + _ui_textbox_move_cursor( ctx, + &ctx->textbox.cursor_user, &ctx->textbox.cursor_pos, 10000, 1 ); - _ui_textbox_put_char( ' ' ); + _ui_textbox_put_char( ctx, ' ' ); } } 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 ); } } -static void console_suggest_next(void) +void console_suggest_next( ui_context *ctx ) { - if( vg_console.suggestion_count ){ + if( vg_console.suggestion_count ) + { _console_suggest_store_normal(); vg_console.suggestion_select ++; @@ -436,13 +478,14 @@ static void console_suggest_next(void) if( vg_console.suggestion_select >= vg_console.suggestion_count ) vg_console.suggestion_select = -1; - _console_fetch_suggestion(); + _console_fetch_suggestion( ctx ); } } -static void console_suggest_prev(void) +void console_suggest_prev( ui_context *ctx ) { - if( vg_console.suggestion_count ){ + if( vg_console.suggestion_count ) + { _console_suggest_store_normal(); vg_console.suggestion_select --; @@ -450,14 +493,15 @@ static void console_suggest_prev(void) if( vg_console.suggestion_select < -1 ) vg_console.suggestion_select = vg_console.suggestion_count-1; - _console_fetch_suggestion(); + _console_fetch_suggestion( ctx ); } } -static void _vg_console_on_update( char *buf, u32 len ) +static void _vg_console_on_update( ui_context *ctx, char *buf, u32 len ) { - if( buf == vg_console.input ){ - console_update_suggestions(); + if( buf == vg_console.input ) + { + console_update_suggestions( ctx ); } } @@ -472,10 +516,10 @@ static void console_history_get( char* buf, int entry_num ) strcpy( buf, vg_console.history[ pick ] ); } -static void _vg_console_on_up( char *buf, u32 len ) +static void _vg_console_on_up( ui_context *ctx, char *buf, u32 len ) { - ui_context *ctx = ui_current_context(); - if( buf == vg_console.input ){ + if( buf == vg_console.input ) + { vg_console.history_pos = VG_MAX ( @@ -492,29 +536,31 @@ static void _vg_console_on_up( char *buf, u32 len ) ); console_history_get( vg_console.input, vg_console.history_pos ); - _ui_textbox_move_cursor( &ctx->textbox.cursor_user, + _ui_textbox_move_cursor( ctx, + &ctx->textbox.cursor_user, &ctx->textbox.cursor_pos, - vg_list_size(vg_console.input)-1, 1); + vg_list_size(vg_console.input)-1, 1 ); } } -static void _vg_console_on_down( char *buf, u32 len ) +static void _vg_console_on_down( ui_context *ctx, char *buf, u32 len ) { - ui_context *ctx = ui_current_context(); - if( buf == vg_console.input ){ + 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 ); - _ui_textbox_move_cursor( &ctx->textbox.cursor_user, + _ui_textbox_move_cursor( ctx, + &ctx->textbox.cursor_user, &ctx->textbox.cursor_pos, vg_list_size(vg_console.input)-1, 1 ); } } -static void _vg_console_on_enter( char *buf, u32 len ) +static void _vg_console_on_enter( ui_context *ctx, char *buf, u32 len ) { - ui_context *ctx = ui_current_context(); - if( buf == vg_console.input ){ + if( buf == vg_console.input ) + { if( !strlen( vg_console.input ) ) return; @@ -534,11 +580,12 @@ static void _vg_console_on_enter( char *buf, u32 len ) vg_console.history_pos = -1; vg_execute_console_input( vg_console.input, 0 ); - _ui_textbox_move_cursor( &ctx->textbox.cursor_user, + _ui_textbox_move_cursor( ctx, + &ctx->textbox.cursor_user, &ctx->textbox.cursor_pos, -10000, 1 ); vg_console.input[0] = '\0'; - console_update_suggestions(); + console_update_suggestions( ctx ); } } @@ -554,20 +601,24 @@ int vg_console_exec( int argc, const char *argv[] ) strncat( path, argv[0], 250 ); FILE *fp = fopen( path, "r" ); - if( fp ){ + 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, silent ); } } fclose( fp ); } - else{ + else + { vg_error( "Could not open '%s'\n", path ); } @@ -593,14 +644,14 @@ void vg_console_load_autos(void) vg_console_exec( 2, (const char *[]){ "auto.conf", "silent" } ); } -void vg_console_draw(void) +void vg_console_draw( ui_context *ctx ) { if( !vg_console.enabled ) return; SDL_AtomicLock( &vg_log.print_sl ); int ptr = vg_log.log_line_current; - int const fh = vg_ui.ctx->font->sy, log_lines = 32; + int const fh = ctx->font->sy, log_lines = 32; int console_lines = VG_MIN( log_lines, vg_log.log_line_count ); ui_rect rect_log = { 0, 0, vg.window_x, log_lines*fh }, @@ -629,7 +680,8 @@ void vg_console_draw(void) * Input area */ - struct ui_textbox_callbacks callbacks = { + struct ui_textbox_callbacks callbacks = + { .up = _vg_console_on_up, .down = _vg_console_on_down, .change = _vg_console_on_update, @@ -660,12 +712,12 @@ void vg_console_draw(void) u32 text_colour; if( i == vg_console.suggestion_select ) { - ui_fill( ctx, rect_suggest, ui_colour( k_ui_orange ) ); + ui_fill( ctx, rect_suggest, ui_colour( ctx, k_ui_orange ) ); text_colour = ui_colourcont( ctx, k_ui_orange ); } - else text_colour = ui_colourcont( k_ui_bg ); + else text_colour = ui_colourcont( ctx, k_ui_bg ); - ui_text( rect_suggest, vg_console.suggestions[i].str, 1, + ui_text( ctx, rect_suggest, vg_console.suggestions[i].str, 1, k_ui_align_left, text_colour ); rect_suggest[1] += fh; diff --git a/vg_console.h b/vg_console.h index c24423a..27c11b8 100644 --- a/vg_console.h +++ b/vg_console.h @@ -72,7 +72,7 @@ void vg_console_reg_cmd( const char *alias, int (*function)(int argc, const char *argv[]), void (*poll_suggest)(int argc, const char *argv[]) ); void vg_console_load_autos(void); -void vg_console_draw(void); +void vg_console_draw( ui_context *ctx ); void vg_console_init(void); int vg_console_exec( int argc, const char *argv[] ); void vg_execute_console_input( const char *cmd, bool silent ); @@ -81,5 +81,5 @@ void console_suggest_score_text( const char *str, const char *input, int minscore ); vg_var *vg_console_match_var( const char *kw ); vg_cmd *vg_console_match_cmd( const char *kw ); -static void console_suggest_next(void); -static void console_suggest_prev(void); +void console_suggest_next( ui_context *ctx ); +void console_suggest_prev( ui_context *ctx ); diff --git a/vg_engine.c b/vg_engine.c index 254590f..3e11ae5 100644 --- a/vg_engine.c +++ b/vg_engine.c @@ -209,12 +209,14 @@ static void _vg_process_events(void) ui_defocus_all( &vg_ui.ctx ); } else if( (event.key.keysym.mod & KMOD_CTRL) && - event.key.keysym.sym == SDLK_n ){ - console_suggest_next(); + event.key.keysym.sym == SDLK_n ) + { + console_suggest_next( &vg_ui.ctx ); } else if( (event.key.keysym.mod & KMOD_CTRL ) && - event.key.keysym.sym == SDLK_p ){ - console_suggest_prev(); + event.key.keysym.sym == SDLK_p ) + { + console_suggest_prev( &vg_ui.ctx ); } else { @@ -322,7 +324,7 @@ static void _vg_gameloop_update(void) vg_profile_end( &vg_prof_update ); } -static void vg_settings_gui(void); +static void vg_settings_gui( ui_context *ctx ); static void _vg_gameloop_render(void) { vg_profile_begin( &vg_prof_render ); @@ -344,7 +346,7 @@ static void _vg_gameloop_render(void) if( vg_console.enabled ) { ui_ignore_input_frames( &vg_ui.ctx, 10 ); - vg_gui(); + vg_gui( &vg_ui.ctx ); ui_ignore_input_frames( &vg_ui.ctx, 0 ); ui_capture_mouse( &vg_ui.ctx, 1 ); vg_console_draw( &vg_ui.ctx ); @@ -533,21 +535,26 @@ static void _vg_gameloop(void){ if( vg.window_should_close ) break; - if( status == k_engine_status_crashed ){ + if( status == k_engine_status_crashed ) + { if( _vg_crashscreen() ) break; } - else{ - if( status == k_engine_status_running ){ + else + { + if( status == k_engine_status_running ) + { _vg_gameloop_update(); _vg_gameloop_render(); } - else{ + else + { vg_loader_render(); } } - if( vg.loader_ring > 0.01f ){ + if( vg.loader_ring > 0.01f ) + { vg_loader_render_ring( vg.loader_ring ); vg.loader_ring -= vg.time_frame_delta * 0.5f; } @@ -560,26 +567,22 @@ static void _vg_gameloop(void){ static void _vg_process_launch_opts_internal( int argc, char *argv[] ) { char *arg; - while( vg_argp( argc, argv ) ){ - if( (arg = vg_opt_arg( 'w' )) ){ + while( vg_argp( argc, argv ) ) + { + if( (arg = vg_opt_arg( 'w' )) ) vg.window_x = atoi( arg ); - } - if( (arg = vg_opt_arg( 'h' )) ){ + if( (arg = vg_opt_arg( 'h' )) ) vg.window_y = atoi( arg ); - } - if( (arg = vg_long_opt_arg( "samples" )) ){ + if( (arg = vg_long_opt_arg( "samples" )) ) vg.samples = VG_MAX( 0, VG_MIN( 8, atoi( arg ) ) ); - } - if( vg_long_opt( "use-libc-malloc" ) ){ + if( vg_long_opt( "use-libc-malloc" ) ) vg_mem.use_libc_malloc = 1; - } - if( vg_long_opt( "high-performance" ) ){ + if( vg_long_opt( "high-performance" ) ) vg.quality_profile = k_quality_profile_low; - } vg_launch_opt(); } @@ -594,7 +597,8 @@ static void _vg_init_window( const char *window_name ) #else vg_info( "SDL_INIT\n" ); - if( SDL_Init( SDL_INIT_VIDEO ) != 0 ){ + if( SDL_Init( SDL_INIT_VIDEO ) != 0 ) + { vg_error( "SDL_Init failed: %s\n", SDL_GetError() ); exit(0); } @@ -637,7 +641,8 @@ static void _vg_init_window( const char *window_name ) mode_index = 0; SDL_DisplayMode video_mode; - if( SDL_GetDesktopDisplayMode( display_index, &video_mode ) ){ + if( SDL_GetDesktopDisplayMode( display_index, &video_mode ) ) + { vg_error( "SDL_GetDesktopDisplayMode failed: %s\n", SDL_GetError() ); SDL_Quit(); exit(0); @@ -647,7 +652,8 @@ static void _vg_init_window( const char *window_name ) vg.window_x = video_mode.w; vg.window_y = video_mode.h; - if( vg.screen_mode == 2 ){ + if( vg.screen_mode == 2 ) + { vg.window_x = 1280; vg.window_y = 720; } @@ -669,11 +675,13 @@ static void _vg_init_window( const char *window_name ) vg_info( "CreateWindow( %d %d %u )\n", vg.window_x, vg.window_y, flags ); if((vg.window = SDL_CreateWindow( window_name, 0, 0, - vg.window_x, vg.window_y, flags ))){ + vg.window_x, vg.window_y, flags ))) + { if( vg.screen_mode == 2 ) SDL_SetWindowPosition( vg.window, video_mode.w-vg.window_x, 0 ); } - else{ + else + { vg_error( "SDL_CreateWindow failed: %s", SDL_GetError() ); exit(0); } @@ -690,17 +698,20 @@ static void _vg_init_window( const char *window_name ) /* * OpenGL loading */ - if( (vg.gl_context = SDL_GL_CreateContext(vg.window) )){ + if( (vg.gl_context = SDL_GL_CreateContext(vg.window) )) + { SDL_GL_GetDrawableSize( vg.window, &vg.window_x, &vg.window_y ); vg_success( "Window created (%dx%d)\n", vg.window_x, vg.window_y ); } - else{ + else + { vg_error( "SDL_GL_CreateContext failed: %s\n", SDL_GetError() ); SDL_Quit(); exit(0); } - if( !gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress) ) { + if( !gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress) ) + { vg_error( "Glad Failed to initialize\n" ); SDL_GL_DeleteContext( vg.gl_context ); SDL_Quit(); @@ -713,18 +724,22 @@ static void _vg_init_window( const char *window_name ) SDL_GL_SetSwapInterval(0); /* disable vsync while loading */ SDL_DisplayMode dispmode; - if( !SDL_GetWindowDisplayMode( vg.window, &dispmode ) ){ - if( dispmode.refresh_rate ){ + if( !SDL_GetWindowDisplayMode( vg.window, &dispmode ) ) + { + if( dispmode.refresh_rate ) + { vg.display_refresh_rate = dispmode.refresh_rate; } } - if( vg.display_refresh_rate < 25 || vg.display_refresh_rate > 300 ){ + if( vg.display_refresh_rate < 25 || vg.display_refresh_rate > 300 ) + { vg.display_refresh_rate = 60; } vg_info( "Display refresh rate: %d\n", dispmode.refresh_rate ); - if( !vg.fps_limit) vg.fps_limit = vg.display_refresh_rate; + if( !vg.fps_limit ) + vg.fps_limit = vg.display_refresh_rate; #endif } @@ -827,7 +842,7 @@ void vg_fatal_error( const char *fmt, ... ) */ #ifdef VG_GAME_SETTINGS -extern void vg_game_settings_gui( ui_rect panel ) ; +extern void vg_game_settings_gui( ui_context *ctx, ui_rect panel ) ; extern void vg_game_settings_init(void); #endif @@ -879,56 +894,66 @@ static vg_settings = { .options = vg_settings_dsp_enum, .option_count=2 }, }; -static void vg_settings_ui_draw_diff( ui_rect orig ){ +static void vg_settings_ui_draw_diff( ui_context *ctx, ui_rect orig ) +{ ui_rect l,r; ui_split( orig, k_ui_axis_v, -32, 0, l, r ); - ui_text( r, "*", 1, k_ui_align_middle_center, ui_colour(k_ui_blue) ); + ui_text( ctx, r, "*", 1, + k_ui_align_middle_center, ui_colour(ctx, k_ui_blue) ); } /* i32 settings * ------------------------------------------------------------------------- */ -static void vg_settings_ui_int( char *buf, u32 len ){ - for( u32 i=0, j=0; i= '0') && (buf[i] <= '9')) || (buf[i] == '\0') ) buf[j ++] = buf[i]; } } -struct ui_textbox_callbacks static vg_settings_ui_int_callbacks = { +struct ui_textbox_callbacks static vg_settings_ui_int_callbacks = +{ .change = vg_settings_ui_int }; -static bool vg_settings_ranged_i32_valid( struct vg_setting_ranged_i32 *prop ){ +static bool vg_settings_ranged_i32_valid( struct vg_setting_ranged_i32 *prop ) +{ if( prop->new_value < prop->min ) return 0; if( prop->new_value > prop->max ) return 0; return 1; } -static bool vg_settings_ranged_i32_diff( struct vg_setting_ranged_i32 *prop ){ +static bool vg_settings_ranged_i32_diff( struct vg_setting_ranged_i32 *prop ) +{ if( prop->new_value != *prop->actual_value ) return 1; else return 0; } -static bool vg_settings_ui_ranged_i32( struct vg_setting_ranged_i32 *prop, - ui_rect rect ){ +static bool vg_settings_ui_ranged_i32( ui_context *ctx, + struct vg_setting_ranged_i32 *prop, + ui_rect rect ) +{ ui_rect orig; rect_copy( rect, orig ); - ui_textbox( rect, prop->label, prop->buf, sizeof(prop->buf), + ui_textbox( ctx, rect, prop->label, prop->buf, sizeof(prop->buf), 1, 0, &vg_settings_ui_int_callbacks ); prop->new_value = atoi( prop->buf ); if( vg_settings_ranged_i32_diff( prop ) ) - vg_settings_ui_draw_diff( orig ); + vg_settings_ui_draw_diff( ctx, orig ); bool valid = vg_settings_ranged_i32_valid( prop ); - if( !valid ){ + if( !valid ) + { ui_rect _null, line; ui_split( orig, k_ui_axis_h, -1, 0, _null, line ); line[1] += 3; - ui_fill( line, ui_colour( k_ui_red ) ); + ui_fill( ctx, line, ui_colour( ctx, k_ui_red ) ); } return valid; @@ -951,16 +976,17 @@ bool vg_settings_enum_diff( struct vg_setting_enum *prop ) else return 0; } -bool vg_settings_enum( struct vg_setting_enum *prop, ui_rect rect ) +bool vg_settings_enum( ui_context *ctx, + struct vg_setting_enum *prop, ui_rect rect ) { ui_rect orig; rect_copy( rect, orig ); - ui_enum( rect, prop->label, + ui_enum( ctx, rect, prop->label, prop->options, prop->option_count, &prop->new_value ); if( vg_settings_enum_diff( prop ) ) - vg_settings_ui_draw_diff( orig ); + vg_settings_ui_draw_diff( ctx, orig ); return 1; } @@ -972,35 +998,40 @@ void ui_settings_enum_init( struct vg_setting_enum *prop ) /* .. */ -void vg_settings_ui_header( ui_rect inout_panel, const char *name ) +void vg_settings_ui_header( ui_context *ctx, + ui_rect inout_panel, const char *name ) { ui_rect rect; - ui_standard_widget( inout_panel, rect, 2 ); - ui_text( rect, name, 1, k_ui_align_middle_center, ui_colour(k_ui_fg+3) ); + ui_standard_widget( ctx, inout_panel, rect, 2 ); + ui_text( ctx, rect, name, 1, + k_ui_align_middle_center, ui_colour(ctx, k_ui_fg+3) ); } -bool vg_settings_apply_button( ui_rect inout_panel, bool validated ) +bool vg_settings_apply_button( ui_context *ctx, + ui_rect inout_panel, bool validated ) { ui_rect last_row; - ui_px height = ui_standard_widget_height( 1 ); + ui_px height = ui_standard_widget_height( ctx, 1 ); ui_split( inout_panel, k_ui_axis_h, -height, 8, inout_panel, last_row ); const char *string = "Apply"; - if( validated ){ - if( ui_button( last_row, string ) == 1 ) + if( validated ) + { + if( ui_button( ctx, last_row, string ) == 1 ) return 1; } - else{ + else + { ui_rect rect; - ui_standard_widget( last_row, rect, 1 ); - ui_fill( rect, ui_colour( k_ui_bg+1 ) ); - ui_outline( rect, -1, ui_colour( k_ui_red ), 0 ); + ui_standard_widget( ctx, last_row, rect, 1 ); + ui_fill( ctx, rect, ui_colour( ctx, k_ui_bg+1 ) ); + ui_outline( ctx, rect, -1, ui_colour( ctx, k_ui_red ), 0 ); - ui_rect t = { 0,0, ui_text_line_width( string ), 14 }; + ui_rect t = { 0,0, ui_text_line_width( ctx, string ), 14 }; ui_rect_center( rect, t ); - ui_text( t, string, 1, k_ui_align_left, ui_colour(k_ui_fg+3) ); + ui_text( ctx, t, string, 1, k_ui_align_left, ui_colour(ctx,k_ui_fg+3) ); } return 0; @@ -1034,7 +1065,8 @@ static void vg_settings_video_apply(void) SDL_SetWindowFullscreen( vg.window, SDL_WINDOW_FULLSCREEN_DESKTOP ); if( vg.screen_mode == 1 ) SDL_SetWindowFullscreen( vg.window, SDL_WINDOW_FULLSCREEN ); - if( vg.screen_mode == 2 ){ + if( vg.screen_mode == 2 ) + { SDL_SetWindowFullscreen( vg.window, 0 ); SDL_SetWindowSize( vg.window, 1280, 720 ); SDL_SetWindowPosition( vg.window, 16, 16 ); @@ -1049,11 +1081,12 @@ static void vg_settings_video_apply(void) vg.vsync = vg_settings.vsync.new_value; } -static void vg_settings_video_gui( ui_rect panel ){ +static void vg_settings_video_gui( ui_context *ctx, ui_rect panel ) +{ bool validated = 1; ui_rect rq; - ui_standard_widget( panel, rq, 1 ); - vg_settings_enum( &vg_settings.quality, rq ); + ui_standard_widget( ctx, panel, rq, 1 ); + vg_settings_enum( ctx, &vg_settings.quality, rq ); /* FIXME */ #if 0 @@ -1063,41 +1096,49 @@ static void vg_settings_video_gui( ui_rect panel ){ #endif /* frame timing */ - vg_settings_ui_header( panel, "Frame Timing" ); + vg_settings_ui_header( ctx, panel, "Frame Timing" ); ui_rect duo, d0,d1; - ui_standard_widget( panel, duo, 1 ); + ui_standard_widget( ctx, panel, duo, 1 ); ui_split_ratio( duo, k_ui_axis_v, 0.5f, 16, d0, d1 ); - vg_settings_enum( &vg_settings.vsync, d0 ); - validated &= vg_settings_ui_ranged_i32( &vg_settings.fps_limit, d1 ); + vg_settings_enum( ctx, &vg_settings.vsync, d0 ); + validated &= vg_settings_ui_ranged_i32( ctx, &vg_settings.fps_limit, d1 ); /* profiler */ - ui_standard_widget( panel, duo, 10 ); + ui_standard_widget( ctx, panel, duo, 10 ); int frame_target = vg.display_refresh_rate; if( !vg.vsync ) frame_target = vg.fps_limit; vg_profile_drawn( - (struct vg_profile *[]){ - &vg_prof_update,&vg_prof_render,&vg_prof_swap}, 3, + ctx, + (struct vg_profile *[]) + { + &vg_prof_update, + &vg_prof_render, + &vg_prof_swap + }, 3, (1.0f/(f32)frame_target)*1500.0f, duo, 1, 0 ); - ui_fill( (ui_rect){ duo[0], duo[1]+(duo[3]*2)/3, duo[2], 1 }, - ui_colour(k_ui_fg) ); + ui_fill( ctx, (ui_rect){ duo[0], duo[1]+(duo[3]*2)/3, duo[2], 1 }, + ui_colour(ctx, k_ui_fg) ); /* window spec */ - vg_settings_ui_header( panel, "Window Specification" ); + vg_settings_ui_header( ctx, panel, "Window Specification" ); - ui_standard_widget( panel, duo, 1 ); - vg_settings_enum( &vg_settings.screenmode, duo ); + ui_standard_widget( ctx, panel, duo, 1 ); + vg_settings_enum( ctx, &vg_settings.screenmode, duo ); - if( vg_settings_apply_button( panel, validated ) ) + if( vg_settings_apply_button( ctx, panel, validated ) ) vg_settings_video_apply(); } -static void vg_settings_audio_apply(void){ - if( vg_settings_enum_diff( &vg_settings.audio_devices ) ){ - if( vg_audio.sdl_output_device ){ +static void vg_settings_audio_apply(void) +{ + if( vg_settings_enum_diff( &vg_settings.audio_devices ) ) + { + if( vg_audio.sdl_output_device ) + { vg_info( "Closing audio device %d\n", vg_audio.sdl_output_device ); SDL_CloseAudioDevice( vg_audio.sdl_output_device ); } @@ -1105,16 +1146,20 @@ static void vg_settings_audio_apply(void){ vg_strfree( &vg_audio.device_choice ); if( vg_settings.audio_devices.new_value == -1 ){ } - else if( vg_settings.audio_devices.new_value == -2 ){ + else if( vg_settings.audio_devices.new_value == -2 ) + { vg_fatal_error( "Programming error\n" ); } - else { + else + { struct ui_enum_opt *selected = NULL, *oi; - for( int i=0; ivalue == vg_settings.audio_devices.new_value ){ + if( oi->value == vg_settings.audio_devices.new_value ) + { selected = oi; break; } @@ -1130,7 +1175,8 @@ static void vg_settings_audio_apply(void){ } audio_lock(); - if( vg_settings_enum_diff( &vg_settings.dsp ) ){ + if( vg_settings_enum_diff( &vg_settings.dsp ) ) + { *vg_settings.dsp.actual_value = vg_settings.dsp.new_value; } @@ -1138,15 +1184,16 @@ static void vg_settings_audio_apply(void){ audio_unlock(); } -static void vg_settings_audio_gui( ui_rect panel ){ +static void vg_settings_audio_gui( ui_context *ctx, ui_rect panel ) +{ ui_rect rq; - ui_standard_widget( panel, rq, 1 ); - vg_settings_enum( &vg_settings.audio_devices, rq ); + ui_standard_widget( ctx, panel, rq, 1 ); + vg_settings_enum( ctx, &vg_settings.audio_devices, rq ); - ui_standard_widget( panel, rq, 1 ); - vg_settings_enum( &vg_settings.dsp, rq ); + ui_standard_widget( ctx, panel, rq, 1 ); + vg_settings_enum( ctx, &vg_settings.dsp, rq ); - if( vg_settings_apply_button( panel, 1 ) ) + if( vg_settings_apply_button( ctx, panel, 1 ) ) vg_settings_audio_apply(); } @@ -1214,27 +1261,27 @@ void vg_settings_close(void) free( vg_settings.audio_devices.options ); } -static void vg_settings_gui(void) +static void vg_settings_gui( ui_context *ctx ) { ui_rect null; ui_rect screen = { 0, 0, vg.window_x, vg.window_y }; ui_rect window = { 0, 0, 1000, 700 }; ui_rect_center( screen, window ); - ui_capture_mouse( 1 ); + ui_capture_mouse( ctx, 1 ); - ui_fill( window, ui_colour( k_ui_bg+1 ) ); - ui_outline( window, 1, ui_colour( k_ui_bg+7 ), 0 ); + ui_fill( ctx, window, ui_colour( ctx, k_ui_bg+1 ) ); + ui_outline( ctx, window, 1, ui_colour( ctx, k_ui_bg+7 ), 0 ); ui_rect title, panel; ui_split( window, k_ui_axis_h, 28, 0, title, panel ); - ui_fill( title, ui_colour( k_ui_bg+7 ) ); - ui_text( title, "Settings", 1, k_ui_align_middle_center, - ui_colourcont(k_ui_bg+7) ); + ui_fill( ctx, title, ui_colour( ctx, k_ui_bg+7 ) ); + ui_text( ctx, title, "Settings", 1, k_ui_align_middle_center, + ui_colourcont(ctx, k_ui_bg+7) ); ui_rect quit_button; ui_split( title, k_ui_axis_v, title[2]-title[3], 2, title, quit_button ); - if( ui_button_text( quit_button, "X", 1 ) == k_ui_button_click ) + if( ui_button_text( ctx, quit_button, "X", 1 ) == k_ui_button_click ) { vg_settings_close(); return; @@ -1249,21 +1296,23 @@ static void vg_settings_gui(void) }; static i32 page = 0; - ui_tabs( panel, panel, opts, vg_list_size(opts), &page ); + ui_tabs( ctx, panel, panel, opts, vg_list_size(opts), &page ); - if( page == 0 ){ - vg_settings_video_gui( panel ); + if( page == 0 ) + { + vg_settings_video_gui( ctx, panel ); } else if( page == 1 ) - vg_settings_audio_gui( panel ); + vg_settings_audio_gui( ctx, panel ); #ifdef VG_GAME_SETTINGS else if( page == 2 ) - vg_game_settings_gui( panel ); + vg_game_settings_gui( ctx, panel ); #endif } -static int cmd_vg_settings_toggle( int argc, const char *argv[] ){ +static int cmd_vg_settings_toggle( int argc, const char *argv[] ) +{ vg_settings_open(); return 0; } diff --git a/vg_engine.h b/vg_engine.h index 4f56768..bd73a5d 100644 --- a/vg_engine.h +++ b/vg_engine.h @@ -107,7 +107,7 @@ extern void vg_fixed_update(void); extern void vg_post_update(void); extern void vg_render(void); -extern void vg_gui(void); +extern void vg_gui( ui_context *ctx ); void vg_settings_open(void); void vg_settings_close(void); @@ -223,6 +223,29 @@ struct vg_engine } extern vg; +struct vg_ui +{ + GLuint vao, vbo, ebo; + m3x3f pv; + ui_context ctx; + GLuint tex_glyphs; + v2f inverse_font_sheet; + +#ifdef VG_ANDROID +#else + SDL_Cursor *cursor_map[ k_ui_cursor_max ]; +#endif + + /* at some point this should be implementation specific? */ + v4f colour; + f32 frosting; + v2f bg_inverse_ratio; + GLuint tex_bg; +} +extern vg_ui; +void vg_ui_set_screen( i32 width, i32 height ); +void vg_ui_set_mouse_pos( ui_px x, ui_px y ); + struct vg_setting_enum { i32 new_value, *actual_value; @@ -241,10 +264,13 @@ struct vg_setting_ranged_i32 void ui_settings_ranged_i32_init( struct vg_setting_ranged_i32 *prop ); void ui_settings_enum_init( struct vg_setting_enum *prop ); -bool vg_settings_enum( struct vg_setting_enum *prop, ui_rect rect ); bool vg_settings_enum_diff( struct vg_setting_enum *prop ); -void vg_settings_ui_header( ui_rect inout_panel, const char *name ); -bool vg_settings_apply_button( ui_rect inout_panel, bool validated ); +bool vg_settings_enum( ui_context *ctx, + struct vg_setting_enum *prop, ui_rect rect ); +void vg_settings_ui_header( ui_context *ctx, + ui_rect inout_panel, const char *name ); +bool vg_settings_apply_button( ui_context *ctx, + ui_rect inout_panel, bool validated ); enum engine_status _vg_engine_status(void); enum vg_thread_purpose vg_thread_purpose(void); diff --git a/vg_profiler.c b/vg_profiler.c index 3684ae8..79e0723 100644 --- a/vg_profiler.c +++ b/vg_profiler.c @@ -37,7 +37,7 @@ void vg_profile_end( struct vg_profile *profile ) } } -void vg_profile_drawn( struct vg_profile **profiles, u32 count, +void vg_profile_drawn( ui_context *ctx, struct vg_profile **profiles, u32 count, f64 budget, ui_rect panel, int dir, i32 normalize ) { @@ -50,29 +50,33 @@ void vg_profile_drawn( struct vg_profile **profiles, u32 count, f64 sh = (f32)panel[3^dir] / (f32)VG_PROFILE_SAMPLE_COUNT, sw = (f32)panel[2^dir]; - ui_fill( panel, 0xa0000000 ); + ui_fill( ctx, panel, 0xa0000000 ); if( count > 8 ) vg_fatal_error( "Too many profiles\n" ); f64 avgs[8]; u32 colours[8]; - for( u32 i=0; isamples[i] * rate_mul; } - for( int j=0; jsamples[i] * rate_mul, px = (total / budget) * sw, wx = (sample / budget) * sw; @@ -82,7 +86,7 @@ void vg_profile_drawn( struct vg_profile **profiles, u32 count, block[1^dir] = panel[1^dir] + (f32)i*sh; block[2^dir] = VG_MAX( 1, wx-1 ); block[3^dir] = ceilf(sh)-1; - ui_fill( block, colours[j] ); + ui_fill( ctx, block, colours[j] ); total += sample; avgs[j] += sample; @@ -92,18 +96,21 @@ void vg_profile_drawn( struct vg_profile **profiles, u32 count, char infbuf[64]; snprintf( infbuf, 64, "accuracy: %.7fms", rate_mul ); - ui_text( (ui_rect){ panel[0] + 4, + ui_text( ctx, + (ui_rect){ panel[0] + 4, panel[1] + panel[3] - 14, 500, 30 }, infbuf, 1, k_ui_align_left, 0 ); - for( int i=0; iname ); - ui_text( (ui_rect){ panel[0] + 4, + ui_text( ctx, + (ui_rect){ panel[0] + 4, panel[1] + panel[3] + 4 + i*14, panel[2]-8, 14 }, infbuf, 1, k_ui_align_left, 0 ); diff --git a/vg_profiler.h b/vg_profiler.h index 5de304e..4cad16b 100644 --- a/vg_profiler.h +++ b/vg_profiler.h @@ -25,7 +25,7 @@ struct vg_profile void vg_profile_begin( struct vg_profile *profile ); void vg_profile_increment( struct vg_profile *profile ); void vg_profile_end( struct vg_profile *profile ); -void vg_profile_drawn( struct vg_profile **profiles, u32 count, +void vg_profile_drawn( ui_context *ctx, struct vg_profile **profiles, u32 count, f64 budget, ui_rect panel, int dir, i32 normalize ); void vg_profiler_init(void); diff --git a/vg_ui/imgui.c b/vg_ui/imgui.c index 7ad4c46..8886652 100644 --- a/vg_ui/imgui.c +++ b/vg_ui/imgui.c @@ -624,7 +624,7 @@ void ui_defocus_all( ui_context *ctx ) { ctx->stop_text_input(); if( ctx->textbox.callbacks.escape ) - ctx->textbox.callbacks.escape(); + ctx->textbox.callbacks.escape( ctx ); } ctx->focused_control_id = NULL; @@ -1205,8 +1205,7 @@ static void _ui_textbox_change_callback( ui_context *ctx ) { if( ctx->textbox.callbacks.change ) { - ctx->textbox.callbacks.change( ctx->textbuf, - ctx->textbox.len ); + ctx->textbox.callbacks.change( ctx, ctx->textbuf, ctx->textbox.len ); /* we gave permission to modify the buffer in this callback so.. */ int len = strlen( ctx->textbuf ); @@ -1323,7 +1322,7 @@ void _ui_textbox_up( ui_context *ctx ) { if( ctx->textbox.callbacks.up ) { - ctx->textbox.callbacks.up( ctx->textbuf, ctx->textbox.len ); + ctx->textbox.callbacks.up( ctx, ctx->textbuf, ctx->textbox.len ); } } } @@ -1387,7 +1386,7 @@ void _ui_textbox_down( ui_context *ctx ) { if( ctx->textbox.callbacks.down ) { - ctx->textbox.callbacks.down( ctx->textbuf, ctx->textbox.len ); + ctx->textbox.callbacks.down( ctx, ctx->textbuf, ctx->textbox.len ); } } } @@ -1499,7 +1498,7 @@ void _ui_textbox_enter( ui_context *ctx ) ui_ignore_input_frames( ctx, 2 ); if( ctx->textbox.callbacks.enter ) - ctx->textbox.callbacks.enter( ctx->textbuf, ctx->textbox.len ); + ctx->textbox.callbacks.enter( ctx, ctx->textbuf, ctx->textbox.len ); if( ctx->focused_control_type != k_ui_control_textbox ) return; diff --git a/vg_ui/imgui.h b/vg_ui/imgui.h index 2c4eb38..32e636a 100644 --- a/vg_ui/imgui.h +++ b/vg_ui/imgui.h @@ -146,11 +146,11 @@ struct ui_context struct ui_textbox_callbacks { - void (*enter)( char *, u32 ), - (*up)( char *, u32 ), - (*down)( char *, u32 ), - (*change)( char *, u32 ), - (*escape)( void ); + void (*enter)( ui_context *ctx, char *, u32 ), + (*up)( ui_context *ctx, char *, u32 ), + (*down)( ui_context *ctx, char *, u32 ), + (*change)( ui_context *ctx, char *, u32 ), + (*escape)( ui_context *ctx ); } callbacks; } diff --git a/vg_ui/imgui_impl_opengl.c b/vg_ui/imgui_impl_opengl.c index 2e0bdc6..f56f4d9 100644 --- a/vg_ui/imgui_impl_opengl.c +++ b/vg_ui/imgui_impl_opengl.c @@ -3,26 +3,7 @@ #include "vg_ui/imgui.h" #include "vg_engine.h" -struct -{ - GLuint vao, vbo, ebo; - m3x3f pv; - ui_context ctx; - GLuint tex_glyphs; - v2f inverse_font_sheet; - -#ifdef VG_ANDROID -#else - SDL_Cursor *cursor_map[ k_ui_cursor_max ]; -#endif - - /* at some point this should be implementation specific? */ - v4f colour; - f32 frosting; - v2f bg_inverse_ratio; - GLuint tex_bg; -} -static vg_ui = +struct vg_ui vg_ui = { .ctx = { -- 2.25.1