Add some challenges to the world map
[carveJwlIkooP6JGAAIwe30JlM.git] / world_routes_ui.c
index 7becb73dec665e210f7f5ffb89df1e9c5a5eacb4..e367e666973015ba658fae26921a22abae72daa4 100644 (file)
@@ -1,6 +1,7 @@
 #include "skaterift.h"
 #include "world_routes_ui.h"
 #include "world_routes.h"
+#include "player.h"
 
 static u32 v4_rgba( v4f colour ){
    u32 r = vg_minf(1.0f,colour[0])*255.0f,
@@ -13,16 +14,20 @@ static u32 v4_rgba( v4f colour ){
 
 static void ent_route_imgui( world_instance *world, ent_route *route, 
                              ui_point inout_cursor ){
+   if( route->flags & k_ent_route_flag_out_of_zone )
+      return;
+
    u32 last_version=0;
    f64 last_time = 0.0;
+   ent_checkpoint *last_cp = NULL;
 
    u32 valid_sections=0;
 
    struct time_block{
-      f32 length;
+      f32 length, best;
       int clean;
    }
-   *blocks = alloca( sizeof(struct time_block) * route->checkpoints_count );
+   blocks[ route->checkpoints_count ];
 
    for( u32 i=0; i<route->checkpoints_count; i++ ){
       u32 cpid  = i+route->active_checkpoint+1;
@@ -37,17 +42,20 @@ static void ent_route_imgui( world_instance *world, ent_route *route,
          struct time_block *block = &blocks[ valid_sections ++ ];
          block->clean  = (rg->flags & k_ent_gate_clean_pass)? 1: 0;
          block->length = rg->timing_time - last_time;
+         block->best = last_cp? last_cp->best_time: 0.0f;
       }
       else valid_sections = 0;
 
       last_version = rg->timing_version;
       last_time = rg->timing_time;
+      last_cp = cp;
    }
 
    if( last_version+1 == world_static.current_run_version ){
       struct time_block *block = &blocks[ valid_sections ++ ];
       block->clean = localplayer.rewinded_since_last_gate? 0: 1;
       block->length = world_static.time - last_time;
+      block->best = last_cp->best_time;
    }
    else 
       valid_sections = 0;
@@ -55,34 +63,97 @@ static void ent_route_imgui( world_instance *world, ent_route *route,
    u32 colour = v4_rgba( route->colour ) | 0xff000000;
 
    ui_px x = 0,
-         h = route->factive * 16.0f;
+         h = route->factive * 16.0f,
+         base = inout_cursor[0];//(f32)vg.window_x*0.5f - route->ui_stopper;
+
+   if( route->ui_residual > 0.0f ){
+      ui_px w = route->ui_residual_block_w,
+            total = w + 4;
+
+      f32 t = vg_smoothstepf(1.0f-route->ui_residual);
+      
+      x -= (f32)total * t;
+
+      ui_rect rect = { base+x, inout_cursor[1], w, h };
+
+      v4f fadecolour;
+      v4_copy( route->colour, fadecolour );
+      fadecolour[3] *= route->ui_residual;
+
+      ui_fill( rect, v4_rgba(fadecolour) );
+
+      x += total;
+   }
+
+   int got_first = 0;
 
    for( u32 i=0; i<valid_sections; i ++ ){
       struct time_block *block = &blocks[ i ];
-      ui_px w = block->length * 2.0f;
-      ui_rect rect = { x, inout_cursor[1], w, h };
+      ui_px w = 20 + (block->length * 6.0f);
+      ui_rect rect = { base+x, inout_cursor[1], w, h };
       ui_fill( rect, colour );
    
       if( block->clean )
          ui_outline( rect, 1, 0xff00ffff, 0 );
 
+      if( block->best != 0.0f ){
+         char buf[32];
+         vg_str str;
+         vg_strnull( &str, buf, 32 );
+         
+         f32 diff = block->length - block->best,
+             as = fabsf(diff),
+             s  = floorf( as ),
+             ds = floorf( vg_fractf( as ) * 10.0f );
+
+         if( (block->best != 0.0f) && (fabsf(diff) > 0.001f) ){
+            if( diff > 0.0f )
+               vg_strcatch( &str, '+' );
+            else
+               vg_strcatch( &str, '-' );
+
+            vg_strcati32( &str, s );
+            vg_strcatch( &str, '.' );
+            vg_strcati32( &str, ds );
+
+            ui_text( rect, buf, 1, k_ui_align_middle_center, 0 );
+         }
+      }
+
       x += w + 4;
+
+      if( !got_first ){
+         route->ui_first_block_width = w;
+         got_first = 1;
+      }
    }
 
    for( u32 i=0; i<route->checkpoints_count-valid_sections; i++ ){
       struct time_block *block = &blocks[ i ];
 
       ui_px w = 20;
-      ui_rect rect = { x, inout_cursor[1], w, h };
+      ui_rect rect = { base+x, inout_cursor[1], w, h };
       ui_outline( rect, -1, colour, 0 );
       x += w + 4;
+
+      if( !got_first ){
+         route->ui_first_block_width = w;
+         got_first = 1;
+      }
    }
 
    inout_cursor[1] += h + 4;
+
+   vg_slewf( &route->ui_residual, 0.0f, vg.time_frame_delta );
+   route->ui_stopper = vg_lerpf( route->ui_stopper, (f32)x*0.5f, 
+                                 vg.time_frame_delta );
 }
 
-static void world_routes_imgui( world_instance *world ){
-   ui_point cursor = { 0, 0 };
+void world_routes_imgui( world_instance *world )
+{
+   if( skaterift.activity == k_skaterift_menu ) return;
+
+   ui_point cursor = { 4, 4 };
    for( u32 i=0; i<mdl_arrcount(&world->ent_route); i++ ){
       ent_route_imgui( world, mdl_arritm( &world->ent_route, i ), cursor );
    }