6 #include "world_render.h"
9 #include "shaders/menu.h"
11 static mdl_header
*menu_model
;
12 static glmesh menu_glmesh
;
13 static m4x3f menu_mdl_mtx
;
14 static float menu_opacity
= 0.0f
;
15 static float menu_input_cooldown
= 0.0f
;
16 static float menu_fov_target
= 97.0f
;
17 static v2f menu_extra_angles
;
19 static int menu_loc
= 1,
21 static u32 menu_page
= 0;
23 static int cl_menu
= 0,
25 static int cl_playermdl_id
= 0;
27 static const char *playermodels
[] = { "ch_new", "ch_jordan", "ch_outlaw" };
29 static void menu_btn_paused( int event
);
30 static void menu_btn_quit( int event
);
31 static void menu_btn_skater( int event
);
32 static void menu_btn_map( int event
);
33 static void menu_btn_map_a( int event
);
34 static void menu_btn_map_b( int event
);
35 static void menu_btn_map_c( int event
);
36 static void menu_btn_fuckoff( int event
);
43 void (*fn_press
)(int event
);
49 static menu_buttons
[] =
51 /*0*/{"text_paused", 1, menu_btn_paused
},
52 /*1*/{"text_quit", 9, menu_btn_quit
, {3,-1,4,2}},
53 /*2*/{"text_skater", 3, menu_btn_skater
, {3,1,4,-1}},
54 /*3*/{"text_map", 5, menu_btn_map
, {-1,-1,2,-1}},
55 /*4*/{"text_about_game", 1, NULL
, {2,-1,-1,-1}},
56 /*5*/{"skater_left", 2, NULL
, {-1,-1,-1,-1}},
57 /*6*/{"skater_right", 2, NULL
, {-1,-1,-1,-1}},
58 /*7*/{"map_a", 4, menu_btn_map_a
,{8, -1, 9, 9 }},
59 /*8*/{"map_b", 4, menu_btn_map_b
,{-1,7,7,-1}},
60 /*9*/{"map_c", 4, menu_btn_map_c
,{7,7,-1,8}},
61 /*a*/{"g_map", 5, NULL
},
62 /*b*/{"g_controls", 1, NULL
},
63 /*c*/{"text_quitty", 8, NULL
},
64 /*d*/{"text_yes", 8, menu_btn_fuckoff
,{-1,-1,-1,-1} },
67 static void menu_btn_map_a( int event
){}
68 static void menu_btn_map_b( int event
){}
69 static void menu_btn_map_c( int event
){}
71 static void menu_btn_paused( int event
)
76 static void menu_btn_fuckoff( int event
)
78 glfwSetWindowShouldClose( vg
.window
, 1 );
81 static void menu_btn_quit( int event
)
87 static void menu_btn_map( int event
)
93 static void menu_btn_skater( int event
)
98 static void menu_init(void)
100 menu_model
= mdl_load( "models/rs_menu.mdl" );
103 vg_fatal_exit_loop( "No menu model" );
105 for( int i
=0; i
<vg_list_size(menu_buttons
); i
++ )
107 struct menu_button
*btn
= &menu_buttons
[i
];
108 btn
->pnode
= mdl_node_from_name( menu_model
, btn
->name
);
111 vg_fatal_exit_loop( "Menu programming error" );
114 vg_convar_push( (struct vg_convar
){
115 .name
= "cl_playermdl_id",
116 .data
= &cl_playermdl_id
,
117 .data_type
= k_convar_dtype_i32
,
118 .opt_i32
= { .min
=0, .max
=2, .clamp
=1 },
122 vg_acquire_thread_sync();
123 mdl_unpack_glmesh( menu_model
, &menu_glmesh
);
124 vg_release_thread_sync();
126 shader_menu_register();
129 static void menu_run_directional(void)
131 struct menu_button
*btn
= &menu_buttons
[ menu_loc
];
133 if( vg_get_button_down( "jump" ) )
138 audio_play_oneshot( &audio_ui
[0], 1.0f
);
146 if( menu_input_cooldown
<= 0.0f
)
148 v2f dir
= { vg_get_axis( "lookh" ), vg_get_axis( "lookv" ) };
150 if( v2_length2( dir
) > 0.8f
*0.8f
)
154 if( fabsf(dir
[0]) > fabsf(dir
[1]) )
156 if( dir
[0] > 0.0f
) idir
= 2;
161 if( dir
[1] > 0.0f
) idir
= 3;
165 int link
= btn
->links
[idir
];
169 menu_loc_last
= menu_loc
;
171 menu_input_cooldown
= 0.25f
;
177 static int menu_page_should_backout(void)
179 return vg_get_button_down( "break" );
182 static void menu_close(void)
188 static void menu_page_main(void)
190 if( menu_page_should_backout() )
196 menu_fov_target
= 112.0f
;
197 menu_run_directional();
200 static void menu_page_map(void)
202 if( menu_page_should_backout() )
208 menu_fov_target
= 80.0f
;
209 menu_run_directional();
212 static void menu_page_quit(void)
214 if( menu_page_should_backout() )
220 menu_fov_target
= 90.0f
;
221 menu_run_directional();
224 static void menu_page_skater(void)
226 float h
= vg_get_axis( "lookh" );
227 menu_fov_target
= 97.0f
;
229 if( menu_page_should_backout() )
236 if( (fabsf(h
) > 0.7f
) && (menu_input_cooldown
<= 0.0f
) )
241 if( cl_playermdl_id
< 0 )
244 menu_buttons
[5].fsize
= 0.4f
;
245 menu_buttons
[5].falpha
= 1.0f
;
247 menu_input_cooldown
= 0.25f
;
248 player_load_model( playermodels
[ cl_playermdl_id
], 1 );
253 if( cl_playermdl_id
> 2 )
256 menu_buttons
[6].fsize
= 0.4f
;
257 menu_buttons
[6].falpha
= 1.0f
;
259 menu_input_cooldown
= 0.25f
;
260 player_load_model( playermodels
[ cl_playermdl_id
], 1 );
265 static void menu_update(void)
267 if( vg_get_button_down( "menu" ) )
283 else if( menu_page
== 2 )
285 else if( menu_page
== 4 )
287 else if( menu_page
== 8 )
290 struct menu_button
*btn
= &menu_buttons
[ menu_loc
];
298 v3f
*mtx
= player
.mdl
.sk
.final_mtx
[player
.mdl
.id_head
];
299 m3x3_mulv( mtx
, (v3f
){-1.0f
,0.0f
,0.0f
}, lookdir
);
302 v3_normalize( lookdir
);
308 v3_copy(player
.mdl
.ragdoll
[ player
.mdl
.id_hip
-1 ].rb
.co
, center_rough
);
312 v3_add( player
.camera_pos
, player
.visual_transform
[3], center_rough
);
313 v3_muls( center_rough
, 0.5f
, center_rough
);
316 v3_muladds( center_rough
, lookdir
, 1.5f
, pos
);
317 v3_add( (v3f
){ 0.0f
,0.8f
,0.0f
}, pos
, pos
);
320 angles
[0] = -atan2f( lookdir
[0], lookdir
[2] );
322 /* setup model matrix */
324 q_axis_angle( qmenu_mdl
, (v3f
){0.0f
,1.0f
,0.0f
}, -angles
[0] );
326 q_m3x3( qmenu_mdl
, menu_mdl_mtx
);
327 v3_copy( center_rough
, menu_mdl_mtx
[3] );
333 v3_sub( btn
->pnode
->co
, (v3f
){ 0.0f
,1.5f
,-1.5f
}, delta
);
334 v3_normalize( delta
);
336 float y
= atan2f( delta
[0], delta
[2] ),
340 menu_extra_angles
[0] = vg_lerpf( menu_extra_angles
[0], y
, dt
);
341 menu_extra_angles
[1] = vg_lerpf( menu_extra_angles
[1], p
, dt
);
343 v2_muladds( angles
, menu_extra_angles
, 0.8f
, angles
);
344 angles
[0] = fmodf( angles
[0], VG_TAUf
);
349 camera_angles
[0] = vg_alerpf( camera_angles
[0], angles
[0], menu_opacity
);
350 camera_angles
[1] = vg_lerpf ( camera_angles
[1], angles
[1], menu_opacity
);
351 v3_lerp( camera_pos
, pos
, menu_opacity
, camera_pos
);
355 float dt
= vg
.frame_delta
* 6.0f
;
356 menu_opacity
= vg_lerpf( menu_opacity
, cl_menu
&&!cl_menu_go_away
, dt
);
358 if( menu_opacity
<= 0.01f
)
364 vg
.time_rate
= 1.0-(double)menu_opacity
;
368 menu_input_cooldown
-= vg
.frame_delta
;
372 /* https://iquilezles.org/articles/functions/ */
373 float expSustainedImpulse( float x
, float f
, float k
)
375 float s
= fmaxf(x
-f
,0.0f
);
376 return fminf( x
*x
/(f
*f
), 1.0f
+(2.0f
/f
)*s
*expf(-k
*s
));
379 static void menu_render( m4x4f projection
)
382 glDisable(GL_DEPTH_TEST
);
383 glBlendFunc( GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
384 glBlendEquation(GL_FUNC_ADD
);
386 shader_fscolour_use();
387 shader_fscolour_uColour( (v4f
){ 0.1f
, 0.1f
, 0.3f
, menu_opacity
*0.5f
} );
390 glEnable( GL_DEPTH_TEST
);
391 glDisable( GL_BLEND
);
396 shader_menu_uColour( (v4f
){ 1.0f
,1.0f
,1.0f
,1.0f
} );
397 shader_menu_uTexMain( 1 );
398 vg_tex2d_bind( &tex_graffiti
, 1 );
400 shader_menu_uPv( projection
);
401 mesh_bind( &menu_glmesh
);
403 for( int i
=0; i
<vg_list_size(menu_buttons
); i
++ )
405 struct menu_button
*btn
= &menu_buttons
[i
];
406 float talpha
= i
==menu_loc
? 1.0f
: 0.0f
,
407 tsize0
= btn
->areas
& menu_page
? 1.0f
: 0.0f
,
408 tsize1
= i
==menu_loc
? 0.07f
: 0.0f
,
409 tsize
= tsize0
+tsize1
;
411 btn
->falpha
= vg_lerpf( btn
->falpha
, talpha
, vg
.frame_delta
* 14.0f
);
412 btn
->fsize
= vg_lerpf( btn
->fsize
, tsize
, vg
.frame_delta
* 3.0f
);
415 v4f vselected
= {0.95f
*1.3f
,0.45f
*1.3f
,0.095f
*1.3f
, 1.0f
},
416 vnormal
= {1.0f
,1.0f
,1.0f
, 1.0f
},
419 v4_lerp( vnormal
, vselected
, btn
->falpha
, vcurrent
);
420 shader_menu_uColour( vcurrent
);
424 mdl_node_transform( btn
->pnode
, mtx
);
425 m4x3_mul( menu_mdl_mtx
, mtx
, mtx
);
426 m4x3_identity( mtx_size
);
427 m4x3_scale( mtx_size
, expSustainedImpulse( btn
->fsize
, 0.5f
, 8.7f
) );
428 m4x3_mul( mtx
, mtx_size
, mtx
);
429 shader_menu_uMdl( mtx
);
431 for( int j
=0; j
<btn
->pnode
->submesh_count
; j
++ )
434 mdl_submesh_from_id( menu_model
, btn
->pnode
->submesh_start
+j
);
435 mdl_draw_submesh( sm
);
440 for( int i=0; i<menu_model->node_count; i++ )
442 mdl_node *pnode = mdl_node_from_id( menu_model, i );
444 for( int j=0; j<pnode->submesh_count; j++ )
447 mdl_submesh_from_id( menu_model, pnode->submesh_start+j );
449 mdl_node_transform( pnode, mtx );
450 m4x3_mul( menu_mdl_mtx, mtx, mtx );
451 shader_menu_uMdl( mtx );
453 mdl_draw_submesh( sm );
459 static void menu_free(void *_
)
461 mesh_free( &menu_glmesh
);