From 223e75026f958029f9664380ed20a5daa3ee2ae7 Mon Sep 17 00:00:00 2001 From: hgn Date: Fri, 28 Apr 2023 23:56:21 +0100 Subject: [PATCH] the pain is gone --- ent_skateshop.c | 7 +- font.h | 85 +++++++++----- gui.h | 22 +++- input.h | 256 +++++++++++++++++++++++++++++++++++------ models_src/rs_font.mdl | Bin 913928 -> 929416 bytes player_common.c | 7 +- player_drive.c | 8 +- player_skate.c | 55 ++++++--- player_walk.c | 14 ++- 9 files changed, 355 insertions(+), 99 deletions(-) diff --git a/ent_skateshop.c b/ent_skateshop.c index 9d31a26..6cf47dc 100644 --- a/ent_skateshop.c +++ b/ent_skateshop.c @@ -323,6 +323,7 @@ next_file: tinydir_next( &dir ); VG_STATIC void global_skateshop_exit(void) { + vg_info( "exit skateshop\n" ); localplayer.immobile = 0; global_skateshop.active = 0; } @@ -439,9 +440,9 @@ VG_STATIC void global_skateshop_preupdate(void) if( global_skateshop.interface_loc <= k_skateshop_loc_page__viewing ){ - gui_helper_action( NULL, "\x88 \x02\xaf\x03""browse" ); - gui_helper_action( NULL, "\x1e\x85 \x02\xaf\x03""pick" ); - gui_helper_action( NULL, "\x1e\x86 \x02\xaf\x03""exit" ); + gui_helper_action( axis_display_string( k_sraxis_mbrowse_h ), "browse" ); + gui_helper_action( button_display_string( k_srbind_maccept ), "pick" ); + gui_helper_action( button_display_string( k_srbind_mback ), "exit" ); int moved = 0; diff --git a/font.h b/font.h index 82af99a..b1185f9 100644 --- a/font.h +++ b/font.h @@ -53,7 +53,9 @@ enum efont_SRglyph{ k_SRglyph_kbm_ctrl = 0x9f, k_SRglyph_kbm_alt = 0xa0, k_SRglyph_kbm_space = 0xa1, - k_SRglyph_kbm_return = 0xa2 + k_SRglyph_kbm_return = 0xa2, + k_SRglyph_kbm_escape = 0xa3, + k_SRglyph_kbm_mousemove = 0xa4 }; typedef struct font3d font3d; @@ -138,61 +140,77 @@ VG_STATIC ent_glyph *font3d_glyph( font3d *font, u32 variant_id, u32 utf32 ) return mdl_arritm( &font->glyphs, index ); } +struct font3d_render{ + v4f offset; + font3d *font; + const u8 *u8pch; + u32 variant_id; +}; + VG_STATIC -float font3d_simple_draw( font3d *font, u32 variant_id, const char *text, - camera *cam, m4x3f transform ) +void font3d_begin( font3d *font, u32 variant_id, + camera *cam, m4x3f transform, struct font3d_render *render ) { - v4f offset; - q_identity( offset ); + q_identity( render->offset ); m4x4f prev_mtx; - m4x3_expand( transform, prev_mtx ); m4x4_mul( cam->mtx_prev.pv, prev_mtx, prev_mtx ); shader_model_font_uPvmPrev( prev_mtx ); shader_model_font_uMdl( transform ); - const u8 *u8str = (u8*)text; + render->font = font; + render->variant_id = variant_id; +} + +VG_STATIC void font3d_draw( struct font3d_render *render ) +{ + u32 max_chars = 512; + while( render->u8pch && max_chars ){ + max_chars --; - for( u32 i=0;; i++ ){ - u32 c0 = u8str[i], - c1; + u32 c0 = *render->u8pch, c1; + render->u8pch ++; if( !c0 ) break; - ent_glyph *glyph0 = font3d_glyph( font, variant_id, c0 ), + ent_glyph *glyph0 = font3d_glyph( render->font, render->variant_id, c0 ), *glyph1; /* multibyte characters */ if( c0 >= 1 && c0 < k_SRglyph_ascii_min ){ - c1 = u8str[i+1]; + c1 = *render->u8pch; if( !c1 ) break; - glyph1 = font3d_glyph( font, variant_id, c1 ); + glyph1 = font3d_glyph( render->font, render->variant_id, c1 ); } if( c0 == k_SRglyph_ctrl_variant ){ - variant_id = c1; - i ++; + render->variant_id = c1; + render->u8pch ++; continue; } else if( c0 == k_SRglyph_ctrl_size ){ - offset[3] = (float)c1 * (1.0f/255.0f); - i ++; + render->offset[3] = (float)c1 * (1.0f/255.0f); + render->u8pch ++; continue; } else if( c0 == k_SRglyph_ctrl_baseline ){ - offset[1] = 0.0f; + render->offset[1] = 0.0f; continue; } else if( c0 == k_SRglyph_ctrl_center ){ - if( glyph1 ) - offset[1] = (glyph1->size[1] - glyph1->size[1]*offset[3]) * 0.5f; + if( glyph1 ){ + float diff = glyph1->size[1] - glyph1->size[1]*render->offset[3]; + render->offset[1] = diff * 0.5f; + } continue; } else if( c0 == k_SRglyph_ctrl_top ){ - if( glyph1 ) - offset[1] = glyph1->size[1] - glyph1->size[1]*offset[3]; + if( glyph1 ){ + float diff = glyph1->size[1] - glyph1->size[1]*render->offset[3]; + render->offset[1] = diff; + } continue; } @@ -201,23 +219,34 @@ float font3d_simple_draw( font3d *font, u32 variant_id, const char *text, if( glyph1 && (c0 == k_SRglyph_mod_square || c0 == k_SRglyph_mod_circle)){ v4f v0; v2_sub( glyph0->size, glyph1->size, v0 ); - v2_muladds( offset, v0, -0.5f, v0 ); - v0[2] = offset[2]; - v0[3] = offset[3]; + v2_muladds( render->offset, v0, -0.5f, v0 ); + v0[2] = render->offset[2]; + v0[3] = render->offset[3]; shader_model_font_uOffset( v0 ); mesh_drawn( glyph0->indice_start, glyph0->indice_count ); continue; } else{ - shader_model_font_uOffset( offset ); + shader_model_font_uOffset( render->offset ); mesh_drawn( glyph0->indice_start, glyph0->indice_count ); } - offset[0] += glyph0->size[0]*offset[3]; + render->offset[0] += glyph0->size[0]*render->offset[3]; } - return offset[0]; + render->u8pch = NULL; +} + +VG_STATIC +float font3d_simple_draw( font3d *font, u32 variant_id, const char *text, + camera *cam, m4x3f transform ) +{ + struct font3d_render render; + font3d_begin( font, variant_id, cam, transform, &render ); + render.u8pch = (u8*)text; + font3d_draw( &render ); + return render.offset[0]; } VG_STATIC diff --git a/gui.h b/gui.h index 8cb94f1..2ec0a50 100644 --- a/gui.h +++ b/gui.h @@ -5,8 +5,7 @@ struct{ struct gui_helper{ - struct input_binding *bind; - const char *text; + const char *bindstr, *text; } helpers[4]; u32 helper_count; @@ -73,7 +72,20 @@ void gui_draw(void) shader_model_font_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} ); - float w = font3d_simple_draw( font, 2, helper->text, &ortho, mmdl )+1.0f; + struct font3d_render render; + font3d_begin( font, 2, &ortho, mmdl, &render ); + + render.u8pch = (u8*)helper->bindstr; + font3d_draw( &render ); + + const char *make_smaller = "\x02\xaf\x03 "; + render.u8pch = (const u8*)make_smaller; + font3d_draw( &render ); + + render.u8pch = (u8*)helper->text; + font3d_draw( &render ); + + float w = render.offset[0]+1.0f; mmdl[3][0] += w*scale; } @@ -81,13 +93,13 @@ void gui_draw(void) } VG_STATIC -void gui_helper_action( void *bind, const char *text ) +void gui_helper_action( const char *bindstr, const char *text ) { if( gui.helper_count >= vg_list_size(gui.helpers) ) vg_fatal_error( "Too many helpers\n" ); struct gui_helper *helper = &gui.helpers[ gui.helper_count ++ ]; - helper->bind = bind; + helper->bindstr = bindstr; helper->text = text; } diff --git a/input.h b/input.h index c6710f2..6f19634 100644 --- a/input.h +++ b/input.h @@ -8,6 +8,7 @@ #include "vg/vg_input.h" #include "vg/vg_m.h" #include "conf.h" +#include "font.h" enum sr_bind{ k_srbind_jump = 0, @@ -24,29 +25,174 @@ enum sr_bind{ k_srbind_mdown, k_srbind_mback, k_srbind_maccept, - k_srbind_max + k_srbind_mopen, + k_srbind_max, }; -struct { - v2f joy_steer, - joy_grab, - joy_look; +enum sr_joystick{ + k_srjoystick_steer = 0, + k_srjoystick_grab, + k_srjoystick_look, + k_srjoystick_max +}; - float axis_grab; +enum sr_axis{ + k_sraxis_grab = 0, + k_sraxis_mbrowse_h, + k_sraxis_mbrowse_v, + k_sraxis_max +}; +struct { + float axis_states[ k_sraxis_max ][2]; + v2f joystick_states[ k_srjoystick_max ][2]; u8 button_states[ k_srbind_max ][2]; - float repeaters[4]; } static srinput; -static int button_down( enum sr_bind button ) +static const char *controller_glyphs[ SDL_CONTROLLER_BUTTON_MAX ][2] = +{ /* xbox/generic playstation */ + [ SDL_CONTROLLER_BUTTON_A ] = { "\x1e\x85","\x1e\x82" }, + [ SDL_CONTROLLER_BUTTON_B ] = { "\x1e\x86","\x1e\x81" }, + [ SDL_CONTROLLER_BUTTON_X ] = { "\x1e\x83","\x1e\x7f" }, + [ SDL_CONTROLLER_BUTTON_Y ] = { "\x1e\x84","\x1e\x80" }, + [ SDL_CONTROLLER_BUTTON_LEFTSTICK ] = { "\x87", "\x87" }, + [ SDL_CONTROLLER_BUTTON_RIGHTSTICK ] = { "\x8b", "\x8b" }, + [ SDL_CONTROLLER_BUTTON_LEFTSHOULDER ] = { "\x91", "\x91" }, + [ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER ]= { "\x92", "\x92" }, + [ SDL_CONTROLLER_BUTTON_DPAD_LEFT ] = { "\x1e\x93","\x1e\x93" }, + [ SDL_CONTROLLER_BUTTON_DPAD_UP ] = { "\x1e\x94","\x1e\x94" }, + [ SDL_CONTROLLER_BUTTON_DPAD_RIGHT ] = { "\x1e\x95","\x1e\x95" }, + [ SDL_CONTROLLER_BUTTON_DPAD_DOWN ] = { "\x1e\x96","\x1e\x96" }, + [ SDL_CONTROLLER_BUTTON_GUIDE ] = { "\x91", "\x91" }, +}; + +static const char *controller_glyph( u32 sdl_index ) +{ + if( vg_input.display_input_type == SDL_CONTROLLER_TYPE_PS3 || + vg_input.display_input_type == SDL_CONTROLLER_TYPE_PS4 || + vg_input.display_input_type == SDL_CONTROLLER_TYPE_PS5 ) + { + return controller_glyphs[ sdl_index ][ 1 ]; + } + else if( vg_input.display_input_type == + SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO || + vg_input.display_input_type == + SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT || + vg_input.display_input_type == + SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR || + vg_input.display_input_type == + SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT ) + { + return NULL; + } + else + return controller_glyphs[ sdl_index ][ 0 ]; +} + +#define KEYBOARD_GLYPH( X ) "\x1f" X " " + +static const char *button_display_string( enum sr_bind button ) +{ + const char *controller_table[ k_srbind_max ] = { + [k_srbind_jump] = controller_glyph( SDL_CONTROLLER_BUTTON_A ), + [k_srbind_push] = controller_glyph( SDL_CONTROLLER_BUTTON_B ), + [k_srbind_trick0] = controller_glyph( SDL_CONTROLLER_BUTTON_A ), + [k_srbind_trick1] = controller_glyph( SDL_CONTROLLER_BUTTON_B ), + [k_srbind_trick2] = controller_glyph( SDL_CONTROLLER_BUTTON_X ), + [k_srbind_use] = controller_glyph( SDL_CONTROLLER_BUTTON_Y ), + [k_srbind_reset] = controller_glyph( SDL_CONTROLLER_BUTTON_LEFTSHOULDER ), + [k_srbind_camera] = controller_glyph( SDL_CONTROLLER_BUTTON_RIGHTSHOULDER ), + [k_srbind_mleft] = controller_glyph( SDL_CONTROLLER_BUTTON_DPAD_LEFT ), + [k_srbind_mright] = controller_glyph( SDL_CONTROLLER_BUTTON_DPAD_RIGHT ), + [k_srbind_mup] = controller_glyph( SDL_CONTROLLER_BUTTON_DPAD_UP ), + [k_srbind_mdown] = controller_glyph( SDL_CONTROLLER_BUTTON_DPAD_DOWN ), + [k_srbind_mback] = controller_glyph( SDL_CONTROLLER_BUTTON_B ), + [k_srbind_maccept]= controller_glyph( SDL_CONTROLLER_BUTTON_A ), + [k_srbind_mopen] = controller_glyph( SDL_CONTROLLER_BUTTON_GUIDE ) + }; + + const char *keyboard_table[ k_srbind_max ] = { + [k_srbind_jump] = KEYBOARD_GLYPH( "A" ), + [k_srbind_push] = KEYBOARD_GLYPH( "W" ), + [k_srbind_trick0] = "\x99", + [k_srbind_trick1] = "\x9a", + [k_srbind_trick2] = "\x9b", + [k_srbind_use] = KEYBOARD_GLYPH( "E" ), + [k_srbind_reset] = KEYBOARD_GLYPH( "R" ), + [k_srbind_camera] = KEYBOARD_GLYPH( "C" ), + [k_srbind_mleft] = KEYBOARD_GLYPH( "\x93" ), + [k_srbind_mright] = KEYBOARD_GLYPH( "\x95" ), + [k_srbind_mup] = KEYBOARD_GLYPH( "\x94" ), + [k_srbind_mdown] = KEYBOARD_GLYPH( "\x96" ), + [k_srbind_mback] = "\xa3", + [k_srbind_maccept]= "\xa2", + [k_srbind_mopen] = "\xa3" , + }; + + if( vg_input.display_input_method == k_input_method_controller ) + return controller_table[ button ]; + else + return keyboard_table[ button ]; +} + +static const char *axis_display_string( enum sr_axis axis ) +{ + const char *controller_table[ k_sraxis_max ] = { + [k_sraxis_grab] = "\x90", + [k_sraxis_mbrowse_h] = "\x88", + [k_sraxis_mbrowse_v] = "\x89" + }; + + const char *keyboard_table[ k_sraxis_max ] = { + [k_sraxis_grab] = "\x9e", + [k_sraxis_mbrowse_h] = KEYBOARD_GLYPH("\x93")KEYBOARD_GLYPH("\x95"), + [k_sraxis_mbrowse_v] = KEYBOARD_GLYPH("\x96")KEYBOARD_GLYPH("\x94") + }; + + if( vg_input.display_input_method == k_input_method_controller ) + return controller_table[ axis ]; + else + return keyboard_table[ axis ]; +} + +static const char *joystick_display_string( enum sr_joystick joystick ) +{ + const char *controller_table[ k_srjoystick_max ] = { + [k_srjoystick_steer] = "\x88", + [k_srjoystick_grab] = "\x8e", + [k_srjoystick_look] = "\x8e" + }; + + const char *keyboard_table[ k_srjoystick_max ] = { + [k_srjoystick_steer] = KEYBOARD_GLYPH( "\x93" )KEYBOARD_GLYPH( "\x95" ), + [k_srjoystick_grab] = "\xa4", + [k_srjoystick_look] = "\xa4" + }; + + if( vg_input.display_input_method == k_input_method_controller ) + return controller_table[ joystick ]; + else + return keyboard_table[ joystick ]; +} + +static int buttons_filter_fixed(void) { if( vg_console.enabled ) - return 0; + return 1; if( vg.engine_stage == k_engine_stage_update_fixed ) if( vg.fixed_iterations > 0 ) - return 0; + return 1; + + return 0; +} + +/* Rising edge of button */ +static int button_down( enum sr_bind button ) +{ + if( buttons_filter_fixed() ) + return 0; if( srinput.button_states[ button ][0] && !srinput.button_states[ button ][1] ) @@ -55,14 +201,11 @@ static int button_down( enum sr_bind button ) return 0; } +/* Falling edge of button */ static int button_up( enum sr_bind button ) { - if( vg_console.enabled ) + if( buttons_filter_fixed() ) return 0; - - if( vg.engine_stage == k_engine_stage_update_fixed ) - if( vg.fixed_iterations > 0 ) - return 0; if( !srinput.button_states[ button ][0] && srinput.button_states[ button ][1] ) @@ -71,6 +214,7 @@ static int button_up( enum sr_bind button ) return 0; } +/* State of button */ static int button_press( enum sr_bind button ) { if( vg_console.enabled ) @@ -79,6 +223,20 @@ static int button_press( enum sr_bind button ) return srinput.button_states[ button ][0]; } +static void joystick_state( enum sr_joystick joystick, v2f state ) +{ + if( vg_console.enabled ) + v2_zero( state ); + else + v2_copy( srinput.joystick_states[ joystick ][0], state ); +} + +static float axis_state( enum sr_axis axis ) +{ + if( vg_console.enabled ) return 0.0f; + else return srinput.axis_states[axis][0]; +} + static void setbtn( enum sr_bind button, u8 value ) { srinput.button_states[button][0] |= value; @@ -91,6 +249,16 @@ static void skaterift_preupdate_inputs(void) srinput.button_states[i][0] = 0; } + for( u32 i=0; iaxises; + + float *steer = srinput.joystick_states[ k_srjoystick_steer ][0], + *look = srinput.joystick_states[ k_srjoystick_look ][0], + *grab = srinput.joystick_states[ k_srjoystick_grab ][0], + *axisgrab = &srinput.axis_states[ k_sraxis_grab ][0], + *axisbrowseh = &srinput.axis_states[ k_sraxis_mbrowse_h ][0], + *axisbrowsev = &srinput.axis_states[ k_sraxis_mbrowse_v ][0]; - srinput.joy_steer[0] += axis[ SDL_CONTROLLER_AXIS_LEFTX ], - srinput.joy_steer[1] += axis[ SDL_CONTROLLER_AXIS_LEFTY ], - srinput.joy_look[0] += axis[ SDL_CONTROLLER_AXIS_RIGHTX ]; - srinput.joy_look[1] += axis[ SDL_CONTROLLER_AXIS_RIGHTY ]; - srinput.joy_grab[0] += axis[ SDL_CONTROLLER_AXIS_RIGHTX ]; - srinput.joy_grab[1] += axis[ SDL_CONTROLLER_AXIS_RIGHTY ]; - srinput.axis_grab += vg_maxf( 0.0f, - axis[ SDL_CONTROLLER_AXIS_TRIGGERRIGHT ] ); + steer[0] += axis[ SDL_CONTROLLER_AXIS_LEFTX ]; + steer[1] += axis[ SDL_CONTROLLER_AXIS_LEFTY ]; + look[0] += axis[ SDL_CONTROLLER_AXIS_RIGHTX ]; + look[1] += axis[ SDL_CONTROLLER_AXIS_RIGHTY ]; + grab[0] += axis[ SDL_CONTROLLER_AXIS_RIGHTX ]; + grab[1] += axis[ SDL_CONTROLLER_AXIS_RIGHTY ]; + axisgrab[0] += vg_maxf( 0.0f, axis[ SDL_CONTROLLER_AXIS_TRIGGERRIGHT ] ); + axisbrowseh[0] += axis[ SDL_CONTROLLER_AXIS_LEFTX ]; + axisbrowsev[0] += axis[ SDL_CONTROLLER_AXIS_LEFTY ]; float lh = axis[ SDL_CONTROLLER_AXIS_LEFTX ], lv = axis[ SDL_CONTROLLER_AXIS_LEFTY ], @@ -166,9 +355,8 @@ static void skaterift_preupdate_inputs(void) if( lv < -sensitivity ) setbtn( k_srbind_mdown, 1 ); } - //v2_normalize_clamp( srinput.joy_steer ); - //v2_normalize_clamp( srinput.joy_grab ); - srinput.axis_grab = vg_minf( 1.0f, srinput.axis_grab ); + srinput.axis_states[ k_sraxis_grab ][0] = + vg_minf( 1.0f, srinput.axis_states[ k_sraxis_grab ][0] ); } #endif /* INPUT_H */ diff --git a/models_src/rs_font.mdl b/models_src/rs_font.mdl index d351fa05d65025eec693226a053d87f36669d925..bf167ad41c359b2b77924271478caf234545d6d8 100644 GIT binary patch delta 25770 zcmZu(2|yK9|9uOa@CFeP1VmXBQBeUwkmWth%&pXxrOfF*6j0< z^UNkwh{?r>}Y8IDRa%{X!FUrG2qK{yO^T~Uyk-(NkZ`4Q_l_?Gvd{e zFFo`I#p7F`0azneXZ6pL%+@p37uf7ZYHr3Gth| z$-Lc)aLX8r(?2Wz^mhBsUI*==EDe8OUH#gg8t}<&`^3u4|8u?DjNk1I+ka-Cd#%Ci z!`c;vJL)ppEHfOlOPc(TJ*Z3AZTsj0e>(0?KLFQGUvGZ<`ja`1|G5r(%a*_)cRY;h zW->Ln%fkf2uJbV2uy1?VGxT*AYi!!xWIBk9bsqi%`%S~9hfm&TGEIVA=i#@oTf?sN z(5HvVGz4~?hfly>ZP@o`_Hy|3G?|9OZt3@gqZRNpY(Lm@F6O!%)4LWpUN9o6;uqVQ z;T72YD~{@T+h&H@C9mlABqP1D-|S%e$%ege{2u*!kztP-`HODPH0+Mw{-oP;4SUf- zSEL@X(1_UBW4UfGGi*z{BHdnX*gsdT(Czhxy)0^zZhvanDFMm4?KbSTMe}ugw_&#_ z3fJvY!@kEg<5@jopAk{lg2VOf~r<(i}mck4BJ&#;q`h6w0gF0FYlN= z@MMVYa8NzFkzv2?*s5QTFzla<9*Z&T-yYniUr+GbE>m4Z8zaH~<-Youb~NlS_n*}> zWEl2#tVND_PCdJ8J-bIe`vJr5Jk6u$e^|F&Ce!+6-{=vK8VQE|T&3H?4BKqXff0s% z?-yJ2>thVN_2Y+i`$favW;i&(um@rV(cw1?d$O`$Pd|k=>Nj0JdPt9$W+bTVk@pN+ z?pmW?pJ&*0J+RoYHSJ6N`f|grYtUN5uA8JA3_CBdT2H?Pwu{SZ>V-zShue(=#m21u z(y)J8eOk}3*RTgawNtkb7UOvz~44?ahCG=03eVf5SeEJ)A=#^+x~ST|r|b zL0yHBh8@*$h@PQ^Vec@;xRqgFF@~_6VgLK^a6NshVaIL`)q6P8u|XWke)VjpVb@KvgMQhGE}0Hc`Jm$FS>`oiOZ?BmLMTF2~Zk0%q78za})AiovoF-Muhg@z-fg?k zg|$Y+im|nNmsxQ<;iRmy8yNP_Rq?t*4Gnwzo))^@#IWm5D$#~rcT$Nn?7DM6Ys2O_ zz{R6Vdn2OcpCrA&PW9|Au=&?*#&7kykOXM2as3pvN=g7^_lxvbO&?MlxfjL)1u9Q1+W4>fUkR6 zwBJDgfPihE*iBbnzt#u z#kr=Y+frr6v!MVzCU zJ$QkL=)st>e?$+8;@3}#2|fHeSe7*tYxRg7?L{?3;g6BRzbDfocP50TGEt1|iK@1( zZY%_^FmnaP<*KXVsva|Lo@m|6Tin22Mkz%U#VFSeVL9JQ{DKtLrZ4)7h~9`e*+tyf z8xf|fl9<4V(Me(rBZ_@%MKvO<{olML{QE%E^t>!GDN;O_#VB1ow@e5M)3}wQf+BX| zN^zB<<`MXEKVw46#XyRXD+fgpMa`N$!cCF#%ocHuqHxDS5%B=T>?M0d4~qQ9w}=T8 z1-ti(wGW_8N25ix5&HMV1y+zr5gR*CjG~|ug5q-8JW)YWPylZzQbv3#TK9t}j65U; z)`=orELtht{ZN6{Oq^px{)CT3M1LbwkN(~(6Bx1im6c+x5m9Y~{tx0pNY3XXlcMmU zm10y~jHrvLps4CJPh5S_TUzUfjEI2`c_WG#Hg782MtF`1W*;vW5f4Mue6vyXs1p+? zcxf%g<#qc-b)E2k#7LZ3Cq_}2E))w{W72hsL(~mm*Of#&9X|-dJqIX7)X(_;gBez==po7a8peDH9(w$@G%WtnJbz;>X+Xj~pC+nJ}L&Zt@M7FX+%^|zFY)2zx%EdSX%G(Fc^ zB=irF%56cDr>5z1XDau|_sdBb5E*-6hb zh7p5OUw0J$818r)Wh~zQzjYp9g2KBhy~zakt<7EVl{Z7X9X^TvPkM4q%{%0Zi6gKM zJ~(F=>qcM&D*yhTCr(loGcI6cU0l{}HTt$%0A;ONwNX@zL>W~(JmPAdXg!L{43`E% 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 JmaoNR`aij(4uSvx delta 13058 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 E0o6<_drive; drivable_vehicle *vehc = drive->vehicle; - vehc->steer = vg_lerpf( vehc->steer, srinput.joy_steer[0] * 0.4f, - k_rb_delta * 8.0f ); - vehc->drive = srinput.joy_steer[1]; + v2f steer; + joystick_state( k_srjoystick_steer, steer ); + + vehc->steer = vg_lerpf( vehc->steer, steer[0] * 0.4f, k_rb_delta * 8.0f ); + vehc->drive = steer[1]; } VG_STATIC void player__drive_update( player_instance *player ) diff --git a/player_skate.c b/player_skate.c index fed0058..d1be6b8 100644 --- a/player_skate.c +++ b/player_skate.c @@ -669,7 +669,7 @@ invalidated_grind:; } v2f steer; - v2_copy( srinput.joy_steer, steer ); + joystick_state( k_srjoystick_steer, steer ); v2_normalize_clamp( steer ); if( (fabsf(steer[1]) > 0.5f) && (s->land_dist >= 1.5f) ){ @@ -790,7 +790,7 @@ VG_STATIC void skate_apply_grab_model( player_instance *player ) { struct player_skate *s = &player->_skate; - float grabt = srinput.axis_grab; + float grabt = axis_state( k_sraxis_grab ); if( grabt > 0.5f ){ v2_muladds( s->state.grab_mouse_delta, vg.mouse_delta, 0.02f, @@ -808,9 +808,12 @@ VG_STATIC void skate_apply_steering_model( player_instance *player ) { struct player_skate *s = &player->_skate; + v2f jsteer; + joystick_state( k_srjoystick_steer, jsteer ); + /* Steering */ - float steer = srinput.joy_steer[0], - grab = srinput.axis_grab; + float steer = jsteer[0], + grab = axis_state( k_sraxis_grab ); steer = vg_signf( steer ) * steer*steer * k_steer_ground; @@ -958,7 +961,10 @@ VG_STATIC void skate_apply_jump_model( player_instance *player ) s->grind_cooldown = 30; s->state.activity = k_skate_activity_ground; - float tilt = srinput.joy_steer[0] * 0.4f; + v2f steer; + joystick_state( k_srjoystick_steer, steer ); + + float tilt = steer[0] * 0.3f; tilt *= vg_signf(v3_dot( player->rb.v, s->grind_dir )); v4f qtilt; @@ -989,7 +995,7 @@ VG_STATIC void skate_apply_pump_model( player_instance *player ) /* Throw / collect routine */ - if( srinput.axis_grab > 0.5f ){ + if( axis_state( k_sraxis_grab ) > 0.5f ){ if( s->state.activity == k_skate_activity_ground ){ /* Throw */ v3_muls( player->rb.to_world[1], k_mmthrow_scale, s->state.throw_v ); @@ -1033,8 +1039,8 @@ VG_STATIC void skate_apply_cog_model( player_instance *player ) v3_copy( s->state.up_dir, ideal_dir ); v3_normalize( ideal_dir ); - v3_muladds( player->rb.co, ideal_dir, - 1.0f-srinput.axis_grab, ideal_cog ); + float grab = axis_state( k_sraxis_grab ); + v3_muladds( player->rb.co, ideal_dir, 1.0f-grab, ideal_cog ); v3_sub( ideal_cog, s->state.cog, ideal_diff ); /* Apply velocities */ @@ -1443,14 +1449,16 @@ VG_STATIC void skate_weight_distribute( player_instance *player ) int reverse_dir = v3_dot( player->rb.to_world[2], player->rb.v ) < 0.0f?1:-1; + v2f steer; + joystick_state( k_srjoystick_steer, steer ); + if( s->state.manual_direction == 0 ){ - if( (srinput.joy_steer[1] > 0.7f) && - (s->state.activity == k_skate_activity_ground) && + if( (steer[1] > 0.7f) && (s->state.activity == k_skate_activity_ground) && (s->state.jump_charge <= 0.01f) ) s->state.manual_direction = reverse_dir; } else{ - if( srinput.joy_steer[1] < 0.1f ){ + if( steer[1] < 0.1f ){ s->state.manual_direction = 0; } else{ @@ -1461,7 +1469,7 @@ VG_STATIC void skate_weight_distribute( player_instance *player ) } if( s->state.manual_direction ){ - float amt = vg_minf( srinput.joy_steer[1] * 8.0f, 1.0f ); + float amt = vg_minf( steer[1] * 8.0f, 1.0f ); s->weight_distribution[2] = k_board_length * amt * (float)s->state.manual_direction; } @@ -1614,9 +1622,10 @@ VG_STATIC void skate_grind_truck_apply( player_instance *player, v3_normalize( target_fwd ); v3_normalize( fwd ); + v2f steer; + joystick_state( k_srjoystick_steer, steer ); - float way = srinput.joy_steer[1] * - vg_signf( v3_dot( raw_nplane, player->rb.v ) ); + float way = steer[1] * vg_signf( v3_dot( raw_nplane, player->rb.v ) ); v4f q; q_axis_angle( q, axis, VG_PIf*0.125f * way ); @@ -1668,8 +1677,10 @@ VG_STATIC void skate_5050_apply( player_instance *player, v3_cross( axis, inf_avg.dir, inf_avg.n ); skate_grind_decay( player, &inf_avg, 1.0f ); + v2f steer; + joystick_state( k_srjoystick_steer, steer ); - float way = srinput.joy_steer[1] * + float way = steer[1] * vg_signf( v3_dot( player->rb.to_world[2], player->rb.v ) ); v4f q; v3f up, target_up; @@ -1963,11 +1974,14 @@ VG_STATIC enum skate_activity skate_availible_grind( player_instance *player ) int allow_back = 1, allow_front = 1; + v2f steer; + joystick_state( k_srjoystick_steer, steer ); + if( s->state.activity == k_skate_activity_grind_5050 || s->state.activity == k_skate_activity_grind_back50 || s->state.activity == k_skate_activity_grind_front50 ) { - float tilt = srinput.joy_steer[1]; + float tilt = steer[1]; if( fabsf(tilt) >= 0.25f ){ v3f raw = {0.0f,0.0f,tilt}; @@ -2011,7 +2025,7 @@ VG_STATIC enum skate_activity skate_availible_grind( player_instance *player ) res_front50 = skate_grind_truck_entry( player, -1.0f, &inf_front50 ); if( res_back50 != res_front50 ){ - int wants_to_do_that = fabsf(srinput.joy_steer[1]) >= 0.25f; + int wants_to_do_that = fabsf(steer[1]) >= 0.25f; res_back50 &= wants_to_do_that; res_front50 &= wants_to_do_that; @@ -2763,7 +2777,10 @@ VG_STATIC void player__skate_animate( player_instance *player, mdl_keyframe air_pose[32]; { - float target = -srinput.joy_steer[1]; + v2f steer; + joystick_state( k_srjoystick_steer, steer ); + + float target = -steer[1]; s->blend_airdir = vg_lerpf( s->blend_airdir, target, 2.4f*vg.time_delta ); @@ -2773,7 +2790,7 @@ VG_STATIC void player__skate_animate( player_instance *player, static v2f grab_choice; v2f grab_input; - v2_copy( srinput.joy_grab, grab_input ); + joystick_state( k_srjoystick_grab, grab_input ); v2_add( s->state.grab_mouse_delta, grab_input, grab_input ); if( v2_length2( grab_input ) <= 0.001f ) diff --git a/player_walk.c b/player_walk.c index 4334473..1845906 100644 --- a/player_walk.c +++ b/player_walk.c @@ -382,7 +382,10 @@ VG_STATIC void player__walk_update( player_instance *player ) m3x3_mulv( player->basis, forward_dir, forward_dir ); m3x3_mulv( player->basis, right_dir, right_dir ); - w->move_speed = v2_length( srinput.joy_steer ); + v2f steer; + joystick_state( k_srjoystick_steer, steer ); + + w->move_speed = v2_length( steer ); world_instance *world = get_active_world(); /* @@ -424,8 +427,9 @@ VG_STATIC void player__walk_update( player_instance *player ) */ float accel_speed = 0.0f, nominal_speed = 0.0f; v3f movedir; - v3_muls( right_dir, srinput.joy_steer[0], movedir ); - v3_muladds( movedir, forward_dir, srinput.joy_steer[1], movedir ); + + v3_muls( right_dir, steer[0], movedir ); + v3_muladds( movedir, forward_dir, steer[1], movedir ); if( w->state.activity == k_walk_activity_ground ){ v3_normalize( surface_avg ); @@ -433,7 +437,7 @@ VG_STATIC void player__walk_update( player_instance *player ) v3f tx, ty; rb_tangent_basis( surface_avg, tx, ty ); - if( v2_length2(srinput.joy_steer) > 0.001f ){ + if( v2_length2(steer) > 0.001f ){ /* clip movement to the surface */ float d = v3_dot(surface_avg,movedir); v3_muladds( movedir, surface_avg, -d, movedir ); @@ -461,7 +465,7 @@ VG_STATIC void player__walk_update( player_instance *player ) nominal_speed = k_airspeed; } - if( v2_length2( srinput.joy_steer ) > 0.001f ){ + if( v2_length2( steer ) > 0.001f ){ player_accelerate( player->rb.v, movedir, nominal_speed, accel_speed ); v3_normalize( movedir ); } -- 2.25.1