added support for loading a preview version of the world. just reduced details etc
authorhgn <hgodden00@gmail.com>
Wed, 12 Feb 2025 23:42:35 +0000 (23:42 +0000)
committerhgn <hgodden00@gmail.com>
Wed, 12 Feb 2025 23:42:35 +0000 (23:42 +0000)
19 files changed:
build.c
content_skaterift/maps/sr002-local-dev_hub-cm-straw.qoi [new file with mode: 0644]
content_skaterift/maps/sr002-local-mp_mtzero-cm-straw.qoi [new file with mode: 0644]
shaders/scene_preview.fs [new file with mode: 0644]
src/client.c
src/menu.c
src/menu.h
src/player.c
src/save.c
src/skaterift.c
src/world.c
src/world.h
src/world_entity.c
src/world_gate.c
src/world_gen.c
src/world_load.c
src/world_load.h
src/world_render.c
src/world_render.h

diff --git a/build.c b/build.c
index e6797834ce5082b348c35d9eacafd55627ef0099..34245b57c3128e46af832817b84bab9bad0f6e3d 100644 (file)
--- a/build.c
+++ b/build.c
@@ -100,6 +100,7 @@ void build_shaders(void){
    _S( "scene_standard_alphatest",  "scene.vs", "scene_standard_alphatest.fs" );
    _S( "scene_foliage",             "scene_foliage.vs", "scene_foliage.fs" );
    _S( "scene_override",            "scene_override.vs", "scene_override.fs" );
+   _S( "scene_preview",             "scene_override.vs", "scene_preview.fs" );
    _S( "scene_fxglow",              "scene_fxglow.vs", "scene_fxglow.fs" );
    _S( "scene_vertex_blend",        "scene.vs", "scene_vertex_blend.fs" );
    _S( "scene_terrain",             "scene.vs", "scene_terrain.fs" );
diff --git a/content_skaterift/maps/sr002-local-dev_hub-cm-straw.qoi b/content_skaterift/maps/sr002-local-dev_hub-cm-straw.qoi
new file mode 100644 (file)
index 0000000..c441340
Binary files /dev/null and b/content_skaterift/maps/sr002-local-dev_hub-cm-straw.qoi differ
diff --git a/content_skaterift/maps/sr002-local-mp_mtzero-cm-straw.qoi b/content_skaterift/maps/sr002-local-mp_mtzero-cm-straw.qoi
new file mode 100644 (file)
index 0000000..2274a14
Binary files /dev/null and b/content_skaterift/maps/sr002-local-mp_mtzero-cm-straw.qoi differ
diff --git a/shaders/scene_preview.fs b/shaders/scene_preview.fs
new file mode 100644 (file)
index 0000000..0cc5ee0
--- /dev/null
@@ -0,0 +1,42 @@
+in vec2 aUv;
+in vec4 aNorm;
+in vec3 aCo;
+in vec3 aWorldCo;
+
+uniform bool uAlphatest;
+uniform vec4 uMapInfo; /* x: min, y: max, z: iso line amount */
+
+layout (location = 0) out vec4 oColour;
+
+#include "motion_vectors_fs.glsl"
+
+void main()
+{
+   vec2 ssuv = gl_FragCoord.xy;
+   vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), ssuv) );
+   float dither = fract( vDither.g / 71.0 ) - 0.5;
+
+   float dy0 = aCo.y - uMapInfo.x;
+   float dy1 = uMapInfo.y - aCo.y;
+
+   if( min(dy0,dy1)*0.5 + dither < 0.51 ) 
+      discard;
+
+   compute_motion_vectors();
+
+   vec3 vfrag = vec3(aUv.xy,0.0);
+   vec3 qnorm = aNorm.xyz;
+
+   qnorm = normalize(floor(aNorm.xyz*4.0)*0.25);
+   qnorm += vec3(0.001,0.0,0.0);
+
+   if( uAlphatest ){
+      //vec4 vSample = texture( uTexMain, aUv );
+      //if( vSample.a < 0.5 )
+      //  discard;
+   }
+   else{
+   }
+
+   oColour = vec4( vfrag, 1.0 );
+}
index 0896d890dfc10a5c666cec888e7d7380c66f01f8..60b09fe69c3bb064d89bcaf915daf3fbc1785285 100644 (file)
@@ -88,7 +88,7 @@ int main( int argc, char *argv[] )
 {
    network_set_host( "skaterift.com", NULL );
    vg_mem.use_libc_malloc = 0;
-   vg_set_mem_quota( 160*1024*1024 );
+   vg_set_mem_quota( 200*1024*1024 );
    vg_enter( argc, argv, "Voyager Game Engine" ); 
    return 0;
 }
