well yeah i guess
[carveJwlIkooP6JGAAIwe30JlM.git] / world_routes.h
index e53f0920537bea10fe3eebcfd66c9855fcac5e21..312429579a0fcd021d9b3cfe966d85424f9e4919 100644 (file)
 
 enum route_special_type
 {
+   k_route_special_type_none = 0,
    k_route_special_type_gate = 1,
    k_route_special_type_collector = 2
 };
 
-static void debug_sbpath( struct route_node *rna, struct route_node *rnb,
+VG_STATIC void debug_sbpath( struct route_node *rna, struct route_node *rnb,
                           u32 colour, float xoffset )
 {
    v3f p0, h0, p1, h1, l, p;
@@ -48,7 +49,7 @@ static void debug_sbpath( struct route_node *rna, struct route_node *rnb,
 /*
  * Get a list of node ids in stack, and return how many there is
  */
-static u32 world_routes_get_path( u32 starter, u32 stack[64] )
+VG_STATIC u32 world_routes_get_path( u32 starter, u32 stack[64] )
 {
    u32 stack_i[64];
 
@@ -66,7 +67,7 @@ static u32 world_routes_get_path( u32 starter, u32 stack[64] )
          continue;
       }
 
-      struct route_node *rn = &world_routes.nodes[stack[si-1]];
+      struct route_node *rn = &world.nodes[stack[si-1]];
       u32 nextid = rn->next[stack_i[si-1]];
       stack_i[si-1] ++;
 
@@ -107,37 +108,35 @@ static u32 world_routes_get_path( u32 starter, u32 stack[64] )
 /*
  * Free a segment from the UI bar to be reused later
  */
-static void world_routes_ui_popfirst( u32 route )
+VG_STATIC void world_routes_ui_popfirst( struct route_ui_bar *pui )
 {
-   struct route *pr = &world_routes.routes[route];
-
-   if( pr->ui.segment_count )
+   if( pui->segment_count )
    {
-      pr->ui.segment_start ++;
+      pui->segment_start ++;
 
-      if( pr->ui.segment_start == 32 )
-         pr->ui.segment_start = 0;
+      if( pui->segment_start == 32 )
+         pui->segment_start = 0;
 
-      pr->ui.segment_count --;
+      pui->segment_count --;
    }
 }
 
 /*
  * Reset ui bar completely
  */
-static void world_routes_ui_clear( u32 route )
+VG_STATIC void world_routes_ui_clear( struct route_ui_bar *pui )
 {
-   struct route *pr = &world_routes.routes[route];
-   pr->ui.segment_start = (pr->ui.segment_start + pr->ui.segment_count) %
-                              k_max_ui_segments;
-   pr->ui.segment_count = 0;
+   pui->segment_start = (pui->segment_start + pui->segment_count) %
+                                                            k_max_ui_segments;
+   pui->segment_count = 0;
 }
 
 /*
  * Break a index range into two pieces over the edge of the maximum it can
  * store. s1 is 0 always, so its a ring buffer.
  */
-static void world_routes_ui_split_indices( u32 s0, u32 count, u32 *c0, u32 *c1 )
+VG_STATIC void world_routes_ui_split_indices( u32 s0, u32 count, 
+                                              u32 *c0, u32 *c1 )
 {
    *c0 = (VG_MIN( s0+count, k_route_ui_max_indices )) - s0;
    *c1 = count-(*c0);
@@ -147,41 +146,42 @@ static void world_routes_ui_split_indices( u32 s0, u32 count, u32 *c0, u32 *c1 )
  * Place a set of indices into gpu array automatically splits
  * across bounds
  */
-static void world_routes_ui_set_indices( struct route *pr
-                                          u16 *indices, u32 count )
+VG_STATIC void world_routes_ui_set_indices( struct route_ui_bar *pui
+                                         u16 *indices, u32 count )
 {
    u32 c0, c1;
-   world_routes_ui_split_indices( pr->ui.indices_head, count, &c0, &c1 );
+   world_routes_ui_split_indices( pui->indices_head, count, &c0, &c1 );
 
-   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, pr->ui.ebo );
+   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, pui->ebo );
 
    if( c0 )
    {
-      glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, pr->ui.indices_head*sizeof(u16),
+      glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, pui->indices_head*sizeof(u16),
             c0*sizeof(u16), indices );
    }
 
    if( c1 )
    {
       glBufferSubData( GL_ELEMENT_ARRAY_BUFFER, 0, c1*sizeof(u16), indices+c0 );
-      pr->ui.indices_head = c1;
+      pui->indices_head = c1;
    }
    else
-      pr->ui.indices_head += c0;
+      pui->indices_head += c0;
 }
 
 /*
  * Place a set of vertices into gpu array 
  */
-static u32 world_routes_ui_set_verts( struct route *pr, v2f *verts, u32 count )
+VG_STATIC u32 world_routes_ui_set_verts( struct route_ui_bar *pui,
+                                      v2f *verts, u32 count )
 {
-   if( pr->ui.vertex_head + count >= k_route_ui_max_verts )
-      pr->ui.vertex_head = 0;
+   if( pui->vertex_head + count >= k_route_ui_max_verts )
+      pui->vertex_head = 0;
 
-   u32 vert_start = pr->ui.vertex_head;
-   pr->ui.vertex_head += count;
+   u32 vert_start = pui->vertex_head;
+   pui->vertex_head += count;
 
-   glBindBuffer( GL_ARRAY_BUFFER, pr->ui.vbo );
+   glBindBuffer( GL_ARRAY_BUFFER, pui->vbo );
    glBufferSubData( GL_ARRAY_BUFFER, (GLintptr)(vert_start*sizeof(v2f)),
                         sizeof(v2f)*count, verts );
 
@@ -192,12 +192,12 @@ static u32 world_routes_ui_set_verts( struct route *pr, v2f *verts, u32 count )
  * Update the last (count) vertices positions, does not add any.
  * Data must already be written to, and not cross either array boundaries.
  */
-static u32 world_routes_ui_update_verts( struct route *pr, 
+VG_STATIC u32 world_routes_ui_update_verts( struct route_ui_bar *pui,
                                          v2f *verts, u32 count )
 {
-   u32 vert_start = pr->ui.vertex_head-count;
+   u32 vert_start = pui->vertex_head-count;
 
-   glBindBuffer( GL_ARRAY_BUFFER, pr->ui.vbo );
+   glBindBuffer( GL_ARRAY_BUFFER, pui->vbo );
    glBufferSubData( GL_ARRAY_BUFFER, (GLintptr)(vert_start*sizeof(v2f)),
                         sizeof(v2f)*count, verts );
 
@@ -207,28 +207,29 @@ static u32 world_routes_ui_update_verts( struct route *pr,
 /* 
  * Current/active segment of this UI bar 
  */
-static struct route_ui_segment *world_routes_ui_curseg( struct route *pr )
+VG_STATIC struct route_ui_segment *world_routes_ui_curseg( 
+      struct route_ui_bar *pui )
 {
-   u32 index = (pr->ui.segment_start+pr->ui.segment_count-1)%k_max_ui_segments;
-   return &pr->ui.segments[ index ];
+   u32 index = (pui->segment_start+pui->segment_count-1)%k_max_ui_segments;
+   return &pui->segments[ index ];
 }
 
 /*
  * Start a new segment in the UI bar, will create a split on the last one if
  * there is one active currently. (api)
  */
-static void world_routes_ui_newseg( u32 route )
+VG_STATIC void world_routes_ui_newseg( u32 route )
 {
-   struct route *pr = &world_routes.routes[route];
+   struct route_ui_bar *pui = &world.ui_bars[route];
 
-   pr->ui.last_notch = 0.0;
+   pui->last_notch = 0.0;
    
-   glBindVertexArray( pr->ui.vao );
-   if( pr->ui.segment_count )
+   glBindVertexArray( pui->vao );
+   if( pui->segment_count )
    {
       float const k_gap_width = 1.0f;
 
-      struct route_ui_segment *cseg = world_routes_ui_curseg(pr);
+      struct route_ui_segment *cseg = world_routes_ui_curseg( pui );
       
       v2f verts[2];
       verts[0][0] =  cseg->length-k_gap_width;
@@ -236,11 +237,11 @@ static void world_routes_ui_newseg( u32 route )
       verts[1][0] =  cseg->length-k_gap_width;
       verts[1][1] = -0.5f;
 
-      world_routes_ui_update_verts( pr, verts, 2 );
+      world_routes_ui_update_verts( pui, verts, 2 );
    }
 
-   pr->ui.segment_count ++;
-   struct route_ui_segment *segment = world_routes_ui_curseg(pr);
+   pui->segment_count ++;
+   struct route_ui_segment *segment = world_routes_ui_curseg( pui );
    
    v2f verts[4];
    verts[0][0] =  0.0f;
@@ -252,7 +253,7 @@ static void world_routes_ui_newseg( u32 route )
    verts[3][0] =  0.0f;
    verts[3][1] = -0.5f;
 
-   u32 vert_start = world_routes_ui_set_verts( pr, verts, 4 );
+   u32 vert_start = world_routes_ui_set_verts( pui, verts, 4 );
 
    u16 indices[6];
    indices[0] = vert_start + 0;
@@ -264,19 +265,19 @@ static void world_routes_ui_newseg( u32 route )
 
    segment->vertex_start = vert_start;
    segment->vertex_count = 4;
-   segment->index_start  = pr->ui.indices_head;
+   segment->index_start  = pui->indices_head;
    segment->index_count  = 6;
    segment->notches      = 0;
 
-   world_routes_ui_set_indices( pr, indices, 6 );
+   world_routes_ui_set_indices( pui, indices, 6 );
 }
 
 /*
  * Extend the end of the bar 
  */
-static void world_routes_ui_updatetime( u32 route, float time )
+VG_STATIC void world_routes_ui_updatetime( u32 route, float time )
 {
-   struct route *pr = &world_routes.routes[route];
+   struct route_ui_bar *pui = &world.ui_bars[route];
 
    v2f verts[2];
    verts[0][0] =  time;
@@ -284,96 +285,16 @@ static void world_routes_ui_updatetime( u32 route, float time )
    verts[1][0] =  time;
    verts[1][1] = -0.5f;
 
-   u32 vert_start = pr->ui.vertex_head-2;
+   u32 vert_start = pui->vertex_head-2;
 
-   glBindVertexArray( pr->ui.vao );
-   world_routes_ui_update_verts( pr, verts, 2 );
+   glBindVertexArray( pui->vao );
+   world_routes_ui_update_verts( pui, verts, 2 );
 
-   struct route_ui_segment *cseg = world_routes_ui_curseg(pr);
+   struct route_ui_segment *cseg = world_routes_ui_curseg( pui );
    cseg->length = time;
 }
 
-/*
- * Create a notch in the bar, used when a reset is triggered by the user
- */
-static void world_routes_ui_notch( u32 route, float time )
-{
-   return; /* FIXME: Temporarily disabled */
-
-   struct route *pr = &world_routes.routes[route];
-
-   if( (time - pr->ui.last_notch) > 1.0 )
-   {
-      struct route_ui_segment *segment = world_routes_ui_curseg(pr);
-      if( segment->notches == k_max_ui_splits_per_segment )
-         return;
-
-      segment->notches ++;
-
-      v2f verts[8];
-      
-      float const k_notch_width = 1.0f;
-
-      float xa = time-k_notch_width,
-            xb = time-k_notch_width * 0.5f,
-            xc = time;
-
-      verts[0][0] =  xa;
-      verts[0][1] =  0.5f;
-      verts[1][0] =  xa;
-      verts[1][1] = -0.5f;
-
-      verts[2][0] =  xb;
-      verts[2][1] =  0.25f;
-      verts[3][0] =  xb;
-      verts[3][1] = -0.25f;
-
-      verts[4][0] =  xc;
-      verts[4][1] =  0.5f;
-      verts[5][0] =  xc;
-      verts[5][1] = -0.5f;
-
-      verts[6][0] =  xc;
-      verts[6][1] =  0.5f;
-      verts[7][0] =  xc;
-      verts[7][1] = -0.5f;
-
-      glBindVertexArray( pr->ui.vao );
-      u32 vert_start_mod = world_routes_ui_update_verts( pr, verts, 2 ),
-          vert_start_new = world_routes_ui_set_verts( pr, verts+2, 6 );
-
-      u16 indices[18];
-      indices[ 0] = vert_start_mod+1;
-      indices[ 1] = vert_start_new+0;
-      indices[ 2] = vert_start_mod+0;
-      indices[ 3] = vert_start_mod+1;
-      indices[ 4] = vert_start_new+1;
-      indices[ 5] = vert_start_new+0;
-
-      indices[ 6] = vert_start_new+0;
-      indices[ 7] = vert_start_new+1;
-      indices[ 8] = vert_start_new+3;
-      indices[ 9] = vert_start_new+0;
-      indices[10] = vert_start_new+3;
-      indices[11] = vert_start_new+2;
-
-      indices[12] = vert_start_new+3;
-      indices[13] = vert_start_new+4;
-      indices[14] = vert_start_new+2;
-      indices[15] = vert_start_new+3;
-      indices[16] = vert_start_new+5;
-      indices[17] = vert_start_new+4;
-
-      world_routes_ui_set_indices( pr, indices, 18 );
-
-      pr->ui.last_notch = time;
-
-      segment->vertex_count += 6;
-      segment->index_count  += 18;
-   }
-}
-
-static void world_routes_ui_draw_segment( struct route_ui_segment *segment )
+VG_STATIC void world_routes_ui_draw_segment( struct route_ui_segment *segment )
 {
    u32 c0, c1;
    world_routes_ui_split_indices( segment->index_start, 
@@ -388,28 +309,29 @@ static void world_routes_ui_draw_segment( struct route_ui_segment *segment )
 /*
  * Draws full bar at Y offset(offset).
  */
-static void world_routes_ui_draw( u32 route, v4f colour, float offset )
+VG_STATIC void world_routes_ui_draw( u32 route, v4f colour, float offset )
 {
    float const k_bar_height = 0.05f,
                k_bar_scale_x = 0.005f;
 
-   struct route *pr = &world_routes.routes[route];
+   struct route *pr = &world.routes[route];
+   struct route_ui_bar *pui = &world.ui_bars[route];
 
-   float cx = pr->ui.xpos;
+   float cx = pui->xpos;
 
    shader_routeui_use();
-   glBindVertexArray( pr->ui.vao );
+   glBindVertexArray( pui->vao );
 
-   float fade_amt = world_routes.time - pr->ui.fade_timer_start;
+   float fade_amt = world.time - pui->fade_timer_start;
    fade_amt = vg_clampf( fade_amt / 1.0f, 0.0f, 1.0f );
    
    float fade_block_size = 0.0f,
          main_block_size = 0.0f;
 
-   for( u32 i=0; i<pr->ui.fade_count; i++ )
+   for( u32 i=0; i<pui->fade_count; i++ )
    {
-      u32 j = (pr->ui.fade_start + i) % k_max_ui_segments;
-      struct route_ui_segment *segment = &pr->ui.segments[j];
+      u32 j = (pui->fade_start + i) % k_max_ui_segments;
+      struct route_ui_segment *segment = &pui->segments[j];
 
       fade_block_size += segment->length;
    }
@@ -421,7 +343,7 @@ static void world_routes_ui_draw( u32 route, v4f colour, float offset )
    fade_colour[3] *= 1.0f-fade_amt;
 
    /* 1 minute timer */
-   float timer_delta = (world_routes.time - world_routes.last_use) * (1.0/45.0),
+   float timer_delta = (world.time - world.last_use) * (1.0/45.0),
          timer_scale = 1.0f - vg_minf( timer_delta, 1.0f );
 
    /* 
@@ -432,10 +354,10 @@ static void world_routes_ui_draw( u32 route, v4f colour, float offset )
          base = -1.0f + (offset+0.5f)*k_bar_height * timer_scale;
 
    shader_routeui_uColour( fade_colour );
-   for( u32 i=0; i<pr->ui.fade_count; i++ )
+   for( u32 i=0; i<pui->fade_count; i++ )
    {
-      u32 j = (pr->ui.fade_start + i) % k_max_ui_segments;
-      struct route_ui_segment *segment = &pr->ui.segments[j];
+      u32 j = (pui->fade_start + i) % k_max_ui_segments;
+      struct route_ui_segment *segment = &pui->segments[j];
 
       shader_routeui_uOffset( (v4f){ cx*k_bar_scale_x, base,
                                      k_bar_scale_x, height } );
@@ -448,10 +370,10 @@ static void world_routes_ui_draw( u32 route, v4f colour, float offset )
     * Draw main bar 
     */
    shader_routeui_uColour( colour );
-   for( u32 i=0; i<pr->ui.segment_count; i++ )
+   for( u32 i=0; i<pui->segment_count; i++ )
    {
-      u32 j = (pr->ui.segment_start + i) % k_max_ui_segments;
-      struct route_ui_segment *segment = &pr->ui.segments[j];
+      u32 j = (pui->segment_start + i) % k_max_ui_segments;
+      struct route_ui_segment *segment = &pui->segments[j];
 
       shader_routeui_uOffset( (v4f){ cx*k_bar_scale_x, base,
                                      k_bar_scale_x, height } );
@@ -462,14 +384,14 @@ static void world_routes_ui_draw( u32 route, v4f colour, float offset )
       main_block_size += segment->length;
    }
 
-   pr->ui.xpos = vg_lerpf( pr->ui.xpos, -main_block_size * 0.5f, 0.03f );
+   pui->xpos = vg_lerpf( pui->xpos, -main_block_size * 0.5f, 0.03f );
 }
 
-static void world_routes_local_set_record( u32 route, double lap_time )
+VG_STATIC void world_routes_local_set_record( u32 route, double lap_time )
 {
    vg_success( "  NEW LAP TIME: %f\n", lap_time );
 
-   struct route *pr = &world_routes.routes[route];
+   struct route *pr = &world.routes[route];
 
    if( pr->track_id != 0xffffffff )
    {
@@ -507,12 +429,13 @@ static void world_routes_local_set_record( u32 route, double lap_time )
  *   2: the time of each segment will be recorded into the data buffer
  *       (not implemented: TODO)
  */
-static void world_routes_verify_run( u32 route )
+VG_STATIC void world_routes_verify_run( u32 route )
 {
-   struct route *pr = &world_routes.routes[route];
+   struct route *pr = &world.routes[route];
+   struct route_ui_bar *pui = &world.ui_bars[route];
 
    u32 stack[64];
-   u32 si = world_routes_get_path( world_routes.routes[route].start, stack );
+   u32 si = world_routes_get_path( world.routes[route].start, stack );
 
    /* 
     * we only care about gates that ref gates, so shuffle down the array
@@ -521,15 +444,15 @@ static void world_routes_verify_run( u32 route )
    u32 sj = 0, maxv = 0, begin = 0;
    for( u32 i=0; i<si; i++ )
    {
-      struct route_node *inode = &world_routes.nodes[stack[i]];
+      struct route_node *inode = &world.nodes[stack[i]];
 
       if( inode->special_type == k_route_special_type_collector )
       {
-         timings[sj ++] = &world_routes.collectors[ inode->special_id ].timing;
+         timings[sj ++] = &world.collectors[ inode->special_id ].timing;
       }
       else if( inode->special_type == k_route_special_type_gate )
       {
-         timings[sj ++] = &world_routes.gates[inode->special_id].timing;
+         timings[sj ++] = &world.gates[inode->special_id].timing;
       }
    }
    
@@ -543,10 +466,10 @@ static void world_routes_verify_run( u32 route )
    }
 
    vg_info( "== begin verification (%u) ==\n", route );
-   vg_info( "  current version: %u\n", world_routes.current_run_version );
+   vg_info( "  current version: %u\n", world.current_run_version );
 
    int verified = 0;
-   if( timings[begin]->version == world_routes.current_run_version )
+   if( timings[begin]->version == world.current_run_version )
       verified = 1;
 
    int valid_segment_count = 0;
@@ -576,24 +499,24 @@ static void world_routes_verify_run( u32 route )
       
       if( verified )
          vg_success( " [ %u %f ] %f\n", timings[j1]->time, 
-                                         timings[j1]->version, diff );
+                                        timings[j1]->version, diff );
       else
          vg_warn( " [ %u %f ]\n", timings[j1]->time, timings[j1]->version );
    }
 
-   pr->ui.fade_start = pr->ui.segment_start;
-   pr->ui.fade_count = 0;
-   pr->ui.fade_timer_start = world_routes.time;
+   pui->fade_start = pui->segment_start;
+   pui->fade_count = 0;
+   pui->fade_timer_start = world.time;
 
-   int orig_seg_count = pr->ui.segment_count;
+   int orig_seg_count = pui->segment_count;
 
    world_routes_ui_newseg( route );
 
    if( verified )
    {
       world_routes_local_set_record( route, lap_time );
-      world_routes_ui_popfirst(route);
-      pr->ui.fade_count ++;
+      world_routes_ui_popfirst( pui );
+      pui->fade_count ++;
    }
    else
       vg_info( "  ctime: %f\n", lap_time );
@@ -602,32 +525,33 @@ static void world_routes_verify_run( u32 route )
    int to_remove = orig_seg_count-valid_segment_count;
    for( int i=0; i<to_remove; i++ )
    {
-      world_routes_ui_popfirst(route);
-      pr->ui.fade_count ++;
+      world_routes_ui_popfirst( pui );
+      pui->fade_count ++;
    }
 
-   world_routes.routes[route].latest_pass = world_routes.time;
+   world.routes[route].latest_pass = world.time;
 }
 
 /*
  * When going through a gate this is called for bookkeeping purposes
  */
-static void world_routes_activate_gate( u32 id )
+VG_STATIC void world_routes_activate_gate( u32 id )
 {
-   struct route_gate *rg = &world_routes.gates[id];
-   struct route_node *pnode = &world_routes.nodes[rg->node_id],
-                     *pdest = &world_routes.nodes[pnode->next[0]];
+   struct route_gate *rg = &world.gates[id];
+   struct route_node *pnode = &world.nodes[rg->node_id],
+                     *pdest = &world.nodes[pnode->next[0]];
+
+   world.last_use = world.time;
 
-   world_routes.last_use = world_routes.time;
+   struct route_collector *rc = &world.collectors[ pdest->special_id ];
 
-   struct route_collector *rc = &world_routes.collectors[ pdest->special_id ];
+   world.active_gate = id;
+   rg->timing.version = world.current_run_version;
+   rg->timing.time = world.time;
 
-   world_routes.active_gate = id;
-   rg->timing.version = world_routes.current_run_version;
-   rg->timing.time = world_routes.time;
-   for( u32 i=0; i<world_routes.route_count; i++ )
+   for( u32 i=0; i<world.route_count; i++ )
    {
-      struct route *route = &world_routes.routes[i];
+      struct route *route = &world.routes[i];
       
       int was_active = route->active;
 
@@ -644,30 +568,31 @@ static void world_routes_activate_gate( u32 id )
 
       if( was_active && !route->active )
       {
-         route->ui.fade_start = route->ui.segment_start;
-         route->ui.fade_count = route->ui.segment_count;
-         route->ui.fade_timer_start = world_routes.time;
-         world_routes_ui_clear(i);
-
-         vg_success( "CLEARING -> %u %u \n", route->ui.fade_start,
-                                             route->ui.fade_count );
+         struct route_ui_bar *pui = &world.ui_bars[i];
+         pui->fade_start = pui->segment_start;
+         pui->fade_count = pui->segment_count;
+         pui->fade_timer_start = world.time;
+
+         world_routes_ui_clear( pui );
+         vg_success( "CLEARING -> %u %u \n", pui->fade_start,
+                                             pui->fade_count );
       }
    }
    
-   world_routes.current_run_version ++;
+   world.current_run_version ++;
 
-   rc->timing.version = world_routes.current_run_version;
-   rc->timing.time = world_routes.time;
-   world_routes.current_run_version ++;
+   rc->timing.version = world.current_run_version;
+   rc->timing.time = world.time;
+   world.current_run_version ++;
 }
 
 /*
  * Notify the UI system that we've reset the player
  */
-static void world_routes_notify_reset(void)
+VG_STATIC void world_routes_notify_reset(void)
 {
-   world_routes.rewind_from = world_routes.time;
-   world_routes.rewind_to = world_routes.last_use;
+   world.rewind_from = world.time;
+   world.rewind_to = world.last_use;
 
 #if 0
    for( int i=0; i<r->route_count; i++ )
@@ -681,25 +606,23 @@ static void world_routes_notify_reset(void)
 }
 
 /* Rewind between the saved points in time */
-static void world_routes_rollback_time( double t )
+VG_STATIC void world_routes_rollback_time( double t )
 {
-   world_routes.time = 
-      vg_lerp( world_routes.rewind_to, world_routes.rewind_from, t );
+   world.time = vg_lerp( world.rewind_to, world.rewind_from, t );
 }
 
 /* draw lines along the paths */
-static void world_routes_debug(void)
+VG_STATIC void world_routes_debug(void)
 {
-
-   for( int i=0; i<world_routes.node_count; i++ )
+   for( int i=0; i<world.node_count; i++ )
    {
-      struct route_node *rn = &world_routes.nodes[i];
+      struct route_node *rn = &world.nodes[i];
       vg_line_pt3( rn->co, 1.0f, rn->special_type? 0xffffff00: 0xff00b2ff );
    }
 
-   for( int i=0; i<world_routes.route_count; i++ )
+   for( int i=0; i<world.route_count; i++ )
    {
-      struct route *route = &world_routes.routes[i];
+      struct route *route = &world.routes[i];
 
       u32 stack[64];
       u32 si = world_routes_get_path( route->start, stack );
@@ -713,39 +636,31 @@ static void world_routes_debug(void)
       {
          int sk = (sj+1)%si;
 
-         struct route_node *pj = &world_routes.nodes[stack[sj]],
-                           *pk = &world_routes.nodes[stack[sk]];
+         struct route_node *pj = &world.nodes[stack[sj]],
+                           *pk = &world.nodes[stack[sk]];
          debug_sbpath( pj, pk, cc, (float)i );
       }
    }
 
-   for( int i=0; i<world_routes.node_count; i++ )
+   for( int i=0; i<world.node_count; i++ )
    {
-      struct route_node *ri = &world_routes.nodes[i],
+      struct route_node *ri = &world.nodes[i],
                         *rj = NULL;
       
       for( int j=0; j<2; j++ )
       {
          if( ri->next[j] != 0xffffffff )
          {
-            rj = &world_routes.nodes[ri->next[j]];
+            rj = &world.nodes[ri->next[j]];
             vg_line( ri->co, rj->co, 0x20ffffff );
          }
       }
    }
 }
 
-static void world_id_fixup( u32 *uid, mdl_header *mdl )
+VG_STATIC void world_routes_create_mesh( u32 route_id )
 {
-   if( *uid )
-      *uid = mdl_node_from_id( mdl, *uid )->sub_uid;
-   else
-      *uid = 0xffffffff;
-}
-
-static void world_routes_create_mesh( u32 route_id )
-{
-   struct route *route = &world_routes.routes[ route_id ];
+   struct route *route = &world.routes[ route_id ];
 
    u32 stack[64];
    u32 si = world_routes_get_path( route->start, stack );
@@ -756,8 +671,8 @@ static void world_routes_create_mesh( u32 route_id )
    {
       int sk=(sj+1)%si;
 
-      struct route_node *rnj = &world_routes.nodes[ stack[sj] ],
-                        *rnk = &world_routes.nodes[ stack[sk] ],
+      struct route_node *rnj = &world.nodes[ stack[sj] ],
+                        *rnk = &world.nodes[ stack[sk] ],
                         *rnl;
       
       if( rnj->special_type && rnk->special_type )
@@ -771,7 +686,7 @@ static void world_routes_create_mesh( u32 route_id )
 
       if( rnk->special_type )
       {
-         rnl = &world_routes.nodes[ rnk->next[0] ];
+         rnl = &world.nodes[ rnk->next[0] ];
          base_x1 = (float)rnl->ref_count*-0.5f + (float)rnl->current_refs;
       }
 
@@ -830,19 +745,19 @@ static void world_routes_create_mesh( u32 route_id )
             v2_zero( va.uv );
             v2_zero( vb.uv );
 
-            scene_push_vert( &world_routes.scene_lines, &va );
-            scene_push_vert( &world_routes.scene_lines, &vb );
+            scene_push_vert( world.scene_lines, &va );
+            scene_push_vert( world.scene_lines, &vb );
 
             if( last_valid )
             {
                /* Connect them with triangles */
-               scene_push_tri( &world_routes.scene_lines, (u32[3]){ 
+               scene_push_tri( world.scene_lines, (u32[3]){ 
                      last_valid+0-2, last_valid+1-2, last_valid+2-2} );
-               scene_push_tri( &world_routes.scene_lines, (u32[3]){ 
+               scene_push_tri( world.scene_lines, (u32[3]){ 
                      last_valid+1-2, last_valid+3-2, last_valid+2-2} );
             }
             
-            last_valid = world_routes.scene_lines.vertex_count;
+            last_valid = world.scene_lines->vertex_count;
          }
          else
             last_valid = 0;
@@ -860,255 +775,286 @@ static void world_routes_create_mesh( u32 route_id )
       rnj->current_refs ++;
    }
 
-   scene_copy_slice( &world_routes.scene_lines, &route->sm );
+   scene_copy_slice( world.scene_lines, &route->sm );
 }
 
 /* 
  * Create the strips of colour that run through the world along course paths
  */
-static int world_routes_create_all_meshes(void)
+VG_STATIC void world_routes_generate(void)
 {
    vg_info( "Generating route meshes\n" );
+   world.scene_lines = scene_init( world.dynamic_vgl, 200000, 300000 );
 
-   scene_init( &world_routes.scene_lines );
-
-   for( u32 i=0; i<world_routes.route_count; i++ )
+   for( u32 i=0; i<world.route_count; i++ )
       world_routes_create_mesh( i );
 
    vg_acquire_thread_sync();
    {
-      scene_upload( &world_routes.scene_lines );
+      scene_upload( world.scene_lines, &world.mesh_route_lines );
+   }
+   vg_release_thread_sync();
+   vg_linear_del( world.dynamic_vgl, world.scene_lines );
+}
+
+/* determine if special type is required for this gate */
+VG_STATIC enum route_special_type world_route_node_type( mdl_node *pnode )
+{
+   if( pnode->classtype == k_classtype_gate )
+   {
+      struct classtype_gate *inf = mdl_get_entdata( world.meta, pnode );
 
-      /* UI buffers */
-      for( int i=0; i<world_routes.route_count; i++ )
+      if( inf->target )
       {
-         /* OpenGL strips */
-         struct route *route = &world_routes.routes[i];
+         mdl_node *pother = mdl_node_from_id( world.meta, inf->target );
+         
+         if( pother->classtype == k_classtype_gate )
+         {
+            return k_route_special_type_gate;
+         }
+      }
 
-         glGenVertexArrays( 1, &route->ui.vao );
-         glGenBuffers( 1, &route->ui.vbo );
-         glGenBuffers( 1, &route->ui.ebo );
-         glBindVertexArray( route->ui.vao );
+      return k_route_special_type_collector;
+   }
 
-         size_t stride = sizeof(v2f);
+   return k_route_special_type_none;
+}
 
-         glBindBuffer( GL_ARRAY_BUFFER, route->ui.vbo );
-         glBufferData( GL_ARRAY_BUFFER, k_route_ui_max_verts*stride, 
-                       NULL, GL_DYNAMIC_DRAW );
+/* count entities and allocate correct amount of memory in advance */
+VG_STATIC void world_routes_allocate(void)
+{
+   vg_info( "Allocating routes\n" );
 
-         glBindVertexArray( route->ui.vao );
-         glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, route->ui.ebo );
-         glBufferData( GL_ELEMENT_ARRAY_BUFFER, 
-               k_route_ui_max_indices*sizeof(u16), NULL,
-               GL_DYNAMIC_DRAW );
+   /* count */
+   u32 node_count       = 0,
+       route_count      = 0,
+       gate_count       = 0,
+       collector_count  = 0;
+   
+   for( int i=0; i<world.meta->info.node_count; i++ )
+   {
+      mdl_node *pnode = mdl_node_from_id( world.meta, i );
 
-         glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, stride, (void *)0 );
-         glEnableVertexAttribArray( 0 );
-         VG_CHECK_GL_ERR();
+      if( pnode->classtype == k_classtype_route_node ||
+          pnode->classtype == k_classtype_gate )
+      {
+         pnode->sub_uid = node_count;
+
+         enum route_special_type type = world_route_node_type( pnode );
+
+         if( type == k_route_special_type_gate )
+            gate_count ++;
+         else if( type == k_route_special_type_collector )
+            collector_count ++;
+
+         node_count ++;
+      }
+      else if( pnode->classtype == k_classtype_route )
+      {
+         route_count ++;
       }
    }
-   vg_release_thread_sync();
 
-   scene_free_offline_buffers( &world_routes.scene_lines );
-   return 1;
-}
+   /* allocate */
+   u32 node_size        = node_count      * sizeof(struct route_node),
+       route_size       = route_count     * sizeof(struct route),
+       gate_size        = gate_count      * sizeof(struct route_gate),
+       collector_size   = collector_count * sizeof(struct route_collector);
 
+   world.nodes          = vg_linear_alloc( world.dynamic_vgl, node_size );
+   world.routes         = vg_linear_alloc( world.dynamic_vgl, route_size );
+   world.gates          = vg_linear_alloc( world.dynamic_vgl, gate_size );
+   world.collectors     = vg_linear_alloc( world.dynamic_vgl, collector_size );
+}
 
-static void world_routes_loadfrom( mdl_header *mdl )
+/* create node from mdl node */
+VG_STATIC struct route_node *world_routes_create_node( mdl_node *pnode )
 {
-   vg_info( "Initializing routes\n" );
+   struct route_node *rn = &world.nodes[ world.node_count ++ ];
 
-   world_routes.nodes = NULL;
-   world_routes.node_count = 0; 
-   world_routes.node_cap = 0; 
-   world_routes.routes = NULL;
-   world_routes.route_count = 0;
-   world_routes.route_cap = 0;
-   world_routes.gates = NULL;
-   world_routes.gate_count = 0;
-   world_routes.gate_cap = 0;
-
-   /* TODO Break this up */
-   for( int i=0; i<mdl->node_count; i++ )
-   {
-      mdl_node *pnode = mdl_node_from_id(mdl,i);
-      m4x3f transform;
+   m4x3f transform;
+   mdl_node_transform( pnode, transform );
 
-      if( pnode->classtype == k_classtype_route_node ||
-          pnode->classtype == k_classtype_gate )
-      {
-         mdl_node_transform( pnode, transform );
-         pnode->sub_uid = world_routes.node_count;
-         
-         world_routes.nodes = buffer_reserve( world_routes.nodes, 
-                                              world_routes.node_count, 
-                                              &world_routes.node_cap, 1,
-                                                sizeof( struct route_node ) );
-
-         struct route_node *rn = &world_routes.nodes[world_routes.node_count];
-
-         v3_copy( transform[0], rn->right );
-         v3_normalize( rn->right );
-         v3_copy( transform[1], rn->up );
-         v3_normalize( rn->up );
-         v3_muls( transform[2], -1.0f, rn->h );
-         v3_copy( transform[3], rn->co );
-         rn->ref_count = 0;
-         rn->current_refs = 0;
-         rn->special_type = 0;
-         rn->special_id = 0;
+   v3_copy( transform[3], rn->co );
+   v3_copy( transform[0], rn->right );
+   v3_copy( transform[1], rn->up );
+   v3_muls( transform[2], -1.0f, rn->h );
+   v3_normalize( rn->right );
+   v3_normalize( rn->up );
 
-         if( pnode->classtype == k_classtype_gate )
-         {
-            struct classtype_gate *inf = mdl_get_entdata( mdl, pnode );
+   rn->next[0] = 0xffffffff;
+   rn->next[1] = 0xffffffff;
 
-            /* H is later scaled based on link distance */
-            v3_normalize( rn->h );
-            rn->next[0] = inf->target;
-            rn->next[1] = 0;
+   rn->special_type = 0;
+   rn->special_id = 0;
+   rn->current_refs = 0;
+   rn->ref_count = 0;
 
-            /* TODO */
-            if( inf->target )
-            {
-               mdl_node *pother = mdl_node_from_id( mdl, inf->target );
-               
-               if( pother->classtype == k_classtype_gate )
-               {
-                  world_routes.gates = buffer_reserve( world_routes.gates, 
-                                                       world_routes.gate_count, 
-                                             &world_routes.gate_cap,
-                                             1, sizeof( struct route_gate ) );
-
-                  struct route_gate *rg = 
-                     &world_routes.gates[world_routes.gate_count];
-
-                  rg->node_id = world_routes.node_count;
-                  rg->timing.time = 0.0;
-                  rg->timing.version = 0;
-
-                  v3_copy( pnode->co,  rg->gate.co[0] );
-                  v3_copy( pother->co, rg->gate.co[1] );
-                  v4_copy( pnode->q,   rg->gate.q[0] );
-                  v4_copy( pother->q,  rg->gate.q[1] );
-                  v2_copy( inf->dims,  rg->gate.dims );
-
-                  gate_transform_update( &rg->gate );
-                  rn->special_type = k_route_special_type_gate;
-                  rn->special_id = world_routes.gate_count;
-
-                  world_routes.gate_count ++;
-               }
-            }
+   return rn;
+}
 
-            if( rn->special_type == 0 )
-            {
-               world_routes.collectors = buffer_reserve( 
-                     world_routes.collectors, 
-                     world_routes.collector_count, 
-                     &world_routes.collector_cap,
-                                          1, sizeof( struct route_collector ));
+/* retrieve the correct node id from mdl subuid */
+VG_STATIC u32 world_routes_get_subuid( u32 target )
+{
+   if( target == 0 )
+      return 0xffffffff;
+   else
+      return mdl_node_from_id( world.meta, target )->sub_uid;
+}
+
+#if 0
+VG_STATIC void world_id_fixup( u32 *uid, mdl_context *mdl )
+{
+   if( *uid )
+      *uid = mdl_node_from_id( mdl, *uid )->sub_uid;
+   else
+      *uid = 0xffffffff;
+}
+#endif
 
-               struct route_collector *rc = 
-                  &world_routes.collectors[world_routes.collector_count];
-               rc->timing.time = 0.0;
-               rc->timing.version = 0;
+/* process gate attachement onto node */
+VG_STATIC void world_routes_process_gate( struct route_node *rn, 
+                                          mdl_node *pnode )
+{
+   struct classtype_gate *inf = mdl_get_entdata( world.meta, pnode );
 
-               rn->special_type = k_route_special_type_collector;
-               rn->special_id = world_routes.collector_count;
+   /* H is later scaled based on link distance */
+   v3_normalize( rn->h );
 
-               world_routes.collector_count ++;
-            }
-         }
-         else
-         {
-            struct classtype_route_node *inf = mdl_get_entdata( mdl, pnode );
-            rn->next[0] = inf->target;
-            rn->next[1] = inf->target1;
-         }
+   rn->next[0] = world_routes_get_subuid( inf->target );
+   rn->next[1] = 0xffffffff;
+   rn->special_type = world_route_node_type( pnode );
 
-         world_routes.node_count ++;
-      }
-      else if( pnode->classtype == k_classtype_route )
-      {
-         struct classtype_route *inf = mdl_get_entdata( mdl, pnode );
-         world_routes.routes = buffer_reserve( world_routes.routes, 
-                                               world_routes.route_count, 
-                                               &world_routes.route_cap,
-                                     1, sizeof( struct route ) );
+   /* process gate type */
+   if( rn->special_type == k_route_special_type_gate )
+   {
+      mdl_node *pother = mdl_node_from_id( world.meta, inf->target );
+      
+      struct route_gate *rg = &world.gates[ world.gate_count ];
 
-         struct route *route = &world_routes.routes[world_routes.route_count];
-         memset( route, 0, sizeof(struct route) );
+      rg->node_id = world.node_count-1;
+      rg->timing.time = 0.0;
+      rg->timing.version = 0;
 
-         v3_copy( inf->colour, route->colour );
-         route->colour[3] = 1.0f;
+      v3_copy( pnode->co,  rg->gate.co[0] );
+      v3_copy( pother->co, rg->gate.co[1] );
+      v4_copy( pnode->q,   rg->gate.q[0] );
+      v4_copy( pother->q,  rg->gate.q[1] );
+      v2_copy( inf->dims,  rg->gate.dims );
 
+      gate_transform_update( &rg->gate );
+      rn->special_id = world.gate_count;
 
-         route->track_id = 0xffffffff;
-         for( u32 j=0; j<vg_list_size(track_infos); j++ )
-         {
-            if( !strcmp( mdl_pstr(mdl,pnode->pstr_name), track_infos[j].name ))
-            {
-               route->track_id = j;
-               break;
-            }
-         }
+      world.gate_count ++;
+   }
 
-         route->start = inf->id_start;
-         route->active = 0;
-         route->factive = 0.0f;
-         mdl_node_transform( pnode, route->scoreboard_transform );
-
-         route->ui.indices_head = k_route_ui_max_indices - 9;
-         route->ui.vertex_head = k_route_ui_max_verts - 200;
-         route->ui.segment_start = 0;
-         route->ui.segment_count = 0;
-         route->ui.last_notch = 0.0;
-         route->ui.fade_start = 0;
-         route->ui.fade_count = 0;
-         route->ui.fade_timer_start = 0.0;
-
-         world_routes.route_count ++;
-      }
+   /* process collector type */
+   else if( rn->special_type == k_route_special_type_collector )
+   {
+      struct route_collector *rc = 
+         &world.collectors[ world.collector_count ];
+
+      rc->timing.time = 0.0;
+      rc->timing.version = 0;
+
+      rn->special_id = world.collector_count;
+      world.collector_count ++;
    }
+   else
+      vg_fatal_exit_loop( "Invalid state" );
+}
 
-   /* 
-    * Apply correct system-local ids
-    */
-   for( int i=0; i<world_routes.node_count; i++ )
+/* create route from node description */
+VG_STATIC void world_routes_create_route( mdl_node *pnode )
+{
+   mdl_context *mdl = world.meta;
+
+   struct classtype_route *inf = mdl_get_entdata( mdl, pnode );
+   struct route *route = &world.routes[ world.route_count ];
+   memset( route, 0, sizeof(struct route) );
+
+   v3_copy( inf->colour, route->colour );
+   route->colour[3] = 1.0f;
+   route->track_id = 0xffffffff;
+
+   for( u32 j=0; j<vg_list_size(track_infos); j++ )
    {
-      struct route_node *rn = &world_routes.nodes[i];
-      
-      for( int j=0; j<2; j++ )
-         world_id_fixup( &rn->next[j], mdl );
+      if( !strcmp( mdl_pstr(mdl,pnode->pstr_name), track_infos[j].name ))
+      {
+         route->track_id = j;
+         break;
+      }
    }
 
-   for( int i=0; i<world_routes.route_count; i++ )
+   route->start = world_routes_get_subuid( inf->id_start );
+   route->active = 0;
+   route->factive = 0.0f;
+   mdl_node_transform( pnode, route->scoreboard_transform );
+
+   struct route_ui_bar *pui = &world.ui_bars[ world.route_count ];
+   pui->indices_head = k_route_ui_max_indices - 9;
+   pui->vertex_head = k_route_ui_max_verts - 200;
+   pui->segment_start = 0;
+   pui->segment_count = 0;
+   pui->last_notch = 0.0;
+   pui->fade_start = 0;
+   pui->fade_count = 0;
+   pui->fade_timer_start = 0.0;
+
+   world.route_count ++;
+}
+
+/* load all routes from model header */
+VG_STATIC void world_routes_process(void)
+{
+   vg_info( "Initializing routes\n" );
+   mdl_context *mdl = world.meta;
+
+   for( int i=0; i<mdl->info.node_count; i++ )
    {
-      struct route *route = &world_routes.routes[i];
-      world_id_fixup( &route->start, mdl );
+      mdl_node *pnode = mdl_node_from_id(mdl,i);
+
+      if( pnode->classtype == k_classtype_route_node ||
+          pnode->classtype == k_classtype_gate )
+      {
+         struct route_node *rn = world_routes_create_node( pnode );
+
+         if( pnode->classtype == k_classtype_gate )
+         {
+            world_routes_process_gate( rn, pnode );
+         }
+         else
+         {
+            struct classtype_route_node *inf = mdl_get_entdata( mdl, pnode );
+            rn->next[0] = world_routes_get_subuid( inf->target  );
+            rn->next[1] = world_routes_get_subuid( inf->target1 );
+         }
+      }
+      else if( pnode->classtype == k_classtype_route )
+      {
+         world_routes_create_route( pnode );
+      }
    }
 
    /*
     * Gather references
     */
-   for( int i=0; i<world_routes.route_count; i++ )
+   for( int i=0; i<world.route_count; i++ )
    {
-      struct route *route = &world_routes.routes[i];
+      struct route *route = &world.routes[i];
 
       u32 stack[64];
       u32 si = world_routes_get_path( route->start, stack );
 
       for( int sj=0; sj<si; sj++ )
       {
-         struct route_node *rn = &world_routes.nodes[ stack[sj] ];
+         struct route_node *rn = &world.nodes[ stack[sj] ];
          rn->route_ids[ rn->ref_count ++ ] = i;
 
          if( rn->ref_count > 4 )
             vg_warn( "Too many references on route node %i\n", i );
       }
    }
-
-   world_routes_create_all_meshes();
 }
 
 /* 
@@ -1117,42 +1063,67 @@ static void world_routes_loadfrom( mdl_header *mdl )
  * -----------------------------------------------------------------------------
  */
 
-static void world_routes_init(void)
+VG_STATIC void world_routes_init(void)
 {
-   world_routes.current_run_version = 2;
-   world_routes.time = RESET_MAX_TIME*2.0;
-   world_routes.last_use = 0.0;
+   world.current_run_version = 2;
+   world.time = RESET_MAX_TIME*2.0;
+   world.last_use = 0.0;
 
    shader_route_register();
    shader_routeui_register();
-}
 
-static void world_routes_free(void*_)
-{
-   vg_free( world_routes.nodes );
-   vg_free( world_routes.routes );
-   vg_free( world_routes.gates );
+   vg_acquire_thread_sync();
+   {
+      /* UI buffers */
+      for( int i=0; i<vg_list_size(world.ui_bars); i++ )
+      {
+         /* OpenGL strips */
+         struct route_ui_bar *pui = &world.ui_bars[i];
+
+         glGenVertexArrays( 1, &pui->vao );
+         glGenBuffers( 1, &pui->vbo );
+         glGenBuffers( 1, &pui->ebo );
+         glBindVertexArray( pui->vao );
+
+         size_t stride = sizeof(v2f);
+
+         glBindBuffer( GL_ARRAY_BUFFER, pui->vbo );
+         glBufferData( GL_ARRAY_BUFFER, k_route_ui_max_verts*stride, 
+                       NULL, GL_DYNAMIC_DRAW );
+
+         glBindVertexArray( pui->vao );
+         glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, pui->ebo );
+         glBufferData( GL_ELEMENT_ARRAY_BUFFER, 
+               k_route_ui_max_indices*sizeof(u16), NULL,
+               GL_DYNAMIC_DRAW );
+
+         glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, stride, (void *)0 );
+         glEnableVertexAttribArray( 0 );
+         VG_CHECK_GL_ERR();
+      }
+   }
+   vg_release_thread_sync();
 }
 
-static void world_routes_update(void)
+VG_STATIC void world_routes_update(void)
 {
-   world_routes.time += vg.time_delta;
+   world.time += vg.time_delta;
 
-   for( int i=0; i<world_routes.route_count; i++ )
+   for( int i=0; i<world.route_count; i++ )
    {
-      struct route *route = &world_routes.routes[i];
+      struct route *route = &world.routes[i];
       route->factive = vg_lerpf( route->factive, route->active, 
                                  0.6f*vg.time_delta );
 
       if( route->active )
       {
-         world_routes_ui_updatetime(i, world_routes.time - route->latest_pass );
+         world_routes_ui_updatetime(i, world.time - route->latest_pass );
       }
    }
 }
 
-static void bind_terrain_textures(void);
-static void render_world_routes( m4x4f projection, v3f camera )
+VG_STATIC void bind_terrain_textures(void);
+VG_STATIC void render_world_routes( m4x4f projection, v3f camera )
 {
    m4x3f identity_matrix;
    m4x3_identity( identity_matrix );
@@ -1166,11 +1137,11 @@ static void render_world_routes( m4x4f projection, v3f camera )
    shader_route_uMdl( identity_matrix );
    shader_route_uCamera( camera );
 
-   scene_bind( &world_routes.scene_lines );
+   mesh_bind( &world.mesh_route_lines );
 
-   for( int i=0; i<world_routes.route_count; i++ )
+   for( int i=0; i<world.route_count; i++ )
    {
-      struct route *route = &world_routes.routes[i];
+      struct route *route = &world.routes[i];
 
       v4f colour;
       v3_lerp( (v3f){0.7f,0.7f,0.7f}, route->colour, route->factive, colour );
@@ -1181,16 +1152,16 @@ static void render_world_routes( m4x4f projection, v3f camera )
    }
 }
 
-static void render_world_routes_ui(void)
+VG_STATIC void render_world_routes_ui(void)
 {
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glBlendEquation(GL_FUNC_ADD);
 
    float active_offset = 0.0f;
-   for( int i=0; i<world_routes.route_count; i++ )
+   for( int i=0; i<world.route_count; i++ )
    {
-      struct route *route = &world_routes.routes[i];
+      struct route *route = &world.routes[i];
       world_routes_ui_draw( i, route->colour, active_offset );
       active_offset += route->factive;
    }