boards now pickable
authorhgn <hgodden00@gmail.com>
Sat, 29 Apr 2023 14:03:04 +0000 (15:03 +0100)
committerhgn <hgodden00@gmail.com>
Sat, 29 Apr 2023 14:03:04 +0000 (15:03 +0100)
ent_skateshop.c
ent_skateshop.h [new file with mode: 0644]
highscores.h
input.h
player.h
player_common.c
player_render.c
player_skate.c
player_walk.c

index 6cf47dc69cd1fb5192d23a291b65a3c301d545bc..3ebc9f0622982a75ffeb0640025b7a625f767e62 100644 (file)
@@ -1,82 +1,11 @@
 #ifndef ENT_SKATESHOP_C
 #define ENT_SKATESHOP_C
 
+#include "ent_skateshop.h"
 #include "world.h"
 #include "player.h"
 #include "gui.h"
 
-#define MAX_LOCAL_BOARDS 64
-#define BILL_TIN_BOARDS  1
-#define MAX_DYNAMIC_BOARDS 9
-
-struct{
-   v3f look_target;
-   ent_skateshop *ptr_ent;
-
-   int active;
-   float factive;
-
-   enum skateshop_loc{
-      k_skateshop_loc_page__viewing,
-
-      k_skateshop_loc_select_use,
-      k_skateshop_loc_select_cancel,
-      k_skateshop_loc_select_upload,
-      k_skateshop_loc_page__selected,
-
-      k_skateshop_loc_page__upload,
-   }
-   interface_loc;
-
-   struct dynamic_board
-   {
-      enum dynamic_board_state{
-         k_dynamic_board_state_none,
-         k_dynamic_board_state_loaded,
-         k_dynamic_board_state_loading,
-      }
-      state;
-
-      u32 ref_count;
-
-      struct player_board board;
-
-      u32 registry_id;
-
-      double last_use_time;
-   }
-   *dynamic_boards,
-   *localplayer_slot;
-
-   struct shop_view_slot
-   {
-      struct dynamic_board *db;
-      float view_blend;
-   }
-   shop_view_slots[6];
-
-   struct board_registry
-   {
-      int workshop;
-      u64 uid;
-
-      struct dynamic_board *dynamic;
-
-      char filename[64];   /* if workshop, string version of uid. */
-      u32 filename_hash;
-
-      int ghost;
-   } 
-   *registry;
-   u32 registry_count;
-
-   int loading;
-   float interaction_cooldown;
-
-   u32 selected_registry_id;
-}
-static global_skateshop;
-
 static inline int const_str_eq( u32 hash, const char *str, const char *cmp )
 {
    if( hash == vg_strdjb2(cmp) )
@@ -127,8 +56,6 @@ struct dynamic_board *skateshop_lru_alloc( u32 id )
    }
 
    if( min_board ){
-      localplayer.board = NULL; /* temp */
-
       if( min_board->state == k_dynamic_board_state_loaded ){
          struct board_registry *other = 
             &global_skateshop.registry[min_board->registry_id];
@@ -167,22 +94,45 @@ void skateshop_board_registry_path( struct board_registry *reg, char path[256] )
    }
 }
 
