#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) )
}
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];
}
}
+/* 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;
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 );
}
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 )
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;
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;
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];
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 );
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";
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;
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 */