semantics and world reloading
[carveJwlIkooP6JGAAIwe30JlM.git] / world_gen.h
index 2bada3aa5fcd79acb692054b0c9a239c38accddf..6cae853576ec97cee25c020bc35c29ef848bb3bc 100644 (file)
@@ -596,15 +596,15 @@ VG_STATIC void world_process_resources( world_instance *world )
    }
 }
 
-#if 0
 VG_STATIC void world_free( world_instance *world )
 {
-   vg_acquire_thread_sync();
+   vg_info( "Free world @%p\n", world );
 
    /* free meshes */
    mesh_free( &world->mesh_route_lines );
    mesh_free( &world->mesh_geo );
    mesh_free( &world->mesh_no_collide );
+   mesh_free( &world->mesh_water );
    
    /* glDeleteBuffers silently ignores 0's and names that do not correspond to 
     * existing buffer objects. 
@@ -616,11 +616,46 @@ VG_STATIC void world_free( world_instance *world )
    /* delete textures and meshes */
    glDeleteTextures( world->texture_count, world->textures );
 
-   vg_release_thread_sync();
+   u32 world_index = world - world_global.worlds;
+   if( world_index ){
+      vg_linear_del( world_global.worlds[world_index-1].heap, 
+                     vg_linear_header(world->heap) );
+   }
 
    world->status = k_world_status_unloaded;
 }
-#endif
+
+/* 
+ * checks:
+ *  1. to see if all audios owned by the world have been stopped
+ *  2. that this is the least significant world
+ */
+VG_STATIC int world_freeable( world_instance *world )
+{
+   if( world->status != k_world_status_unloading ) return 0;
+   u8 world_id = (world - world_global.worlds) + 1;
+
+   for( u32 i=world_id; i<vg_list_size(world_global.worlds); i++ ){
+      if( world_global.worlds[i].status != k_world_status_unloaded ){
+         return 0;
+      }
+   }
+
+   int freeable = 1;
+   audio_lock();
+   for( u32 i=0; i<AUDIO_CHANNELS; i++ ){
+      audio_channel *ch = &vg_audio.channels[i];
+      
+      if( ch->allocated && (ch->world_id == world_id)){
+         if( !audio_channel_finished( ch ) ){
+            freeable = 0;
+            break;
+         }
+      }
+   }
+   audio_unlock();
+   return freeable;
+}
 
 VG_STATIC void world_init_blank( world_instance *world )
 {
@@ -661,32 +696,29 @@ VG_STATIC void world_init_blank( world_instance *world )
    v3_copy( (v3f){1.10f, 0.89f, 0.35f}, state->g_sun_colour );
 }
 
-VG_STATIC void world_entities_init( u32 world_id )
+/* detatches any nonlocal gates */
+VG_STATIC void world_unlink_nonlocal( world_instance *world )
 {
-   world_instance *world = &world_global.worlds[world_id];
-
-   /* lights */
-   for( u32 j=0; j<mdl_arrcount(&world->ent_light); j ++ ){
-      ent_light *light = mdl_arritm( &world->ent_light, j );
-
-      m4x3f to_world;
-      q_m3x3( light->transform.q, to_world );
-      v3_copy( light->transform.co, to_world[3] );
-      m4x3_invert_affine( to_world, light->inverse_world );
+   for( u32 j=0; j<mdl_arrcount(&world->ent_gate); j ++ ){
+      ent_gate *gate = mdl_arritm( &world->ent_gate, j );
 
-      light->angle_sin_cos[0] = sinf( light->angle * 0.5f );
-      light->angle_sin_cos[1] = cosf( light->angle * 0.5f );
+      if( gate->type == k_gate_type_nonlocel ){
+         gate->type = k_gate_type_nonlocal_unlinked;
+      }
    }
+}
+
+/* attatches nonlocal gates, to be called from main thread ONLY! */
+VG_STATIC void world_link_nonlocal_async( void *payload, u32 size )
+{
+   world_instance *world = payload;
+   u32 world_id = world - world_global.worlds;
 
-   /* gates */
    for( u32 j=0; j<mdl_arrcount(&world->ent_gate); j ++ ){
       ent_gate *gate = mdl_arritm( &world->ent_gate, j );
 
-      if( gate->type == k_gate_type_teleport ){
-         gate_transform_update( gate );
-      }
-      else if( gate->type == k_gate_type_nonlocal_unlinked ){
-         const char *key = mdl_pstr( &world->meta, gate->target );
+      if( gate->type == k_gate_type_nonlocal_unlinked ){
+         const char *key = mdl_pstr( &world->meta, gate->key );
          vg_info( "key: %s\n", key );
 
          for( u32 i=0; i<vg_list_size(world_global.worlds); i++ ){
@@ -699,7 +731,7 @@ VG_STATIC void world_entities_init( u32 world_id )
                ent_gate *gate2 = mdl_arritm( &other->ent_gate, j );
                if( gate2->type != k_gate_type_nonlocal_unlinked ) continue;
 
-               const char *key2 = mdl_pstr( &other->meta, gate2->target );
+               const char *key2 = mdl_pstr( &other->meta, gate2->key );
                vg_info( " key2: %s\n", key2 );
 
                if( strcmp( key, key2 ) ) continue;
@@ -731,6 +763,34 @@ VG_STATIC void world_entities_init( u32 world_id )
 matched:;
       }
    }
+}
+
+VG_STATIC void world_entities_init( u32 world_id )
+{
+   world_instance *world = &world_global.worlds[world_id];
+
+   /* lights */
+   for( u32 j=0; j<mdl_arrcount(&world->ent_light); j ++ ){
+      ent_light *light = mdl_arritm( &world->ent_light, j );
+
+      m4x3f to_world;
+      q_m3x3( light->transform.q, to_world );
+      v3_copy( light->transform.co, to_world[3] );
+      m4x3_invert_affine( to_world, light->inverse_world );
+
+      light->angle_sin_cos[0] = sinf( light->angle * 0.5f );
+      light->angle_sin_cos[1] = cosf( light->angle * 0.5f );
+   }
+
+   /* gates */
+   for( u32 j=0; j<mdl_arrcount(&world->ent_gate); j ++ ){
+      ent_gate *gate = mdl_arritm( &world->ent_gate, j );
+
+      if( gate->type == k_gate_type_teleport ){
+         gate_transform_update( gate );
+      }
+   }
+   vg_async_call( world_link_nonlocal_async, world, 0 );
 
    /* water */
    for( u32 j=0; j<mdl_arrcount(&world->ent_water); j++ ){
@@ -811,8 +871,7 @@ VG_STATIC void world_load( u32 index, const char *path )
    }
 
    u32 size = heap_availible - min_overhead;
-   void *heap = vg_create_linear_allocator( allocator, size, 
-                                            VG_MEMORY_SYSTEM );
+   void *heap = vg_create_linear_allocator( allocator, size, VG_MEMORY_SYSTEM );
 
    world->heap = heap;
    mdl_context *meta = &world->meta;
@@ -872,7 +931,6 @@ VG_STATIC void world_load( u32 index, const char *path )
    world_post_process( world );
 
    mdl_close( meta );
-
    world->status = k_world_status_loaded;
 }