my fucking fingers
[carveJwlIkooP6JGAAIwe30JlM.git] / ent_skateshop.c
index adccac50c0521ada3f09c45da2c8b48dab30235f..e985582c4c4438a3bd04de4cc8bf5743b586999d 100644 (file)
@@ -1,80 +1,10 @@
 #ifndef ENT_SKATESHOP_C
 #define ENT_SKATESHOP_C
 
+#include "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,
-   *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;
+#include "gui.h"
 
 static inline int const_str_eq( u32 hash, const char *str, const char *cmp )
 {
@@ -90,13 +20,13 @@ static int skateshop_workshop_name_blacklisted( u32 hash, const char *name )
    return 0;
 }
 
-VG_STATIC void skateshop_loader_start( void (*pfn)(void) )
+VG_STATIC void skateshop_loader_start( void (*pfn)(void *data) )
 {
    if( global_skateshop.loading )
       vg_fatal_error( "skateshop thread sync failure\n" );
 
    global_skateshop.loading = 1;
-   vg_loader_start( pfn );
+   vg_loader_start( pfn, NULL );
 }
 
 VG_STATIC void skateshop_async_post( void *payload, u32 size )
@@ -126,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];
@@ -166,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;
 
@@ -208,7 +159,7 @@ VG_STATIC void skateshop_load_requested_boards(void)
    }
 }
 
-VG_STATIC void skateshop_thread1_refresh(void)
+VG_STATIC void skateshop_thread1_refresh( void *data )
 {
    skateshop_load_requested_boards();
    vg_async_call( skateshop_async_post, NULL, 0 );
@@ -228,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 );
             }
@@ -265,7 +221,7 @@ VG_STATIC void skateshop_use_board_suggest( int argc, const char *argv[] )
    }
 }
 
-VG_STATIC void skateshop_scan_for_items(void)
+VG_STATIC void skateshop_scan_for_items( void *data )
 {
    vg_linear_clear( vg_mem.scratch );
 
@@ -322,8 +278,10 @@ next_file: tinydir_next( &dir );
 
 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 )
@@ -436,29 +394,63 @@ VG_STATIC void global_skateshop_preupdate(void)
       return;
    }
 
-   float h = localplayer.input_js1h->axis.value;
-
    if( global_skateshop.interface_loc <= k_skateshop_loc_page__viewing ){
-      if( fabsf(h) > 0.25f ){
-         if( h < 0.0f ){
-            if( global_skateshop.selected_registry_id > 0 )
-               global_skateshop.selected_registry_id --;
+
+      gui_helper_action( axis_display_string( k_sraxis_mbrowse_h ), "browse" );
+      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;
+
+      if( button_down( k_srbind_mleft ) ){
+         if( global_skateshop.selected_registry_id > 0 ){
+            global_skateshop.selected_registry_id --;
+            moved = 1;
          }
-         else{
-            if( global_skateshop.selected_registry_id < 
-                     global_skateshop.registry_count-1 )
-            {
-               global_skateshop.selected_registry_id ++;
-            }
+      }
+
+      if( button_down( k_srbind_mright ) ){
+         if( global_skateshop.selected_registry_id < 
+                  global_skateshop.registry_count-1 )
+         {
+            global_skateshop.selected_registry_id ++;
+            moved = 1;
          }
+      }
 
+      if( moved ){
          vg_info( "Select registry: %u\n", 
                   global_skateshop.selected_registry_id );
          global_skateshop.interaction_cooldown = 0.125f;
          return;
       }
 
-      if( vg_input_button_down( &input_menu_back ) ){
+      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;
       }
@@ -489,7 +481,7 @@ VG_STATIC void skateshop_init(void)
    vg_console_reg_cmd( "use_board", 
                        skateshop_use_board, skateshop_use_board_suggest );
 
-   skateshop_scan_for_items();
+   //skateshop_scan_for_items(NULL);
 }
 
 VG_STATIC void skateshop_render(void)
@@ -500,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];
@@ -517,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 );
@@ -543,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";
@@ -554,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;
@@ -568,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 */