yes menu master
authorhgn <hgodden00@gmail.com>
Tue, 18 Feb 2025 20:06:51 +0000 (20:06 +0000)
committerhgn <hgodden00@gmail.com>
Tue, 18 Feb 2025 20:06:51 +0000 (20:06 +0000)
content_skaterift/models/rs_icons.mdl
src/gui.h
src/menu.c
src/menu.h
src/skaterift.c
src/world_load.c
src/world_map.c
src/world_map.h
src/world_render.c

index ecbe3bcc79c43f306392654c04a0ec1da3fbf7bb..a9ada53936799ef044f548e4e1b11d0d33f47d83 100644 (file)
Binary files a/content_skaterift/models/rs_icons.mdl and b/content_skaterift/models/rs_icons.mdl differ
index dc38d32a77ed15faad39f86a76dcfdb594a79fa3..93a461333b5f587d4435a2ad0093a55aaf49985a 100644 (file)
--- a/src/gui.h
+++ b/src/gui.h
@@ -23,6 +23,7 @@ enum gui_icon {
    k_gui_icon_rift_run_2d,
    k_gui_icon_friend,
    k_gui_icon_player,
+   k_gui_icon_player2d,
    k_gui_icon_rift_run_gold,
    k_gui_icon_rift_run_silver,
    k_gui_icon_glider,
@@ -313,6 +314,7 @@ static void gui_init(void)
    gui.icons[ k_gui_icon_rift_run_2d ] = gui_find_icon( "icon_rift_run2d" );
    gui.icons[ k_gui_icon_friend ] = gui_find_icon( "icon_friend" );
    gui.icons[ k_gui_icon_player ] = gui_find_icon( "icon_player" );
+   gui.icons[ k_gui_icon_player2d ] = gui_find_icon( "icon_player2d" );
    gui.icons[ k_gui_icon_glider ] = gui_find_icon( "icon_glider" );
    gui.icons[ k_gui_icon_spawn ] = gui_find_icon( "icon_spawn" );
    gui.icons[ k_gui_icon_spawn_select ] = gui_find_icon( "icon_spawn_select" );
index b4abd2b635795aada419b75800291ed8f2c30273..692ffe33d805c9e9d4aea040bc1e1384ae97f0a8 100644 (file)
@@ -45,7 +45,7 @@ static void menu_update_world_filter(void)
       menu.world_list_whitelist = ADDON_REG_VENUS;
 }
 
-void menu_figure_out_where_to_start_world_select( addon_reg *addon_reg )
+void menu_on_world_change( addon_reg *addon_reg )
 {
    if( addon_reg == NULL )
       return;
@@ -71,6 +71,8 @@ void menu_figure_out_where_to_start_world_select( addon_reg *addon_reg )
    if( !name )
       name = addon_reg->alias.foldername;
    menu.clicked_world_name = name;
+
+   world_map_initialize_view();
 }
 
 void menu_open( enum menu_page page )
@@ -153,12 +155,8 @@ static bool menu_slider( ui_context *ctx,
    return (state & mask_using) && 1;
 }
 
