+ ui_text( timeline, buffer, 1, k_ui_align_middle_left, 0 );
+ ui_text( timeline, "0s", 1, k_ui_align_middle_right, 0 );
+
+ if( player_replay.editor_mode )
+ {
+ gui_helper_clear();
+ vg_ui.wants_mouse = 1;
+
+ ui_rect panel = { 0, timeline[3] + 20, 200, 400 };
+ ui_fill( panel, ui_opacity( ui_colour(k_ui_bg), 0.5f ) );
+ ui_rect_pad( panel, (ui_px[2]){4,4} );
+
+ if( ui_button( panel,
+ (player_replay.replay_control == k_replay_control_play)?
+ "Pause": "Play" ) == k_ui_button_click )
+ {
+ player_replay.replay_control ^= k_replay_control_play;
+ }
+
+
+
+
+ /* script bar */
+ ui_rect script = { 0, height + 2, vg.window_x, 16 };
+ ui_fill( script, ui_colour( k_ui_bg ) );
+
+ f64 mouse_t = start + ((f64)vg_ui.mouse[0] / (f64)vg.window_x)*len;
+
+ /* 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 = t*(f64)vg.window_x-8;
+
+ if( i )
+ {
+ ui_rect con = { lx, script[1]+7, x-lx, 1 };
+ ui_fill( con, ui_colour(k_ui_blue) );
+
+ vg_line( kf->cam.pos,
+ player_replay.keyframes[i-1].cam.pos, VG__BLUE );
+ }
+
+ ui_rect tag = { x, script[1], 16, 16 };
+
+ if( ui_inside_rect( tag, vg_ui.mouse ) )
+ {
+ absorb_by_keyframe = 1;
+
+ if( ui_click_down( UI_MOUSE_LEFT ) )
+ {
+ if( player_replay.active_keyframe != i )
+ {
+ player_replay.drag_wait = 1;
+ player_replay.active_keyframe = i;
+ replay_seek( &player_replay.local, kf->time );
+ }
+ }
+ else
+ {
+ ui_outline( tag, 1, ui_colour(k_ui_fg), 0 );
+ }
+ }
+
+ if( i == player_replay.active_keyframe )
+ {
+ ui_outline( tag, 2, ui_colour(k_ui_fg), 0 );
+
+ if( ui_inside_rect( tag, vg_ui.mouse_click )
+ && !player_replay.drag_wait )
+ {
+ if( ui_clicking( UI_MOUSE_LEFT ) )
+ {
+ absorb_by_keyframe = 1;
+ tag[0] = vg_ui.mouse[0]-8;
+ replay_seek( &player_replay.local, mouse_t );
+ }
+ else if( ui_click_up( UI_MOUSE_LEFT ) )
+ {
+ kf->time = mouse_t;
+ replay_keyframe_sort();
+ }
+ }
+ }
+
+ ui_fill( tag, ui_colour(k_ui_blue) );
+ lx = x;
+ }
+
+ if( player_replay.drag_wait && !ui_clicking(UI_MOUSE_LEFT) )
+ player_replay.drag_wait = 0;
+
+ /* adding keyframes */
+ if( ui_inside_rect( script, vg_ui.mouse ) )
+ {
+ vg_ui.cursor = k_ui_cursor_hand;
+
+ ui_rect cursor = { vg_ui.mouse[0], script[1], 4, 16 };
+ ui_fill( cursor, ui_colour( k_ui_fg ) );
+
+ if( !absorb_by_keyframe && ui_click_down( UI_MOUSE_LEFT ) )
+ {
+ u32 max = vg_list_size( player_replay.keyframes );
+ if( player_replay.keyframe_count == max )
+ {
+ ui_start_modal( "Maximum keyframes reached", UI_MODAL_BAD );
+ }
+ else
+ {
+ replay_keyframe *kf =
+ &player_replay.keyframes[player_replay.keyframe_count++];
+
+ kf->time = mouse_t;
+ v3_copy( skaterift.cam.pos, kf->cam.pos );
+ v3_copy( skaterift.cam.angles, kf->cam.angles );
+ kf->cam.fov = skaterift.cam.fov;
+
+ replay_keyframe_sort();
+ }
+ }
+ }
+
+
+ /* timeline scrub */
+ bool start_in_timeline =
+ ui_clicking(UI_MOUSE_LEFT) &&
+ ui_inside_rect(timeline, vg_ui.mouse_click);
+ if( (ui_inside_rect( timeline, vg_ui.mouse )) || start_in_timeline )
+ {
+ ui_rect cursor = { vg_ui.mouse[0], timeline[1], 4, timeline[3] };
+ ui_fill( cursor, ui_colour( k_ui_fg ) );
+ vg_ui.cursor = k_ui_cursor_ibeam;
+
+ if( ui_clicking( UI_MOUSE_LEFT ) && start_in_timeline )
+ {
+ replay_seek( &player_replay.local, mouse_t );
+ player_replay.active_keyframe = -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( panel, "Edit cam" ) & mask_using )
+ {
+ if( ui_click_down( 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 );
+ player_replay.replay_freecam.fov = kf->cam.fov;
+ }
+
+ /* move freecam */
+ vg_ui.wants_mouse = 0;
+ freecam_preupdate();
+
+ v3_copy( player_replay.replay_freecam.pos, skaterift.cam.pos );
+ v3_copy( player_replay.replay_freecam.angles, skaterift.cam.angles);
+ skaterift.cam.fov = player_replay.replay_freecam.fov;
+
+ v3_copy( skaterift.cam.pos, kf->cam.pos );
+ v3_copy( skaterift.cam.angles, kf->cam.angles );
+ kf->cam.fov = skaterift.cam.fov;
+ }
+ }
+ }