+/* we can only keep using a viewslot pointer for multiple frames if we watch it
+ * using this function */
+VG_STATIC void watch_dynamic_board( struct dynamic_board *db )
+{
+   if( db->ref_count >= 32 ){
+      vg_fatal_error( "dynamic board watch missmatch (limit is 32)\n" );
+   }
+
+   db->last_use_time = vg.time;
+   db->ref_count ++;
+}
+
+/* after this is called, the calling code only has access to the pointer for the
+ * duration of a frame */
+VG_STATIC void unwatch_dynamic_board( struct dynamic_board *db )
+{
+   if( db->ref_count == 0 ){
+      vg_fatal_error( "dynamic board unwatch missmatch (no watchers)\n" );
+   }
+
+   db->ref_count --;
+}
+
 VG_STATIC void skateshop_async_board_complete( void *payload, u32 size )
 {
    struct dynamic_board *db = payload;
 
-   if( db == global_skateshop.localplayer_slot ){
-      localplayer.board = &db->board;
-      db->ref_count ++;
-   }
-   else{
-      for( u32 i=0; i<vg_list_size(global_skateshop.shop_view_slots); i++ ){
-         if( global_skateshop.shop_view_slots[i].db == db ){
-            db->ref_count ++;
-         }
+   /* all possible view slots are 'listening' for this event, 
+    * which must be checked here */
+   for( u32 i=0; i<vg_list_size(global_skateshop.shop_view_slots); i++ ){
+      if( global_skateshop.shop_view_slots[i].db == db ){
+         watch_dynamic_board( db );
       }
    }
 
+   if( localplayer.board_view_slot == db ){
+      watch_dynamic_board( db );
+   }
+
    db->last_use_time = vg.time;
    db->state = k_dynamic_board_state_loaded;
 
@@ -229,20 +179,25 @@ VG_STATIC int skateshop_use_board( int argc, const char *argv[] )
          struct board_registry *reg = &global_skateshop.registry[i];
 
          if( const_str_eq( hash, argv[0], reg->filename ) ){
-            
             if( reg->dynamic ){
                struct dynamic_board *db = reg->dynamic;
 
                if( db->state == k_dynamic_board_state_loaded ){
-                  localplayer.board = &db->board;
-                  db->last_use_time = vg.time;
+                  localplayer.board_view_slot = db;
+                  watch_dynamic_board( db );
                }
                else{
                   vg_fatal_error( "Invalid state while loading board\n" );
                }
             }
             else{
+               if( localplayer.board_view_slot ){
+                  unwatch_dynamic_board( localplayer.board_view_slot );
+                  localplayer.board_view_slot = NULL;
+               }
+
                struct dynamic_board *db = skateshop_lru_alloc( i );
+               localplayer.board_view_slot = db;
                db->state = k_dynamic_board_state_loading;
                skateshop_loader_start( skateshop_thread1_refresh );
             }
@@ -326,6 +281,7 @@ VG_STATIC void global_skateshop_exit(void)
    vg_info( "exit skateshop\n" );
    localplayer.immobile = 0;
    global_skateshop.active = 0;
+   srinput.ignore_input_frames = 2;
 }
 
 VG_STATIC void skateshop_request_viewpage( u32 page )
@@ -441,8 +397,18 @@ VG_STATIC void global_skateshop_preupdate(void)
    if( global_skateshop.interface_loc <= k_skateshop_loc_page__viewing ){
 
       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" );
+
+      u32 reg_id = global_skateshop.selected_registry_id;
+      struct board_registry *picker = &global_skateshop.registry[ reg_id ];
+
+      int pick_availible = 0;
+      if( picker->dynamic && 
+            (picker->dynamic->state == k_dynamic_board_state_loaded ) )
+      {
+         pick_availible = 1;
+         gui_helper_action( button_display_string( k_srbind_maccept ), "pick" );
+      }
       
       int moved = 0;
 
@@ -469,6 +435,21 @@ VG_STATIC void global_skateshop_preupdate(void)
          return;
       }
 
+      if( pick_availible && button_down( k_srbind_maccept ) ){
+         vg_info( "chose board from skateshop (%u)\n", reg_id );
+
+         if( localplayer.board_view_slot ){
+            unwatch_dynamic_board( localplayer.board_view_slot );
+            localplayer.board_view_slot = NULL;
+         }
+
+         localplayer.board_view_slot = picker->dynamic;
+         watch_dynamic_board( localplayer.board_view_slot );
+
+         global_skateshop_exit();
+         return;
+      }
+
       if( button_down( k_srbind_mback ) ){
          global_skateshop_exit();
          return;
@@ -511,6 +492,11 @@ VG_STATIC void skateshop_render(void)
    world_instance *world = get_active_world();
 
    u32 slot_count = vg_list_size(global_skateshop.shop_view_slots);
+
+   ent_marker *mark_rack = mdl_arritm( &world->ent_marker, 
+                                  mdl_entity_id_id(shop->id_rack)),
+              *mark_display = mdl_arritm( &world->ent_marker,
+                                  mdl_entity_id_id(shop->id_display));
    
    for( u32 i=0; i<slot_count; i++ ){
       struct shop_view_slot *slot = &global_skateshop.shop_view_slots[i];
@@ -528,21 +514,16 @@ VG_STATIC void skateshop_render(void)
 
       xform.co[0] = -((float)i - ((float)slot_count)*0.5f)*0.45f;
 
-      ent_marker *rack = mdl_arritm( &world->ent_marker, 
-                                     mdl_entity_id_id(shop->id_rack)),
-                 *display = mdl_arritm( &world->ent_marker,
-                                     mdl_entity_id_id(shop->id_display));
-
-      mdl_transform_mul( &rack->transform, &xform, &xform );
+      mdl_transform_mul( &mark_rack->transform, &xform, &xform );
 
       if( slot->db->registry_id == global_skateshop.selected_registry_id ){
          selected = 1.0f;
       }
 
       float t = slot->view_blend;
-      v3_lerp( xform.co, display->transform.co, t, xform.co );
-      q_nlerp( xform.q, display->transform.q, t, xform.q );
-      v3_lerp( xform.s, display->transform.s, t, xform.s );
+      v3_lerp( xform.co, mark_display->transform.co, t, xform.co );
+      q_nlerp( xform.q, mark_display->transform.q, t, xform.q );
+      v3_lerp( xform.s, mark_display->transform.s, t, xform.s );
 
       m4x3f mmdl;
       mdl_transform_m4x3( &xform, mmdl );
@@ -554,10 +535,11 @@ set_fade_amt:;
       slot->view_blend = vg_lerpf( slot->view_blend, selected, rate );
    }
 
-   ent_marker *info = mdl_arritm( &world->ent_marker, 
+   ent_marker *mark_info = mdl_arritm( &world->ent_marker, 
                                   mdl_entity_id_id(shop->id_info));
-   m4x3f mtext;
-   mdl_transform_m4x3( &info->transform, mtext );
+   m4x3f mtext, mrack;
+   mdl_transform_m4x3( &mark_info->transform, mtext );
+   mdl_transform_m4x3( &mark_rack->transform, mrack );
 
    const char *text_title = "Fish - Title";
    const char *text_author = "by Shaniqua";
@@ -565,10 +547,12 @@ set_fade_amt:;
    m4x3f mlocal, mmdl;
    m4x3_identity( mlocal );
 
-   float scale = 0.2f;
+   /* Skin title
+    * ----------------------------------------------------------------- */
+   float scale = 0.2f,
+         thickness = 0.03f;
 
-   mlocal[0][0] = scale; mlocal[1][1] = scale;
-   mlocal[2][2] = 0.03f;
+   m3x3_setdiagonalv3( mlocal, (v3f){ scale, scale, thickness } );
    mlocal[3][0] = -font3d_string_width(&world_global.font,0,text_title);
    mlocal[3][0] *= scale*0.5f;
    mlocal[3][1] = 0.1f;
@@ -579,13 +563,35 @@ set_fade_amt:;
    shader_model_font_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} );
    font3d_simple_draw( &world_global.font, 0, text_title, &main_camera, mmdl );
 
+   /* Author name
+    * ----------------------------------------------------------------- */
    scale *= 0.4f;
-   mlocal[0][0] = scale; mlocal[1][1] = scale;
+   m3x3_setdiagonalv3( mlocal, (v3f){ scale, scale, thickness } );
    mlocal[3][0] = -font3d_string_width(&world_global.font,0,text_author);
    mlocal[3][0] *= scale*0.5f;
    mlocal[3][1] = 0.0f;
    m4x3_mul( mtext, mlocal, mmdl );
    font3d_simple_draw( &world_global.font, 0, text_author, &main_camera, mmdl );
+
+   /* Selection counter
+    * ------------------------------------------------------------------ */
+   scale = 0.4f;
+   m3x3_zero( mlocal );
+   v3_zero( mlocal[3] );
+   mlocal[0][0] = -scale;
+   mlocal[1][2] = -scale;
+   mlocal[2][1] = -thickness;
+   mlocal[3][2] = -0.7f;
+   m4x3_mul( mrack, mlocal, mmdl );
+
+   char buf[16];
+   int i=0;
+   i+=highscore_intl( buf+i, global_skateshop.selected_registry_id+1, 3 );
+   buf[i++] = '/';
+   i+=highscore_intl( buf+i, global_skateshop.registry_count, 3 );
+   buf[i++] = '\0';
+
+   font3d_simple_draw( &world_global.font, 0, buf, &main_camera, mmdl );
 }
 
 #endif /* ENT_SKATESHOP_C */
diff --git a/ent_skateshop.h b/ent_skateshop.h
new file mode 100644 (file)
index 0000000..e7acd43
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef ENT_SKATESHOP_H
+#define ENT_SKATESHOP_H
+
+#include "world.h"
+#include "player.h"
+
+#define MAX_LOCAL_BOARDS 64
+#define BILL_TIN_BOARDS  1
+#define MAX_DYNAMIC_BOARDS 9
+
+struct{
+   v3f look_target;
+   ent_skateshop *ptr_ent;
+
+   int active;
+   float factive;
+
+   enum skateshop_loc{
+      k_skateshop_loc_page__viewing,
+
+      k_skateshop_loc_select_use,
+      k_skateshop_loc_select_cancel,
+      k_skateshop_loc_select_upload,
+      k_skateshop_loc_page__selected,
+
+      k_skateshop_loc_page__upload,
+   }
+   interface_loc;
+
+   struct dynamic_board
+   {
+      enum dynamic_board_state{
+         k_dynamic_board_state_none,
+         k_dynamic_board_state_loaded,
+         k_dynamic_board_state_loading,
+      }
+      state;
+
+      u32 ref_count;
+
+      struct player_board board;
+
+      u32 registry_id;
+
+      double last_use_time;
+   }
+   *dynamic_boards;
+
+   struct shop_view_slot
+   {
+      struct dynamic_board *db;
+      float view_blend;
+   }
+   shop_view_slots[6];
+
+   struct board_registry
+   {
+      int workshop;
+      u64 uid;
+
+      struct dynamic_board *dynamic;
+
+      char filename[64];   /* if workshop, string version of uid. */
+      u32 filename_hash;
+
+      int ghost;
+   } 
+   *registry;
+   u32 registry_count;
+
+   int loading;
+   float interaction_cooldown;
+
+   u32 selected_registry_id;
+}
+static global_skateshop;
+
+#endif /* ENT_SKATESHOP_H */
index 079e4d8d69af2befbed093ddbb2a5b4ddb20f6d0..3a2071758a8c04f76c6ddd8d5a2a1ead67d1c62d 100644 (file)
@@ -478,13 +478,14 @@ VG_STATIC void highscore_strr( char *buf, const char *str, int len, int width )
    }
 }
 
