start of a replay system
[carveJwlIkooP6JGAAIwe30JlM.git] / player_replay.c
1 #ifndef PLAYER_REPLAY_C
2 #define PLAYER_REPLAY_C
3
4 #include "player_replay.h"
5
6 VG_STATIC void local_replay_init( u32 bytes ){
7 localplayer.replay.data = vg_linear_alloc( vg_mem.rtmemory, bytes );
8 localplayer.replay.size = bytes;
9 localplayer.replay.cursor = -9999.9;
10 vg_console_reg_var( "k_replay_test", &k_replay_test, k_var_dtype_i32, 0 );
11 }
12
13 u32 replay_frame_size( replay_frame *frame ){
14 /* eventually it will be a dynamic size */
15 return vg_align8( sizeof( replay_frame ) );
16 }
17
18 VG_STATIC replay_frame *replay_newframe( replay_buffer *replay ){
19 replay_frame *frame = NULL;
20 if( replay->head ){
21 assert( replay->head );
22
23 u32 headsize = replay_frame_size( replay->head ),
24 nextpos = ((void *)replay->head - replay->data) + headsize,
25 nextsize = vg_align8( sizeof(replay_frame) );
26
27 if( nextsize > replay->size ){
28 vg_error( "Keyframe too big\n" );
29 return NULL;
30 }
31
32 if( nextpos + nextsize > replay->size )
33 nextpos = 0;
34
35 check_again:;
36
37 u32 tailpos = (void *)replay->tail - replay->data;
38
39 if( tailpos >= nextpos ){
40 if( nextpos + nextsize > tailpos ){
41 if( replay->cursor_frame == replay->tail ){
42 replay->cursor_frame = NULL;
43 }
44
45 replay->tail = replay->tail->r;
46
47 if( replay->tail ) {
48 replay->tail->l = NULL;
49 goto check_again;
50 }
51 else{
52 replay->head = NULL;
53 }
54 }
55 }
56
57 frame = replay->data + nextpos;
58
59 if( replay->head ){
60 replay->head->r = frame;
61 }
62 }
63 else {
64 frame = replay->data;
65 }
66
67 frame->l = replay->head;
68 frame->r = NULL;
69 replay->head = frame;
70 if( !replay->tail ) replay->tail = frame;
71
72 return frame;
73 }
74
75 VG_STATIC void replay_seek( replay_buffer *replay, f64 t ){
76 if( !replay->head ) return;
77 assert( replay->tail );
78
79 if( t < replay->tail->time ) t = replay->tail->time;
80 if( t > replay->head->time ) t = replay->head->time;
81
82 if( !replay->cursor_frame ) {
83 replay->cursor = replay->head->time;
84 replay->cursor_frame = replay->head;
85
86 if( fabs(replay->head->time-t) > fabs(replay->tail->time-t) ){
87 replay->cursor = replay->tail->time;
88 replay->cursor_frame = replay->tail;
89 }
90 }
91
92 f64 dir = t - replay->cursor;
93 if( dir == 0.0 ) return;
94 dir = vg_signf( dir );
95
96 u32 i=0;
97 for( ; i<100; i++ ){
98 if( dir < 0.0 )
99 if( t > replay->cursor_frame->time ) break;
100
101 replay_frame *next;
102 if( dir > 0.0 ) next = replay->cursor_frame->r;
103 else next = replay->cursor_frame->l;
104
105 if( !next ) break;
106
107 if( dir > 0.0 )
108 if( t < next->time ) break;
109
110 replay->cursor_frame = next;
111 }
112
113 replay->cursor = t;
114 }
115
116 VG_STATIC void replay_debug_info( player_instance *player ){
117 player__debugtext( 2, "replay info" );
118
119 replay_buffer *replay = &player->replay;
120
121 u32 head = 0,
122 tail = 0;
123 if( replay->tail ) tail = (void *)replay->tail - replay->data;
124 if( replay->head ) head = (void *)replay->head - replay->data;
125
126 player__debugtext( 1, "head @%u | tail @%u\n", head, tail );
127
128 f64 start = replay->cursor,
129 end = replay->cursor;
130 if( replay->tail ) start = replay->tail->time;
131 if( replay->head ) end = replay->head->time;
132
133 f64 cur = replay->cursor - start,
134 len = end - start;
135
136 player__debugtext( 1, "cursor: %.2fs / %.2fs\n", cur, len );
137 }
138
139 VG_STATIC void replay_imgui( player_instance *player ){
140 if( !k_replay_test ) return;
141
142 replay_buffer *replay = &player->replay;
143 f64 start = replay->cursor,
144 end = replay->cursor;
145 if( replay->tail ) start = replay->tail->time;
146 if( replay->head ) end = replay->head->time;
147 f64 len = end - start,
148 cur = (replay->cursor - start) / len;
149
150 char buffer[ 128 ];
151
152 ui_px height = 20,
153 cwidth = 8;
154 ui_rect bar = { 0, vg.window_y - height, vg.window_x, height };
155 ui_fill( bar, ui_colour( k_ui_bg ) );
156
157 ui_rect cusor = { cur * (f64)vg.window_x - (cwidth/2), bar[1],
158 cwidth, bar[3] };
159 ui_fill( cusor, ui_colour( k_ui_bg+4 ) );
160
161 cusor[1] -= height;
162 cusor[2] = 200;
163 snprintf( buffer, 128, "-%.2fs\n", (end-replay->cursor) );
164 ui_text( cusor, buffer, 1, k_ui_align_middle_left, 0 );
165
166 snprintf( buffer, 128, "-%.2fs\n", len );
167 ui_text( bar, buffer, 1, k_ui_align_middle_left, 0 );
168 ui_text( bar, "0s", 1, k_ui_align_middle_right, 0 );
169 }
170
171 #endif /* PLAYER_REPLAY_C */