X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=menu.h;h=30c025d17f085c61ed3961a6ed28490dc7223d61;hb=7fb47c3eb672f4468da8b5b452c09d44e1389d5f;hp=0bfdd261047b640c2d46a6e5dde5dbfd1f89b1fa;hpb=5af2a88b715579036a6c49397588ffe2e04400e1;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/menu.h b/menu.h index 0bfdd26..30c025d 100644 --- a/menu.h +++ b/menu.h @@ -5,456 +5,663 @@ #include "model.h" #include "world_render.h" #include "player.h" +#include "conf.h" +#include "shaders/model_menu.h" +#include "audio.h" +#include "input.h" +#include "workshop.h" -#include "shaders/menu.h" +#define MENU_STACK_SIZE 8 -static mdl_header *menu_model; -static glmesh menu_glmesh; -static m4x3f menu_mdl_mtx; -static float menu_opacity = 0.0f; -static float menu_input_cooldown = 0.0f; -static float menu_fov_target = 97.0f; -static v2f menu_extra_angles; +struct { + int active, credits_open; + f32 factive; + int disable_open; -static int menu_loc = 1, - menu_loc_last = 1; -static u32 menu_page = 0; + u32 page, /* current page index */ + page_depth; -static int cl_menu = 0, - cl_menu_go_away = 0; -static int cl_playermdl_id = 0; - -static const char *playermodels[] = { "ch_new", "ch_jordan", "ch_outlaw" }; - -static void menu_btn_paused( int event ); -static void menu_btn_quit( int event ); -static void menu_btn_skater( int event ); -static void menu_btn_map( int event ); -static void menu_btn_map_a( int event ); -static void menu_btn_map_b( int event ); -static void menu_btn_map_c( int event ); -static void menu_btn_fuckoff( int event ); - -struct menu_button -{ - const char *name; - u32 areas; + enum menu_input_mode{ + k_menu_input_mode_mouse, + k_menu_input_mode_keys + } + input_mode; + f32 mouse_track, mouse_dist; /* used for waking up mouse */ + f32 slider_offset; + + struct page_stack_frame { + u32 page; + ent_menuitem *loc; + ent_camera *cam; + } + page_stack[ MENU_STACK_SIZE ]; + + ent_menuitem *loc; + ent_camera *cam; + camera view; - void (*fn_press)(int event); - int links[4]; - mdl_node *pnode; + mdl_context model; + GLuint texture; + glmesh mesh; - float falpha, fsize; + mdl_array_ptr items, markers, cameras; } -static menu_buttons[] = -{ -/*0*/{"text_paused", 1, menu_btn_paused }, -/*1*/{"text_quit", 9, menu_btn_quit, {3,-1,4,2}}, -/*2*/{"text_skater", 3, menu_btn_skater, {3,1,4,-1}}, -/*3*/{"text_map", 5, menu_btn_map, {-1,-1,2,-1}}, -/*4*/{"text_about_game", 1, NULL, {2,-1,-1,-1}}, -/*5*/{"skater_left", 2, NULL, {-1,-1,-1,-1}}, -/*6*/{"skater_right", 2, NULL, {-1,-1,-1,-1}}, -/*7*/{"map_a", 4, menu_btn_map_a,{8, -1, 9, 9 }}, -/*8*/{"map_b", 4, menu_btn_map_b,{-1,7,7,-1}}, -/*9*/{"map_c", 4, menu_btn_map_c,{7,7,-1,8}}, -/*a*/{"g_map", 5, NULL }, -/*b*/{"g_controls", 1, NULL }, -/*c*/{"text_quitty", 8, NULL }, -/*d*/{"text_yes", 8, menu_btn_fuckoff,{-1,-1,-1,-1} }, -}; - -static void menu_btn_map_a( int event ){} -static void menu_btn_map_b( int event ){} -static void menu_btn_map_c( int event ){} - -static void menu_btn_paused( int event ) -{ +static menu; -} - -static void menu_btn_fuckoff( int event ) +/* + * Attaches memory locations to the various items in the menu + */ +static void menu_link(void) { - glfwSetWindowShouldClose( vg.window, 1 ); -} + /* link data locations */ + for( u32 i=0; itype == k_ent_menuitem_type_toggle || + item->type == k_ent_menuitem_type_slider ){ + + const char *name; -static void menu_btn_quit( int event ) -{ - menu_page = 0x8; - menu_loc = 0xd; + if( item->type == k_ent_menuitem_type_slider ) + name = mdl_pstr( &menu.model, item->slider.pstr_data ); + else + name = mdl_pstr( &menu.model, item->checkmark.pstr_data ); + vg_var *var = vg_console_match_var( name ); + + if( var ){ + if( ( item->type == k_ent_menuitem_type_slider && + var->data_type != k_var_dtype_f32 + ) || + ( item->type == k_ent_menuitem_type_toggle &&! + ( var->data_type == k_var_dtype_i32 || + var->data_type == k_var_dtype_u32 + ) + ) + ){ + vg_error( "Cannot hook to data %s(%p), because it is type %d.\n", + name, var, var->data_type ); + item->pvoid = NULL; + } + else{ + item->pvoid = var->data; + } + } + else{ + vg_error( "No data named %s\n", name ); + item->pvoid = NULL; + } + } + else{ + item->pvoid = NULL; + } + } } -static void menu_btn_map( int event ) +static void menu_init(void) { - menu_page = 0x4; - menu_loc = 7; -} + void *alloc = vg_mem.rtmemory; -static void menu_btn_skater( int event ) -{ - menu_page = 0x2; -} + mdl_open( &menu.model, "models/rs_menu.mdl", alloc ); + mdl_load_metadata_block( &menu.model, alloc ); -static void menu_init(void) -{ - menu_model = mdl_load( "models/rs_menu.mdl" ); + vg_linear_clear( vg_mem.scratch ); - if( !menu_model ) - vg_fatal_exit_loop( "No menu model" ); + 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 ); - for( int i=0; ipnode = mdl_node_from_name( menu_model, btn->name ); + vg_linear_clear( vg_mem.scratch ); - if( !btn->pnode ) - vg_fatal_exit_loop( "Menu programming error" ); - } + if( !mdl_arrcount( &menu.model.textures ) ) + vg_fatal_error( "No texture in menu file" ); - vg_convar_push( (struct vg_convar){ - .name = "cl_playermdl_id", - .data = &cl_playermdl_id, - .data_type = k_convar_dtype_i32, - .opt_i32 = { .min=0, .max=2, .clamp=1 }, - .persistent = 1 - }); + 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 ); - vg_acquire_thread_sync(); - mdl_unpack_glmesh( menu_model, &menu_glmesh ); - vg_release_thread_sync(); + 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 ); - shader_menu_register(); + mdl_close( &menu.model ); + shader_model_menu_register(); } -static void menu_run_directional(void) +/* + * Drop back a page until we're at the bottom which then we jus quit + */ +static void menu_back_page(void) { - struct menu_button *btn = &menu_buttons[ menu_loc ]; - - if( vg_get_button_down( "jump" ) ) - { - if( btn->fn_press ) - { - btn->fn_press( 1 ); - return; - } + vg_info( "menu_back_page()\n" ); + menu.page_depth --; + if( menu.page_depth == 0 ){ + menu.active = 0; + menu.page = 0xffffffff; } + else{ + menu.page = menu.page_stack[ menu.page_depth ].page; + menu.cam = menu.page_stack[ menu.page_depth ].cam; - if( menu_input_cooldown <= 0.0f ) - { - v2f dir = { vg_get_axis( "lookh" ), vg_get_axis( "lookv" ) }; - - if( v2_length2( dir ) > 0.8f*0.8f ) - { - int idir = 0; + if( menu.input_mode == k_menu_input_mode_keys ) + menu.loc = menu.page_stack[ menu.page_depth ].loc; + else menu.loc = NULL; + } +} - if( fabsf(dir[0]) > fabsf(dir[1]) ) - { - if( dir[0] > 0.0f ) idir = 2; - else idir = 0; - } - else - { - if( dir[1] > 0.0f ) idir = 3; - else idir = 1; - } +/* + * Open page to the string identifier + */ +static void menu_open_page( const char *name ) +{ + if( menu.page_depth >= MENU_STACK_SIZE ) + vg_fatal_error( "Stack overflow\n" ); - int link = btn->links[idir]; + vg_info( "Try to open %s\n", name ); - if( link != -1 ) - { - menu_loc_last = menu_loc; - menu_loc = link; - menu_input_cooldown = 0.25f; + u32 hash = vg_strdjb2( name ); + for( u32 i=0; itype == k_ent_menuitem_type_page ){ + if( mdl_pstreq( &menu.model, item->page.pstr_name, name, hash ) ){ + u32 new_page = __builtin_ctz( item->groups ); + + if( new_page == menu.page ){ + menu_back_page(); + } + else{ + menu.page_stack[ menu.page_depth ].page = menu.page; + menu.page_stack[ menu.page_depth ].cam = menu.cam; + menu.page_stack[ menu.page_depth ++ ].loc = menu.loc; + menu.page = __builtin_ctz( item->groups ); + + if( menu.input_mode == k_menu_input_mode_keys ){ + 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 ); + } + vg_info( "menu page: %u (%p,%p)\n", + menu.page, menu.loc, menu.cam ); + } + return; } } } } -static int menu_page_should_backout(void) -{ - return vg_get_button_down( "break" ); -} - -static void menu_close(void) +/* + * activate a pressable type + */ +static void menu_trigger_item( ent_menuitem *item ) { - cl_menu_go_away = 1; - menu_page = 0; -} + if ( item->type == k_ent_menuitem_type_event_button ){ + u32 q = item->button.pstr; -static void menu_page_main(void) -{ - if( menu_page_should_backout() ) - { - menu_close(); - return; + if( MDL_CONST_PSTREQ( &menu.model, q, "quit" ) ){ + vg.window_should_close = 1; + } + else if( MDL_CONST_PSTREQ( &menu.model, q, "reset" ) ){ + localplayer_cmd_respawn( 0, NULL ); + + menu.page_depth = 0; + menu.active = 0; + menu.page = 0xffffffff; + } + else if( MDL_CONST_PSTREQ( &menu.model, q, "credits" ) ){ + menu.credits_open = 1; + } + else if( MDL_CONST_PSTREQ( &menu.model, q, "workshop" ) ){ + workshop_submit_command(0,NULL); + } + } + else if( item->type == k_ent_menuitem_type_page_button ){ + menu_open_page( mdl_pstr( &menu.model, item->button.pstr ) ); + } + else if( item->type == k_ent_menuitem_type_toggle ){ + if( item->pi32 ){ + *item->pi32 = *item->pi32 ^ 0x1; + } } - - menu_fov_target = 112.0f; - menu_run_directional(); } -static void menu_page_map(void) +static f32 menu_slider_snap( f32 value, f32 old, f32 notch ) { - if( menu_page_should_backout() ) - { - menu_page = 1; - menu_loc = 3; - } + f32 const k_epsilon = 0.0125f; - menu_fov_target = 80.0f; - menu_run_directional(); -} + if( fabsf(notch-value) < k_epsilon ){ + if( fabsf(notch-old) > k_epsilon ){ + audio_lock(); + audio_oneshot( &audio_ui[0], 1.0f, 0.0f ); + audio_unlock(); + } -static void menu_page_quit(void) -{ - if( menu_page_should_backout() ) - { - menu_page = 1; - menu_loc = 1; + return notch; } - - menu_fov_target = 90.0f; - menu_run_directional(); + else + return value; } -static void menu_page_skater(void) +/* + * Run from vg_gui every frame + */ +static void menu_update(void) { - float h = vg_get_axis( "lookh" ); - menu_fov_target = 97.0f; + if( workshop_form.page != k_workshop_form_hidden ){ + return; + } - if( menu_page_should_backout() ) - { - menu_page = 1; - menu_loc = 2; + int escape = button_down( k_srbind_mback ); + if( menu.credits_open ){ + if( escape ){ + menu.credits_open = 0; + } return; } - if( (fabsf(h) > 0.7f) && (menu_input_cooldown <= 0.0f) ) - { - if( h < 0.0f ) - { - cl_playermdl_id --; - if( cl_playermdl_id < 0 ) - cl_playermdl_id = 2; + if( button_down( k_srbind_mopen ) ){ + if( !menu.active && !menu.disable_open ){ + menu.active = 1; + menu.page = 0xffffffff; + menu_open_page( "Main Menu" ); + return; + } + } + + menu.factive = vg_lerpf( menu.factive, menu.active, + vg.time_frame_delta * 6.0f ); - menu_buttons[5].fsize = 0.4f; - menu_buttons[5].falpha = 1.0f; + if( !menu.active ) return; - menu_input_cooldown = 0.25f; - player_load_model( playermodels[ cl_playermdl_id ], 1 ); - } - else - { - cl_playermdl_id ++; - if( cl_playermdl_id > 2 ) - cl_playermdl_id = 0; - - menu_buttons[6].fsize = 0.4f; - menu_buttons[6].falpha = 1.0f; + enum menu_input_mode prev_mode = menu.input_mode; - menu_input_cooldown = 0.25f; - player_load_model( playermodels[ cl_playermdl_id ], 1 ); - } + /* get buttons inputs + * -------------------------------------------------------------------*/ + 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 ); + + if( mh||mv||enter ){ + menu.input_mode = k_menu_input_mode_keys; } -} -static void menu_update(void) -{ - if( vg_get_button_down( "menu" ) ) - { - if( cl_menu ) - { - cl_menu_go_away = 1; - menu_page = 0; - } - else - { - cl_menu = 1; - menu_page = 1; + /* get mouse inputs + * --------------------------------------------------------------------*/ + menu.mouse_dist += v2_length( vg.mouse_delta ); /* TODO: Move to UI */ + menu.mouse_track += vg.time_frame_delta; + if( menu.mouse_track > 0.1f ){ + menu.mouse_track = fmodf( menu.mouse_track, 0.1f ); + if( menu.mouse_dist > 10.0f ){ + menu.input_mode = k_menu_input_mode_mouse; + menu.mouse_dist = 0.0f; } } - if( menu_page == 1 ) - menu_page_main(); - else if( menu_page == 2 ) - menu_page_skater(); - else if( menu_page == 4 ) - menu_page_map(); - else if( menu_page == 8 ) - menu_page_quit(); - - struct menu_button *btn = &menu_buttons[ menu_loc ]; - - v3f pos; - v2f angles; + if( ui_clicking(UI_MOUSE_LEFT) || ui_clicking(UI_MOUSE_RIGHT) ){ + menu.input_mode = k_menu_input_mode_mouse; + } - /* Base */ - { - v3f lookdir; - v3f *mtx = player.mdl.sk.final_mtx[player.mdl.id_head]; - m3x3_mulv( mtx, (v3f){-1.0f,0.0f,0.0f}, lookdir ); + if( menu.input_mode == k_menu_input_mode_mouse ){ + /* + * handle mouse input + * ------------------------------------------------------------*/ + vg_ui.wants_mouse = 1; + + /* + * this raycasting is super cumbersome because all the functions were + * designed for other purposes. we dont care though. + */ + m4x4f inverse; + m4x4_inv( menu.view.mtx.p, inverse ); + v4f coords; + coords[0] = vg_ui.mouse[0]; + coords[1] = vg.window_y - vg_ui.mouse[1]; + v2_div( coords, (v2f){ vg.window_x, vg.window_y }, coords ); + v2_muls( coords, 2.0f, coords ); + v2_add( coords, (v2f){-1.0f,-1.0f}, coords ); + coords[2] = 1.0f; + coords[3] = 1.0f; + m4x4_mulv( inverse, coords, coords ); + v3f ray; + m3x3_mulv( menu.view.transform, coords, ray ); + v3_normalize( ray ); + + if( menu.loc && (menu.loc->type == k_ent_menuitem_type_slider) && + ui_clicking(UI_MOUSE_LEFT) && menu.loc->pf32 ){ + + u32 il = mdl_entity_id_id( menu.loc->slider.id_min ), + ir = mdl_entity_id_id( menu.loc->slider.id_max ); + ent_marker *ml = mdl_arritm( &menu.markers, il ), + *mr = mdl_arritm( &menu.markers, ir ); + + v3f q2; + v3_muladds( menu.view.pos, ray, 100.0f, q2 ); + + f32 s,t; + v3f c1, c2; + v3f p1, q1, v0; + v3_sub( mr->transform.co, ml->transform.co, v0 ); + v3_muladds( ml->transform.co, v0, -1.0f, p1 ); + v3_muladds( mr->transform.co, v0, 1.0f, q1 ); + closest_segment_segment( p1, q1, menu.view.pos, q2, &s,&t, c1,c2 ); + + s-=(1.0f/3.0f); + s/=(1.0f/3.0f); + + if( ui_click_down(UI_MOUSE_LEFT) ){ + menu.slider_offset = *menu.loc->pf32 - s; + } - lookdir[1] = 0.0f; - v3_normalize( lookdir ); + f32 newvalue = vg_clampf( s+menu.slider_offset, 0.0f, 1.0f ); - v3f center_rough; + newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 0.00f ); + newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 1.00f ); + newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 0.25f ); + newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 0.50f ); + newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 0.75f ); - if( player.is_dead ) - { - v3_copy(player.mdl.ragdoll[ player.mdl.id_hip-1 ].rb.co, center_rough); - } - else - { - v3_add( player.camera_pos, player.visual_transform[3], center_rough ); - v3_muls( center_rough, 0.5f, center_rough ); + *menu.loc->pf32 = newvalue; + return; } - v3_muladds( center_rough, lookdir, 1.5f, pos ); - v3_add( (v3f){ 0.0f,0.8f,0.0f}, pos, pos ); + ent_menuitem *hit_item = NULL; - angles[1] = 0.0f; - angles[0] = -atan2f( lookdir[0], lookdir[2] ); + for( u32 i=0; itype == k_ent_menuitem_type_page ) continue; + if( item->type == k_ent_menuitem_type_visual ) continue; + if( !(item->groups & (0x1<pnode->co, (v3f){ 0.0f,1.5f,-1.5f }, delta ); - v3_normalize( delta ); + if( item->type == k_ent_menuitem_type_slider ){ + u32 subtarget = mdl_entity_id_id( item->slider.id_handle ); + ray_item = mdl_arritm( &menu.items, subtarget ); + } + + v3f local_ray, + local_co; - float y = atan2f( delta[0], delta[2] ), - p = -sinf(delta[1]), - dt = vg.frame_delta; + m4x3f inverse_mtx; + mdl_transform_m4x3( &ray_item->transform, inverse_mtx ); + m4x3_invert_full( inverse_mtx, inverse_mtx ); + + m4x3_mulv( inverse_mtx, menu.view.transform[3], local_co ); + m3x3_mulv( inverse_mtx, ray, local_ray ); + v3_normalize( local_ray ); + + local_ray[0] = 1.0f/local_ray[0]; + local_ray[1] = 1.0f/local_ray[1]; + local_ray[2] = 1.0f/local_ray[2]; + + for( u32 j=0; jsubmesh_count; j++ ){ + mdl_submesh *sm = mdl_arritm( &menu.model.submeshs, + ray_item->submesh_start + j ); + if( ray_aabb1( sm->bbx, local_co, local_ray, 1000.0f ) ){ + hit_item = item; + break; + } + } + } - menu_extra_angles[0] = vg_lerpf( menu_extra_angles[0], y, dt ); - menu_extra_angles[1] = vg_lerpf( menu_extra_angles[1], p, dt ); + if( hit_item != menu.loc ){ + menu.loc = hit_item; + } - v2_muladds( angles, menu_extra_angles, 0.8f, angles ); - angles[0] = fmodf( angles[0], VG_TAUf ); - } - - /* Update camera */ - { - camera_angles[0] = vg_alerpf( camera_angles[0], angles[0], menu_opacity ); - camera_angles[1] = vg_lerpf ( camera_angles[1], angles[1], menu_opacity ); - v3_lerp( camera_pos, pos, menu_opacity, camera_pos ); - camera_update(); + if( escape ){ + menu_back_page(); + } + else if( menu.loc ){ + if( ui_click_down( UI_MOUSE_LEFT ) ){ + menu_trigger_item( menu.loc ); + } + } } + else if( menu.input_mode == k_menu_input_mode_keys ){ + /* + * handle button input + * ------------------------------------------------------------*/ + if( (prev_mode != k_menu_input_mode_keys) && !menu.loc ){ + for( u32 i=0; itype != k_ent_menuitem_type_page) && + (item->type != k_ent_menuitem_type_visual) && + (item->groups & (0x1<type == k_ent_menuitem_type_slider && menu.loc->pf32 ){ + f32 move = 0.0f; - vg.time_rate = 1.0-(double)menu_opacity; + if( vg_input.display_input_method == k_input_method_controller ){ + move += button_press( k_srbind_mright ); + move -= button_press( k_srbind_mleft ); + } + else{ + move += axis_state( k_sraxis_mbrowse_h ); + } - if( cl_menu ) - { - menu_input_cooldown -= vg.frame_delta; - } -} + move *= vg.time_frame_delta; + *menu.loc->pf32 = vg_clampf( *menu.loc->pf32 + move, 0.0f, 1.0f ); -/* https://iquilezles.org/articles/functions/ */ -float expSustainedImpulse( float x, float f, float k ) -{ - float s = fmaxf(x-f,0.0f); - return fminf( x*x/(f*f), 1.0f+(2.0f/f)*s*expf(-k*s)); + mh = 0; + } + + if( escape ){ + menu_back_page(); + } + else if( enter ){ + menu_trigger_item( menu.loc ); + } + 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; + } + } + } } -static void menu_render( m4x4f projection ) +/* + * Run from vg_gui when active + */ +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_fscolour_use(); - shader_fscolour_uColour( (v4f){ 0.1f, 0.1f, 0.3f, menu_opacity*0.5f } ); + shader_blitcolour_use(); + v4f colour; + ui_hex_to_norm( ui_colour( k_ui_bg+3 ), colour ); + colour[3] = 0.5f; + + shader_blitcolour_uColour( colour ); render_fsquad(); + if( workshop_form.page != k_workshop_form_hidden ){ + return; + } + + if( menu.credits_open ){ + ui_rect panel = { 0,0, 460, 400 }, + screen = { 0,0, vg.window_x,vg.window_y }; + ui_rect_center( screen, panel ); + ui_fill( panel, ui_colour(k_ui_bg) ); + ui_outline( panel, 1, ui_colour(k_ui_fg) ); + ui_rect_pad( panel, (ui_px[]){8,8} ); + + ui_rect title; + ui_split( panel, k_ui_axis_h, 28*2, 0, title, panel ); + ui_text( title, "Skate Rift - Credits", 2, k_ui_align_middle_center, 0 ); + ui_split( panel, k_ui_axis_h, 28, 0, title, panel ); + ui_text( title, "Mt.Zero Software", 1, k_ui_align_middle_center, 0 ); + + ui_split( panel, k_ui_axis_h, 8, 0, title, panel ); + ui_split( panel, k_ui_axis_h, 28, 0, title, panel ); + ui_text( title, "A game by Harry Godden", 1, + k_ui_align_middle_center, 0 ); + + ui_split( panel, k_ui_axis_h, 8, 0, title, panel ); + ui_split( panel, k_ui_axis_h, 28*2, 0, title, panel ); + ui_text( title, "Free Software", 2, k_ui_align_middle_center, 0 ); + + ui_split( panel, k_ui_axis_h, 8, 0, title, panel ); + ui_text( panel, + "Sam Lantinga - SDL2 - libsdl.org\n" + "Hunter WB - Anyascii\n" + "David Herberth - GLAD\n" + "Dominic Szablewski - QOI - qoiformat.org\n" + "Sean Barrett - stb_image,stb_vorbis,stb_include\n" + "Khronos Group - OpenGL\n" + , 1, k_ui_align_left, 0 ); + return; + } + glEnable( GL_DEPTH_TEST ); glDisable( GL_BLEND ); - m4x3f mtx; - - shader_menu_use(); - shader_menu_uColour( (v4f){ 1.0f,1.0f,1.0f,1.0f} ); - shader_menu_uTexMain( 1 ); - vg_tex2d_bind( &tex_graffiti, 1 ); - - shader_menu_uPv( projection ); - mesh_bind( &menu_glmesh ); - - for( int i=0; iareas & menu_page? 1.0f: 0.0f, - tsize1 = i==menu_loc? 0.07f: 0.0f, - tsize = tsize0+tsize1; - - btn->falpha = vg_lerpf( btn->falpha, talpha, vg.frame_delta * 14.0f ); - btn->fsize = vg_lerpf( btn->fsize, tsize, vg.frame_delta * 3.0f ); - - /* Colour */ - v4f vselected = {0.95f*1.3f,0.45f*1.3f,0.095f*1.3f, 1.0f}, - vnormal = {1.0f,1.0f,1.0f, 1.0f}, - vcurrent; - - v4_lerp( vnormal, vselected, btn->falpha, vcurrent ); - shader_menu_uColour( vcurrent ); - - /* Create matrix */ - m4x3f mtx_size; - mdl_node_transform( btn->pnode, mtx ); - m4x3_mul( menu_mdl_mtx, mtx, mtx ); - m4x3_identity( mtx_size ); - m4x3_scale( mtx_size, expSustainedImpulse( btn->fsize, 0.5f, 8.7f) ); - m4x3_mul( mtx, mtx_size, mtx ); - shader_menu_uMdl( mtx ); - - for( int j=0; jpnode->submesh_count; j++ ) - { - mdl_submesh *sm = - mdl_submesh_from_id( menu_model, btn->pnode->submesh_start+j ); - mdl_draw_submesh( sm ); - } + f32 rate = vg.time_frame_delta * 12.0f; + + if( menu.cam ){ + camera target; + + target.fov = menu.cam->fov; + v3_copy( menu.cam->transform.co, target.pos ); + + v3f v0; + mdl_transform_vector( &menu.cam->transform, (v3f){0.0f,-1.0f,0.0f}, v0 ); + player_vector_angles( target.angles, v0, 1.0f, 0.0f ); + + camera_lerp( &menu.view, &target, rate, &menu.view ); + + menu.view.farz = 150.0f; + menu.view.nearz = 0.01f; + + camera_update_transform( &menu.view ); + camera_update_view( &menu.view ); + camera_update_projection( &menu.view ); + camera_finalize( &menu.view ); } - - /* - for( int i=0; inode_count; i++ ) - { - mdl_node *pnode = mdl_node_from_id( menu_model, i ); + 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 ); + + v4f white, blue; + + ui_hex_to_norm( ui_colour( k_ui_fg ), white ); + ui_hex_to_norm( ui_colour( k_ui_orange+k_ui_brighter ), blue ); + + for( u32 i=0; itype == k_ent_menuitem_type_page ) continue; + if( !(item->groups & (0x1 << menu.page)) ) continue; + + int selected = 0; - for( int j=0; jsubmesh_count; j++ ) - { - mdl_submesh *sm = - mdl_submesh_from_id( menu_model, pnode->submesh_start+j ); + if( menu.loc ){ + if( menu.loc->type == k_ent_menuitem_type_slider ){ + u32 subid = menu.loc->slider.id_handle; + if( item == mdl_arritm( &menu.items, mdl_entity_id_id(subid) )) + selected = 1; + } + else{ + if( item == menu.loc ) + selected = 1; + } + } + + item->factive = vg_lerpf( item->factive, selected, rate ); + v4f colour; + v4_lerp( white, blue, item->factive, colour ); + shader_model_menu_uColour( colour ); + + f32 scale = 1.0f+item->factive*0.1f; - mdl_node_transform( pnode, mtx ); - m4x3_mul( menu_mdl_mtx, mtx, mtx ); - shader_menu_uMdl( mtx ); + m4x3f mmdl; + mdl_transform transform = item->transform; + v3_muls( transform.s, scale, transform.s ); + mdl_transform_m4x3( &transform, mmdl ); - mdl_draw_submesh( sm ); + if( item->type == k_ent_menuitem_type_toggle && item->pi32 ){ + u32 subid = mdl_entity_id_id( item->checkmark.id_check ); + ent_menuitem *subitem = mdl_arritm( &menu.items, subid ); + + v3_muladds( item->transform.co, item->checkmark.offset, scale, + subitem->transform.co ); + + subitem->fvisible = vg_lerpf( subitem->fvisible, *item->pi32, rate ); + v3_fill( subitem->transform.s, subitem->fvisible ); + } + else if( item->type == k_ent_menuitem_type_slider && item->pf32 ){ + u32 il = mdl_entity_id_id( item->slider.id_min ), + ir = mdl_entity_id_id( item->slider.id_max ), + ih = mdl_entity_id_id( item->slider.id_handle ); + ent_marker *ml = mdl_arritm( &menu.markers, il ), + *mr = mdl_arritm( &menu.markers, ir ); + ent_menuitem *handle = mdl_arritm( &menu.items, ih ); + + v3_lerp( ml->transform.co, mr->transform.co, *item->pf32, + handle->transform.co ); } - } - */ -} -static void menu_free(void *_) -{ - mesh_free( &menu_glmesh ); + shader_model_menu_uMdl( mmdl ); + + for( u32 j=0; jsubmesh_count; j++ ){ + u32 index = item->submesh_start + j; + mdl_draw_submesh( mdl_arritm( &menu.model.submeshs, index )); + } + } } #endif /* MENU_H */