-static bool menu_button( ui_context *ctx,
-                         ui_rect inout_panel, bool select, bool clickable, const char *text )
+bool menu_button_rect( ui_context *ctx, ui_rect rect, bool select, bool clickable, const char *text )
 {
-   ui_rect rect;
-   menu_standard_widget( ctx, inout_panel, rect, 1 );
-
    enum ui_button_state state = k_ui_button_none;
 
    if( vg_input.display_input_method == k_input_method_controller )
@@ -222,6 +220,13 @@ static bool menu_button( ui_context *ctx,
    else return 0;
 }
 
+static bool menu_button( ui_context *ctx, ui_rect inout_panel, bool select, bool clickable, const char *text )
+{
+   ui_rect rect;
+   menu_standard_widget( ctx, inout_panel, rect, 1 );
+   return menu_button_rect( ctx, rect, select, clickable, text );
+}
+
 static bool menu_checkbox( ui_context *ctx, ui_rect inout_panel, bool select, 
                            const char *str_label, i32 *data )
 {
@@ -793,419 +798,7 @@ void menu_gui( ui_context *ctx )
       menu_backable_to_exit = (vg_input.display_input_method == k_input_method_kbm);
       menu.bg_blur = 0;
 
-      ui_rect title_box = { vg.window_x/2 - 300/2, height + 8, 300, 100 };
-
-      ui_rect upper_title, lower_title;
-      ui_split( title_box, k_ui_axis_h, title_box[3]-24, 0, upper_title, lower_title );
-
-      const char *title_text = NULL,
-                 *subtitle_text = NULL;
-
-      if( world_map.activity == k_map_activity_local_world )
-      {
-         world_instance *world = &_world.main; 
-         title_text = af_str( &world->meta.af, world->info.pstr_name );
-         subtitle_text = "Current Location";
-
-         ctx->font = &vgf_default_title;
-         upper_title[2] = ui_text_line_width(ctx,title_text) + 24;
-         upper_title[0] = (vg.window_x - upper_title[2])/2;
-
-
-         /* main title  (world location, world status)
-          * ---------------------------------------------------------------------
-          */
-         bool go_to_super = 0;
-
-         ui_px back_box_size = 48;
-
-         ctx->font = &vgf_default_title;
-         ui_rect back_box = { upper_title[0] - (back_box_size + 8), title_box[1] + ((title_box[3]-back_box_size)/2), 
-                              back_box_size, back_box_size };
-         if( ui_button_text( ctx, back_box, "<", 1 ) == k_ui_button_click )
-         {
-            go_to_super = 1;
-         }
-
-         if( vg_input.display_input_method == k_input_method_controller )
-         {
-            char buf[32];
-            vg_str helper_text;
-            vg_strnull( &helper_text, buf, 32 );
-            vg_input_string( &helper_text, input_button_list[k_srbind_mback], 1 );
-            
-            ui_rect helper_label_box = { back_box[0] + (back_box[2]-32)/2, back_box[1] + back_box[3]-4, 32, 32 };
-            ui_fill( ctx, helper_label_box, ui_opacity( GUI_COL_DARK, 0.36f ) );
-            ui_text( ctx, helper_label_box, buf, 1, k_ui_align_middle_center, 0 );
-
-            if( button_down( k_srbind_mback ) )
-            {
-               audio_lock();
-               audio_oneshot( &audio_ui[3], 1.0f, 0.0f );
-               audio_unlock();
-               go_to_super = 1;
-            }
-         }
-
-         ctx->font = &vgf_default_title;
-         ui_rect super_location_box = { back_box[0] - (120+8), back_box[1], 120, 32 };
-         ui_text( ctx, super_location_box, "Earth", 1, k_ui_align_middle_center, ui_colour( ctx, k_ui_gray ) );
-
-
-         if( go_to_super )
-         {
-            world_map.activity = k_map_activity_galaxy;
-            menu_update_world_list();
-         }
-
-#if 0
-         ctx->font = &vgf_default_large;
-         ui_rect title = { vg.window_x/2- 512/2, height+8, 512, 64 };
-
-         ui_px x = 8,
-               y = height+8;
-
-         struct ui_vert *vs = ui_fill( ctx, (ui_rect){ x,y, 0,height }, GUI_COL_DARK );
-
-         char buf[64];
-         vg_str str;
-         vg_strnull( &str, buf, sizeof(buf) );
-
-         world_instance *world = &_world.main;
-         const char *world_name = af_str( &world->meta.af, world->info.pstr_name );
-         vg_strnull( &str, buf, sizeof(buf) );
-         vg_strcat( &str, world_name );
-         
-         ui_px w = ui_text( ctx, (ui_rect){ x+8, y, 1000, height }, buf, 1,
-                            k_ui_align_middle_left, 0 );
-
-         w *= ctx->font->sx;
-         x += w + 16;
-
-         vs[1].co[0] = x + 8;
-         vs[2].co[0] = x;
-
-         x = 8;
-         y += 8 + height;
-
-         ui_rect stat_panel = { x,y, 256,vg.window_y-y };
-         u32 c0 = ui_opacity( GUI_COL_DARK, 0.36f );
-         vs = ui_fill( ctx, stat_panel, c0 );
-
-         ui_rect_pad( stat_panel, (ui_px[2]){8,0} );
-
-         for( u32 i=0; i<af_arrcount( &world->ent_region ); i ++ )
-         {
-            ent_region *region = af_arritm( &world->ent_region, i );
-
-            if( !region->zone_volume )
-               continue;
-
-            const char *title = af_str( &world->meta.af, region->pstr_title );
-            ctx->font = &vgf_default_large;
-
-            ui_rect title_box;
-            menu_standard_widget( ctx, stat_panel, title_box, 1 );
-            
-            stat_panel[0] += 16;
-            stat_panel[2] -= 16;
-            ctx->font = &vgf_default_small;
-
-            ent_volume *volume = af_arritm(&world->ent_volume,
-                  mdl_entity_id_id(region->zone_volume));
-
-            u32 combined = k_ent_route_flag_achieve_gold | 
-                           k_ent_route_flag_achieve_silver;
-
-            char buf[128];
-            vg_str str;
-
-            for( u32 j=0; j<af_arrcount(&world->ent_route); j ++ )
-            {
-               ent_route *route = af_arritm(&world->ent_route, j );
-
-               v3f local;
-               m4x3_mulv( volume->to_local, route->board_transform[3], local );
-               if( !((fabsf(local[0]) <= 1.0f) &&
-                     (fabsf(local[1]) <= 1.0f) &&
-                     (fabsf(local[2]) <= 1.0f)) )
-               {
-                  continue;
-               }
-
-               combined &= route->flags;
-
-               vg_strnull( &str, buf, sizeof(buf) );
-               vg_strcat( &str, "(Race) " );
-               vg_strcat( &str, af_str( &world->meta.af, route->pstr_name ));
-
-               if( route->flags & k_ent_route_flag_achieve_silver )
-                  vg_strcat( &str, " \xb3");
-               if( route->flags & k_ent_route_flag_achieve_gold )
-                  vg_strcat( &str, "\xb3");
-
-               ui_rect r;
-               ui_standard_widget( ctx, stat_panel, r, 1 );
-               ui_text( ctx, r, buf, 1, k_ui_align_middle_left, 
-                        medal_colour( ctx, route->flags ) );
-            }
-
-            for( u32 j=0; j<af_arrcount(&world->ent_challenge); j ++ )
-            {
-               ent_challenge *challenge = af_arritm( &world->ent_challenge, j );
-
-               v3f local;
-               m4x3_mulv( volume->to_local, challenge->transform.co, local );
-               if( !((fabsf(local[0]) <= 1.0f) &&
-                     (fabsf(local[1]) <= 1.0f) &&
-                     (fabsf(local[2]) <= 1.0f)) )
-               {
-                  continue;
-               }
-
-               vg_strnull( &str, buf, sizeof(buf) );
-               vg_strcat( &str, af_str( &world->meta.af,challenge->pstr_alias));
-
-               u32 flags = 0x00;
-               if( challenge->status )
-               {
-                  flags |= k_ent_route_flag_achieve_gold;
-                  flags |= k_ent_route_flag_achieve_silver;
-                  vg_strcat( &str, " \xb3\xb3" );
-               }
-
-               combined &= flags;
-
-               ui_rect r;
-               ui_standard_widget( ctx, stat_panel, r, 1 );
-               ui_text( ctx, r, buf, 1, 
-                        k_ui_align_middle_left, medal_colour( ctx, flags ) );
-            }
-
-            stat_panel[0] -= 16;
-            stat_panel[2] += 16;
-
-            u32 title_col = 0;
-            if( combined & k_ent_route_flag_achieve_gold ) 
-               title_col = ui_colour( ctx, k_ui_yellow );
-            else if( combined & k_ent_route_flag_achieve_silver )
-               title_col = ui_colour( ctx, k_ui_fg );
-
-            menu_heading( ctx, title_box, title, title_col );
-         }
-
-         vs[2].co[1] = stat_panel[1];
-         vs[3].co[1] = stat_panel[1];
-
-         ui_rect back_button = {0,0,300,32};
-         ui_rect_center( (ui_rect){0,0,vg.window_x,vg.window_y}, back_button );
-         if( ui_button_text( ctx, back_button, "up", 1 ) == k_ui_button_click )
-         {
-            world_map.activity = k_map_activity_
-         }
-#endif
-      }
-      else if( world_map.activity >= k_map_activity_galaxy )
-      {
-         ui_rect panel = { 24, height+24, WORKSHOP_PREVIEW_WIDTH+8, vg.window_y-(height+24+24) };
-         ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
-
-
-         title_text = menu.clicked_world_name? menu.clicked_world_name: "...";
-         subtitle_text = (menu.clicked_world_reg == _world.main.addon)? "Current Location": NULL;
-
-         ctx->font = &vgf_default_title;
-         upper_title[2] = ui_text_line_width(ctx,title_text) + 24;
-         upper_title[0] = panel[0]+panel[2] + ((vg.window_x - (panel[0]+panel[2])) - upper_title[2])/2;
-         lower_title[0] = panel[0]+panel[2] + 24;
-         lower_title[2] = (vg.window_x - (lower_title[0]+24));
-
-
-         /* planet box
-          * -------------------------------------------------------------------------------------------------------- */
-         ui_rect planet_box;
-         ui_split( panel, k_ui_axis_h, WORKSHOP_PREVIEW_HEIGHT, 8, planet_box, panel );
-
-         planet_box[0] += 4;
-         planet_box[2] = WORKSHOP_PREVIEW_WIDTH;
-         planet_box[3] = WORKSHOP_PREVIEW_HEIGHT;
-         ui_image( ctx, planet_box, &g_render.fb_workshop_preview->attachments[0].id );
-
-         ui_rect planet_box_title;
-         ui_split( planet_box, k_ui_axis_h, 28, 0, planet_box_title, planet_box );
-         ui_fill( ctx, planet_box_title, ui_opacity( GUI_COL_DARK, 0.2f ) );
-         ctx->font = &vgf_default_large;
-         ui_text( ctx, planet_box_title, _superworld_names[world_map.superworld_list_selected], 1, 
-                  k_ui_align_middle_center, ui_colour(ctx,k_ui_yellow) );
-
-         ui_px change_w = 48,
-               change_h = 160,
-               change_y = planet_box[1] + (planet_box[3]-80)/2;
-
-         /* << */
-         bool superworld_changed = 0;
-         ui_rect change_box_l = { panel[0], change_y, change_w, change_h };
-         if( world_map.superworld_actual_world < world_map.superworld_list_selected )
-         {
-            ui_rect helper_box = { change_box_l[0], planet_box_title[1]+planet_box_title[3], 300, 24 };
-            ctx->font = &vgf_default_small;
-            ui_text( ctx, helper_box, "<< Current location", 1, k_ui_align_middle_left, ui_colour(ctx,k_ui_yellow) );
-         }  
-         ctx->font = &vgf_default_title;
-         if( menu_button( ctx, change_box_l, 0, world_map.superworld_list_selected > 0, "<" ) )
-         {
-            world_map.superworld_list_selected --;
-            superworld_changed = 1;
-         }
-
-         /* >> */
-         ui_rect change_box_r = { (panel[0]+panel[2]) - change_w, change_y, change_w, change_h };
-         if( world_map.superworld_actual_world > world_map.superworld_list_selected )
-         {
-            ui_rect helper_box = { change_box_r[0] - 300, planet_box_title[1]+planet_box_title[3], 300, 24 };
-            ctx->font = &vgf_default_small;
-            ui_text( ctx, helper_box, "Current location >>", 1, k_ui_align_middle_right, ui_colour(ctx,k_ui_yellow) );
-         }  
-         ctx->font = &vgf_default_title;
-         if( menu_button( ctx, change_box_r, 0, world_map.superworld_list_selected < k_superworld_max-1, ">" ) )
-         {
-            world_map.superworld_list_selected ++;
-            superworld_changed = 1;
-         }
-
-         /* controller input */
-         if( mh ) 
-         {
-            i32 s = world_map.superworld_list_selected - mh;
-            if( s < 0 ) s = 0;
-            if( s > k_superworld_max -1 ) s = k_superworld_max -1;
-
-            if( s != world_map.superworld_list_selected )
-            {
-               world_map.superworld_list_selected = s;
-               superworld_changed = 1;
-            }
-         }
-
-         /* World list
-          * -------------------------------------------------------------------------------------------- */
-         ui_rect title;
-         ui_split( panel, k_ui_axis_h, 28, 0, title, panel );
-         ctx->font = &vgf_default_large;
-         ui_text( ctx, title, "Locations", 1, k_ui_align_middle_center, 0 );
-
-         i32 nominal_count = ((panel[3]+8) / (ctx->font->sy*2 + 8)) - 2;
-         if( nominal_count > MENU_WORLD_MAX_COUNT )
-            nominal_count = MENU_WORLD_MAX_COUNT;
-         if( nominal_count <= 0 )
-            nominal_count = 1;
-
-         if( superworld_changed || (nominal_count != menu.world_list_nominal_display_count) )
-         {
-            menu.world_list_nominal_display_count = nominal_count;
-            menu_update_world_list();
-         }
-
-         i32 *selected_world_index = &menu.world_list_selected_index[ world_map.superworld_list_selected ],
-             page = (*selected_world_index) / menu.world_list_nominal_display_count,
-             page_base = page * menu.world_list_nominal_display_count,
-             max_page = (menu.world_list_total_count-1) / menu.world_list_nominal_display_count;
-
-         i32 R = menu_nav( selected_world_index, mv, menu.world_list_total_count-1 );
-
-
-         if( menu_button( ctx, panel, R == -999, page>0, "\x94" ) )
-            *selected_world_index = (page-1)*menu.world_list_nominal_display_count;
-
-         for( u32 i=0; i<menu.world_list_display_count; i ++ )
-         {
-            addon_reg *reg = menu.world_list_entries[i];
-
-            bool selected = reg == menu.clicked_world_reg;
-            
-            if( selected )
-            {
-               ui_rect sel_box, _null;
-               ui_split( panel, k_ui_axis_h, ctx->font->sy*2, 8, sel_box, _null );
-               ui_outline( ctx, sel_box, 2, ui_colour(ctx,k_ui_fg), 0 );
-            }
-
-            if( menu_button( ctx, panel, R == (page_base + i), !selected, menu.world_list_names[i] ) )
-            {
-               menu.clicked_world_reg = reg;
-               menu.clicked_world_name = menu.world_list_names[i];
-            }
-         }
-         
-         if( menu_button( ctx, panel, R == -999, page<max_page, "\x96" ) )
-            *selected_world_index = (page+1)*menu.world_list_nominal_display_count;
-
-         if( (*selected_world_index < page_base) || 
-             (*selected_world_index >= (page_base+menu.world_list_nominal_display_count)) )
-         {
-            menu_update_world_list();
-         }
-
-         if( (_world.loader_state == k_world_loader_done) && (menu.clicked_world_reg) )
-         {
-            bool do_load = 0;
-            
-            if( _world.preview_instance.complete ) 
-            {
-               if( _world.preview_instance.addon != menu.clicked_world_reg )
-                  do_load = 1;
-            }
-            else
-               do_load = 1;
-
-            if( do_load )
-               skaterift_load_world_start( menu.clicked_world_reg, 1 );
-         }
-
-         ctx->font = &vgf_default_title;
-         ui_px remainder = vg.window_x - (panel[0] + panel[2]),
-               width     = 400,
-               height    = ctx->font->sy*2;
-
-         ui_rect enter_world_box = { panel[0] + panel[2] + (remainder-width)/2, vg.window_y - (height + 24),
-                                     width, height };
-
-         char buf[64];
-         vg_str enter_helper;
-         vg_strnull( &enter_helper, buf, sizeof(buf) );
-         vg_strcat( &enter_helper, "Enter location " );
-         if( vg_input.display_input_method == k_input_method_controller )
-            vg_input_string( &enter_helper, input_button_list[k_srbind_mhub], 1 );
-
-         bool enter_location = 0;
-         if( menu_button( ctx, enter_world_box, 0, menu.clicked_world_reg?1:0, buf ) )
-            enter_location = 1;
-
-         if( button_down( k_srbind_mhub ) )
-            enter_location = 1;
-
-         if( enter_location && menu.clicked_world_reg )
-         {
-            if( menu.clicked_world_reg != _world.main.addon )
-               skaterift_load_world_start( menu.clicked_world_reg, 0 );
-
-            world_map.activity = k_map_activity_local_world;
-            world_map.superworld_actual_world = world_map.superworld_list_selected;
-         }
-      }
-
-      /* Render title & subtitle 
-       * ---------------------------------------------------------------------------------------------------
-       */
-
-      ctx->font = &vgf_default_title;
-      ui_text( ctx, upper_title, title_text, 1, k_ui_align_middle_center, ui_colour( ctx, k_ui_yellow ) );
-
-      if( subtitle_text )
-      {
-         ctx->font = &vgf_default_large;
-         ui_text( ctx, lower_title, subtitle_text, 1, k_ui_align_middle_center, 0 );
-      }
+      world_map_gui( ctx, (ui_rect){ 0, height, vg.window_x, vg.window_y - height }, mh, mv, &menu_backable_to_exit );
    }
    else /* menu.main_index != k_menu_main_map) */
    {
index 05f59287df7ecc13d3ab131dadaedf5c0c2c6840..f8a96a0ff78405da045649f0b0aedf40dc8ed2fa 100644 (file)
@@ -71,4 +71,5 @@ void menu_open( enum menu_page page );
 bool menu_viewing_map(void);
 bool menu_viewing_preview(void);
 void menu_update_world_list(void);
-void menu_figure_out_where_to_start_world_select( addon_reg *addon_reg );
+void menu_on_world_change( addon_reg *addon_reg );
+bool menu_button_rect( ui_context *ctx, ui_rect rect, bool select, bool clickable, const char *text );
index e4cb625ba5be8bbdc6b266721b8952073db7401b..0bee2f30ee752b3e054a09c65cde98613825f161 100644 (file)
@@ -76,7 +76,7 @@ static addon_reg *skaterift_mount_world_unloadable( const char *path, u32 ext )
 static void skaterift_load_world_content(void)
 {
    /* hub world */
-   _world.default_hub_addon = skaterift_mount_world_unloadable( "maps/dev_hub", 0 );
+   _world.default_hub_addon = skaterift_mount_world_unloadable( "maps/dev_hub", ADDON_REG_CAMPAIGN );
    skaterift_mount_world_unloadable( "maps/dev_heaven",  ADDON_REG_CAMPAIGN | ADDON_REG_HIDDEN );
    skaterift_mount_world_unloadable( "maps/mp_spawn",    ADDON_REG_CAMPAIGN | ADDON_REG_CITY|ADDON_REG_PREMIUM );
    skaterift_mount_world_unloadable( "maps/mp_mtzero",   ADDON_REG_CAMPAIGN | ADDON_REG_MTZERO|ADDON_REG_PREMIUM );
@@ -153,9 +153,10 @@ void game_load(void)
       vg_warn( "Falling back to default hub world...\n" );
       _world.loader_reg = _world.default_hub_addon;
    }
-   menu_figure_out_where_to_start_world_select( _world.loader_reg );
    world_switcher_thread( NULL );
-
+   
+   vg_async_stall();
+   menu_on_world_change( _world.main.addon );
 
    /* add autosave function to exit list */
    vg_loader_step( NULL, skaterift_autosave_synchronous );
@@ -227,7 +228,6 @@ void vg_pre_update(void)
 
    world_update( &_world.main, localplayer.rb.co );
    audio_ambient_sprites_update( &_world.main, listen_co );
-   world_map_pre_update();
 }
 
 void vg_fixed_update(void)
@@ -343,17 +343,15 @@ static void skaterift_composite_maincamera(void)
       ent_camera_unpack( menu.bg_cam, &g_render.cam );
    }
 
