VG_STATIC void vg_render(void);
VG_STATIC void vg_gui(void);
-struct vg
-{
+struct vg{
/* Engine sync */
SDL_Window *window;
SDL_GLContext gl_context;
+ const char *base_path;
SDL_sem *sem_loader; /* allows only one loader at a time */
-
jmp_buf env_loader_exit;
SDL_threadID thread_id_main,
thread_id_loader;
+ void *thread_data;
SDL_SpinLock sl_status;
- enum engine_status
- {
+ enum engine_status{
k_engine_status_none,
k_engine_status_load_internal,
k_engine_status_running,
int display_refresh_rate,
fps_limit; /* 0: use vsync, >0: cap fps to this, no vsync */
- enum vsync_feature
- {
+ enum vsync_feature{
k_vsync_feature_disabled=0,
k_vsync_feature_enabled=1,
k_vsync_feature_enabled_adaptive=2,
int fixed_iterations;
- enum engine_stage
- {
+ enum engine_stage{
k_engine_stage_none,
k_engine_stage_update,
k_engine_stage_update_fixed,
/* graphics */
m4x4f pv;
- enum quality_profile
- {
+ enum quality_profile{
k_quality_profile_high = 0,
k_quality_profile_low = 1,
}
SDL_AtomicUnlock( &vg.sl_status );
}
-VG_STATIC void _vg_load_full(void)
+VG_STATIC void _vg_load_full( void *data )
{
vg_preload();
SDL_Event event;
while( SDL_PollEvent( &event ) ){
if( event.type == SDL_KEYDOWN ){
- //console_proc_key( event.key.keysym );
- _ui_proc_key( event.key.keysym );
+ if( vg_console.enabled ){
+ if( event.key.keysym.sym == SDLK_ESCAPE ||
+ event.key.keysym.sym == SDLK_BACKQUOTE ){
+ vg_console.enabled = 0;
+ ui_defocus_all();
+ }
+ else if( (event.key.keysym.mod & KMOD_CTRL) &&
+ event.key.keysym.sym == SDLK_n ){
+ _console_suggest_next();
+ }
+ else if( (event.key.keysym.mod & KMOD_CTRL ) &&
+ event.key.keysym.sym == SDLK_p ){
+ _console_suggest_prev();
+ }
+ else{
+ _ui_proc_key( event.key.keysym );
+ }
+ }
+ else{
+ if( event.key.keysym.sym == SDLK_BACKQUOTE ){
+ vg_console.enabled = 1;
+ }
+ else {
+ _ui_proc_key( event.key.keysym );
+ }
+ }
}
else if( event.type == SDL_MOUSEWHEEL ){
vg.mouse_wheel[0] += event.wheel.preciseX;
}
}
else if( event.type == SDL_TEXTINPUT ){
- //console_proc_utf8( event.text.text );
ui_proc_utf8( event.text.text );
}
}
vg.engine_stage = k_engine_stage_ui;
{
ui_prerender();
- vg_gui();
+ if( vg_console.enabled ){
+ vg_ui.ignore_input_frames = 10;
+ vg_gui();
+ vg_ui.ignore_input_frames = 0;
+ vg_ui.wants_mouse = 1;
+ _vg_console_draw();
+ }
+ else vg_gui();
+
ui_postrender();
#if 0
ui_begin( vg.window_x, vg.window_y );
/* FIXME */
audio_debug_ui( vg.pv );
vg_gui();
- _vg_console_draw();
ui_resolve();
ui_draw( NULL );
SDL_InitSubSystem( SDL_INIT_AUDIO );
SDL_InitSubSystem( SDL_INIT_GAMECONTROLLER );
+ char *exe_basepath = SDL_GetBasePath();
+ u32 len = vg_align8( strlen(exe_basepath)+1 );
+ char *dest = vg_linear_alloc( vg_mem.rtmemory, len );
+ strcpy( dest, exe_basepath );
+ SDL_free( exe_basepath );
+ vg.base_path = dest;
+
+ vg_info( "Basepath: %s\n", vg.base_path );
+
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 3 );
#ifdef VG_DEVWINDOW
0, 0, vg.window_x, vg.window_y,
- SDL_WINDOW_BORDERLESS|SDL_WINDOW_OPENGL
+ SDL_WINDOW_BORDERLESS|SDL_WINDOW_OPENGL|SDL_WINDOW_INPUT_GRABBED
))){}
#else
0, 0,
vg_info( "Display refresh rate: %d\n", dispmode.refresh_rate );
-#ifdef _WIN32
+#if defined(_WIN32) || defined(VG_DEVWINDOW)
vg.fps_limit = vg.display_refresh_rate;
#else
- /* request vsync by default on linux to avoid screen tearing.
- * this does have its own issues with compositing on X11. */
vg.fps_limit = 0;
#endif
}
_vg_init_window( window_name );
vg_async_init();
-
-#ifndef VG_DEVWINDOW
SDL_SetRelativeMouseMode(1);
-#endif
vg.thread_id_main = SDL_GetThreadID(NULL);
vg.engine_status = k_engine_status_load_internal;
_vg_opengl_sync_init();
- vg_loader_start( _vg_load_full );
+ vg_loader_start( _vg_load_full, NULL );
_vg_gameloop();
_vg_terminate();
}
#define VG_GAME
#endif
-#include "vg/vg_ui.h"
+#include "vg/vg_imgui.h"
#include "vg/vg_log.h"
#define VG_VAR_F32( NAME, ... ) \
char input[96],
input_copy[96];
- int cursor_user, cursor_pos, string_length;
char history[32][96];
int history_last, history_pos, history_count;
/*
* 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 );
vg_info( "Console function '%s' registered\n", alias );
}
-VG_STATIC void _vg_console_draw(void)
-{
-#if 0
- 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<console_lines; i ++ ){
- ptr --;
-
- if( ptr < 0 )
- ptr = vg_list_size( vg_log.buffer )-1;
-
- ui_text( vg_uictx.cursor, vg_log.buffer[ptr], 1, 0 );
- vg_uictx.cursor[1] -= fh;
- }
-
- }
- ui_end_down();
-
-
- /* Input area */
- vg_uictx.cursor[1] += 2;
- vg_uictx.cursor[3] = fh;
-
- ui_new_node();
- {
- ui_fill_rect( vg_uictx.cursor, 0x77111111 );
- ui_text( vg_uictx.cursor, vg_console.input, 1, 0 );
-
- int start = VG_MIN( vg_console.cursor_pos, vg_console.cursor_user ),
- end = VG_MAX( vg_console.cursor_pos, vg_console.cursor_user );
-
- vg_uictx.cursor[0] = start * UI_GLYPH_SPACING_X;
- vg_uictx.cursor[2] = (start == end? 0.5f: (float)(end-start))
- * (float)UI_GLYPH_SPACING_X;
-
- ui_fill_rect( vg_uictx.cursor, 0x66ffffff );
- }
- 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;
-
- ui_new_node();
- {
- ui_fill_rect( vg_uictx.cursor, 0x77040404 );
-
- vg_uictx.cursor[3] = fh;
- for( int i=0; i<vg_console.suggestion_count; i ++ ){
- if( i == vg_console.suggestion_select )
- ui_fill_rect( vg_uictx.cursor, 0x66a0e508 );
-
- ui_text( vg_uictx.cursor, vg_console.suggestions[i].str, 1, 0 );
- vg_uictx.cursor[1] += fh;
- }
- }
- ui_end_down();
- }
-
- 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 ++ ){
VG_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;
* - 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];
}
/*
- * Console Interface
+ * Suggestion controls
*/
-VG_STATIC void console_make_selection( int* start, int* end )
-{
- *start = VG_MIN( vg_console.cursor_pos, vg_console.cursor_user );
- *end = VG_MAX( vg_console.cursor_pos, vg_console.cursor_user );
-}
-
-VG_STATIC void console_move_cursor( int* cursor0, int* cursor1,
- int dir, int snap_together )
+VG_STATIC void _console_fetch_suggestion(void)
{
- *cursor0 = VG_MAX( 0, vg_console.cursor_user + dir );
- *cursor0 =
- VG_MIN(
- VG_MIN( vg_list_size(vg_console.input)-1, strlen( vg_console.input )),
- *cursor0 );
-
- if( snap_together )
- *cursor1 = *cursor0;
-}
+ char *target = &vg_console.input[ vg_console.suggestion_pastepos ];
-VG_STATIC int console_makeroom( int datastart, int length )
-{
- int move_to = VG_MIN( datastart+length, vg_list_size( vg_console.input )-1 );
- int move_amount = strlen( vg_console.input )-datastart;
- int move_end =
- VG_MIN( move_to+move_amount, vg_list_size( vg_console.input )-1 );
- move_amount = move_end-move_to;
-
- if( move_amount )
- memmove( &vg_console.input[ move_to ],
- &vg_console.input[ datastart ],
- move_end-move_to );
-
- vg_console.input[ move_end ] = '\0';
-
- return VG_MIN( length, vg_list_size( vg_console.input )-datastart-1 );
-}
+ if( vg_console.suggestion_select == -1 ){
+ strcpy( target, vg_console.input_copy );
+ _ui_textbox_move_cursor( &vg_ui.textbox.cursor_user,
+ &vg_ui.textbox.cursor_pos, 10000, 1 );
+ }
+ else{
+ strncpy( target,
+ vg_console.suggestions[ vg_console.suggestion_select ].str,
+ vg_list_size( vg_console.input )-1 );
-VG_STATIC int console_delete_char( int direction )
-{
- int start, end;
- console_make_selection( &start, &end );
-
- /* There is no selection */
- 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 );
- }
-
- /* Still no selction, no need to do anything */
- if( !(end-start) )
- return start;
-
- /* Copy the end->terminator 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)
+VG_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)
+VG_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 );
+VG_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 )
+VG_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 )
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)
+VG_STATIC void _vg_console_on_up( char *buf, u32 len )
{
- 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)
-{
- 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();
+ )
+ )
+ );
+
+ 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_select(void)
+VG_STATIC void _vg_console_on_down( char *buf, u32 len )
{
- console_move_cursor( &vg_console.cursor_user, NULL, -10000, 0 );
-}
+ 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_home(void)
-{
- console_move_cursor( &vg_console.cursor_user,
- &vg_console.cursor_pos, -10000, 1 );
+ _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_select(void)
+VG_STATIC void _vg_console_on_enter( char *buf, u32 len )
{
- console_move_cursor( &vg_console.cursor_user, NULL, 10000, 0 );
-}
+ if( buf == vg_console.input ){
+ if( !strlen( vg_console.input ) )
+ return;
-VG_STATIC void _console_end(void)
-{
- console_move_cursor( &vg_console.cursor_user,
- &vg_console.cursor_pos,
- vg_list_size(vg_console.input)-1, 1 );
-}
+ vg_info( "%s\n", vg_console.input );
-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_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)
+VG_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.buffer_line_current;
+ int const fh = 14, log_lines = 32;
+ int console_lines = VG_MIN( log_lines, vg_log.buffer_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<console_lines; i ++ ){
+ ptr --;
- if( vg_console.suggestion_select >= vg_console.suggestion_count )
- vg_console.suggestion_select = -1;
+ if( ptr < 0 ) ptr = vg_list_size( vg_log.buffer )-1;
- _console_fetch_suggestion();
+ ui_text( rect_line, vg_log.buffer[ptr], 1, k_ui_align_left, 0 );
+ rect_line[1] -= fh;
}
-}
+
+ /*
+ * Input area
+ */
+ vg_ui.textbuf_on_up = _vg_console_on_up;
+ vg_ui.textbuf_on_down = _vg_console_on_down;
+ vg_ui.textbuf_on_change = _vg_console_on_update;
+ vg_ui.textbuf_on_enter = _vg_console_on_enter;
+ ui_textbox( rect_input, vg_console.input, vg_list_size(vg_console.input),
+ UI_TEXTBOX_AUTOFOCUS );
-VG_STATIC void _console_suggest_prev(void)
-{
+ /*
+ * suggestions
+ */
if( vg_console.suggestion_count ){
- _console_suggest_store_normal();
+ ui_rect rect_suggest;
+ rect_copy( rect_input, rect_suggest );
- vg_console.suggestion_select --;
-
- if( vg_console.suggestion_select < -1 )
- vg_console.suggestion_select = vg_console.suggestion_count-1;
-
- _console_fetch_suggestion();
- }
-}
+ rect_suggest[0] += 6 + UI_GLYPH_SPACING_X*vg_console.suggestion_pastepos;
+ rect_suggest[1] += rect_input[3];
+ rect_suggest[2] = UI_GLYPH_SPACING_X * vg_console.suggestion_maxlen;
+ rect_suggest[3] = vg_console.suggestion_count * fh;
-/*
- * 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;
+ ui_fill( rect_suggest, bg_colour );
- if( vg_console.enabled ){
- vg_info( "SDL_StartTextInput()\n" );
- SDL_StartTextInput();
- }
- else{
- SDL_StopTextInput();
- }
- }
-
- if( !vg_console.enabled ) return;
+ rect_suggest[3] = fh;
- 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 }
- };
-
- SDL_Keymod mod = 0;
-
- if( ev.mod & KMOD_SHIFT )
- mod |= KMOD_SHIFT;
-
- if( ev.mod & KMOD_CTRL )
- mod |= KMOD_CTRL;
-
- if( ev.mod & KMOD_ALT )
- mod |= KMOD_ALT;
-
- 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 ){
- mapping->handler();
- return;
- }
+ for( int i=0; i<vg_console.suggestion_count; i ++ ){
+ u32 text_colour;
+ if( i == vg_console.suggestion_select ){
+ ui_fill( rect_suggest, ui_colour( k_ui_orange ) );
+ text_colour = ui_colourcont( k_ui_orange );
}
- else if( (mod & mapping->mod) == mapping->mod ){
- mapping->handler();
- return;
- }
- }
- }
-}
+ else text_colour = ui_colourcont( k_ui_bg );
-/*
- * Callback for text entry mode
- */
-VG_STATIC void console_proc_utf8( const char *text )
-{
- const char *ptr = text;
+ ui_text( rect_suggest, vg_console.suggestions[i].str, 1,
+ k_ui_align_left, text_colour );
- while( *ptr ){
- if( *ptr != '`' )
- console_put_char( *ptr );
- ptr ++;
+ rect_suggest[1] += fh;
+ }
}
- console_update_suggestions();
+ SDL_AtomicUnlock( &log_print_sl );
}
+
#endif /* VG_CONSOLE_H */
#define UI_TEXTBOX_MULTILINE 0x1
#define UI_TEXTBOX_WRAP 0x2
+#define UI_TEXTBOX_AUTOFOCUS 0x4
+#define UI_MOUSE_LEFT (SDL_BUTTON(SDL_BUTTON_LEFT))
+#define UI_MOUSE_RIGHT (SDL_BUTTON(SDL_BUTTON_RIGHT))
+#define UI_MOUSE_MIDDLE (SDL_BUTTON(SDL_BUTTON_MIDDLE))
struct{
struct ui_vert *vertex_buffer;
u32 flags;
}
textbox;
+
+ void (*textbuf_on_enter) ( char *buf, u32 len );
+ void (*textbuf_on_up) ( char *buf, u32 len );
+ void (*textbuf_on_down) ( char *buf, u32 len );
+ void (*textbuf_on_change)( char *buf, u32 len );
GLuint tex_glyphs, vao, vbo, ebo;
ui_px mouse[2], mouse_click[2];
u32 mouse_state[2];
u32 ignore_input_frames;
+ int wants_mouse;
ui_rect click_fader, click_fader_end;
float click_fade_opacity;
glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, indice_offset, indice_size,
vg_ui.indice_buffer+vg_ui.indice_start );
+ glDisable( GL_DEPTH_TEST );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glBlendEquation( GL_FUNC_ADD );
{
int length = 0;
const char *_c = str;
- char c;
+ u8 c;
while( (c = *(_c ++)) ){
- if( c >= 32 && c <= 126 )
- length ++;
- else if( c == '\n' )
- break;
+ if( c >= 32 ) length ++;
+ else if( c == '\n' ) break;
}
return length * 8;
{
int height = 1;
const char *_c = str;
- char c;
+ u8 c;
while( (c = *(_c ++)) ){
if( c == '\n' ) height ++;
return 0;
}
-static int ui_click_down(void)
+static int ui_click_down( u32 mask )
{
if( vg_ui.ignore_input_frames ) return 0;
-
- if( (vg_ui.mouse_state[0] & SDL_BUTTON(SDL_BUTTON_LEFT)) &&
- !(vg_ui.mouse_state[1] & SDL_BUTTON(SDL_BUTTON_LEFT)) )
+ if( (vg_ui.mouse_state[0] & mask) &&
+ !(vg_ui.mouse_state[1] & mask) )
return 1;
else
return 0;
}
-static int ui_clicking(void)
+static int ui_clicking( u32 mask )
{
if( vg_ui.ignore_input_frames ) return 0;
- return vg_ui.mouse_state[0] & SDL_BUTTON(SDL_BUTTON_LEFT);
+ return vg_ui.mouse_state[0] & mask;
}
-static int ui_click_up(void)
+static int ui_click_up( u32 mask )
{
if( vg_ui.ignore_input_frames ) return 0;
- if( (vg_ui.mouse_state[1] & SDL_BUTTON(SDL_BUTTON_LEFT)) &&
- !(vg_ui.mouse_state[0] & SDL_BUTTON(SDL_BUTTON_LEFT)) )
+ if( (vg_ui.mouse_state[1] & mask) &&
+ !(vg_ui.mouse_state[0] & mask) )
return 1;
else
return 0;
vg_ui.indice_start = 0;
vg_ui.focused_control_hit = 0;
vg_ui.cursor = k_ui_cursor_default;
+ vg_ui.wants_mouse = 0;
if( vg_ui.ignore_input_frames ){
vg_ui.ignore_input_frames --;
return;
}
- if( ui_click_down() ){
+ if( ui_click_down(UI_MOUSE_LEFT)||ui_click_down(UI_MOUSE_MIDDLE) ){
vg_ui.mouse_click[0] = vg_ui.mouse[0];
vg_ui.mouse_click[1] = vg_ui.mouse[1];
}
printed_chars = 0;
continue;
}
- else
- if( c >= 33 ){
+ else if( c >= 33 ){
u8 glyph_base[2];
u8 glyph_index = c;
glyph_base[0] = glyph_index & 0xf;
case '3'|'4'<<8: colour = ui_colour( k_ui_blue ); break;
case '3'|'5'<<8: colour = ui_colour( k_ui_purple ); break;
case '3'|'6'<<8: colour = ui_colour( k_ui_aqua ); break;
- case '3'|'7'<<8: colour = ui_colour( 0xffffffff ); break;
+ case '3'|'7'<<8: colour = 0xffffffff; break;
}
colour &= 0x00ffffff;
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, image );
- ui_fill_rect( rect, 0xffffffff, (ui_px[4]){ 0,0, 255,255 } );
+ ui_fill_rect( rect, 0xffffffff, (ui_px[4]){ 0,128, 128, 0 } );
ui_flush( k_ui_shader_image );
}
static void ui_defocus_all(void)
{
if( vg_ui.focused_control_type == k_ui_control_textbox ){
- vg_info( "SDL_StopTextInput()\n" );
SDL_StopTextInput();
}
vg_ui.focused_control_type = k_ui_control_none;
}
-static int ui_button( ui_rect rect, enum ui_scheme_colour colour )
+static int ui_colourbutton( ui_rect rect, enum ui_scheme_colour colour )
{
- int clickup= ui_click_up(),
- click = ui_clicking() | clickup,
+ int clickup= ui_click_up(UI_MOUSE_LEFT),
+ click = ui_clicking(UI_MOUSE_LEFT) | clickup,
target = ui_inside_rect( rect, vg_ui.mouse_click ) && click,
hover = ui_inside_rect( rect, vg_ui.mouse );
}
}
-static int ui_button_text( ui_rect rect, const char *string, ui_px scale,
- enum ui_scheme_colour colour )
+static int ui_colourbutton_text( ui_rect rect, const char *string, ui_px scale,
+ enum ui_scheme_colour colour )
{
- int result = ui_button( rect, colour );
+ int result = ui_colourbutton( rect, colour );
ui_rect t = { 0,0, ui_text_line_width( string )*scale, 14*scale };
ui_rect_center( rect, t );
ui_text( t, string, scale, k_ui_align_left, ui_colourcont(colour) );
return result;
}
+static int ui_button_text( ui_rect rect, const char *string, ui_px scale )
+{
+ return ui_colourbutton_text( rect, string, scale, k_ui_bg+4 );
+}
+
static void ui_postrender(void)
{
if( vg_ui.click_fade_opacity > 0.0f ){
ui_defocus_all();
}
+ if( vg_ui.wants_mouse ){
+ SDL_SetWindowGrab( vg.window, SDL_FALSE );
+ SDL_SetRelativeMouseMode( SDL_FALSE );
+ }
+ else{
+ SDL_SetWindowGrab( vg.window, SDL_TRUE );
+ SDL_SetRelativeMouseMode( SDL_TRUE );
+ }
+
SDL_SetCursor( vg_ui.cursor_map[ vg_ui.cursor ] );
SDL_ShowCursor(1);
}
-
-
static void ui_dev_colourview(void)
{
ui_rect window = {vg.window_x-256,0,256,vg.window_y}, swatch;
}
}
+/*
+ * checkbox
+ * -----------------------------------------------------------------------------
+ */
+static int ui_checkbox( ui_rect rect, const char *str_label, int *data )
+{
+ ui_rect label, box;
+ ui_split_px( rect, k_ui_axis_v, rect[2]-rect[3], 0, label, box );
+ ui_text( label, str_label, 1, k_ui_align_middle_left, 0 );
+ int changed = ui_colourbutton( box, k_ui_bg );
+ if( changed )
+ *data = (*data) ^ 0x1;
+ if( *data ){
+ ui_rect_pad( box, 4 );
+ ui_fill( box, ui_colour( k_ui_orange ) );
+ }
+
+ return changed;
+}
/*
- * text box interface
+ * Textbox chaos
+ * -----------------------------------------------------------------------------
*/
+
static void _ui_textbox_make_selection( int *start, int *end )
{
*start = VG_MIN( vg_ui.textbox.cursor_pos, vg_ui.textbox.cursor_user );
}
}
else{
-
+ if( vg_ui.textbuf_on_up ){
+ vg_ui.textbuf_on_up( vg_ui.textbuf, vg_ui.textbox.len );
+ }
}
}
vg_ui.textbox.cursor_pos = line_below_begin+offset;
}
else{
-
+ if( vg_ui.textbuf_on_down ){
+ vg_ui.textbuf_on_down( vg_ui.textbuf, vg_ui.textbox.len );
+ }
}
}
static void _ui_textbox_backspace(void)
{
- vg_ui.textbox.cursor_user = _ui_textbox_delete_char( -1 );
- vg_ui.textbox.cursor_pos = vg_ui.textbox.cursor_user;
+ if( vg_ui.focused_control_type == k_ui_control_textbox ){
+ vg_ui.textbox.cursor_user = _ui_textbox_delete_char( -1 );
+ vg_ui.textbox.cursor_pos = vg_ui.textbox.cursor_user;
+
+ if( vg_ui.textbuf_on_change )
+ vg_ui.textbuf_on_change( vg_ui.textbuf, vg_ui.textbox.len );
+ }
}
static void _ui_textbox_delete(void)
{
- vg_ui.textbox.cursor_user = _ui_textbox_delete_char( 1 );
- vg_ui.textbox.cursor_pos = vg_ui.textbox.cursor_user;
+ if( vg_ui.focused_control_type == k_ui_control_textbox ){
+ vg_ui.textbox.cursor_user = _ui_textbox_delete_char( 1 );
+ vg_ui.textbox.cursor_pos = vg_ui.textbox.cursor_user;
+
+ if( vg_ui.textbuf_on_change )
+ vg_ui.textbuf_on_change( vg_ui.textbuf, vg_ui.textbox.len );
+ }
}
static void _ui_textbox_home_select(void)
_ui_textbox_put_char( '\n' );
}
else{
- ui_defocus_all();
+ if( !(vg_ui.textbox.flags & UI_TEXTBOX_AUTOFOCUS ) )
+ ui_defocus_all();
}
- }
-}
-
-/*
- * Handles binds
- */
-static void _ui_proc_key( SDL_Keysym ev )
-{
- struct textbox_mapping
- {
- u16 mod;
- SDL_Keycode key;
-
- void (*handler)(void);
- }
- mappings[] =
- {
- { 0, SDLK_LEFT, _ui_textbox_left },
- { KMOD_SHIFT, SDLK_LEFT, _ui_textbox_left_select },
- { 0, SDLK_RIGHT, _ui_textbox_right },
- { KMOD_SHIFT, SDLK_RIGHT, _ui_textbox_right_select },
- { 0, SDLK_DOWN, _ui_textbox_down },
- { 0, SDLK_UP, _ui_textbox_up },
- { 0, SDLK_BACKSPACE, _ui_textbox_backspace },
- { KMOD_SHIFT, SDLK_BACKSPACE, _ui_textbox_backspace },
- { KMOD_CTRL, SDLK_BACKSPACE, _ui_textbox_backspace },
- { 0, SDLK_DELETE, _ui_textbox_delete },
- { 0, SDLK_HOME, _ui_textbox_home },
- { KMOD_SHIFT, SDLK_HOME, _ui_textbox_home_select },
- { 0, SDLK_END, _ui_textbox_end },
- { KMOD_SHIFT, SDLK_END, _ui_textbox_end_select },
- { KMOD_CTRL, SDLK_a, _ui_textbox_select_all },
- { KMOD_CTRL, SDLK_c, _ui_textbox_to_clipboard },
- { KMOD_CTRL, SDLK_x, _ui_textbox_cut },
- { KMOD_CTRL, SDLK_v, _ui_textbox_clipboard_paste },
- { 0, SDLK_RETURN, _ui_textbox_enter },
-#if 0
- { KMOD_CTRL, SDLK_n, _ui_textbox_suggest_next },
- { KMOD_CTRL, SDLK_p, _ui_textbox_suggest_prev }
-#endif
- { 0, SDLK_ESCAPE, ui_defocus_all },
- };
-
- if( vg_ui.focused_control_type == k_ui_control_none ){
- return;
- }
-
- SDL_Keymod mod = 0;
-
- if( ev.mod & KMOD_SHIFT )
- mod |= KMOD_SHIFT;
-
- if( ev.mod & KMOD_CTRL )
- mod |= KMOD_CTRL;
-
- if( ev.mod & KMOD_ALT )
- mod |= KMOD_ALT;
-
- for( int i=0; i<vg_list_size( mappings ); i++ ){
- struct textbox_mapping *mapping = &mappings[i];
- if( mapping->key == ev.sym ){
- if( mapping->mod == 0 ){
- if( mod == 0 ){
- mapping->handler();
- return;
- }
- }
- else if( (mod & mapping->mod) == mapping->mod ){
- mapping->handler();
- return;
- }
+ if( vg_ui.textbuf_on_enter ){
+ vg_ui.textbuf_on_enter( vg_ui.textbuf, vg_ui.textbox.len );
}
}
}
-/*
- * Callback for text entry mode
+/*
+ * based on a visual character coordinate relative to the anchor of the textbox,
+ * this works out the linear place in the buffer that coordinate maps to
+ *
+ * input coordinates go in co[0], co[1], and the result index is in co[2]
*/
-VG_STATIC void ui_proc_utf8( const char *text )
-{
- const char *ptr = text;
-
- while( *ptr ){
- if( *ptr != '`' ) _ui_textbox_put_char( *ptr );
- ptr ++;
- }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-static void _ui_textbox_cursor_rect( ui_rect text_rect, ui_rect cursor )
-{
- int start = VG_MIN( vg_ui.textbox.cursor_pos, vg_ui.textbox.cursor_user ),
- end = VG_MAX( vg_ui.textbox.cursor_pos, vg_ui.textbox.cursor_user );
-
- cursor[0] = text_rect[0] + start*UI_GLYPH_SPACING_X-1;
- cursor[1] = text_rect[1];
- cursor[2] = start == end? 2: (float)(end-start)*(float)UI_GLYPH_SPACING_X;
- cursor[3] = 14;
-}
-
-static void _ui_textbox_calc_index_from_grid( int co[3], int char_width )
+static void _ui_textbox_calc_index_from_grid( int co[3], int wrap_length )
{
int i[3] = {0,0,0};
while( (c = vg_ui.textbuf[i[2]]) ){
if( i[1]==co[1] && i[0]>=co[0] ) break;
- if( i[0] >= char_width ){
+ if( i[0] >= wrap_length ){
i[1] ++;
i[0] = 0;
}
co[2] = i[2];
}
-static
-void _ui_textbox_index_calc_coords( int co[3], int char_width )
+/*
+ * based on the index specied in co[2], work out the visual character
+ * coordinates and store them in co[0], co[1]
+ */
+static void _ui_textbox_index_calc_coords( int co[3], int wrap_length )
{
co[0] = 0;
co[1] = 0;
while( (c = vg_ui.textbuf[i ++]) ){
if( i > co[2] ) break;
- if( co[0] >= char_width ){
+ if( co[0] >= wrap_length ){
co[1] ++;
co[0] = 0;
}
}
}
-static int _ui_textbox_run_remaining( int index[3], int char_width )
+/*
+ * calculate the number of characters remaining until either:
+ * - the wrap_length limit is hit
+ * - end of the line/string
+ *
+ * index must be fully populated with visual X/Y, and linear index
+ */
+static int _ui_textbox_run_remaining( int index[3], int wrap_length )
{
int i=0, printed_chars=0;
char c;
while( (c = vg_ui.textbuf[index[2] + (i ++)]) ){
- if( index[0]+i >= char_width ) break;
+ if( index[0]+i >= wrap_length ) break;
if( c >= 32 && c <= 126 ) printed_chars ++;
else if( c == '\n' ) break;
}
static int ui_textbox( ui_rect rect, char *buf, u32 len, u32 flags )
{
- int clickup= ui_click_up(),
- click = ui_clicking() | clickup,
+ int clickup= ui_click_up(UI_MOUSE_LEFT),
+ click = ui_clicking(UI_MOUSE_LEFT) | clickup,
target = ui_inside_rect( rect, vg_ui.mouse_click ) && click,
hover = ui_inside_rect( rect, vg_ui.mouse );
text_rect[2] -= 16;
ui_rect_center( rect, text_rect );
- ui_px char_width = 1024;
+ ui_px wrap_length = 1024;
if( flags & UI_TEXTBOX_WRAP )
- char_width = text_rect[2] / UI_GLYPH_SPACING_X;
+ wrap_length = text_rect[2] / UI_GLYPH_SPACING_X;
if( hover ){
vg_ui.cursor = k_ui_cursor_ibeam;
if( vg_ui.focused_control_id == buf ){
ui_fill( rect, col_base );
- ui_ntext( text_rect, buf, char_width, 1, k_ui_align_left, 0 );
+ ui_ntext( text_rect, buf, wrap_length, 1, k_ui_align_left, 0 );
- if( (clickup||ui_click_down()) && !target ){
+ if( !(flags & UI_TEXTBOX_AUTOFOCUS) &&
+ ((clickup||ui_click_down(UI_MOUSE_LEFT)) && !target) ){
ui_defocus_all();
}
else{
};
if( flags & UI_TEXTBOX_MULTILINE ){
- _ui_textbox_calc_index_from_grid( p0, char_width );
- _ui_textbox_calc_index_from_grid( p1, char_width );
+ _ui_textbox_calc_index_from_grid( p0, wrap_length );
+ _ui_textbox_calc_index_from_grid( p1, wrap_length );
vg_ui.textbox.cursor_pos = p0[2];
vg_ui.textbox.cursor_user = p1[2];
int pos[3], remaining = chars;
pos[2] = start;
- _ui_textbox_index_calc_coords( pos, char_width );
+ _ui_textbox_index_calc_coords( pos, wrap_length );
if( start==end ){
cursor[0] = text_rect[0] + pos[0]*UI_GLYPH_SPACING_X-1;
else{
while( remaining ){
/* TODO: scan for newlines and stuff
- * eol or char_width can have line breaks! */
+ * eol or wrap_length can have line breaks! */
- int run = _ui_textbox_run_remaining( pos, char_width );
+ int run = _ui_textbox_run_remaining( pos, wrap_length );
run = VG_MIN( run, remaining );
cursor[0] = text_rect[0] + pos[0]*UI_GLYPH_SPACING_X-1;
return 0;
}
- if( click ){
- if( target && hover ){
+ if( click || (flags & UI_TEXTBOX_AUTOFOCUS) ){
+ if( (target && hover) || (flags & UI_TEXTBOX_AUTOFOCUS) ){
ui_defocus_all();
ui_fill( rect, col_highlight );
vg_ui.textbox.cursor_pos = 0;
vg_ui.textbox.cursor_user = 0;
- vg_info( "SDL_StartTextInput()\n" );
SDL_StartTextInput();
}
}
ui_outline( rect, -1, col_highlight );
}
- ui_ntext( text_rect, buf, char_width, 1, k_ui_align_left, 0 );
+ ui_ntext( text_rect, buf, wrap_length, 1, k_ui_align_left, 0 );
return 0;
}
+/*
+ * Input handling
+ * -----------------------------------------------------------------------------
+ */
+
+/*
+ * Handles binds
+ */
+static void _ui_proc_key( SDL_Keysym ev )
+{
+ if( vg_ui.focused_control_type != k_ui_control_textbox ){
+ return;
+ }
+
+ struct textbox_mapping
+ {
+ u16 mod;
+ SDL_Keycode key;
+
+ void (*handler)(void);
+ }
+ mappings[] =
+ {
+ { 0, SDLK_LEFT, _ui_textbox_left },
+ { KMOD_SHIFT, SDLK_LEFT, _ui_textbox_left_select },
+ { 0, SDLK_RIGHT, _ui_textbox_right },
+ { KMOD_SHIFT, SDLK_RIGHT, _ui_textbox_right_select },
+ { 0, SDLK_DOWN, _ui_textbox_down },
+ { 0, SDLK_UP, _ui_textbox_up },
+ { 0, SDLK_BACKSPACE, _ui_textbox_backspace },
+ { KMOD_SHIFT, SDLK_BACKSPACE, _ui_textbox_backspace },
+ { KMOD_CTRL, SDLK_BACKSPACE, _ui_textbox_backspace },
+ { 0, SDLK_DELETE, _ui_textbox_delete },
+ { 0, SDLK_HOME, _ui_textbox_home },
+ { KMOD_SHIFT, SDLK_HOME, _ui_textbox_home_select },
+ { 0, SDLK_END, _ui_textbox_end },
+ { KMOD_SHIFT, SDLK_END, _ui_textbox_end_select },
+ { KMOD_CTRL, SDLK_a, _ui_textbox_select_all },
+ { KMOD_CTRL, SDLK_c, _ui_textbox_to_clipboard },
+ { KMOD_CTRL, SDLK_x, _ui_textbox_cut },
+ { KMOD_CTRL, SDLK_v, _ui_textbox_clipboard_paste },
+ { 0, SDLK_RETURN, _ui_textbox_enter },
+ { 0, SDLK_ESCAPE, ui_defocus_all },
+ };
+
+ SDL_Keymod mod = 0;
+
+ if( ev.mod & KMOD_SHIFT )
+ mod |= KMOD_SHIFT;
+
+ if( ev.mod & KMOD_CTRL )
+ mod |= KMOD_CTRL;
+
+ if( ev.mod & KMOD_ALT )
+ mod |= KMOD_ALT;
+
+ for( int i=0; i<vg_list_size( mappings ); i++ ){
+ struct textbox_mapping *mapping = &mappings[i];
+
+ if( mapping->key == ev.sym ){
+ if( mapping->mod == 0 ){
+ if( mod == 0 ){
+ mapping->handler();
+ return;
+ }
+ }
+ else if( (mod & mapping->mod) == mapping->mod ){
+ mapping->handler();
+ return;
+ }
+ }
+ }
+}
+
+/*
+ * Callback for text entry mode
+ */
+VG_STATIC void ui_proc_utf8( const char *text )
+{
+ if( vg_ui.focused_control_type == k_ui_control_textbox ){
+ const char *ptr = text;
+
+ while( *ptr ){
+ if( *ptr != '`' ) _ui_textbox_put_char( *ptr );
+ ptr ++;
+ }
+
+ if( vg_ui.textbuf_on_change ){
+ vg_ui.textbuf_on_change( vg_ui.textbuf, vg_ui.textbox.len );
+ }
+ }
+}
+
#endif /* VG_IMGUI_H */
#include <stdio.h>
#include <errno.h>
+
#define _TINYDIR_MALLOC(_size) vg_linear_alloc( vg_mem.scratch, _size )
#define _TINYDIR_FREE(_size)
#include "submodules/tinydir/tinydir.h"
+#include <sys/stat.h>
+VG_STATIC int vg_mkdir( const char *path )
+{
+ if( mkdir( path, S_IRWXU|S_IRWXG|S_IWOTH|S_IXOTH ) ){
+ vg_error( "Failed to create directory: %s\n", path );
+ return 0;
+ }
+ else{
+ return 1;
+ }
+}
+
/*
* File I/O
*/
fclose( f );
*size = (u32)current;
-
return buffer;
}
else{
}
}
+/* TODO: error handling if read fails */
+VG_STATIC int vg_file_copy( const char *src, const char *dst, void *lin_alloc )
+{
+ vg_info( "vg_file_copy( %s -> %s )\n", src, dst );
+ u32 size;
+ void *data = vg_file_read( lin_alloc, src, &size );
+ return vg_asset_write( dst, data, size );
+}
+
+VG_STATIC const char *vg_path_filename( const char *path )
+{
+ const char *base = path;
+
+ for( int i=0; i<1024; i++ ){
+ if( path[i] == '\0' ) break;
+ if( path[i] == '/' ){
+ base = path+i+1;
+ }
+ }
+
+ return base;
+}
+
#endif /* VG_IO_H */
#include "common.h"
-VG_STATIC void vg_loader_start( void(*pfn)(void) );
+VG_STATIC void vg_loader_start( void(*pfn)(void *data), void *data );
VG_STATIC void vg_loader_step( void( *fn_load )(void), void( *fn_free )(void) );
static struct vg_shader _shader_loader =
static struct vg_loader
{
/* Shutdown steps */
- struct loader_free_step
- {
+ struct loader_free_step{
void (*fn_free)(void);
}
step_buffer[16];
VG_STATIC void vg_load_full(void);
-VG_STATIC int _vg_loader_thread(void *pfn)
+VG_STATIC int _vg_loader_thread( void *pfn )
{
if( setjmp( vg.env_loader_exit ) )
return 0;
/* Run client loader */
vg_info( "Starting client loader thread @%p\n", pfn );
- void (*call_func)(void) = pfn;
- call_func();
+ void (*call_func)(void *data) = pfn;
+ call_func( vg.thread_data );
SDL_SemPost( vg.sem_loader );
vg.thread_id_loader = 0;
return 0;
}
-VG_STATIC void vg_loader_start( void(*pfn)(void) )
+VG_STATIC void vg_loader_start( void(*pfn)(void *data), void *data )
{
SDL_SemWait( vg.sem_loader );
+
+ vg.thread_data = data;
SDL_CreateThread( _vg_loader_thread, "Loader thread", pfn );
}
k_strncpy_allow_cutoff = 1
};
-VG_STATIC void vg_strncpy( const char *src, char *dst, u32 len,
- enum strncpy_behaviour behaviour )
+VG_STATIC u32 vg_strncpy( const char *src, char *dst, u32 len,
+ enum strncpy_behaviour behaviour )
{
for( u32 i=0; i<len; i++ ){
dst[i] = src[i];
- if( !src[i] )
- break;
+ if( !src[i] ) return i;
- if( (behaviour == k_strncpy_always_add_null) && (i == len-1) )
+ if( (behaviour == k_strncpy_always_add_null) && (i == len-1) ){
dst[i] = '\0';
+ return i;
+ }
}
+
+ return 0;
}
VG_STATIC u32 vg_strdjb2( const char *str )
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
-0x400000,0,0,0,0,0,0,0,
-0x800000,0,0,0,0,0,0,0,
-0x1000000,0,0,0,0,0,0,0,
-0x1000000,0,0,0,0,0,0,0,
-0x1000000,0,0,0,0,0,0,0,
-0xe00000,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,
+0x400070,0,0,0,0,0,0,0,
+0x800730,0,0,0,0,0,0,0,
+0x1000450,0,0,0,0,0,0,0,
+0x1000480,0,0,0,0,0,0,0,
+0x1000420,0,0,0,0,0,0,0,
+0xe00420,0,0,0,0,0,0,0,
+0x7e0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
const DepotId_t k_uDepotIdInvalid = 0x0;
typedef u32 RTime32;
+typedef u32 AccountID_t;
enum { k_iSteamUserCallbacks = 100 };
enum { k_iSteamGameServerCallbacks = 200 };
enum { k_iSteamNetworkingSocketsCallbacks = 1220 };
enum { k_iSteamNetworkingMessagesCallbacks = 1250 };
enum { k_iSteamNetworkingUtilsCallbacks = 1280 };
-enum { k_iClientRemoteStorageCallbacks = 1300 };
+enum { k_iSteamRemoteStorageCallbacks = 1300 };
enum { k_iClientDepotBuilderCallbacks = 1400 };
enum { k_iSteamGameServerItemsCallbacks = 1500 };
enum { k_iClientUtilsCallbacks = 1600 };
enum { k_iClientMusicCallbacks = 3200 };
enum { k_iClientRemoteClientManagerCallbacks = 3300 };
enum { k_iClientUGCCallbacks = 3400 };
+enum { k_iSteamUGCCallbacks = 3400 };
enum { k_iSteamStreamClientCallbacks = 3500 };
enum { k_IClientProductBuilderCallbacks = 3600 };
enum { k_iClientShortcutsCallbacks = 3700 };
* Async callbacks
* =============================================================================
*/
-typedef struct steam_async steam_async;
-struct steam_async
-{
- SteamAPICall_t id;
- void *data;
- void (*p_handler)( void *result, void *userdata );
+typedef struct vg_steam_async_call vg_steam_async_call;
+typedef struct vg_steam_callback_handler vg_steam_callback_handler;
+
+struct vg_steam{
+ struct vg_steam_async_call{
+ SteamAPICall_t id;
+ void *userdata;
+
+ void (*p_handler)( void *result, void *userdata );
+ }
+ calls[4];
+ u32 call_count;
+
+ struct vg_steam_callback_handler{
+ u32 callback_id;
+ void (*p_handler)( CallbackMsg_t *msg );
+ }
+ callback_handlers[32];
+ u32 callback_handler_count;
}
-static steam_async_trackers[32];
-static u32 steam_async_track_count;
+static vg_steam;
-steam_async *steam_new_async(void)
+vg_steam_async_call *vg_alloc_async_steam_api_call(void)
{
- if( steam_async_track_count == vg_list_size(steam_async_trackers) )
- {
- vg_error( "Maximum concurrent API calls exceeded (%u)\n",
- steam_async_track_count );
- return NULL;
+ if( vg_steam.call_count == vg_list_size(vg_steam.calls) ){
+ vg_fatal_error( "Maximum concurrent API calls exceeded (%u)\n",
+ vg_steam.call_count );
}
- return &steam_async_trackers[ steam_async_track_count ++ ];
+ return &vg_steam.calls[ vg_steam.call_count ++ ];
}
/*
* =============================================================================
*/
-typedef struct steam_callback_handler steam_callback_handler;
-struct steam_callback_handler
-{
- u32 callback_id;
- void (*p_handler)( CallbackMsg_t *msg );
-}
-static steam_callback_handlers[64];
-static u32 steam_callback_handler_count;
-
-static int steam_register_callback( u32 id,
- void (*p_handler)( CallbackMsg_t *msg ) )
+static void steam_register_callback( u32 id,
+ void (*p_handler)( CallbackMsg_t *msg ) )
{
- if( steam_callback_handler_count == vg_list_size(steam_callback_handlers) )
+ if( vg_steam.callback_handler_count ==
+ vg_list_size(vg_steam.callback_handlers) )
{
- vg_error( "Too many steam callback handlers registered (%u)\n",
- steam_callback_handler_count );
-
- return 0;
+ vg_fatal_error( "Too many steam callback handlers registered (%u)\n",
+ vg_steam.callback_handler_count );
}
- steam_callback_handler *handler = &steam_callback_handlers[
- steam_callback_handler_count ++ ];
+ vg_steam_callback_handler *handler =
+ &vg_steam.callback_handlers[ vg_steam.callback_handler_count ++ ];
handler->p_handler = p_handler;
handler->callback_id = id;
-
- return 1;
}
/*
(SteamAPICallCompleted_t *)callback->m_pubParam;
int bFailed;
-
- void *temp = alloca( pCallCompleted->m_cubParam );
+ void *call_data = alloca( pCallCompleted->m_cubParam );
if( SteamAPI_ManualDispatch_GetAPICallResult(
pipe,
pCallCompleted->m_hAsyncCall,
- temp,
+ call_data,
pCallCompleted->m_cubParam,
pCallCompleted->m_iCallback,
&bFailed )
*/
vg_info( "steamworks_event::api_call_completed( %lu )\n",
- pCallCompleted->m_hAsyncCall );
+ pCallCompleted->m_hAsyncCall );
int j=0;
- for( int i=0; i<steam_async_track_count; i++ )
- {
- if( steam_async_trackers[j].id != pCallCompleted->m_hAsyncCall )
- {
- steam_async_trackers[j ++] = steam_async_trackers[i];
+ for( int i=0; i<vg_steam.call_count; i++ ){
+ if( vg_steam.calls[i].id != pCallCompleted->m_hAsyncCall ){
+ vg_steam.calls[j ++] = vg_steam.calls[i];
}
- else
- {
- steam_async *pasync = &steam_async_trackers[j];
- pasync->p_handler( temp, pasync->data );
+ else{
+ vg_steam_async_call *call = &vg_steam.calls[i];
+ call->p_handler( call_data, call->userdata );
}
}
- if( steam_async_track_count == j )
- {
+ if( vg_steam.call_count == j ){
vg_error( "No tracker was register for API call\n" );
}
- steam_async_track_count = j;
+ vg_steam.call_count = j;
}
else
{
SteamAPI_ManualDispatch_RunFrame( pipe );
CallbackMsg_t callback;
- while( SteamAPI_ManualDispatch_GetNextCallback( pipe, &callback ) )
- {
+ while( SteamAPI_ManualDispatch_GetNextCallback( pipe, &callback ) ){
vg_low( "steamworks_event::callback( %i )\n", callback.m_iCallback );
/* Check for dispatching API call results */
- if( callback.m_iCallback == k_iSteamAPICallCompleted )
- {
+ if( callback.m_iCallback == k_iSteamAPICallCompleted ){
steamworks_process_api_call( pipe, &callback );
}
- else
- {
+ else {
/*
* Look at callback.m_iCallback to see what kind of callback it is,
* and dispatch to appropriate handler(s)
* void *data = callback.m_pubParam;
*/
- for( int i=0; i<steam_callback_handler_count; i++ )
- {
- steam_callback_handler *handler = &steam_callback_handlers[i];
- if( handler->callback_id == callback.m_iCallback )
- {
+ for( int i=0; i<vg_steam.callback_handler_count; i++ ){
+ vg_steam_callback_handler *handler = &vg_steam.callback_handlers[i];
+ if( handler->callback_id == callback.m_iCallback ){
handler->p_handler( &callback );
break;
}
--- /dev/null
+#ifndef VG_STEAM_REMOTE_STORAGE_H
+#define VG_STEAM_REMOTE_STORAGE_H
+
+#include "vg/vg_steam.h"
+
+const u32 k_unMaxCloudFileChunkSize = 100 * 1024 * 1024;
+
+#if defined( VALVE_CALLBACK_PACK_SMALL )
+#pragma pack( push, 4 )
+#elif defined( VALVE_CALLBACK_PACK_LARGE )
+#pragma pack( push, 8 )
+#else
+#error steam_api_common.h should define VALVE_CALLBACK_PACK_xxx
+#endif
+typedef struct SteamParamStringArray_t SteamParamStringArray_t;
+struct SteamParamStringArray_t{
+ const char **m_ppStrings;
+ i32 m_nNumStrings;
+};
+#pragma pack( pop )
+
+/* A handle to a piece of user generated content */
+typedef u64 UGCHandle_t;
+typedef u64 PublishedFileUpdateHandle_t;
+typedef u64 PublishedFileId_t;
+const PublishedFileId_t k_PublishedFileIdInvalid = 0;
+const UGCHandle_t k_UGCHandleInvalid = 0xffffffffffffffffull;
+const PublishedFileUpdateHandle_t
+k_PublishedFileUpdateHandleInvalid = 0xffffffffffffffffull;
+
+/* Handle for writing to Steam Cloud */
+typedef u64 UGCFileWriteStreamHandle_t;
+const UGCFileWriteStreamHandle_t
+k_UGCFileStreamHandleInvalid = 0xffffffffffffffffull;
+
+enum{ k_cchPublishedDocumentTitleMax = 128 + 1 };
+enum{ k_cchPublishedDocumentDescriptionMax = 8000 };
+enum{ k_cchPublishedDocumentChangeDescriptionMax = 8000 };
+enum{ k_unEnumeratePublishedFilesMaxResults = 50 };
+enum{ k_cchTagListMax = 1024 + 1 };
+enum{ k_cchFilenameMax = 260 };
+enum{ k_cchPublishedFileURLMax = 256 };
+
+typedef enum ERemoteStoragePlatform ERemoteStoragePlatform;
+enum ERemoteStoragePlatform{
+ k_ERemoteStoragePlatformNone = 0,
+ k_ERemoteStoragePlatformWindows = (1 << 0),
+ k_ERemoteStoragePlatformOSX = (1 << 1),
+ k_ERemoteStoragePlatformPS3 = (1 << 2),
+ k_ERemoteStoragePlatformLinux = (1 << 3),
+ k_ERemoteStoragePlatformSwitch = (1 << 4),
+ k_ERemoteStoragePlatformAndroid = (1 << 5),
+ k_ERemoteStoragePlatformIOS = (1 << 6),
+
+ /* NB we get one more before we need to widen some things */
+ k_ERemoteStoragePlatformAll = 0xffffffff
+};
+
+typedef enum ERemoteStoragePublishedFileVisibility
+ ERemoteStoragePublishedFileVisibility;
+enum ERemoteStoragePublishedFileVisibility{
+ k_ERemoteStoragePublishedFileVisibilityPublic = 0,
+ k_ERemoteStoragePublishedFileVisibilityFriendsOnly = 1,
+ k_ERemoteStoragePublishedFileVisibilityPrivate = 2,
+ k_ERemoteStoragePublishedFileVisibilityUnlisted = 3,
+};
+
+
+typedef enum EWorkshopFileType EWorkshopFileType;
+enum EWorkshopFileType{
+ k_EWorkshopFileTypeFirst = 0,
+ k_EWorkshopFileTypeCommunity = 0,
+ k_EWorkshopFileTypeMicrotransaction = 1,
+ k_EWorkshopFileTypeCollection = 2,
+ k_EWorkshopFileTypeArt = 3,
+ k_EWorkshopFileTypeVideo = 4,
+ k_EWorkshopFileTypeScreenshot = 5,
+ k_EWorkshopFileTypeGame = 6,
+ k_EWorkshopFileTypeSoftware = 7,
+ k_EWorkshopFileTypeConcept = 8,
+ k_EWorkshopFileTypeWebGuide = 9,
+ k_EWorkshopFileTypeIntegratedGuide = 10,
+ k_EWorkshopFileTypeMerch = 11,
+ k_EWorkshopFileTypeControllerBinding = 12,
+ k_EWorkshopFileTypeSteamworksAccessInvite = 13,
+ k_EWorkshopFileTypeSteamVideo = 14,
+ k_EWorkshopFileTypeGameManagedItem = 15,
+ k_EWorkshopFileTypeMax = 16
+};
+
+typedef enum EWorkshopVote EWorkshopVote;
+enum EWorkshopVote{
+ k_EWorkshopVoteUnvoted = 0,
+ k_EWorkshopVoteFor = 1,
+ k_EWorkshopVoteAgainst = 2,
+ k_EWorkshopVoteLater = 3,
+};
+
+typedef enum EWorkshopFileAction EWorkshopFileAction;
+enum EWorkshopFileAction{
+ k_EWorkshopFileActionPlayed = 0,
+ k_EWorkshopFileActionCompleted = 1,
+};
+
+typedef enum EWorkshopEnumerationType EWorkshopEnumerationType;
+enum EWorkshopEnumerationType{
+ k_EWorkshopEnumerationTypeRankedByVote = 0,
+ k_EWorkshopEnumerationTypeRecent = 1,
+ k_EWorkshopEnumerationTypeTrending = 2,
+ k_EWorkshopEnumerationTypeFavoritesOfFriends = 3,
+ k_EWorkshopEnumerationTypeVotedByFriends = 4,
+ k_EWorkshopEnumerationTypeContentByFriends = 5,
+ k_EWorkshopEnumerationTypeRecentFromFollowedUsers = 6,
+};
+
+typedef enum EWorkshopVideoProvider EWorkshopVideoProvider;
+enum EWorkshopVideoProvider{
+ k_EWorkshopVideoProviderNone = 0,
+ k_EWorkshopVideoProviderYoutube = 1
+};
+
+typedef enum EUGCReadAction EUGCReadAction;
+enum EUGCReadAction{
+ k_EUGCRead_ContinueReadingUntilFinished = 0,
+ k_EUGCRead_ContinueReading = 1,
+ k_EUGCRead_Close = 2,
+};
+
+typedef enum ERemoteStorageLocalFileChange ERemoteStorageLocalFileChange;
+enum ERemoteStorageLocalFileChange{
+ k_ERemoteStorageLocalFileChange_Invalid = 0,
+ k_ERemoteStorageLocalFileChange_FileUpdated = 1,
+ k_ERemoteStorageLocalFileChange_FileDeleted = 2,
+};
+
+typedef enum ERemoteStorageFilePathType ERemoteStorageFilePathType;
+enum ERemoteStorageFilePathType{
+ k_ERemoteStorageFilePathType_Invalid = 0,
+ k_ERemoteStorageFilePathType_Absolute = 1,
+ k_ERemoteStorageFilePathType_APIFilename = 2,
+};
+
+#define STEAMREMOTESTORAGE_INTERFACE_VERSION \
+ "STEAMREMOTESTORAGE_INTERFACE_VERSION016"
+
+#if defined( VALVE_CALLBACK_PACK_SMALL )
+#pragma pack( push, 4 )
+#elif defined( VALVE_CALLBACK_PACK_LARGE )
+#pragma pack( push, 8 )
+#else
+#error steam_api_common.h should define VALVE_CALLBACK_PACK_xxx
+#endif
+
+typedef struct RemoteStorageFileShareResult_t RemoteStorageFileShareResult_t;
+struct RemoteStorageFileShareResult_t{
+ EResult m_eResult;
+ UGCHandle_t m_hFile;
+ char m_rgchFilename[k_cchFilenameMax];
+};
+enum { k_iRemoteStorageFileShareResult = k_iSteamRemoteStorageCallbacks + 7 };
+
+typedef struct RemoteStoragePublishFileResult_t
+ RemoteStoragePublishFileResult_t;
+struct RemoteStoragePublishFileResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+ int m_bUserNeedsToAcceptWorkshopLegalAgreement;
+};
+enum { k_iRemoteStoragePublushFileResult = k_iSteamRemoteStorageCallbacks + 9 };
+
+typedef struct RemoteStorageDeletePublishedFileResult_t
+ RemoteStorageDeletePublishedFileResult_t;
+struct RemoteStorageDeletePublishedFileResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+};
+enum { k_iRemoteStorageDeletePublishedFileResult =
+ k_iSteamRemoteStorageCallbacks + 11 };
+
+typedef struct RemoteStorageEnumerateUserPublishedFilesResult_t
+ RemoteStorageEnumerateUserPublishedFilesResult_t;
+struct RemoteStorageEnumerateUserPublishedFilesResult_t{
+ EResult m_eResult;
+ i32 m_nResultsReturned;
+ i32 m_nTotalResultCount;
+ PublishedFileId_t m_rgPublishedFileId[k_unEnumeratePublishedFilesMaxResults];
+};
+enum { k_iRemoteStorageEnumerateUserPublishedFilesResult =
+ k_iSteamRemoteStorageCallbacks + 12 };
+
+typedef struct RemoteStorageSubscribePublishedFileResult_t
+ RemoteStorageSubscribePublishedFileResult_t;
+struct RemoteStorageSubscribePublishedFileResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+};
+enum { k_iRemoteStorageSubscribePublishedFileResult =
+ k_iSteamRemoteStorageCallbacks + 13 };
+
+
+typedef struct RemoteStorageEnumerateUserSubscribedFilesResult_t
+ RemoteStorageEnumerateUserSubscribedFilesResult_t;
+struct RemoteStorageEnumerateUserSubscribedFilesResult_t{
+ EResult m_eResult;
+ i32 m_nResultsReturned;
+ i32 m_nTotalResultCount;
+ PublishedFileId_t m_rgPublishedFileId[ k_unEnumeratePublishedFilesMaxResults ];
+ u32 m_rgRTimeSubscribed[ k_unEnumeratePublishedFilesMaxResults ];
+};
+enum { k_iRemoteStorageEnumerateUserSubscribedFilesResult =
+ k_iSteamRemoteStorageCallbacks + 14 };
+
+typedef struct RemoteStorageUnsubscribePublishedFileResult_t
+ RemoteStorageUnsubscribePublishedFileResult_t;
+struct RemoteStorageUnsubscribePublishedFileResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+};
+enum { k_iRemoteStorageUnsubscribePublishedFileResult =
+ k_iSteamRemoteStorageCallbacks + 15 };
+
+typedef struct RemoteStorageUpdatePublishedFileResult_t
+ RemoteStorageUpdatePublishedFileResult_t;
+struct RemoteStorageUpdatePublishedFileResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+ int m_bUserNeedsToAcceptWorkshopLegalAgreement;
+};
+enum { k_iRemoteStorageUpdatePublishedFileResult =
+ k_iSteamRemoteStorageCallbacks + 16 };
+
+
+typedef struct RemoteStorageDownloadUGCResult_t
+ RemoteStorageDownloadUGCResult_t;
+struct RemoteStorageDownloadUGCResult_t{
+ EResult m_eResult;
+ UGCHandle_t m_hFile;
+ AppId_t m_nAppID;
+ i32 m_nSizeInBytes;
+ char m_pchFileName[k_cchFilenameMax];
+ u64 m_ulSteamIDOwner;
+};
+enum { k_iRemoteStorageDownloadUGCResult =
+ k_iSteamRemoteStorageCallbacks + 17 };
+
+
+typedef struct RemoteStorageGetPublishedFileDetailsResult_t
+ RemoteStorageGetPublishedFileDetailsResult_t;
+struct RemoteStorageGetPublishedFileDetailsResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+ AppId_t m_nCreatorAppID;
+ AppId_t m_nConsumerAppID;
+ char m_rgchTitle[k_cchPublishedDocumentTitleMax];
+ char m_rgchDescription[k_cchPublishedDocumentDescriptionMax];
+ UGCHandle_t m_hFile;
+ UGCHandle_t m_hPreviewFile;
+ u64 m_ulSteamIDOwner;
+ u32 m_rtimeCreated;
+ u32 m_rtimeUpdated;
+ ERemoteStoragePublishedFileVisibility m_eVisibility;
+ int m_bBanned;
+ char m_rgchTags[k_cchTagListMax];
+ int m_bTagsTruncated;
+ char m_pchFileName[k_cchFilenameMax];
+ i32 m_nFileSize;
+ i32 m_nPreviewFileSize;
+ char m_rgchURL[k_cchPublishedFileURLMax];
+ EWorkshopFileType m_eFileType;
+ int m_bAcceptedForUse;
+};
+enum { k_iRemoteStorageGetPublishedFileDetailsResult =
+ k_iSteamRemoteStorageCallbacks + 18 };
+
+typedef struct RemoteStorageEnumerateWorkshopFilesResult_t
+ RemoteStorageEnumerateWorkshopFilesResult_t;
+struct RemoteStorageEnumerateWorkshopFilesResult_t{
+ EResult m_eResult;
+ i32 m_nResultsReturned;
+ i32 m_nTotalResultCount;
+ PublishedFileId_t m_rgPublishedFileId[ k_unEnumeratePublishedFilesMaxResults ];
+ float m_rgScore[ k_unEnumeratePublishedFilesMaxResults ];
+ AppId_t m_nAppId;
+ u32 m_unStartIndex;
+};
+enum { k_iRemoteStorageEnumerateWorkshopFilesResult_t =
+ k_iSteamRemoteStorageCallbacks + 19 };
+
+
+typedef struct RemoteStorageGetPublishedItemVoteDetailsResult_t
+ RemoteStorageGetPublishedItemVoteDetailsResult_t;
+struct RemoteStorageGetPublishedItemVoteDetailsResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_unPublishedFileId;
+ i32 m_nVotesFor;
+ i32 m_nVotesAgainst;
+ i32 m_nReports;
+ float m_fScore;
+};
+enum { k_iRemoteStorageGetPublishedItemVoteDetailsResult_t =
+ k_iSteamRemoteStorageCallbacks + 20 };
+
+
+typedef struct RemoteStoragePublishedFileSubscribed_t
+ RemoteStoragePublishedFileSubscribed_t;
+struct RemoteStoragePublishedFileSubscribed_t{
+ PublishedFileId_t m_nPublishedFileId;
+ AppId_t m_nAppID;
+};
+enum { k_iRemoteStoragePublishedFileSubscribed_t =
+ k_iSteamRemoteStorageCallbacks + 21 };
+
+typedef struct RemoteStoragePublishedFileUnsubscribed_t
+ RemoteStoragePublishedFileUnsubscribed_t;
+struct RemoteStoragePublishedFileUnsubscribed_t{
+ PublishedFileId_t m_nPublishedFileId;
+ AppId_t m_nAppID;
+};
+enum { k_iRemoteStoragePublishedFileUnsubscribed_t =
+ k_iSteamRemoteStorageCallbacks + 22 };
+
+
+typedef struct RemoteStoragePublishedFileDeleted_t
+ RemoteStoragePublishedFileDeleted_t;
+struct RemoteStoragePublishedFileDeleted_t{
+ PublishedFileId_t m_nPublishedFileId;
+ AppId_t m_nAppID;
+};
+enum { k_iRemoteStoragePublishedFileDeleted_t =
+ k_iSteamRemoteStorageCallbacks + 23 };
+
+typedef struct RemoteStorageUpdateUserPublishedItemVoteResult_t
+ RemoteStorageUpdateUserPublishedItemVoteResult_t;
+struct RemoteStorageUpdateUserPublishedItemVoteResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+};
+enum { k_iRemoteStorageUpdateUserPublishedItemVoteResult_t =
+ k_iSteamRemoteStorageCallbacks + 24 };
+
+typedef struct RemoteStorageUserVoteDetails_t RemoteStorageUserVoteDetails_t;
+struct RemoteStorageUserVoteDetails_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+ EWorkshopVote m_eVote;
+};
+enum { k_iRemoteStorageUserVoteDetails_t =
+ k_iSteamRemoteStorageCallbacks + 25 };
+
+typedef struct RemoteStorageEnumerateUserSharedWorkshopFilesResult_t
+ RemoteStorageEnumerateUserSharedWorkshopFilesResult_t;
+struct RemoteStorageEnumerateUserSharedWorkshopFilesResult_t{
+ EResult m_eResult;
+ i32 m_nResultsReturned;
+ i32 m_nTotalResultCount;
+ PublishedFileId_t m_rgPublishedFileId[k_unEnumeratePublishedFilesMaxResults];
+};
+enum { k_iRemoteStorageEnumerateUserSharedWorkshopFilesResult_t =
+ k_iSteamRemoteStorageCallbacks + 26 };
+
+typedef struct RemoteStorageSetUserPublishedFileActionResult_t
+ RemoteStorageSetUserPublishedFileActionResult_t;
+struct RemoteStorageSetUserPublishedFileActionResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+ EWorkshopFileAction m_eAction;
+};
+enum { k_iRemoteStorageSetUserPublishedFileActionResult_t =
+ k_iSteamRemoteStorageCallbacks + 27 };
+
+typedef struct RemoteStorageEnumeratePublishedFilesByUserActionResult_t
+ RemoteStorageEnumeratePublishedFilesByUserActionResult_t;
+struct RemoteStorageEnumeratePublishedFilesByUserActionResult_t{
+ EResult m_eResult;
+ EWorkshopFileAction m_eAction;
+ i32 m_nResultsReturned;
+ i32 m_nTotalResultCount;
+ PublishedFileId_t m_rgPublishedFileId[ k_unEnumeratePublishedFilesMaxResults ];
+ u32 m_rgRTimeUpdated[ k_unEnumeratePublishedFilesMaxResults ];
+};
+enum { k_iRemoteStorageEnumeratePublishedFilesByUserActionResult_t =
+ k_iSteamRemoteStorageCallbacks + 28 };
+
+typedef struct RemoteStoragePublishFileProgress_t
+ RemoteStoragePublishFileProgress_t;
+struct RemoteStoragePublishFileProgress_t{
+ double m_dPercentFile;
+ int m_bPreview;
+};
+enum { k_iRemoteStoragePublishFileProgress_t =
+ k_iSteamRemoteStorageCallbacks + 29 };
+
+typedef struct RemoteStoragePublishedFileUpdated_t
+ RemoteStoragePublishedFileUpdated_t;
+struct RemoteStoragePublishedFileUpdated_t{
+ PublishedFileId_t m_nPublishedFileId;
+ AppId_t m_nAppID;
+ u64 m_ulUnused;
+};
+enum { k_iRemoteStoragePublishedFileUpdated_t =
+ k_iSteamRemoteStorageCallbacks + 30 };
+
+typedef struct RemoteStorageFileWriteAsyncComplete_t
+ RemoteStorageFileWriteAsyncComplete_t;
+struct RemoteStorageFileWriteAsyncComplete_t{
+ EResult m_eResult;
+};
+enum { k_iRemoteStorageFileWriteAsyncComplete_t =
+ k_iSteamRemoteStorageCallbacks + 31 };
+
+typedef struct RemoteStorageFileReadAsyncComplete_t
+ RemoteStorageFileReadAsyncComplete_t;
+struct RemoteStorageFileReadAsyncComplete_t{
+ SteamAPICall_t m_hFileReadAsync;
+ EResult m_eResult;
+ u32 m_nOffset;
+ u32 m_cubRead;
+};
+enum { k_iRemoteStorageFileReadAsyncComplete_t =
+ k_iSteamRemoteStorageCallbacks + 32 };
+
+#pragma pack( pop )
+
+#endif /* VG_STEAM_REMOTE_STORAGE_H */
--- /dev/null
+#ifndef VG_STEAM_UGC_H
+#define VG_STEAM_UGC_H
+
+#include "vg_steam.h"
+#include "vg_steam_remote_storage.h"
+
+#if defined( VALVE_CALLBACK_PACK_SMALL )
+ ;
+ #pragma pack( push, 4 )
+#elif defined( VALVE_CALLBACK_PACK_LARGE )
+ #pragma pack( push, 8 )
+#endif
+
+typedef void ISteamUGC;
+typedef u64 UGCQueryHandle_t;
+typedef u64 UGCUpdateHandle_t;
+
+const UGCQueryHandle_t k_UGCQueryHandleInvalid = 0xffffffffffffffffull;
+const UGCUpdateHandle_t k_UGCUpdateHandleInvalid = 0xffffffffffffffffull;
+
+/* Matching UGC types for queries */
+typedef enum EUGCMatchingUGCType EUGCMatchingUGCType;
+enum EUGCMatchingUGCType{
+ /* both mtx items and ready-to-use items */
+ k_EUGCMatchingUGCType_Items = 0,
+ k_EUGCMatchingUGCType_Items_Mtx = 1,
+ k_EUGCMatchingUGCType_Items_ReadyToUse = 2,
+ k_EUGCMatchingUGCType_Collections = 3,
+ k_EUGCMatchingUGCType_Artwork = 4,
+ k_EUGCMatchingUGCType_Videos = 5,
+ k_EUGCMatchingUGCType_Screenshots = 6,
+
+ /* both web guides and integrated guides */
+ k_EUGCMatchingUGCType_AllGuides = 7,
+ k_EUGCMatchingUGCType_WebGuides = 8,
+ k_EUGCMatchingUGCType_IntegratedGuides = 9,
+
+ /* ready-to-use items and integrated guides */
+ k_EUGCMatchingUGCType_UsableInGame = 10,
+ k_EUGCMatchingUGCType_ControllerBindings= 11,
+
+ /* game managed items (not managed by users) */
+ k_EUGCMatchingUGCType_GameManagedItems = 12,
+
+ /* @note: will only be valid for CreateQueryUserUGCRequest requests */
+ k_EUGCMatchingUGCType_All = ~0,
+};
+
+/*
+ * Different lists of published UGC for a user.
+ * If the current logged in user is different than the specified user, then some
+ * options may not be allowed.
+ */
+typedef enum EUserUGCList EUserUGCList;
+enum EUserUGCList{
+ k_EUserUGCList_Published,
+ k_EUserUGCList_VotedOn,
+ k_EUserUGCList_VotedUp,
+ k_EUserUGCList_VotedDown,
+ k_EUserUGCList_WillVoteLater,
+ k_EUserUGCList_Favorited,
+ k_EUserUGCList_Subscribed,
+ k_EUserUGCList_UsedOrPlayed,
+ k_EUserUGCList_Followed,
+};
+
+/*
+ * Sort order for user published UGC lists (defaults to creation order
+ * descending)
+ */
+typedef enum EUserUGCListSortOrder EUserUGCListSortOrder;
+enum EUserUGCListSortOrder{
+ k_EUserUGCListSortOrder_CreationOrderDesc,
+ k_EUserUGCListSortOrder_CreationOrderAsc,
+ k_EUserUGCListSortOrder_TitleAsc,
+ k_EUserUGCListSortOrder_LastUpdatedDesc,
+ k_EUserUGCListSortOrder_SubscriptionDateDesc,
+ k_EUserUGCListSortOrder_VoteScoreDesc,
+ k_EUserUGCListSortOrder_ForModeration,
+};
+
+/*
+ * Combination of sorting and filtering for queries across all UGC
+ */
+typedef enum EUGCQuery EUGCQuery;
+enum EUGCQuery{
+ k_EUGCQuery_RankedByVote = 0,
+ k_EUGCQuery_RankedByPublicationDate = 1,
+ k_EUGCQuery_AcceptedForGameRankedByAcceptanceDate = 2,
+ k_EUGCQuery_RankedByTrend = 3,
+ k_EUGCQuery_FavoritedByFriendsRankedByPublicationDate = 4,
+ k_EUGCQuery_CreatedByFriendsRankedByPublicationDate = 5,
+ k_EUGCQuery_RankedByNumTimesReported = 6,
+ k_EUGCQuery_CreatedByFollowedUsersRankedByPublicationDate= 7,
+ k_EUGCQuery_NotYetRated = 8,
+ k_EUGCQuery_RankedByTotalVotesAsc = 9,
+ k_EUGCQuery_RankedByVotesUp = 10,
+ k_EUGCQuery_RankedByTextSearch = 11,
+ k_EUGCQuery_RankedByTotalUniqueSubscriptions = 12,
+ k_EUGCQuery_RankedByPlaytimeTrend = 13,
+ k_EUGCQuery_RankedByTotalPlaytime = 14,
+ k_EUGCQuery_RankedByAveragePlaytimeTrend = 15,
+ k_EUGCQuery_RankedByLifetimeAveragePlaytime = 16,
+ k_EUGCQuery_RankedByPlaytimeSessionsTrend = 17,
+ k_EUGCQuery_RankedByLifetimePlaytimeSessions = 18,
+ k_EUGCQuery_RankedByLastUpdatedDate = 19,
+};
+
+typedef enum EItemUpdateStatus EItemUpdateStatus;
+enum EItemUpdateStatus{
+ /* The item update handle was invalid, job might be finished, listen too
+ * SubmitItemUpdateResult_t */
+ k_EItemUpdateStatusInvalid = 0,
+
+ /* The item update is processing configuration data */
+ k_EItemUpdateStatusPreparingConfig = 1,
+
+ /* The item update is reading and processing content files */
+ k_EItemUpdateStatusPreparingContent= 2,
+
+ /* The item update is uploading content changes to Steam */
+ k_EItemUpdateStatusUploadingContent= 3,
+
+ /* The item update is uploading new preview file image */
+ k_EItemUpdateStatusUploadingPreviewFile= 4,
+
+ /* The item update is committing all changes */
+ k_EItemUpdateStatusCommittingChanges = 5
+};
+
+typedef enum EItemState EItemState;
+enum EItemState{
+ /* item not tracked on client */
+ k_EItemStateNone = 0,
+
+ /* current user is subscribed to this item. Not just cached. */
+ k_EItemStateSubscribed = 1,
+
+ /* item was created with ISteamRemoteStorage */
+ k_EItemStateLegacyItem = 2,
+
+ /* item is installed and usable (but maybe out of date) */
+ k_EItemStateInstalled = 4,
+
+ /* items needs an update. Either because it's not installed yet or creator
+ * updated content */
+ k_EItemStateNeedsUpdate = 8,
+
+ /* item update is currently downloading */
+ k_EItemStateDownloading = 16,
+
+ /* DownloadItem() was called for this item, content isn't available until
+ * DownloadItemResult_t is fired */
+ k_EItemStateDownloadPending= 32,
+};
+
+typedef enum EItemStatistic EItemStatistic;
+enum EItemStatistic{
+ k_EItemStatistic_NumSubscriptions = 0,
+ k_EItemStatistic_NumFavorites = 1,
+ k_EItemStatistic_NumFollowers = 2,
+ k_EItemStatistic_NumUniqueSubscriptions = 3,
+ k_EItemStatistic_NumUniqueFavorites = 4,
+ k_EItemStatistic_NumUniqueFollowers = 5,
+ k_EItemStatistic_NumUniqueWebsiteViews = 6,
+ k_EItemStatistic_ReportScore = 7,
+ k_EItemStatistic_NumSecondsPlayed = 8,
+ k_EItemStatistic_NumPlaytimeSessions = 9,
+ k_EItemStatistic_NumComments = 10,
+ k_EItemStatistic_NumSecondsPlayedDuringTimePeriod = 11,
+ k_EItemStatistic_NumPlaytimeSessionsDuringTimePeriod = 12,
+};
+
+typedef enum EItemPreviewType EItemPreviewType;
+enum EItemPreviewType{
+ /* standard image file expected (e.g. jpg, png, gif, etc.) */
+ k_EItemPreviewType_Image = 0,
+
+ k_EItemPreviewType_YouTubeVideo = 1, /* video id is stored */
+ k_EItemPreviewType_Sketchfab = 2, /* model id is stored */
+
+ /*
+ * standard image file expected - cube map in the layout
+ * +---+---+-------+
+ * | |Up | |
+ * +---+---+---+---+
+ * | L | F | R | B |
+ * +---+---+---+---+
+ * | |Dn | |
+ * +---+---+---+---+
+ */
+ k_EItemPreviewType_EnvironmentMap_HorizontalCross = 3,
+
+ /* standard image file expected */
+ k_EItemPreviewType_EnvironmentMap_LatLong = 4,
+
+ /* you can specify your own types above this value */
+ k_EItemPreviewType_ReservedMax = 255,
+};
+
+const u32 kNumUGCResultsPerPage = 50;
+const u32 k_cchDeveloperMetadataMax = 5000;
+
+/* Details for a single published file/UGC */
+typedef struct SteamUGCDetails_t SteamUGCDetails_t;
+struct SteamUGCDetails_t{
+ PublishedFileId_t m_nPublishedFileId;
+ EResult m_eResult; /* The result of the operation. */
+ EWorkshopFileType m_eFileType; /* Type of the file */
+ AppId_t m_nCreatorAppID; /*ID of the app that created this file. */
+ AppId_t m_nConsumerAppID; /* ID of the app that will consume this file. */
+ char m_rgchTitle[k_cchPublishedDocumentTitleMax]; /* title of document */
+
+ /* description of document */
+ char m_rgchDescription[k_cchPublishedDocumentDescriptionMax];
+ u64 m_ulSteamIDOwner; /* Steam ID of the user who created this content. */
+ u32 m_rtimeCreated; /* time when the published file was created */
+ u32 m_rtimeUpdated; /* time when the published file was last updated */
+
+ /* time when the user added the published file to their list (not always
+ * applicable) */
+ u32 m_rtimeAddedToUserList;
+ ERemoteStoragePublishedFileVisibility m_eVisibility; /* visibility */
+ int m_bBanned; /* whether the file was banned */
+
+ /* developer has specifically flagged this item as accepted in the Workshop*/
+ int m_bAcceptedForUse;
+
+ /* whether the list of tags was too long to be returned in the provided
+ * buffer */
+ int m_bTagsTruncated;
+
+ /* comma separated list of all tags associated with this file */
+ char m_rgchTags[k_cchTagListMax];
+
+ /* file/url information */
+ UGCHandle_t m_hFile; /* The handle of the primary file */
+ UGCHandle_t m_hPreviewFile; /* The handle of the preview file */
+
+ /* The cloud filename of the primary file */
+ char m_pchFileName[k_cchFilenameMax];
+
+ /* Size of the primary file */
+ i32 m_nFileSize;
+ i32 m_nPreviewFileSize; /* Size of the preview file */
+ char m_rgchURL[k_cchPublishedFileURLMax]; /* URL (for a video or a website)*/
+
+ /* voting information */
+ u32 m_unVotesUp; /* number of votes up */
+ u32 m_unVotesDown; /* number of votes down */
+ float m_flScore; /* calculated score */
+
+ /* collection details */
+ u32 m_unNumChildren;
+};
+
+/*
+ * Callback for querying UGC
+ */
+typedef struct SteamUGCQueryCompleted_t SteamUGCQueryCompleted_t;
+struct SteamUGCQueryCompleted_t{
+ UGCQueryHandle_t m_handle;
+ EResult m_eResult;
+ u32 m_unNumResultsReturned;
+ u32 m_unTotalMatchingResults;
+
+ /* indicates whether this data was retrieved from the local on-disk cache */
+ int m_bCachedData;
+
+ /* If a paging cursor was used, then this will be the next cursor to get the
+ * next result set. */
+ char m_rgchNextCursor[k_cchPublishedFileURLMax];
+};
+enum { k_iSteamUGCQueryCompleted = k_iSteamUGCCallbacks + 31 };
+
+/*
+ * Callback for requesting details on one piece of UGC
+ */
+typedef struct SteamUGCRequestUGCDetailsResult_t
+ SteamUGCRequestUGCDetailsResult_t;
+struct SteamUGCRequestUGCDetailsResult_t{
+ SteamUGCDetails_t m_details;
+
+ /* indicates whether this data was retrieved from the local on-disk cache */
+ int m_bCachedData;
+};
+enum { k_iSteamUGCRequestUGCDetailsResult = k_iSteamUGCCallbacks + 2 };
+
+
+/*
+ * Purpose: result for ISteamUGC::CreateItem()
+ */
+typedef struct CreateItemResult_t CreateItemResult_t;
+struct CreateItemResult_t{
+ EResult m_eResult;
+
+ /* new item got this UGC PublishFileID */
+ PublishedFileId_t m_nPublishedFileId;
+ int m_bUserNeedsToAcceptWorkshopLegalAgreement;
+};
+enum { k_iCreateItemResult = k_iSteamUGCCallbacks + 3 };
+
+
+/*
+ * Purpose: result for ISteamUGC::SubmitItemUpdate()
+ */
+typedef struct SubmitItemUpdateResult_t SubmitItemUpdateResult_t;
+struct SubmitItemUpdateResult_t{
+ EResult m_eResult;
+ int m_bUserNeedsToAcceptWorkshopLegalAgreement;
+ PublishedFileId_t m_nPublishedFileId;
+};
+enum { k_iSubmitItemUpdateResult = k_iSteamUGCCallbacks + 4 };
+
+
+/*
+ * Purpose: a Workshop item has been installed or updated
+ */
+typedef struct ItemInstalled_t ItemInstalled_t;
+struct ItemInstalled_t{
+ AppId_t m_unAppID;
+ PublishedFileId_t m_nPublishedFileId;
+};
+enum { k_iItemInstalled = k_iSteamUGCCallbacks + 5 };
+
+
+/*
+ * Purpose: result of DownloadItem(), existing item files can be accessed again
+ */
+typedef struct DownloadItemResult_t DownloadItemResult_t;
+struct DownloadItemResult_t{
+ AppId_t m_unAppID;
+ PublishedFileId_t m_nPublishedFileId;
+ EResult m_eResult;
+};
+enum { k_iDownloadItemResult = k_iSteamUGCCallbacks + 6 };
+
+/*
+ * Purpose: result of AddItemToFavorites() or RemoveItemFromFavorites()
+ */
+typedef struct UserFavoriteItemsListChanged_t UserFavoriteItemsListChanged_t;
+struct UserFavoriteItemsListChanged_t{
+ PublishedFileId_t m_nPublishedFileId;
+ EResult m_eResult;
+ int m_bWasAddRequest;
+};
+enum { k_iUserFavoriteItemsListChanged = k_iSteamUGCCallbacks + 7 };
+
+/*
+ * Purpose: The result of a call to SetUserItemVote()
+ */
+typedef struct SetUserItemVoteResult_t SetUserItemVoteResult_t;
+struct SetUserItemVoteResult_t{
+ PublishedFileId_t m_nPublishedFileId;
+ EResult m_eResult;
+ int m_bVoteUp;
+};
+enum { k_iSetUserItemVoteResult = k_iSteamUGCCallbacks + 8 };
+
+/*
+ * Purpose: The result of a call to GetUserItemVote()
+ */
+typedef struct GetUserItemVoteResult_t GetUserItemVoteResult_t;
+struct GetUserItemVoteResult_t{
+ PublishedFileId_t m_nPublishedFileId;
+ EResult m_eResult;
+ int m_bVotedUp;
+ int m_bVotedDown;
+ int m_bVoteSkipped;
+};
+enum { k_iGetUserItemVoteResult = k_iSteamUGCCallbacks + 9 };
+
+/*
+ * Purpose: The result of a call to StartPlaytimeTracking()
+ */
+typedef struct StartPlaytimeTrackingResult_t StartPlaytimeTrackingResult_t;
+struct StartPlaytimeTrackingResult_t{
+ EResult m_eResult;
+};
+enum { k_iStartPlaytimeTrackingResult = k_iSteamUGCCallbacks + 10 };
+
+/*
+ * Purpose: The result of a call to StopPlaytimeTracking()
+ */
+typedef struct StopPlaytimeTrackingResult_t StopPlaytimeTrackingResult_t;
+struct StopPlaytimeTrackingResult_t{
+ EResult m_eResult;
+};
+enum { k_iStopPlaytimeTrackingResult = k_iSteamUGCCallbacks + 11 };
+
+/*
+ * Purpose: The result of a call to AddDependency
+ */
+typedef struct AddUGCDependencyResult_t AddUGCDependencyResult_t;
+struct AddUGCDependencyResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+ PublishedFileId_t m_nChildPublishedFileId;
+};
+enum { k_iAddUGCDependecyResult = k_iSteamUGCCallbacks + 12 };
+
+/*
+ * Purpose: The result of a call to RemoveDependency
+ */
+typedef struct RemoveUGCDependencyResult_t RemoveUGCDependencyResult_t;
+struct RemoveUGCDependencyResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+ PublishedFileId_t m_nChildPublishedFileId;
+};
+enum { k_iRemoveUGCDependecyResult = k_iSteamUGCCallbacks + 13 };
+
+
+/*
+ * Purpose: The result of a call to AddAppDependency
+ */
+typedef struct AddAppDependencyResult_t AddAppDependencyResult_t;
+struct AddAppDependencyResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+ AppId_t m_nAppID;
+};
+enum { k_iAddAppDependencyResult = k_iSteamUGCCallbacks + 14 };
+
+/*
+ * Purpose: The result of a call to RemoveAppDependency
+ */
+typedef struct RemoveAppDependencyResult_t RemoveAppDependencyResult_t;
+struct RemoveAppDependencyResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+ AppId_t m_nAppID;
+};
+enum { k_iRemoveAppDependencyResult = k_iSteamUGCCallbacks + 15 };
+
+/*
+ * Purpose: The result of a call to GetAppDependencies. Callback may be called
+ * multiple times until all app dependencies have been returned.
+ */
+typedef struct GetAppDependenciesResult_t GetAppDependenciesResult_t;
+struct GetAppDependenciesResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+ AppId_t m_rgAppIDs[32];
+ u32 m_nNumAppDependencies; // number returned in this struct
+ u32 m_nTotalNumAppDependencies; // total found
+};
+enum { k_iGetAppDependeniesResult = k_iSteamUGCCallbacks + 16 };
+
+/*
+ * Purpose: The result of a call to DeleteItem
+ */
+typedef struct DeleteItemResult_t DeleteItemResult_t;
+struct DeleteItemResult_t{
+ EResult m_eResult;
+ PublishedFileId_t m_nPublishedFileId;
+};
+enum { k_iDeleteItemResult = k_iSteamUGCCallbacks + 17 };
+
+
+/*
+ * Purpose: signal that the list of subscribed items changed
+ */
+typedef struct UserSubscribedItemsListChanged_t
+ UserSubscribedItemsListChanged_t;
+struct UserSubscribedItemsListChanged_t{
+ AppId_t m_nAppID;
+};
+enum { k_iUserSubscribedItemsListChanged = k_iSteamUGCCallbacks + 18 };
+
+
+/*
+ * Purpose: Status of the user's acceptable/rejection of the app's specific
+ * Workshop EULA
+ */
+typedef struct WorkshopEULAStatus_t WorkshopEULAStatus_t;
+struct WorkshopEULAStatus_t{
+ EResult m_eResult;
+ AppId_t m_nAppID;
+ u32 m_unVersion;
+ RTime32 m_rtAction;
+ int m_bAccepted;
+ int m_bNeedsAction;
+};
+enum { k_iWorkshopEULAStatus = k_iSteamUGCCallbacks + 20 };
+
+#pragma pack( pop )
+
+#define STEAMUGC_INTERFACE_VERSION "STEAMUGC_INTERFACE_VERSION016"
+
+ISteamUGC *SteamAPI_SteamUGC_v016();
+ISteamUGC *SteamAPI_SteamUGC()
+{
+ return SteamAPI_SteamUGC_v016();
+}
+ISteamUGC *SteamAPI_SteamGameServerUGC_v016();
+ISteamUGC *SteamAPI_SteamGameServerUGC()
+{
+ return SteamAPI_SteamGameServerUGC_v016();
+}
+UGCQueryHandle_t SteamAPI_ISteamUGC_CreateQueryUserUGCRequest(
+ ISteamUGC *self, AccountID_t unAccountID, EUserUGCList eListType,
+ EUGCMatchingUGCType eMatchingUGCType, EUserUGCListSortOrder eSortOrder,
+ AppId_t nCreatorAppID, AppId_t nConsumerAppID, u32 unPage );
+
+UGCQueryHandle_t SteamAPI_ISteamUGC_CreateQueryAllUGCRequestPage(
+ ISteamUGC *self, EUGCQuery eQueryType,
+ EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType,
+ AppId_t nCreatorAppID, AppId_t nConsumerAppID, u32 unPage );
+
+UGCQueryHandle_t SteamAPI_ISteamUGC_CreateQueryAllUGCRequestCursor(
+ ISteamUGC *self, EUGCQuery eQueryType,
+ EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType,
+ AppId_t nCreatorAppID, AppId_t nConsumerAppID, const char * pchCursor );
+
+UGCQueryHandle_t SteamAPI_ISteamUGC_CreateQueryUGCDetailsRequest(
+ ISteamUGC *self, PublishedFileId_t *pvecPublishedFileID,
+ u32 unNumPublishedFileIDs );
+
+SteamAPICall_t SteamAPI_ISteamUGC_SendQueryUGCRequest( ISteamUGC* self,
+ UGCQueryHandle_t handle );
+
+int SteamAPI_ISteamUGC_GetQueryUGCResult(
+ ISteamUGC *self, UGCQueryHandle_t handle, u32 index,
+ SteamUGCDetails_t *pDetails );
+
+u32 SteamAPI_ISteamUGC_GetQueryUGCNumTags( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 index );
+
+int SteamAPI_ISteamUGC_GetQueryUGCTag(
+ ISteamUGC* self, UGCQueryHandle_t handle, u32 index, u32 indexTag,
+ char * pchValue, u32 cchValueSize );
+
+int SteamAPI_ISteamUGC_GetQueryUGCTagDisplayName( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 index, u32 indexTag, char * pchValue,
+ u32 cchValueSize );
+
+int SteamAPI_ISteamUGC_GetQueryUGCPreviewURL( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 index, char * pchURL, u32 cchURLSize );
+
+int SteamAPI_ISteamUGC_GetQueryUGCMetadata( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 index, char * pchMetadata,
+ u32 cchMetadatasize );
+
+int SteamAPI_ISteamUGC_GetQueryUGCChildren( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 index,
+ PublishedFileId_t *pvecPublishedFileID, u32 cMaxEntries );
+
+int SteamAPI_ISteamUGC_GetQueryUGCStatistic( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 index, EItemStatistic eStatType,
+ u64 *pStatValue );
+
+u32 SteamAPI_ISteamUGC_GetQueryUGCNumAdditionalPreviews( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 index );
+
+int SteamAPI_ISteamUGC_GetQueryUGCAdditionalPreview( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 index, u32 previewIndex,
+ char *pchURLOrVideoID, u32 cchURLSize, char *pchOriginalFileName,
+ u32 cchOriginalFileNameSize, EItemPreviewType *pPreviewType );
+
+u32 SteamAPI_ISteamUGC_GetQueryUGCNumKeyValueTags( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 index );
+
+int SteamAPI_ISteamUGC_GetQueryUGCKeyValueTag( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 index, u32 keyValueTagIndex, char *pchKey,
+ u32 cchKeySize, char * pchValue, u32 cchValueSize );
+
+int SteamAPI_ISteamUGC_GetQueryFirstUGCKeyValueTag( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 index, const char *pchKey, char *pchValue,
+ u32 cchValueSize );
+
+int SteamAPI_ISteamUGC_ReleaseQueryUGCRequest( ISteamUGC* self,
+ UGCQueryHandle_t handle );
+
+int SteamAPI_ISteamUGC_AddRequiredTag( ISteamUGC* self, UGCQueryHandle_t handle,
+ const char * pTagName );
+
+int SteamAPI_ISteamUGC_AddRequiredTagGroup( ISteamUGC* self,
+ UGCQueryHandle_t handle, const SteamParamStringArray_t * pTagGroups );
+
+int SteamAPI_ISteamUGC_AddExcludedTag( ISteamUGC* self, UGCQueryHandle_t handle,
+ const char * pTagName );
+
+int SteamAPI_ISteamUGC_SetReturnOnlyIDs( ISteamUGC* self,
+ UGCQueryHandle_t handle, int bReturnOnlyIDs );
+
+int SteamAPI_ISteamUGC_SetReturnKeyValueTags( ISteamUGC* self,
+ UGCQueryHandle_t handle, int bReturnKeyValueTags );
+
+int SteamAPI_ISteamUGC_SetReturnLongDescription( ISteamUGC* self,
+ UGCQueryHandle_t handle, int bReturnLongDescription );
+
+int SteamAPI_ISteamUGC_SetReturnMetadata( ISteamUGC* self,
+ UGCQueryHandle_t handle, int bReturnMetadata );
+
+int SteamAPI_ISteamUGC_SetReturnChildren( ISteamUGC* self,
+ UGCQueryHandle_t handle, int bReturnChildren );
+
+int SteamAPI_ISteamUGC_SetReturnAdditionalPreviews( ISteamUGC* self,
+ UGCQueryHandle_t handle, int bReturnAdditionalPreviews );
+
+int SteamAPI_ISteamUGC_SetReturnTotalOnly( ISteamUGC* self,
+ UGCQueryHandle_t handle, int bReturnTotalOnly );
+
+int SteamAPI_ISteamUGC_SetReturnPlaytimeStats( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 unDays );
+
+int SteamAPI_ISteamUGC_SetLanguage( ISteamUGC* self, UGCQueryHandle_t handle,
+ const char * pchLanguage );
+
+int SteamAPI_ISteamUGC_SetAllowCachedResponse( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 unMaxAgeSeconds );
+
+int SteamAPI_ISteamUGC_SetCloudFileNameFilter( ISteamUGC* self,
+ UGCQueryHandle_t handle, const char * pMatchCloudFileName );
+
+int SteamAPI_ISteamUGC_SetMatchAnyTag( ISteamUGC* self, UGCQueryHandle_t handle,
+ int bMatchAnyTag );
+
+int SteamAPI_ISteamUGC_SetSearchText( ISteamUGC* self, UGCQueryHandle_t handle,
+ const char * pSearchText );
+
+int SteamAPI_ISteamUGC_SetRankedByTrendDays( ISteamUGC* self,
+ UGCQueryHandle_t handle, u32 unDays );
+
+int SteamAPI_ISteamUGC_SetTimeCreatedDateRange( ISteamUGC* self,
+ UGCQueryHandle_t handle, RTime32 rtStart, RTime32 rtEnd );
+
+int SteamAPI_ISteamUGC_SetTimeUpdatedDateRange( ISteamUGC* self,
+ UGCQueryHandle_t handle, RTime32 rtStart, RTime32 rtEnd );
+
+int SteamAPI_ISteamUGC_AddRequiredKeyValueTag( ISteamUGC* self,
+ UGCQueryHandle_t handle, const char * pKey, const char * pValue );
+
+SteamAPICall_t SteamAPI_ISteamUGC_RequestUGCDetails( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID, u32 unMaxAgeSeconds );
+
+SteamAPICall_t SteamAPI_ISteamUGC_CreateItem( ISteamUGC* self,
+ AppId_t nConsumerAppId, EWorkshopFileType eFileType );
+
+UGCUpdateHandle_t SteamAPI_ISteamUGC_StartItemUpdate( ISteamUGC* self,
+ AppId_t nConsumerAppId, PublishedFileId_t nPublishedFileID );
+
+int SteamAPI_ISteamUGC_SetItemTitle( ISteamUGC* self, UGCUpdateHandle_t handle,
+ const char * pchTitle );
+
+int SteamAPI_ISteamUGC_SetItemDescription( ISteamUGC* self,
+ UGCUpdateHandle_t handle, const char * pchDescription );
+
+int SteamAPI_ISteamUGC_SetItemUpdateLanguage( ISteamUGC* self,
+ UGCUpdateHandle_t handle, const char * pchLanguage );
+
+int SteamAPI_ISteamUGC_SetItemMetadata( ISteamUGC* self,
+ UGCUpdateHandle_t handle, const char * pchMetaData );
+
+int SteamAPI_ISteamUGC_SetItemVisibility( ISteamUGC* self,
+ UGCUpdateHandle_t handle,
+ ERemoteStoragePublishedFileVisibility eVisibility );
+
+int SteamAPI_ISteamUGC_SetItemTags( ISteamUGC* self,
+ UGCUpdateHandle_t updateHandle, const SteamParamStringArray_t * pTags );
+
+int SteamAPI_ISteamUGC_SetItemContent( ISteamUGC* self,
+ UGCUpdateHandle_t handle, const char * pszContentFolder );
+
+int SteamAPI_ISteamUGC_SetItemPreview( ISteamUGC* self,
+ UGCUpdateHandle_t handle, const char * pszPreviewFile );
+
+int SteamAPI_ISteamUGC_SetAllowLegacyUpload( ISteamUGC* self,
+ UGCUpdateHandle_t handle, int bAllowLegacyUpload );
+
+int SteamAPI_ISteamUGC_RemoveAllItemKeyValueTags( ISteamUGC* self,
+ UGCUpdateHandle_t handle );
+
+int SteamAPI_ISteamUGC_RemoveItemKeyValueTags( ISteamUGC* self,
+ UGCUpdateHandle_t handle, const char * pchKey );
+
+int SteamAPI_ISteamUGC_AddItemKeyValueTag( ISteamUGC* self,
+ UGCUpdateHandle_t handle, const char * pchKey, const char * pchValue );
+
+int SteamAPI_ISteamUGC_AddItemPreviewFile( ISteamUGC* self,
+ UGCUpdateHandle_t handle, const char * pszPreviewFile,
+ EItemPreviewType type );
+
+int SteamAPI_ISteamUGC_AddItemPreviewVideo( ISteamUGC* self,
+ UGCUpdateHandle_t handle, const char * pszVideoID );
+
+int SteamAPI_ISteamUGC_UpdateItemPreviewFile( ISteamUGC* self,
+ UGCUpdateHandle_t handle, u32 index, const char * pszPreviewFile );
+
+int SteamAPI_ISteamUGC_UpdateItemPreviewVideo( ISteamUGC* self,
+ UGCUpdateHandle_t handle, u32 index, const char * pszVideoID );
+
+int SteamAPI_ISteamUGC_RemoveItemPreview( ISteamUGC* self,
+ UGCUpdateHandle_t handle, u32 index );
+
+SteamAPICall_t SteamAPI_ISteamUGC_SubmitItemUpdate( ISteamUGC* self,
+ UGCUpdateHandle_t handle, const char * pchChangeNote );
+
+EItemUpdateStatus SteamAPI_ISteamUGC_GetItemUpdateProgress( ISteamUGC* self,
+ UGCUpdateHandle_t handle, u64 * punBytesProcessed, u64 * punBytesTotal );
+
+SteamAPICall_t SteamAPI_ISteamUGC_SetUserItemVote( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID, int bVoteUp );
+
+SteamAPICall_t SteamAPI_ISteamUGC_GetUserItemVote( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID );
+
+SteamAPICall_t SteamAPI_ISteamUGC_AddItemToFavorites( ISteamUGC* self,
+ AppId_t nAppId, PublishedFileId_t nPublishedFileID );
+
+SteamAPICall_t SteamAPI_ISteamUGC_RemoveItemFromFavorites( ISteamUGC* self,
+ AppId_t nAppId, PublishedFileId_t nPublishedFileID );
+
+SteamAPICall_t SteamAPI_ISteamUGC_SubscribeItem( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID );
+
+SteamAPICall_t SteamAPI_ISteamUGC_UnsubscribeItem( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID );
+
+u32 SteamAPI_ISteamUGC_GetNumSubscribedItems( ISteamUGC* self );
+
+u32 SteamAPI_ISteamUGC_GetSubscribedItems( ISteamUGC* self,
+ PublishedFileId_t * pvecPublishedFileID, u32 cMaxEntries );
+
+u32 SteamAPI_ISteamUGC_GetItemState( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID );
+
+int SteamAPI_ISteamUGC_GetItemInstallInfo( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID, u64 * punSizeOnDisk, char * pchFolder,
+ u32 cchFolderSize, u32 * punTimeStamp );
+
+int SteamAPI_ISteamUGC_GetItemDownloadInfo( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID, u64 * punBytesDownloaded,
+ u64 * punBytesTotal );
+
+int SteamAPI_ISteamUGC_DownloadItem( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID, int bHighPriority );
+
+int SteamAPI_ISteamUGC_BInitWorkshopForGameServer( ISteamUGC* self,
+ DepotId_t unWorkshopDepotID, const char * pszFolder );
+
+void SteamAPI_ISteamUGC_SuspendDownloads( ISteamUGC* self, int bSuspend );
+
+SteamAPICall_t SteamAPI_ISteamUGC_StartPlaytimeTracking( ISteamUGC* self,
+ PublishedFileId_t * pvecPublishedFileID, u32 unNumPublishedFileIDs );
+
+SteamAPICall_t SteamAPI_ISteamUGC_StopPlaytimeTracking( ISteamUGC* self,
+ PublishedFileId_t * pvecPublishedFileID, u32 unNumPublishedFileIDs );
+
+SteamAPICall_t SteamAPI_ISteamUGC_StopPlaytimeTrackingForAllItems(
+ ISteamUGC* self );
+
+SteamAPICall_t SteamAPI_ISteamUGC_AddDependency( ISteamUGC* self,
+ PublishedFileId_t nParentPublishedFileID,
+ PublishedFileId_t nChildPublishedFileID );
+
+SteamAPICall_t SteamAPI_ISteamUGC_RemoveDependency( ISteamUGC* self,
+ PublishedFileId_t nParentPublishedFileID,
+ PublishedFileId_t nChildPublishedFileID );
+
+SteamAPICall_t SteamAPI_ISteamUGC_AddAppDependency( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID, AppId_t nAppID );
+
+SteamAPICall_t SteamAPI_ISteamUGC_RemoveAppDependency( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID, AppId_t nAppID );
+
+SteamAPICall_t SteamAPI_ISteamUGC_GetAppDependencies( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID );
+
+SteamAPICall_t SteamAPI_ISteamUGC_DeleteItem( ISteamUGC* self,
+ PublishedFileId_t nPublishedFileID );
+
+int SteamAPI_ISteamUGC_ShowWorkshopEULA( ISteamUGC* self );
+
+SteamAPICall_t SteamAPI_ISteamUGC_GetWorkshopEULAStatus( ISteamUGC* self );
+
+#endif /* VG_STEAM_UGC_H */
-/* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
+/* Copyright (C) 2021-2023 Harry Godden (hgn) - All Rights Reserved
+ *
+ * A portion of this file is copied and altered from the QOI projects' source,
+ * Originally written by Dominic Szablewski. It is slightly modified.
+ * For the original unaltered QOI header, you can find it here:
+ * https://github.com/phoboslab/qoi/blob/master/qoi.h
+ *
+ * Copyright (C) 2021, Dominic Szablewski
+ * SPDX-License-Identifier: MIT
+ *
+ * MIT License
+ Copyright (c) 2022 Dominic Szablewski - https://phoboslab.org
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
#ifndef VG_TEX_H
#define VG_TEX_H
#include "vg/vg.h"
#include "vg/vg_log.h"
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+#include "vg/submodules/stb/stb_image_write.h"
+
struct vg_sprite
{
v4f uv_xywh;