index 6f8c48d47f0e30c084ca66e92f61c039f40675f8..b6fa1977078e4cb44f359387c557145e14db516d 100644 (file)
@@ -114,7 +114,7 @@ static bool menu_slider( ui_context *ctx,
 }
 
 static bool menu_button( ui_context *ctx,
-                         ui_rect inout_panel, bool select, const char *text )
+                         ui_rect inout_panel, bool select, bool clickable, const char *text )
 {
    ui_rect rect;
    menu_standard_widget( ctx, inout_panel, rect, 1 );
@@ -127,42 +127,50 @@ static bool menu_button( ui_context *ctx,
       {
          menu_decor_select( ctx, rect );
 
-         if( button_down( k_srbind_maccept ) )
+         if( clickable && button_down( k_srbind_maccept ) )
             state = k_ui_button_click;
       }
    }
    else
    {
-      state = ui_button_base( ctx, rect );
+      if( clickable )
+         state = ui_button_base( ctx, rect );
       select = 0;
    }
 
-   if( state == k_ui_button_click )
-   {
-      ui_fill( ctx, rect, GUI_COL_DARK );
-   }
-   else if( state == k_ui_button_holding_inside )
+   if( clickable )
    {
-      ui_fill( ctx, rect, GUI_COL_DARK );
+      if( state == k_ui_button_click )
+      {
+         ui_fill( ctx, rect, GUI_COL_DARK );
+      }
+      else if( state == k_ui_button_holding_inside )
+      {
+         ui_fill( ctx, rect, GUI_COL_DARK );
+      }
+      else if( state == k_ui_button_holding_outside )
+      {
+         ui_fill( ctx, rect, GUI_COL_DARK );
+         ui_outline( ctx, rect, 1, GUI_COL_CLICK, 0 );
+      }
+      else if( state == k_ui_button_hover )
+      {
+         ui_fill( ctx, rect, GUI_COL_ACTIVE );
+         ui_outline( ctx, rect, 1, GUI_COL_CLICK, 0 );
+      }
+      else 
+      {
+         ui_fill( ctx, rect, select? GUI_COL_ACTIVE: GUI_COL_NORM );
+         if( select )
+            ui_outline( ctx, rect, 1, GUI_COL_HI, 0 );
+      }
    }
-   else if( state == k_ui_button_holding_outside )
+   else
    {
       ui_fill( ctx, rect, GUI_COL_DARK );
-      ui_outline( ctx, rect, 1, GUI_COL_CLICK, 0 );
-   }
-   else if( state == k_ui_button_hover )
-   {
-      ui_fill( ctx, rect, GUI_COL_ACTIVE );
-      ui_outline( ctx, rect, 1, GUI_COL_CLICK, 0 );
-   }
-   else 
-   {
-      ui_fill( ctx, rect, select? GUI_COL_ACTIVE: GUI_COL_NORM );
-      if( select )
-         ui_outline( ctx, rect, 1, GUI_COL_HI, 0 );
    }
 
-   ui_text( ctx, rect, text, 1, k_ui_align_middle_center, 0 );
+   ui_text( ctx, rect, text, 1, k_ui_align_middle_center, clickable? 0: ui_colour(ctx,k_ui_bg) );
 
    if( state == k_ui_button_click )
    {
@@ -301,6 +309,44 @@ static void menu_link_modal( const char *url )
       menu.web_choice = 0;
 }
 
+static void menu_update_world_list(void)
+{
+   menu.world_list_total_count = addon_count( k_addon_type_world, ADDON_REG_HIDDEN );
+
+   if( menu.world_list_selected_index >= menu.world_list_total_count )
+      vg_fatal_error( "World list index out of range! (%d >= %d)\n",
+            menu.world_list_selected_index, menu.world_list_total_count );
+
+   u32 selected_world_index = menu.world_list_selected_index,
+       page_base = (selected_world_index / MENU_WORLD_COUNT) * MENU_WORLD_COUNT;
+
+   menu.world_list_display_count = 0;
+
+   for( u32 i=0; i<MENU_WORLD_COUNT; i ++ )
+   {
+      u32 world_index = page_base + i;
+
+      if( world_index >= menu.world_list_total_count )
+         menu.world_list_entries[i] = NULL;
+      else
+      {
+         addon_reg *reg = get_addon_from_index( k_addon_type_world, world_index, ADDON_REG_HIDDEN );
+         menu.world_list_entries[ menu.world_list_display_count ] = reg;
+
+         vg_msg msg;
+         vg_msg_init( &msg, reg->metadata, reg->metadata_len );
+
+         const char *name = vg_msg_getkvstr( &msg, "location" );
+
+         if( !name )
+            name = reg->alias.foldername;
+
+         menu.world_list_names[ menu.world_list_display_count ] = name;
+         menu.world_list_display_count ++;
+      }
+   }
+}
+
 void menu_gui( ui_context *ctx )
 {
    if( button_down( k_srbind_mopen ) )
@@ -390,19 +436,16 @@ void menu_gui( ui_context *ctx )
 
       i32 R = menu_nav( &menu.web_choice, mh, 2 );
 
-      if( menu_button( ctx, a, R==0, "Steam Overlay" ) )
+      if( menu_button( ctx, a, R==0, steam_ready, "Steam Overlay" ) )
       {
-         if( steam_ready )
-         {
-            ISteamFriends *hSteamFriends = SteamAPI_SteamFriends();
-            SteamAPI_ISteamFriends_ActivateGameOverlayToWebPage( hSteamFriends,
-                  menu.web_link,
-                  k_EActivateGameOverlayToWebPageMode_Default );
-            menu.web_link = NULL;
-         }
+         ISteamFriends *hSteamFriends = SteamAPI_SteamFriends();
+         SteamAPI_ISteamFriends_ActivateGameOverlayToWebPage( hSteamFriends,
+               menu.web_link,
+               k_EActivateGameOverlayToWebPageMode_Default );
+         menu.web_link = NULL;
       }
 
-      if( menu_button( ctx, b, R==1, "Web Browser" ) )
+      if( menu_button( ctx, b, R==1, 1, "Web Browser" ) )
       {
          char buf[512];
          vg_str str;
@@ -420,7 +463,7 @@ void menu_gui( ui_context *ctx )
          menu.web_link = NULL;
       }
       
-      if( menu_button( ctx, c, R==2, "No" ) || button_down( k_srbind_mback ) )
+      if( menu_button( ctx, c, R==2, 1, "No" ) || button_down( k_srbind_mback ) )
       {
          audio_lock();
          audio_oneshot( &audio_ui[3], 1.0f, 0.0f );
@@ -485,7 +528,7 @@ void menu_gui( ui_context *ctx )
 
       ui_rect end = { panel[0], panel[1] + panel[3] - 64, panel[2], 64 };
 
-      if( menu_button( ctx, end, 1, "Back" ) || button_down( k_srbind_mback ) )
+      if( menu_button( ctx, end, 1, 1, "Back" ) || button_down( k_srbind_mback ) )
       {
          menu.page = k_menu_page_main;
       }
@@ -520,7 +563,7 @@ void menu_gui( ui_context *ctx )
       ui_rect end = { panel[0], panel[1] + panel[3] - 100, panel[2], 100 };
       menu_checkbox( ctx, end, R == 2, 
                      "Don't show this again", &menu.skip_starter );
-      if( menu_button( ctx, end, R == 3, "OK" ) )
+      if( menu_button( ctx, end, R == 3, 1, "OK" ) )
       {
          menu.page = k_menu_page_main;
          skaterift.activity = k_skaterift_default;
@@ -555,14 +598,13 @@ void menu_gui( ui_context *ctx )
       ui_rect end = { panel[0], panel[1] + panel[3] - 48, panel[2], 48 }, a,b;
       ui_split_ratio( end, k_ui_axis_v, 0.5f, 2, a, b );
 
-      if( menu_button( ctx, a, R == 0, "Store Page" ) )
+      if( menu_button( ctx, a, R == 0, steam_ready, "Store Page" ) )
       {
-         if( steam_ready )
-            SteamAPI_ISteamFriends_ActivateGameOverlayToStore( 
-                  SteamAPI_SteamFriends(), 2103940, k_EOverlayToStoreFlag_None);
+         SteamAPI_ISteamFriends_ActivateGameOverlayToStore( 
+               SteamAPI_SteamFriends(), 2103940, k_EOverlayToStoreFlag_None);
       }
 
-      if( menu_button( ctx, b, R == 1, "Nah" ) || button_down( k_srbind_mback ) )
+      if( menu_button( ctx, b, R == 1, 1, "Nah" ) || button_down( k_srbind_mback ) )
       {
          audio_lock();
          audio_oneshot( &audio_ui[3], 1.0f, 0.0f );
@@ -573,6 +615,56 @@ void menu_gui( ui_context *ctx )
 
       goto menu_draw;
    }
+   else if( menu.page == k_menu_page_world_select )
+   {
+      ctx->font = &vgf_default_large;
+
+      ui_rect left_world_list = { 0, 0, 300, vg.window_y };
+      ui_fill( ctx, left_world_list, ui_opacity( GUI_COL_DARK, 0.35f ) );
+
+      ui_rect title;
+      ui_split( left_world_list, k_ui_axis_h, 28, 0, title, left_world_list );
+      ui_text( ctx, title, "Locations", 1, k_ui_align_middle_center, 0 );
+
+      i32 selected_world_index = menu.world_list_selected_index,
+          page = selected_world_index / MENU_WORLD_COUNT,
+          page_base = page * MENU_WORLD_COUNT,
+          max_page = (menu.world_list_total_count-1) / MENU_WORLD_COUNT;
+
+      i32 R = menu_nav( &menu.world_list_selected_index, mv, menu.world_list_total_count-1 );
+
+
+
+      if( menu_button( ctx, left_world_list, R == -999, page>0, "\x94" ) )
+         menu.world_list_selected_index = (page-1)*MENU_WORLD_COUNT;
+
+      for( u32 i=0; i<menu.world_list_display_count; i ++ )
+      {
+         addon_reg *reg = menu.world_list_entries[i];
+         if( menu_button( ctx, left_world_list, R == (page_base + i), 1, menu.world_list_names[i] ) )
+         {
+         }
+      }
+      
+      if( menu_button( ctx, left_world_list, R == -999, page<max_page, "\x96" ) )
+         menu.world_list_selected_index = (page+1)*MENU_WORLD_COUNT;
+
+      if( menu.world_list_selected_index < page_base || 
+          menu.world_list_selected_index >= (page_base+MENU_WORLD_COUNT) )
+      {
+         menu_update_world_list();
+      }
+
+
+
+
+      if( /*menu_button( ctx, end, 1, 1, "Back" ) ||*/ button_down( k_srbind_mback ) )
+      {
+         menu.page = k_menu_page_main;
+      }
+
+      goto menu_draw;
+   }
 
    /*                              TOP BAR 
     * -------------------------------------------------------------------*/
@@ -839,19 +931,25 @@ void menu_gui( ui_context *ctx )
       {
          i32 R = menu_nav( &menu.main_row, mv, 2 );
 
-         if( menu_button( ctx, list, R == 0, "Resume" ) )
+         if( menu_button( ctx, list, R == 0, 1, "Resume" ) )
          {
             skaterift.activity = k_skaterift_default;
             return;
          }
 
-         if( menu_button( ctx, list, R == 1, "Credits" ) )
+         if( menu_button( ctx, list, R == 1, 1, "Change World" ) )
+         {
+            menu.page = k_menu_page_world_select;
+            menu_update_world_list();
+         }
+
+         if( menu_button( ctx, list, R == 2, 1, "Credits" ) )
          {
             menu.page = k_menu_page_credits;
          }
 
          ui_rect end = { list[0], list[1]+list[3]-64, list[2], 72 };
-         if( menu_button( ctx, end, R == 2, "Quit Game" ) )
+         if( menu_button( ctx, end, R == 3, 1, "Quit Game" ) )
          {
             vg.window_should_close = 1;
          }
@@ -889,7 +987,7 @@ void menu_gui( ui_context *ctx )
          ui_rect end = { list[0], list[1]+list[3]-64, list[2], 72 };
          ctx->font = &vgf_default_small;
          menu_heading( ctx, end, "Advanced", 0 );
-         if( menu_button( ctx, end, R == 8, "Open Engine Settings" ) )
+         if( menu_button( ctx, end, R == 8, 1, "Open Engine Settings" ) )
          {
             vg_settings_open();
          }
@@ -949,7 +1047,7 @@ void menu_gui( ui_context *ctx )
             vs[2].co[1] = vs[0].co[1] + 84 + vgf_default_large.sy*11 + 16;
             vs[3].co[1] = vs[2].co[1];
          }
-         if( menu_button( ctx, list, R == 0, "Where to go" ) ) 
+         if( menu_button( ctx, list, R == 0, 1, "Where to go" ) ) 
             menu.guide_sel = 1;
 
          if( menu.guide_sel == 3 )
@@ -976,11 +1074,11 @@ void menu_gui( ui_context *ctx )
             vs[2].co[1] = vs[0].co[1] + 84 + vgf_default_large.sy*7 + 16;
             vs[3].co[1] = vs[2].co[1];
          }
-         if( menu_button( ctx, list, R == 1, "Playing Online" ) ) 
+         if( menu_button( ctx, list, R == 1, 1, "Playing Online" ) ) 
             menu.guide_sel = 3;
 
          menu_heading( ctx, list, "Controls", 0 );
-         if( menu_button( ctx, list, R == 2, "Skating \xb2" ) )
+         if( menu_button( ctx, list, R == 2, 1, "Skating \xb2" ) )
          {
             menu.guide_sel = 0;
             menu_link_modal( 
@@ -988,7 +1086,7 @@ void menu_gui( ui_context *ctx )
          }
          //if( menu.guide_sel == 0 || menu.guide_sel > 3 ) menu_try_find_cam( 3 );
 
-         if( menu_button( ctx, list, R == 3, "Tricks \xb2" ) )
+         if( menu_button( ctx, list, R == 3, 1, "Tricks \xb2" ) )
          {
             menu.guide_sel = 0;
             menu_link_modal( 
@@ -996,19 +1094,19 @@ void menu_gui( ui_context *ctx )
          }
 
          menu_heading( ctx, list, "Workshop", 0 );
-         if( menu_button( ctx, list, R == 4, "Create a Board \xb2" ) )
+         if( menu_button( ctx, list, R == 4, 1, "Create a Board \xb2" ) )
          {
             menu.guide_sel = 0;
             menu_link_modal( 
                   "https://skaterift.com/index.php?page=workshop_board" );
          }
-         if( menu_button( ctx, list, R == 5, "Create a World \xb2" ) )
+         if( menu_button( ctx, list, R == 5, 1, "Create a World \xb2" ) )
          {
             menu.guide_sel = 0;
             menu_link_modal( 
                   "https://skaterift.com/index.php?page=workshop_world" );
          }
-         if( menu_button( ctx, list, R == 6, "Create a Playermodel \xb2" ) )
+         if( menu_button( ctx, list, R == 6, 1, "Create a Playermodel \xb2" ) )
          {
             menu.guide_sel = 0;
             menu_link_modal( 
index 5a6dbc452f41f731c2f66c9f8b6f3f9e96334185..be5cbbe6daeeef8f71b3a7a7839e1b7b5eb753a8 100644 (file)
@@ -1,6 +1,7 @@
 #pragma once
 
 #define MENU_STACK_SIZE 8
+#define MENU_WORLD_COUNT 4
 
 #include "vg/vg_engine.h"
 #include "entity.h"
@@ -13,6 +14,7 @@ enum menu_page
    k_menu_page_main,
    k_menu_page_credits,
    k_menu_page_help,
+   k_menu_page_world_select
 };
 
 enum menu_main_subpage
@@ -46,6 +48,13 @@ struct global_menu
    i32 web_choice;
 
    GLuint prem_tex;
+
+   addon_reg *world_list_entries[ MENU_WORLD_COUNT ];
+   const char *world_list_names[ MENU_WORLD_COUNT ];
+
+   i32 world_list_display_count, 
+       world_list_total_count,
+       world_list_selected_index;
 }
 extern menu;
 
index 7daea1151e873261a6b65ad7fcd08f084ced11cb..473c14715c47221dfe5d1950f396c33b65662014 100644 (file)
@@ -210,7 +210,7 @@ void player__pass_gate( u32 id )
                   k_strncpy_overflow_fatal );
 
       addon_reg *reg = get_addon_from_index( k_addon_type_world, gate->addon_reg, 0 );
-      skaterift_switch_world_start( reg );
+      skaterift_load_world_start( reg, 0 );
       return;
    }
    else
index fe8c0b6c32014910734979f45212c1cce962414d..432f3418d42a530b27895d8d16c8a52c9e334018 100644 (file)
@@ -244,16 +244,14 @@ void skaterift_load_mainsave(void)
          reg_id = addon_match( &q );
          if( reg_id != 0xffffffff )
          {
-            _world.switch_to_addon = 
-               get_addon_from_index( k_addon_type_world, reg_id, 0 );
+            _world.loader_reg = get_addon_from_index( k_addon_type_world, reg_id, 0 );
          }
          else
          {
             char buf[ADDON_UID_MAX];
             addon_alias_uid( &q, buf );
 
-            vg_error( "While loading player location from save file, "
-                      "couldn't find addon '%s'\n", buf );
+            vg_error( "While loading player location from save file, couldn't find addon '%s'\n", buf );
          }
       }
    }
@@ -272,8 +270,7 @@ void skaterift_load_mainsave(void)
    else
    {
       vg_info( "Starting new story!\n" );
-      _world.switch_to_addon = 
-         addon_mount_local_addon( "maps/dev_heaven", k_addon_type_world, ".mdl" );
+      _world.loader_reg = addon_mount_local_addon( "maps/dev_heaven", k_addon_type_world, ".mdl" );
       _skaterift_script_hook( 2, (const char *[]){ "unlock", "intro" } );
    }
 }
