6 #include "world_render.h"
10 #include "shaders/model_menu.h"
11 #include "vg_steam_friends.h"
12 #include "submodules/tinydir/tinydir.h"
14 VG_STATIC mdl_context menu_model
;
15 VG_STATIC mdl_array_ptr menu_markers
;
16 VG_STATIC glmesh menu_glmesh
;
17 VG_STATIC m4x3f menu_mdl_mtx
;
18 VG_STATIC
float menu_opacity
= 0.0f
;
19 VG_STATIC
float menu_input_cooldown
= 0.0f
;
20 VG_STATIC
float menu_fov_target
= 97.0f
,
21 menu_smooth_fov
= 97.0f
;
22 VG_STATIC v2f menu_extra_angles
;
23 VG_STATIC v3f menu_camera_pos
;
24 VG_STATIC v2f menu_camera_angles
;
26 VG_STATIC
int cl_menu
= 0,
29 VG_STATIC
int menu_enabled(void){ return cl_menu
; }
31 VG_STATIC
const char *playermodels
[] = { "ch_new", "ch_jordan", "ch_outlaw" };
33 vg_tex2d tex_menu
= { .path
= "textures/menu.qoi",.flags
= VG_TEXTURE_NEAREST
};
35 VG_STATIC
struct input_binding input_menu_h
,
40 input_menu_toggle_kbm
;
42 VG_STATIC
void menu_btn_quit( int event
);
43 VG_STATIC
void menu_btn_skater( int event
);
44 VG_STATIC
void menu_btn_blur( int event
);
45 VG_STATIC
void menu_btn_fuckoff( int event
);
46 VG_STATIC
void menu_btn_reset( int event
);
47 VG_STATIC
void menu_btn_map( int event
);
48 VG_STATIC
void menu_btn_settings( int event
);
49 VG_STATIC
void menu_btn_invert_y( int event
);
51 VG_STATIC mdl_mesh
*menu_mesh_fov_slider
,
52 *menu_mesh_vol_slider
,
53 *menu_mesh_res_slider
;
80 k_menu_page_main
= 0x1,
81 k_menu_page_skater
= 0x2,
82 k_menu_page_quit
= 0x4,
83 k_menu_page_settings
= 0x8,
84 k_menu_page_map
= 0x10
87 struct menu_btn_userdata
{
92 VG_STATIC
int menu_settings_if( struct menu_btn_userdata ud
)
94 if( game_menu
.page
& k_menu_page_settings
){
95 int *ptr
= ud
.ptr_generic
;
102 VG_STATIC
int menu_vis( struct menu_btn_userdata ud
)
104 if( ud
.i
& game_menu
.page
)
110 VG_STATIC
int menu_controller( struct menu_btn_userdata ud
)
112 if( (game_menu
.page
& (k_menu_page_main
|k_menu_page_settings
))
113 && (ud
.i
== steam_display_controller
) )
118 VG_STATIC
int menu_controller_inf( struct menu_btn_userdata ud
)
120 if( (game_menu
.page
& k_menu_page_settings
)
121 && (ud
.i
== steam_display_controller
) )
130 int (*fn_visibility
)( struct menu_btn_userdata ud
);
131 struct menu_btn_userdata user
;
133 void (*fn_press
)( int event
);
143 VG_STATIC menu_buttons
[] =
146 "text_quit", menu_vis
, {.i
=k_menu_page_main
|k_menu_page_quit
},
147 .fn_press
= menu_btn_quit
,
148 .ld
="text_reset", .lr
="text_settings", /*.ll="text_map"*/
151 "text_quitty", menu_vis
, {.i
=k_menu_page_quit
}
154 "text_yes", menu_vis
, {.i
=k_menu_page_quit
},
155 .fn_press
= menu_btn_fuckoff
158 "text_reset", menu_vis
, {.i
=k_menu_page_main
},
159 .fn_press
= menu_btn_reset
,
160 .lu
="text_quit", .ld
="text_skater", /*.ll="text_map",*/ .lr
="text_settings"
163 "text_skater", menu_vis
, {.i
=k_menu_page_main
|k_menu_page_skater
},
164 .fn_press
= menu_btn_skater
,
165 .lu
="text_reset", /*.ll="text_map",*/ .lr
="text_settings"
169 "text_map", menu_vis, {.i=k_menu_page_main},
170 .fn_press = menu_btn_map,
175 "text_settings", menu_vis
, {.i
=k_menu_page_main
|k_menu_page_settings
},
176 .fn_press
= menu_btn_settings
,
180 "skater_left", menu_vis
, {k_menu_page_skater
}
183 "skater_right", menu_vis
, {k_menu_page_skater
}
187 "fov_slider", menu_vis
, {k_menu_page_settings
},
190 { "fov_info", menu_vis
, {k_menu_page_settings
} },
193 "vol_slider", menu_vis
, {k_menu_page_settings
},
196 { "vol_info", menu_vis
, {k_menu_page_settings
} },
199 "text_invert_y", menu_vis
, {k_menu_page_settings
},
200 .fn_press
= menu_btn_invert_y
,
201 .lu
= "fov_slider", .ld
="text_blur"
204 "text_invert_y_check", menu_settings_if
, {.ptr_generic
=&cl_invert_y
}
207 "text_blur", menu_vis
, {k_menu_page_settings
},
208 .fn_press
= menu_btn_blur
,
209 .lu
="text_invert_y", .ld
="res_slider"
212 "text_blur_check", menu_settings_if
, {.ptr_generic
=&cl_blur
}
215 "res_slider", menu_vis
, {k_menu_page_settings
},
216 .ld
= "vol_slider", .lu
= "text_blur"
219 "res_info", menu_vis
, {k_menu_page_settings
},
221 { "ctr_xbox", menu_controller_inf
, {k_steam_controller_type_xbox
}},
222 { "ctr_xbox_text", menu_controller_inf
, {k_steam_controller_type_xbox
}},
223 { "ctr_steam", menu_controller_inf
, {k_steam_controller_type_steam
}},
224 { "ctr_steam_text", menu_controller_inf
, {k_steam_controller_type_steam
}},
225 { "ctr_deck", menu_controller_inf
, {k_steam_controller_type_steam_deck
}},
226 { "ctr_deck_text", menu_controller_inf
, {k_steam_controller_type_steam_deck
}},
227 { "ctr_ps", menu_controller_inf
, {k_steam_controller_type_playstation
}},
228 { "ctr_ps_text", menu_controller_inf
, {k_steam_controller_type_playstation
}},
229 { "ctr_kbm", menu_controller_inf
, {k_steam_controller_type_keyboard
}},
230 { "ctr_kbm_text", menu_controller_inf
, {k_steam_controller_type_keyboard
}},
232 "text_paused", menu_vis
, {k_menu_page_main
}
236 VG_STATIC
int menu_get_loc( const char *loc
)
238 for( int i
=0; i
<vg_list_size(menu_buttons
); i
++ )
239 if( !strcmp( menu_buttons
[i
].name
, loc
) )
246 VG_STATIC
void menu_btn_reset( int event
)
248 localplayer_cmd_respawn( 0, NULL
);
253 VG_STATIC
void menu_btn_fuckoff( int event
)
255 vg
.window_should_close
= 1;
258 VG_STATIC
void menu_btn_quit( int event
)
260 game_menu
.page
= k_menu_page_quit
;
261 game_menu
.loc
= menu_get_loc( "text_yes" );
264 VG_STATIC
void menu_btn_settings( int event
)
266 game_menu
.page
= k_menu_page_settings
;
267 game_menu
.loc
= menu_get_loc( "fov_slider" );
270 VG_STATIC
void menu_btn_skater( int event
)
272 game_menu
.page
= k_menu_page_skater
;
275 VG_STATIC
void menu_btn_blur( int event
)
280 VG_STATIC
void menu_btn_invert_y( int event
)
285 VG_STATIC
void menu_btn_map( int event
)
287 game_menu
.page
= k_menu_page_map
;
288 game_menu
.map_count
= 0;
289 game_menu
.selected_map
= 0;
292 tinydir_open( &dir
, "maps" );
294 while( dir
.has_next
){
296 tinydir_readfile( &dir
, &file
);
299 struct menu_map_file
*mf
= &game_menu
.maps_list
[ game_menu
.map_count
];
301 vg_strncpy( file
.name
, mf
->name
,
302 vg_list_size(game_menu
.maps_list
[0].name
)-1 );
304 game_menu
.map_count
++;
305 if( game_menu
.map_count
== vg_list_size(game_menu
.maps_list
) )
309 tinydir_next( &dir
);
315 VG_STATIC
void menu_crap_ui(void)
317 if( cl_menu
&& (game_menu
.page
== k_menu_page_map
) ){
319 box
[0] = vg
.window_x
/2 - 150;
320 box
[1] = vg
.window_y
/2 - 300;
324 ui_fill_rect( box
, 0xa0000000 );
326 if( game_menu
.map_count
== 0 ){
327 ui_text( (ui_rect
){ vg
.window_x
/2, box
[1]+8, 0,0 }, "No maps found", 1,
328 k_text_align_center
);
331 ui_rect_pad( box
, 4 );
334 for( int i
=0; i
<game_menu
.map_count
; i
++ ){
335 struct menu_map_file
*mf
= &game_menu
.maps_list
[ i
];
337 ui_fill_rect( box
, game_menu
.selected_map
== i
? 0xa0ffffff:
339 ui_text( (ui_rect
){ vg
.window_x
/2, box
[1]+2, 0,0 },
340 mf
->name
, 1, k_text_align_center
);
347 VG_STATIC
void steam_on_game_overlay( CallbackMsg_t
*msg
)
349 GameOverlayActivated_t
*inf
= (GameOverlayActivated_t
*)msg
->m_pubParam
;
350 vg_info( "Steam game overlay activated; pausing\n" );
352 if( inf
->m_bActive
){
354 game_menu
.page
= k_menu_page_main
;
355 game_menu
.loc
= menu_get_loc( "text_skater" );
359 VG_STATIC
void menu_init(void)
361 vg_create_unnamed_input( &input_menu_h
, k_input_type_axis
);
362 vg_create_unnamed_input( &input_menu_v
, k_input_type_axis
);
363 vg_create_unnamed_input( &input_menu_back
, k_input_type_button
);
364 vg_create_unnamed_input( &input_menu_press
, k_input_type_button
);
365 vg_create_unnamed_input( &input_menu_toggle
, k_input_type_button
);
366 vg_create_unnamed_input( &input_menu_toggle_kbm
, k_input_type_button
);
368 vg_apply_bind_str( &input_menu_h
, "", "gp-ls-h" );
369 vg_apply_bind_str( &input_menu_h
, "+", "right" );
370 vg_apply_bind_str( &input_menu_h
, "-", "left" );
371 vg_apply_bind_str( &input_menu_v
, "", "-gp-ls-v" );
372 vg_apply_bind_str( &input_menu_v
, "+", "up" );
373 vg_apply_bind_str( &input_menu_v
, "-", "down" );
374 vg_apply_bind_str( &input_menu_press
, "", "gp-a" );
375 vg_apply_bind_str( &input_menu_press
, "", "\2enter" );
376 vg_apply_bind_str( &input_menu_back
, "", "gp-b" );
377 vg_apply_bind_str( &input_menu_back
, "", "\2escape" );
378 vg_apply_bind_str( &input_menu_toggle_kbm
, "", "\2escape" );
379 vg_apply_bind_str( &input_menu_toggle
, "", "\2gp-menu" );
381 vg_linear_clear( vg_mem
.scratch
);
383 mdl_open( &menu_model
, "models/rs_menu.mdl", vg_mem
.rtmemory
);
384 mdl_load_metadata_block( &menu_model
, vg_mem
.rtmemory
);
385 mdl_load_mesh_block( &menu_model
, vg_mem
.scratch
);
386 mdl_load_array( &menu_model
, &menu_markers
, "ent_marker", vg_mem
.rtmemory
);
387 //mdl_invert_uv_coordinates( &menu_model );
388 mdl_close( &menu_model
);
390 vg_acquire_thread_sync();
392 mdl_unpack_glmesh( &menu_model
, &menu_glmesh
);
393 vg_tex2d_init( (vg_tex2d
*[]){ &tex_menu
}, 1 );
395 vg_release_thread_sync();
397 for( int i
=0; i
<vg_list_size(menu_buttons
); i
++ ){
398 struct menu_button
*btn
= &menu_buttons
[i
];
399 btn
->mesh
= mdl_find_mesh( &menu_model
, btn
->name
);
402 vg_info( "info: %s\n", btn
->name
);
403 vg_fatal_exit_loop( "Menu programming error" );
408 ent_find_marker( &menu_model
, &menu_markers
, "fov_slider_max" );
410 ent_find_marker( &menu_model
, &menu_markers
, "fov_slider_min" );
412 ent_find_marker( &menu_model
, &menu_markers
, "vol_slider_max" );
414 ent_find_marker( &menu_model
, &menu_markers
, "vol_slider_min" );
416 ent_find_marker( &menu_model
, &menu_markers
, "res_slider_max" );
418 ent_find_marker( &menu_model
, &menu_markers
, "res_slider_min" );
420 menu_mesh_fov_slider
= mdl_find_mesh( &menu_model
, "fov_slider" );
421 menu_mesh_vol_slider
= mdl_find_mesh( &menu_model
, "vol_slider" );
422 menu_mesh_res_slider
= mdl_find_mesh( &menu_model
, "res_slider" );
424 shader_model_menu_register();
427 steam_register_callback( k_iGameOverlayActivated
, steam_on_game_overlay
);
431 VG_STATIC
void menu_run_directional(void)
433 struct menu_button
*btn
= &menu_buttons
[ game_menu
.loc
];
435 if( vg_input_button_down( &input_menu_press
) ){
438 audio_oneshot( &audio_ui
[0], 1.0f
, 0.0f
);
446 if( menu_input_cooldown
<= 0.0f
){
447 v2f dir
= { input_menu_h
.axis
.value
,
448 -input_menu_v
.axis
.value
};
450 if( v2_length2( dir
) > 0.8f
*0.8f
){
451 const char *link
= NULL
;
453 if( fabsf(dir
[0]) > fabsf(dir
[1]) ){
454 if( dir
[0] > 0.0f
) link
= btn
->lr
;
458 if( dir
[1] > 0.0f
) link
= btn
->ld
;
463 game_menu
.loc
= menu_get_loc( link
);
464 menu_input_cooldown
= 0.25f
;
470 VG_STATIC
int menu_page_should_backout(void)
472 return vg_input_button_down( &input_menu_back
);
475 VG_STATIC
void menu_close(void)
479 game_menu
.loc
= menu_get_loc( "text_skater" );
482 VG_STATIC
void menu_page_main(void)
484 if( menu_page_should_backout() )
490 menu_fov_target
= 112.0f
;
491 menu_run_directional();
494 VG_STATIC
void menu_page_map(void)
496 if( menu_page_should_backout() ){
497 game_menu
.page
= k_menu_page_main
;
498 game_menu
.loc
= menu_get_loc( "text_map" );
501 if( game_menu
.map_count
> 0 ){
502 float v
= input_menu_v
.axis
.value
;
503 if( (fabsf(v
) > 0.7f
) && (menu_input_cooldown
<= 0.0f
) ){
505 audio_oneshot( &audio_rewind
[4], 1.0f
, 0.0f
);
509 game_menu
.selected_map
--;
511 if( game_menu
.selected_map
< 0 )
512 game_menu
.selected_map
= game_menu
.map_count
-1;
514 menu_input_cooldown
= 0.25f
;
517 game_menu
.selected_map
++;
519 if( game_menu
.selected_map
>= game_menu
.map_count
)
520 game_menu
.selected_map
= 0;
522 menu_input_cooldown
= 0.25f
;
526 if( vg_input_button_down( &input_menu_press
) ){
530 strcpy( temp
, "maps/" );
531 strcat( temp
, game_menu
.maps_list
[game_menu
.selected_map
].name
);
533 world_change_world( 1, (const char *[]){ temp
} );
539 menu_fov_target
= 80.0f
;
542 VG_STATIC
void menu_page_quit(void)
544 if( menu_page_should_backout() ){
545 game_menu
.page
= k_menu_page_main
;
546 game_menu
.loc
= menu_get_loc( "text_quit" );
549 menu_fov_target
= 90.0f
;
550 menu_run_directional();
553 void temp_update_playermodel(void);
554 VG_STATIC
void menu_page_skater(void)
556 float h
= input_menu_h
.axis
.value
;
557 menu_fov_target
= 97.0f
;
559 if( menu_page_should_backout() ){
560 game_menu
.page
= k_menu_page_main
;
561 game_menu
.loc
= menu_get_loc( "text_skater" );
565 if( (fabsf(h
) > 0.7f
) && (menu_input_cooldown
<= 0.0f
) ){
567 audio_oneshot( &audio_rewind
[4], 1.0f
, 0.0f
);
570 vg_info( "%f\n", h
);
574 if( cl_playermdl_id
< 0 )
577 int li
= menu_get_loc( "skater_left" );
579 menu_buttons
[li
].fsize
= 0.4f
;
580 menu_buttons
[li
].falpha
= 1.0f
;
582 menu_input_cooldown
= 0.25f
;
586 if( cl_playermdl_id
> 2 )
589 int ri
= menu_get_loc( "skater_right" );
591 menu_buttons
[ri
].fsize
= 0.4f
;
592 menu_buttons
[ri
].falpha
= 1.0f
;
594 menu_input_cooldown
= 0.25f
;
597 temp_update_playermodel();
601 VG_STATIC
void menu_slider( float *value
, int set_value
,
602 mdl_mesh
*slider
, v3f co_min
, v3f co_max
)
605 float h
= input_menu_h
.axis
.value
;
606 if( fabsf(h
) > 0.04f
)
607 *value
+= h
* vg
.frame_delta
;
608 *value
= vg_clampf( *value
, 0.0f
, 1.0f
);
611 v3_lerp( co_min
, co_max
, *value
, slider
->transform
.co
);
614 VG_STATIC
void menu_page_settings(void)
616 menu_run_directional();
618 int fov_select
= game_menu
.loc
== menu_get_loc( "fov_slider" );
619 menu_slider( &cl_fov
, fov_select
,
620 menu_mesh_fov_slider
, menu_mark_fov_min
->transform
.co
,
621 menu_mark_fov_max
->transform
.co
);
624 menu_fov_target
= vg_lerpf( 97.0f
, 135.0f
, cl_fov
) * 0.8f
;
626 menu_slider( &vg_audio
.external_global_volume
,
627 (game_menu
.loc
== menu_get_loc( "vol_slider" )),
628 menu_mesh_vol_slider
, menu_mark_vol_min
->transform
.co
,
629 menu_mark_vol_max
->transform
.co
);
631 menu_slider( &gpipeline
.view_render_scale
,
632 (game_menu
.loc
== menu_get_loc( "res_slider" )),
633 menu_mesh_res_slider
, menu_mark_res_min
->transform
.co
,
634 menu_mark_res_max
->transform
.co
);
636 if( menu_page_should_backout() ){
637 game_menu
.page
= k_menu_page_main
;
638 game_menu
.loc
= menu_get_loc( "text_settings" );
643 VG_STATIC
void menu_update(void)
645 vg_input_update( 1, &input_menu_h
);
646 vg_input_update( 1, &input_menu_v
);
647 vg_input_update( 1, &input_menu_back
);
648 vg_input_update( 1, &input_menu_press
);
649 vg_input_update( 1, &input_menu_toggle
);
650 vg_input_update( 1, &input_menu_toggle_kbm
);
652 int toggle_gp
= vg_input_button_down( &input_menu_toggle
),
653 toggle_kb
= vg_input_button_down( &input_menu_toggle_kbm
),
656 if( toggle_gp
|| toggle_kb
){
671 if( !wait_for_a_sec
&& cl_menu
){
672 if( game_menu
.page
== k_menu_page_main
)
674 else if( game_menu
.page
== k_menu_page_skater
)
676 else if( game_menu
.page
== k_menu_page_quit
)
678 else if( game_menu
.page
== k_menu_page_settings
)
679 menu_page_settings();
680 else if( game_menu
.page
== k_menu_page_map
)
684 struct menu_button
*btn
= &menu_buttons
[ game_menu
.loc
];
688 player_instance
*player
= &localplayer
;
689 struct player_avatar
*av
= player
->playeravatar
;
692 if( player
->subsystem
== k_player_subsystem_dead
){
693 m4x3_mulv( av
->sk
.final_mtx
[av
->id_hip
], (v3f
){0.0f
,0.9f
,0.0f
},
697 m4x3_mulv( av
->sk
.final_mtx
[av
->id_head
], (v3f
){0.0f
,1.5f
,0.0f
},
703 if( player
->subsystem
== k_player_subsystem_walk
){
704 v3_muls( player
->rb
.to_world
[2], 1.0f
, cam_offset
);
708 v3_muls( player
->rb
.to_world
[0], -1.0f
, cam_offset
);
709 cam_rot
= -VG_PIf
*0.5f
;
714 m3x3_mulv( player
->invbasis
, cam_offset
, lookdir
);
716 v3_normalize( lookdir
);
718 m3x3_mulv( player
->basis
, lookdir
, cam_offset
);
719 v3_muladds( center_rough
, cam_offset
, 2.0f
, menu_camera_pos
);
721 menu_camera_angles
[1] = 0.0f
;
722 menu_camera_angles
[0] = -atan2f( lookdir
[0], lookdir
[2] );
724 /* setup model matrix */
726 q_axis_angle( qmenu_mdl
, (v3f
){0.0f
,1.0f
,0.0f
}, -menu_camera_angles
[0] );
727 q_m3x3( qmenu_mdl
, menu_mdl_mtx
);
728 v3_add( center_rough
, (v3f
){0.0f
,-0.5f
,0.0f
}, menu_mdl_mtx
[3] );
729 m3x3_mul( player
->basis
, menu_mdl_mtx
, menu_mdl_mtx
);
731 menu_smooth_fov
= vg_lerpf( menu_smooth_fov
, menu_fov_target
,
732 vg
.frame_delta
* 8.2f
);
738 v3_sub( btn
->mesh
->transform
.co
, (v3f
){ 0.0f
,1.5f
,-1.5f
}, delta
);
739 v3_normalize( delta
);
741 float y
= atan2f( delta
[0], delta
[2] ),
745 menu_extra_angles
[0] = vg_lerpf( menu_extra_angles
[0], y
, dt
);
746 menu_extra_angles
[1] = vg_lerpf( menu_extra_angles
[1], p
, dt
);
748 v2_muladds( menu_camera_angles
, menu_extra_angles
, 0.8f
,
749 menu_camera_angles
);
750 menu_camera_angles
[0] = fmodf( menu_camera_angles
[0], VG_TAUf
);
753 float dt
= vg
.frame_delta
* 6.0f
;
754 menu_opacity
= vg_lerpf( menu_opacity
, cl_menu
&&!cl_menu_go_away
, dt
);
756 if( menu_opacity
<= 0.01f
){
761 vg
.time_rate
= 1.0-(double)menu_opacity
;
764 menu_input_cooldown
-= vg
.frame_delta
;
768 /* https://iquilezles.org/articles/functions/ */
769 float expSustainedImpulse( float x
, float f
, float k
)
771 float s
= fmaxf(x
-f
,0.0f
);
772 return fminf( x
*x
/(f
*f
), 1.0f
+(2.0f
/f
)*s
*expf(-k
*s
));
775 VG_STATIC
void menu_render_bg(void)
778 glDisable(GL_DEPTH_TEST
);
779 glBlendFunc( GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
780 glBlendEquation(GL_FUNC_ADD
);
782 shader_blitcolour_use();
783 shader_blitcolour_uColour( (v4f
){ 0.1f
, 0.1f
, 0.3f
, menu_opacity
*0.5f
} );
787 VG_STATIC
void menu_render_fg( camera
*cam
)
789 glEnable( GL_DEPTH_TEST
);
790 glDisable( GL_BLEND
);
794 shader_model_menu_use();
795 shader_model_menu_uColour( (v4f
){ 1.0f
,1.0f
,1.0f
,1.0f
} );
796 shader_model_menu_uTexMain( 1 );
797 vg_tex2d_bind( &tex_menu
, 1 );
799 shader_model_menu_uPv( cam
->mtx
.pv
);
800 shader_model_menu_uPvmPrev( cam
->mtx_prev
.pv
);
801 mesh_bind( &menu_glmesh
);
803 for( int i
=0; i
<vg_list_size(menu_buttons
); i
++ ){
804 struct menu_button
*btn
= &menu_buttons
[i
];
805 float talpha
= i
==game_menu
.loc
? 1.0f
: 0.0f
,
806 tsize0
= btn
->fn_visibility( btn
->user
)? 1.0f
: 0.0f
,
807 tsize1
= i
==game_menu
.loc
? 0.07f
: 0.0f
,
808 tsize
= tsize0
+tsize1
;
810 btn
->falpha
= vg_lerpf( btn
->falpha
, talpha
, vg
.frame_delta
* 14.0f
);
811 btn
->fsize
= vg_lerpf( btn
->fsize
, tsize
, vg
.frame_delta
* 7.0f
);
814 v4f vselected
= {0.95f
*1.3f
,0.45f
*1.3f
,0.095f
*1.3f
, 1.0f
},
815 vnormal
= {1.0f
,1.0f
,1.0f
, 1.0f
},
818 v4_lerp( vnormal
, vselected
, btn
->falpha
, vcurrent
);
819 shader_model_menu_uColour( vcurrent
);
823 mdl_transform_m4x3( &btn
->mesh
->transform
, mtx
);
824 m4x3_mul( menu_mdl_mtx
, mtx
, mtx
);
825 m4x3_identity( mtx_size
);
826 m3x3_scalef( mtx_size
, expSustainedImpulse( btn
->fsize
, 0.5f
, 8.7f
) );
827 m4x3_mul( mtx
, mtx_size
, mtx
);
828 shader_model_menu_uMdl( mtx
);
830 for( int j
=0; j
<btn
->mesh
->submesh_count
; j
++ ){
832 mdl_arritm( &menu_model
.submeshs
, btn
->mesh
->submesh_start
+j
);
833 mdl_draw_submesh( sm
);
838 for( int i=0; i<menu_model->node_count; i++ )
840 mdl_node *pnode = mdl_node_from_id( menu_model, i );
842 for( int j=0; j<pnode->submesh_count; j++ )
845 mdl_submesh_from_id( menu_model, pnode->submesh_start+j );
847 mdl_node_transform( pnode, mtx );
848 m4x3_mul( menu_mdl_mtx, mtx, mtx );
849 shader_menu_uMdl( mtx );
851 mdl_draw_submesh( sm );