-   if( menu_viewing_map() )
-   {
-      vg_camera_copy( &world_map.cam, &g_render.cam );
-      g_render.cam.nearz = 4.0f;
-      g_render.cam.farz = 3100.0f;
-   }
-
    ent_camera *cs_cam = _cutscene_active_camera();
    if( cs_cam )
       ent_camera_unpack( cs_cam, &g_render.cam );
 
+   if( world_map.sel_spawn && (world_map.spawn_timer > 0.0f) )
+   {
+      vg_camera_copy( &world_map.final_cam, &g_render.cam );
+   }
+
    vg_camera_update_transform( &g_render.cam );
 
    if( _TEMP_VAR )
@@ -361,6 +359,7 @@ static void skaterift_composite_maincamera(void)
       m4x3_copy( _TEMP_VAR[0], g_render.cam.transform );
       _TEMP_VAR = NULL;
    }
+
    vg_camera_update_view( &g_render.cam );
    vg_camera_update_projection( &g_render.cam, vg.window_x, vg.window_y );
    vg_camera_finalize( &g_render.cam );
@@ -394,6 +393,7 @@ static void render_main_game(void)
    skaterift_composite_maincamera();
 
    bool render_actual_game = !menu_viewing_map();
+   bool render_stenciled = 0;
 
    if( render_actual_game )
    {
@@ -406,6 +406,27 @@ static void render_main_game(void)
    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT );
 
+   if( !render_actual_game )
+   {
+      render_world_map();
+
+      if( world_map.sel_spawn && (world_map.spawn_timer > 0.0f) )
+      {
+         glEnable( GL_STENCIL_TEST );
+         glDisable( GL_DEPTH_TEST );
+         glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
+         glStencilFunc( GL_ALWAYS, 1, 0xFF );
+         glStencilMask( 0xFF );
+         
+         shader_blit_transition_use();
+         shader_blit_transition_uInverseRatio( (v2f){1.0f,1.0f} );
+         shader_blit_transition_uT( -(sqrtf(2)+0.5f) * world_map.spawn_timer );
+         render_fsquad();
+         render_stenciled = 1;
+         render_actual_game = 1;
+      }
+   }
+
    if( render_actual_game )
    {
       /* Draw world */
@@ -425,7 +446,7 @@ static void render_main_game(void)
       }
 #endif
 
-      render_world( &_world.main, &g_render.cam, 0, 0, 1, 1 );
+      render_world( &_world.main, &g_render.cam, render_stenciled, 0, 1, 1 );
 
       particle_system_update( &particles_grind, vg.time_delta );
       //particle_system_debug( &particles_grind );
@@ -439,10 +460,6 @@ static void render_main_game(void)
 
       player_glide_render_effects( &g_render.cam );
    }
-   else
-   {
-      render_world_map();
-   }
 
    glEnable( GL_DEPTH_TEST );
 
@@ -450,7 +467,7 @@ static void render_main_game(void)
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
    glViewport( 0,0, vg.window_x, vg.window_y );
 