index f31e6044aaa3e0b3b7fb7158c9da2532de04681d..590282bcd61c0ae9cdc219c5672ef70bc0e1efea 100644 (file)
@@ -69,20 +69,19 @@ static addon_reg *skaterift_mount_world_unloadable( const char *path, u32 ext )
 {
    addon_reg *reg = addon_mount_local_addon( path, k_addon_type_world, ".mdl" );
    if( !reg ) vg_fatal_error( "world not found\n" );
-   reg->flags |= (ADDON_REG_HIDDEN | ext);
+   reg->flags |= (ext);
    return reg;
 }
 
 static void skaterift_load_world_content(void)
 {
    /* hub world */
-   _world.default_hub_addon = 
-      skaterift_mount_world_unloadable( "maps/dev_hub", 0 );
-   skaterift_mount_world_unloadable( "maps/dev_heaven", 0 );
+   _world.default_hub_addon = skaterift_mount_world_unloadable( "maps/dev_hub", 0 );
+   skaterift_mount_world_unloadable( "maps/dev_heaven", ADDON_REG_HIDDEN );
    skaterift_mount_world_unloadable( "maps/mp_spawn", ADDON_REG_CITY|ADDON_REG_PREMIUM );
    skaterift_mount_world_unloadable( "maps/mp_mtzero", ADDON_REG_MTZERO|ADDON_REG_PREMIUM );
    skaterift_mount_world_unloadable( "maps/dev_tutorial", 0 );
-   skaterift_mount_world_unloadable( "maps/dev_flatworld", 0 );
+   skaterift_mount_world_unloadable( "maps/dev_flatworld", ADDON_REG_HIDDEN );
    skaterift_mount_world_unloadable( "maps/mp_line1", ADDON_REG_PREMIUM );
 }
 
