From 1c56bc84c9ad3da49c9d2447ec97aaf7f6038601 Mon Sep 17 00:00:00 2001 From: hgn Date: Wed, 22 Nov 2023 12:09:58 +0000 Subject: [PATCH] load in preview images to dynamic rt textures --- addon.c | 28 ++++++--- addon.h | 2 +- blender_export.py | 7 +++ ent_skateshop.c | 119 +++++++++++++++++++++++++++++++++++--- ent_skateshop.h | 7 ++- maps_src/dev_hub/main.mdl | Bin 249656 -> 249728 bytes skaterift.h | 6 ++ world_load.c | 2 +- world_render.c | 24 +++++--- 9 files changed, 169 insertions(+), 26 deletions(-) diff --git a/addon.c b/addon.c index 0b342ce..7ebd165 100644 --- a/addon.c +++ b/addon.c @@ -522,16 +522,30 @@ static void addon_mount_content_folder( enum addon_type type, /* * write the full path of the addon's folder into the vg_str */ -static int addon_get_content_folder( addon_reg *reg, vg_str *folder ){ +static int addon_get_content_folder( addon_reg *reg, vg_str *folder, int async){ if( reg->alias.workshop_id ){ - vg_async_item *call = - vg_async_alloc( sizeof(struct async_workshop_filepath_info) ); - struct async_workshop_filepath_info *info = call->payload; + struct async_workshop_filepath_info *info = NULL; + vg_async_item *call = NULL; + + if( async ){ + call = vg_async_alloc( sizeof(struct async_workshop_filepath_info) ); + info = call->payload; + } + else + info = alloca( sizeof(struct async_workshop_filepath_info) ); + info->buf = folder->buffer; info->id = reg->alias.workshop_id; info->len = folder->len; - vg_async_dispatch( call, async_workshop_get_filepath ); - vg_async_stall(); /* too bad! */ + + if( async ){ + vg_async_dispatch( call, async_workshop_get_filepath ); + vg_async_stall(); /* too bad! */ + } + else { + async_workshop_get_filepath( info, 0 ); + } + if( info->buf[0] == '\0' ){ vg_error( "Failed SteamAPI_GetItemInstallInfo(" PRINTF_U64 ")\n", reg->alias.workshop_id ); @@ -723,7 +737,7 @@ static void addon_cache_load_loop(void){ vg_str folder; vg_strnull( &folder, path_buf, 4096 ); - if( addon_get_content_folder( reg, &folder ) ){ + if( addon_get_content_folder( reg, &folder, 1 ) ){ if( addon_cache_load_request( type, id, reg, folder ) ){ vg_async_call( async_addon_setstate, entry, k_addon_cache_state_loaded ); diff --git a/addon.h b/addon.h index cae83f6..5ca812c 100644 --- a/addon.h +++ b/addon.h @@ -74,7 +74,7 @@ static u32 addon_count( enum addon_type type, u32 ignoreflags ); static addon_reg *get_addon_from_index( enum addon_type type, u32 index, u32 ignoreflags ); static u32 get_index_from_addon( enum addon_type type, addon_reg *a ); -static int addon_get_content_folder( addon_reg *reg, vg_str *folder ); +static int addon_get_content_folder( addon_reg *reg, vg_str *folder, int async); /* scanning routines */ static u32 addon_match( addon_alias *alias ); diff --git a/blender_export.py b/blender_export.py index 5eb5975..d397cd7 100644 --- a/blender_export.py +++ b/blender_export.py @@ -910,6 +910,10 @@ def sr_compile_material( mat ):#{ m.tex_diffuse = sr_compile_texture(inf['tex_diffuse']) #} + if mat.SR_data.tex_diffuse_rt >= 0:#{ + m.tex_diffuse = 0x80000000 | mat.SR_data.tex_diffuse_rt + #} + sr_compile.material_data.extend( bytearray(m) ) return index #} @@ -2502,6 +2506,7 @@ class SR_MATERIAL_PANEL(bpy.types.Panel): _.layout.prop( active_mat.SR_data, "shader" ) _.layout.prop( active_mat.SR_data, "surface_prop" ) _.layout.prop( active_mat.SR_data, "collision" ) + _.layout.prop( active_mat.SR_data, "tex_diffuse_rt" ) if active_mat.SR_data.collision:#{ box = _.layout.box() @@ -3586,6 +3591,8 @@ class SR_MATERIAL_PROPERTIES(bpy.types.PropertyGroup): cubemap: bpy.props.PointerProperty( \ type=bpy.types.Object, name="cubemap", \ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_cubemap'])) + + tex_diffuse_rt: bpy.props.IntProperty( name="diffuse: RT index", default=-1 ) #} # ---------------------------------------------------------------------------- # diff --git a/ent_skateshop.c b/ent_skateshop.c index 962edf4..c10352d 100644 --- a/ent_skateshop.c +++ b/ent_skateshop.c @@ -44,6 +44,76 @@ static void skateshop_update_viewpage(void){ } } +struct async_preview_load_thread_data{ + void *data; + addon_reg *reg; +}; + +static void skateshop_async_preview_imageload( void *data, u32 len ){ + struct async_preview_load_thread_data *inf = data; + + if( inf->data ){ + glBindTexture( GL_TEXTURE_2D, global_skateshop.tex_preview ); + glTexSubImage2D( GL_TEXTURE_2D, 0,0,0, + WORKSHOP_PREVIEW_WIDTH, WORKSHOP_PREVIEW_HEIGHT, + GL_RGB, GL_UNSIGNED_BYTE, inf->data ); + glGenerateMipmap( GL_TEXTURE_2D ); + stbi_image_free( inf->data ); + + skaterift.rt_textures[k_skaterift_rt_workshop_preview] = + global_skateshop.tex_preview; + } + else { + skaterift.rt_textures[k_skaterift_rt_workshop_preview] = + global_skateshop.tex_preview_err; + } + + SDL_AtomicLock( &addon_system.sl_cache_using_resources ); + global_skateshop.reg_loaded_preview = inf->reg; + SDL_AtomicUnlock( &addon_system.sl_cache_using_resources ); +} + +static void skateshop_update_preview_image_thread(void *_args){ + char path_buf[4096]; + vg_str folder; + vg_strnull( &folder, path_buf, sizeof(path_buf) ); + + SDL_AtomicLock( &addon_system.sl_cache_using_resources ); + addon_reg *reg_preview = global_skateshop.reg_preview; + SDL_AtomicUnlock( &addon_system.sl_cache_using_resources ); + + if( !addon_get_content_folder( reg_preview, &folder, 1 ) ){ + SDL_AtomicLock( &addon_system.sl_cache_using_resources ); + global_skateshop.reg_loaded_preview = reg_preview; + SDL_AtomicUnlock( &addon_system.sl_cache_using_resources ); + return; + } + + vg_strcat( &folder, "/preview.jpg" ); + vg_async_item *call = + vg_async_alloc( sizeof(struct async_preview_load_thread_data) ); + struct async_preview_load_thread_data *inf = call->payload; + + inf->reg = reg_preview; + + if( vg_strgood( &folder ) ){ + stbi_set_flip_vertically_on_load(1); + int x, y, nc; + inf->data = stbi_load( folder.buffer, &x, &y, &nc, 3 ); + + if( inf->data ){ + if( (x != WORKSHOP_PREVIEW_WIDTH) || (y != WORKSHOP_PREVIEW_HEIGHT) ){ + vg_error( "Resolution does not match framebuffer, so we can't" + " show it\n" ); + stbi_image_free( inf->data ); + inf->data = NULL; + } + } + + vg_async_dispatch( call, skateshop_async_preview_imageload ); + } +} + /* * op/subroutine: k_workshop_op_item_load * ----------------------------------------------------------------------------- @@ -84,6 +154,12 @@ static void skateshop_autostart_loading(void){ if( !vg_loader_availible() ) return; SDL_AtomicLock( &addon_system.sl_cache_using_resources ); + if( global_skateshop.reg_preview != global_skateshop.reg_loaded_preview ){ + SDL_AtomicUnlock( &addon_system.sl_cache_using_resources ); + vg_loader_start( skateshop_update_preview_image_thread, NULL ); + return; + } + for( u32 type=0; typepool, id ); if( entry->state == k_addon_cache_state_load_request ){ SDL_AtomicUnlock( &addon_system.sl_cache_using_resources ); - goto launch; + vg_loader_start( board_processview_thread, NULL ); + return; } } } SDL_AtomicUnlock( &addon_system.sl_cache_using_resources ); - return; -launch: - vg_loader_start( board_processview_thread, NULL ); } /* @@ -106,10 +180,30 @@ launch: * ----------------------------------------------------------------------------- */ +static void skateshop_init_async(void *_data,u32 size){ + glGenTextures( 1, &global_skateshop.tex_preview ); + glBindTexture( GL_TEXTURE_2D, global_skateshop.tex_preview ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, + WORKSHOP_PREVIEW_WIDTH, WORKSHOP_PREVIEW_HEIGHT, + 0, GL_RGB, GL_UNSIGNED_BYTE, NULL ); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR_MIPMAP_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); +} + /* * VG event init */ static void skateshop_init(void){ + vg_async_call( skateshop_init_async, NULL, 0 ); + vg_tex2d_replace_with_error( &global_skateshop.tex_preview_err ); + vg_async_stall(); + + skaterift.rt_textures[ k_skaterift_rt_workshop_preview ] = + global_skateshop.tex_preview_err; } static u16 skateshop_selected_cache_id(void){ @@ -264,8 +358,9 @@ static void ent_skateshop_preupdate( ent_skateshop *shop, int active ){ global_skateshop.helper_browse->greyed = !browseable; global_skateshop.helper_pick->greyed = !loadable; - int change = 0; + addon_reg *selected_world = NULL; + int change = 0; if( browseable ){ if( button_down( k_srbind_mleft ) ){ if( global_skateshop.selected_world_id > 0 ){ @@ -280,14 +375,20 @@ static void ent_skateshop_preupdate( ent_skateshop *shop, int active ){ change = 1; } } + + selected_world = get_addon_from_index( k_addon_type_world, + global_skateshop.selected_world_id, ADDON_REG_HIDDEN ); + + if( change || (global_skateshop.reg_preview == NULL) ){ + SDL_AtomicLock( &addon_system.sl_cache_using_resources ); + global_skateshop.reg_preview = selected_world; + SDL_AtomicUnlock( &addon_system.sl_cache_using_resources ); + } } if( loadable ){ if( button_down( k_srbind_maccept ) ){ - skaterift_change_world_start( - get_addon_from_index( k_addon_type_world, - global_skateshop.selected_world_id, - ADDON_REG_HIDDEN )); + skaterift_change_world_start( selected_world ); } } } diff --git a/ent_skateshop.h b/ent_skateshop.h index 81be2e8..5e9a0a8 100644 --- a/ent_skateshop.h +++ b/ent_skateshop.h @@ -34,8 +34,13 @@ struct{ render; struct gui_helper *helper_pick, *helper_browse; + + addon_reg *reg_preview, *reg_loaded_preview; + GLuint tex_preview, tex_preview_err; } -static global_skateshop={.render={.reg_id=0xffffffff,.world_reg=0xffffffff}}; +static global_skateshop={ + .render={.reg_id=0xffffffff,.world_reg=0xffffffff} +}; static void ent_skateshop_preupdate( ent_skateshop *shop, int active ); static void skateshop_render( ent_skateshop *shop ); diff --git a/maps_src/dev_hub/main.mdl b/maps_src/dev_hub/main.mdl index 6c422906a55ca4ab8c8bc350d2e0f017e359c993..e53ae013d3289987f43f29eeb60a4b8456dea482 100644 GIT binary patch delta 479 zcmXX?JxD@P6u#$a`ktk}YU%k9-q0Y}P}veC6c|NCS`CSd3B4lHq}S_@mKP1$63SU> z>1V6J=@CUkv^oY2j=HrpH53HVx#`FK?m2M2`<-*{fKKk$Os#FU8k$>T+`3kQTSGO$ zWv|H+Wwn}FI&vNU8O90-ph6oH6nmHjH8CPuq-x)%59@l%@GMyo4?q2&6TYw) z=m%`ub{52EfG1}hq-jO8q!dixz0?88Sq-HD-ti`!gCc&0b0Xn3CgnNU!F9PF8&MxO yCDJb|zTEzb^C*7{FoVNL8Wx>#WEx<@nToCfD7eK_pme(Yw9A1c+;(~3=iv`=J!(Aw diff --git a/skaterift.h b/skaterift.h index 96b9b90..9a1e0c5 100644 --- a/skaterift.h +++ b/skaterift.h @@ -12,6 +12,11 @@ #include "world.h" #include "addon.h" +enum skaterift_rt { + k_skaterift_rt_workshop_preview, + k_skaterift_rt_max +}; + struct{ enum async_operation{ k_async_op_none, @@ -56,6 +61,7 @@ struct{ activity; f64 last_autosave; + GLuint rt_textures[k_skaterift_rt_max]; } static skaterift = { .op = k_async_op_clientloading, .time_rate = 1.0f }; diff --git a/world_load.c b/world_load.c index 1b256a2..d7f4afb 100644 --- a/world_load.c +++ b/world_load.c @@ -177,7 +177,7 @@ static void skaterift_world_load_thread( void *_args ){ vg_strnull( &path, path_buf, 4096 ); assert( reg ); - addon_get_content_folder( reg, &path ); + addon_get_content_folder( reg, &path, 1 ); vg_str folder = path; if( !vg_strgood( &folder ) ) { diff --git a/world_render.c b/world_render.c index 0584415..3f87a12 100644 --- a/world_render.c +++ b/world_render.c @@ -12,6 +12,7 @@ #include "respawn.h" #include "ent_miniworld.h" #include "player_remote.h" +#include "ent_skateshop.h" static int ccmd_set_time( int argc, const char *argv[] ){ world_instance *world = world_current_instance(); @@ -278,18 +279,25 @@ void world_render_both_stages( world_instance *world, struct world_pass *pass ) glEnable( GL_CULL_FACE ); } +static GLuint world_get_texture( world_instance *world, u32 id ){ + if( id & 0x80000000 ) + return skaterift.rt_textures[id & ~0x80000000]; + else + return world->textures[ id ]; +} + static void bindpoint_diffuse_texture1( world_instance *world, - struct world_surface *mat ) - -{ + struct world_surface *mat ){ glActiveTexture( GL_TEXTURE1 ); - glBindTexture( GL_TEXTURE_2D, world->textures[ mat->info.tex_diffuse ] ); + glBindTexture( GL_TEXTURE_2D, + world_get_texture(world,mat->info.tex_diffuse) ); } static void bindpoint_diffuse1_and_cubemap10( world_instance *world, struct world_surface *mat ){ glActiveTexture( GL_TEXTURE1 ); - glBindTexture( GL_TEXTURE_2D, world->textures[ mat->info.tex_diffuse ] ); + glBindTexture( GL_TEXTURE_2D, + world_get_texture(world,mat->info.tex_diffuse) ); u32 cubemap_id = mat->info.tex_none0, cubemap_index = 0; @@ -645,7 +653,8 @@ static void bindpoint_terrain( world_instance *world, struct world_surface *mat ) { glActiveTexture( GL_TEXTURE1 ); - glBindTexture( GL_TEXTURE_2D, world->textures[ mat->info.tex_diffuse ] ); + glBindTexture( GL_TEXTURE_2D, + world_get_texture(world,mat->info.tex_diffuse) ); shader_scene_terrain_uSandColour( mat->info.colour ); shader_scene_terrain_uBlendOffset( mat->info.colour1 ); @@ -658,7 +667,8 @@ static void bindpoint_override( world_instance *world, } else{ glActiveTexture( GL_TEXTURE1 ); - glBindTexture( GL_TEXTURE_2D, world->textures[ mat->info.tex_diffuse ] ); + glBindTexture( GL_TEXTURE_2D, + world_get_texture(world,mat->info.tex_diffuse) ); shader_scene_override_uAlphatest(1); } } -- 2.25.1