-   if( render_actual_game )
+   if( render_actual_game && !render_stenciled )
    {
       render_player_transparent(); /* needs to read the depth buffer before we fuck
                                       it up with the oblique rendering inside the
index bb8755112cbf29a99590b28fc3f667db07a05583..6124964a0777f5467574e3b83b9d501f429cc91b 100644 (file)
@@ -525,7 +525,7 @@ int skaterift_load_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,0 );
-         menu_figure_out_where_to_start_world_select( reg );
+         menu_on_world_change( reg );
          skaterift_load_world_start( reg, preview );
       }
       else 
index ced1cbaba7de7aaee4b8a2139c110a6bdfd034b9..214647e7ce331bd1ca5a0a39fbbbfd59519d78c6 100644 (file)
@@ -85,247 +85,108 @@ static void world_map_help_normal(void)
 #endif
 }
 
-void world_map_pre_update(void)
+void world_map_initialize_view(void)
 {
-   if( menu_viewing_map() )
-   {
-      if( world_map.activity == k_map_activity_galaxy )
-      {
-         return;
-      }
-
-      if( !world_map.view_ready )
-      {
-         world_instance *world = &_world.main;
-         v3f *bbx = world->scene_geo.bbx;
+   world_instance *world = &_world.main;
+   v3f *bbx = world->scene_geo.bbx;
 
-         respawn_world_to_plane_pos( localplayer.rb.co, world_map.plane_pos );
-         world_map.boom_dist = 400.0f;
-         world_map.home_select = 0;
-         world_map.view_ready = 1;
-         world_map.sel_spawn = NULL;
-         world_map.close_spawn = NULL;
+   respawn_world_to_plane_pos( localplayer.rb.co, world_map.plane_pos );
+   world_map.boom_dist = 400.0f;
+   world_map.view_ready = 1;
+   world_map.sel_spawn = NULL;
+   world_map.close_spawn = NULL;
+   world_map.smooth_warm = 0;
+}
 
-         world_map_help_normal();
-      }
-   }
+static void world_map_update_final_camera( vg_camera *cam )
+{
+   if( world_map.smooth_warm )
+      vg_camera_lerp( &world_map.smoothed_cam, cam, vg.time_frame_delta*3.0f, &world_map.smoothed_cam );
    else
    {
-      if( world_map.view_ready )
-      {
-         gui_helper_reset( k_gui_helper_mode_clear );
-         world_map.view_ready = 0;
-      }
-
-      return;
+      world_map.smooth_warm = 1;
+      vg_camera_copy( cam, &world_map.smoothed_cam );
    }
 
-   world_instance *world = &_world.main;
-   v3f *bbx = world->scene_geo.bbx;
-   f32 *pos = world_map.plane_pos;
+   world_map.final_cam.farz = 5000.0f;
+   world_map.final_cam.nearz = 10.0f;
 
-#if 0
-   v2f steer;
-   joystick_state( k_srjoystick_steer, steer );
-   v2_normalize_clamp( steer );
-
-   if( !world_map.sel_spawn )
+   if( world_map.sel_spawn && (world_map.spawn_timer > 0.0f) )
    {
-      f32 *pos = world_map.plane_pos;
-      m2x2f rm;
-      m2x2_create_rotation( rm, -0.25f*VG_PIf );
-      m2x2_mulv( rm, steer, steer );
-      v2_muladds( pos, steer, vg.time_frame_delta * 200.0f, pos );
+      f32 t = vg_smoothstepf( world_map.spawn_timer );
+      vg_camera_lerp( &localplayer.cam, &world_map.smoothed_cam, t, &world_map.final_cam );
+      world_map.final_cam.nearz = vg_lerpf( 0.1f, 10.0f, t );
    }
-#endif
-
-   f32 bd_target = 400.0f,
-       interp = vg.time_frame_delta*2.0f;
-
-   if( world_map.sel_spawn )
+   else
    {
-      v2f pp;
-      respawn_world_to_plane_pos( world_map.sel_spawn->transform.co, pp );
-      v2_lerp( pos, pp, interp, pos );
-
-      bd_target = 200.0f;
+      vg_camera_copy( &world_map.smoothed_cam, &world_map.final_cam );
    }
-   world_map.boom_dist = vg_lerpf( world_map.boom_dist, bd_target, interp );
-
-   v2_minv( (v2f){ bbx[1][0], bbx[1][2] }, pos, pos );
-   v2_maxv( (v2f){ bbx[0][0], bbx[0][2] }, pos, pos );
-
-   /* update camera */
-   vg_camera *cam = &world_map.cam;
-   v3f dir;
-   world_map_get_dir(dir);
-
-   v4f plane;
-   world_map_get_plane( plane );
-
-   v3f co = { pos[0], plane[3]*plane[1], pos[1] };
-   v3_muladds( co, dir, world_map.boom_dist, cam->pos );
-
-   vg_line_cross( co, VG__RED, 10.0f );
-
-   cam->angles[0] = 0.25f * VG_PIf;
-   cam->angles[1] = 0.25f * VG_PIf;
-   cam->farz = 5000.0f;
-   cam->nearz = 10.0f;
-   cam->fov = 40.0f;
-
-   vg_camera_update_transform( cam );
-   vg_camera_update_view( cam );
-   vg_camera_update_projection( cam, vg.window_x, vg.window_y );
-   vg_camera_finalize( cam );
+   vg_camera_update_transform( &world_map.final_cam );
+   vg_camera_update_view( &world_map.final_cam );
+   vg_camera_update_projection( &world_map.final_cam, vg.window_x, vg.window_y );
+   vg_camera_finalize( &world_map.final_cam );
+   vg_camera_finalize( &world_map.final_cam );
+}
 