@@ -93,11 +92,9 @@ static void skaterift_load_player_content(void)
 
    player_load_animation_reference( "models/ch_none.mdl" );
    player_load_animations( "metascenes/skater.ms" );
-   player_model_load( &localplayer.fallback_model, "models/ch_none.mdl",
-                       vg_mem.rtmemory );
+   player_model_load( &localplayer.fallback_model, "models/ch_none.mdl", vg_mem.rtmemory );
    player__bind();
-   player_board_load( &localplayer.fallback_board, "models/board_none.mdl",
-                      vg_mem.rtmemory );
+   player_board_load( &localplayer.fallback_board, "models/board_none.mdl", vg_mem.rtmemory );
 }
 
 void game_load(void)
@@ -106,7 +103,7 @@ void game_load(void)
 
    vg_loader_set_user_information( "Initializing subsystems" );
 
-   vg_console_reg_cmd( "switch_world", skaterift_switch_world_command, NULL );
+   vg_console_reg_cmd( "load_world", skaterift_load_world_command, NULL );
    vg_console_reg_var( "immobile", &localplayer.immobile, k_var_dtype_i32, 0 );
    vg_loader_step( menu_init, NULL );
    vg_loader_step( control_overlay_init, NULL );
@@ -146,10 +143,14 @@ void game_load(void)
    vg_loader_set_user_information( "Loading savedata" );
    skaterift_load_mainsave();
 
-   if( !_world.switch_to_addon )
+   _world.loader_instance = &_world.main;
+   _world.loader_preview_mode = 0;
+   _world.loader_heap = _world.heap; 
+
+   if( !_world.loader_reg )
    {
       vg_warn( "Falling back to default hub world...\n" );
-      _world.switch_to_addon = _world.default_hub_addon;
+      _world.loader_reg = _world.default_hub_addon;
    }
    world_switcher_thread( NULL );
 
@@ -298,6 +299,9 @@ static void render_player_transparent(void)
    player__render( &small_cam );
 }
 
+
+
+
 static void render_scene(void)
 {
    /* Draw world */
@@ -334,8 +338,13 @@ static void render_scene(void)
       render_world_routes( world, world, identity, &g_render.cam, 0, 1 );
       return;
    }
-
-   render_world( &_world.main, &g_render.cam, 0, 0, 1, 1 );
+   
+   if( _world.preview_instance.complete )
+   {
+      render_world_preview();
+   }
+   else
+      render_world( &_world.main, &g_render.cam, 0, 0, 1, 1 );
 
    particle_system_update( &particles_grind, vg.time_delta );
    //particle_system_debug( &particles_grind );
index 2600113cfb8a095e9e03d7cce64b8c4fff4b06d9..382a9ebd43ec2988760a97692aea75fd3b792568 100644 (file)
@@ -23,8 +23,10 @@ void world_init(void)
 
    /* Allocate dynamic world memory arena */
    u32 max_size = 76*1024*1024;
-   _world.heap = vg_create_linear_allocator( vg_mem.rtmemory, max_size,
-                                                   VG_MEMORY_SYSTEM );
+   _world.heap = vg_create_linear_allocator( vg_mem.rtmemory, max_size, VG_MEMORY_SYSTEM );
+
+   max_size = 32*1024*1024;
+   _world.preview_heap = vg_create_linear_allocator( vg_mem.rtmemory, max_size, VG_MEMORY_SYSTEM );
 }
 
 void skaterift_world_get_save_path( addon_reg *world_reg, char buf[128] )
index 7cd280f86dfff19f70c8945fe91910c487d26691..89be65e7a9b4d1cc2ad170298aa5103fe034619d 100644 (file)
@@ -58,6 +58,8 @@ static i32   k_debug_light_indices   = 0,
 
 struct world_instance 
 {
+   bool complete;
+
    addon_reg *addon;
    void *heap;
 
@@ -228,7 +230,7 @@ struct world_static
     * Allocated as system memory
     * --------------------------------------------------------------------------
     */
-   void *heap;
+   void *heap, *preview_heap;
 
    u32 current_run_version;
    double time, rewind_from, rewind_to;
@@ -236,8 +238,8 @@ struct world_static
    u32 active_trigger_volumes[8];
    u32 active_trigger_volume_count;
 
-   world_instance main;
-   addon_reg *default_hub_addon, *switch_to_addon;
+   world_instance main, preview_instance;
+   addon_reg *default_hub_addon;
 
    addon_reg *previous_world_addon;
    char nonlocal_destination_key[32];
@@ -255,6 +257,11 @@ struct world_static
    }
    loader_state;
 
+   addon_reg *loader_reg;
+   world_instance *loader_instance;
+   void *loader_heap;
+   bool loader_preview_mode;
+
    enum world_event
    {
       k_world_event_none = 0,
@@ -271,16 +278,9 @@ struct world_static
 }
 extern _world;
 
-struct world_load_args 
-{
-   addon_reg *reg;
-   world_instance *instance;
-   void *heap;
-};
-
 void world_init(void);
 
-void skaterift_world_load_thread( void *_args );
+void skaterift_world_load_thread( void *_ );
 void world_update( world_instance *world, v3f pos );
 
 bool world_set_event( enum world_event activity );
