6 #include "world_render.h"
9 #include "shaders/menu.h"
10 #include "vg/vg_steam_friends.h"
12 VG_STATIC mdl_context menu_model
;
13 VG_STATIC glmesh menu_glmesh
;
14 VG_STATIC m4x3f menu_mdl_mtx
;
15 VG_STATIC
float menu_opacity
= 0.0f
;
16 VG_STATIC
float menu_input_cooldown
= 0.0f
;
17 VG_STATIC
float menu_fov_target
= 97.0f
;
18 VG_STATIC v2f menu_extra_angles
;
20 VG_STATIC
int menu_loc
= 0xb,
22 VG_STATIC u32 menu_page
= 0;
24 VG_STATIC
int cl_menu
= 0,
27 VG_STATIC
int menu_enabled(void){ return cl_menu
; }
29 VG_STATIC
const char *playermodels
[] = { "ch_new", "ch_jordan", "ch_outlaw" };
31 vg_tex2d tex_menu
= { .path
= "textures/menu.qoi",.flags
= VG_TEXTURE_NEAREST
};
33 VG_STATIC
struct input_binding input_menu_h
,
38 input_menu_toggle_kbm
;
40 VG_STATIC
void menu_btn_paused( int event
);
41 VG_STATIC
void menu_btn_quit( int event
);
42 VG_STATIC
void menu_btn_skater( int event
);
43 VG_STATIC
void menu_btn_map( int event
);
44 VG_STATIC
void menu_btn_map_a( int event
);
45 VG_STATIC
void menu_btn_map_b( int event
);
46 VG_STATIC
void menu_btn_map_c( int event
);
47 VG_STATIC
void menu_btn_fuckoff( int event
);
48 VG_STATIC
void menu_btn_reset( int event
);
55 void (*fn_press
)(int event
);
61 VG_STATIC menu_buttons
[] =
63 /*0*/{"text_paused", 1, menu_btn_paused
},
64 /*1*/{"text_quit", 9, menu_btn_quit
, {3,-1,4,0xb}},
65 /*2*/{"text_skater", 3, menu_btn_skater
, {3,0xb,4,-1}},
66 /*3*/{"text_map", 5, NULL
, {-1,-1,2,-1}},
67 /*4*/{"text_about_game", 1, NULL
, {2,-1,-1,-1}},
68 /*5*/{"skater_left", 2, NULL
, {-1,-1,-1,-1}},
69 /*6*/{"skater_right", 2, NULL
, {-1,-1,-1,-1}},
70 /*7*/{"g_map", 5, NULL
},
71 /*8*/{"g_controls", 1, NULL
},
72 /*9*/{"text_quitty", 8, NULL
},
73 /*a*/{"text_yes", 8, menu_btn_fuckoff
,{-1,-1,-1,-1} },
74 /*b*/{"text_reset", 1, menu_btn_reset
,{3,1,4,2} },
77 VG_STATIC
void menu_btn_map_a( int event
){}
78 VG_STATIC
void menu_btn_map_b( int event
){}
79 VG_STATIC
void menu_btn_map_c( int event
){}
81 VG_STATIC
void menu_btn_paused( int event
)
86 VG_STATIC
void menu_btn_reset( int event
)
95 VG_STATIC
void menu_btn_fuckoff( int event
)
97 glfwSetWindowShouldClose( vg
.window
, 1 );
100 VG_STATIC
void menu_btn_quit( int event
)
106 VG_STATIC
void menu_btn_map( int event
)
112 VG_STATIC
void menu_btn_skater( int event
)
118 VG_STATIC
void steam_on_game_overlay( CallbackMsg_t
*msg
)
120 GameOverlayActivated_t
*inf
= (GameOverlayActivated_t
*)msg
->m_pubParam
;
121 vg_info( "Steam game overlay activated; pausing\n" );
130 VG_STATIC
void menu_init(void)
132 vg_create_unnamed_input( &input_menu_h
, k_input_type_axis
);
133 vg_create_unnamed_input( &input_menu_v
, k_input_type_axis
);
134 vg_create_unnamed_input( &input_menu_back
, k_input_type_button
);
135 vg_create_unnamed_input( &input_menu_press
, k_input_type_button
);
136 vg_create_unnamed_input( &input_menu_toggle
, k_input_type_button
);
137 vg_create_unnamed_input( &input_menu_toggle_kbm
, k_input_type_button
);
139 vg_apply_bind_str( &input_menu_h
, "", "gp-ls-h" );
140 vg_apply_bind_str( &input_menu_h
, "+", "d" );
141 vg_apply_bind_str( &input_menu_h
, "-", "a" );
142 vg_apply_bind_str( &input_menu_v
, "", "-gp-ls-v" );
143 vg_apply_bind_str( &input_menu_v
, "+", "w" );
144 vg_apply_bind_str( &input_menu_v
, "-", "s" );
145 vg_apply_bind_str( &input_menu_press
, "", "gp-a" );
146 vg_apply_bind_str( &input_menu_press
, "", "e" );
147 vg_apply_bind_str( &input_menu_back
, "", "gp-b" );
148 vg_apply_bind_str( &input_menu_back
, "", "\2escape" );
149 vg_apply_bind_str( &input_menu_toggle_kbm
, "", "\2escape" );
150 vg_apply_bind_str( &input_menu_toggle
, "", "\2gp-menu" );
152 vg_linear_clear( vg_mem
.scratch
);
154 mdl_open( &menu_model
, "models/rs_menu.mdl" );
155 mdl_load_metadata( &menu_model
, vg_mem
.rtmemory
);
156 mdl_load_mesh_data( &menu_model
, vg_mem
.scratch
);
157 mdl_close( &menu_model
);
159 vg_acquire_thread_sync();
161 mdl_unpack_glmesh( &menu_model
, &menu_glmesh
);
162 vg_tex2d_init( (vg_tex2d
*[]){ &tex_menu
}, 1 );
164 vg_release_thread_sync();
166 for( int i
=0; i
<vg_list_size(menu_buttons
); i
++ )
168 struct menu_button
*btn
= &menu_buttons
[i
];
169 btn
->pnode
= mdl_node_from_name( &menu_model
, btn
->name
);
172 vg_fatal_exit_loop( "Menu programming error" );
175 shader_menu_register();
178 steam_register_callback( k_iGameOverlayActivated
, steam_on_game_overlay
);
182 VG_STATIC
void menu_run_directional(void)
184 struct menu_button
*btn
= &menu_buttons
[ menu_loc
];
186 if( vg_input_button_down( &input_menu_press
) )
191 audio_play_oneshot( &audio_ui
[0], 1.0f
);
199 if( menu_input_cooldown
<= 0.0f
)
201 v2f dir
= { input_menu_h
.axis
.value
,
202 -input_menu_v
.axis
.value
};
204 if( v2_length2( dir
) > 0.8f
*0.8f
)
208 if( fabsf(dir
[0]) > fabsf(dir
[1]) )
210 if( dir
[0] > 0.0f
) idir
= 2;
215 if( dir
[1] > 0.0f
) idir
= 3;
219 int link
= btn
->links
[idir
];
223 menu_loc_last
= menu_loc
;
225 menu_input_cooldown
= 0.25f
;
231 VG_STATIC
int menu_page_should_backout(void)
233 return vg_input_button_down( &input_menu_back
);
236 VG_STATIC
void menu_close(void)
242 VG_STATIC
void menu_page_main(void)
244 if( menu_page_should_backout() )
250 menu_fov_target
= 112.0f
;
251 menu_run_directional();
254 VG_STATIC
void menu_page_map(void)
256 if( menu_page_should_backout() )
262 menu_fov_target
= 80.0f
;
263 menu_run_directional();
266 VG_STATIC
void menu_page_quit(void)
268 if( menu_page_should_backout() )
274 menu_fov_target
= 90.0f
;
275 menu_run_directional();
278 VG_STATIC
void menu_page_skater(void)
280 float h
= input_menu_h
.axis
.value
;
281 menu_fov_target
= 97.0f
;
283 if( menu_page_should_backout() )
290 if( (fabsf(h
) > 0.7f
) && (menu_input_cooldown
<= 0.0f
) )
293 audio_play_oneshot( &audio_rewind
[4], 1.0f
);
299 if( cl_playermdl_id
< 0 )
302 menu_buttons
[5].fsize
= 0.4f
;
303 menu_buttons
[5].falpha
= 1.0f
;
305 menu_input_cooldown
= 0.25f
;
310 if( cl_playermdl_id
> 2 )
313 menu_buttons
[6].fsize
= 0.4f
;
314 menu_buttons
[6].falpha
= 1.0f
;
316 menu_input_cooldown
= 0.25f
;
321 VG_STATIC
void menu_update(void)
323 vg_input_update( 1, &input_menu_h
);
324 vg_input_update( 1, &input_menu_v
);
325 vg_input_update( 1, &input_menu_back
);
326 vg_input_update( 1, &input_menu_press
);
327 vg_input_update( 1, &input_menu_toggle
);
328 vg_input_update( 1, &input_menu_toggle_kbm
);
330 int toggle_gp
= vg_input_button_down( &input_menu_toggle
),
331 toggle_kb
= vg_input_button_down( &input_menu_toggle_kbm
),
334 if( toggle_gp
|| toggle_kb
)
354 if( !wait_for_a_sec
)
358 else if( menu_page
== 2 )
360 else if( menu_page
== 4 )
362 else if( menu_page
== 8 )
366 struct menu_button
*btn
= &menu_buttons
[ menu_loc
];
374 v3f
*mtx
= player
.mdl
.sk
.final_mtx
[player
.mdl
.id_head
];
375 m3x3_mulv( mtx
, (v3f
){-1.0f
,0.0f
,0.0f
}, lookdir
);
378 v3_normalize( lookdir
);
384 v3_copy(player
.mdl
.ragdoll
[ player
.mdl
.id_hip
-1 ].rb
.co
, center_rough
);
388 v3_add( player
.camera_pos
, player
.visual_transform
[3], center_rough
);
389 v3_muls( center_rough
, 0.5f
, center_rough
);
392 v3_muladds( center_rough
, lookdir
, 1.5f
, pos
);
393 v3_add( (v3f
){ 0.0f
,0.8f
,0.0f
}, pos
, pos
);
396 angles
[0] = -atan2f( lookdir
[0], lookdir
[2] );
398 /* setup model matrix */
400 q_axis_angle( qmenu_mdl
, (v3f
){0.0f
,1.0f
,0.0f
}, -angles
[0] );
402 q_m3x3( qmenu_mdl
, menu_mdl_mtx
);
403 v3_copy( center_rough
, menu_mdl_mtx
[3] );
409 v3_sub( btn
->pnode
->co
, (v3f
){ 0.0f
,1.5f
,-1.5f
}, delta
);
410 v3_normalize( delta
);
412 float y
= atan2f( delta
[0], delta
[2] ),
416 menu_extra_angles
[0] = vg_lerpf( menu_extra_angles
[0], y
, dt
);
417 menu_extra_angles
[1] = vg_lerpf( menu_extra_angles
[1], p
, dt
);
419 v2_muladds( angles
, menu_extra_angles
, 0.8f
, angles
);
420 angles
[0] = fmodf( angles
[0], VG_TAUf
);
425 camera_angles
[0] = vg_alerpf( camera_angles
[0], angles
[0], menu_opacity
);
426 camera_angles
[1] = vg_lerpf ( camera_angles
[1], angles
[1], menu_opacity
);
427 v3_lerp( camera_pos
, pos
, menu_opacity
, camera_pos
);
431 float dt
= vg
.frame_delta
* 6.0f
;
432 menu_opacity
= vg_lerpf( menu_opacity
, cl_menu
&&!cl_menu_go_away
, dt
);
434 if( menu_opacity
<= 0.01f
)
440 vg
.time_rate
= 1.0-(double)menu_opacity
;
444 menu_input_cooldown
-= vg
.frame_delta
;
448 /* https://iquilezles.org/articles/functions/ */
449 float expSustainedImpulse( float x
, float f
, float k
)
451 float s
= fmaxf(x
-f
,0.0f
);
452 return fminf( x
*x
/(f
*f
), 1.0f
+(2.0f
/f
)*s
*expf(-k
*s
));
455 VG_STATIC
void menu_render( m4x4f projection
)
458 glDisable(GL_DEPTH_TEST
);
459 glBlendFunc( GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
460 glBlendEquation(GL_FUNC_ADD
);
462 shader_fscolour_use();
463 shader_fscolour_uColour( (v4f
){ 0.1f
, 0.1f
, 0.3f
, menu_opacity
*0.5f
} );
466 glEnable( GL_DEPTH_TEST
);
467 glDisable( GL_BLEND
);
472 shader_menu_uColour( (v4f
){ 1.0f
,1.0f
,1.0f
,1.0f
} );
473 shader_menu_uTexMain( 1 );
474 vg_tex2d_bind( &tex_menu
, 1 );
476 shader_menu_uPv( projection
);
477 mesh_bind( &menu_glmesh
);
479 for( int i
=0; i
<vg_list_size(menu_buttons
); i
++ )
481 struct menu_button
*btn
= &menu_buttons
[i
];
482 float talpha
= i
==menu_loc
? 1.0f
: 0.0f
,
483 tsize0
= btn
->areas
& menu_page
? 1.0f
: 0.0f
,
484 tsize1
= i
==menu_loc
? 0.07f
: 0.0f
,
485 tsize
= tsize0
+tsize1
;
487 btn
->falpha
= vg_lerpf( btn
->falpha
, talpha
, vg
.frame_delta
* 14.0f
);
488 btn
->fsize
= vg_lerpf( btn
->fsize
, tsize
, vg
.frame_delta
* 3.0f
);
491 v4f vselected
= {0.95f
*1.3f
,0.45f
*1.3f
,0.095f
*1.3f
, 1.0f
},
492 vnormal
= {1.0f
,1.0f
,1.0f
, 1.0f
},
495 v4_lerp( vnormal
, vselected
, btn
->falpha
, vcurrent
);
496 shader_menu_uColour( vcurrent
);
500 mdl_node_transform( btn
->pnode
, mtx
);
501 m4x3_mul( menu_mdl_mtx
, mtx
, mtx
);
502 m4x3_identity( mtx_size
);
503 m4x3_scale( mtx_size
, expSustainedImpulse( btn
->fsize
, 0.5f
, 8.7f
) );
504 m4x3_mul( mtx
, mtx_size
, mtx
);
505 shader_menu_uMdl( mtx
);
507 for( int j
=0; j
<btn
->pnode
->submesh_count
; j
++ )
510 &menu_model
.submesh_buffer
[ btn
->pnode
->submesh_start
+j
];
511 mdl_draw_submesh( sm
);
516 for( int i=0; i<menu_model->node_count; i++ )
518 mdl_node *pnode = mdl_node_from_id( menu_model, i );
520 for( int j=0; j<pnode->submesh_count; j++ )
523 mdl_submesh_from_id( menu_model, pnode->submesh_start+j );
525 mdl_node_transform( pnode, mtx );
526 m4x3_mul( menu_mdl_mtx, mtx, mtx );
527 shader_menu_uMdl( mtx );
529 mdl_draw_submesh( sm );