X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=player_replay.c;h=f0487f4b36d99a7694d60dcddf69f46d84adbe36;hb=9eb3de757a997becb8406417a4bf613f4cb04900;hp=83b9b835544671c094d3172f0e9fb4feb4784272;hpb=b615f03b922d155f9449d2a23d3cc18eed320ed3;p=carveJwlIkooP6JGAAIwe30JlM.git diff --git a/player_replay.c b/player_replay.c index 83b9b83..f0487f4 100644 --- a/player_replay.c +++ b/player_replay.c @@ -10,19 +10,40 @@ VG_STATIC void local_replay_init( u32 bytes ){ vg_console_reg_var( "k_replay_test", &k_replay_test, k_var_dtype_i32, 0 ); } +replay_gamestate *replay_frame_gamestate( replay_frame *frame, u16 index ){ + void *baseptr = frame; + + replay_gamestate *array = (baseptr + vg_align8( sizeof(replay_frame))); + return &array[ index ]; +} + +replay_sfx *replay_frame_sfx( replay_frame *frame, u16 index ){ + void *gsarr = replay_frame_gamestate( frame, 0 ); + u32 gssize = frame->gamestate_count * sizeof(replay_gamestate); + + replay_sfx *array = (gsarr + vg_align8(gssize)); + return &array[index]; +} + +u32 _replay_frame_size( u16 gamestate_count, u16 sfx_count ){ + return vg_align8( sizeof( replay_frame ) ) + + vg_align8( gamestate_count * sizeof(replay_gamestate) ) + + vg_align8( sfx_count * sizeof(replay_sfx) ); +} + u32 replay_frame_size( replay_frame *frame ){ - /* eventually it will be a dynamic size */ - return vg_align8( sizeof( replay_frame ) ); + return _replay_frame_size( frame->gamestate_count, frame->sfx_count ); } -VG_STATIC replay_frame *replay_newframe( replay_buffer *replay ){ +VG_STATIC replay_frame *replay_newframe( replay_buffer *replay, + u16 gamestate_count, u16 sfx_count ){ replay_frame *frame = NULL; if( replay->head ){ assert( replay->head ); u32 headsize = replay_frame_size( replay->head ), nextpos = ((void *)replay->head - replay->data) + headsize, - nextsize = vg_align8( sizeof(replay_frame) ); + nextsize = _replay_frame_size( gamestate_count, sfx_count ); if( nextsize > replay->size ){ vg_error( "Keyframe too big\n" ); @@ -38,36 +59,39 @@ check_again:; if( tailpos >= nextpos ){ if( nextpos + nextsize > tailpos ){ - if( replay->cursor_frame == replay->tail ){ + /* remove links */ + if( replay->cursor_frame == replay->tail ) replay->cursor_frame = NULL; - } + if( replay->statehead == replay->tail ) + replay->statehead = NULL; + /* pop node */ replay->tail = replay->tail->r; if( replay->tail ) { replay->tail->l = NULL; goto check_again; } - else{ + else replay->head = NULL; - } } } frame = replay->data + nextpos; - if( replay->head ){ + if( replay->head ) replay->head->r = frame; - } } - else { + else frame = replay->data; - } + frame->gamestate_count = gamestate_count; + frame->sfx_count = sfx_count; frame->l = replay->head; frame->r = NULL; replay->head = frame; if( !replay->tail ) replay->tail = frame; + if( gamestate_count ) replay->statehead = frame; return frame; } @@ -94,7 +118,7 @@ VG_STATIC void replay_seek( replay_buffer *replay, f64 t ){ dir = vg_signf( dir ); u32 i=0; - for( ; i<100; i++ ){ + for( ; i<1024; i++ ){ if( dir < 0.0 ) if( t > replay->cursor_frame->time ) break; @@ -108,11 +132,27 @@ VG_STATIC void replay_seek( replay_buffer *replay, f64 t ){ if( t < next->time ) break; replay->cursor_frame = next; + replay->cursor = next->time; + + if( i == 1023 ) return; } replay->cursor = t; } +VG_STATIC replay_frame *replay_find_recent_stateframe( replay_buffer *replay ){ + replay_frame *frame = replay->cursor_frame; + + u32 i=0; + for( ; i<4096; i++ ){ + if( !frame ) return frame; + if( frame->gamestate_count ) return frame; + frame = frame->l; + } + + return NULL; +} + VG_STATIC void replay_debug_info( player_instance *player ){ player__debugtext( 2, "replay info" ); @@ -125,6 +165,13 @@ VG_STATIC void replay_debug_info( player_instance *player ){ player__debugtext( 1, "head @%u | tail @%u\n", head, tail ); + if( replay->statehead ){ + u32 state = (void *)replay->statehead - replay->data; + player__debugtext( 1, "gs @%u\n", state ); + } + else + player__debugtext( 1, "gs @NULL\n" ); + f64 start = replay->cursor, end = replay->cursor; if( replay->tail ) start = replay->tail->time; @@ -149,14 +196,42 @@ VG_STATIC void replay_imgui( player_instance *player ){ char buffer[ 128 ]; + /* mainbar */ ui_px height = 20, - cwidth = 8; + cwidth = 2; ui_rect bar = { 0, vg.window_y - height, vg.window_x, height }; ui_fill( bar, ui_colour( 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 = { s*(f64)vg.window_x, bar[1]-2, + VG_MAX(4,(ui_px)l), bar[3]+2 }; + ui_fill( box, ui_colour( k_ui_bg+4 ) ); + } + } + + /* cursor */ ui_rect cusor = { cur * (f64)vg.window_x - (cwidth/2), bar[1], cwidth, bar[3] }; - ui_fill( cusor, ui_colour( k_ui_bg+4 ) ); + ui_fill( cusor, ui_colour( k_ui_bg+7 ) ); + + /* latest state marker */ + if( replay->statehead ){ + f64 t = (replay->statehead->time - start) / len; + ui_rect tag = { t*(f64)vg.window_x, bar[1]-8, 2, bar[3]+8 }; + ui_fill( tag, ui_colour( 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 = { t*(f64)vg.window_x, bar[1]-8, 2, bar[3]+8 }; + ui_fill( tag, ui_colour( k_ui_yellow+k_ui_brighter ) ); + } cusor[1] -= height; cusor[2] = 200;