index 025126a167eaac869efa3afe69691f11f84a3b86..3c5eed218639bec54eecf90fac23e6e70a32028a 100644 (file)
@@ -319,9 +319,9 @@ void world_gen_entities_init( world_instance *world )
          world->entity_list[index ++] = mdl_entity_id( type, j );
    }
 
-   world->entity_bh = bh_create( world->heap, &bh_system_entity_list, world,
-                                 indexed_count, 2 );
+   world->entity_bh = bh_create( world->heap, &bh_system_entity_list, world, indexed_count, 2 );
 
+   /* FIXME: This should be scene geometry instead?????????? */
    world->tar_min = world->entity_bh->nodes[0].bbx[0][1];
    world->tar_max = world->entity_bh->nodes[0].bbx[1][1] + 20.0f;
 
index adf0bd2b3145a6cccd38a95ba94f49f6974a7b5d..f8fb4fbd1094285df5420cf1727340076a6f4d83 100644 (file)
@@ -326,6 +326,7 @@ void nonlocal_gate_cubemap_path( addon_reg *world_addon, const char *gate_key, c
 
    vg_str path_str;
    vg_strnull( &path_str, path, 256 );
+   vg_strcat( &path_str, "maps/" );
    vg_strcat( &path_str, id );
    vg_strcat( &path_str, "-cm-" );
    vg_strcat( &path_str, gate_key );
index 30ee158992bc0fb2c965e1c0cc4e17f99e06ea47..cd1e5709e9835f38a66237739b44d96165974952 100644 (file)
@@ -230,7 +230,8 @@ void world_gen_generate_meshes( world_instance *world )
 
    vg_info( "Generating collidable geometry\n" );
    
-   for( u32 i=0; i<world->surface_count; i++ ){
+   for( u32 i=0; i<world->surface_count; i++ )
+   {
       struct world_surface *surf = &world->surfaces[ i ];
 
       if( surf->info.flags & k_material_flag_collision )
@@ -267,8 +268,12 @@ void world_gen_generate_meshes( world_instance *world )
 
    /* need send off the memory to the gpu before we can create the bvh. */
    vg_async_stall();
-   vg_info( "creating bvh\n" );
-   world->geo_bh = scene_bh_create( world->heap, &world->scene_geo );
+
+   if( !_world.loader_preview_mode )
+   {
+      vg_info( "creating bvh\n" );
+      world->geo_bh = scene_bh_create( world->heap, &world->scene_geo );
+   }
 
    /*
     * Generate scene: non-collidable geometry
@@ -280,27 +285,33 @@ void world_gen_generate_meshes( world_instance *world )
                                             &world->mesh_no_collide,
                                             250000, 500000 );
 
-   for( u32 i=0; i<world->surface_count; i++ ){
+   for( u32 i=0; i<world->surface_count; i++ )
+   {
       struct world_surface *surf = &world->surfaces[ i ];
 
-      if( !(surf->info.flags & k_material_flag_collision) ){
-         world_add_all_if_material( midentity, 
-                                    &world->scene_no_collide, &world->meta, i );
-      }
+      if( !(surf->info.flags & k_material_flag_collision) )
+         world_add_all_if_material( midentity, &world->scene_no_collide, &world->meta, i );
 
-      if( surf->info.flags & k_material_flag_grow_grass ){
-         world_apply_procedural_foliage( world, &world->scene_no_collide, 
-                                         surf );
+      if( !_world.loader_preview_mode )
+      {
+         if( surf->info.flags & k_material_flag_grow_grass )
+            world_apply_procedural_foliage( world, &world->scene_no_collide, surf );
       }
 
       scene_copy_slice( &world->scene_no_collide, &surf->sm_no_collide );
    }
 
+   if( _world.loader_preview_mode )
+      goto IL_UPLOAD;
+
    /* unpack traffic models.. TODO: should we just put all these submeshes in a
     * dynamic models list? and then the actual entitities point to the 
     * models. we only have 2 types at the moment which need dynamic models but
     * would make sense to do this when/if we have more.
+    *
+    * update to self: there were more than 2 and we never gave a shit anyway.
     */
+
    for( u32 i=0; i<af_arrcount( &world->ent_traffic ); i++ )
    {
       ent_traffic *vehc = af_arritm( &world->ent_traffic, i );
@@ -362,11 +373,13 @@ void world_gen_generate_meshes( world_instance *world )
       }
    }
 
+IL_UPLOAD:
    vg_async_dispatch( call, async_scene_upload );
 }
 
 /* signed distance function for cone */
-static f32 fsd_cone_infinite( v3f p, v2f c ){
+static f32 fsd_cone_infinite( v3f p, v2f c )
+{
    v2f q = { v2_length( (v2f){ p[0], p[2] } ), -p[1] };
    float s = vg_maxf( 0.0f, v2_dot( q, c ) );
 
@@ -718,38 +731,40 @@ void async_world_postprocess( void *payload, u32 _size )
 /* Loads textures from the pack file */
 void world_gen_load_surfaces( world_instance *world )
 {
-   vg_info( "Loading textures\n" );
-   world->texture_count = 0;
-
-   world->texture_count = world->meta.texture_count+1;
-   world->textures = vg_linear_alloc( world->heap,
-                              vg_align8(sizeof(GLuint)*world->texture_count) );
-   world->textures[0] = vg.tex_missing;
-
-   for( u32 i=0; i<world->meta.texture_count; i++ )
+   if( _world.loader_preview_mode )
+   {
+      world->texture_count = 0;
+   }
+   else
    {
-      mdl_texture *tex = &world->meta.textures[ i ];
+      vg_info( "Loading textures\n" );
+      world->texture_count = world->meta.texture_count+1;
+      world->textures = vg_linear_alloc( world->heap, vg_align8(sizeof(GLuint)*world->texture_count) );
+      world->textures[0] = vg.tex_missing;
 
-      if( !tex->file.pack_size )
+      for( u32 i=0; i<world->meta.texture_count; i++ )
       {
-         vg_fatal_error( "World models must have packed textures!" );
-      }
+         mdl_texture *tex = &world->meta.textures[ i ];
 
-      vg_linear_clear( vg_mem.scratch );
-      void *src_data = vg_linear_alloc( vg_mem.scratch, 
-                                        tex->file.pack_size );
-      mdl_fread_pack_file( &world->meta, &tex->file, src_data );
+         if( !tex->file.pack_size )
+         {
+            vg_fatal_error( "World models must have packed textures!" );
+         }
 
-      vg_tex2d_load_qoi_async( src_data, tex->file.pack_size,
-                               VG_TEX2D_NEAREST|VG_TEX2D_REPEAT,
-                               &world->textures[i+1] );
+         vg_linear_clear( vg_mem.scratch );
+         void *src_data = vg_linear_alloc( vg_mem.scratch, tex->file.pack_size );
+         mdl_fread_pack_file( &world->meta, &tex->file, src_data );
+
+         vg_tex2d_load_qoi_async( src_data, tex->file.pack_size,
+                                  VG_TEX2D_NEAREST|VG_TEX2D_REPEAT,
+                                  &world->textures[i+1] );
+      }
    }
 
    vg_info( "Loading materials\n" );
 
    world->surface_count = world->meta.material_count+1;
-   world->surfaces = vg_linear_alloc( world->heap,
-               vg_align8(sizeof(struct world_surface)*world->surface_count) );
+   world->surfaces = vg_linear_alloc( world->heap, vg_align8(sizeof(struct world_surface)*world->surface_count) );
 
    /* error material */
    struct world_surface *errmat = &world->surfaces[0];
@@ -767,8 +782,7 @@ void world_gen_load_surfaces( world_instance *world )
          world->ub_lighting.g_water_fog = props->fog_scale;
       }
 
-      if( surf->info.shader == k_shader_standard_cutout ||
-          surf->info.shader == k_shader_foliage )
+      if( surf->info.shader == k_shader_standard_cutout || surf->info.shader == k_shader_foliage )
       {
          struct shader_props_standard *props = surf->info.props.compiled;
          surf->alpha_tex = props->tex_diffuse;
index b75a80db620afe3c838db9ee8d1ed0842467ecd9..ba69fcce786e3200cb6f3b9bd974bb296aa83f16 100644 (file)
@@ -14,8 +14,7 @@
 /* 
  * load the .mdl file located in path as a world instance
  */
-static void world_instance_load_mdl( world_instance *world, const char *path,
-                                     void *heap )
+static void world_instance_load_mdl( world_instance *world, const char *path, void *heap )
 {
    vg_loader_set_user_information( "Loading world data" );
 
@@ -31,49 +30,52 @@ static void world_instance_load_mdl( world_instance *world, const char *path,
    mdl_load_metadata_block( meta, world->heap );
    mdl_load_mesh_block( meta, world->heap );
 
-   vg_info( "%u\n", sizeof(ent_cubemap) );
+   bool load_all = !_world.loader_preview_mode;
 
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_gate,      ent_gate,       heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_camera,    ent_camera,     heap );
-
-#if (MDL_VERSION_MIN <= 107)
-   if( meta->version <= 107 )
+   if( load_all )
    {
-      array_file_ptr legacy_cameras;
-      af_load_array( af, &legacy_cameras, "ent_camera",
-            vg_mem.scratch, sizeof(struct ent_camera_v107) );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_gate,      ent_gate,       heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_camera,    ent_camera,     heap );
 
-      for( u32 i=0; i<af_arrcount(&legacy_cameras); i ++ )
+#if (MDL_VERSION_MIN <= 107)
+      if( meta->version <= 107 )
       {
-         fix_ent_camera_v107( af_arritm( &legacy_cameras, i ), 
-                              af_arritm( &world->ent_camera, i ) );
+         array_file_ptr legacy_cameras;
+         af_load_array( af, &legacy_cameras, "ent_camera",
+               vg_mem.scratch, sizeof(struct ent_camera_v107) );
+
+         for( u32 i=0; i<af_arrcount(&legacy_cameras); i ++ )
+         {
+            fix_ent_camera_v107( af_arritm( &legacy_cameras, i ), 
+                                 af_arritm( &world->ent_camera, i ) );
+         }
       }
-   }
 #endif
 
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_spawn,     ent_spawn,      heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_light,     ent_light,      heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_route_node,ent_route_node, heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_path_index,ent_path_index, heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_checkpoint,ent_checkpoint, heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_route,     ent_route,      heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_water,     ent_water,      heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_audio_clip,ent_audio_clip, heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_audio,     ent_audio,      heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_volume,    ent_volume,     heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_traffic,   ent_traffic,    heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_marker,    ent_marker,     heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_skateshop, ent_skateshop,  heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_swspreview,ent_swspreview, heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_ccmd,      ent_ccmd,       heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_objective, ent_objective,  heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_challenge, ent_challenge,  heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_relay,     ent_relay,      heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_cubemap,   ent_cubemap,    heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_miniworld, ent_miniworld,  heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_prop,      ent_prop,       heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_region,    ent_region,     heap );
-   AF_LOAD_ARRAY_STRUCT( af, &world->ent_glider,    ent_glider,     heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_spawn,     ent_spawn,      heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_light,     ent_light,      heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_route_node,ent_route_node, heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_path_index,ent_path_index, heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_checkpoint,ent_checkpoint, heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_route,     ent_route,      heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_water,     ent_water,      heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_audio_clip,ent_audio_clip, heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_audio,     ent_audio,      heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_volume,    ent_volume,     heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_traffic,   ent_traffic,    heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_marker,    ent_marker,     heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_skateshop, ent_skateshop,  heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_swspreview,ent_swspreview, heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_ccmd,      ent_ccmd,       heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_objective, ent_objective,  heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_challenge, ent_challenge,  heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_relay,     ent_relay,      heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_cubemap,   ent_cubemap,    heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_miniworld, ent_miniworld,  heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_prop,      ent_prop,       heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_region,    ent_region,     heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_glider,    ent_glider,     heap );
+   }
 
    array_file_ptr infos;
    AF_LOAD_ARRAY_STRUCT( af, &infos, ent_worldinfo, vg_mem.scratch );
@@ -103,8 +105,10 @@ static void world_instance_load_mdl( world_instance *world, const char *path,
       world->info.flags = 0;
    }
 
-   world->events = vg_linear_alloc( heap, 
-               af_arrcount(&world->ent_challenge)*sizeof(struct event_info) );
+   if( load_all )
+   {
+      world->events = vg_linear_alloc( heap, af_arrcount(&world->ent_challenge)*sizeof(struct event_info) );
+   }
 
    vg_loader_set_user_information( "Compiling world details" );
 
@@ -116,17 +120,28 @@ static void world_instance_load_mdl( world_instance *world, const char *path,
    u64 t4 = SDL_GetPerformanceCounter();
    world_gen_load_surfaces( world );
    u64 t5 = SDL_GetPerformanceCounter();
-   world_gen_routes_ent_init( world );
-   world_gen_entities_init( world );
+
+   if( load_all )
+   {
+      world_gen_routes_ent_init( world );
+      world_gen_entities_init( world );
+   }
+
    u64 t6 = SDL_GetPerformanceCounter();
    
    /* main bulk */
    u64 t0 = SDL_GetPerformanceCounter();
    world_gen_generate_meshes( world );
    u64 t1 = SDL_GetPerformanceCounter();
-   world_gen_routes_generate( world );
+
+   if( load_all )
+      world_gen_routes_generate( world );
+
    u64 t2 = SDL_GetPerformanceCounter();
-   world_gen_compute_light_indices( world );
+
+   if( load_all )
+      world_gen_compute_light_indices( world );
+
    u64 t3 = SDL_GetPerformanceCounter();
    mdl_close( meta );
 
@@ -147,24 +162,27 @@ static void world_instance_load_mdl( world_instance *world, const char *path,
                ftime_mesh, ftime_route, ftime_ind, ftime_tex, ftime_ent );
 
    /* allocate leaderboard buffers */
-   u32 bs = af_arrcount(&world->ent_route)*sizeof(struct leaderboard_cache);
-   world->leaderboard_cache = vg_linear_alloc( heap, bs );
-
-   for( u32 i=0; i<af_arrcount( &world->ent_route ); i ++ )
+   if( load_all )
    {
-      struct leaderboard_cache *board = &world->leaderboard_cache[i];
-      board->data = vg_linear_alloc( heap, NETWORK_REQUEST_MAX );
-      board->status = k_request_status_client_error;
-      board->cache_time = 0.0;
-      board->data_len = 0;
-   }
+      u32 bs = af_arrcount(&world->ent_route)*sizeof(struct leaderboard_cache);
+      world->leaderboard_cache = vg_linear_alloc( heap, bs );
 
-   world->routes_ui = vg_linear_alloc( heap, 
-         sizeof(struct route_ui)*af_arrcount(&world->ent_route) );
+      for( u32 i=0; i<af_arrcount( &world->ent_route ); i ++ )
+      {
+         struct leaderboard_cache *board = &world->leaderboard_cache[i];
+         board->data = vg_linear_alloc( heap, NETWORK_REQUEST_MAX );
+         board->status = k_request_status_client_error;
+         board->cache_time = 0.0;
+         board->data_len = 0;
+      }
 
-   vg_loader_set_user_information( "Postprocessing world" );
-   vg_async_call( async_world_postprocess, world, 0 );
-   vg_async_stall();
+      world->routes_ui = vg_linear_alloc( heap, 
+            sizeof(struct route_ui)*af_arrcount(&world->ent_route) );
+
+      vg_loader_set_user_information( "Postprocessing world" );
+      vg_async_call( async_world_postprocess, world, 0 );
+      vg_async_stall();
+   }
 
    vg_loader_set_user_information( NULL );
 }