-   /* pick spawn */
-   f32 closest2 = INFINITY;
-   v2f centroid = { 0, 0 };
+void render_world_map(void)
+{
+   glEnable( GL_DEPTH_TEST );
 
-   for( u32 i=0; i<af_arrcount(&world->ent_spawn); i++ )
+   if( world_map.activity == k_map_activity_local_world )
    {
-      ent_spawn *spawn = af_arritm(&world->ent_spawn,i);
+      world_instance *world = &_world.main;
 
-      v4f v;
-      v3_copy( spawn->transform.co, v );
-      v[3] = 1.0f;
-      m4x4_mulv( cam->mtx.pv, v, v );
-      v2_divs( v, v[3], v );
+      /* update camera based on input position and zoom 
+       * ---------------------------------------------------------------------------------------- */
+      vg_camera cam;
+      v3f dir;
+      world_map_get_dir(dir);
 
-      f32 d2 = v2_dist2(v, centroid);
-      if( d2 < closest2 )
-      {
-         world_map.close_spawn = spawn;
-         closest2 = d2;
-      }
-      spawn->transform.s[0] = d2;
-   }
+      v4f plane;
+      world_map_get_plane( plane );
 
-#if 0
-   if( button_down( k_srbind_maccept ) )
-   {
-      if( world_map.sel_spawn )
-      {
-         skaterift.activity = k_skaterift_default;
-         srinput.state = k_input_state_resume;
-         player__spawn( world_map.sel_spawn );
-         return;
-      }
-      else
-      {
-         world_map_select_close();
-      }
-   }
+      v3f co = { world_map.plane_pos[0], plane[3]*plane[1], world_map.plane_pos[1] };
+      v3_muladds( co, dir, world_map.boom_dist, cam.pos );
 
-   if( button_down( k_srbind_mback ) )
-   {
-      if( world_map.sel_spawn )
-      {
-         world_map.sel_spawn = NULL;
-         world_map_help_normal();
-      }
-   }
-#endif
+      cam.angles[0] = 0.25f * VG_PIf;
+      cam.angles[1] = 0.25f * VG_PIf;
+      cam.angles[2] = 0.0f;
+      cam.fov = 40.0f;
 
-   /* icons
-    * ---------------------*/
-   for( u32 i=0; i<af_arrcount(&world->ent_challenge); i++ )
-   {
-      ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
-      if( challenge->flags & k_ent_challenge_locked ) 
-         continue;
+      world_map_update_final_camera( &cam );
 
-      enum gui_icon icon = k_gui_icon_exclaim_2d;
-      if( challenge->flags & k_ent_challenge_is_story )
+      /* update closest spawn based on camera
+       * ------------------------------------------------------------------------------------------- */
+      f32 closest2 = INFINITY;
+      for( u32 i=0; i<af_arrcount(&world->ent_spawn); i++ )
       {
-         icon = k_gui_icon_story2d;
-         if( world->events[i].story_script )
+         ent_spawn *spawn = af_arritm(&world->ent_spawn,i);
+
+         if( world_map.sel_spawn )
          {
-            if( world->events[i].story_script->viewed_time )
+            spawn->transform.s[0] = ( spawn == world_map.sel_spawn )? 0.0f: 10000.0f;
+         }
+         else
+         {
+            v4f v;
+            v3_copy( spawn->transform.co, v );
+            v[3] = 1.0f;
+            m4x4_mulv( world_map.final_cam.mtx.pv, v, v );
+            v2_divs( v, v[3], v );
+
+            f32 d2 = v2_dist2(v, world_map.view_centroid);
+            if( d2 < closest2 )
             {
-               icon = k_gui_icon_story_done2d;
+               world_map.close_spawn = spawn;
+               closest2 = d2;
             }
+            spawn->transform.s[0] = d2;
          }
       }
-      else
-      {
-         if( challenge->status )
-            icon = k_gui_icon_tick_2d;
-      }
 
-      respawn_map_draw_icon( cam, icon, challenge->transform.co, 1.0f );
-   }
-
-   for( u32 i=0; i<af_arrcount(&world->ent_spawn); i ++ )
-   {
-      ent_spawn *spawn = af_arritm( &world->ent_spawn, i );
+      /* Do the rendering of the world in override shader
+       * ------------------------------------------------------------------------------------------------- */
 
-      if( spawn->transform.s[0] > 0.3f )
-         continue;
-
-      f32 s = 1.0f-(spawn->transform.s[0] / 0.3f);
-      respawn_map_draw_icon( cam, 
-            spawn==world_map.sel_spawn? 
-               k_gui_icon_spawn_select: k_gui_icon_spawn,
-            spawn->transform.co, s );
-   }
-
-   for( u32 i=0; i<af_arrcount(&world->ent_skateshop); i++ )
-   {
-      ent_skateshop *shop = af_arritm( &world->ent_skateshop, i );
-      if( shop->type == k_skateshop_type_boardshop )
-      {
-         respawn_map_draw_icon( cam, k_gui_icon_board, shop->transform.co, 1 );
-      }
-      else if( shop->type == k_skateshop_type_worldshop )
-      {
-         respawn_map_draw_icon( cam, k_gui_icon_world, shop->transform.co, 1 );
-      }
-   }
-
-   for( u32 i=0; i<af_arrcount(&world->ent_gate); i++ )
-   {
-      ent_gate *gate = af_arritm( &world->ent_gate, i );
-      if( gate->flags & k_ent_gate_nonlocal )
-      {
-         respawn_map_draw_icon( cam, k_gui_icon_rift, gate->co[0], 1 );
-      }
-   }
-
-   for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
-   {
-      ent_route *route = af_arritm( &world->ent_route, i );
-
-      v4f colour;
-      v4_copy( route->colour, colour );
-      v3_muls( colour, 1.6666f, colour );
-      gui_icon_setcolour( colour );
-      respawn_map_draw_icon( cam, k_gui_icon_rift_run_2d, 
-                             route->board_transform[3], 1 );
-   }
-
-   for( u32 i=0; i<af_arrcount(&world->ent_glider); i ++ )
-   {
-      ent_glider *glider = af_arritm( &world->ent_glider, i );
-
-      v4f colour = { 1,1,1,1 };
-
-      if( !(glider->flags & 0x1) )
-         v3_muls( colour, 0.5f, colour );
-      gui_icon_setcolour( colour );
-
-      respawn_map_draw_icon( cam, k_gui_icon_glider, glider->transform.co, 1 );
-   }
-}
-
-void render_world_map(void)
-{
-   glEnable( GL_DEPTH_TEST );
-
-   if( world_map.activity == k_map_activity_local_world )
-   {
-      world_instance *world = &_world.main;
       world_prerender( world );
 
       glDrawBuffers( 1, (GLenum[]){ GL_COLOR_ATTACHMENT0 } );
@@ -347,12 +208,103 @@ void render_world_map(void)
 
       m4x3f identity;
       m4x3_identity( identity );
-      render_world_override( world, world, identity, &g_render.cam, 
-                             world_map.close_spawn, 
+      render_world_override( world, world, identity, &world_map.final_cam, 
+                              world_map.sel_spawn? world_map.sel_spawn: world_map.close_spawn, 
                              (v4f){world->tar_min, world->tar_max, 1.0f, 0.0f});
-      render_world_routes( world, world, identity, &g_render.cam, 0, 1 );
+      render_world_routes( world, world, identity, &world_map.final_cam, 0, 1 );
+
+      /* Add icons to the map
+       * ------------------------------------------------------------------------------------------------- */
+      for( u32 i=0; i<af_arrcount(&world->ent_challenge); i++ )
+      {
+         ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
+         if( challenge->flags & k_ent_challenge_locked ) 
+            continue;
+
+         enum gui_icon icon = k_gui_icon_exclaim_2d;
+         if( challenge->flags & k_ent_challenge_is_story )
+         {
+            icon = k_gui_icon_story2d;
+            if( world->events[i].story_script )
+            {
+               if( world->events[i].story_script->viewed_time )
+               {
+                  icon = k_gui_icon_story_done2d;
+               }
+            }
+         }
+         else
+         {
+            if( challenge->status )
+               icon = k_gui_icon_tick_2d;
+         }
+
+         respawn_map_draw_icon( &world_map.final_cam, icon, challenge->transform.co, 1.0f );
+      }
+
+      for( u32 i=0; i<af_arrcount(&world->ent_spawn); i ++ )
+      {
+         ent_spawn *spawn = af_arritm( &world->ent_spawn, i );
+
+         if( spawn->transform.s[0] > 0.3f )
+            continue;
+
+         f32 s = 1.0f-(spawn->transform.s[0] / 0.3f);
+         respawn_map_draw_icon( &world_map.final_cam, 
+                                 spawn==world_map.sel_spawn? k_gui_icon_spawn_select: k_gui_icon_spawn,
+                                 spawn->transform.co, s );
+      }
+
+      for( u32 i=0; i<af_arrcount(&world->ent_skateshop); i++ )
+      {
+         ent_skateshop *shop = af_arritm( &world->ent_skateshop, i );
+         if( shop->type == k_skateshop_type_boardshop )
+         {
+            respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_board, shop->transform.co, 1 );
+         }
+         else if( shop->type == k_skateshop_type_worldshop )
+         {
+            respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_world, shop->transform.co, 1 );
+         }
+      }
+
+      for( u32 i=0; i<af_arrcount(&world->ent_gate); i++ )
+      {
+         ent_gate *gate = af_arritm( &world->ent_gate, i );
+         if( gate->flags & k_ent_gate_nonlocal )
+         {
+            respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_rift, gate->co[0], 1 );
+         }
+      }
+
+      for( u32 i=0; i<af_arrcount(&world->ent_route); i++ )
+      {
+         ent_route *route = af_arritm( &world->ent_route, i );
+
+         v4f colour;
+         v4_copy( route->colour, colour );
+         v3_muls( colour, 1.6666f, colour );
+         gui_icon_setcolour( colour );
+         respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_rift_run_2d, route->board_transform[3], 1 );
+      }
+
+      for( u32 i=0; i<af_arrcount(&world->ent_glider); i ++ )
+      {
+         ent_glider *glider = af_arritm( &world->ent_glider, i );
+
+         v4f colour = { 1,1,1,1 };
+
+         if( !(glider->flags & 0x1) )
+            v3_muls( colour, 0.5f, colour );
+         gui_icon_setcolour( colour );
+
+         respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_glider, glider->transform.co, 1 );
+      }
+
+      gui_icon_setcolour( (v4f){1,1,1,1} );
+      respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_player2d, localplayer.rb.co, 1.0f );
    }
-   else
+   else if( world_map.activity == k_map_activity_galaxy )
    {
       glDrawBuffers( 1, (GLenum[]){ GL_COLOR_ATTACHMENT0 } );
       glClearColor( 0.1f,0.1f,0.2f, 0.0f );
@@ -363,8 +315,8 @@ void render_world_map(void)
          world_instance *world = &_world.preview_instance;
          vg_camera cam;
          v3f dir;
-         dir[0] = -sqrtf(0.5f);
-         dir[2] =  sqrtf(0.5f);
+         dir[0] = -1.0f;
+         dir[2] =  1.0f;
          dir[1] =  1.0f;
          v3_normalize(dir);
 
@@ -383,20 +335,23 @@ void render_world_map(void)
 
          v3_muladds( cam.pos, ofs, 40.0f, cam.pos );
 
-         cam.angles[0] = 0.25f * VG_PIf + ofs[0]*0.1f;
-         cam.angles[1] = 0.25f * VG_PIf + ofs[1]*0.1f;
-         cam.angles[2] = ofs[2]*0.01f;
-         cam.farz = 5000.0f;
-         cam.nearz = 10.0f;
-         cam.fov = 40.0f;
+         v3_negate( dir, dir );
+         v3_angles( dir, cam.angles );
+         v3f v0, v1;
+         v3_sub( centroid, cam.pos, v0 );
+         v3_sub( world->scene_geo.bbx[1], cam.pos, v1 );
+         v3_normalize( v0 );
+         v3_normalize( v1 );
 
-         vg_camera_update_transform( &cam );
-         vg_camera_update_view( &cam );
-         vg_camera_update_projection( &cam, vg.window_x, vg.window_y );
-         vg_camera_finalize( &cam );
-         vg_camera_finalize( &cam );
+         f32 a = v3_dot(v0,v1);
+         cam.fov = acosf( a ) * 45.0f;
 
-         render_world_preview( &cam );
+         cam.angles[0] -= 0.07f*a + ofs[0]*0.1f;
+         cam.angles[1] += 0.03f*a + ofs[1]*0.1f;
+         cam.angles[2] = ofs[2]*0.01f;
+
+         world_map_update_final_camera( &cam );
+         render_world_preview( &world_map.final_cam );
 
          if( world->complete )
          {
@@ -408,7 +363,7 @@ void render_world_map(void)
                v4_copy( route->colour, colour );
                v3_muls( colour, 1.6666f, colour );
                gui_icon_setcolour( colour );
-               respawn_map_draw_icon( &cam, k_gui_icon_rift_run_2d, route->anon.transform.co, 0.5f );
+               respawn_map_draw_icon( &world_map.final_cam, k_gui_icon_rift_run_2d, route->anon.transform.co, 0.5f );
             }
          }
       }
