// TODO: put this in a header
u32 minutes_span = (centiseconds+(200*60)) / (100*60);
- vg_queue_clear( &_remote_replay.replay.buffer );
+ vg_queue_clear( &_remote_replay.buffer );
_remote_replay.min_frame_t = 0.0;
_remote_replay.total_chunks = minutes_span;
_remote_replay.chunks_downloaded = 0;
}
// TODO: UI overlay for downlaoding
- sfd_encode( (v2i){0,6}, "Downloading ...", k_world_sfd_center );
+ world_clear_event( k_world_event_route_leaderboard );
+ srinput.state = k_input_state_resume;
+ gui_helper_reset( k_gui_helper_mode_clear );
+ _replay2_open_player( k_replay_type_network, 0 );
break;
}
else
}
}
-#if 0
-if( button_down( k_srbind_mleft ) )
- {
- world_sfd.view_weekly = 1;
- world_sfd_compile_active_scores();
- }
-
- if( button_down( k_srbind_mright ) )
- {
- world_sfd.view_weekly = 0;
- world_sfd_compile_active_scores();
- }
- _ent_route.helper_alltime->greyed = !world_sfd.view_weekly;
- _ent_route.helper_weekly->greyed = world_sfd.view_weekly;
-#endif
-
E0:
-
if( button_down( k_srbind_mback ) )
{
if( world_clear_event( k_world_event_route_leaderboard ) )
#include "skaterift.h"
#include "player.h"
#include "player_render.h"
-#include "player_replay.h"
+#include "replay2.h"
#include "input.h"
void freecam_preupdate(void)
{
- vg_camera *cam = &player_replay.replay_freecam;
+ vg_camera *cam = &_replay2.replay_freecam;
v3f angles;
v3_copy( cam->angles, angles );
player_look( angles, 1.0f );
v3f d;
v3_sub( angles, cam->angles, d );
- v3_muladds( player_replay.freecam_w, d, 20.0f, player_replay.freecam_w );
- v3_muls( player_replay.freecam_w, decay, player_replay.freecam_w );
- v3_muladds( cam->angles, player_replay.freecam_w, vg.time_frame_delta,
- cam->angles );
+ v3_muladds( _replay2.freecam_w, d, 20.0f, _replay2.freecam_w );
+ v3_muls( _replay2.freecam_w, decay, _replay2.freecam_w );
+ v3_muladds( cam->angles, _replay2.freecam_w, vg.time_frame_delta, cam->angles );
cam->angles[1] = vg_clampf( cam->angles[1], -VG_PIf*0.5f,VG_PIf*0.5f);
vg_camera_update_transform( cam );
joystick_state( k_srjoystick_steer, input );
v2_muls( input, vg.time_frame_delta*6.0f*20.0f, input );
- v3_muladds( player_replay.freecam_v, lookdir, -input[1],
- player_replay.freecam_v );
- v3_muladds( player_replay.freecam_v, sidedir, input[0],
- player_replay.freecam_v );
+ v3_muladds( _replay2.freecam_v, lookdir, -input[1], _replay2.freecam_v );
+ v3_muladds( _replay2.freecam_v, sidedir, input[0], _replay2.freecam_v );
- v3_muls( player_replay.freecam_v, decay, player_replay.freecam_v );
- v3_muladds( cam->pos,
- player_replay.freecam_v, vg.time_frame_delta, cam->pos );
+ v3_muls( _replay2.freecam_v, decay, _replay2.freecam_v );
+ v3_muladds( cam->pos,_replay2.freecam_v, vg.time_frame_delta, cam->pos );
}
signal( SIGQUIT, inthandler );
signal( SIGPIPE, SIG_IGN );
- char *arg;
- while( vg_argp( argc, argv ) )
{
+ _vg_opt_init( argc, argv );
+ const char *arg;
if( vg_long_opt( "noauth", "Disable server authentication" ) )
_gameserver.auth_mode = eServerModeNoAuthentication;
if( vg_long_opt( "replay-info", "Print replay info periodically" ) )
_gs_replay.print_info = 1;
+
+ if( !_vg_opt_check() )
+ return 0;
}
if( !vg_init_async_queue( &_gameserver.tasks ) )
{
menu.page = page;
}
+
+ if( menu.page == k_menu_page_main )
+ {
+ if( menu.main_index == k_menu_main_map )
+ {
+ world_map_initialize_view();
+ }
+ }
}
static void menu_close(void)
if( menu_button( ctx, list, R == 2, 1, "Replay" ) )
{
- //menu.page = k_menu_page_credits;
- skaterift_open_replay();
+ _replay2_open_player( k_replay_type_local, 1 );
}
ui_rect end = { list[0], list[1]+list[3]-64, list[2], 72 };
ui_rect title;
ui_split( inf, k_ui_axis_h, 28*2, 0, title, inf );
ctx->font = &vgf_default_title;
- ui_text( ctx,
- title, "Where to go", 1, k_ui_align_middle_center, 0 );
+ ui_text( ctx, title, "Where to go", 1, k_ui_align_middle_center, 0 );
ui_split( inf, k_ui_axis_h, 28, 0, title, inf );
ctx->font = &vgf_default_large;
network_send_request( packet, &data, NULL, 0 );
}
-#if 0
-static void replay_download_callback( void *data, u32 data_size, u64 userdata, enum request_status status )
-{
- if( status == k_request_status_ok )
- vg_info( "%u bytes downloaded OK\n", data_size );
- else
- vg_warn( "Womp womp\n" );
-}
-
-void network_download_replay( u64 steamid, u32 minute )
-{
- if( !network_connected() )
- return;
-
- netmsg_request *packet = alloca( sizeof(netmsg_request) + 512 );
- packet->inetmsg_id = k_inetmsg_request;
-
- vg_msg data;
- vg_msg_init( &data, packet->buffer, 512 );
- vg_msg_wkvstr( &data, "endpoint", "replay" );
- vg_msg_wkvnum( &data, "minute", k_vg_msg_u32, 1, &minute );
- vg_msg_wkvnum( &data, "steamid", k_vg_msg_u64, 1, &steamid );
- network_send_request( packet, &data, replay_download_callback, 0 );
-}
-#endif
-
static void _delete_request( net_request *request )
{
vg_pool_unwatch( &_net_requests.request_pool, vg_pool_id( &_net_requests.request_pool, request ) );
if( old_id )
{
net_request *old_request = vg_pool_item( &_net_requests.request_pool, old_id );
+ if( old_request->callback )
+ old_request->callback( NULL, 0, old_request->userdata, k_request_status_server_error );
old_request->state = k_request_state_error;
log_request_status( old_request, "Interrupted by new header" );
_delete_request( old_request );
struct netmsg_transfer_header *header = (void *)response->buffer;
if( header->data_size > 1024*1024*4 )
{
+ if( request->callback )
+ request->callback( NULL, 0, request->userdata, k_request_status_out_of_memory );
request->state = k_request_state_error;
log_request_status( request, "Header specified size too large (>4mb)" );
_delete_request( request );
if( current_id != response->id )
{
net_request *current = vg_pool_item( &_net_requests.request_pool, current_id );
+ if( request->callback )
+ request->callback( NULL, 0, request->userdata, k_request_status_server_error );
+ if( current->callback )
+ current->callback( NULL, 0, current->userdata, k_request_status_server_error );
current->state = k_request_state_error;
request->state = k_request_state_error;
log_request_status( current, "Transfer protocol fault" );
}
else
{
+ if( request->callback )
+ request->callback( NULL, 0, request->userdata, k_request_status_server_error );
request->state = k_request_state_error;
log_request_status( request, request_status_string(response->status) );
_delete_request( request );
#include "input.h"
#include "world.h"
#include "audio.h"
-#include "player_replay.h"
#include "network.h"
#include "network_common.h"
#include "world_routes.h"
{
player__transport( gate->transport );
- skaterift_record_frame( &player_replay.local, 1 );
-
/* I genuinely have no idea why this code was like it was, I don't think it's right. Maybe an artifact of editing
* this area some time ago. Keeping it but zero'd out in case I remember in the distant futre. */
#if 0
#endif
localplayer.gate_waiting = gate;
- localplayer.deferred_frame_record = 1;
-
world_routes_fracture( world, gate, localplayer.rb.co, localplayer.rb.v );
world_routes_activate_entry_gate( world, gate );
}
if( player_subsystems[ localplayer.subsystem ]->im_gui )
player_subsystems[ localplayer.subsystem ]->im_gui( ctx );
- skaterift_replay_debug_info( ctx );
+ // FIXME
+ //skaterift_replay_debug_info( ctx );
}
void player__setpos( v3f pos )
void player__clean_refs(void)
{
- replay_clear( &player_replay.local );
+ // FIXME
+ //replay_clear( &player_replay.local );
gui_helper_reset( k_gui_helper_mode_clear );
_world.challenge_target = NULL;
}
};
-static struct net_sfx *find_lower_priority_sfx( struct net_sfx *buffer, u32 len,
- u32 *count, u8 priority ){
+struct net_sfx *net_sfx_buffer_allocate( struct net_sfx *buffer, u32 len, u32 *count, u8 priority )
+{
struct net_sfx *p_sfx = NULL;
- if( *count < len ){
+ if( *count < len )
+ {
p_sfx = &buffer[ *count ];
*count = *count+1;
}
- else {
- for( u32 i=0; i<len; i++ ){
+ else
+ {
+ for( u32 i=0; i<len; i++ )
+ {
struct net_sfx *a = &buffer[i];
- if( a->priority < priority ){
+ if( a->priority < priority )
+ {
p_sfx = a;
break;
}
}
}
-
return p_sfx;
}
-void player__networked_sfx( u8 system, u8 priority, u8 id,
- v3f pos, f32 volume )
+void player__networked_sfx( u8 system, u8 priority, u8 id, v3f pos, f32 volume )
{
struct net_sfx sfx,
- *p_net = find_lower_priority_sfx(
+ *p_net = net_sfx_buffer_allocate(
localplayer.sfx_buffer, 4,
&localplayer.sfx_buffer_count, priority ),
- *p_replay = find_lower_priority_sfx(
+ *p_replay = net_sfx_buffer_allocate(
localplayer.local_sfx_buffer, 2,
&localplayer.local_sfx_buffer_count, priority );
v3f cam_land_punch, cam_land_punch_v;
ent_gate *gate_waiting;
- int deferred_frame_record;
int immobile;
bool immunity;
static void player_camera_portal_correction(void)
{
- if( localplayer.gate_waiting ){
+ if( localplayer.gate_waiting )
+ {
/* construct plane equation for reciever gate */
v4f plane;
q_mulv( localplayer.gate_waiting->q[1], (v3f){0.0f,0.0f,1.0f}, plane );
plane[3] = v3_dot( plane, localplayer.gate_waiting->co[1] );
f32 pol = v3_dot( localplayer.cam.pos, plane ) - plane[3];
-
- int cleared = (pol < 0.0f) || (pol > 5.0f);
-
- if( cleared ){
+ bool cleared = (pol < 0.0f) || (pol > 5.0f);
+ if( cleared )
vg_success( "Plane cleared\n" );
- }
m4x3f inverse;
m4x3_invert_affine( localplayer.gate_waiting->transport, inverse );
m3x3_mulv( inverse, v0, v0 );
v3_angles( v0, localplayer.cam.angles );
- skeleton_apply_transform( &localplayer.skeleton, inverse,
- localplayer.final_mtx );
+ skeleton_apply_transform( &localplayer.skeleton, inverse, localplayer.final_mtx );
/* record and re-put things again */
if( cleared )
{
- skaterift_record_frame( &player_replay.local, 1 );
- localplayer.deferred_frame_record = 1;
-
- skeleton_apply_transform( &localplayer.skeleton,
- localplayer.gate_waiting->transport,
- localplayer.final_mtx );
-
- m4x3_mulv( localplayer.gate_waiting->transport,
- localplayer.cam.pos, localplayer.cam.pos );
+ skeleton_apply_transform( &localplayer.skeleton, localplayer.gate_waiting->transport, localplayer.final_mtx );
+ m4x3_mulv( localplayer.gate_waiting->transport, localplayer.cam.pos, localplayer.cam.pos );
v3_angles_vector( localplayer.cam.angles, v0 );
m3x3_mulv( localplayer.gate_waiting->transport, v0, v0 );
v3_angles( v0, localplayer.cam.angles );
}
}
-void player__cam_iterate(void)
+void compute_cam_controller_offsets( enum player_subsystem system, struct player_cam_controller *cc )
{
- struct player_cam_controller *cc = &localplayer.cam_control;
-
- if( localplayer.subsystem == k_player_subsystem_walk ){
+ if( system == k_player_subsystem_walk )
+ {
v3_copy( (v3f){-0.1f,1.8f,0.0f}, cc->fpv_viewpoint );
v3_copy( (v3f){0.0f,0.0f,0.0f}, cc->fpv_offset );
v3_copy( (v3f){0.0f,1.8f,0.0f}, cc->tpv_offset );
}
- else if( localplayer.subsystem == k_player_subsystem_glide ){
+ else if( system == k_player_subsystem_glide )
+ {
v3_copy( (v3f){-0.15f,1.75f,0.0f}, cc->fpv_viewpoint );
v3_copy( (v3f){0.0f,0.0f,0.0f}, cc->fpv_offset );
v3_copy( (v3f){0.0f,-1.0f,0.0f}, cc->tpv_offset );
v3_add( cc->tpv_offset_extra, cc->tpv_offset, cc->tpv_offset );
}
- else{
+ else
+ {
v3_copy( (v3f){-0.15f,1.75f,0.0f}, cc->fpv_viewpoint );
v3_copy( (v3f){0.0f,0.0f,0.0f}, cc->fpv_offset );
v3_copy( (v3f){0.0f,h,0.0f}, cc->tpv_offset );
v3_add( cc->tpv_offset_extra, cc->tpv_offset, cc->tpv_offset );
}
+}
+
+void player__cam_iterate(void)
+{
+ struct player_cam_controller *cc = &localplayer.cam_control;
+ compute_cam_controller_offsets( localplayer.subsystem, cc );
localplayer.cam_velocity_constant = 0.25f;
localplayer.cam_velocity_coefficient = 0.7f;
/* lerping */
- if( localplayer.cam_dist_smooth == 0.0f ){
+ if( localplayer.cam_dist_smooth == 0.0f )
localplayer.cam_dist_smooth = localplayer.cam_dist;
- }
- else {
+ else
+ {
localplayer.cam_dist_smooth = vg_lerpf(
localplayer.cam_dist_smooth,
localplayer.cam_dist,
/* position */
v3f fpv_pos, fpv_offset;
- m4x3_mulv( localplayer.final_mtx[ localplayer.id_head-1 ],
- cc->fpv_viewpoint_smooth, fpv_pos );
+ m4x3_mulv( localplayer.final_mtx[ localplayer.id_head-1 ], cc->fpv_viewpoint_smooth, fpv_pos );
m3x3_mulv( localplayer.rb.to_world, cc->fpv_offset_smooth, fpv_offset );
v3_add( fpv_offset, fpv_pos, fpv_pos );
/* angles */
v3f velocity_angles;
- v3_lerp( cc->cam_velocity_smooth, localplayer.rb.v, 4.0f*vg.time_frame_delta,
- cc->cam_velocity_smooth );
-
+ v3_lerp( cc->cam_velocity_smooth, localplayer.rb.v, 4.0f*vg.time_frame_delta, cc->cam_velocity_smooth );
v3_angles( cc->cam_velocity_smooth, velocity_angles );
velocity_angles[1] *= localplayer.cam_velocity_coefficient_smooth;
velocity_angles[1] += localplayer.cam_velocity_constant_smooth;
- float inf_fpv = localplayer.cam_velocity_influence_smooth *
- cc->camera_type_blend,
- inf_tpv = localplayer.cam_velocity_influence_smooth *
- (1.0f-cc->camera_type_blend);
-
- vg_camera_lerp_angles( localplayer.angles, velocity_angles,
- inf_fpv,
- localplayer.angles );
+ float inf_fpv = localplayer.cam_velocity_influence_smooth * cc->camera_type_blend,
+ inf_tpv = localplayer.cam_velocity_influence_smooth * (1.0f-cc->camera_type_blend);
+ vg_camera_lerp_angles( localplayer.angles, velocity_angles, inf_fpv, localplayer.angles );
/*
* Third person camera
float ya = atan2f( -cc->cam_velocity_smooth[1], 30.0f );
follow_angles[1] = 0.3f + ya;
- vg_camera_lerp_angles( localplayer.angles, follow_angles,
- inf_tpv,
- localplayer.angles );
+ vg_camera_lerp_angles( localplayer.angles, follow_angles, inf_tpv, localplayer.angles );
v3f pco;
v4f pq;
rb_extrapolate( &localplayer.rb, pco, pq );
- v3_muladds( pco, localplayer.holdout_pose.root_co,
- localplayer.holdout_time, pco );
+ v3_muladds( pco, localplayer.holdout_pose.root_co, localplayer.holdout_time, pco );
v3_lerp( cc->tpv_lpf, pco, 20.0f*vg.time_frame_delta, cc->tpv_lpf );
/* now move into world */
v3_add( tpv_origin, tpv_offset, tpv_pos );
#if 0
- if( localplayer.subsystem == k_player_subsystem_walk )
+ if( localplayer.subsystem == k_player_susystem_walk )
{
v3f fwd, right;
v3_angles_vector( localplayer.angles, fwd );
/* Camera shake */
f32 speed = v3_length(localplayer.rb.v),
strength = k_cam_shake_strength * speed;
- localplayer.cam_trackshake +=
- speed*k_cam_shake_trackspeed*vg.time_frame_delta;
+ localplayer.cam_trackshake += speed*k_cam_shake_trackspeed*vg.time_frame_delta;
v2f rnd = {vg_perlin_fract_1d( localplayer.cam_trackshake, 1.0f, 4, 20 ),
vg_perlin_fract_1d( localplayer.cam_trackshake, 1.0f, 4, 63 ) };
v3_muladds( localplayer.cam_land_punch, localplayer.cam_land_punch_v,
vg.time_frame_delta, localplayer.cam_land_punch );
v3_add( Fd, Fs, F );
- v3_muladds( localplayer.cam_land_punch_v, F, vg.time_frame_delta,
- localplayer.cam_land_punch_v );
- v3_add( localplayer.cam_land_punch, localplayer.cam.pos,
- localplayer.cam.pos );
+ v3_muladds( localplayer.cam_land_punch_v, F, vg.time_frame_delta, localplayer.cam_land_punch_v );
+ v3_add( localplayer.cam_land_punch, localplayer.cam.pos, localplayer.cam.pos );
/* portal transitions */
player_camera_portal_correction();
void player_remote_update_friendflags( struct network_player *remote )
{
ISteamFriends *hSteamFriends = SteamAPI_SteamFriends();
- remote->isfriend = SteamAPI_ISteamFriends_HasFriend( hSteamFriends,
- remote->steamid, k_EFriendFlagImmediate );
- remote->isblocked = SteamAPI_ISteamFriends_HasFriend( hSteamFriends,
- remote->steamid, k_EFriendFlagBlocked );
+ remote->isfriend = SteamAPI_ISteamFriends_HasFriend( hSteamFriends, remote->steamid, k_EFriendFlagImmediate );
+ remote->isblocked = SteamAPI_ISteamFriends_HasFriend( hSteamFriends, remote->steamid, k_EFriendFlagBlocked );
}
-void decode_playerframe( netmsg_playerframe *frame, u32 data_length, struct interp_frame *dest )
+void decode_playerframe( netmsg_playerframe *frame, u32 data_length, struct interp_frame *dest, v2f out_angles,
+ struct net_sfx *sfx_buffer, u32 *inout_sfx_buffer_len )
{
dest->active = 1;
dest->subsystem = frame->subsystem;
};
/* camera */
- v2f _null_v2f = {0,0};
- bitpack_qv2f( &ctx, 8, 0.0f, VG_TAUf, _null_v2f );
+ v2f angles = {0,0};
+ bitpack_qv2f( &ctx, 8, 0.0f, 1.0f, angles );
+ if( out_angles )
+ v2_muls( angles, VG_TAUf, out_angles );
/* animation
* -------------------------------------------------------------*/
/* sfx
* -------------------------------------------------------------*/
+ u32 max_sfx_out = 0, sfx_out = 0;
+
+ if( sfx_buffer )
+ max_sfx_out = *inout_sfx_buffer_len;
+
for( u32 i=0; i<frame->sound_effects; i ++ )
{
- struct net_sfx sfx;
- net_sfx_exchange( &ctx, &sfx );
+ struct net_sfx sfx, *sfx_dst = &sfx;
-#if 0
- f64 t = (frame->timestamp - NETWORK_FRAMERATE) + (sfx.subframe*NETWORK_FRAMERATE);
- f32 remaining = t - ib->t;
-
- if( remaining <= 0.0f )
- net_sfx_play( &sfx );
- else
+ // TODO: Priority?
+ if( i<max_sfx_out )
{
- struct net_sfx *dst = NULL;
- for( u32 j=0; j<NETWORK_SFX_QUEUE_LENGTH; j ++ )
- {
- struct net_sfx *sj = &netplayers.sfx_queue[j];
- if( sj->system == k_player_subsystem_invalid )
- {
- dst = sj;
- break;
- }
-
- if( sj->priority < sfx.priority )
- dst = sj;
- }
-
- *dst = sfx;
- dst->subframe = remaining;
+ sfx_out ++;
+ sfx_dst = &sfx_buffer[i];
}
-#endif
+
+ net_sfx_exchange( &ctx, sfx_dst );
}
+ if( sfx_buffer )
+ *inout_sfx_buffer_len = sfx_out;
+
/* glider
* -------------------------------------------------------------*/
/* camera */
v2f _null_v2f = {0,0};
- bitpack_qv2f( &ctx, 8, 0.0f, VG_TAUf, _null_v2f );
+ bitpack_qv2f( &ctx, 8, 0.0f, 1.0f, _null_v2f );
/* animation
* -------------------------------------------------------------*/
/* camera
* -------------------------------- */
- bitpack_qv2f( &ctx, 8, 0.0f, VG_TAUf, (v2f){ fmod( localplayer.angles[0], VG_TAUf ), localplayer.angles[1] } );
+
+ f32 y = vg_fractf(localplayer.angles[0]/VG_TAUf),
+ p = localplayer.angles[1]/VG_TAUf;
+ bitpack_qv2f( &ctx, 8, 0.0f, 1.0f, (v2f){ y, p } );
/* animation
* -----------------------------------------------*/
void remote_sfx_pre_update(void)
{
- for( u32 i=0; i<NETWORK_SFX_QUEUE_LENGTH; i ++ ){
+ for( u32 i=0; i<NETWORK_SFX_QUEUE_LENGTH; i ++ )
+ {
struct net_sfx *si = &netplayers.sfx_queue[i];
- if( si->system != k_player_subsystem_invalid ){
+ if( si->system != k_player_subsystem_invalid )
+ {
si->subframe -= vg.time_frame_delta;
- if( si->subframe <= 0.0f ){
+ if( si->subframe <= 0.0f )
+ {
net_sfx_play( si );
si->system = k_player_subsystem_invalid;
}
void player_remote_update_friendflags( struct network_player *remote );
void remote_players_init(void);
void remote_sfx_pre_update(void);
-void remote_players_imgui_world( ui_context *ctx, world_instance *world,
- m4x4f pv, f32 max_dist, int geo_cull );
+void remote_players_imgui_world( ui_context *ctx, world_instance *world, m4x4f pv, f32 max_dist, int geo_cull );
void remote_players_imgui_lobby( ui_context *ctx );
void remote_players_chat_imgui( ui_context *ctx );
void pose_remote_player( f64 pose_time, struct interp_frame *f0, struct interp_frame *f1, struct player_board *board,
struct player_board_pose *out_board_pose,
struct player_effects_data *out_effects,
bool *out_render_glider );
+
+void decode_playerframe( netmsg_playerframe *frame, u32 data_length, struct interp_frame *dest, v2f out_angles,
+ struct net_sfx *sfx_buffer, u32 *inout_sfx_buffer_len );
player__cam_iterate();
}
+#if 0
static void player_copy_frame_animator( replay_frame *frame )
{
struct player_subsystem_interface *sys = player_subsystems[localplayer.subsystem];
memcpy( sys->animator_data, src, sys->animator_size );
}
}
+#endif
void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t, player_pose *posed )
{
}
}
+#if 0
void player__animate_from_replay( replay_buffer *replay )
{
+ VG_ASSERT(0);
replay_frame *frame = replay->cursor_frame,
*next = NULL;
if( frame )
apply_full_skeleton_pose( &localplayer.skeleton, &localplayer.pose, localplayer.final_mtx );
}
+#endif
void player__pre_render(void)
{
#include "world.h"
#include "player_render.h"
#include "player_api.h"
-#include "player_replay.h"
enum eboard_truck{
k_board_truck_back = 0,
void player_load_animations( const char *path );
void player_load_animation_reference( const char *path );
void player__render( vg_camera *cam );
-void player__animate_from_replay( replay_buffer *replay );
void player__animate(void);
void player__pre_render(void);
+++ /dev/null
-#include "skaterift.h"
-#include "player.h"
-#include "player_replay.h"
-#include "input.h"
-#include "gui.h"
-#include "freecam.h"
-
-#include "player_walk.h"
-#include "player_skate.h"
-#include "player_dead.h"
-#include "player_glide.h"
-
-struct replay_globals player_replay =
-{
- .active_keyframe = -1,
-};
-
-void replay_clear( replay_buffer *replay )
-{
- replay->head = NULL;
- replay->tail = NULL;
- replay->cursor_frame = NULL;
- replay->statehead = NULL;
- replay->cursor = -99999.9;
-}
-
-void *replay_frame_data( replay_frame *frame, enum replay_framedata type )
-{
- if( frame->data_table[type][1] == 0 )
- return NULL;
-
- void *baseptr = frame;
- return baseptr + frame->data_table[type][0];
-}
-
-static u16 replay_frame_calculate_data_offsets(
- u16 data_table[k_replay_framedata_rows][2] ){
-
- u32 total = vg_align8( sizeof(replay_frame) );
- for( u32 i=0; i<k_replay_framedata_rows; i++ ){
- data_table[i][0] = total;
- total += vg_align8(data_table[i][1]);
-
- if( total > 0xffff )
- vg_fatal_error( "Exceeded frame storage capacity\n" );
- }
- return total;
-}
-
-static void replay_tailpop( replay_buffer *replay ){
- if( replay->cursor_frame == replay->tail )
- replay->cursor_frame = NULL;
- if( replay->statehead == replay->tail )
- replay->statehead = NULL;
-
- replay->tail = replay->tail->r;
-
- if( replay->tail )
- replay->tail->l = NULL;
- else
- replay->head = NULL;
-}
-
-static replay_frame *replay_newframe( replay_buffer *replay, u16 animator_size, u16 gamestate_size, u16 sfx_count,
- bool save_glider )
-{
- u16 data_table[ k_replay_framedata_rows ][2];
- data_table[ k_replay_framedata_animator ][1] = animator_size;
- data_table[ k_replay_framedata_gamestate ][1] = gamestate_size;
- data_table[ k_replay_framedata_sfx ][1] = sfx_count*sizeof(struct net_sfx);
- data_table[ k_replay_framedata_internal_gamestate ][1] = 0;
- if( gamestate_size )
- {
- data_table[ k_replay_framedata_internal_gamestate ][1] =
- sizeof( replay_gamestate );
- }
-
- data_table[ k_replay_framedata_glider ][1] = 0;
- if( save_glider )
- {
- data_table[ k_replay_framedata_glider ][1] =
- sizeof(struct replay_glider_data);
- }
-
- u32 nextsize = replay_frame_calculate_data_offsets( data_table );
-
- replay_frame *frame = NULL;
- if( replay->head )
- {
- u32 headsize = replay->head->total_size,
- nextpos = ((void *)replay->head - replay->data) + headsize;
-
- if( nextpos + nextsize > replay->size )
- {
- nextpos = 0;
-
- /* maintain contiguity */
- while( replay->tail )
- {
- if( (void *)replay->tail - replay->data )
- replay_tailpop( replay );
- else break;
- }
- }
-
-check_again:;
- u32 tailpos = (void *)replay->tail - replay->data;
-
- if( tailpos >= nextpos )
- {
- if( nextpos + nextsize > tailpos )
- {
- replay_tailpop( replay );
-
- if( replay->tail )
- goto check_again;
- }
- }
-
- frame = replay->data + nextpos;
-
- if( replay->head )
- replay->head->r = frame;
- }
- else
- frame = replay->data;
-
- for( u32 i=0; i<k_replay_framedata_rows; i++ )
- {
- frame->data_table[i][0] = data_table[i][0];
- frame->data_table[i][1] = data_table[i][1];
- }
-
- frame->total_size = nextsize;
- frame->l = replay->head;
- frame->r = NULL;
- replay->head = frame;
- if( !replay->tail ) replay->tail = frame;
- if( gamestate_size ) replay->statehead = frame;
-
- return frame;
-}
-
-static void replay_emit_frame_sounds( replay_frame *frame )
-{
- void *baseptr = frame;
- u16 *inf = frame->data_table[k_replay_framedata_sfx];
- struct net_sfx *buffer = baseptr + inf[0];
- u32 count = inf[1] / sizeof(struct net_sfx);
-
- for( u32 i=0; i<count; i ++ ){
- net_sfx_play( buffer + i );
- }
-}
-
-int replay_seek( replay_buffer *replay, f64 t )
-{
- if( !replay->head ) return 0;
-
- if( t < replay->tail->time ) t = replay->tail->time;
- if( t > replay->head->time ) t = replay->head->time;
-
- if( !replay->cursor_frame ) {
- replay->cursor = replay->head->time;
- replay->cursor_frame = replay->head;
-
- if( fabs(replay->head->time-t) > fabs(replay->tail->time-t) ){
- replay->cursor = replay->tail->time;
- replay->cursor_frame = replay->tail;
- }
- }
-
- f64 dir = t - replay->cursor;
- if( dir == 0.0 ) return 0;
- dir = vg_signf( dir );
-
-
- u32 i=4096;
- while( i --> 0 ){
- if( dir < 0.0 ){
- if( t > replay->cursor_frame->time ) {
- replay->cursor = t;
- return 1;
- }
- }
-
- replay_frame *next;
- if( dir > 0.0 ) next = replay->cursor_frame->r;
- else next = replay->cursor_frame->l;
-
- if( !next ) break;
-
- if( dir > 0.0 ){
- if( t < next->time ){
- replay->cursor = t;
- return 1;
- }
- }
-
- replay_emit_frame_sounds( next );
-
- replay->cursor_frame = next;
- replay->cursor = next->time;
-
- if( !i ) return 1;
- }
-
- replay->cursor = t;
- return 0;
-}
-
-replay_frame *replay_find_recent_stateframe( replay_buffer *replay )
-{
- replay_frame *frame = replay->cursor_frame;
- u32 i=4096;
- while( i --> 0 ){
- if( !frame ) return frame;
- if( frame->data_table[ k_replay_framedata_gamestate ][1] ) return frame;
- frame = frame->l;
- }
-
- return NULL;
-}
-
-f32 replay_subframe_time( replay_buffer *replay )
-{
- replay_frame *frame = replay->cursor_frame;
- if( !frame ) return 0.0f;
- replay_frame *next = frame->r;
- if( next )
- {
- f64 l = next->time - frame->time,
- t = (l <= (1.0/128.0))? 0.0: (replay->cursor - frame->time) / l;
- return vg_clampf( t, 0.0f, 1.0f );
- }
- else
- return 0.0f;
-}
-
-void replay_get_frame_camera( replay_frame *frame, vg_camera *cam )
-{
- cam->fov = frame->cam.fov;
- v3_copy( frame->cam.pos, cam->pos );
- v3_copy( frame->cam.angles, cam->angles );
-}
-
-void replay_get_camera( replay_buffer *replay, vg_camera *cam )
-{
- cam->nearz = 0.1f;
- cam->farz = 100.0f;
- if( replay->cursor_frame )
- {
- replay_frame *next = replay->cursor_frame->r;
-
- if( next )
- {
- vg_camera temp;
-
- replay_get_frame_camera( replay->cursor_frame, cam );
- replay_get_frame_camera( next, &temp );
- vg_camera_lerp( cam, &temp, replay_subframe_time( replay ), cam );
- }
- else
- {
- replay_get_frame_camera( replay->cursor_frame, cam );
- }
- }
- else
- {
- v3_zero( cam->pos );
- v3_zero( cam->angles );
- cam->fov = 90.0f;
- }
-}
-
-void skaterift_get_replay_cam( vg_camera *cam )
-{
- replay_buffer *replay = &player_replay.local;
-
- if( player_replay.active_keyframe != -1 )
- {
- replay_keyframe *kf =
- &player_replay.keyframes[player_replay.active_keyframe];
-
- v3_copy( kf->cam.pos, cam->pos );
- v3_copy( kf->cam.angles, cam->angles );
- cam->fov = kf->cam.fov;
- return;
- }
-
- if( player_replay.keyframe_count >= 2 )
- {
- for( u32 i=0; i<player_replay.keyframe_count-1; i ++ )
- {
- replay_keyframe *kf = &player_replay.keyframes[i];
-
- if( (kf[0].time<=replay->cursor) && (kf[1].time>replay->cursor) )
- {
- f64 l = kf[1].time - kf[0].time,
- t = (l <= (1.0/128.0))? 0.0: (replay->cursor-kf[0].time) / l;
-
- if( player_replay.keyframe_count >= 3 )
- {
- f32 m_start = 0.5f, m_end = 0.5f;
-
- if( i > 0 )
- {
- if( (t < 0.5f) || (i==player_replay.keyframe_count-2) )
- {
- kf --;
- }
- }
-
- u32 last = player_replay.keyframe_count-1;
- if( kf+0 == player_replay.keyframes ) m_start = 1.0f;
- if( kf+2 == player_replay.keyframes+last ) m_end = 1.0f;
-
- f32 ts = vg_lerpf( kf[0].time, kf[1].time, 1.0f-m_start ),
- te = vg_lerpf( kf[1].time, kf[2].time, m_end );
-
- l = te-ts;
- t = (replay->cursor-ts)/l;
-
- /*
- * Adjust t, so that its derivative matches at the endpoints.
- * Since t needs to go from 0 to 1, it will naturally change at
- * different rates between keyframes. So this smooths it out.
- *
- * Newton method, going through standard direct quadratic eq has
- * precision / other problems. Also we only care about 0>t>1.
- */
- f32 b = (kf[1].time-ts)/l,
- x0 = 1.0-t;
- for( u32 i=0; i<4; i ++ )
- {
- f32 ix0 = 1.0f-x0,
- fx_x0 = 2.0f*b*x0*ix0 + ix0*ix0 - t,
- fxd_x0 = 2.0f*(-2.0f*b*x0 + b + x0 - 1.0f);
- x0 = x0 - (fx_x0/fxd_x0);
- }
- t = 1.0-x0;
-
- f32 t0 = t*m_start+(1.0f-m_start),
- t1 = t*m_end;
-
- v3f ps, pe, as, ae;
- f32 fs, fe;
-
- /* first order */
- v3_lerp( kf[0].cam.pos, kf[1].cam.pos, t0, ps );
- vg_camera_lerp_angles( kf[0].cam.angles, kf[1].cam.angles,
- t0, as );
- fs = vg_lerpf( kf[0].cam.fov, kf[1].cam.fov, t0 );
-
- v3_lerp( kf[1].cam.pos, kf[2].cam.pos, t1, pe );
- vg_camera_lerp_angles( kf[1].cam.angles, kf[2].cam.angles,
- t1, ae );
- fe = vg_lerpf( kf[1].cam.fov, kf[2].cam.fov, t1 );
-
- /* second order */
- v3_lerp( ps, pe, t, cam->pos );
- vg_camera_lerp_angles( as, ae, t, cam->angles );
- cam->fov = vg_lerpf( fs, fe, t );
- }
- else
- {
- v3_lerp( kf[0].cam.pos, kf[1].cam.pos, t, cam->pos );
- vg_camera_lerp_angles( kf[0].cam.angles, kf[1].cam.angles,
- t, cam->angles );
- cam->fov = vg_lerpf( kf[0].cam.fov, kf[1].cam.fov, t );
- }
- return;
- }
- }
- }
-
- replay_get_camera( replay, cam );
-}
-
-struct replay_rb
-{
- v3f co, v, w;
- v4f q;
-};
-
-void skaterift_record_frame( replay_buffer *replay, int force_gamestate )
-{
- f64 delta = 9999999.9,
- statedelta = 9999999.9;
-
- if( replay->head )
- delta = vg.time - replay->head->time;
-
- if( replay->statehead )
- statedelta = vg.time - replay->statehead->time;
-
- const f64 k_replay_rate = 1.0/30.0,
- k_gamestate_rate = 0.5;
-
- int save_frame = 0,
- save_state = 0,
- save_glider = 0;
-
- if( force_gamestate ) save_state = 1;
- if( statedelta > k_gamestate_rate ) save_state = 1;
- if( delta > k_replay_rate ) save_frame = 1;
- if( save_state ) save_frame = 1;
-
- if( localplayer.have_glider || localplayer.glider_orphan || localplayer.subsystem == k_player_subsystem_glide )
- save_glider = 1;
-
- if( !save_frame ) return;
-
- u16 gamestate_size = 0;
- if( save_state )
- {
- /* TODO: have as part of system struct */
- gamestate_size = (u32 []){
- [k_player_subsystem_walk ] = sizeof(struct player_walk_state),
- [k_player_subsystem_drive] = 0,
- [k_player_subsystem_skate] = sizeof(struct player_skate_state),
- [k_player_subsystem_dead ] = localplayer.ragdoll.part_count * sizeof(struct replay_rb),
- [k_player_subsystem_glide] = sizeof(struct replay_rb),
- }[ localplayer.subsystem ];
- }
-
- u16 animator_size = player_subsystems[localplayer.subsystem]->animator_size;
-
- replay_frame *frame = replay_newframe( replay, animator_size, gamestate_size,
- localplayer.local_sfx_buffer_count,
- save_glider );
- frame->system = localplayer.subsystem;
-
- if( save_state )
- {
- replay_gamestate *gs = replay_frame_data( frame, k_replay_framedata_internal_gamestate );
-
- gs->current_run_version = _world.current_run_version;
- gs->drowned = localplayer.drowned;
-
- /* permanent block */
- memcpy( &gs->rb, &localplayer.rb, sizeof(rigidbody) );
- memcpy( &gs->glider_rb, &player_glide.rb, sizeof(rigidbody) );
- memcpy( &gs->cam_control, &localplayer.cam_control,
- sizeof(struct player_cam_controller) );
- v3_copy( localplayer.angles, gs->angles );
-
- void *dst = replay_frame_data( frame, k_replay_framedata_gamestate );
-
- /* subsytem/dynamic block */
- if( localplayer.subsystem == k_player_subsystem_walk )
- memcpy( dst, &player_walk.state, gamestate_size );
- else if( localplayer.subsystem == k_player_subsystem_skate )
- memcpy( dst, &player_skate.state, gamestate_size );
- else if( localplayer.subsystem == k_player_subsystem_dead ){
- struct replay_rb *arr = dst;
- for( u32 i=0; i<localplayer.ragdoll.part_count; i ++ ){
- rigidbody *rb = &localplayer.ragdoll.parts[i].rb;
- v3_copy( rb->co, arr[i].co );
- v3_copy( rb->w, arr[i].w );
- v3_copy( rb->v, arr[i].v );
- v4_copy( rb->q, arr[i].q );
- }
- }
- else if( localplayer.subsystem == k_player_subsystem_glide ){
- struct replay_rb *arr = dst;
- rigidbody *rb = &player_glide.rb;
- v3_copy( rb->co, arr[0].co );
- v3_copy( rb->w, arr[0].w );
- v3_copy( rb->v, arr[0].v );
- v4_copy( rb->q, arr[0].q );
- }
- }
-
- if( save_glider )
- {
- struct replay_glider_data *inf = replay_frame_data( frame, k_replay_framedata_glider );
- inf->have_glider = localplayer.have_glider;
- inf->glider_orphan = localplayer.glider_orphan;
- inf->t = player_glide.t;
- v3_copy( player_glide.rb.co, inf->co );
- v4_copy( player_glide.rb.q, inf->q );
- }
-
- replay->cursor = vg.time;
- replay->cursor_frame = frame;
- frame->time = vg.time;
-
- /* camera */
- v3_copy( localplayer.cam.pos, frame->cam.pos );
- if( localplayer.gate_waiting ){
- m4x3_mulv( localplayer.gate_waiting->transport,
- frame->cam.pos, frame->cam.pos );
-
- v3f v0;
- v3_angles_vector( localplayer.cam.angles, v0 );
- m3x3_mulv( localplayer.gate_waiting->transport, v0, v0 );
- v3_angles( v0, frame->cam.angles );
- }
- else
- v3_copy( localplayer.cam.angles, frame->cam.angles );
-
- frame->cam.fov = localplayer.cam.fov;
-
- /* animator */
- void *dst = replay_frame_data( frame, k_replay_framedata_animator ),
- *src = player_subsystems[localplayer.subsystem]->animator_data;
- memcpy( dst, src, animator_size );
-
- /* sound effects */
- memcpy( replay_frame_data( frame, k_replay_framedata_sfx ),
- localplayer.local_sfx_buffer,
- sizeof(struct net_sfx)*localplayer.local_sfx_buffer_count );
-
- localplayer.local_sfx_buffer_count = 0;
-}
-
-static void skaterift_restore_frame( replay_frame *frame )
-{
- replay_gamestate *gs =
- replay_frame_data( frame, k_replay_framedata_internal_gamestate );
- void *src = replay_frame_data( frame, k_replay_framedata_gamestate );
- u16 src_size = frame->data_table[ k_replay_framedata_gamestate ][1];
- _world.current_run_version = gs->current_run_version;
- localplayer.drowned = gs->drowned;
-
- if(frame->system == k_player_subsystem_walk ){
- memcpy( &player_walk.state, src, src_size );
- }
- else if( frame->system == k_player_subsystem_skate ){
- memcpy( &player_skate.state, src, src_size );
- }
- else if( frame->system == k_player_subsystem_dead ){
- player__dead_transition(0);
- struct replay_rb *arr = src;
-
- for( u32 i=0; i<localplayer.ragdoll.part_count; i ++ ){
- struct ragdoll_part *part = &localplayer.ragdoll.parts[i];
- rigidbody *rb = &part->rb;
-
- v3_copy( arr[i].co, rb->co );
- v3_copy( arr[i].w, rb->w );
- v3_copy( arr[i].v, rb->v );
- v4_copy( arr[i].q, rb->q );
-
- v3_copy( arr[i].co, part->prev_co );
- v4_copy( arr[i].q, part->prev_q );
- rb_update_matrices( rb );
- }
- }
- else if( frame->system == k_player_subsystem_glide ){
- struct replay_rb *arr = src;
- rigidbody *rb = &player_glide.rb;
- v3_copy( arr[0].co, rb->co );
- v3_copy( arr[0].w, rb->w );
- v3_copy( arr[0].v, rb->v );
- v4_copy( arr[0].q, rb->q );
- rb_update_matrices( rb );
- }
-
- localplayer.subsystem = frame->system;
-
- /* restore the seperated glider data if we have it */
- if( frame->data_table[ k_replay_framedata_glider ][1] ){
- struct replay_glider_data *inf =
- replay_frame_data( frame, k_replay_framedata_glider );
-
- localplayer.have_glider = inf->have_glider;
- localplayer.glider_orphan = inf->glider_orphan;
- player_glide.t = inf->t;
- }
- else {
- localplayer.have_glider = 0;
- localplayer.glider_orphan = 0;
- player_glide.t = 0.0f;
- }
-
- memcpy( &localplayer.rb, &gs->rb, sizeof(rigidbody) );
- memcpy( &player_glide.rb, &gs->glider_rb, sizeof(rigidbody) );
- v3_copy( gs->angles, localplayer.angles );
-
- v3_copy( frame->cam.pos, localplayer.cam.pos );
- v3_copy( frame->cam.angles, localplayer.cam.angles );
- localplayer.cam.fov = frame->cam.fov;
-
- memcpy( &localplayer.cam_control, &gs->cam_control,
- sizeof(struct player_cam_controller) );
-
- /* chop end off replay */
- frame->r = NULL;
- player_replay.local.statehead = frame;
- player_replay.local.head = frame;
- player_replay.local.cursor_frame = frame;
- player_replay.local.cursor = frame->time;
- player_replay.replay_control = k_replay_control_scrub;
- skaterift.activity = k_skaterift_default;
- vg.time = frame->time;
-}
-
-static void skaterift_replay_resume(void)
-{
- replay_frame *prev = replay_find_recent_stateframe(&player_replay.local);
-
- if( prev )
- {
- player_replay.replay_control = k_replay_control_resume;
- player_replay.resume_target = prev;
- player_replay.resume_begin = player_replay.local.cursor;
- player_replay.resume_transition = 0.0f;
- }
-}
-
-static void _remote_replay_pre_update(void);
-void skaterift_replay_pre_update(void)
-{
- if( skaterift.activity != k_skaterift_replay )
- return;
-
- bool input = 1;
-
- if( player_replay.replay_control == k_replay_control_resume )
- {
- if( player_replay.local.cursor_frame == player_replay.resume_target ||
- player_replay.local.cursor_frame == NULL )
- {
- skaterift_restore_frame( player_replay.resume_target );
- }
- else
- {
- vg_slewf( &player_replay.resume_transition, 1.0f, vg.time_frame_delta * (1.0f/1.0f) );
-
- if( player_replay.resume_transition >= 1.0f )
- skaterift_restore_frame( player_replay.resume_target );
- else {
- f64 target = vg_lerp( player_replay.resume_begin,
- player_replay.resume_target->time,
- vg_smoothstepf( player_replay.resume_transition ) );
- if( replay_seek( &player_replay.local, target ) )
- player_replay.track_velocity = 1.0f;
- else
- player_replay.track_velocity = 0.0f;
- }
- }
- }
- else
- {
- if( button_down( k_srbind_replay_play ) )
- player_replay.replay_control ^= k_replay_control_play;
-
- if( button_down( k_srbind_replay_freecam ) )
- {
- player_replay.use_freecam ^= 0x1;
-
- if( player_replay.use_freecam )
- {
- replay_get_camera( &player_replay.local, &player_replay.replay_freecam );
- }
- }
-
- if( button_down( k_srbind_replay_hide_ui ) )
- player_replay.hide_ui = 1;
-
- f32 target_speed = axis_state( k_sraxis_replay_h ) * 5.0;
-
- if( fabsf(target_speed) > 0.01f )
- player_replay.replay_control = k_replay_control_scrub;
-
- if( player_replay.replay_control == k_replay_control_play )
- target_speed = 1.0;
-
- vg_slewf( &player_replay.track_velocity, target_speed, 18.0f*vg.time_frame_delta );
-
- if( fabsf( player_replay.track_velocity ) > 0.0001f )
- {
- f64 target = player_replay.local.cursor;
- target += player_replay.track_velocity * vg.time_frame_delta;
-
- if( !replay_seek( &player_replay.local, target ) )
- player_replay.track_velocity = 0.0f;
- }
-
- if( button_down( k_srbind_mback ) )
- {
- if( player_replay.hide_ui )
- {
- player_replay.hide_ui = 0;
- }
- else
- {
- if( player_replay.local.statehead )
- skaterift_restore_frame( player_replay.local.statehead );
- else
- skaterift.activity = k_skaterift_default;
- }
- srinput.state = k_input_state_resume;
- }
-
- if( player_replay.use_freecam )
- {
- freecam_preupdate();
- }
- else
- {
- if( skaterift.allow_replay_resume )
- {
- if( button_down( k_srbind_replay_resume ) )
- {
- skaterift_replay_resume();
- }
- }
- }
- }
-}
-
-void skaterift_open_replay(void)
-{
- vg_error( "stub!!!\n" );
- return;
-
- skaterift.activity = k_skaterift_replay;
- skaterift_record_frame( &player_replay.local, 1 );
- if( player_replay.local.head )
- {
- player_replay.local.cursor = player_replay.local.head->time;
- player_replay.local.cursor_frame = player_replay.local.head;
- }
- player_replay.replay_control = k_replay_control_scrub;
- player_replay.hide_ui = 0;
- gui_helper_reset( k_gui_helper_mode_clear );
-}
-
-void skaterift_replay_init(void)
-{
- u32 MB = 1024*1024;
- player_replay.local.data = vg_linear_alloc( vg_mem.rtmemory, 6*MB );
- player_replay.local.size = 6*MB;
- replay_clear( &player_replay.local );
-}
-
-void skaterift_replay_debug_info( ui_context *ctx )
-{
- player__debugtext( ctx, 2, "replay info" );
- replay_buffer *replay = &player_replay.local;
-
- u32 head = 0,
- tail = 0;
- if( replay->tail ) tail = (void *)replay->tail - replay->data;
- if( replay->head ) head = (void *)replay->head - replay->data;
-
- player__debugtext( ctx, 1, "head @%u | tail @%u\n", head, tail );
-
- if( replay->statehead )
- {
- for( u32 i=0; i<k_replay_framedata_rows; i++ )
- {
- player__debugtext( ctx, 1, "[%u]: [%hu, %hu]\n", i,
- replay->statehead->data_table[i][0],
- replay->statehead->data_table[i][1] );
- }
- u32 state = (void *)replay->statehead - replay->data;
- player__debugtext( ctx, 1, "gs @%u\n", state );
- player__debugtext( ctx, 1, "gamestate_size: %hu\n",
- replay->statehead->data_table[k_replay_framedata_gamestate][1] );
- }
- else
- player__debugtext( ctx, 1, "gs @NULL\n" );
-
- f64 start = replay->cursor,
- end = replay->cursor;
- if( replay->tail ) start = replay->tail->time;
- if( replay->head ) end = replay->head->time;
-
- f64 cur = replay->cursor - start,
- len = end - start;
-
- player__debugtext( ctx, 1, "cursor: %.2fs / %.2fs\n", cur, len );
-}
-
-static int _keyframe_cmp( const void *p1, const void *p2 )
-{
- const replay_keyframe *kf1 = p1, *kf2 = p2;
- return kf1->time > kf2->time;
-}
-
-static void replay_keyframe_sort(void)
-{
- qsort( player_replay.keyframes, player_replay.keyframe_count,
- sizeof(replay_keyframe), _keyframe_cmp );
-}
-
-static void replay_fly_edit_keyframe( ui_context *ctx, replay_keyframe *kf )
-{
- if( ui_click_down( ctx, UI_MOUSE_LEFT ) )
- {
- /* init freecam */
- v3_copy( kf->cam.pos, player_replay.replay_freecam.pos );
- v3_copy( kf->cam.angles, player_replay.replay_freecam.angles );
- v3_zero( player_replay.freecam_v );
- v3_zero( player_replay.freecam_w );
- player_replay.replay_freecam.fov = kf->cam.fov;
- }
-
- /* move freecam */
- ui_capture_mouse( ctx, 0 );
- freecam_preupdate();
-
- if( vg_getkey(SDLK_q) )
- player_replay.freecam_v[1] -= vg.time_frame_delta*6.0f*20.0f;
- if( vg_getkey(SDLK_e) )
- player_replay.freecam_v[1] += vg.time_frame_delta*6.0f*20.0f;
-
- v3_copy( player_replay.replay_freecam.pos, g_render.cam.pos );
- v3_copy( player_replay.replay_freecam.angles, g_render.cam.angles);
- g_render.cam.fov = player_replay.replay_freecam.fov;
-
- v3_copy( g_render.cam.pos, kf->cam.pos );
- v3_copy( g_render.cam.angles, kf->cam.angles );
- kf->cam.fov = g_render.cam.fov;
-}
-
-void skaterift_replay_imgui( ui_context *ctx )
-{
- if( skaterift.activity != k_skaterift_replay )
- return;
-
- if( player_replay.hide_ui )
- return;
-
- if( vg_input.display_input_method != k_input_method_controller )
- {
- ui_capture_mouse( ctx, 1 );
- }
-
- replay_buffer *replay = &player_replay.local;
- f64 start = replay->cursor,
- end = replay->cursor;
- if( replay->tail ) start = replay->tail->time;
- if( replay->head ) end = replay->head->time;
- f64 len = end - start,
- cur = (replay->cursor - start) / len;
-
- char buffer[ 128 ];
-
- /* mainbar */
- ui_rect timeline = { 8, vg.window_y-(32+8), vg.window_x-16, 32 };
- ui_rect start_box;
- ui_split( timeline, k_ui_axis_v, 32, 8, start_box, timeline );
-
- const char *start_text = (player_replay.replay_control == k_replay_control_play)? "||": ">";
- if( menu_button_rect( ctx, start_box, 0, 1, start_text ) )
- {
- player_replay.replay_control ^= k_replay_control_play;
- }
-
- ui_fill( ctx, timeline, ui_colour( ctx, k_ui_bg ) );
-
- /* cursor frame block */
- if( replay->cursor_frame )
- {
- if( replay->cursor_frame->r )
- {
- f64 l = (replay->cursor_frame->r->time-replay->cursor_frame->time)/len,
- s = (replay->cursor_frame->time - start) / len;
- ui_rect box = { timeline[0] + s*(f64)timeline[2], timeline[1],
- VG_MAX(4,(ui_px)(l*timeline[2])), timeline[3]+2 };
- ui_fill( ctx, box, ui_colour( ctx, k_ui_bg+4 ) );
- }
- }
-
- /* cursor */
- ui_rect cusor = { timeline[0] + cur*(f64)timeline[2] - 1, timeline[1],
- 2, timeline[3] };
- ui_fill( ctx, cusor, ui_colour( ctx, k_ui_bg+7 ) );
-
- /* latest state marker */
- if( skaterift.allow_replay_resume )
- {
- if( replay->statehead )
- {
- f64 t = (replay->statehead->time - start) / len;
- ui_rect tag = { timeline[0] + t*(f64)timeline[2], timeline[1],
- 2, timeline[3]+8 };
- ui_fill( ctx, tag, ui_colour( ctx, k_ui_green+k_ui_brighter ) );
- }
-
- /* previous state marker */
- replay_frame *prev = replay_find_recent_stateframe( replay );
- if( prev )
- {
- f64 t = (prev->time - start) / len;
- ui_rect tag = { timeline[0] + t*(f64)timeline[2], timeline[1],
- 2, timeline[3]+8 };
- ui_fill( ctx, tag, ui_colour( ctx, k_ui_yellow+k_ui_brighter ) );
- }
- }
-
- snprintf( buffer, 128, "-%.2fs", (end-replay->cursor) );
- ui_text( ctx, timeline, buffer, 1, k_ui_align_middle_left, 0 );
- ui_text( ctx, timeline, "0s", 1, k_ui_align_middle_right, 0 );
-
-
- /* helpers */
- ctx->font = &vgf_default_large;
-
- ui_rect helper_list_l = { 10, timeline[1] - (ctx->font->sy+8), vg.window_x/2, ctx->font->sy };
- char buf[256];
- vg_str str;
- vg_strnull( &str, buf, sizeof(buf) );
- vg_input_string( &str, input_axis_list[k_sraxis_replay_h], 1 );
- vg_strcat( &str, "\x07 Scrub" );
- ui_text( ctx, helper_list_l, buf, 1, k_ui_align_left, 0 );
- helper_list_l[1] -= helper_list_l[3]+2;
-
- vg_strnull( &str, buf, sizeof(buf) );
- vg_input_string( &str, input_button_list[k_srbind_replay_play], 1 );
- vg_strcat( &str, (player_replay.replay_control == k_replay_control_play)? "\x07 Pause": "\x07 Play" );
- ui_text( ctx, helper_list_l, buf, 1, k_ui_align_left, 0 );
- helper_list_l[1] -= helper_list_l[3]+2;
-
- vg_strnull( &str, buf, sizeof(buf) );
- vg_input_string( &str, input_button_list[k_srbind_replay_freecam], 1 );
- vg_strcat( &str, "\x07 Freecam" );
- ui_text( ctx, helper_list_l, buf, 1, k_ui_align_left, 0 );
- helper_list_l[1] -= helper_list_l[3]+2;
-
- vg_strnull( &str, buf, sizeof(buf) );
- vg_input_string( &str, input_button_list[k_srbind_replay_hide_ui], 1 );
- vg_strcat( &str, "\x07 Hide UI" );
- ui_text( ctx, helper_list_l, buf, 1, k_ui_align_left, 0 );
- helper_list_l[1] -= helper_list_l[3]+2;
-
- ui_rect helper_list_r = { vg.window_x/2, timeline[1] - (ctx->font->sy+8), vg.window_x/2-10, ctx->font->sy };
- vg_strnull( &str, buf, sizeof(buf) );
- vg_input_string( &str, input_button_list[k_srbind_mback], 1 );
- vg_strcat( &str, "\x07 Exit Replay" );
- ui_text( ctx, helper_list_r, buf, 1, k_ui_align_right, 0 );
- helper_list_l[1] -= helper_list_r[3]+2;
-
- if( player_replay.use_freecam )
- {
- ui_rect box = { vg.window_x/2 - 200, 40, 400, ctx->font->sy };
- ui_text( ctx, box, KYEL "\x06\x02--- Freecam Enabled ---", 1, k_ui_align_center, 0 );
- }
-
- ctx->font = &vgf_default_small;
-
- /* timeline scrub */
- bool start_in_timeline =
- ui_clicking(ctx, UI_MOUSE_LEFT) &&
- ui_inside_rect(timeline, ctx->mouse_click);
-
- if( (ui_inside_rect( timeline, ctx->mouse )) || start_in_timeline )
- {
- ui_rect cursor = { ctx->mouse[0], timeline[1], 4, timeline[3] };
- ui_fill( ctx, cursor, ui_colour( ctx, k_ui_fg ) );
- ctx->cursor = k_ui_cursor_ibeam;
-
- if( ui_clicking( ctx, UI_MOUSE_LEFT ) && start_in_timeline )
- {
- f64 mouse_t = start + ((f64)(ctx->mouse[0]-timeline[0]) / (f64)timeline[2])*len;
- replay_seek( &player_replay.local, mouse_t );
- player_replay.active_keyframe = -1;
- }
- }
-
-
- /* This contains the UI for the old removed keyframe editor --------------------------------------- */
-#if 0
- /* script bar */
- ui_rect script = { timeline[0], timeline[1]+timeline[3] + 2, timeline[2], 16 };
- ui_fill( ctx, script, ui_colour( ctx, k_ui_bg ) );
-
- /* keyframe draw and select */
- bool absorb_by_keyframe = 0;
- ui_px lx = 0;
- for( u32 i=0; i<player_replay.keyframe_count; i ++ )
- {
- replay_keyframe *kf = &player_replay.keyframes[i];
- f64 t = (kf->time-start)/len;
-
- ui_px x = timeline[0] + t*(f64)timeline[2]-8;
-
- /* draw connections between keyframes */
- if( i )
- {
- ui_rect con = { lx, script[1]+7, x-lx, 1 };
- ui_fill( ctx, con, ui_colour( ctx, k_ui_blue ) );
- vg_line( kf->cam.pos, player_replay.keyframes[i-1].cam.pos, VG__BLUE );
- }
-
- /* keyframe selection */
- ui_rect tag = { x, script[1], 16, 16 };
-
- if( ui_inside_rect( tag, ctx->mouse ) )
- {
- absorb_by_keyframe = 1;
-
- if( ui_click_down( ctx, UI_MOUSE_LEFT ) )
- {
- if( player_replay.active_keyframe != i )
- {
- player_replay.active_keyframe = i;
- replay_seek( &player_replay.local, kf->time );
- }
- }
- else
- {
- ui_outline( ctx, tag, 1, ui_colour(ctx, k_ui_fg), 0 );
- }
- }
-
- /* edit controls */
- u32 drag_colour = ui_opacity( ui_colour(ctx, k_ui_bg+2), 0.5f );
- if( i == player_replay.active_keyframe )
- {
- ui_outline( ctx, tag, 2, ui_colour(ctx, k_ui_fg), 0 );
-
- ui_rect tray = { tag[0]+8-32, tag[1]+16+2, 64, 16 };
- ui_rect dragbar = { tray[0]+16, tray[1], 32, 16 };
-
- bool pos_correct = 0;
-
- if( ui_inside_rect( dragbar, ctx->mouse_click ) )
- {
- if( ui_clicking( ctx, UI_MOUSE_LEFT ) )
- {
- drag_colour = ui_opacity( ui_colour(ctx,k_ui_fg), 0.5f );
- pos_correct = 1;
- replay_seek( &player_replay.local, mouse_t );
- }
- else if( ui_click_up( ctx, UI_MOUSE_LEFT ) )
- {
- pos_correct = 1;
- kf->time = mouse_t;
- replay_keyframe_sort();
-
- for( u32 j=0; j<player_replay.keyframe_count; j ++ )
- {
- if( player_replay.keyframes[j].time == mouse_t )
- {
- player_replay.active_keyframe = j;
- break;
- }
- }
- }
-
- if( pos_correct )
- {
- tag[0] = ctx->mouse[0]-8;
- tray[0] = tag[0]+8-32;
- dragbar[0] = tray[0]+16;
- }
- }
-
- if( ui_inside_rect( dragbar, ctx->mouse ) )
- {
- ctx->cursor = k_ui_cursor_hand;
- }
-
- if( !pos_correct )
- {
- ui_fill( ctx, tray,
- ui_opacity( ui_colour( ctx, k_ui_bg+2 ), 0.5f ) );
- }
-
- ui_fill( ctx, dragbar, drag_colour );
- ui_text( ctx, dragbar, ":::", 1, k_ui_align_middle_center, 0 );
-
- if( !pos_correct )
- {
- ui_rect btn = { tray[0], tray[1], 16, 16 };
- if( ui_button_text( ctx, btn, "X", 1 ) == k_ui_button_click )
- {
- for( u32 j=i; j<player_replay.keyframe_count-1; j ++ )
- player_replay.keyframes[j] = player_replay.keyframes[j+1];
-
- player_replay.keyframe_count --;
- player_replay.active_keyframe = -1;
- }
-
- ui_rect btn1 = { tray[0]+48, tray[1], 16, 16 };
-
- enum ui_button_state mask_using =
- k_ui_button_holding_inside |
- k_ui_button_holding_outside |
- k_ui_button_click;
-
- if( ui_button_text( ctx, btn1, "E", 1 ) & mask_using )
- {
- replay_fly_edit_keyframe( ctx, kf );
- vg_ui_set_mouse_pos( btn1[0]+8, btn1[1]+8 );
- }
- }
- }
-
- ui_fill( ctx, tag, ui_colour( ctx, k_ui_blue ) );
- lx = x;
- }
-
- /* adding keyframes */
- if( ui_inside_rect( script, ctx->mouse ) )
- {
- ctx->cursor = k_ui_cursor_hand;
-
- ui_rect cursor = { ctx->mouse[0], script[1], 4, 16 };
- ui_fill( ctx, cursor, ui_colour( ctx, k_ui_fg ) );
-
- if( !absorb_by_keyframe && ui_click_down( ctx, UI_MOUSE_LEFT ) )
- {
- u32 max = VG_ARRAY_LEN( player_replay.keyframes );
- if( player_replay.keyframe_count == max )
- {
- ui_start_modal( ctx, "Maximum keyframes reached", UI_MODAL_BAD );
- }
- else
- {
- replay_keyframe *kf =
- &player_replay.keyframes[player_replay.keyframe_count++];
-
- kf->time = mouse_t;
- v3_copy( g_render.cam.pos, kf->cam.pos );
- v3_copy( g_render.cam.angles, kf->cam.angles );
- kf->cam.fov = g_render.cam.fov;
-
- replay_keyframe_sort();
- }
- }
- }
-#endif
-
-#if 0
- if( ui_button( ctx, panel, "Clear keyframes" ) == k_ui_button_click )
- {
- player_replay.keyframe_count = 0;
- }
-
- if( (ui_button( ctx, panel, "Hide UI (F2)" ) == k_ui_button_click) )
- {
- player_replay.hide_ui = 1;
- }
-
- if( player_replay.active_keyframe != -1 )
- {
- replay_keyframe *kf =
- &player_replay.keyframes[ player_replay.active_keyframe ];
-
- enum ui_button_state mask_using =
- k_ui_button_holding_inside |
- k_ui_button_holding_outside |
- k_ui_button_click;
-
- if( ui_button( ctx, panel, "Edit cam" ) & mask_using )
- {
- replay_fly_edit_keyframe( ctx, kf );
- }
- }
-
- ui_info( ctx, panel, "World settings" );
- f32 new_time = _world.main.time;
- if( ui_slider( ctx, panel, "Time of day", 0, 1, &new_time ) )
- _world.main.time = new_time;
-
- ui_info( ctx, panel, "" );
-#endif
-}
+++ /dev/null
-#pragma once
-#include "player_render.h"
-#include "vg/vg_rigidbody.h"
-
-typedef struct replay_buffer replay_buffer;
-typedef struct replay_frame replay_frame;
-typedef struct replay_keyframe replay_keyframe;
-
-typedef struct replay_gamestate replay_gamestate;
-typedef struct replay_sfx replay_sfx;
-
-struct replay_buffer {
- void *data;
- u32 size; /* bytes */
-
- replay_frame *head, *tail, *cursor_frame,
- *statehead;
- f64 cursor;
-};
-
-enum replay_framedata{
- k_replay_framedata_animator,
- k_replay_framedata_gamestate,
- k_replay_framedata_internal_gamestate,
- k_replay_framedata_sfx,
- k_replay_framedata_glider,
- k_replay_framedata_rows
-};
-
-struct replay_cam
-{
- v3f pos, angles;
- f32 fov;
-};
-
-struct replay_frame
-{
- struct replay_cam cam;
- f64 time;
-
- replay_frame *l, *r;
-
- enum player_subsystem system;
- u16 total_size;
- u16 data_table[k_replay_framedata_rows][2];
-};
-
-/* player-defined replay frames */
-struct replay_keyframe
-{
- struct replay_cam cam;
- f64 time;
-};
-
-struct replay_gamestate
-{
- rigidbody rb, glider_rb; /* TODO: these don't need to be saved with their
- full matrices */
- v3f angles;
- struct player_cam_controller cam_control;
- u32 current_run_version;
- bool drowned;
-};
-
-/* we save this per-anim-frame. if there glider is existing in any state */
-struct replay_glider_data
-{
- bool have_glider, glider_orphan;
- f32 t;
- v3f co;
- v4f q;
-};
-
-struct replay_sfx {
- u32 none;
-};
-
-struct replay_globals
-{
- replay_buffer local;
-
- replay_frame *resume_target;
- f64 resume_begin;
- f32 resume_transition;
-
- enum replay_control {
- k_replay_control_scrub = 0x00,
- k_replay_control_play = 0x01,
- k_replay_control_resume= 0x02
- }
- replay_control;
- f32 track_velocity;
- struct gui_helper *helper_resume, *helper_freecam;
-
- vg_camera replay_freecam;
- bool use_freecam;
- bool hide_ui;
- v3f freecam_v, freecam_w;
-
- i32 editor_mode;
- replay_keyframe keyframes[32];
- u32 keyframe_count;
- i32 active_keyframe;
-}
-extern player_replay;
-
-int replay_seek( replay_buffer *replay, f64 t );
-
-replay_frame *replay_find_recent_stateframe( replay_buffer *replay );
-void replay_get_camera( replay_buffer *replay, vg_camera *cam );
-void replay_get_frame_camera( replay_frame *frame, vg_camera *cam );
-f32 replay_subframe_time( replay_buffer *replay );
-void replay_clear( replay_buffer *replay );
-void *replay_frame_data( replay_frame *frame, enum replay_framedata type );
-
-void skaterift_replay_pre_update(void);
-void skaterift_replay_imgui( ui_context *ctx );
-void skaterift_replay_debug_info( ui_context *ctx );
-void skaterift_record_frame( replay_buffer *replay, int force_gamestate );
-void skaterift_replay_post_render(void);
-void skaterift_replay_init(void);
-void skaterift_get_replay_cam( vg_camera *cam );
-void skaterift_open_replay(void);
slide = 0.0f;
f32 gate = skaterift.time_rate;
-
- if( skaterift.activity == k_skaterift_replay ){
- gate = vg_minf( 1.0f, fabsf(player_replay.track_velocity) );
- }
+ if( skaterift.activity == k_skaterift_replay )
+ gate = vg_minf( 1.0f, fabsf(_replay2.track_velocity) );
f32 vol_main = sqrtf( (1.0f-air)*attn*(1.0f-slide) * 0.4f ) * gate,
vol_air = sqrtf( air *attn * 0.5f ) * gate,
player__pass_gate( id );
}
- /* FIXME: Rate limit */
static int stick_frames = 0;
if( state->activity >= k_skate_activity_ground )
#include "replay2.h"
struct _remote_replay _remote_replay;
-struct _replay_player _replay_player;
+struct _replay2 _replay2;
void _replay2_init(void)
{
u32 MB = 1024*1024,
size = 4*MB;
- _remote_replay.replay.buffer.buffer = vg_linear_alloc( vg_mem.rtmemory, size );
- _remote_replay.replay.buffer.size = size;
+ _remote_replay.buffer.buffer = vg_linear_alloc( vg_mem.rtmemory, size );
+ _remote_replay.buffer.size = size;
+
+ _replay2.buffer.buffer = vg_linear_alloc( vg_mem.rtmemory, size*2 );
+ _replay2.buffer.size = size*2;
struct skeleton *sk = &localplayer.skeleton;
u32 mtx_size = sizeof(m4x3f)*sk->bone_count;
- _replay_player.final_mtx = vg_linear_alloc( vg_mem.rtmemory, mtx_size );
+ _replay2.final_mtx = vg_linear_alloc( vg_mem.rtmemory, mtx_size );
}
-void _replay2_open_player( replay2 *replay, bool end )
+static vg_queue *_replay2_player_buffer(void)
{
- if( replay == NULL )
- {
- vg_error( "Cannot open a NULL replay\n" );
- return;
- }
- if( replay->buffer.allocation_count < 2 )
- {
- vg_error( "Not enough frames in that replay\n" );
- return;
- }
+ return _replay2.type == k_replay_type_local? &_replay2.buffer: &_remote_replay.buffer;
+}
+void _replay2_open_player( enum replay_type type, bool end )
+{
skaterift.activity = k_skaterift_replay;
- _replay_player.replay = replay;
+ _replay2.type = type;
+ _replay2.animation_dirty = 1;
+
+ vg_queue *buffer = _replay2_player_buffer();
+ if( buffer->allocation_count >= 2 )
+ {
+ if( end ) _replay2.cursor_frame_offset = buffer->head_offset;
+ else _replay2.cursor_frame_offset = buffer->tail_offset;
- if( end )
- _replay_player.cursor_frame_offset = replay->buffer.head_offset;
+ replay2_frame *frame = vg_queue_data( buffer, _replay2.cursor_frame_offset );
+ _replay2.cursor = frame->time;
+
+ if( type == k_replay_type_local )
+ {
+ replay2_frame *frame_start = vg_queue_data( buffer, buffer->tail_offset ),
+ *frame_end = vg_queue_data( buffer, buffer->head_offset );
+
+ _replay2.start_t = frame_start->time;
+ _replay2.end_t = frame_end->time;
+ }
+ }
else
- _replay_player.cursor_frame_offset = replay->buffer.tail_offset;
+ _replay2.cursor_frame_offset = 0;
- replay2_frame *frame = vg_queue_data( &replay->buffer, _replay_player.cursor_frame_offset );
- _replay_player.cursor = frame->time;
+ if( type == k_replay_type_local )
+ {
+ _replay2.highlight = 0;
+ _replay2.playermodel_cache_id = localplayer.playermodel_view_slot;
+ _replay2.board_cache_id = localplayer.board_view_slot;
+ addon_cache_watch( k_addon_type_player, _replay2.playermodel_cache_id );
+ addon_cache_watch( k_addon_type_board, _replay2.board_cache_id );
+ }
}
void replay2_close_player(void)
{
- addon_cache_unwatch( k_addon_type_player, _replay_player.playermodel_cache_id );
- addon_cache_unwatch( k_addon_type_board, _replay_player.board_cache_id );
- _replay_player.playermodel_cache_id = 0;
- _replay_player.board_cache_id = 0;
+ addon_cache_unwatch( k_addon_type_player, _replay2.playermodel_cache_id );
+ addon_cache_unwatch( k_addon_type_board, _replay2.board_cache_id );
+ _replay2.playermodel_cache_id = 0;
+ _replay2.board_cache_id = 0;
+ _remote_replay.state = k_remote_replay_state_none;
+ localplayer.immobile = 0;
}
/* remote replay downloader
THREAD_0;
bool is_from_network = userdata;
- replay2 *replay = &_remote_replay.replay;
+
+ if( (_remote_replay.state != k_remote_replay_state_downloading) &&
+ (_remote_replay.state != k_remote_replay_state_getinfo) )
+ {
+ vg_warn( "Ignoring chunk download callback: State is not downloading\n" );
+ return;
+ }
struct remote_replay_chunk *chunk = &_remote_replay.chunks[ _remote_replay.chunks_downloaded ];
if( status == k_request_status_ok )
if( playermodel_str )
{
- addon_cache_unwatch( k_addon_type_player, _replay_player.playermodel_cache_id );
- _replay_player.playermodel_cache_id = addon_cache_create_viewer_from_uid( k_addon_type_player, playermodel_str );
+ addon_cache_unwatch( k_addon_type_player, _replay2.playermodel_cache_id );
+ _replay2.playermodel_cache_id = addon_cache_create_viewer_from_uid( k_addon_type_player, playermodel_str );
}
if( board_str )
{
- addon_cache_unwatch( k_addon_type_board, _replay_player.board_cache_id );
- _replay_player.board_cache_id = addon_cache_create_viewer_from_uid( k_addon_type_board, board_str );
+ addon_cache_unwatch( k_addon_type_board, _replay2.board_cache_id );
+ _replay2.board_cache_id = addon_cache_create_viewer_from_uid( k_addon_type_board, board_str );
}
}
}
vg_info( "Processing %u bytes of network frames\n", data_size );
+ vg_queue *buffer = &_remote_replay.buffer;
u32 offset = 0;
while(1)
}
_remote_replay.min_frame_t = playerframe->timestamp;
- replay2_frame *dst_frame = vg_queue_alloc( &replay->buffer, sizeof(replay2_frame) + snm->msg_size, NULL );
+ replay2_frame *dst_frame = vg_queue_alloc( buffer, sizeof(replay2_frame) + snm->msg_size, NULL );
if( !dst_frame )
{
vg_error( "Out of mem adding frame!\n" );
goto E0;
}
- dst_frame->net_frame_size = snm->msg_size;
+ dst_frame->net.frame_size = snm->msg_size;
dst_frame->time = playerframe->timestamp;
- memcpy( &dst_frame->net_frame, playerframe, snm->msg_size );
+ memcpy( &dst_frame->net.frame, playerframe, snm->msg_size );
}
S0: offset += sizeof(serialized_netmsg) + snm->msg_size;
if( _remote_replay.chunks_downloaded == _remote_replay.total_chunks )
{
_remote_replay.state = k_remote_replay_state_ready;
- vg_success( "Winner! (%u total frames)\n", replay->buffer.allocation_count );
+ vg_success( "Replay got! (%u total frames)\n", buffer->allocation_count );
- replay2_frame *frame_start = vg_queue_data( &replay->buffer, replay->buffer.tail_offset ),
- *frame_end = vg_queue_data( &replay->buffer, replay->buffer.head_offset );
+ replay2_frame *frame_start = vg_queue_data( buffer, buffer->tail_offset ),
+ *frame_end = vg_queue_data( buffer, buffer->head_offset );
- if( 1 /* remote replay specific */ )
+ if( 1 )
{
- _replay2_open_player( replay, 0 );
+ _replay2_open_player( k_replay_type_network, 0 );
f64 highlight_start = (frame_end->time - _remote_replay.start_offset),
highlight_end = (frame_end->time - _remote_replay.end_offset),
if( end > frame_end->time )
end = frame_end->time;
- _replay_player.start_t = start;
- _replay_player.end_t = end;
- _replay_player.highlight_start = highlight_start - start;
- _replay_player.highlight_length = highlight_end - highlight_start;
- _replay_player.highlight = 1;
+ _replay2.start_t = start;
+ _replay2.end_t = end;
+ _replay2.highlight_start = highlight_start - start;
+ _replay2.highlight_length = highlight_end - highlight_start;
+ _replay2.highlight = 1;
_replay2_seek( start, 0 );
}
else
{
+ /* for generic local replay / rewind */
+#if 0
_replay2_open_player( replay, 1 );
- _replay_player.start_t = frame_start->time;
- _replay_player.end_t = frame_end->time;
+ _replay2.start_t = frame_start->time;
+ _replay2.end_t = frame_end->time;
_replay2_seek( frame_end->time, 0 );
+#endif
}
}
else
}
}
+void _replay2_get_camera( vg_camera *cam )
+{
+ if( _replay2.animation_dirty )
+ vg_camera_copy( &localplayer.cam, cam );
+ else
+ {
+ if( _replay2.use_freecam )
+ vg_camera_copy( &_replay2.replay_freecam, cam );
+ else
+ vg_camera_copy( &_replay2.playback_cam, cam );
+ }
+}
+
void _replay2_pre_update(void)
{
_remote_replay_pre_update();
if( skaterift.activity != k_skaterift_replay )
return;
- if( _replay_player.animation_dirty )
+ if( button_down( k_srbind_mback ) )
{
- _replay_player.animation_dirty = 0;
+ if( _replay2.hide_ui )
+ _replay2.hide_ui = 0;
+ else
+ {
+ replay2_close_player();
+ skaterift.activity = k_skaterift_default;
+ }
+
+ srinput.state = k_input_state_resume;
+ }
+
+ vg_queue *buffer = _replay2_player_buffer();
+ if( buffer->allocation_count < 2 )
+ return;
+
+ if( button_down( k_srbind_replay_play ) )
+ _replay2.replay_control ^= k_replay_control_play;
- replay2 *replay = _replay_player.replay;
- replay2_frame *current_frame = vg_queue_data( &replay->buffer, _replay_player.cursor_frame_offset ),
- *next_frame = NULL;
+ if( button_down( k_srbind_replay_freecam ) )
+ {
+ if( !_replay2.use_freecam )
+ _replay2_get_camera( &_replay2.replay_freecam );
+
+ _replay2.use_freecam ^= 0x1;
+ }
- u32 next_frame_offset;
- if( vg_queue_next( &replay->buffer, _replay_player.cursor_frame_offset, &next_frame_offset ) )
+ if( button_down( k_srbind_replay_hide_ui ) )
+ _replay2.hide_ui = 1;
+
+ f32 target_speed = axis_state( k_sraxis_replay_h ) * 5.0;
+ if( fabsf(target_speed) > 0.01f )
+ _replay2.replay_control = k_replay_control_scrub;
+ if( _replay2.replay_control == k_replay_control_play )
+ target_speed = 1.0;
+ vg_slewf( &_replay2.track_velocity, target_speed, 18.0f*vg.time_frame_delta );
+
+ if( fabsf( _replay2.track_velocity ) > 0.0001f )
+ {
+ f64 target = _replay2.cursor;
+ target += _replay2.track_velocity * vg.time_frame_delta;
+ bool stop = 0;
+ if( target > _replay2.end_t )
{
- next_frame = vg_queue_data( &replay->buffer, next_frame_offset );
+ target = _replay2.end_t;
+ stop = 1;
+ }
+ if( target < _replay2.start_t )
+ {
+ target = _replay2.start_t;
+ stop = 1;
+ }
+ if( stop )
+ {
+ _replay2.track_velocity = 0.0;
+ _replay2.replay_control = k_replay_control_scrub;
}
- /* decode frames */
- struct interp_frame interp_frame0, interp_frame1;
- u32 s0 = current_frame->net_frame_size - sizeof(netmsg_playerframe);
- decode_playerframe( ¤t_frame->net_frame, s0, &interp_frame0 );
+ _replay2_seek( target, 1 );
+ }
- m4x3f *final_mtx = _replay_player.final_mtx;
- v3f *glider_mtx = _replay_player.glider_mtx;
- struct player_board_pose *board_pose = &_replay_player.board_pose;
- struct player_board *board = addon_cache_item_data( k_addon_type_board, _replay_player.board_cache_id, 1 );
- struct player_effects_data *effects = &_replay_player.effect_data;
- bool *glider_flag = &_replay_player.render_glider;
- f64 frame_time = _replay_player.cursor;
+ if( _replay2.use_freecam )
+ freecam_preupdate();
- if( next_frame )
+ if( _replay2.animation_dirty )
+ {
+ _replay2.animation_dirty = 0;
+
+ m4x3f *final_mtx = _replay2.final_mtx;
+ v3f *glider_mtx = _replay2.glider_mtx;
+ struct player_board_pose *board_pose = &_replay2.board_pose;
+ struct player_board *board = addon_cache_item_data( k_addon_type_board, _replay2.board_cache_id, 1 );
+ struct player_effects_data *effects = &_replay2.effect_data;
+ bool *glider_flag = &_replay2.render_glider;
+ f64 frame_time = _replay2.cursor;
+
+ if( !_replay2.cursor_decoded )
+ _replay2_decode();
+
+ if( _replay2.type == k_replay_type_network )
{
- u32 s1 = next_frame->net_frame_size - sizeof(netmsg_playerframe);
- decode_playerframe( &next_frame->net_frame, s1, &interp_frame1 );
- pose_remote_player( frame_time, &interp_frame0, &interp_frame1, board, final_mtx, glider_mtx,
- board_pose, effects, glider_flag );
+ struct interp_frame *i0 = &_remote_replay.interp0,
+ *i1 = &_remote_replay.interp1;
+ struct player_cam_controller cc = { .camera_mode = k_cam_thirdperson, .camera_type_blend = 0 };
+ compute_cam_controller_offsets( i0->subsystem, &cc );
+ pose_remote_player( frame_time, i0, i1, board, final_mtx, glider_mtx, board_pose, effects, glider_flag );
+
+ f32 t = (frame_time - i0->timestamp) / (i1->timestamp - i0->timestamp);
+ t = vg_clampf( t, 0.0f, 1.0f );
+ u16 bounds = i0->boundary_hash^i1->boundary_hash;
+ if( bounds & NETMSG_BOUNDARY_BIT )
+ t = 1.0f;
+ if( bounds & NETMSG_GATE_BOUNDARY_BIT )
+ t = 1.0f;
+
+ v2f angles;
+ v2_lerp( _remote_replay.cam0, _remote_replay.cam1, t, angles );
+
+ /* position */
+ v3f fpv_pos, fpv_offset;
+ m4x3_mulv( _replay2.final_mtx[ localplayer.id_head-1 ], cc.fpv_viewpoint, fpv_pos );
+ m3x3_mulv( _replay2.final_mtx[0], cc.fpv_offset, fpv_offset ); // NOTE: [0] could be wrong (was rb.to_world)
+ v3_add( fpv_offset, fpv_pos, fpv_pos );
+
+ /* origin */
+ v3f tpv_origin, tpv_offset, tpv_pos;
+ m4x3_mulv( _replay2.final_mtx[0], cc.tpv_offset, tpv_origin );
+
+ /* offset */
+ v3f camera_follow_dir =
+ { -sinf( angles[0] ) * cosf( angles[1] ),
+ sinf( angles[1] ),
+ cosf( angles[0] ) * cosf( angles[1] ) };
+ v3_muls( camera_follow_dir, 1.8f, tpv_offset );
+ //v3_muladds( tpv_offset, cc.cam_velocity_smooth, -0.025f, tpv_offset );
+
+ v3_add( tpv_origin, tpv_offset, tpv_pos );
+ v3_lerp( tpv_pos, fpv_pos, cc.camera_type_blend, _replay2.playback_cam.pos );
+ v2_copy( angles, _replay2.playback_cam.angles );
+ f32 fov_skate = vg_lerpf( 97.0f, 135.0f, k_fov ),
+ fov_walk = vg_lerpf( 90.0f, 110.0f, k_fov );
+ _replay2.playback_cam.fov = vg_lerpf( fov_walk, fov_skate, cc.camera_type_blend );
}
else
{
- pose_remote_player( frame_time, &interp_frame0, NULL, board, final_mtx, glider_mtx, board_pose,
- effects, glider_flag );
+ replay2_frame *current_frame = vg_queue_data( buffer, _replay2.cursor_frame_offset ),
+ *next_frame = NULL;
+ void *animator0 = (void *)current_frame->local.data,
+ *animator1 = NULL;
+ struct replay_glider_data *glider0 = (void *)current_frame->local.data + current_frame->local.animator_size,
+ *glider1 = NULL;
+ struct player_subsystem_interface *sys0 = player_subsystems[current_frame->local.subsystem],
+ *sys1 = NULL;
+
+ u32 next_offset;
+ if( vg_queue_next( buffer, _replay2.cursor_frame_offset, &next_offset ) )
+ {
+ next_frame = vg_queue_data( buffer, next_offset );
+ animator1 = (void *)next_frame->local.data;
+ glider1 = (void *)next_frame->local.data + next_frame->local.animator_size;
+ sys1 = player_subsystems[next_frame->local.subsystem];
+ }
+
+ player_pose pose;
+
+ f32 t = 0.0f;
+ if( next_frame )
+ {
+ t = (f32)((_replay2.cursor - current_frame->time) / (next_frame->time - current_frame->time));
+
+ u16 bounds = current_frame->local.boundary^next_frame->local.boundary;
+ if( bounds & NETMSG_BOUNDARY_BIT )
+ t = 1.0f;
+ if( bounds & NETMSG_GATE_BOUNDARY_BIT )
+ t = 1.0f;
+
+ player_pose pose0, pose1;
+ sys0->pose( animator0, &pose0 );
+ sys1->pose( animator1, &pose1 );
+ lerp_player_pose( &pose0, &pose1, t, &pose );
+ vg_camera_lerp( ¤t_frame->local.camera, &next_frame->local.camera, t, &_replay2.playback_cam );
+ }
+ else
+ {
+ sys0->pose( animator0, &pose );
+ vg_camera_copy( ¤t_frame->local.camera, &_replay2.playback_cam );
+ }
+
+ player__observe_system( current_frame->local.subsystem );
+ if( sys0->sfx_comp )
+ sys0->sfx_comp( animator0 );
+
+#if 0
+ if( g0 )
+ {
+ if( g0->glider_orphan )
+ {
+ if( g1 )
+ {
+ v3_lerp( g0->co, g1->co, t, player_glide.rb.co );
+ q_nlerp( g0->q, g1->q, t, player_glide.rb.q );
+ }
+ else
+ {
+ v3_copy( g0->co, player_glide.rb.co );
+ v4_copy( g0->q, player_glide.rb.q );
+ }
+
+ rb_update_matrices( &player_glide.rb );
+ }
+
+ if( g1 )
+ player_glide.t = vg_lerpf( g0->t, g1->t, t );
+ else
+ player_glide.t = g0->t;
+
+ localplayer.have_glider = g0->have_glider;
+ localplayer.glider_orphan = g0->glider_orphan;
+ }
+ else /* no glider data in g1, or edge case we dont care about */
+ {
+ localplayer.have_glider = 0;
+ localplayer.glider_orphan = 0;
+ player_glide.t = 0.0f;
+ }
+#endif
+
+ apply_full_skeleton_pose( &localplayer.skeleton, &pose, final_mtx );
+ }
+ }
+
+ if( _replay2.replay_control == k_replay_control_play )
+ {
+ u32 j=0;
+ for( u32 i=0; i<_replay2.sfx_queue_length; i ++ )
+ {
+ struct net_sfx *sfx = &_replay2.sfx_queue[i];
+ f64 t = (_replay2.sfx_basetime - NETWORK_FRAMERATE) + (sfx->subframe*NETWORK_FRAMERATE);
+ if( _replay2.cursor >= t )
+ net_sfx_play( sfx );
+ else
+ _replay2.sfx_queue[ j ++ ] = _replay2.sfx_queue[i];
}
+ _replay2.sfx_queue_length = j;
}
}
if( skaterift.activity != k_skaterift_replay )
return;
- struct player_model *model = addon_cache_item_data( k_addon_type_player, _replay_player.playermodel_cache_id, 1 );
+ struct player_model *model = addon_cache_item_data( k_addon_type_player, _replay2.playermodel_cache_id, 1 );
struct skeleton *sk = &localplayer.skeleton;
- render_playermodel( cam, world, 0, model, sk, _replay_player.final_mtx );
+ render_playermodel( cam, world, 0, model, sk, _replay2.final_mtx );
- struct player_board *board = addon_cache_item_data( k_addon_type_board, _replay_player.board_cache_id, 1 );
- render_board( cam, world, board, _replay_player.final_mtx[localplayer.id_board],
- &_replay_player.board_pose, k_board_shader_player );
+ struct player_board *board = addon_cache_item_data( k_addon_type_board, _replay2.board_cache_id, 1 );
+ render_board( cam, world, board, _replay2.final_mtx[localplayer.id_board],
+ &_replay2.board_pose, k_board_shader_player );
#if 0
if( !gliders )
#endif
}
+void _replay2_decode(void)
+{
+ vg_queue *buffer = _replay2_player_buffer();
+ replay2_frame *current_frame = vg_queue_data( buffer, _replay2.cursor_frame_offset ),
+ *next_frame = NULL;
+ u32 next_offset;
+ if( vg_queue_next( buffer, _replay2.cursor_frame_offset, &next_offset ) )
+ next_frame = vg_queue_data( buffer, next_offset );
+ else
+ _replay2.sfx_queue_length = 0; /* sfx's are expresed relative to the next frame, if no next, no sound. */
+
+ if( _replay2.type == k_replay_type_network )
+ {
+ u32 s0 = current_frame->net.frame_size - sizeof(netmsg_playerframe);
+ decode_playerframe( ¤t_frame->net.frame, s0, &_remote_replay.interp0, _remote_replay.cam0, NULL, NULL );
+
+ if( next_frame )
+ {
+ u32 len = VG_ARRAY_LEN( _replay2.sfx_queue );
+ replay2_frame *next_frame = vg_queue_data( buffer, next_offset );
+ u32 s1 = next_frame->net.frame_size - sizeof(netmsg_playerframe);
+ decode_playerframe( &next_frame->net.frame, s1, &_remote_replay.interp1, _remote_replay.cam1,
+ _replay2.sfx_queue, &len );
+ _replay2.sfx_queue_length = len;
+ }
+ else
+ {
+ memcpy( &_remote_replay.interp1, &_remote_replay.interp0, sizeof(struct interp_frame) );
+ _remote_replay.interp1.timestamp += 1.0;
+ }
+
+ _replay2.sfx_basetime = _remote_replay.interp1.timestamp;
+ }
+ else
+ {
+ if( next_frame )
+ {
+ u32 sfx_offset = next_frame->local.animator_size + next_frame->local.glider_size;
+ struct net_sfx *sfx_src = (void *)next_frame->local.data + sfx_offset;
+
+ _replay2.sfx_queue_length = 0;
+ u32 max_sfx = VG_ARRAY_LEN( _replay2.sfx_queue );
+ for( u32 i=0; (i<next_frame->local.sfx_count) && (_replay2.sfx_queue_length<max_sfx); i ++ )
+ {
+ struct net_sfx *dst = &_replay2.sfx_queue[ _replay2.sfx_queue_length ++ ];
+ memcpy( dst, &sfx_src[i], sizeof(struct net_sfx) );
+ }
+
+ _replay2.sfx_basetime = next_frame->time;
+ }
+ else
+ _replay2.sfx_basetime = current_frame->time + 1.0;
+ }
+
+ _replay2.cursor_decoded = 1;
+}
+
void _replay2_seek( f64 t, bool play_sounds )
{
- replay2 *replay = _replay_player.replay;
- VG_ASSERT( replay );
+ vg_queue *buffer = _replay2_player_buffer();
- replay2_frame *frame_start = vg_queue_data( &replay->buffer, replay->buffer.tail_offset ),
- *frame_end = vg_queue_data( &replay->buffer, replay->buffer.head_offset );
+ replay2_frame *frame_start = vg_queue_data( buffer, buffer->tail_offset ),
+ *frame_end = vg_queue_data( buffer, buffer->head_offset );
if( t < frame_start->time ) t = frame_start->time;
if( t > frame_end->time ) t = frame_end->time;
- f64 dir = t - _replay_player.cursor;
+ f64 dir = t - _replay2.cursor;
if( dir == 0.0 )
return;
dir = vg_signf( dir );
- u32 current_offset = _replay_player.cursor_frame_offset;
- replay2_frame *current_frame = vg_queue_data( &replay->buffer, current_offset );
+ replay2_frame *current_frame = vg_queue_data( buffer, _replay2.cursor_frame_offset );
for( u32 i=0; i<4096; i ++ )
{
if( dir < 0.0 )
bool next = 0;
u32 next_offset;
- if( dir > 0.0 ) next = vg_queue_next( &replay->buffer, current_offset, &next_offset );
- else next = vg_queue_previous( &replay->buffer, current_offset, &next_offset );
+ if( dir > 0.0 ) next = vg_queue_next( buffer, _replay2.cursor_frame_offset, &next_offset );
+ else next = vg_queue_previous( buffer, _replay2.cursor_frame_offset, &next_offset );
if( !next )
break;
- replay2_frame *next_frame = vg_queue_data( &replay->buffer, next_offset );
+ replay2_frame *next_frame = vg_queue_data( buffer, next_offset );
if( dir > 0.0 )
{
if( next_frame->time > t )
}
}
- current_offset = next_offset;
+ _replay2.cursor_frame_offset = next_offset;
+ _replay2.cursor_decoded = 0;
current_frame = next_frame;
if( play_sounds )
{
- //replay_emit_frame_sounds( next );
+ for( u32 i=0; i<_replay2.sfx_queue_length; i ++ )
+ net_sfx_play( &_replay2.sfx_queue[i] );
+ _replay2.sfx_queue_length = 0;
+ _replay2_decode();
}
}
- _replay_player.cursor_frame_offset = current_offset;
- _replay_player.cursor = t;
- _replay_player.animation_dirty = 1;
+ _replay2.cursor = t;
+ _replay2.animation_dirty = 1;
}
void _replay2_imgui( ui_context *ctx )
if( skaterift.activity != k_skaterift_replay )
return;
- if( _replay_player.hide_ui )
+ if( _replay2.hide_ui )
return;
if( vg_input.display_input_method != k_input_method_controller )
ui_capture_mouse( ctx, 1 );
}
- replay2 *replay = _replay_player.replay;
- VG_ASSERT( replay );
+ if( _replay2.type == k_replay_type_network )
+ {
+ if( _remote_replay.state < k_remote_replay_state_ready )
+ {
+ ui_rect box = { vg.window_x/2 - 200, vg.window_y/2-80, 400, 160 };
+ ui_fill( ctx, box, ui_opacity( GUI_COL_DARK, 0.36f ) );
+ ui_rect titlebox, boxbox, boxboxline;
+ ui_split_ratio( box, k_ui_axis_h, 0.5f, 8, titlebox, boxbox );
+
+ ctx->font = &vgf_default_title;
+ ui_text( ctx, titlebox, "Downloading", 1, k_ui_align_middle_center, 0 );
+ ctx->font = &vgf_default_large;
+
+ rect_copy( boxbox, boxboxline );
+ boxboxline[2] -= 16;
+ boxboxline[3] = 32;
+ ui_rect_center( boxbox, boxboxline );
+
+ f32 blockw = boxboxline[2] / (f32)_remote_replay.total_chunks;
+ for( u32 i=0; i<_remote_replay.total_chunks; i ++ )
+ {
+ ui_rect chunkbox = { boxboxline[0]+4 + blockw*(f32)i, boxboxline[1], blockw-8, boxboxline[3] };
+ struct remote_replay_chunk *chunk = &_remote_replay.chunks[i];
- f64 start = _replay_player.start_t,
- end = _replay_player.end_t;
+ if( chunk->state == k_chunk_state_broken )
+ ui_fill( ctx, chunkbox, ui_colour( ctx, k_ui_red ) );
+ else
+ {
+ if( i < _remote_replay.chunks_downloaded )
+ ui_fill( ctx, chunkbox, ui_colour( ctx, k_ui_fg ) );
+ else
+ ui_outline( ctx, chunkbox, -2, ui_colour( ctx, k_ui_fg+2 ), 0 );
+ }
+ }
+
+ ui_rect exit_button = { box[0] + box[2] - 48, box[1], 48, 48 };
+ if( ui_button_text( ctx, exit_button, "X", 1 ) == k_ui_button_click )
+ {
+ skaterift.activity = k_skaterift_default;
+ replay2_close_player();
+ }
+
+ if( _remote_replay.state == k_remote_replay_state_failed )
+ {
+ ui_text( ctx, box, "Failed", 1, k_ui_align_middle_center, 0 );
+ }
+ else /* assume downloading */
+ {
+ ui_text( ctx, box, "Downloading", 1, k_ui_align_middle_center, 0 );
+ }
+
+ return;
+ }
+ }
+
+ vg_queue *buffer = _replay2_player_buffer();
+ if( buffer->allocation_count < 2 )
+ {
+ ctx->font = &vgf_default_large;
+ ui_rect box = { vg.window_x/2 - 200, 40, 400, ctx->font->sy };
+ ui_text( ctx, box, KRED "\x06\x02--- Corrupt replay ---", 1, k_ui_align_center, 0 );
+ // TODO
+ return;
+ }
+
+ ctx->font = &vgf_default_small;
+ f64 start = _replay2.start_t,
+ end = _replay2.end_t;
f64 len = end - start,
- cur = (_replay_player.cursor - start) / len;
+ cur = (_replay2.cursor - start) / len;
/* mainbar */
ui_rect timeline = { 8, vg.window_y-(32+8), vg.window_x-16, 32 };
ui_rect start_box;
ui_split( timeline, k_ui_axis_v, 32, 8, start_box, timeline );
- const char *start_text = (_replay_player.replay_control == k_replay_control_play)? "||": ">";
+ const char *start_text = (_replay2.replay_control == k_replay_control_play)? "||": ">";
if( menu_button_rect( ctx, start_box, 0, 1, start_text ) )
{
- _replay_player.replay_control ^= k_replay_control_play;
+ _replay2.replay_control ^= k_replay_control_play;
}
ui_fill( ctx, timeline, ui_colour( ctx, k_ui_bg ) );
/* for remote replays */
- if( _replay_player.highlight )
+ if( _replay2.highlight )
{
- f64 x = _replay_player.highlight_start / len,
- w = _replay_player.highlight_length / len;
+ f64 x = _replay2.highlight_start / len,
+ w = _replay2.highlight_length / len;
ui_rect highlight = { timeline[0] + x*(f64)timeline[2], timeline[1] + timeline[3] -1, (f64)timeline[2]*w, 2 };
ui_fill( ctx, highlight, ui_colour( ctx, k_ui_green ) );
}
/* cursor frame block */
- replay2_frame *frame_cursor = vg_queue_data( &replay->buffer, _replay_player.cursor_frame_offset );
+ replay2_frame *frame_cursor = vg_queue_data( buffer, _replay2.cursor_frame_offset );
u32 next_frame_offset;
- if( vg_queue_next( &replay->buffer, _replay_player.cursor_frame_offset, &next_frame_offset ) )
+ if( vg_queue_next( buffer, _replay2.cursor_frame_offset, &next_frame_offset ) )
{
- replay2_frame *next_frame = vg_queue_data( &replay->buffer, next_frame_offset );
+ replay2_frame *next_frame = vg_queue_data( buffer, next_frame_offset );
f64 l = (next_frame->time - frame_cursor->time )/len,
s = (frame_cursor->time - start) / len;
ui_rect box = { timeline[0] + s*(f64)timeline[2], timeline[1],
}
#endif
- char buffer[ 128 ];
- snprintf( buffer, 128, "-%.2fs", (end-_replay_player.cursor) );
- ui_text( ctx, timeline, buffer, 1, k_ui_align_middle_left, 0 );
+ char text[ 128 ];
+ snprintf( text, 128, "-%.2fs", (end-_replay2.cursor) );
+ ui_text( ctx, timeline, text, 1, k_ui_align_middle_left, 0 );
ui_text( ctx, timeline, "0s", 1, k_ui_align_middle_right, 0 );
/* helpers */
vg_strnull( &str, buf, sizeof(buf) );
vg_input_string( &str, input_button_list[k_srbind_replay_play], 1 );
- vg_strcat( &str, (_replay_player.replay_control == k_replay_control_play)? "\x07 Pause": "\x07 Play" );
+ vg_strcat( &str, (_replay2.replay_control == k_replay_control_play)? "\x07 Pause": "\x07 Play" );
ui_text( ctx, helper_list_l, buf, 1, k_ui_align_left, 0 );
helper_list_l[1] -= helper_list_l[3]+2;
ui_text( ctx, helper_list_r, buf, 1, k_ui_align_right, 0 );
helper_list_l[1] -= helper_list_r[3]+2;
- if( _replay_player.use_freecam )
+ if( _replay2.use_freecam )
{
ui_rect box = { vg.window_x/2 - 200, 40, 400, ctx->font->sy };
ui_text( ctx, box, KYEL "\x06\x02--- Freecam Enabled ---", 1, k_ui_align_center, 0 );
if( ui_clicking( ctx, UI_MOUSE_LEFT ) && start_in_timeline )
{
f64 mouse_t = start + ((f64)(ctx->mouse[0]-timeline[0]) / (f64)timeline[2])*len;
+ if( mouse_t < _replay2.start_t ) mouse_t = _replay2.start_t;
+ if( mouse_t > _replay2.end_t ) mouse_t = _replay2.end_t;
_replay2_seek( mouse_t, 1 );
}
}
}
+
+/* local replay
+ * ----------------------------------------------------------------------------------------------------------------- */
+
+void _replay2_record_local_frame(void)
+{
+ vg_queue *buffer = &_replay2.buffer;
+
+ f64 delta = 9999999.9;
+ if( buffer->allocation_count )
+ {
+ replay2_frame *frame = vg_queue_data( buffer, buffer->head_offset );
+ delta = vg.time - frame->time;
+ }
+
+ if( delta < 1.0/30.0 )
+ return;
+
+ bool save_glider = 0;
+ if( localplayer.have_glider || localplayer.glider_orphan || localplayer.subsystem == k_player_subsystem_glide )
+ save_glider = 1;
+
+ u32 animator_size = vg_align8( player_subsystems[localplayer.subsystem]->animator_size ),
+ glider_size = save_glider? vg_align8( sizeof(struct replay_glider_data) ): 0,
+ sfx_size = vg_align8( localplayer.local_sfx_buffer_count * sizeof(struct net_sfx) ),
+ total_size = sizeof(replay2_frame) + animator_size + glider_size + sfx_size;
+
+ replay2_frame *dest_frame = vg_queue_alloc( buffer, total_size, NULL );
+ if( !dest_frame )
+ {
+ while( buffer->allocation_count )
+ {
+ vg_queue_pop( buffer );
+ dest_frame = vg_queue_alloc( buffer, total_size, NULL );
+ if( dest_frame )
+ break;
+ }
+
+ if( !dest_frame )
+ {
+ vg_error( "Replay frame tried to allocate which was (way!) too big (%u bytes)\n", total_size );
+ return;
+ }
+ }
+
+ dest_frame->time = vg.time;
+ dest_frame->local.animator_size = animator_size;
+ dest_frame->local.glider_size = glider_size;
+ dest_frame->local.sfx_count = localplayer.local_sfx_buffer_count;
+ dest_frame->local.subsystem = localplayer.subsystem;
+ dest_frame->local.boundary = localplayer.boundary_hash;
+
+ /* camera */
+ v3_copy( localplayer.cam.pos, dest_frame->local.camera.pos );
+ dest_frame->local.camera.fov = localplayer.cam.fov;
+ if( localplayer.gate_waiting )
+ {
+ m4x3_mulv( localplayer.gate_waiting->transport, dest_frame->local.camera.pos, dest_frame->local.camera.pos );
+
+ v3f v0;
+ v3_angles_vector( localplayer.cam.angles, v0 );
+ m3x3_mulv( localplayer.gate_waiting->transport, v0, v0 );
+ v3_angles( v0, dest_frame->local.camera.angles );
+ }
+ else
+ v3_copy( localplayer.cam.angles, dest_frame->local.camera.angles );
+
+ void *data_animator = (void *)dest_frame->local.data,
+ *data_glider = (void *)dest_frame->local.data + animator_size,
+ *data_sfx = (void *)dest_frame->local.data + animator_size + glider_size;
+
+ /* animator */
+ memcpy( data_animator, player_subsystems[localplayer.subsystem]->animator_data, animator_size );
+
+ /* glider */
+ if( save_glider )
+ {
+ struct replay_glider_data *inf = data_glider;
+ inf->have_glider = localplayer.have_glider;
+ inf->glider_orphan = localplayer.glider_orphan;
+ inf->t = player_glide.t;
+ v3_copy( player_glide.rb.co, inf->co );
+ v4_copy( player_glide.rb.q, inf->q );
+ }
+
+ /* sound effects */
+ memcpy( data_sfx, localplayer.local_sfx_buffer, sizeof(struct net_sfx)*localplayer.local_sfx_buffer_count );
+ localplayer.local_sfx_buffer_count = 0;
+}
#include "vg/vg_mem_queue.h"
#include "player_effects.h"
-typedef struct replay2 replay2;
-struct replay2
+typedef struct replay2_frame replay2_frame;
+struct replay2_frame
{
- enum replay_type
+ f64 time; // duplicated from net_frame
+
+ union
{
- k_replay_type_local,
- k_replay_type_network
- }
- type;
+ struct
+ {
+ u32 frame_size;
+ netmsg_playerframe frame;
+ }
+ net;
- vg_queue buffer;
+ struct
+ {
+ vg_camera camera;
+ u16 animator_size, glider_size, sfx_count, subsystem,
+ boundary, unused0, unused1, unused2;
+ u8 data[];
+ }
+ local;
+ };
};
-typedef struct replay2_frame replay2_frame;
-struct replay2_frame
+struct replay_glider_data
{
- f64 time; // duplicated from net_frame
- u32 net_frame_size;
- netmsg_playerframe net_frame;
+ bool have_glider, glider_orphan;
+ f32 t;
+ v3f co;
+ v4f q;
};
struct _remote_replay
k_remote_replay_state_waitnext,
k_remote_replay_state_downloading,
-
+ k_remote_replay_state_failed,
k_remote_replay_state_ready,
- k_remote_replay_state_failed
}
state;
i64 last_second;
f64 end_offset, start_offset; /* from the download */
- replay2 replay;
+ v2f cam0, cam1;
+ struct interp_frame interp0, interp1;
+ vg_queue buffer;
}
extern _remote_replay;
-struct _replay_player
+struct _replay2
{
- replay2 *replay;
+ enum replay_type
+ {
+ k_replay_type_local,
+ k_replay_type_network
+ }
+ type;
+
+ vg_queue buffer;
/* TODO: Modifiers / keyframes lane */
u32 cursor_frame_offset;
f64 cursor;
- enum replay_control replay_control;
+ enum replay_control {
+ k_replay_control_scrub = 0x00,
+ k_replay_control_play = 0x01,
+ k_replay_control_resume= 0x02
+ }
+ replay_control;
f32 track_velocity;
- vg_camera replay_freecam;
+ bool cursor_decoded;
+
+ struct net_sfx sfx_queue[ 8 ];
+ u32 sfx_queue_length;
+ f64 sfx_basetime;
+
+ vg_camera replay_freecam, playback_cam;
bool use_freecam;
bool hide_ui;
v3f freecam_v, freecam_w;
m4x3f *final_mtx, glider_mtx;
struct player_board_pose board_pose;
}
-extern _replay_player;
+extern _replay2;
void _replay2_init(void);
void _replay2_pre_update(void);
void _replay2_imgui( ui_context *ctx );
-void _replay2_open_player( replay2 *replay, bool end );
+void _replay2_open_player( enum replay_type type, bool end );
void _replay2_render_player( world_instance *world, vg_camera *cam );
void _replay2_seek( f64 t, bool play_sounds );
+void _replay2_get_camera( vg_camera *cam );
+void _replay2_decode(void);
+void _replay2_record_local_frame(void);
vg_loader_step( skateshop_init, NULL );
vg_loader_step( world_map_init, NULL );
vg_loader_step( ent_tornado_init, NULL );
- vg_loader_step( skaterift_replay_init, NULL );
vg_loader_step( skaterift_load_player_content, NULL );
vg_loader_step( _replay2_init, NULL );
player__pre_update();
}
- skaterift_replay_pre_update();
_replay2_pre_update();
remote_sfx_pre_update();
* ------------------------------------------------------------------ */
if( skaterift.activity == k_skaterift_replay )
{
- if( player_replay.use_freecam )
- {
- freecam_preupdate();
- v3_copy( player_replay.replay_freecam.pos, g_render.cam.pos );
- v3_copy( player_replay.replay_freecam.angles, g_render.cam.angles );
- g_render.cam.fov = player_replay.replay_freecam.fov;
- }
- else
- {
- skaterift_get_replay_cam( &g_render.cam );
- }
+ _replay2_get_camera( &g_render.cam );
}
g_render.cam.nearz = 0.1f;
}
else if( skaterift.activity == k_skaterift_replay )
{
- player__animate_from_replay( &player_replay.local );
+ //FIXME
+ //player__animate_from_replay( &player_replay.local );
}
else
{
player__animate();
- skaterift_record_frame( &player_replay.local, localplayer.deferred_frame_record );
- localplayer.deferred_frame_record = 0;
+ _replay2_record_local_frame();
}
animate_remote_players();
#include "player_ragdoll.c"
#include "player_remote.c"
#include "player_render.c"
-#include "player_replay.c"
#include "player_skate.c"
#include "player_walk.c"
#include "render.c"
int main( int argc, const char *argv[] )
{
vg_init( argc, argv, "Voyager Game Engine" );
+ network_set_host( "skaterift.com", NULL );
- const char *arg;
- if( vg_long_opt( "noauth", "Disable server authentication" ) )
- network_client.auth_mode = eServerModeNoAuthentication;
+ {
+ const char *arg;
+ if( vg_long_opt( "noauth", "Disable server authentication" ) )
+ network_client.auth_mode = eServerModeNoAuthentication;
- if( (arg = vg_long_opt_arg( "server", "Specify server address" )) )
- network_set_host( arg, NULL );
+ if( (arg = vg_long_opt_arg( "server", "Specify server address" )) )
+ network_set_host( arg, NULL );
- if( vg_long_opt( "demo", "Turn demo mode on" ) )
- g_client.demo_mode = 1;
+ if( vg_long_opt( "demo", "Turn demo mode on" ) )
+ g_client.demo_mode = 1;
- if( vg_long_opt( "nosteam", "Disable steam integration (offline)" ) )
- g_client.nosteam = 1;
+ if( vg_long_opt( "nosteam", "Disable steam integration (offline)" ) )
+ g_client.nosteam = 1;
- if( (arg = vg_long_opt_arg( "world", "Specify path to world to load" )) )
- skaterift.override_load_world = arg;
+ if( (arg = vg_long_opt_arg( "world", "Specify path to world to load" )) )
+ skaterift.override_load_world = arg;
+ }
- network_set_host( "skaterift.com", NULL );
vg_mem.use_libc_malloc = 0;
vg_set_mem_quota( 200*1024*1024 );
skaterift.sig_world = _vg_tower_create_signal( "World Loaded" );
THREAD_0;
_world.loader_state = k_world_loader_init;
_world.loader_instance->complete = 1;
-
- if( !_world.loader_preview_mode )
- menu_on_world_change( _world.main.addon_id );
}
struct world_load_info
_world.loader_state = k_world_loader_done;
_world.load_addon = 0;
_vg_tower_set_flag( skaterift.sig_world, 1 );
+ menu_on_world_change( _world.main.addon_id );
}
void load_world_savedata_t1( void *userdata )