@@ -172,24 +190,25 @@ static void world_instance_load_mdl( world_instance *world, const char *path,
 static void async_world_loader_done( void *payload, u32 size )
 {
    _world.loader_state = k_world_loader_done;
+   _world.loader_instance->complete = 1;
 }
 
-void skaterift_world_load_thread( void *_args )
+void skaterift_world_load_thread( void *_ )
 {
    vg_loader_set_user_information( "Scanning world directory" );
 
-   struct world_load_args args = *((struct world_load_args *)_args);
-   args.instance->addon = args.reg;
+   addon_reg *reg = _world.loader_reg;
+   _world.loader_instance->addon = reg;
 
    char uid[ADDON_UID_MAX];
-   addon_alias_uid( &args.reg->alias, uid );
+   addon_alias_uid( &_world.loader_reg->alias, uid );
    vg_info( "LOAD WORLD %s @%d\n", uid );
 
    char path_buf[4096];
    vg_str path;
    vg_strnull( &path, path_buf, 4096 );
 
-   addon_get_content_folder( args.reg, &path, 1 );
+   addon_get_content_folder( reg, &path, 1 );
 
    vg_str folder = path;
    if( !vg_strgood( &folder ) ) 
@@ -263,7 +282,7 @@ void skaterift_world_load_thread( void *_args )
       vg_fatal_error( "No .mdl files found in the map folder.\n" );
    }
 
-   world_instance_load_mdl( args.instance, mdl_path, args.heap );
+   world_instance_load_mdl( _world.loader_instance, mdl_path, _world.loader_heap );
 
    vg_async_call( async_world_loader_done, NULL, 0 );
    vg_async_stall();
@@ -312,15 +331,13 @@ void async_start_player_from_worldsave( void *payload, u32 size )
    }
 }
 