@@ -456,6 +411,553 @@ void render_world_map(void)
    }
 }
 
+void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *allow_back_to_exit )
+{
+   ui_rect title_box = { main_area[2]/2 - 300/2, main_area[1] + 8, 300, 100 };
+
+   ui_rect upper_title, lower_title;
+   ui_split( title_box, k_ui_axis_h, title_box[3]-24, 0, upper_title, lower_title );
+
+   const char *title_text = NULL,
+              *subtitle_text = NULL;
+
+   if( world_map.activity == k_map_activity_local_world )
+   {
+      world_instance *world = &_world.main; 
+
+      world_map.boom_dist = 400.0f;
+
+      if( world_map.sel_spawn )
+      {
+         /* focus camera down onto spawn */
+         v2f pp;
+         respawn_world_to_plane_pos( world_map.sel_spawn->transform.co, pp );
+         v2_lerp( world_map.plane_pos, pp, vg.time_frame_delta*2.0f, world_map.plane_pos );
+         world_map.boom_dist = 200.0f;
+
+         /* Spawn selected UI
+          * --------------------------------------------------------------------------------------------------- */
+
+         if( world_map.spawn_timer > 0.0f )
+         {
+            world_map.spawn_timer -= vg.time_frame_delta/2.0f;
+
+            if( world_map.spawn_timer <= 0.0f )
+            {
+               skaterift.activity = k_skaterift_default;
+               srinput.state = k_input_state_resume;
+               world_map.sel_spawn = NULL;
+            }
+         }
+         else
+         {
+            *allow_back_to_exit = 0;
+
+            ui_px spawn_box_width = 500;
+            ui_rect spawn_box = { main_area[0] + (main_area[2]-spawn_box_width)/2, main_area[1] + 32, 
+                                  spawn_box_width, 100 };
+            ui_fill( ctx, spawn_box, ui_opacity( GUI_COL_DARK, 0.36f ) );
+
+            ctx->font = &vgf_default_title;
+            ui_rect label_box = { spawn_box[0], spawn_box[1] + 8, spawn_box[2], 48 };
+            ui_text( ctx, label_box, "Spawnpoint", 1, k_ui_align_center, ui_colour(ctx,k_ui_yellow) );
+
+            bool spawn_here = 0,
+                 exit_spawn = 0;
+
+            ui_rect no_box = { spawn_box[0] + spawn_box[2]-32, spawn_box[1], 32, 32 };
+            if( menu_button_rect( ctx, no_box, 0, 1, "X" ) )
+            {
+               exit_spawn = 1;
+            }
+
+            ctx->font = &vgf_default_large;
+            ui_rect yes_box = { spawn_box[0]+(spawn_box[2]-100)/2, spawn_box[1]+spawn_box[3]-32, 100, 32 };
+            if( menu_button_rect( ctx, yes_box, vg_input.display_input_method == k_input_method_controller, 1, "Spawn" ) )
+            {
+               spawn_here = 1;
+            }
+
+            if( button_down( k_srbind_maccept ) )
+               spawn_here = 1;
+            if( button_down( k_srbind_mback ) )
+               exit_spawn = 1;
+
+            if( spawn_here )
+            {
+               player__spawn( world_map.sel_spawn );
+               world_map.spawn_timer = 1.0f;
+            }
+            else if( exit_spawn )
+            {
+               world_map.sel_spawn = NULL;
+            }
+         }
+      }
+      else
+      {
+         title_text = af_str( &world->meta.af, world->info.pstr_name );
+         subtitle_text = "Current Location";
+         ctx->font = &vgf_default_title;
+         upper_title[2] = ui_text_line_width(ctx,title_text) + 24;
+         upper_title[0] = main_area[0] + (main_area[2] - upper_title[2])/2;
+
+         /* Update camera input variables based on user input
+          * -------------------------------------------------------------------------------------------- */
+
+         v2f steer;
+         joystick_state( k_srjoystick_steer, steer );
+         v2_normalize_clamp( steer );
+
+         m2x2f rm;
+         m2x2_create_rotation( rm, -0.25f*VG_PIf );
+         m2x2_mulv( rm, steer, steer );
+         v2_muladds( world_map.plane_pos, steer, vg.time_frame_delta * 200.0f, world_map.plane_pos );
+
+         v3f *bbx = world->scene_geo.bbx;
+         v2_minv( (v2f){ bbx[1][0], bbx[1][2] }, world_map.plane_pos, world_map.plane_pos );
+         v2_maxv( (v2f){ bbx[0][0], bbx[0][2] }, world_map.plane_pos, world_map.plane_pos );
+
+         if( vg_input.display_input_method == k_input_method_kbm )
+         {
+            world_map.view_centroid[0] =   ((f32)ctx->mouse[0] / (f32)vg.window_x)*2.0f - 1.0f;
+            world_map.view_centroid[1] = -(((f32)ctx->mouse[1] / (f32)vg.window_y)*2.0f - 1.0f);
+         }
+         else
+         {
+            world_map.view_centroid[0] = 0.0f;
+            world_map.view_centroid[1] = 0.0f;
+         }
+
+         /* draw information about the world's name and option to go up to the galaxy 
+          * ------------------------------------------------------------------------------------------------------ */
+         bool go_to_super = 0;
+         ctx->font = &vgf_default_title;
+         ui_px back_box_size = 48;
+         ui_rect back_box = { upper_title[0] - (back_box_size + 8), title_box[1] + ((title_box[3]-back_box_size)/2), 
+                              back_box_size, back_box_size };
+         if( ui_button_text( ctx, back_box, "<", 1 ) == k_ui_button_click )
+         {
+            go_to_super = 1;
+         }
+
+         if( vg_input.display_input_method == k_input_method_controller )
+         {
+            char buf[32];
+            vg_str helper_text;
+            vg_strnull( &helper_text, buf, 32 );
+            vg_input_string( &helper_text, input_button_list[k_srbind_mhub], 1 );
+            
+            ui_rect helper_label_box = { back_box[0] + (back_box[2]-32)/2, back_box[1] + back_box[3]-4, 32, 32 };
+            ui_fill( ctx, helper_label_box, ui_opacity( GUI_COL_DARK, 0.36f ) );
+            ui_text( ctx, helper_label_box, buf, 1, k_ui_align_middle_center, 0 );
+
+            if( button_down( k_srbind_mhub ) )
+            {
+               audio_lock();
+               audio_oneshot( &audio_ui[3], 1.0f, 0.0f );
+               audio_unlock();
+               go_to_super = 1;
+            }
+         }
+
+         ctx->font = &vgf_default_title;
+         ui_rect super_location_box = { back_box[0] - (120+8), back_box[1], 120, 32 };
+         ui_text( ctx, super_location_box, "Earth", 1, k_ui_align_middle_center, ui_colour( ctx, k_ui_gray ) );
+
+         if( go_to_super )
+         {
+            world_map.activity = k_map_activity_galaxy;
+            menu_update_world_list();
+         }
+
+         /* Draw world completion list
+          * ------------------------------------------------------------------------------------------------------- */
+         if( af_arrcount( &world->ent_region ) )
+         {
+            ui_rect stat_panel = { main_area[0]+main_area[2]-(256+8), main_area[1]+8, 256, main_area[3]-16 };
+            u32 c0 = ui_opacity( GUI_COL_DARK, 0.36f );
+            ui_fill( ctx, stat_panel, c0 );
+
+            ui_rect_pad( stat_panel, (ui_px[2]){8,0} );
+
+            for( u32 i=0; i<af_arrcount( &world->ent_region ); i ++ )
+            {
+               ent_region *region = af_arritm( &world->ent_region, i );
+
+               if( !region->zone_volume )
+                  continue;
+
+               const char *title = af_str( &world->meta.af, region->pstr_title );
+               ctx->font = &vgf_default_large;
+
+               ui_rect title_box;
+               menu_standard_widget( ctx, stat_panel, title_box, 1 );
+               
+               stat_panel[0] += 16;
+               stat_panel[2] -= 16;
+               ctx->font = &vgf_default_small;
+
+               ent_volume *volume = af_arritm(&world->ent_volume,
+                     mdl_entity_id_id(region->zone_volume));
+
+               u32 combined = k_ent_route_flag_achieve_gold | 
+                              k_ent_route_flag_achieve_silver;
+
+               char buf[128];
+               vg_str str;
+
+               for( u32 j=0; j<af_arrcount(&world->ent_route); j ++ )
+               {
+                  ent_route *route = af_arritm(&world->ent_route, j );
+
+                  v3f local;
+                  m4x3_mulv( volume->to_local, route->board_transform[3], local );
+                  if( !((fabsf(local[0]) <= 1.0f) &&
+                        (fabsf(local[1]) <= 1.0f) &&
+                        (fabsf(local[2]) <= 1.0f)) )
+                  {
+                     continue;
+                  }
+
+                  combined &= route->flags;
+
+                  vg_strnull( &str, buf, sizeof(buf) );
+                  vg_strcat( &str, "(Race) " );
+                  vg_strcat( &str, af_str( &world->meta.af, route->pstr_name ));
+
+                  if( route->flags & k_ent_route_flag_achieve_silver )
+                     vg_strcat( &str, " \xb3");
+                  if( route->flags & k_ent_route_flag_achieve_gold )
+                     vg_strcat( &str, "\xb3");
+
+                  ui_rect r;
+                  ui_standard_widget( ctx, stat_panel, r, 1 );
+                  ui_text( ctx, r, buf, 1, k_ui_align_middle_left, 
+                           medal_colour( ctx, route->flags ) );
+               }
+
+               for( u32 j=0; j<af_arrcount(&world->ent_challenge); j ++ )
+               {
+                  ent_challenge *challenge = af_arritm( &world->ent_challenge, j );
+
+                  v3f local;
+                  m4x3_mulv( volume->to_local, challenge->transform.co, local );
+                  if( !((fabsf(local[0]) <= 1.0f) &&
+                        (fabsf(local[1]) <= 1.0f) &&
+                        (fabsf(local[2]) <= 1.0f)) )
+                  {
+                     continue;
+                  }
+
+                  vg_strnull( &str, buf, sizeof(buf) );
+                  vg_strcat( &str, af_str( &world->meta.af,challenge->pstr_alias));
+
+                  u32 flags = 0x00;
+                  if( challenge->status )
+                  {
+                     flags |= k_ent_route_flag_achieve_gold;
+                     flags |= k_ent_route_flag_achieve_silver;
+                     vg_strcat( &str, " \xb3\xb3" );
+                  }
+
+                  combined &= flags;
+
+                  ui_rect r;
+                  ui_standard_widget( ctx, stat_panel, r, 1 );
+                  ui_text( ctx, r, buf, 1, 
+                           k_ui_align_middle_left, medal_colour( ctx, flags ) );
+               }
+
+               stat_panel[0] -= 16;
+               stat_panel[2] += 16;
+
+               u32 title_col = 0;
+               if( combined & k_ent_route_flag_achieve_gold ) 
+                  title_col = ui_colour( ctx, k_ui_yellow );
+               else if( combined & k_ent_route_flag_achieve_silver )
+                  title_col = ui_colour( ctx, k_ui_fg );
+
+               menu_heading( ctx, title_box, title, title_col );
+            }
+         }
+         
+         /* allow selecting of a spawnpoint 
+          * ------------------------------------------------------------------------------------------------------ */
+
+         if( ctx->focused_control_type == k_ui_control_none )
+         {
+            if( world_map.close_spawn )
+            {
+               if( vg_input.display_input_method == k_input_method_kbm )
+               {
+                  if( ui_inside_rect( main_area, ctx->mouse ) )
+                  {
+                     if( ui_click_up(ctx, UI_MOUSE_LEFT) )
+                     {
+                        world_map.sel_spawn = world_map.close_spawn;
+                     }
+                  }
+               }
+               else
+               {
+                  if( button_down( k_srbind_maccept ) )
+                     world_map.sel_spawn = world_map.close_spawn;
+               }
+            }
+         }
+      }
+
+
+#if 0
+      ctx->font = &vgf_default_large;
+      ui_rect title = { vg.window_x/2- 512/2, height+8, 512, 64 };
+
+      ui_px x = 8,
+            y = height+8;
+
+      struct ui_vert *vs = ui_fill( ctx, (ui_rect){ x,y, 0,height }, GUI_COL_DARK );
+
+      char buf[64];
+      vg_str str;
+      vg_strnull( &str, buf, sizeof(buf) );
+
+      world_instance *world = &_world.main;
+      const char *world_name = af_str( &world->meta.af, world->info.pstr_name );
+      vg_strnull( &str, buf, sizeof(buf) );
+      vg_strcat( &str, world_name );
+      
+      ui_px w = ui_text( ctx, (ui_rect){ x+8, y, 1000, height }, buf, 1,
+                         k_ui_align_middle_left, 0 );
+
+      w *= ctx->font->sx;
+      x += w + 16;
+
+      vs[1].co[0] = x + 8;
+      vs[2].co[0] = x;
+
+      x = 8;
+      y += 8 + height;
+
+      vs[2].co[1] = stat_panel[1];
+      vs[3].co[1] = stat_panel[1];
+
+      ui_rect back_button = {0,0,300,32};
+      ui_rect_center( (ui_rect){0,0,vg.window_x,vg.window_y}, back_button );
+      if( ui_button_text( ctx, back_button, "up", 1 ) == k_ui_button_click )
+      {
+         world_map.activity = k_map_activity_
+      }
+#endif
+   }
+   else if( world_map.activity >= k_map_activity_galaxy )
+   {
+      ui_rect panel = { 24, main_area[1]+24, WORKSHOP_PREVIEW_WIDTH+8, main_area[3]-(24+24) };
+      ui_fill( ctx, panel, ui_opacity( GUI_COL_DARK, 0.35f ) );
+
+
+      title_text = menu.clicked_world_name? menu.clicked_world_name: "...";
+      subtitle_text = (menu.clicked_world_reg == _world.main.addon)? "Current Location": NULL;
+
+      ctx->font = &vgf_default_title;
+      upper_title[2] = ui_text_line_width(ctx,title_text) + 24;
+      upper_title[0] = panel[0]+panel[2] + ((main_area[2] - (panel[0]+panel[2])) - upper_title[2])/2;
+      lower_title[0] = panel[0]+panel[2] + 24;
+      lower_title[2] = (main_area[2] - (lower_title[0]+24));
+
+
+      /* planet box
+       * -------------------------------------------------------------------------------------------------------- */
+      ui_rect planet_box;
+      ui_split( panel, k_ui_axis_h, WORKSHOP_PREVIEW_HEIGHT, 8, planet_box, panel );
+
+      planet_box[0] += 4;
+      planet_box[2] = WORKSHOP_PREVIEW_WIDTH;
+      planet_box[3] = WORKSHOP_PREVIEW_HEIGHT;
+      ui_image( ctx, planet_box, &g_render.fb_workshop_preview->attachments[0].id );
+
+      ui_rect planet_box_title;
+      ui_split( planet_box, k_ui_axis_h, 28, 0, planet_box_title, planet_box );
+      ui_fill( ctx, planet_box_title, ui_opacity( GUI_COL_DARK, 0.2f ) );
+      ctx->font = &vgf_default_large;
+      ui_text( ctx, planet_box_title, _superworld_names[world_map.superworld_list_selected], 1, 
+               k_ui_align_middle_center, ui_colour(ctx,k_ui_yellow) );
+
+      ui_px change_w = 48,
+            change_h = 160,
+            change_y = planet_box[1] + (planet_box[3]-80)/2;
+
+      /* << */
+      bool superworld_changed = 0;
+      ui_rect change_box_l = { panel[0], change_y, change_w, change_h };
+      if( world_map.superworld_actual_world < world_map.superworld_list_selected )
+      {
+         ui_rect helper_box = { change_box_l[0], planet_box_title[1]+planet_box_title[3], 300, 24 };
+         ctx->font = &vgf_default_small;
+         ui_text( ctx, helper_box, "<< Current location", 1, k_ui_align_middle_left, ui_colour(ctx,k_ui_yellow) );
+      }  
+      ctx->font = &vgf_default_title;
+      if( menu_button( ctx, change_box_l, 0, world_map.superworld_list_selected > 0, "<" ) )
+      {
+         world_map.superworld_list_selected --;
+         superworld_changed = 1;
+      }
+
+      /* >> */
+      ui_rect change_box_r = { (panel[0]+panel[2]) - change_w, change_y, change_w, change_h };
+      if( world_map.superworld_actual_world > world_map.superworld_list_selected )
+      {
+         ui_rect helper_box = { change_box_r[0] - 300, planet_box_title[1]+planet_box_title[3], 300, 24 };
+         ctx->font = &vgf_default_small;
+         ui_text( ctx, helper_box, "Current location >>", 1, k_ui_align_middle_right, ui_colour(ctx,k_ui_yellow) );
+      }  
+      ctx->font = &vgf_default_title;
+      if( menu_button( ctx, change_box_r, 0, world_map.superworld_list_selected < k_superworld_max-1, ">" ) )
+      {
+         world_map.superworld_list_selected ++;
+         superworld_changed = 1;
+      }
+
+      /* controller input */
+      if( mh ) 
+      {
+         i32 s = world_map.superworld_list_selected - mh;
+         if( s < 0 ) s = 0;
+         if( s > k_superworld_max -1 ) s = k_superworld_max -1;
+
+         if( s != world_map.superworld_list_selected )
+         {
+            world_map.superworld_list_selected = s;
+            superworld_changed = 1;
+         }
+      }
+
+      /* World list
+       * -------------------------------------------------------------------------------------------- */
+      ui_rect title;
+      ui_split( panel, k_ui_axis_h, 28, 0, title, panel );
+      ctx->font = &vgf_default_large;
+      ui_text( ctx, title, "Locations", 1, k_ui_align_middle_center, 0 );
+
+      i32 nominal_count = ((panel[3]+8) / (ctx->font->sy*2 + 8)) - 2;
+      if( nominal_count > MENU_WORLD_MAX_COUNT )
+         nominal_count = MENU_WORLD_MAX_COUNT;
+      if( nominal_count <= 0 )
+         nominal_count = 1;
+
+      if( superworld_changed || (nominal_count != menu.world_list_nominal_display_count) )
+      {
+         menu.world_list_nominal_display_count = nominal_count;
+         menu_update_world_list();
+      }
+
+      i32 *selected_world_index = &menu.world_list_selected_index[ world_map.superworld_list_selected ],
+          page = (*selected_world_index) / menu.world_list_nominal_display_count,
+          page_base = page * menu.world_list_nominal_display_count,
+          max_page = (menu.world_list_total_count-1) / menu.world_list_nominal_display_count;
+
+      i32 R = menu_nav( selected_world_index, mv, menu.world_list_total_count-1 );
+
+
+      if( menu_button( ctx, panel, R == -999, page>0, "\x94" ) )
+      {
+         *selected_world_index = (page-1)*menu.world_list_nominal_display_count;
+         world_map.smooth_warm = 0;
+      }
+
+      for( u32 i=0; i<menu.world_list_display_count; i ++ )
+      {
+         addon_reg *reg = menu.world_list_entries[i];
+
+         bool selected = reg == menu.clicked_world_reg;
+         
+         if( selected )
+         {
+            ui_rect sel_box, _null;
+            ui_split( panel, k_ui_axis_h, ctx->font->sy*2, 8, sel_box, _null );
+            ui_outline( ctx, sel_box, 2, ui_colour(ctx,k_ui_fg), 0 );
+         }
+
+         if( menu_button( ctx, panel, R == (page_base + i), !selected, menu.world_list_names[i] ) )
+         {
+            menu.clicked_world_reg = reg;
+            menu.clicked_world_name = menu.world_list_names[i];
+         }
+      }
+      
+      if( menu_button( ctx, panel, R == -999, page<max_page, "\x96" ) )
+         *selected_world_index = (page+1)*menu.world_list_nominal_display_count;
+
+      if( (*selected_world_index < page_base) || 
+          (*selected_world_index >= (page_base+menu.world_list_nominal_display_count)) )
+      {
+         menu_update_world_list();
+      }
+
+      if( (_world.loader_state == k_world_loader_done) && (menu.clicked_world_reg) )
+      {
+         bool do_load = 0;
+         
+         if( _world.preview_instance.complete ) 
+         {
+            if( _world.preview_instance.addon != menu.clicked_world_reg )
+               do_load = 1;
+         }
+         else
+            do_load = 1;
+
+         if( do_load )
+            skaterift_load_world_start( menu.clicked_world_reg, 1 );
+      }
+
+      ctx->font = &vgf_default_title;
+      ui_px remainder = main_area[2] - (panel[0] + panel[2]),
+            width     = 400,
+            height    = ctx->font->sy*2;
+
+      ui_rect enter_world_box = { panel[0]+panel[2] + (remainder-width)/2, main_area[3] - (height+24), width, height };
+
+      char buf[64];
+      vg_str enter_helper;
+      vg_strnull( &enter_helper, buf, sizeof(buf) );
+      vg_strcat( &enter_helper, "Enter location " );
+      if( vg_input.display_input_method == k_input_method_controller )
+         vg_input_string( &enter_helper, input_button_list[k_srbind_mhub], 1 );
+
+      bool enter_location = 0;
+      if( menu_button( ctx, enter_world_box, 0, menu.clicked_world_reg?1:0, buf ) )
+         enter_location = 1;
+
+      if( button_down( k_srbind_mhub ) )
+         enter_location = 1;
+
+      if( enter_location && menu.clicked_world_reg )
+      {
+         if( menu.clicked_world_reg != _world.main.addon )
+            skaterift_load_world_start( menu.clicked_world_reg, 0 );
+
+         world_map.activity = k_map_activity_local_world;
+         world_map.superworld_actual_world = world_map.superworld_list_selected;
+      }
+   }
+
+   /* Render title & subtitle 
+    * ---------------------------------------------------------------------------------------------------
+    */
+
+   if( title_text )
+   {
+      ctx->font = &vgf_default_title;
+      ui_text( ctx, upper_title, title_text, 1, k_ui_align_middle_center, ui_colour( ctx, k_ui_yellow ) );
+
+      if( subtitle_text )
+      {
+         ctx->font = &vgf_default_large;
+         ui_text( ctx, lower_title, subtitle_text, 1, k_ui_align_middle_center, 0 );
+      }
+   }
+}
+
 void world_map_init(void)
 {
    mdl_context *model = &world_map.superworld_meta;
@@ -469,4 +971,10 @@ void world_map_init(void)
    world_map.superworld_cam.nearz = 0.1f;
    world_map.superworld_cam.farz = 250.0f;
    world_map.superworld_cam.fov = 90.0f;
+   world_map.smoothed_cam.nearz = 0.1f;
+   world_map.smoothed_cam.farz = 250.0f;
+   world_map.smoothed_cam.fov = 90.0f;
+   world_map.final_cam.nearz = 0.1f;
+   world_map.final_cam.farz = 250.0f;
+   world_map.final_cam.fov = 90.0f;
 }
