#ifndef MENU_H
#define MENU_H
+#include "common.h"
+#include "model.h"
+#include "world_render.h"
+#include "player.h"
+#include "conf.h"
+#include "shaders/model_menu.h"
+
+#define MENU_STACK_SIZE 8
+
+struct {
+ int active;
+ f32 factive;
+ int disable_open;
+
+ u32 page, /* current page index */
+ page_stack[ MENU_STACK_SIZE ],
+ page_depth;
+ ent_menuitem *loc;
+ ent_camera *cam;
+ camera view;
+
+ mdl_context model;
+ GLuint texture;
+ glmesh mesh;
+
+ mdl_array_ptr items, markers, cameras;
+}
+static menu;
+
+static void menu_init(void)
+{
+ void *alloc = vg_mem.rtmemory;
+
+ mdl_open( &menu.model, "models/rs_menu.mdl", alloc );
+ mdl_load_metadata_block( &menu.model, alloc );
+
+ vg_linear_clear( vg_mem.scratch );
+
+ mdl_load_array( &menu.model, &menu.items, "ent_menuitem", alloc );
+ mdl_load_array( &menu.model, &menu.markers, "ent_marker", alloc );
+ mdl_load_array( &menu.model, &menu.cameras, "ent_camera", alloc );
+
+ vg_linear_clear( vg_mem.scratch );
+
+ if( !mdl_arrcount( &menu.model.textures ) )
+ vg_fatal_error( "No texture in menu file" );
+
+ mdl_texture *tex0 = mdl_arritm( &menu.model.textures, 0 );
+ void *data = vg_linear_alloc( vg_mem.scratch, tex0->file.pack_size );
+ mdl_fread_pack_file( &menu.model, &tex0->file, data );
+
+ mdl_async_load_glmesh( &menu.model, &menu.mesh );
+ vg_tex2d_load_qoi_async( data, tex0->file.pack_size,
+ VG_TEX2D_LINEAR|VG_TEX2D_CLAMP,
+ &menu.texture );
+
+ mdl_close( &menu.model );
+ shader_model_menu_register();
+}
+
+static void menu_open_page( const char *name )
+{
+ vg_info( "Try to open %s\n", name );
+
+ u32 hash = vg_strdjb2( name );
+ for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
+ ent_menuitem *item = mdl_arritm( &menu.items, i );
+
+ if( item->type == k_ent_menuitem_type_page ){
+ if( mdl_pstreq( &menu.model, item->page.pstr_name, name, hash ) ){
+ menu.page = __builtin_ctz( item->groups );
+ vg_info( "menu page: %u\n", menu.page );
+
+ if( item->page.id_entrypoint ){
+ u32 id = mdl_entity_id_id( item->page.id_entrypoint );
+ menu.loc = mdl_arritm( &menu.items, id );
+ }
+
+ if( item->page.id_viewpoint ){
+ u32 id = mdl_entity_id_id( item->page.id_viewpoint );
+ menu.cam = mdl_arritm( &menu.cameras, id );
+ }
+
+ menu.page_stack[ menu.page_depth ++ ] = menu.page;
+ return;
+ }
+ }
+ }
+}
+
+static void menu_back_page(void)
+{
+ if( menu.page_depth == 0 ){
+ menu.active = 0;
+ }
+ else{
+ menu.page = menu.page_stack[ -- menu.page_depth ];
+ }
+}
+
+static void menu_update(void)
+{
+ if( button_down( k_srbind_mopen ) ){
+ if( !menu.active && !menu.disable_open ){
+ menu.active = 1;
+ menu_open_page( "Main Menu" );
+ }
+ }
+
+ menu.factive = vg_lerpf( menu.factive, menu.active,
+ vg.time_frame_delta * 6.0f );
+
+ if( menu.factive > 0.01f ){
+
+ }
+
+ if( !menu.active ) return;
+ if( !menu.loc ) return;
+ if( !menu.cam ) return;
+
+ int ml = button_down( k_srbind_mleft ),
+ mr = button_down( k_srbind_mright ),
+ mu = button_down( k_srbind_mup ),
+ md = button_down( k_srbind_mdown ),
+ mh = ml-mr,
+ mv = mu-md,
+ enter = button_down( k_srbind_maccept ),
+ escape = button_down( k_srbind_mback );
+
+ if( escape ){
+ menu_back_page();
+ }
+ else if( enter ){
+ if ( menu.loc->type == k_ent_menuitem_type_event_button ){
+
+ }
+ else if( menu.loc->type == k_ent_menuitem_type_page_button ){
+ menu_open_page( mdl_pstr( &menu.model, menu.loc->button.pstr ) );
+ }
+ else if( menu.loc->type == k_ent_menuitem_type_toggle ){
+
+ }
+ }
+ else if( mh||mv ){
+ v3f opt;
+ v3_zero( opt );
+ f32 best = 0.707f;
+ ent_menuitem *nextpos = NULL;
+
+ opt[0] += mh;
+ opt[2] += mv;
+ mdl_transform_vector( &menu.cam->transform, opt, opt );
+
+ for( u32 i=0; i<4; i++ ){
+ u32 id = menu.loc->id_links[i];
+ if( !id ) continue;
+ u32 index = mdl_entity_id_id( id );
+
+ ent_menuitem *other = mdl_arritm( &menu.items, index );
+ v3f delta;
+ v3_sub( menu.loc->transform.co, other->transform.co, delta );
+ v3_normalize( delta );
+
+ f32 score = v3_dot( delta, opt );
+ if( score > best ){
+ best = score;
+ nextpos = other;
+ }
+ }
+
+ if( nextpos ){
+ menu.loc = nextpos;
+ }
+ }
+}
+
+VG_STATIC void menu_render(void)
+{
+ glEnable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+ glBlendEquation(GL_FUNC_ADD);
+
+ shader_blitcolour_use();
+ shader_blitcolour_uColour( (v4f){ 0.1f, 0.1f, 0.3f, menu.factive*0.5f } );
+ render_fsquad();
+
+ glEnable( GL_DEPTH_TEST );
+ glDisable( GL_BLEND );
+
+ if( menu.cam ){
+ menu.view.fov = menu.cam->fov;
+ menu.view.farz = 150.0f;
+ menu.view.nearz = 0.01f;
+ v3_copy( menu.cam->transform.co, menu.view.pos );
+
+ v3f v0;
+ mdl_transform_vector( &menu.cam->transform, (v3f){0.0f,-1.0f,0.0f}, v0 );
+ player_vector_angles( menu.view.angles, v0, 1.0f, 0.0f );
+ camera_update_transform( &menu.view );
+ camera_update_view( &menu.view );
+ camera_update_projection( &menu.view );
+ camera_finalize( &menu.view );
+ }
+ else return;
+
+ shader_model_menu_use();
+ shader_model_menu_uTexMain( 1 );
+ glActiveTexture( GL_TEXTURE1 );
+ glBindTexture( GL_TEXTURE_2D, menu.texture );
+ shader_model_menu_uPv( menu.view.mtx.pv );
+ shader_model_menu_uPvmPrev( menu.view.mtx_prev.pv );
+
+ mesh_bind( &menu.mesh );
+
+ for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
+ ent_menuitem *item = mdl_arritm( &menu.items, i );
+
+ if( item->type == k_ent_menuitem_type_page ) continue;
+ if( !(item->groups & (0x1 << menu.page)) ) continue;
+
+ if( item == menu.loc ){
+ shader_model_menu_uColour( (v4f){ 0.1f,0.25f,0.9f,1.0f} );
+ }
+ else{
+ shader_model_menu_uColour( (v4f){ 1.0f,1.0f,1.0f,1.0f} );
+ }
+
+ m4x3f mmdl;
+ mdl_transform_m4x3( &item->transform, mmdl );
+ shader_model_menu_uMdl( mmdl );
+
+ for( u32 j=0; j<item->submesh_count; j++ ){
+ u32 index = item->submesh_start + j;
+ mdl_draw_submesh( mdl_arritm( &menu.model.submeshs, index ));
+ }
+ }
+}
+
+#endif /* MENU_H */
+
+#if 0
+#ifndef MENU_H
+#define MENU_H
+
#include "common.h"
#include "model.h"
#include "world_render.h"
#include "shaders/model_menu.h"
#include "vg_steam_friends.h"
-#include "submodules/tinydir/tinydir.h"
VG_STATIC mdl_context menu_model;
VG_STATIC mdl_array_ptr menu_markers;
GLuint tex_menu;
+#if 0
VG_STATIC struct input_binding input_menu_h,
input_menu_v,
input_menu_press,
input_menu_back,
input_menu_toggle,
input_menu_toggle_kbm;
+#endif
VG_STATIC void menu_btn_quit( int event );
VG_STATIC void menu_btn_skater( int event );
return 0;
}
+#if 0
VG_STATIC int menu_controller( struct menu_btn_userdata ud )
{
if( (game_menu.page & (k_menu_page_main|k_menu_page_settings))
return 1;
return 0;
}
+#endif
struct menu_button
{
{
"res_info", menu_vis, {k_menu_page_settings},
},
+#if 0
{ "ctr_xbox", menu_controller_inf, {k_steam_controller_type_xbox}},
{ "ctr_xbox_text", menu_controller_inf, {k_steam_controller_type_xbox}},
{ "ctr_steam", menu_controller_inf, {k_steam_controller_type_steam}},
{ "ctr_ps_text", menu_controller_inf, {k_steam_controller_type_playstation}},
{ "ctr_kbm", menu_controller_inf, {k_steam_controller_type_keyboard}},
{ "ctr_kbm_text", menu_controller_inf, {k_steam_controller_type_keyboard}},
+#endif
{
"text_paused", menu_vis, {k_menu_page_main}
},
struct menu_map_file *mf = &game_menu.maps_list[ game_menu.map_count ];
vg_strncpy( file.name, mf->name,
- vg_list_size(game_menu.maps_list[0].name)-1 );
+ vg_list_size(game_menu.maps_list[0].name),
+ k_strncpy_always_add_null );
game_menu.map_count ++;
if( game_menu.map_count == vg_list_size(game_menu.maps_list) )
VG_STATIC void menu_crap_ui(void)
{
+#if 0
if( cl_menu && (game_menu.page == k_menu_page_map) ){
ui_rect box;
box[0] = vg.window_x/2 - 150;
}
}
}
+#endif
}
VG_STATIC void steam_on_game_overlay( CallbackMsg_t *msg )
VG_STATIC void menu_init(void)
{
- vg_create_unnamed_input( &input_menu_h, k_input_type_axis );
- vg_create_unnamed_input( &input_menu_v, k_input_type_axis );
- vg_create_unnamed_input( &input_menu_back, k_input_type_button );
- vg_create_unnamed_input( &input_menu_press, k_input_type_button );
- vg_create_unnamed_input( &input_menu_toggle, k_input_type_button );
- vg_create_unnamed_input( &input_menu_toggle_kbm, k_input_type_button );
-
+#if 0
vg_apply_bind_str( &input_menu_h, "", "gp-ls-h" );
vg_apply_bind_str( &input_menu_h, "+", "right" );
vg_apply_bind_str( &input_menu_h, "-", "left" );
vg_apply_bind_str( &input_menu_back, "", "\2escape" );
vg_apply_bind_str( &input_menu_toggle_kbm, "", "\2escape" );
vg_apply_bind_str( &input_menu_toggle, "", "\2gp-menu" );
+#endif
vg_linear_clear( vg_mem.scratch );
VG_STATIC void menu_run_directional(void)
{
+#if 0
struct menu_button *btn = &menu_buttons[ game_menu.loc ];
if( vg_input_button_down( &input_menu_press ) ){
}
}
}
+#endif
}
VG_STATIC int menu_page_should_backout(void)
{
+ return 0;
+#if 0
return vg_input_button_down( &input_menu_back );
+#endif
}
VG_STATIC void menu_close(void)
}
if( game_menu.map_count > 0 ){
+#if 0
float v = input_menu_v.axis.value;
if( (fabsf(v) > 0.7f) && (menu_input_cooldown <= 0.0f) ){
audio_lock();
menu_close();
#endif
}
+#endif
}
menu_fov_target = 80.0f;
void temp_update_playermodel(void);
VG_STATIC void menu_page_skater(void)
{
+#if 0
float h = input_menu_h.axis.value;
menu_fov_target = 97.0f;
temp_update_playermodel();
}
+#endif
}
VG_STATIC void menu_slider( float *value, int set_value,
mdl_mesh *slider, v3f co_min, v3f co_max )
{
+#if 0
if( set_value ){
float h = input_menu_h.axis.value;
if( fabsf(h) > 0.04f )
}
v3_lerp( co_min, co_max, *value, slider->transform.co );
+#endif
}
VG_STATIC void menu_page_settings(void)
VG_STATIC void menu_update(void)
{
+#if 0
vg_input_update( 1, &input_menu_h );
vg_input_update( 1, &input_menu_v );
vg_input_update( 1, &input_menu_back );
vg_input_update( 1, &input_menu_press );
vg_input_update( 1, &input_menu_toggle );
vg_input_update( 1, &input_menu_toggle_kbm );
+#endif
+ return;
+
+#if 0
int toggle_gp = vg_input_button_down( &input_menu_toggle ),
toggle_kb = vg_input_button_down( &input_menu_toggle_kbm ),
wait_for_a_sec = 0;
if( cl_menu ){
menu_input_cooldown -= vg.time_frame_delta;
}
+#endif
}
/* https://iquilezles.org/articles/functions/ */
}
#endif /* MENU_H */
+#endif