-void load_player_from_world_savedata_thread( void *_args )
+void load_player_from_world_savedata_thread( void *_ )
 {
-   struct world_load_args *args = _args;
-
    vg_async_item *call = vg_async_alloc( sizeof(struct world_savedata_thread_data) );
    struct world_savedata_thread_data *data = call->payload;
 
-   data->instance = args->instance;
-   skaterift_world_get_save_path( args->reg, data->save.path );
+   data->instance = _world.loader_instance;
+   skaterift_world_get_save_path( _world.loader_reg, data->save.path );
    savedata_file_read( &data->save );
 
    vg_async_dispatch( call, async_start_player_from_worldsave );
@@ -329,31 +346,29 @@ void load_player_from_world_savedata_thread( void *_args )
 
 void async_world_switcher_done( void *payload, u32 size )
 {
-   _world.switch_to_addon = NULL;
-   g_client.unreadyness --;
+   _world.loader_reg = NULL;
+
+   if( !_world.loader_preview_mode )
+      g_client.unreadyness --;
 }
 
 void world_switcher_thread( void *_ )
 {
-   struct world_load_args args = 
-   {
-      .reg = _world.switch_to_addon,
-      .instance = &_world.main,
-      .heap = _world.heap
-   };
-
-   skaterift_world_load_thread( &args );
+   skaterift_world_load_thread( NULL );
    vg_async_stall();
 
-   load_player_from_world_savedata_thread( &args );
-   vg_async_stall();
+   if( !_world.loader_preview_mode )
+   {
+      load_player_from_world_savedata_thread( NULL );
+      vg_async_stall();
+   }
 
    vg_async_call( async_world_switcher_done, NULL, 0 );
 }
 
 void world_switcher_update(void)
 {
-   if( !_world.switch_to_addon )
+   if( !_world.loader_reg )
       return;
 
    if( _world.loader_state == k_world_loader_saving_current )
@@ -389,6 +404,7 @@ void world_switcher_update(void)
       
       _skaterift_script_unlink_all_challenges();
       world_instance_free_graphics_data( &_world.main );
+      _world.main.complete = 0;
       _world.loader_state = k_world_loader_ready;
       vg_loader_set_user_information( "Waiting for loading thread" );
    }
@@ -400,13 +416,13 @@ void world_switcher_update(void)
          _world.loader_state = k_world_loader_loading;
 
          vg_linear_clear( vg_async.buffer );
-         vg_linear_clear( _world.heap );
+         vg_linear_clear( _world.loader_heap );
          vg_loader_start( world_switcher_thread, NULL );
       }
    }
 }
 
-void skaterift_switch_world_start( addon_reg *reg )
+void skaterift_load_world_start( addon_reg *reg, bool preview )
 {
    if( g_client.unreadyness )
    {
@@ -420,45 +436,58 @@ void skaterift_switch_world_start( addon_reg *reg )
       return;
    }
 
-   if( _world.main.addon == reg )
-   {
-      vg_warn( "World is already loaded\n" );
-      return;
-   }
+   world_instance *world = preview? &_world.preview_instance: &_world.main;
 
    if( !reg )
    {
-      if( _world.main.addon )
+      if( world->addon )
       {
-         reg = _world.main.addon;
+         reg = world->addon;
       }
       else
       {
-         vg_error( "Loaded world has no associated addon registration."
-                   " Can't reload this!\n" );
+         vg_error( "Loaded world has no associated addon registration, can't reload this!\n" );
          return;
       }
    }
    
-   if( reg != _world.main.addon )
-      _world.previous_world_addon = _world.main.addon;
+   if( !preview )
+   {
+      if( reg != world->addon )
+         _world.previous_world_addon = _world.main.addon;
 
-   g_client.unreadyness ++;
-   _world.loader_state = k_world_loader_saving_current;
-   vg_loader_set_user_information( "Saving current world" );
+      g_client.unreadyness ++;
+      _world.loader_state = k_world_loader_saving_current;
+      vg_loader_set_user_information( "Saving current world" );
+   }
+   else
+      _world.loader_state = k_world_loader_ready;
 
    char buf[76];
    addon_alias_uid( &reg->alias, buf );
-   vg_info( "switching to: %s\n", buf );
+   vg_info( "loading world: %s %s\n", buf, preview? "(preview mode)": "" );
 
    vg_linear_clear( vg_mem.scratch ); /* ?? */
-   world_fadeout_audio( &_world.main );
 
-   _world.switch_to_addon = reg;
+   if( preview )
+   {
+      if( world->complete )
+      {
+         world_instance_free_graphics_data( world );
+         world->complete = 0;
+      }
+   }
+   else
+      world_fadeout_audio( &_world.main );
+
+   _world.loader_reg = reg;
+   _world.loader_instance = world;
+   _world.loader_heap = preview? _world.preview_heap: _world.heap;
+   _world.loader_preview_mode = preview;
 }
 
 /* console command for the above function */
