09cc136cbd477d6395aaea837b2486f815ae1da9
1 #ifndef PLAYER_REPLAY_C
2 #define PLAYER_REPLAY_C
4 #include "player_replay.h"
6 VG_STATIC
void replay_clear( replay_buffer
*replay
){
9 replay
->cursor_frame
= NULL
;
10 replay
->statehead
= NULL
;
11 replay
->cursor
= -99999.9;
14 replay_gamestate
*replay_frame_gamestate( replay_frame
*frame
, u16 index
){
15 void *baseptr
= frame
;
17 replay_gamestate
*array
= (baseptr
+ vg_align8( sizeof(replay_frame
)));
18 return &array
[ index
];
21 replay_sfx
*replay_frame_sfx( replay_frame
*frame
, u16 index
){
22 void *gsarr
= replay_frame_gamestate( frame
, 0 );
23 u32 gssize
= frame
->gamestate_count
* sizeof(replay_gamestate
);
25 replay_sfx
*array
= (gsarr
+ vg_align8(gssize
));
29 u32
_replay_frame_size( u16 gamestate_count
, u16 sfx_count
){
30 return vg_align8( sizeof( replay_frame
) ) +
31 vg_align8( gamestate_count
* sizeof(replay_gamestate
) ) +
32 vg_align8( sfx_count
* sizeof(replay_sfx
) );
35 u32
replay_frame_size( replay_frame
*frame
){
36 return _replay_frame_size( frame
->gamestate_count
, frame
->sfx_count
);
39 VG_STATIC replay_frame
*replay_newframe( replay_buffer
*replay
,
40 u16 gamestate_count
, u16 sfx_count
){
41 replay_frame
*frame
= NULL
;
43 assert( replay
->head
);
45 u32 headsize
= replay_frame_size( replay
->head
),
46 nextpos
= ((void *)replay
->head
- replay
->data
) + headsize
,
47 nextsize
= _replay_frame_size( gamestate_count
, sfx_count
);
49 if( nextsize
> replay
->size
){
50 vg_error( "Keyframe too big\n" );
54 if( nextpos
+ nextsize
> replay
->size
)
59 u32 tailpos
= (void *)replay
->tail
- replay
->data
;
61 if( tailpos
>= nextpos
){
62 if( nextpos
+ nextsize
> tailpos
){
64 if( replay
->cursor_frame
== replay
->tail
)
65 replay
->cursor_frame
= NULL
;
66 if( replay
->statehead
== replay
->tail
)
67 replay
->statehead
= NULL
;
70 replay
->tail
= replay
->tail
->r
;
73 replay
->tail
->l
= NULL
;
81 frame
= replay
->data
+ nextpos
;
84 replay
->head
->r
= frame
;
89 frame
->gamestate_count
= gamestate_count
;
90 frame
->sfx_count
= sfx_count
;
91 frame
->l
= replay
->head
;
94 if( !replay
->tail
) replay
->tail
= frame
;
95 if( gamestate_count
) replay
->statehead
= frame
;
100 VG_STATIC
void replay_seek( replay_buffer
*replay
, f64 t
){
101 if( !replay
->head
) return;
102 assert( replay
->tail
);
104 if( t
< replay
->tail
->time
) t
= replay
->tail
->time
;
105 if( t
> replay
->head
->time
) t
= replay
->head
->time
;
107 if( !replay
->cursor_frame
) {
108 replay
->cursor
= replay
->head
->time
;
109 replay
->cursor_frame
= replay
->head
;
111 if( fabs(replay
->head
->time
-t
) > fabs(replay
->tail
->time
-t
) ){
112 replay
->cursor
= replay
->tail
->time
;
113 replay
->cursor_frame
= replay
->tail
;
117 f64 dir
= t
- replay
->cursor
;
118 if( dir
== 0.0 ) return;
119 dir
= vg_signf( dir
);
124 if( t
> replay
->cursor_frame
->time
) break;
127 if( dir
> 0.0 ) next
= replay
->cursor_frame
->r
;
128 else next
= replay
->cursor_frame
->l
;
133 if( t
< next
->time
) break;
135 replay
->cursor_frame
= next
;
136 replay
->cursor
= next
->time
;
144 VG_STATIC replay_frame
*replay_find_recent_stateframe( replay_buffer
*replay
){
145 replay_frame
*frame
= replay
->cursor_frame
;
149 if( !frame
) return frame
;
150 if( frame
->gamestate_count
) return frame
;
157 VG_STATIC
void replay_get_camera( replay_buffer
*replay
, camera
*cam
){
160 if( replay
->cursor_frame
){
161 /* TODO: frame lerp */
162 cam
->fov
= replay
->cursor_frame
->cam_fov
;
163 v3_copy( replay
->cursor_frame
->cam_pos
, cam
->pos
);
164 v3_copy( replay
->cursor_frame
->cam_angles
, cam
->angles
);
168 v3_zero( cam
->angles
);
173 VG_STATIC
void skaterift_replay_pre_update(void){
174 if( skaterift
.activity
!= k_skaterift_replay
) return;
177 f64 target
= skaterift
.replay
.cursor
;
179 if( vg_getkey( SDLK_9
) ){
180 target
-= vg
.time_frame_delta
* speed
;
181 skaterift
.replay_control
= k_replay_control_scrub
;
182 replay_seek( &skaterift
.replay
, target
);
184 if( vg_getkey( SDLK_0
) ){
185 target
+= vg
.time_frame_delta
* speed
;
186 skaterift
.replay_control
= k_replay_control_scrub
;
187 replay_seek( &skaterift
.replay
, target
);
190 if( vg_getkey( SDLK_7
) )
191 skaterift
.replay_control
= k_replay_control_play
;
193 if( skaterift
.replay_control
== k_replay_control_play
){
194 target
+= vg
.time_frame_delta
;
195 replay_seek( &skaterift
.replay
, target
);
198 if( vg_getkey( SDLK_8
) ){
199 replay_frame
*prev
= replay_find_recent_stateframe( &skaterift
.replay
);
202 /* TODO: Make gamestate_apply function / swap ... */
203 replay_gamestate
*gs
= replay_frame_gamestate( prev
, 0 );
205 if( gs
->system
== k_player_subsystem_walk
){
206 memcpy( &localplayer
._walk
.state
, &gs
->walk
,
207 sizeof(struct player_walk_state
) );
209 else if( gs
->system
== k_player_subsystem_skate
){
210 memcpy( &localplayer
._skate
.state
, &gs
->skate
,
211 sizeof(struct player_skate_state
) );
213 localplayer
.subsystem
= gs
->system
;
215 memcpy( &localplayer
.rb
, &gs
->rb
, sizeof(rigidbody
) );
216 v3_copy( gs
->angles
, localplayer
.angles
);
218 v3_copy( prev
->cam_pos
, localplayer
.cam
.pos
);
219 v3_copy( prev
->cam_angles
, localplayer
.cam
.angles
);
220 localplayer
.cam
.fov
= prev
->cam_fov
;
222 memcpy( &localplayer
.cam_control
, &gs
->cam_control
,
223 sizeof(struct player_cam_controller
) );
225 /* chop end off replay */
227 skaterift
.replay
.statehead
= prev
;
228 skaterift
.replay
.head
= prev
;
229 skaterift
.replay
.cursor_frame
= prev
;
230 skaterift
.replay
.cursor
= prev
->time
;
231 skaterift
.replay_control
= k_replay_control_scrub
;
232 skaterift
.activity
= k_skaterift_default
;
233 vg
.time
= prev
->time
;
239 VG_STATIC
void skaterift_replay_debug_info(void){
240 player__debugtext( 2, "replay info" );
242 replay_buffer
*replay
= &skaterift
.replay
;
246 if( replay
->tail
) tail
= (void *)replay
->tail
- replay
->data
;
247 if( replay
->head
) head
= (void *)replay
->head
- replay
->data
;
249 player__debugtext( 1, "head @%u | tail @%u\n", head
, tail
);
251 if( replay
->statehead
){
252 u32 state
= (void *)replay
->statehead
- replay
->data
;
253 player__debugtext( 1, "gs @%u\n", state
);
256 player__debugtext( 1, "gs @NULL\n" );
258 f64 start
= replay
->cursor
,
259 end
= replay
->cursor
;
260 if( replay
->tail
) start
= replay
->tail
->time
;
261 if( replay
->head
) end
= replay
->head
->time
;
263 f64 cur
= replay
->cursor
- start
,
266 player__debugtext( 1, "cursor: %.2fs / %.2fs\n", cur
, len
);
269 VG_STATIC
void skaterift_replay_imgui(void){
270 if( skaterift
.activity
!= k_skaterift_replay
) return;
272 replay_buffer
*replay
= &skaterift
.replay
;
273 f64 start
= replay
->cursor
,
274 end
= replay
->cursor
;
275 if( replay
->tail
) start
= replay
->tail
->time
;
276 if( replay
->head
) end
= replay
->head
->time
;
277 f64 len
= end
- start
,
278 cur
= (replay
->cursor
- start
) / len
;
285 ui_rect bar
= { 0, vg
.window_y
- height
, vg
.window_x
, height
};
286 ui_fill( bar
, ui_colour( k_ui_bg
) );
288 /* cursor frame block */
289 if( replay
->cursor_frame
){
290 if( replay
->cursor_frame
->r
){
291 f64 l
= (replay
->cursor_frame
->r
->time
-replay
->cursor_frame
->time
)/len
,
292 s
= (replay
->cursor_frame
->time
- start
) / len
;
293 ui_rect box
= { s
*(f64
)vg
.window_x
, bar
[1]-2,
294 VG_MAX(4,(ui_px
)(l
*vg
.window_x
)), bar
[3]+2 };
295 ui_fill( box
, ui_colour( k_ui_bg
+4 ) );
300 ui_rect cusor
= { cur
* (f64
)vg
.window_x
- (cwidth
/2), bar
[1],
302 ui_fill( cusor
, ui_colour( k_ui_bg
+7 ) );
304 /* latest state marker */
305 if( replay
->statehead
){
306 f64 t
= (replay
->statehead
->time
- start
) / len
;
307 ui_rect tag
= { t
*(f64
)vg
.window_x
, bar
[1]-8, 2, bar
[3]+8 };
308 ui_fill( tag
, ui_colour( k_ui_green
+k_ui_brighter
) );
311 /* previous state marker */
312 replay_frame
*prev
= replay_find_recent_stateframe( replay
);
314 f64 t
= (prev
->time
- start
) / len
;
315 ui_rect tag
= { t
*(f64
)vg
.window_x
, bar
[1]-8, 2, bar
[3]+8 };
316 ui_fill( tag
, ui_colour( k_ui_yellow
+k_ui_brighter
) );
321 snprintf( buffer
, 128, "-%.2fs\n", (end
-replay
->cursor
) );
322 ui_text( cusor
, buffer
, 1, k_ui_align_middle_left
, 0 );
324 snprintf( buffer
, 128, "-%.2fs\n", len
);
325 ui_text( bar
, buffer
, 1, k_ui_align_middle_left
, 0 );
326 ui_text( bar
, "0s", 1, k_ui_align_middle_right
, 0 );
329 #endif /* PLAYER_REPLAY_C */