index d78cd773aa87f44845efc50eb3358084932cf456..95dd78212ad759b95d370d038e9967895b2e8617 100644 (file)
@@ -15,12 +15,13 @@ struct world_map
 {
    v2f plane_pos;
    f32 boom_dist;
-   u32 home_select;
 
    ent_spawn *sel_spawn, *close_spawn;
-   vg_camera cam;
+   vg_camera smoothed_cam, final_cam;
 
+   bool smooth_warm;
    bool view_ready;
+   f32 spawn_timer;
 
    enum map_activity
    {
@@ -39,12 +40,13 @@ struct world_map
        superworld_actual_world;
 
    vg_camera superworld_cam;
+   v2f view_centroid;
 }
 extern world_map;
-void world_map_pre_update(void);
+void world_map_gui( ui_context *ctx, ui_rect main_area, i32 mh, i32 mv, bool *allow_back_to_exit );
 void render_world_map(void);
 void world_map_init(void);
-
+void world_map_initialize_view(void);
 
 const char *_superworld_names[] =
 {
index 2206739af2a5835d0f6f3a2f0a2e8ad2af2b600e..e91ee0c08ce7840504eef5061234f42ded69c453 100644 (file)
@@ -1089,14 +1089,16 @@ void render_world( world_instance *world, vg_camera *cam,
                    int stenciled, int viewing_from_gate, 
                    int with_water, int with_cubemaps )
 {
-   if( stenciled ){
+   if( stenciled )
+   {
       glClear( GL_DEPTH_BUFFER_BIT );
       glStencilFunc( GL_EQUAL, 1, 0xFF );
       glStencilMask( 0x00 ); 
       glEnable( GL_CULL_FACE );
       glEnable( GL_STENCIL_TEST );
    }
-   else {
+   else 
+   {
       glStencilMask( 0xFF );
       glStencilFunc( GL_ALWAYS, 1, 0xFF );
       glDisable( GL_STENCIL_TEST );
@@ -1115,7 +1117,8 @@ void render_world( world_instance *world, vg_camera *cam,
    render_world_foliage( world, cam );
    render_terrain( world, cam );
 
-   if( !viewing_from_gate ){
+   if( !viewing_from_gate )
+   {
 #if 0
       world_entity_focus_render();
 #endif
@@ -1140,14 +1143,16 @@ void render_world( world_instance *world, vg_camera *cam,
       }
    }
 
-   if( !viewing_from_gate ){
+   if( !viewing_from_gate )
+   {
       f32 greyout = 0.0f;
 #if 0
       if( mdl_entity_id_type(_world.focused_entity) == k_ent_challenge )
          greyout = _world.focus_strength;
 #endif
 
-      if( greyout > 0.0f ){
+      if( greyout > 0.0f )
+      {
          glDrawBuffers( 1, (GLenum[]){ GL_COLOR_ATTACHMENT0 } );
          glEnable(GL_BLEND);
          glDisable(GL_DEPTH_TEST);
@@ -1269,7 +1274,7 @@ void render_world_override( world_instance *world,
    v4f uPlayerPos, uSpawnPos;
    v4_zero( uPlayerPos );
    v4_zero( uSpawnPos );
-   v3_copy( (v3f){0,0,0}, uPlayerPos );
+   v3_copy( localplayer.rb.co, uPlayerPos );
    
    if( dest_spawn && (v3_dist2(dest_spawn->transform.co,uPlayerPos) > 0.1f) )
       v3_copy( dest_spawn->transform.co, uSpawnPos );