-int skaterift_switch_world_command( int argc, const char *argv[] )
+int skaterift_load_world_command( int argc, const char *argv[] )
 {
    if( !vg_loader_availible() ) 
    {
@@ -466,14 +495,24 @@ int skaterift_switch_world_command( int argc, const char *argv[] )
       return 0;
    }
 
-   if( argc == 1 )
+   if( argc >= 1 )
    {
       if( !strcmp( argv[0], "reload" ) )
       {
-         skaterift_switch_world_start( NULL );
+         skaterift_load_world_start( NULL, 0 );
          return 0;
       }
 
+      bool preview = 0;
+
+      if( argc >= 2 )
+      {
+         if( !strcmp( argv[1], "preview" ) )
+         {
+            preview = 1;
+         }
+      }
+
       addon_alias q;
       addon_uid_to_alias( argv[0], &q );
 
@@ -481,7 +520,7 @@ int skaterift_switch_world_command( int argc, const char *argv[] )
       if( reg_id != 0xffffffff )
       {
          addon_reg *reg = get_addon_from_index( k_addon_type_world, reg_id, 0 );
-         skaterift_switch_world_start( reg );
+         skaterift_load_world_start( reg, preview );
       }
       else 
       {
@@ -521,7 +560,8 @@ void world_instance_free_graphics_data( world_instance *world )
    glDeleteTextures( 1, &world->tex_light_cubes );
 
    /* delete textures and meshes */
-   glDeleteTextures( world->texture_count-1, world->textures+1 );
+   if( world->texture_count )
+      glDeleteTextures( world->texture_count-1, world->textures+1 );
 
    for( u32 i=0; i<af_arrcount(&world->ent_cubemap); i++ )
    {
@@ -531,7 +571,8 @@ void world_instance_free_graphics_data( world_instance *world )
       glDeleteRenderbuffers( 1, &cm->renderbuffer_id );
    }
 
-   glDeleteTextures( world->nonlocal_gate_count, world->nonlocal_gates_cubemaps );
+   if( world->nonlocal_gate_count )
+      glDeleteTextures( world->nonlocal_gate_count, world->nonlocal_gates_cubemaps );
 }
 
 /* 
@@ -586,4 +627,9 @@ void world_init_blank( world_instance *world )
    v3_copy( (v3f){0.25f, 0.17f, 0.51f}, state->g_sunset_ambient );
    v3_copy( (v3f){1.000f, 0.809f, 0.318f}, state->g_sun_colour );
 #endif
+
+   world->tbo_light_entities = 0;
+   world->tex_light_entities = 0;
+   world->tex_light_cubes = 0;
+   world->nonlocal_gates_cubemaps = NULL;
 }
index fbd9226514b51935f97197dee4d739fd5ea463e2..f175bd2caaad6b92a0111b30476de2b19708c72a 100644 (file)
@@ -4,8 +4,8 @@
 #include "world.h"
 #include "addon.h"
 
-int skaterift_switch_world_command( int argc, const char *argv[] );
-void skaterift_switch_world_start( addon_reg *reg );
+int skaterift_load_world_command( int argc, const char *argv[] );
+void skaterift_load_world_start( addon_reg *reg, bool preview_mode );
 void world_switcher_update(void);
 void world_switcher_thread( void *_ );
 void world_instance_free_graphics_data( world_instance *world );
index 12b94fa1f9d5167bc38c8f0652feb582cc742503..afcc3578caf698a246123ddb357989045c48793f 100644 (file)
@@ -12,6 +12,8 @@
 #include "ent_skateshop.h"
 #include "shaders/model_entity.h"
 #include "shaders/model_sky_cubemap.h"
+#include "shaders/scene_preview.h"
+#include "shaders/scene_override.h"
 
 struct world_render world_render;
 
@@ -760,8 +762,7 @@ static void bindpoint_terrain( world_instance *world,
    shader_scene_terrain_uSandColour( props->sand_colour );
 }
 
-static void bindpoint_override( world_instance *world,
-                                   struct world_surface *mat )
+static void bindpoint_override( world_instance *world, struct world_surface *mat )
 {
    if( mat->info.flags & k_material_flag_collision )
    {
@@ -775,6 +776,17 @@ static void bindpoint_override( world_instance *world,
    }
 }
 
+static void bindpoint_world_preview( world_instance *world, struct world_surface *mat )
+{
+   if( mat->info.flags & k_material_flag_collision )
+   {
+   }
+   else
+   {
+   }
+}
+
+
 static void render_terrain( world_instance *world, vg_camera *cam )
 {
    shader_scene_terrain_use();
@@ -1277,6 +1289,48 @@ void render_world_override( world_instance *world,
    render_world_fxglow( world, world, cam, mmdl, 0, 0, 1 );
 }
 
+void render_world_preview(void)
+{
+   world_instance *world = &_world.preview_instance;
+   struct world_pass pass = 
+   {
+      .cam = &g_render.cam,
+      .fn_bind = bindpoint_world_preview,
+      .fn_set_mdl = shader_scene_preview_uMdl,
+      .fn_set_uPvmPrev = shader_scene_preview_uPvmPrev,
+      .fn_set_uNormalMtx = shader_scene_preview_uNormalMtx,
+      .shader = k_shader_override
+   };
+
+   shader_scene_preview_use();
+   shader_scene_preview_uPv( pass.cam->mtx.pv );
+   shader_scene_preview_uMapInfo((v4f){-1000.0f, 1000.0f, 0.0f, 0.0f});
+   //shader_scene_preview_uMapInfo((v4f){world->tar_min, world->tar_max, 1.0f, 0.0f});
+
+   m4x3f mmdl;
+   m4x3_identity( mmdl );
+
+   m4x4f mpvm_prev;
+   m4x3_expand( mmdl, mpvm_prev );
+   m4x4_mul( pass.cam->mtx_prev.pv, mpvm_prev, mpvm_prev );
+
+   m3x3f mnormal;
+   m3x3_inv( mmdl, mnormal );
+   m3x3_transpose( mnormal, mnormal );
+   v3_normalize( mnormal[0] );
+   v3_normalize( mnormal[1] );
+   v3_normalize( mnormal[2] );
+
+   glDisable( GL_CULL_FACE );
+   mesh_bind( &world->mesh_geo );
+   pass.geo_type = k_world_geo_type_solid;
+   render_world_override_pass( world, &pass, mmdl, mnormal, mpvm_prev );
+   mesh_bind( &world->mesh_no_collide );
+   pass.geo_type = k_world_geo_type_nonsolid;
+   render_world_override_pass( world, &pass, mmdl, mnormal, mpvm_prev );
+   glEnable( GL_CULL_FACE );
+}
+
 static void render_cubemap_side( world_instance *world, v3f co, m3x3f rotation, u32 side )
 {
    vg_camera cam;
index 8d512cbe67d4d692c3accada90bc57e6d44eef25..6e6915b7689dcfb1fff42af9dc65c38c7a42f27f 100644 (file)
@@ -83,6 +83,7 @@ void render_world_override( world_instance *world,
                             m4x3f mmdl,
                             vg_camera *cam,
                             ent_spawn *dest_spawn, v4f map_info );
+void render_world_preview(void);
 void render_world_gates( world_instance *world, vg_camera *cam );
 void imgui_world_light_edit( ui_context *ctx, world_instance *world );