-/* Print integer (padded with: alt), right aligned into buf(width: len) */
-VG_STATIC void highscore_intr( char *buf, int value, int len, char alt )
+/* Print integer (padded with: alt), right aligned into buf(width: len)
+ * returns number of digits (not including alt), that were written to buf */
+VG_STATIC int highscore_intr( char *buf, int value, int len, char alt )
 {
    int i=0;
    while(value){
       if( i>=len ) 
-         return;
+         return i;
 
       buf[ len-1 - (i ++) ] = '0' + (value % 10);
       value /= 10;
@@ -492,16 +493,18 @@ VG_STATIC void highscore_intr( char *buf, int value, int len, char alt )
 
    for( ;i<len; i ++ )
       buf[ len-1 - i ] = alt;
+
+   return i;
 }
 
-/* Print integer into buffer with max length len */
-VG_STATIC void highscore_intl( char *buf, int value, int len )
+/* Print integer into buffer with max length len 
+ * retuns the number of digits written to buf */
+VG_STATIC int highscore_intl( char *buf, int value, int len )
 {
    char temp[32];
 
    int i=0;
-   while(value)
-   {
+   while(value){
       if( i>=len ) 
          break;
 
@@ -513,9 +516,9 @@ VG_STATIC void highscore_intl( char *buf, int value, int len )
       i = len;
 
    for( int j=0; j<i; j ++ )
-   {
       buf[j] = temp[ i-1-j ];
-   }
+
+   return i;
 }
 
 /* Clear buffer with length using clr character */
diff --git a/input.h b/input.h
index 6f19634f606e4dde10fd52754dbcaf9d3804cd66..dffcb28235221648b4250c63eb60359801b088ce 100644 (file)
--- a/input.h
+++ b/input.h
@@ -47,6 +47,7 @@ struct {
    float axis_states[ k_sraxis_max ][2];
    v2f joystick_states[ k_srjoystick_max ][2];
    u8 button_states[ k_srbind_max ][2];
+   u32 ignore_input_frames;
 }
 static srinput;
 
@@ -178,6 +179,9 @@ static const char *joystick_display_string( enum sr_joystick joystick )
 
 static int buttons_filter_fixed(void)
 {
+   if( srinput.ignore_input_frames )
+      return 1;
+
    if( vg_console.enabled )
       return 1;
 
@@ -244,6 +248,9 @@ static void setbtn( enum sr_bind button, u8 value )
 
 static void skaterift_preupdate_inputs(void)
 {
+   if( srinput.ignore_input_frames )
+      srinput.ignore_input_frames --;
+
    for( u32 i=0; i<k_srbind_max; i++ ){
       srinput.button_states[i][1] = srinput.button_states[i][0];
       srinput.button_states[i][0] = 0;
index 1e3ba671cad5c63d70561bdab470fd8d5a6a3c91..0a7486013716a670bfb57de29e7c031550f29ed1 100644 (file)
--- a/player.h
+++ b/player.h
@@ -71,7 +71,8 @@ struct player_instance
    struct player_avatar  *playeravatar;
    struct player_model   *playermodel;
    struct player_ragdoll  ragdoll;
-   struct player_board   *board;
+   //struct player_board   *board;
+   struct dynamic_board  *board_view_slot;
 
    player_pose            holdout_pose;
    float                  holdout_time;
index 110ee1640e33d0fd85816c44ee6d05a67a5b629d..669c20ae3dc191d18758f7a4356b178199066338 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef PLAYER_COMMON_C
 #define PLAYER_COMMON_C
 
+#include "ent_skateshop.h"
 #include "player.h"
 #include "conf.h"
 #include "input.h"
@@ -257,4 +258,18 @@ VG_STATIC void player_look( player_instance *player, v3f angles )
    angles[1] = vg_clampf( angles[1], -VG_PIf*0.5f, VG_PIf*0.5f );
 }
 
+struct player_board *player_get_player_board( struct player_instance *player )
+{
+   struct player_board *board = NULL;
+
+   if( localplayer.board_view_slot ){
+      struct dynamic_board *vs = localplayer.board_view_slot;
+      if( vs->state == k_dynamic_board_state_loaded ){
+         board = &vs->board;
+      }
+   }
+
+   return board;
+}
+
 #endif /* PLAYER_COMMON_C */
index 33724245771fe10b0f07a3a13d5e74ee9e883fbe..f34aa1665028c9ac4909508e56503648f59694bb 100644 (file)
@@ -5,6 +5,7 @@
 #include "player_render.h"
 #include "camera.h"
 #include "player_model.h"
+#include "ent_skateshop.h"
 
 #include "shaders/model_character_view.h"
 #include "shaders/model_board_view.h"
@@ -159,8 +160,7 @@ VG_STATIC void player__pre_render( player_instance *player )
       _player_post_animate[ player->subsystem ]( player );
 
    struct player_avatar *av = player->playeravatar;
-
-   struct player_board *board = player->board;
+   struct player_board *board = player_get_player_board( player );
 
    v3f vp0, vp1;
 
@@ -438,7 +438,7 @@ PLAYER_API void player__render( camera *cam, player_instance *player )
    mesh_bind( &player->playermodel->mesh );
    mesh_draw( &player->playermodel->mesh );
 
-   struct player_board *board = player->board;
+   struct player_board *board = player_get_player_board( player );
 
    render_board( cam, world, board, player->playeravatar->sk.final_mtx[
                                        player->playeravatar->id_board],
index d1be6b8b82c84adf3d7978e176b138e4afec7117..e1971b2000725198264cf07b6d7ec5f65e675d40 100644 (file)
@@ -5,6 +5,7 @@
 #include "audio.h"
 #include "vg/vg_perlin.h"
 #include "menu.h"
+#include "ent_skateshop.h"
 
 VG_STATIC void player__skate_bind( player_instance *player )
 {
@@ -2966,7 +2967,7 @@ VG_STATIC void player__skate_animate( player_instance *player,
       q_mul( kf_board->q, qtrick, kf_board->q );
       q_normalize( kf_board->q );
 
-      struct player_board *board = player->board;
+      struct player_board *board = player_get_player_board( player );
       
       if( board ){
          /* foot weight distribution */
index 1845906e2fe01263dbddebf14bed07c860d232f0..be2195f42437e9fabdbe0674dd27c6368b648a3d 100644 (file)
@@ -69,6 +69,7 @@ VG_STATIC void player_walk_generic_to_skate( player_instance *player,
 
 VG_STATIC void player_walk_drop_in_to_skate( player_instance *player )
 {
+   player->immobile = 0;
    player->subsystem = k_player_subsystem_skate;
 
    struct player_walk *w = &player->_walk;
@@ -282,6 +283,9 @@ VG_STATIC void player__walk_pre_update( player_instance *player )
          player->subsystem = k_player_subsystem_drive;
       }
       else{
+         if( !player_get_player_board(player) )
+            return;
+
          if( w->state.activity == k_walk_activity_ground ){
             if( player_walk_scan_for_drop_in( player ) ){
                w->state.outro_type = k_walk_outro_drop_in;