8 #include "ent_miniworld.h"
12 #include "control_overlay.h"
14 #include "shaders/model_menu.h"
16 struct global_menu menu
= { .skip_starter
= 0 };
18 void menu_at_begin(void)
20 if( menu
.skip_starter
) return;
22 skaterift
.activity
= k_skaterift_menu
;
23 menu
.page
= k_menu_page_starter
;
28 vg_console_reg_var( "skip_starter_menu", &menu
.skip_starter
,
29 k_var_dtype_i32
, VG_VAR_PERSISTENT
);
30 vg_tex2d_load_qoi_async_file( "textures/prem.qoi",
31 VG_TEX2D_CLAMP
|VG_TEX2D_NOMIP
|VG_TEX2D_NEAREST
,
35 void menu_open( enum menu_page page
)
37 skaterift
.activity
= k_skaterift_menu
;
39 if( page
!= k_menu_page_any
)
45 bool menu_viewing_map(void)
47 return (skaterift
.activity
== k_skaterift_menu
) &&
48 (menu
.page
== k_menu_page_main
) &&
49 (menu
.main_index
== k_menu_main_map
);
52 static void menu_decor_select( ui_context
*ctx
, ui_rect rect
)
54 ui_px b
= ctx
->font
->sx
, hb
= b
/2;
55 ui_rect a0
= { rect
[0] - 20 - hb
, rect
[1] + rect
[3]/2 - hb
, b
,b
},
56 a1
= { rect
[0] + rect
[2] + 20 + hb
, rect
[1] + rect
[3]/2 - hb
, b
,b
};
58 ui_text( ctx
, a0
, "\x95", 1, k_ui_align_middle_center
, 0 );
59 ui_text( ctx
, a1
, "\x93", 1, k_ui_align_middle_center
, 0 );
62 static void menu_standard_widget( ui_context
*ctx
,
63 ui_rect inout_panel
, ui_rect rect
, ui_px s
)
65 ui_split( inout_panel
, k_ui_axis_h
, ctx
->font
->sy
*s
*2,
66 8, rect
, inout_panel
);
69 static bool menu_slider( ui_context
*ctx
,
70 ui_rect inout_panel
, bool select
, const char *label
,
71 const f32 disp_min
, const f32 disp_max
, f32
*value
,
75 menu_standard_widget( ctx
, inout_panel
, rect
, 1 );
76 ui_label( ctx
, rect
, label
, 1, 8, box
);
79 enum ui_button_state state
= ui_slider_base( ctx
, box
, 0, 1, value
, &t
),
81 k_ui_button_holding_inside
|
82 k_ui_button_holding_outside
|
84 mask_brighter
= mask_using
| k_ui_button_hover
;
86 if( vg_input
.display_input_method
== k_input_method_controller
)
90 f32 m
= axis_state( k_sraxis_mbrowse_h
);
93 *value
+= m
* vg
.time_frame_delta
* (1.0f
/2.0f
);
94 *value
= vg_clampf( *value
, 0, 1 );
97 menu_decor_select( ctx
, rect
);
98 state
|= k_ui_button_hover
;
101 state
= k_ui_button_none
;
104 ui_rect line
= { box
[0], box
[1], t
* (f32
)box
[2], box
[3] };
105 ui_fill( ctx
, line
, state
&mask_brighter
? GUI_COL_ACTIVE
: GUI_COL_NORM
);
106 ui_fill( ctx
, (ui_rect
){ box
[0]+line
[2], box
[1], box
[2]-line
[2], box
[3] },
109 ui_outline( ctx
, box
, 1, state
? GUI_COL_HI
: GUI_COL_ACTIVE
, 0 );
110 ui_slider_text( ctx
, box
,
111 format
, disp_min
+ (*value
)*( disp_max
-disp_min
) );
113 return (state
& mask_using
) && 1;
116 static bool menu_button( ui_context
*ctx
,
117 ui_rect inout_panel
, bool select
, const char *text
)
120 menu_standard_widget( ctx
, inout_panel
, rect
, 1 );
122 enum ui_button_state state
= k_ui_button_none
;
124 if( vg_input
.display_input_method
== k_input_method_controller
)
128 menu_decor_select( ctx
, rect
);
130 if( button_down( k_srbind_maccept
) )
131 state
= k_ui_button_click
;
136 state
= ui_button_base( ctx
, rect
);
140 if( state
== k_ui_button_click
)
142 ui_fill( ctx
, rect
, GUI_COL_DARK
);
144 else if( state
== k_ui_button_holding_inside
)
146 ui_fill( ctx
, rect
, GUI_COL_DARK
);
148 else if( state
== k_ui_button_holding_outside
)
150 ui_fill( ctx
, rect
, GUI_COL_DARK
);
151 ui_outline( ctx
, rect
, 1, GUI_COL_CLICK
, 0 );
153 else if( state
== k_ui_button_hover
)
155 ui_fill( ctx
, rect
, GUI_COL_ACTIVE
);
156 ui_outline( ctx
, rect
, 1, GUI_COL_CLICK
, 0 );
160 ui_fill( ctx
, rect
, select
? GUI_COL_ACTIVE
: GUI_COL_NORM
);
162 ui_outline( ctx
, rect
, 1, GUI_COL_HI
, 0 );
165 ui_text( ctx
, rect
, text
, 1, k_ui_align_middle_center
, 0 );
167 if( state
== k_ui_button_click
)
170 audio_oneshot( &audio_ui
[0], 1.0f
, 0.0f
);
177 static bool menu_checkbox( ui_context
*ctx
, ui_rect inout_panel
, bool select
,
178 const char *str_label
, i32
*data
)
180 ui_rect rect
, label
, box
;
181 menu_standard_widget( ctx
, inout_panel
, rect
, 1 );
183 ui_split( rect
, k_ui_axis_v
, -rect
[3], 0, label
, box
);
184 ui_text( ctx
, label
, str_label
, ctx
->scale
, k_ui_align_middle_left
, 0 );
186 enum ui_button_state state
= k_ui_button_none
;
188 if( vg_input
.display_input_method
== k_input_method_controller
)
192 menu_decor_select( ctx
, rect
);
194 if( button_down( k_srbind_maccept
) )
196 *data
= (*data
) ^ 0x1;
197 state
= k_ui_button_click
;
203 state
= ui_checkbox_base( ctx
, box
, data
);
207 if( state
== k_ui_button_holding_inside
)
209 ui_fill( ctx
, box
, GUI_COL_ACTIVE
);
210 ui_outline( ctx
, box
, 1, GUI_COL_CLICK
, 0 );
212 else if( state
== k_ui_button_holding_outside
)
214 ui_fill( ctx
, box
, GUI_COL_DARK
);
215 ui_outline( ctx
, box
, 1, GUI_COL_CLICK
, 0 );
217 else if( state
== k_ui_button_hover
)
219 ui_fill( ctx
, box
, GUI_COL_ACTIVE
);
220 ui_outline( ctx
, box
, 1, GUI_COL_HI
, 0 );
224 ui_fill( ctx
, box
, select
? GUI_COL_ACTIVE
: GUI_COL_DARK
);
225 ui_outline( ctx
, box
, 1, select
? GUI_COL_HI
: GUI_COL_NORM
, 0 );
230 ui_rect_pad( box
, (ui_px
[2]){8,8} );
231 ui_fill( ctx
, box
, GUI_COL_HI
);
234 if( state
== k_ui_button_click
)
237 audio_oneshot( &audio_ui
[0], 1.0f
, 0.0f
);
244 static void menu_heading( ui_context
*ctx
,
245 ui_rect inout_panel
, const char *label
, u32 colour
)
248 menu_standard_widget( ctx
, inout_panel
, rect
, 1 );
253 u32 c0
= ui_opacity( GUI_COL_DARK
, 0.36f
),
254 c1
= ui_opacity( GUI_COL_DARK
, 0.5f
);
256 struct ui_vert
*vs
= ui_fill( ctx
, rect
, c0
);
262 ui_text( ctx
, rect
, label
, 1, k_ui_align_middle_center
, 1 );
265 ui_text( ctx
, rect
, label
, 1, k_ui_align_middle_center
, colour
? colour
:
266 ui_colour(ctx
, k_ui_blue
+k_ui_brighter
) );
269 static u32
medal_colour( ui_context
*ctx
, u32 flags
)
271 if( flags
& k_ent_route_flag_achieve_gold
)
272 return ui_colour( ctx
, k_ui_yellow
);
273 else if( flags
& k_ent_route_flag_achieve_silver
)
274 return ui_colour( ctx
, k_ui_fg
);
278 static i32
menu_nav( i32
*p_row
, int mv
, i32 max
)
280 i32 row_prev
= *p_row
;
282 if( mv
< 0 ) *p_row
= vg_min( max
, (*p_row
) +1 );
283 if( mv
> 0 ) *p_row
= vg_max( 0, (*p_row
) -1 );
285 if( *p_row
!= row_prev
)
288 audio_oneshot( &audio_ui
[3], 1.0f
, 0.0f
);
295 static void menu_try_find_cam( i32 id
)
297 world_instance
*world
= &world_static
.instances
[0];
298 for( u32 i
=0; i
<mdl_arrcount(&world
->ent_npc
); i
++ )
300 ent_npc
*fnpc
= mdl_arritm( &world
->ent_npc
, i
);
301 if( (fnpc
->id
== 50) && (fnpc
->context
== id
) )
303 if( mdl_entity_id_type(fnpc
->camera
) == k_ent_camera
)
305 u32 index
= mdl_entity_id_id( fnpc
->camera
);
306 menu
.bg_cam
= mdl_arritm( &world
->ent_camera
, index
);
313 static void menu_link_modal( const char *url
)
317 /* Only reset the choice of browser if 'No' was selected. */
318 if( menu
.web_choice
== 2 )
322 void menu_gui( ui_context
*ctx
)
324 if( button_down( k_srbind_mopen
) )
326 if( skaterift
.activity
== k_skaterift_default
)
328 menu_open( k_menu_page_main
);
333 if( skaterift
.activity
!= k_skaterift_menu
)
339 /* get buttons inputs
340 * -------------------------------------------------------------------*/
341 int ml
= button_press( k_srbind_mleft
),
342 mr
= button_press( k_srbind_mright
),
343 mu
= button_press( k_srbind_mup
),
344 md
= button_press( k_srbind_mdown
),
347 enter
= button_down( k_srbind_maccept
);
350 u8 lb_down
= 0, rb_down
= 0;
351 vg_exec_input_program( k_vg_input_type_button_u8
,
353 vg_joy_button
, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
, vg_end
355 vg_exec_input_program( k_vg_input_type_button_u8
,
357 vg_joy_button
, SDL_CONTROLLER_BUTTON_LEFTSHOULDER
, vg_end
360 int mtab
= (i32
)rb_down
- (i32
)lb_down
;
362 if( menu
.repeater
> 0.0f
)
364 menu
.repeater
-= vg_minf( vg
.time_frame_delta
, 0.5f
);
371 if( mv
|| mh
|| mtab
)
372 menu
.repeater
+= 0.2f
;
375 if( vg_input
.display_input_method
== k_input_method_kbm
)
377 ui_capture_mouse(ctx
, 1);
380 if( skaterift
.activity
!= k_skaterift_menu
) return;
385 menu_try_find_cam( 3 );
387 ui_rect panel
= { 0,0, 800, 200 },
388 screen
= { 0,0, vg
.window_x
,vg
.window_y
};
389 ui_rect_center( screen
, panel
);
390 ui_fill( ctx
, panel
, GUI_COL_DARK
);
391 ui_outline( ctx
, panel
, 1, GUI_COL_NORM
, 0 );
392 ui_rect_pad( panel
, (ui_px
[]){8,8} );
395 ui_split( panel
, k_ui_axis_h
, 28*2, 0, title
, panel
);
396 ctx
->font
= &vgf_default_title
;
397 ui_text( ctx
, title
, "Open Link?", 1, k_ui_align_middle_center
, 0 );
399 ui_split( panel
, k_ui_axis_h
, 28, 0, title
, panel
);
400 ctx
->font
= &vgf_default_large
;
401 ui_text( ctx
, title
, menu
.web_link
, 1, k_ui_align_middle_center
, 0 );
403 ui_rect end
= { panel
[0], panel
[1] + panel
[3] - 48, panel
[2], 48 };
406 ui_split_ratio( end
, k_ui_axis_v
, 2.0/3.0, 2, a
, c
);
407 ui_split_ratio( a
, k_ui_axis_v
, 1.0/2.0, 2, a
, b
);
409 i32 R
= menu_nav( &menu
.web_choice
, mh
, 2 );
411 if( menu_button( ctx
, a
, R
==0, "Steam Overlay" ) )
415 ISteamFriends
*hSteamFriends
= SteamAPI_SteamFriends();
416 SteamAPI_ISteamFriends_ActivateGameOverlayToWebPage( hSteamFriends
,
418 k_EActivateGameOverlayToWebPageMode_Default
);
419 menu
.web_link
= NULL
;
423 if( menu_button( ctx
, b
, R
==1, "Web Browser" ) )
427 vg_strnull( &str
, buf
, sizeof(buf
) );
429 vg_strcat( &str
, "start " );
431 vg_strcat( &str
, "xdg-open " );
433 vg_strcat( &str
, menu
.web_link
);
435 if( vg_strgood(&str
) )
438 menu
.web_link
= NULL
;
441 if( menu_button( ctx
, c
, R
==2, "No" ) || button_down( k_srbind_mback
) )
444 audio_oneshot( &audio_ui
[3], 1.0f
, 0.0f
);
446 menu
.web_link
= NULL
;
453 if( vg
.settings_open
)
455 if( button_down( k_srbind_mback
) )
458 audio_oneshot( &audio_ui
[3], 1.0f
, 0.0f
);
461 srinput
.state
= k_input_state_resume
;
467 if( menu
.page
== k_menu_page_credits
)
469 ui_rect panel
= { 0,0, 600, 400 },
470 screen
= { 0,0, vg
.window_x
,vg
.window_y
};
471 ui_rect_center( screen
, panel
);
472 ui_fill( ctx
, panel
, GUI_COL_DARK
);
473 ui_outline( ctx
, panel
, 1, GUI_COL_NORM
, 0 );
474 ui_rect_pad( panel
, (ui_px
[]){8,8} );
477 ui_split( panel
, k_ui_axis_h
, 28*2, 0, title
, panel
);
478 ctx
->font
= &vgf_default_title
;
479 ui_text( ctx
, title
, "Skate Rift - Credits",
480 1, k_ui_align_middle_center
, 0 );
482 ui_split( panel
, k_ui_axis_h
, 28, 0, title
, panel
);
483 ctx
->font
= &vgf_default_large
;
485 "Mt.Zero Software", 1, k_ui_align_middle_center
, 0 );
487 ui_split( panel
, k_ui_axis_h
, 8, 0, title
, panel
);
488 ui_split( panel
, k_ui_axis_h
, 28*2, 0, title
, panel
);
489 ctx
->font
= &vgf_default_title
;
490 ui_text( ctx
, title
, "Free Software", 1, k_ui_align_middle_center
, 0 );
492 ui_split( panel
, k_ui_axis_h
, 8, 0, title
, panel
);
493 ctx
->font
= &vgf_default_large
;
495 "Sam Lantinga - SDL2 - libsdl.org\n"
496 "Hunter WB - Anyascii\n"
497 "David Herberth - GLAD\n"
498 "Dominic Szablewski - QOI - qoiformat.org\n"
499 "Sean Barrett - stb_image, stb_vorbis,\n"
501 "Khronos Group - OpenGL\n"
502 , 1, k_ui_align_left
, 0 );
504 ui_rect end
= { panel
[0], panel
[1] + panel
[3] - 64, panel
[2], 64 };
506 if( menu_button( ctx
, end
, 1, "Back" ) || button_down( k_srbind_mback
) )
508 menu
.page
= k_menu_page_main
;
513 else if( menu
.page
== k_menu_page_starter
)
515 i32 R
= menu_nav( &menu
.intro_row
, mv
, 3 );
516 ui_rect panel
= { 0,0, 600, 400 },
517 screen
= { 0,0, vg
.window_x
,vg
.window_y
};
518 ui_rect_center( screen
, panel
);
519 ui_fill( ctx
, panel
, ui_opacity( GUI_COL_DARK
, 0.35f
) );
520 ui_outline( ctx
, panel
, 1, GUI_COL_NORM
, 0 );
521 ui_rect_pad( panel
, (ui_px
[]){8,8} );
524 ui_split( panel
, k_ui_axis_h
, 28*2, 0, title
, panel
);
525 ctx
->font
= &vgf_default_title
;
527 "Welcome to Skate Rift", 1, k_ui_align_middle_center
, 0 );
529 ui_split( panel
, k_ui_axis_h
, 28, 0, title
, panel
);
530 ctx
->font
= &vgf_default_large
;
532 menu_checkbox( ctx
, panel
, R
== 0,
533 "Show controls overlay (good for new players)",
534 &control_overlay
.enabled
);
535 menu_checkbox( ctx
, panel
, R
== 1, "Auto connect to global server",
536 &network_client
.auto_connect
);
538 ui_rect end
= { panel
[0], panel
[1] + panel
[3] - 100, panel
[2], 100 };
539 menu_checkbox( ctx
, end
, R
== 2,
540 "Don't show this again", &menu
.skip_starter
);
541 if( menu_button( ctx
, end
, R
== 3, "OK" ) )
543 menu
.page
= k_menu_page_main
;
544 skaterift
.activity
= k_skaterift_default
;
547 menu_try_find_cam( 3 );
550 else if( menu
.page
== k_menu_page_premium
)
552 i32 R
= menu_nav( &menu
.prem_row
, mh
, 1 );
553 ui_rect panel
= { 0,0, 600, 400+240 },
554 screen
= { 0,0, vg
.window_x
,vg
.window_y
};
555 ui_rect_center( screen
, panel
);
556 ui_fill( ctx
, panel
, ui_opacity( GUI_COL_DARK
, 0.35f
) );
557 ui_outline( ctx
, panel
, 1, GUI_COL_NORM
, 0 );
558 ui_rect_pad( panel
, (ui_px
[]){8,8} );
561 ui_split( panel
, k_ui_axis_h
, 28*2, 0, title
, panel
);
562 ctx
->font
= &vgf_default_title
;
563 ui_text( ctx
, title
, "Content is in the full game.",
564 1, k_ui_align_middle_center
, 0 );
566 ui_split( panel
, k_ui_axis_h
, 28, 0, title
, panel
);
567 ctx
->font
= &vgf_default_large
;
570 ui_split( panel
, k_ui_axis_h
, 456, 0, img
, panel
);
571 ui_image( ctx
, img
, &menu
.prem_tex
);
573 ui_rect end
= { panel
[0], panel
[1] + panel
[3] - 48, panel
[2], 48 }, a
,b
;
574 ui_split_ratio( end
, k_ui_axis_v
, 0.5f
, 2, a
, b
);
576 if( menu_button( ctx
, a
, R
== 0, "Store Page" ) )
579 SteamAPI_ISteamFriends_ActivateGameOverlayToStore(
580 SteamAPI_SteamFriends(), 2103940, k_EOverlayToStoreFlag_None
);
583 if( menu_button( ctx
, b
, R
== 1, "Nah" ) || button_down( k_srbind_mback
) )
586 audio_oneshot( &audio_ui
[3], 1.0f
, 0.0f
);
588 skaterift
.activity
= k_skaterift_default
;
596 * -------------------------------------------------------------------*/
598 ctx
->font
= &vgf_default_title
;
599 ui_px height
= ctx
->font
->ch
+ 16;
600 ui_rect topbar
= { 0, 0, vg
.window_x
, height
};
602 const char *opts
[] = {
603 [k_menu_main_main
] = "Menu",
604 [k_menu_main_map
] = "Map",
605 [k_menu_main_settings
] = "Settings",
606 [k_menu_main_guide
] = "Guides"
611 menu
.main_index
+= mtab
;
613 if( menu
.main_index
== -1 )
616 if( menu
.main_index
== vg_list_size(opts
) )
620 audio_oneshot( &audio_ui
[3], 1.0f
, 0.0f
);
624 ui_px x
= 0, spacer
= 8;
625 for( u32 draw
=0; draw
<2; draw
++ )
627 if( vg_input
.display_input_method
== k_input_method_controller
)
631 ui_rect inf_lb
= { x
, 0, 32, height
};
632 ui_fill( ctx
, inf_lb
, lb_down
? GUI_COL_NORM
: GUI_COL_NORM
);
633 ui_text( ctx
, inf_lb
, "\x91", 1, k_ui_align_middle_center
, 0 );
638 for( i32 i
=0; i
<vg_list_size(opts
); i
++ )
640 ui_rect box
= { x
, 0, ui_text_line_width(ctx
, opts
[i
]) + 32, height
};
644 enum ui_button_state state
= ui_button_base( ctx
, box
);
645 if( state
== k_ui_button_click
)
647 ui_fill( ctx
, box
, GUI_COL_DARK
);
650 else if( state
== k_ui_button_holding_inside
)
652 ui_fill( ctx
, box
, GUI_COL_DARK
);
654 else if( state
== k_ui_button_holding_outside
)
656 ui_fill( ctx
, box
, GUI_COL_DARK
);
657 ui_outline( ctx
, box
, 1, GUI_COL_CLICK
, 0 );
659 else if( state
== k_ui_button_hover
)
661 ui_fill( ctx
, box
, GUI_COL_NORM
);
662 ui_outline( ctx
, box
, 1, GUI_COL_ACTIVE
, 0 );
666 i
==menu
.main_index
? GUI_COL_ACTIVE
: GUI_COL_NORM
);
668 ui_text( ctx
, box
, opts
[i
], 1, k_ui_align_middle_center
, 0 );
671 x
+= box
[2] + spacer
;
674 if( vg_input
.display_input_method
== k_input_method_controller
)
678 ui_rect inf_rb
= { x
, 0, 32, height
};
679 ui_fill( ctx
, inf_rb
, rb_down
? GUI_COL_NORM
: GUI_COL_NORM
);
680 ui_text( ctx
, inf_rb
, "\x92", 1, k_ui_align_middle_center
, 0 );
687 (ui_rect
){ x
+8,0, vg
.window_x
-(x
+8),height
}, GUI_COL_NORM
);
690 x
= vg
.window_x
/2 - x
/2;
692 (ui_rect
){ 0, 0, x
-8, height
}, GUI_COL_NORM
);
696 if( menu
.main_index
== k_menu_main_map
)
699 ctx
->font
= &vgf_default_large
;
700 ui_rect title
= { vg
.window_x
/2- 512/2, height
+8, 512, 64 };
706 ui_fill( ctx
, (ui_rect
){ x
,y
, 0,height
},
707 world_static
.active_instance
? GUI_COL_DARK
: GUI_COL_ACTIVE
);
711 vg_strnull( &str
, buf
, sizeof(buf
) );
712 vg_strcat( &str
, "Hub World" );
714 if( world_static
.active_instance
)
716 vg_strcat( &str
, " (" );
717 vg_input_string( &str
, input_button_list
[k_srbind_mhub
], 1 );
718 vg_strcatch( &str
, '\x06' );
719 vg_strcatch( &str
, '\x00' );
720 vg_strcat( &str
, "\x1B[0m)" );
723 ui_px w
= ui_text( ctx
, (ui_rect
){ x
+8, y
, 1000, height
}, buf
, 1,
724 k_ui_align_middle_left
, 0 );
733 world_instance
*world
= &world_static
.instances
[1];
734 if( world
->status
== k_world_status_loaded
)
736 const char *world_name
=
737 mdl_pstr( &world
->meta
, world
->info
.pstr_name
);
739 vg_strnull( &str
, buf
, sizeof(buf
) );
740 vg_strcat( &str
, world_name
);
742 if( !world_static
.active_instance
&&
743 (vg_input
.display_input_method
== k_input_method_controller
) )
745 vg_strcat( &str
, " (" );
746 vg_input_string( &str
, input_button_list
[k_srbind_mhub
], 1 );
747 vg_strcatch( &str
, '\x06' );
748 vg_strcatch( &str
, '\x00' );
749 vg_strcat( &str
, "\x1B[0m)" );
752 vs
= ui_fill( ctx
, (ui_rect
){ x
,y
, 1000,height
},
753 world_static
.active_instance
? GUI_COL_ACTIVE
: GUI_COL_DARK
);
754 w
= ui_text( ctx
, (ui_rect
){ x
+16,y
, 1000,height
}, buf
,
755 1, k_ui_align_middle_left
, 0 );
757 w
= w
*ctx
->font
->sx
+ 8*3;
760 if( button_down( k_srbind_mhub
) ||
761 ui_button_base( ctx
, (ui_rect
){0,y
,x
,height
} ) == k_ui_button_click
)
763 world_switch_instance( world_static
.active_instance
^ 0x1 );
764 skaterift
.activity
= k_skaterift_default
;
765 world_map
.view_ready
= 0;
776 if( world_static
.active_instance
)
778 ui_rect stat_panel
= { x
,y
, 256,vg
.window_y
-y
};
779 u32 c0
= ui_opacity( GUI_COL_DARK
, 0.36f
);
780 struct ui_vert
*vs
= ui_fill( ctx
, stat_panel
, c0
);
782 ui_rect_pad( stat_panel
, (ui_px
[2]){8,0} );
784 for( u32 i
=0; i
<mdl_arrcount( &world
->ent_region
); i
++ )
786 ent_region
*region
= mdl_arritm( &world
->ent_region
, i
);
788 if( !region
->zone_volume
)
791 const char *title
= mdl_pstr( &world
->meta
, region
->pstr_title
);
792 ctx
->font
= &vgf_default_large
;
795 menu_standard_widget( ctx
, stat_panel
, title_box
, 1 );
799 ctx
->font
= &vgf_default_small
;
801 ent_volume
*volume
= mdl_arritm(&world
->ent_volume
,
802 mdl_entity_id_id(region
->zone_volume
));
804 u32 combined
= k_ent_route_flag_achieve_gold
|
805 k_ent_route_flag_achieve_silver
;
810 for( u32 j
=0; j
<mdl_arrcount(&world
->ent_route
); j
++ )
812 ent_route
*route
= mdl_arritm(&world
->ent_route
, j
);
815 m4x3_mulv( volume
->to_local
, route
->board_transform
[3], local
);
816 if( !((fabsf(local
[0]) <= 1.0f
) &&
817 (fabsf(local
[1]) <= 1.0f
) &&
818 (fabsf(local
[2]) <= 1.0f
)) )
823 combined
&= route
->flags
;
825 vg_strnull( &str
, buf
, sizeof(buf
) );
826 vg_strcat( &str
, "(Race) " );
827 vg_strcat( &str
, mdl_pstr(&world
->meta
, route
->pstr_name
));
829 if( route
->flags
& k_ent_route_flag_achieve_silver
)
830 vg_strcat( &str
, " \xb3");
831 if( route
->flags
& k_ent_route_flag_achieve_gold
)
832 vg_strcat( &str
, "\xb3");
835 ui_standard_widget( ctx
, stat_panel
, r
, 1 );
836 ui_text( ctx
, r
, buf
, 1, k_ui_align_middle_left
,
837 medal_colour( ctx
, route
->flags
) );
840 for( u32 j
=0; j
<mdl_arrcount(&world
->ent_challenge
); j
++ )
842 ent_challenge
*challenge
= mdl_arritm( &world
->ent_challenge
, j
);
845 m4x3_mulv( volume
->to_local
, challenge
->transform
.co
, local
);
846 if( !((fabsf(local
[0]) <= 1.0f
) &&
847 (fabsf(local
[1]) <= 1.0f
) &&
848 (fabsf(local
[2]) <= 1.0f
)) )
853 vg_strnull( &str
, buf
, sizeof(buf
) );
854 vg_strcat( &str
, mdl_pstr(&world
->meta
, challenge
->pstr_alias
));
857 if( challenge
->status
)
859 flags
|= k_ent_route_flag_achieve_gold
;
860 flags
|= k_ent_route_flag_achieve_silver
;
861 vg_strcat( &str
, " \xb3\xb3" );
867 ui_standard_widget( ctx
, stat_panel
, r
, 1 );
868 ui_text( ctx
, r
, buf
, 1,
869 k_ui_align_middle_left
, medal_colour( ctx
, flags
) );
876 if( combined
& k_ent_route_flag_achieve_gold
)
877 title_col
= ui_colour( ctx
, k_ui_yellow
);
878 else if( combined
& k_ent_route_flag_achieve_silver
)
879 title_col
= ui_colour( ctx
, k_ui_fg
);
881 menu_heading( ctx
, title_box
, title
, title_col
);
884 vs
[2].co
[1] = stat_panel
[1];
885 vs
[3].co
[1] = stat_panel
[1];
890 if( button_down( k_srbind_mback
) )
893 audio_oneshot( &audio_ui
[3], 1.0f
, 0.0f
);
895 skaterift
.activity
= k_skaterift_default
;
899 ui_rect list0
= { vg
.window_x
/2 - 512/2, height
+32,
900 512, vg
.window_y
-height
-64 }, list
;
901 rect_copy( list0
, list
);
902 ui_rect_pad( list
, (ui_px
[2]){8,8} );
905 * -------------------------------------------------------------------*/
907 if( menu
.main_index
== k_menu_main_main
)
909 i32 R
= menu_nav( &menu
.main_row
, mv
, 2 );
911 if( menu_button( ctx
, list
, R
== 0, "Resume" ) )
913 skaterift
.activity
= k_skaterift_default
;
917 if( menu_button( ctx
, list
, R
== 1, "Credits" ) )
919 menu
.page
= k_menu_page_credits
;
922 ui_rect end
= { list
[0], list
[1]+list
[3]-64, list
[2], 72 };
923 if( menu_button( ctx
, end
, R
== 2, "Quit Game" ) )
925 vg
.window_should_close
= 1;
928 else if( menu
.main_index
== k_menu_main_settings
)
930 ui_fill( ctx
, list0
, ui_opacity( GUI_COL_DARK
, 0.36f
) );
931 ui_outline( ctx
, list0
, 1, GUI_COL_NORM
, 0 );
932 i32 R
= menu_nav( &menu
.settings_row
, mv
, 8 );
934 ctx
->font
= &vgf_default_large
;
936 menu_heading( ctx
, list
, "Game", 0 );
937 menu_checkbox( ctx
, list
, R
== 0, "Show controls overlay",
938 &control_overlay
.enabled
);
939 menu_checkbox( ctx
, list
, R
== 1, "Auto connect to global server",
940 &network_client
.auto_connect
);
942 menu_heading( ctx
, list
, "Audio/Video", 0 );
943 menu_slider( ctx
, list
, R
== 2, "Volume", 0, 100,
944 &vg_audio
.external_global_volume
, "%.f%%" );
945 menu_slider( ctx
, list
, R
== 3, "Resolution", 0, 100,
946 &k_render_scale
, "%.f%%" );
947 menu_checkbox( ctx
, list
, R
== 4, "Motion Blur", &k_blur_effect
);
949 menu_heading( ctx
, list
, "Camera", 0 );
950 menu_slider( ctx
, list
, R
== 5, "Fov", 97, 135,
951 &k_fov
, "%.1f\xb0" );
952 menu_slider( ctx
, list
, R
== 6, "Cam Height", -0.4f
, +1.4f
,
953 &k_cam_height
, vg_lerpf(-0.4f
,1.4f
,k_cam_height
)>=0.0f
?
955 menu_checkbox( ctx
, list
, R
== 7, "Invert Y Axis", &k_invert_y
);
958 ui_rect end
= { list
[0], list
[1]+list
[3]-64, list
[2], 72 };
959 ctx
->font
= &vgf_default_small
;
960 menu_heading( ctx
, end
, "Advanced", 0 );
961 if( menu_button( ctx
, end
, R
== 8, "Open Engine Settings" ) )
966 else if( menu
.main_index
== k_menu_main_guide
)
972 marg
= list0
[0]+list0
[2],
973 pw
= vg
.window_x
- marg
,
974 infx
= pw
/2 - w
/2 + marg
;
975 ui_rect inf
= { infx
, height
+32, w
, 800 };
977 struct ui_vert
*vs
= NULL
;
979 if( menu
.guide_sel
&& (menu
.guide_sel
<= 3) )
981 vs
= ui_fill( ctx
, inf
, ui_opacity( GUI_COL_DARK
, 0.20f
) );
982 ui_rect_pad( inf
, (ui_px
[]){8,8} );
985 ui_fill( ctx
, list0
, ui_opacity( GUI_COL_DARK
, 0.36f
) );
986 ui_outline( ctx
, list0
, 1, GUI_COL_NORM
, 0 );
987 i32 R
= menu_nav( &menu
.guides_row
, mv
, 6 );
989 ctx
->font
= &vgf_default_large
;
991 menu_heading( ctx
, list
, "Info", 0 );
992 if( menu
.guide_sel
== 1 )
994 menu_try_find_cam( 1 );
997 ui_split( inf
, k_ui_axis_h
, 28*2, 0, title
, inf
);
998 ctx
->font
= &vgf_default_title
;
1000 title
, "Where to go", 1, k_ui_align_middle_center
, 0 );
1002 ui_split( inf
, k_ui_axis_h
, 28, 0, title
, inf
);
1003 ctx
->font
= &vgf_default_large
;
1005 "Visit the sandcastles built by John Cockroach to be\n"
1006 "transported into the real location. Use the map in the\n"
1007 "menu to return back this hub island.\n"
1009 "You can begin training at the Volcano Island, where you\n"
1010 "can learn movement skills. Then travel to Mt.Zero Island\n"
1011 "or Bort Downtown to test them out. Finally the most\n"
1012 "challenging course can be taken on at the Valley.\n"
1014 "Also visit the Steam Workshop for community made\n"
1015 "locations to skate!"
1016 , 1, k_ui_align_left
, 0 );
1018 vs
[2].co
[1] = vs
[0].co
[1] + 84 + vgf_default_large
.sy
*11 + 16;
1019 vs
[3].co
[1] = vs
[2].co
[1];
1021 if( menu_button( ctx
, list
, R
== 0, "Where to go" ) )
1024 if( menu
.guide_sel
== 3 )
1026 menu_try_find_cam( 2 );
1029 ui_split( inf
, k_ui_axis_h
, 28*2, 0, title
, inf
);
1030 ctx
->font
= &vgf_default_title
;
1031 ui_text( ctx
, title
, "Online", 1, k_ui_align_middle_center
, 0 );
1033 ui_split( inf
, k_ui_axis_h
, 28, 0, title
, inf
);
1034 ctx
->font
= &vgf_default_large
;
1036 "Connection to the global server is managed by this radar\n"
1037 "dish in the hub island. Come back here to turn the\n"
1038 "connection on or off.\n"
1040 "You'll then see other players or your friends if you go\n"
1041 "to the same location, and your highscores will be saved\n"
1042 "onto the scoreboards."
1043 , 1, k_ui_align_left
, 0 );
1045 vs
[2].co
[1] = vs
[0].co
[1] + 84 + vgf_default_large
.sy
*7 + 16;
1046 vs
[3].co
[1] = vs
[2].co
[1];
1048 if( menu_button( ctx
, list
, R
== 1, "Playing Online" ) )
1051 menu_heading( ctx
, list
, "Controls", 0 );
1052 if( menu_button( ctx
, list
, R
== 2, "Skating \xb2" ) )
1056 "https://skaterift.com/index.php?page=movement" );
1058 if( menu
.guide_sel
== 0 || menu
.guide_sel
> 3 ) menu_try_find_cam( 3 );
1060 if( menu_button( ctx
, list
, R
== 3, "Tricks \xb2" ) )
1064 "https://skaterift.com/index.php?page=tricks" );
1067 menu_heading( ctx
, list
, "Workshop", 0 );
1068 if( menu_button( ctx
, list
, R
== 4, "Create a Board \xb2" ) )
1072 "https://skaterift.com/index.php?page=workshop_board" );
1074 if( menu_button( ctx
, list
, R
== 5, "Create a World \xb2" ) )
1078 "https://skaterift.com/index.php?page=workshop_world" );
1080 if( menu_button( ctx
, list
, R
== 6, "Create a Playermodel \xb2" ) )
1084 "https://skaterift.com/index.php?page=workshop_player" );
1091 vg_ui
.frosting
= 0.015f
;
1092 ui_flush( ctx
, k_ui_shader_colour
, NULL
);
1093 vg_ui
.frosting
= 0.0f
;
1094 ctx
->font
= &vgf_default_small
;