#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;
- mdl_transform rack_root,
- display_root,
- info_root;
-
- enum camera_mode prev_camera_mode;
-
- 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 )
{
}
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_STATIC void global_skateshop_exit(void)
{
+ vg_info( "exit skateshop\n" );
+ localplayer.immobile = 0;
global_skateshop.active = 0;
- localplayer.camera_mode = global_skateshop.prev_camera_mode;
+ srinput.ignore_input_frames = 2;
}
VG_STATIC void skateshop_request_viewpage( u32 page )
vg_info( "Entering skateshop\n" );
localplayer.immobile = 1;
- global_skateshop.prev_camera_mode = localplayer.camera_mode;
- localplayer.camera_mode = k_cam_firstperson;
global_skateshop.active = 1;
global_skateshop.interface_loc = k_skateshop_loc_page__viewing;
v3_zero( localplayer.rb.w );
localplayer._walk.move_speed = 0.0f;
- struct{
- mdl_transform *transform;
- u32 id;
- }
- targets[] = {
- { &global_skateshop.rack_root, shop->id_rack, },
- { &global_skateshop.info_root, shop->id_info, },
- { &global_skateshop.display_root, shop->id_display, },
- };
-
- v3_copy( shop->transform.co, global_skateshop.look_target );
-
- for( u32 i=0; i<vg_list_size(targets); i++ ){
-
- u32 type = mdl_entity_id_type( targets[i].id ),
- index = mdl_entity_id_id( targets[i].id );
-
- if( type == k_ent_marker ){
- ent_marker *m = mdl_arritm( &world->ent_marker, index );
-
- *targets[i].transform = m->transform;
- }
- else{
- transform_identity( targets[i].transform );
- }
- }
+ global_skateshop.ptr_ent = shop;
skateshop_request_viewpage(0);
skateshop_loader_start( skateshop_scan_for_items );
global_skateshop.factive = vg_lerpf( global_skateshop.factive,
global_skateshop.active, rate );
-
if( !global_skateshop.active ) return;
- v3f delta;
- v3_sub( global_skateshop.look_target, localplayer.cam.pos, delta );
- v3_normalize( delta );
+ world_instance *world = get_active_world();
- v3f target;
- player_vector_angles( target, delta, 1.0f, 0.0f );
+ ent_skateshop *shop = global_skateshop.ptr_ent;
+ ent_camera *ref = mdl_arritm( &world->ent_camera,
+ mdl_entity_id_id(shop->id_camera) );
+ ent_marker *display = mdl_arritm( &world->ent_marker,
+ mdl_entity_id_id(shop->id_display) );
+
+ v3f dir = {0.0f,-1.0f,0.0f};
+ mdl_transform_vector( &ref->transform, dir, dir );
+ player_vector_angles( localplayer.cam_override_angles, dir, 1.0f, 0.0f );
+
+ v3f lookat;
+ v3_sub( display->transform.co, localplayer.rb.co, lookat );
+
+ q_axis_angle( localplayer.rb.q, (v3f){0.0f,1.0f,0.0f},
+ atan2f(lookat[0],lookat[2]) );
- camera_lerp_angles( localplayer.angles, target,
- global_skateshop.factive, localplayer.angles);
+ v3_copy( ref->transform.co, localplayer.cam_override_pos );
+ localplayer.cam_override_fov = ref->fov;
+
+ localplayer.cam_override_strength = global_skateshop.factive;
if( global_skateshop.interaction_cooldown > 0.0f ){
global_skateshop.interaction_cooldown -= vg.time_delta;
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 ) ){
- global_skateshop.active = 0;
- return;
- }
- }
- else if( global_skateshop.interface_loc <= k_skateshop_loc_page__selected ){
- if( vg_input_button_down( &input_menu_back ) ){
- global_skateshop.interface_loc = k_skateshop_loc_page__viewing;
- return;
- }
+ if( pick_availible && button_down( k_srbind_maccept ) ){
+ vg_info( "chose board from skateshop (%u)\n", reg_id );
- if( fabsf(h) > 0.25f ){
- if( global_skateshop.interface_loc == k_skateshop_loc_select_use ){
- global_skateshop.interface_loc = k_skateshop_loc_select_cancel;
- return;
+ 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;
}
- else{
- if( global_skateshop.interface_loc == k_skateshop_loc_select_cancel ){
- global_skateshop.interface_loc = k_skateshop_loc_select_use;
- return;
- }
+
+ if( button_down( k_srbind_mback ) ){
+ global_skateshop_exit();
+ return;
}
}
}
{
if( !global_skateshop.active ) return;
+ ent_skateshop *shop = global_skateshop.ptr_ent;
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];
if( slot->db->state != k_dynamic_board_state_loaded )
goto set_fade_amt;
- mdl_transform rack_xform;
- transform_identity( &rack_xform );
+ mdl_transform xform;
+ transform_identity( &xform );
- rack_xform.co[0] = -((float)i - ((float)slot_count)*0.5f)*0.45f;
+ xform.co[0] = -((float)i - ((float)slot_count)*0.5f)*0.45f;
- mdl_transform_mul( &global_skateshop.rack_root,
- &rack_xform, &rack_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( rack_xform.co, global_skateshop.display_root.co,
- t, rack_xform.co );
- q_nlerp( rack_xform.q, global_skateshop.display_root.q,
- t, rack_xform.q );
- v3_lerp( rack_xform.s, global_skateshop.display_root.s,
- t, rack_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( &rack_xform, mmdl );
+ mdl_transform_m4x3( &xform, mmdl );
render_board( &main_camera, world, &slot->db->board, mmdl,
k_board_shader_entity );
slot->view_blend = vg_lerpf( slot->view_blend, selected, rate );
}
- m4x3f mtext;
- mdl_transform_m4x3( &global_skateshop.info_root, mtext );
+ ent_marker *mark_info = mdl_arritm( &world->ent_marker,
+ mdl_entity_id_id(shop->id_info));
+ 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 );
- m4x3f mlocal = {{0.2f,0.0f,0.0f},{0.0f,0.2f,0.0f},{0.0f,0.0f,0.03f},
- {-font3d_string_width( &world_global.font,0,
- "Made by... Bob man 123" )*0.2f*0.5f,0.0f,0.0f}
- };
+ /* Skin title
+ * ----------------------------------------------------------------- */
+ float scale = 0.2f,
+ thickness = 0.03f;
- m4x3_mul( mtext, mlocal, mtext );
+ 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;
+ m4x3_mul( mtext, mlocal, mmdl );
font3d_bind( &world_global.font, &main_camera );
- shader_model_font_uColour( (v4f){1.0f,0.5f,0.1f,1.0f} );
- font3d_simple_draw( &world_global.font, 0, "Made by... Bob man 123",
- &main_camera, mtext );
+ 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;
+ 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 */